From 72fd008e7fa5a85dd1d3e69d7c194a6160ec3615 Mon Sep 17 00:00:00 2001 From: Daniel Kraft Date: Sun, 7 Feb 2016 14:06:07 +0100 Subject: [PATCH 0001/1802] Fix quoting of copyright holders in configure.ac. The old configure.ac did not work for a copyright holders string containing commas due to insufficient quoting. The new one allows this. While this is, of course, not of direct consequence to the current code (where the string is "Bitcoin Core"), it should still be fixed now that the string is actually factored out. --- configure.ac | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 939dfeaabfce9..bd30b6ab87362 100644 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ define(_CLIENT_VERSION_BUILD, 0) define(_CLIENT_VERSION_IS_RELEASE, false) define(_COPYRIGHT_YEAR, 2016) define(_COPYRIGHT_HOLDERS,[The %s developers]) -define(_COPYRIGHT_HOLDERS_SUBSTITUTION,[Bitcoin Core]) +define(_COPYRIGHT_HOLDERS_SUBSTITUTION,[[Bitcoin Core]]) AC_INIT([Bitcoin Core],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[https://github.com/bitcoin/bitcoin/issues],[bitcoin],[https://bitcoincore.org/]) AC_CONFIG_SRCDIR([src/main.cpp]) AC_CONFIG_HEADERS([src/config/bitcoin-config.h]) @@ -999,10 +999,10 @@ 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, [Version is release]) +AC_DEFINE(COPYRIGHT_YEAR, _COPYRIGHT_YEAR, [Copyright year]) AC_DEFINE(COPYRIGHT_HOLDERS, "_COPYRIGHT_HOLDERS", [Copyright holder(s) before %s replacement]) AC_DEFINE(COPYRIGHT_HOLDERS_SUBSTITUTION, "_COPYRIGHT_HOLDERS_SUBSTITUTION", [Replacement for %s in copyright holders string]) -define(_COPYRIGHT_HOLDERS_FINAL, patsubst(_COPYRIGHT_HOLDERS, [%s], [_COPYRIGHT_HOLDERS_SUBSTITUTION])) +define(_COPYRIGHT_HOLDERS_FINAL, [patsubst(_COPYRIGHT_HOLDERS, [%s], [_COPYRIGHT_HOLDERS_SUBSTITUTION])]) 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) From 7539f1aae3b41279dc5d49e09f448a78a071e114 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 9 Feb 2016 12:37:05 +0100 Subject: [PATCH 0002/1802] tests: Make proxy_test work on travis servers without IPv6 --- qa/rpc-tests/proxy_test.py | 74 +++++++++++++++----------- qa/rpc-tests/test_framework/netutil.py | 15 ++++++ 2 files changed, 58 insertions(+), 31 deletions(-) diff --git a/qa/rpc-tests/proxy_test.py b/qa/rpc-tests/proxy_test.py index 7f77e664d266c..b3c65573ea332 100755 --- a/qa/rpc-tests/proxy_test.py +++ b/qa/rpc-tests/proxy_test.py @@ -7,6 +7,7 @@ from test_framework.socks5 import Socks5Configuration, Socks5Command, Socks5Server, AddressType from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * +from test_framework.netutil import test_ipv6_local ''' Test plan: - Start bitcoind's with different proxy configurations @@ -34,6 +35,7 @@ class ProxyTest(BitcoinTestFramework): def __init__(self): + self.have_ipv6 = test_ipv6_local() # Create two proxies on different ports # ... one unauthenticated self.conf1 = Socks5Configuration() @@ -45,29 +47,36 @@ def __init__(self): self.conf2.addr = ('127.0.0.1', 14000 + (os.getpid() % 1000)) self.conf2.unauth = True self.conf2.auth = True - # ... one on IPv6 with similar configuration - self.conf3 = Socks5Configuration() - self.conf3.af = socket.AF_INET6 - self.conf3.addr = ('::1', 15000 + (os.getpid() % 1000)) - self.conf3.unauth = True - self.conf3.auth = True + if self.have_ipv6: + # ... one on IPv6 with similar configuration + self.conf3 = Socks5Configuration() + self.conf3.af = socket.AF_INET6 + self.conf3.addr = ('::1', 15000 + (os.getpid() % 1000)) + self.conf3.unauth = True + self.conf3.auth = True + else: + print "Warning: testing without local IPv6 support" self.serv1 = Socks5Server(self.conf1) self.serv1.start() self.serv2 = Socks5Server(self.conf2) self.serv2.start() - self.serv3 = Socks5Server(self.conf3) - self.serv3.start() + if self.have_ipv6: + self.serv3 = Socks5Server(self.conf3) + self.serv3.start() def setup_nodes(self): # Note: proxies are not used to connect to local nodes # this is because the proxy to use is based on CService.GetNetwork(), which return NET_UNROUTABLE for localhost - return start_nodes(4, self.options.tmpdir, extra_args=[ + args = [ ['-listen', '-debug=net', '-debug=proxy', '-proxy=%s:%i' % (self.conf1.addr),'-proxyrandomize=1'], ['-listen', '-debug=net', '-debug=proxy', '-proxy=%s:%i' % (self.conf1.addr),'-onion=%s:%i' % (self.conf2.addr),'-proxyrandomize=0'], ['-listen', '-debug=net', '-debug=proxy', '-proxy=%s:%i' % (self.conf2.addr),'-proxyrandomize=1'], - ['-listen', '-debug=net', '-debug=proxy', '-proxy=[%s]:%i' % (self.conf3.addr),'-proxyrandomize=0', '-noonion'] - ]) + [] + ] + if self.have_ipv6: + args[3] = ['-listen', '-debug=net', '-debug=proxy', '-proxy=[%s]:%i' % (self.conf3.addr),'-proxyrandomize=0', '-noonion'] + return start_nodes(4, self.options.tmpdir, extra_args=args) def node_test(self, node, proxies, auth, test_onion=True): rv = [] @@ -84,18 +93,19 @@ def node_test(self, node, proxies, auth, test_onion=True): assert_equal(cmd.password, None) rv.append(cmd) - # Test: outgoing IPv6 connection through node - node.addnode("[1233:3432:2434:2343:3234:2345:6546:4534]:5443", "onetry") - cmd = proxies[1].queue.get() - assert(isinstance(cmd, Socks5Command)) - # Note: bitcoind's SOCKS5 implementation only sends atyp DOMAINNAME, even if connecting directly to IPv4/IPv6 - assert_equal(cmd.atyp, AddressType.DOMAINNAME) - assert_equal(cmd.addr, "1233:3432:2434:2343:3234:2345:6546:4534") - assert_equal(cmd.port, 5443) - if not auth: - assert_equal(cmd.username, None) - assert_equal(cmd.password, None) - rv.append(cmd) + if self.have_ipv6: + # Test: outgoing IPv6 connection through node + node.addnode("[1233:3432:2434:2343:3234:2345:6546:4534]:5443", "onetry") + cmd = proxies[1].queue.get() + assert(isinstance(cmd, Socks5Command)) + # Note: bitcoind's SOCKS5 implementation only sends atyp DOMAINNAME, even if connecting directly to IPv4/IPv6 + assert_equal(cmd.atyp, AddressType.DOMAINNAME) + assert_equal(cmd.addr, "1233:3432:2434:2343:3234:2345:6546:4534") + assert_equal(cmd.port, 5443) + if not auth: + assert_equal(cmd.username, None) + assert_equal(cmd.password, None) + rv.append(cmd) if test_onion: # Test: outgoing onion connection through node @@ -135,10 +145,11 @@ def run_test(self): rv = self.node_test(self.nodes[2], [self.serv2, self.serv2, self.serv2, self.serv2], True) # Check that credentials as used for -proxyrandomize connections are unique credentials = set((x.username,x.password) for x in rv) - assert_equal(len(credentials), 4) + assert_equal(len(credentials), len(rv)) - # proxy on IPv6 localhost - self.node_test(self.nodes[3], [self.serv3, self.serv3, self.serv3, self.serv3], False, False) + if self.have_ipv6: + # proxy on IPv6 localhost + self.node_test(self.nodes[3], [self.serv3, self.serv3, self.serv3, self.serv3], False, False) def networks_dict(d): r = {} @@ -167,11 +178,12 @@ def networks_dict(d): assert_equal(n2[net]['proxy_randomize_credentials'], True) assert_equal(n2['onion']['reachable'], True) - n3 = networks_dict(self.nodes[3].getnetworkinfo()) - for net in ['ipv4','ipv6']: - assert_equal(n3[net]['proxy'], '[%s]:%i' % (self.conf3.addr)) - assert_equal(n3[net]['proxy_randomize_credentials'], False) - assert_equal(n3['onion']['reachable'], False) + if self.have_ipv6: + n3 = networks_dict(self.nodes[3].getnetworkinfo()) + for net in ['ipv4','ipv6']: + assert_equal(n3[net]['proxy'], '[%s]:%i' % (self.conf3.addr)) + assert_equal(n3[net]['proxy_randomize_credentials'], False) + assert_equal(n3['onion']['reachable'], False) if __name__ == '__main__': ProxyTest().main() diff --git a/qa/rpc-tests/test_framework/netutil.py b/qa/rpc-tests/test_framework/netutil.py index 50daa8793732a..bfdef76ad1caf 100644 --- a/qa/rpc-tests/test_framework/netutil.py +++ b/qa/rpc-tests/test_framework/netutil.py @@ -137,3 +137,18 @@ def addr_to_hex(addr): else: raise ValueError('Could not parse address %s' % addr) return binascii.hexlify(bytearray(addr)) + +def test_ipv6_local(): + ''' + Check for (local) IPv6 support. + ''' + import socket + # By using SOCK_DGRAM this will not actually make a connection, but it will + # fail if there is no route to IPv6 localhost. + have_ipv6 = True + try: + s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) + s.connect(('::1', 0)) + except socket.error: + have_ipv6 = False + return have_ipv6 From 8aa722609d7e736b3a3763e15b552795b94f0e9b Mon Sep 17 00:00:00 2001 From: jmacwhyte Date: Thu, 11 Feb 2016 18:02:46 -0800 Subject: [PATCH 0003/1802] Fix IsInitialBlockDownload to play nice with testnet --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 3ad2979b6b01c..9e478b6823685 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1384,7 +1384,7 @@ bool IsInitialBlockDownload() if (lockIBDState) return false; bool state = (chainActive.Height() < pindexBestHeader->nHeight - 24 * 6 || - pindexBestHeader->GetBlockTime() < GetTime() - nMaxTipAge); + std::max(chainActive.Tip()->GetBlockTime(), pindexBestHeader->GetBlockTime()) < GetTime() - nMaxTipAge); if (!state) lockIBDState = true; return state; From 146746bbafe5dfea7b2019231c2d37fe57a4c3bb Mon Sep 17 00:00:00 2001 From: Alice Wonder Date: Fri, 26 Feb 2016 09:30:11 -0800 Subject: [PATCH 0004/1802] All files related to my RPM spec file project in one commit --- contrib/rpm/README.md | 185 +++++++++ contrib/rpm/bitcoin-0.12.0-libressl.patch | 24 ++ contrib/rpm/bitcoin.fc | 8 + contrib/rpm/bitcoin.if | 157 ++++++++ contrib/rpm/bitcoin.spec | 444 ++++++++++++++++++++++ contrib/rpm/bitcoin.te | 81 ++++ 6 files changed, 899 insertions(+) create mode 100644 contrib/rpm/README.md create mode 100644 contrib/rpm/bitcoin-0.12.0-libressl.patch create mode 100644 contrib/rpm/bitcoin.fc create mode 100644 contrib/rpm/bitcoin.if create mode 100644 contrib/rpm/bitcoin.spec create mode 100644 contrib/rpm/bitcoin.te diff --git a/contrib/rpm/README.md b/contrib/rpm/README.md new file mode 100644 index 0000000000000..aecb3ba84f20d --- /dev/null +++ b/contrib/rpm/README.md @@ -0,0 +1,185 @@ +RPM Spec File Notes +------------------- + +The RPM spec file provided here is for Bitcoin-Core 0.12.0 and builds on CentOS +7 with either the CentOS provided OpenSSL library or with LibreSSL as packaged +at [LibreLAMP.com](https://librelamp.com/). It should hopefully not be too +difficult to port the RPM spec file to most RPM based Linux distributions. + +When porting the spec file to build for a particular distribution, there are +some important notes. + +## Sources + +It is considered good form for all sources to reference a URL where the source +can be downloaded. + +Sources 0-9 should be reserved for source code tarballs. `Source0` should +reference the release tarball available from https://bitcoin.org/bin/ and +`Source1` should reference the BerkeleyDB source. + +Sources 10-99 are for source files that are maintained in the +[Bitcoin git repository](https://github.com/bitcoin/bitcoin) but are not part of +the release tarball. Most of these will reside in the `contrib` sub-directory. + +Sources 10-19 should be reserved for miscellaneous configuration files. +Currently only `Source10` is used, for the example `bitcoin.conf` file. + +Sources 20-29 should be reserved for man pages. Currently only `Source20` +through `Source23` are used. + +Sources 30-39 should be reserved for SELinux related files. Currently only +`Source30` through `Source32` are used. Until those files are in a tagged +release, the full URL specified in the RPM spec file will not work. You can get +them from the git ropository where you retrieved this file. + +Sources 100+ are for files that are not source tarballs and are not maintained +in the bitcoin git repository. At present only an SVG version of the Bitcoin +icon is used. + +## Patches + +In general, patches should be avoided. When a packager feels a patch is +necessary, the packager should bring the problem to the attention of the bitcoin +developers so that an official fix to the issue can make it into the next +release. + +### Patch0 bitcoin-0.12.0-libressl.patch + +This patch is only needed if building against LibreSSL. LibreSSL is not the +standard TLS library on most Linux distributions. The patch will likely not be +needed when 0.12.1 is released, a proper fix is already in the Bitcoin git +master branch. + +## BuildRequires + +The packages specified in the `BuildRequires` are specified according to the +package naming convention currently used in CentOS 7 and EPEL for CentOS 7. You +may need to change some of the package names for other distributions. This is +most likely to be the case with the Qt packages. + +## BerkeleyDB + +The `build-unix.md` file recommends building against BerkeleyDB 4.8.30. Even if +that is the version your Linux distribution ships with, it probably is a good +idea to build Bitcoin Core against a static version of that library compiled +according to the instructions in the `build-unix.md` file so that any changes +the distribution may make in the future will not result in a problem for users. + +The problem that can exist, clients built against different versions of +BerkeleyDB may not be able read each other's `wallet.dat` file which can make it +difficult for a user to recover from backup in the event of a system failure. + +## Graphical User Interface and Qt Version + +The RPM spec file will by default build the GUI client linked against the Qt5 +libraries. If you wish instead to link against the Qt4 libraries you need to +pass the switch `-D '_use_qt4 1'` at build time to the `rpmbuild` or `mock` +command used to build the packages. + +If you would prefer not to build the GUI at all, you can pass the switch +`-D '_no_gui 1'` to the `rpmbuild` or `mock` build command. + +## Desktop and KDE Files + +The desktop and KDE meta files are created in the spec file itself with the +`cat` command. This is done to allow easy distribution specific changes without +needing to use any patches. A specific time stamp is given to the files so that +it does not they do not appear to have been updated every time the package is +built. If you do make changes to them, you probably should update time stamp +assigned to them in the `touch` command that specifies the time stamp. + +## SVG, PNG, and XPM Icons + +The `bitcoin.svg` file is from the source listed as `Source100`. It is used as +the source for the PNG and XPM files. The generated PNG and XPM files are given +the same time stamp as the source SVG file as a means of indicating they are +derived from it. + +## Systemd + +This spec file assumes the target distribution uses systemd. That really only +matters for the `bitcoin-server` package. At this point, most RPM based +distributions that still receive vendor updates do in fact use systemd. + +The files to control the service are created in the RPM spec file itself using +the `cat` command. This is done to make it easy to modify for other +distributions that may implement things differently without needing to patch +source. A specific time stamp is given to the files so that they do not appear +to have been updated every time the package is built. If you do make changes to +them, you probably should update the time stamp assigned to them in the `touch` +command that specifies the time stamp. + +## SELinux + +The `bitcoin-server` package should have SELinux support. How to properly do +that *may* vary by distribution and version of distribution. + +The SELinux stuff in this RPM spec file *should* be correct for CentOS, RHEL, +and Fedora but it would be a good idea to review it before building the package +on other distributions. + +## Tests + +The `%check` section takes a very long time to run. If your build system has a +time limit for package build, you may need to make an exception for this +package. On CentOS 7 the `%check` section completes successfully with both +OpenSSL and LibreSSL, a failure really does mean something is wrong. + +## LibreSSL Build Notes + +To build against LibreSSL you will need to pass the switch +`-D '_use_libressl 1'` to the `rpmbuild` or `mock` command or the spec file will +want the OpenSSL development files. + +### LibreSSL and Boost + +LibreSSL (and some newer builds of OpenSSL) do not have support for SSLv3. This +can cause issues with the Boost package if the Boost package has not been +patched accordingly. On those distributions, you will either need to build +Bitcoin-Core against OpenSSL or use a patched version of Boost in the build +system. + +As SSLv3 is no longer safe, distributions that have not patched Boost to work +with TLS libraries that do not support SSLv3 should have bug reports filed +against the Boost package. This bug report has already been filed for RHEL 7 but +it may need to be filed for other distributions. + +A patch for Boost: https://github.com/boostorg/asio/pull/23/files + +## ZeroMQ + +At this time, this RPM spec file does not support the ZeroMQ build options. A +suitable version of ZeroMQ is not available for the platform this spec file was +developed on (CentOS 7). + +## Legacy Credit + +This RPM spec file is largely based upon the work of Michael Hampton at +[Ringing Liberty](https://www.ringingliberty.com/bitcoin/). He has been +packaging Bitcoin for Fedora at least since 2012. + +Most of the differences between his packaging and this package are stylistic in +nature. The major differences: + +1. He builds from a github tagged release rather than a release tarball. This +should not result in different source code. + +2. He does not build BerkeleyDB but instead uses the BerkeleyDB provided by the +Linux distribution. For the distributions he packages for, they currently all +use the same version of BerkeleyDB so that difference is *probably* just +academic. + +3. As of his 10.11.2 package he did not allow for building against LibreSSL, +specifying a build without the Qt GUI, or specifying which version of the Qt +libraries to use. + +4. I renamed the `bitcoin` package that contains the Qt GUI to `bitcoin-core` as +that appears to be how the general population refers to it, in contrast to +`bitcoin-xt` or `bitcoin-classic`. I wanted to make sure the general population +knows what they are getting when installing the GUI package. + +As far as minor differences, I generally prefer to assign the file permissions +in the `%files` portion of an RPM spec file rather than specifying the +permissions of a file during `%install` and other minor things like that that +are largely just cosmetic. diff --git a/contrib/rpm/bitcoin-0.12.0-libressl.patch b/contrib/rpm/bitcoin-0.12.0-libressl.patch new file mode 100644 index 0000000000000..555614a06d49a --- /dev/null +++ b/contrib/rpm/bitcoin-0.12.0-libressl.patch @@ -0,0 +1,24 @@ +diff -ur bitcoin-0.12.0.orig/src/init.cpp bitcoin-0.12.0/src/init.cpp +--- bitcoin-0.12.0.orig/src/init.cpp 2015-12-31 16:00:00.000000000 -0800 ++++ bitcoin-0.12.0/src/init.cpp 2016-02-23 06:03:47.133227757 -0800 +@@ -1075,7 +1075,7 @@ + if (fPrintToDebugLog) + OpenDebugLog(); + +-#if (OPENSSL_VERSION_NUMBER < 0x10100000L) ++#if defined(LIBRESSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x10100000L) + LogPrintf("Using OpenSSL version %s\n", SSLeay_version(SSLEAY_VERSION)); + #else + LogPrintf("Using OpenSSL version %s\n", OpenSSL_version(OPENSSL_VERSION)); +diff -ur bitcoin-0.12.0.orig/src/qt/rpcconsole.cpp bitcoin-0.12.0/src/qt/rpcconsole.cpp +--- bitcoin-0.12.0.orig/src/qt/rpcconsole.cpp 2015-12-31 16:00:00.000000000 -0800 ++++ bitcoin-0.12.0/src/qt/rpcconsole.cpp 2016-02-23 15:09:42.881126841 -0800 +@@ -264,7 +264,7 @@ + + // set library version labels + +-#if (OPENSSL_VERSION_NUMBER < 0x10100000L) ++#if defined(LIBRESSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x10100000L) + ui->openSSLVersion->setText(SSLeay_version(SSLEAY_VERSION)); + #else + ui->openSSLVersion->setText(OpenSSL_version(OPENSSL_VERSION)); diff --git a/contrib/rpm/bitcoin.fc b/contrib/rpm/bitcoin.fc new file mode 100644 index 0000000000000..6f5eef6375255 --- /dev/null +++ b/contrib/rpm/bitcoin.fc @@ -0,0 +1,8 @@ +/usr/bin/bitcoin-cli -- gen_context(system_u:object_r:bitcoin_exec_t,s0) +/usr/sbin/bitcoind -- gen_context(system_u:object_r:bitcoin_exec_t,s0) +/usr/lib(64)?/bitcoin/bitcoind -- gen_context(system_u:object_r:bitcoin_exec_t,s0) + +/etc/bitcoin(/.*)? gen_context(system_u:object_r:bitcoin_conf_t,s0) +/var/lib/bitcoin(/.*)? gen_context(system_u:object_r:bitcoin_var_lib_t,s0) + +(/var)?/run/bitcoind(/.*)? gen_context(system_u:object_r:bitcoin_var_run_t,s0) diff --git a/contrib/rpm/bitcoin.if b/contrib/rpm/bitcoin.if new file mode 100644 index 0000000000000..2b096c24dc323 --- /dev/null +++ b/contrib/rpm/bitcoin.if @@ -0,0 +1,157 @@ + +## policy for bitcoin + + +######################################## +## +## Transition to bitcoin. +## +## +## +## Domain allowed to transition. +## +## +# +interface(`bitcoin_domtrans',` + gen_require(` + type bitcoin_t, bitcoin_exec_t; + ') + + corecmd_search_bin($1) + domtrans_pattern($1, bitcoin_exec_t, bitcoin_t) +') + + +######################################## +## +## Execute bitcoin server in the bitcoin domain. +## +## +## +## Domain allowed access. +## +## +# +interface(`bitcoin_initrc_domtrans',` + gen_require(` + type bitcoin_initrc_exec_t; + ') + + init_labeled_script_domtrans($1, bitcoin_initrc_exec_t) +') + + +######################################## +## +## Search bitcoin lib directories. +## +## +## +## Domain allowed access. +## +## +# +interface(`bitcoin_search_lib',` + gen_require(` + type bitcoin_var_lib_t; + ') + + allow $1 bitcoin_var_lib_t:dir search_dir_perms; + files_search_var_lib($1) +') + +######################################## +## +## Read bitcoin lib files. +## +## +## +## Domain allowed access. +## +## +# +interface(`bitcoin_read_lib_files',` + gen_require(` + type bitcoin_var_lib_t; + ') + + files_search_var_lib($1) + read_files_pattern($1, bitcoin_var_lib_t, bitcoin_var_lib_t) +') + +######################################## +## +## Manage bitcoin lib files. +## +## +## +## Domain allowed access. +## +## +# +interface(`bitcoin_manage_lib_files',` + gen_require(` + type bitcoin_var_lib_t; + ') + + files_search_var_lib($1) + manage_files_pattern($1, bitcoin_var_lib_t, bitcoin_var_lib_t) +') + +######################################## +## +## Manage bitcoin lib directories. +## +## +## +## Domain allowed access. +## +## +# +interface(`bitcoin_manage_lib_dirs',` + gen_require(` + type bitcoin_var_lib_t; + ') + + files_search_var_lib($1) + manage_dirs_pattern($1, bitcoin_var_lib_t, bitcoin_var_lib_t) +') + + +######################################## +## +## All of the rules required to administrate +## an bitcoin environment +## +## +## +## Domain allowed access. +## +## +## +## +## Role allowed access. +## +## +## +# +interface(`bitcoin_admin',` + gen_require(` + type bitcoin_t; + type bitcoin_initrc_exec_t; + type bitcoin_var_lib_t; + ') + + allow $1 bitcoin_t:process { ptrace signal_perms }; + ps_process_pattern($1, bitcoin_t) + + bitcoin_initrc_domtrans($1) + domain_system_change_exemption($1) + role_transition $2 bitcoin_initrc_exec_t system_r; + allow $2 system_r; + + files_search_var_lib($1) + admin_pattern($1, bitcoin_var_lib_t) + +') + diff --git a/contrib/rpm/bitcoin.spec b/contrib/rpm/bitcoin.spec new file mode 100644 index 0000000000000..38ae038180766 --- /dev/null +++ b/contrib/rpm/bitcoin.spec @@ -0,0 +1,444 @@ +%define bdbv 4.8.30 +%global selinux_variants mls strict targeted + +%if 0%{?_no_gui:1} +%define _buildqt 0 +%define buildargs --with-gui=no +%else +%define _buildqt 1 +%if 0%{?_use_qt4} +%define buildargs --with-qrencode --with-gui=qt4 +%else +%define buildargs --with-qrencode --with-gui=qt5 +%endif +%endif + +Name: bitcoin +Version: 0.12.0 +Release: 2%{?dist} +Summary: Peer to Peer Cryptographic Currency + +Group: Applications/System +License: MIT +URL: https://bitcoin.org/ +Source0: https://bitcoin.org/bin/bitcoin-core-%{version}/bitcoin-%{version}.tar.gz +Source1: http://download.oracle.com/berkeley-db/db-%{bdbv}.NC.tar.gz + +Source10: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/debian/examples/bitcoin.conf + +#man pages +Source20: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/debian/manpages/bitcoind.1 +Source21: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/debian/manpages/bitcoin-cli.1 +Source22: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/debian/manpages/bitcoin-qt.1 +Source23: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/debian/manpages/bitcoin.conf.5 + +#selinux +Source30: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/rpm/bitcoin.te +# Source31 - what about bitcoin-tx and bench_bitcoin ??? +Source31: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/rpm/bitcoin.fc +Source32: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/rpm/bitcoin.if + +Source100: https://upload.wikimedia.org/wikipedia/commons/4/46/Bitcoin.svg + +%if 0%{?_use_libressl:1} +BuildRequires: libressl-devel +%else +BuildRequires: openssl-devel +%endif +BuildRequires: boost-devel +BuildRequires: miniupnpc-devel +BuildRequires: autoconf automake libtool +BuildRequires: libevent-devel + + +Patch0: bitcoin-0.12.0-libressl.patch + + +%description +Bitcoin is a digital cryptographic currency that uses peer-to-peer technology to +operate with no central authority or banks; managing transactions and the +issuing of bitcoins is carried out collectively by the network. + +%if %{_buildqt} +%package core +Summary: Peer to Peer Cryptographic Currency +Group: Applications/System +Obsoletes: %{name} < %{version}-%{release} +Provides: %{name} = %{version}-%{release} +%if 0%{?_use_qt4} +BuildRequires: qt-devel +%else +BuildRequires: qt5-qtbase-devel +# for /usr/bin/lrelease-qt5 +BuildRequires: qt5-linguist +%endif +BuildRequires: protobuf-devel +BuildRequires: qrencode-devel +BuildRequires: %{_bindir}/desktop-file-validate +# for icon generation from SVG +BuildRequires: %{_bindir}/inkscape +BuildRequires: %{_bindir}/convert + +%description core +Bitcoin is a digital cryptographic currency that uses peer-to-peer technology to +operate with no central authority or banks; managing transactions and the +issuing of bitcoins is carried out collectively by the network. + +This package contains the Qt based graphical client and node. If you are looking +to run a Bitcoin wallet, this is probably the package you want. +%endif + + +%package libs +Summary: Bitcoin shared libraries +Group: System Environment/Libraries + +%description libs +This package provides the bitcoinconsensus shared libraries. These libraries +may be used by third party software to provide consensus verification +functionality. + +Unless you know need this package, you probably do not. + +%package devel +Summary: Development files for bitcoin +Group: Development/Libraries +Requires: %{name}-libs = %{version}-%{release} + +%description devel +This package contains the header files and static library for the +bitcoinconsensus shared library. If you are developing or compiling software +that wants to link against that library, then you need this package installed. + +Most people do not need this package installed. + +%package server +Summary: The bitcoin daemon +Group: System Environment/Daemons +Requires: bitcoin-utils = %{version}-%{release} +Requires: selinux-policy policycoreutils-python +Requires(pre): shadow-utils +Requires(post): %{_sbindir}/semodule %{_sbindir}/restorecon %{_sbindir}/fixfiles %{_sbindir}/sestatus +Requires(postun): %{_sbindir}/semodule %{_sbindir}/restorecon %{_sbindir}/fixfiles %{_sbindir}/sestatus +BuildRequires: systemd +BuildRequires: checkpolicy +BuildRequires: %{_datadir}/selinux/devel/Makefile + +%description server +This package provides a stand-alone bitcoin-core daemon. For most users, this +package is only needed if they need a full-node without the graphical client. + +Some third party wallet software will want this package to provide the actual +bitcoin-core node they use to connect to the network. + +If you use the graphical bitcoin-core client then you almost certainly do not +need this package. + +%package utils +Summary: Bitcoin utilities +Group: Applications/System + +%description utils +This package provides several command line utilities for interacting with a +bitcoin-core daemon. + +The bitcoin-cli utility allows you to communicate and control a bitcoin daemon +over RPC, the bitcoin-tx utility allows you to create a custom transaction, and +the bench_bitcoin utility can be used to perform some benchmarks. + +This package contains utilities needed by the bitcoin-server package. + + +%prep +%setup -q +%patch0 -p1 -b .libressl +cp -p %{SOURCE10} ./bitcoin.conf.example +tar -zxf %{SOURCE1} +cp -p db-%{bdbv}.NC/LICENSE ./db-%{bdbv}.NC-LICENSE +mkdir db4 SELinux +cp -p %{SOURCE30} %{SOURCE31} %{SOURCE32} SELinux/ + + +%build +CWD=`pwd` +cd db-%{bdbv}.NC/build_unix/ +../dist/configure --enable-cxx --disable-shared --with-pic --prefix=${CWD}/db4 +make install +cd ../.. + +./autogen.sh +%configure LDFLAGS="-L${CWD}/db4/lib/" CPPFLAGS="-I${CWD}/db4/include/" --with-miniupnpc --enable-glibc-back-compat %{buildargs} +make %{?_smp_mflags} + +pushd SELinux +for selinuxvariant in %{selinux_variants}; do + make NAME=${selinuxvariant} -f %{_datadir}/selinux/devel/Makefile + mv bitcoin.pp bitcoin.pp.${selinuxvariant} + make NAME=${selinuxvariant} -f %{_datadir}/selinux/devel/Makefile clean +done +popd + + +%install +make install DESTDIR=%{buildroot} + +mkdir -p -m755 %{buildroot}%{_sbindir} +mv %{buildroot}%{_bindir}/bitcoind %{buildroot}%{_sbindir}/bitcoind + +# systemd stuff +mkdir -p %{buildroot}%{_tmpfilesdir} +cat < %{buildroot}%{_tmpfilesdir}/bitcoin.conf +d /run/bitcoind 0750 bitcoin bitcoin - +EOF +touch -a -m -t 201504280000 %{buildroot}%{_tmpfilesdir}/bitcoin.conf + +mkdir -p %{buildroot}%{_sysconfdir}/sysconfig +cat < %{buildroot}%{_sysconfdir}/sysconfig/bitcoin +# Provide options to the bitcoin daemon here, for example +# OPTIONS="-testnet -disable-wallet" + +OPTIONS="" + +# System service defaults. +# Don't change these unless you know what you're doing. +CONFIG_FILE="%{_sysconfdir}/bitcoin/bitcoin.conf" +DATA_DIR="%{_localstatedir}/lib/bitcoin" +PID_FILE="/run/bitcoind/bitcoind.pid" +EOF +touch -a -m -t 201504280000 %{buildroot}%{_sysconfdir}/sysconfig/bitcoin + +mkdir -p %{buildroot}%{_unitdir} +cat < %{buildroot}%{_unitdir}/bitcoin.service +[Unit] +Description=Bitcoin daemon +After=syslog.target network.target + +[Service] +Type=forking +ExecStart=%{_sbindir}/bitcoind -daemon -conf=\${CONFIG_FILE} -datadir=\${DATA_DIR} -pid=\${PID_FILE} \$OPTIONS +EnvironmentFile=%{_sysconfdir}/sysconfig/bitcoin +User=bitcoin +Group=bitcoin + +Restart=on-failure +PrivateTmp=true +TimeoutStopSec=120 +TimeoutStartSec=60 +StartLimitInterval=240 +StartLimitBurst=5 + +[Install] +WantedBy=multi-user.target +EOF +touch -a -m -t 201504280000 %{buildroot}%{_unitdir}/bitcoin.service +#end systemd stuff + +mkdir %{buildroot}%{_sysconfdir}/bitcoin +mkdir -p %{buildroot}%{_localstatedir}/lib/bitcoin + +#SELinux +for selinuxvariant in %{selinux_variants}; do + install -d %{buildroot}%{_datadir}/selinux/${selinuxvariant} + install -p -m 644 SELinux/bitcoin.pp.${selinuxvariant} %{buildroot}%{_datadir}/selinux/${selinuxvariant}/bitcoin.pp +done + +%if %{_buildqt} +# qt icons +install -D -p share/pixmaps/bitcoin.ico %{buildroot}%{_datadir}/pixmaps/bitcoin.ico +install -p share/pixmaps/nsis-header.bmp %{buildroot}%{_datadir}/pixmaps/ +install -p share/pixmaps/nsis-wizard.bmp %{buildroot}%{_datadir}/pixmaps/ +install -p %{SOURCE100} %{buildroot}%{_datadir}/pixmaps/bitcoin.svg +%{_bindir}/inkscape %{SOURCE100} --export-png=%{buildroot}%{_datadir}/pixmaps/bitcoin16.png -w16 -h16 +%{_bindir}/inkscape %{SOURCE100} --export-png=%{buildroot}%{_datadir}/pixmaps/bitcoin32.png -w32 -h32 +%{_bindir}/inkscape %{SOURCE100} --export-png=%{buildroot}%{_datadir}/pixmaps/bitcoin64.png -w64 -h64 +%{_bindir}/inkscape %{SOURCE100} --export-png=%{buildroot}%{_datadir}/pixmaps/bitcoin128.png -w128 -h128 +%{_bindir}/inkscape %{SOURCE100} --export-png=%{buildroot}%{_datadir}/pixmaps/bitcoin256.png -w256 -h256 +%{_bindir}/convert -resize 16x16 %{buildroot}%{_datadir}/pixmaps/bitcoin256.png %{buildroot}%{_datadir}/pixmaps/bitcoin16.xpm +%{_bindir}/convert -resize 32x32 %{buildroot}%{_datadir}/pixmaps/bitcoin256.png %{buildroot}%{_datadir}/pixmaps/bitcoin32.xpm +%{_bindir}/convert -resize 64x64 %{buildroot}%{_datadir}/pixmaps/bitcoin256.png %{buildroot}%{_datadir}/pixmaps/bitcoin64.xpm +%{_bindir}/convert -resize 128x128 %{buildroot}%{_datadir}/pixmaps/bitcoin256.png %{buildroot}%{_datadir}/pixmaps/bitcoin128.xpm +%{_bindir}/convert %{buildroot}%{_datadir}/pixmaps/bitcoin256.png %{buildroot}%{_datadir}/pixmaps/bitcoin256.xpm +touch %{buildroot}%{_datadir}/pixmaps/*.png -r %{SOURCE100} +touch %{buildroot}%{_datadir}/pixmaps/*.xpm -r %{SOURCE100} + +# Desktop File - change the touch timestamp if modifying +mkdir -p %{buildroot}%{_datadir}/applications +cat < %{buildroot}%{_datadir}/applications/bitcoin-core.desktop +[Desktop Entry] +Encoding=UTF-8 +Name=Bitcoin +Comment=Bitcoin P2P Cryptocurrency +Comment[fr]=Bitcoin, monnaie virtuelle cryptographique pair à pair +Comment[tr]=Bitcoin, eşten eşe kriptografik sanal para birimi +Exec=bitcoin-qt %u +Terminal=false +Type=Application +Icon=bitcoin128 +MimeType=x-scheme-handler/bitcoin; +Categories=Office;Finance; +EOF +# change touch date when modifying desktop +touch -a -m -t 201511100546 %{buildroot}%{_datadir}/applications/bitcoin-core.desktop +%{_bindir}/desktop-file-validate %{buildroot}%{_datadir}/applications/bitcoin-core.desktop + +# KDE protocol - change the touch timestamp if modifying +mkdir -p %{buildroot}%{_datadir}/kde4/services +cat < %{buildroot}%{_datadir}/kde4/services/bitcoin-core.protocol +[Protocol] +exec=bitcoin-qt '%u' +protocol=bitcoin +input=none +output=none +helper=true +listing= +reading=false +writing=false +makedir=false +deleting=false +EOF +# change touch date when modifying protocol +touch -a -m -t 201511100546 %{buildroot}%{_datadir}/kde4/services/bitcoin-core.protocol +%endif + +# man pages +install -D -p %{SOURCE20} %{buildroot}%{_mandir}/man1/bitcoind.1 +install -p %{SOURCE21} %{buildroot}%{_mandir}/man1/bitcoin-cli.1 +%if %{_buildqt} +install -p %{SOURCE22} %{buildroot}%{_mandir}/man1/bitcoin-qt.1 +%endif +install -D -p %{SOURCE23} %{buildroot}%{_mandir}/man5/bitcoin.conf.5 + +# nuke these, we do extensive testing of binaries in %%check before packaging +rm -f %{buildroot}%{_bindir}/test_* + +%check +make check +pushd src +srcdir=. test/bitcoin-util-test.py +popd +qa/pull-tester/rpc-tests.py -extended + +%post libs -p /sbin/ldconfig + +%postun libs -p /sbin/ldconfig + +%pre server +getent group bitcoin >/dev/null || groupadd -r bitcoin +getent passwd bitcoin >/dev/null || + useradd -r -g bitcoin -d /var/lib/bitcoin -s /sbin/nologin \ + -c "Bitcoin wallet server" bitcoin +exit 0 + +%post server +%systemd_post bitcoin.service +# SELinux +if [ `%{_sbindir}/sestatus |grep -c "disabled"` -eq 0 ]; then +for selinuxvariant in %{selinux_variants}; do + %{_sbindir}/semodule -s ${selinuxvariant} -i %{_datadir}/selinux/${selinuxvariant}/bitcoin.pp &> /dev/null || : +done +%{_sbindir}/semanage port -a -t bitcoin_port_t -p tcp 8332 +%{_sbindir}/semanage port -a -t bitcoin_port_t -p tcp 8333 +%{_sbindir}/semanage port -a -t bitcoin_port_t -p tcp 18332 +%{_sbindir}/semanage port -a -t bitcoin_port_t -p tcp 18333 +%{_sbindir}/fixfiles -R bitcoin-server restore &> /dev/null || : +%{_sbindir}/restorecon -R %{_localstatedir}/lib/bitcoin || : +fi + +%posttrans server +%{_bindir}/systemd-tmpfiles --create + +%preun server +%systemd_preun bitcoin.service + +%postun server +%systemd_postun bitcoin.service +# SELinux +if [ $1 -eq 0 ]; then + if [ `%{_sbindir}/sestatus |grep -c "disabled"` -eq 0 ]; then + %{_sbindir}/semanage port -d -p tcp 8332 + %{_sbindir}/semanage port -d -p tcp 8333 + %{_sbindir}/semanage port -d -p tcp 18332 + %{_sbindir}/semanage port -d -p tcp 18333 + for selinuxvariant in %{selinux_variants}; do + %{_sbindir}/semodule -s ${selinuxvariant} -r bitcoin &> /dev/null || : + done + %{_sbindir}/fixfiles -R bitcoin-server restore &> /dev/null || : + [ -d %{_localstatedir}/lib/bitcoin ] && \ + %{_sbindir}/restorecon -R %{_localstatedir}/lib/bitcoin &> /dev/null || : + fi +fi + +%clean +rm -rf %{buildroot} + +%if %{_buildqt} +%files core +%defattr(-,root,root,-) +%license COPYING db-%{bdbv}.NC-LICENSE +%doc COPYING bitcoin.conf.example doc/README.md doc/bips.md doc/files.md doc/multiwallet-qt.md doc/reduce-traffic.md doc/release-notes.md doc/tor.md +%attr(0755,root,root) %{_bindir}/bitcoin-qt +%attr(0644,root,root) %{_datadir}/applications/bitcoin-core.desktop +%attr(0644,root,root) %{_datadir}/kde4/services/bitcoin-core.protocol +%attr(0644,root,root) %{_datadir}/pixmaps/*.ico +%attr(0644,root,root) %{_datadir}/pixmaps/*.bmp +%attr(0644,root,root) %{_datadir}/pixmaps/*.svg +%attr(0644,root,root) %{_datadir}/pixmaps/*.png +%attr(0644,root,root) %{_datadir}/pixmaps/*.xpm +%attr(0644,root,root) %{_mandir}/man1/bitcoin-qt.1* +%endif + +%files libs +%defattr(-,root,root,-) +%license COPYING +%doc COPYING doc/README.md doc/shared-libraries.md +%{_libdir}/lib*.so.* + +%files devel +%defattr(-,root,root,-) +%license COPYING +%doc COPYING doc/README.md doc/developer-notes.md doc/shared-libraries.md +%attr(0644,root,root) %{_includedir}/*.h +%{_libdir}/*.so +%{_libdir}/*.a +%{_libdir}/*.la +%attr(0644,root,root) %{_libdir}/pkgconfig/*.pc + +%files server +%defattr(-,root,root,-) +%license COPYING db-%{bdbv}.NC-LICENSE +%doc COPYING bitcoin.conf.example doc/README.md doc/REST-interface.md doc/bips.md doc/dnsseed-policy.md doc/files.md doc/reduce-traffic.md doc/release-notes.md doc/tor.md +%attr(0755,root,root) %{_sbindir}/bitcoind +%attr(0644,root,root) %{_tmpfilesdir}/bitcoin.conf +%attr(0644,root,root) %{_unitdir}/bitcoin.service +%dir %attr(0750,bitcoin,bitcoin) %{_sysconfdir}/bitcoin +%dir %attr(0750,bitcoin,bitcoin) %{_localstatedir}/lib/bitcoin +%config(noreplace) %attr(0600,root,root) %{_sysconfdir}/sysconfig/bitcoin +%attr(0644,root,root) %{_datadir}/selinux/*/*.pp +%attr(0644,root,root) %{_mandir}/man1/bitcoind.1* +%attr(0644,root,root) %{_mandir}/man5/bitcoin.conf.5* + +%files utils +%defattr(-,root,root,-) +%license COPYING +%doc COPYING bitcoin.conf.example doc/README.md +%attr(0755,root,root) %{_bindir}/bitcoin-cli +%attr(0755,root,root) %{_bindir}/bitcoin-tx +%attr(0755,root,root) %{_bindir}/bench_bitcoin +%attr(0644,root,root) %{_mandir}/man1/bitcoin-cli.1* +%attr(0644,root,root) %{_mandir}/man5/bitcoin.conf.5* + + + +%changelog +* Fri Feb 26 2016 Alice Wonder - 0.12.0-2 +- Rename Qt package from bitcoin to bitcoin-core +- Make building of the Qt package optional +- When building the Qt package, default to Qt5 but allow building +- against Qt4 +- Only run SELinux stuff in post scripts if it is not set to disabled + +* Wed Feb 24 2016 Alice Wonder - 0.12.0-1 +- Initial spec file for 0.12.0 release + +# This spec file is written from scratch but a lot of the packaging decisions are directly +# based upon the 0.11.2 package spec file from https://www.ringingliberty.com/bitcoin/ diff --git a/contrib/rpm/bitcoin.te b/contrib/rpm/bitcoin.te new file mode 100644 index 0000000000000..d6231c591a243 --- /dev/null +++ b/contrib/rpm/bitcoin.te @@ -0,0 +1,81 @@ +policy_module(bitcoin, 1.100.1) + +######################################## +# +# Declarations +# + +type bitcoin_t; +type bitcoin_exec_t; +init_daemon_domain(bitcoin_t, bitcoin_exec_t) + +permissive bitcoin_t; + +type bitcoin_initrc_exec_t; +init_script_file(bitcoin_initrc_exec_t) + +type bitcoin_conf_t; +files_type(bitcoin_conf_t) + +type bitcoin_var_lib_t; +files_type(bitcoin_var_lib_t) + +type bitcoin_var_run_t; +files_type(bitcoin_var_run_t) + +type bitcoin_port_t; +corenet_port(bitcoin_port_t) + +######################################## +# +# bitcoin local policy +# +allow bitcoin_t self:process { fork }; + +allow bitcoin_t self:fifo_file rw_fifo_file_perms; +allow bitcoin_t self:unix_stream_socket create_stream_socket_perms; + +manage_dirs_pattern(bitcoin_t, bitcoin_conf_t, bitcoin_conf_t) +manage_files_pattern(bitcoin_t, bitcoin_conf_t, bitcoin_conf_t) + +manage_dirs_pattern(bitcoin_t, bitcoin_var_lib_t, bitcoin_var_lib_t) +manage_files_pattern(bitcoin_t, bitcoin_var_lib_t, bitcoin_var_lib_t) +files_var_lib_filetrans(bitcoin_t, bitcoin_var_lib_t, { dir file }) + +manage_dirs_pattern(bitcoin_t, bitcoin_var_run_t, bitcoin_var_run_t) +manage_files_pattern(bitcoin_t, bitcoin_var_run_t, bitcoin_var_run_t) + +sysnet_dns_name_resolve(bitcoin_t) +corenet_all_recvfrom_unlabeled(bitcoin_t) + +allow bitcoin_t self:tcp_socket create_stream_socket_perms; +corenet_tcp_sendrecv_generic_if(bitcoin_t) +corenet_tcp_sendrecv_generic_node(bitcoin_t) +corenet_tcp_sendrecv_all_ports(bitcoin_t) +corenet_tcp_bind_generic_node(bitcoin_t) + +gen_require(` + type bitcoin_port_t; +') +allow bitcoin_t bitcoin_port_t:tcp_socket name_bind; + +gen_require(` + type bitcoin_port_t; +') +allow bitcoin_t bitcoin_port_t:tcp_socket name_connect; + +domain_use_interactive_fds(bitcoin_t) + +files_read_etc_files(bitcoin_t) + +miscfiles_read_localization(bitcoin_t) + +sysnet_dns_name_resolve(bitcoin_t) + +allow bitcoin_t bitcoin_exec_t:file execute_no_trans; +allow bitcoin_t self:process setsched; +corecmd_exec_ls(bitcoin_t) +corenet_tcp_connect_http_port(bitcoin_t) +dev_read_urand(bitcoin_t) +fs_getattr_xattr_fs(bitcoin_t) +kernel_read_system_state(bitcoin_t) From 0e4b50a48c72061f4bafe7f99f0b261a148b457b Mon Sep 17 00:00:00 2001 From: Alice Wonder Date: Fri, 26 Feb 2016 10:09:03 -0800 Subject: [PATCH 0005/1802] Description of RPM directory --- contrib/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contrib/README.md b/contrib/README.md index b6e572102acb7..fe77476037682 100644 --- a/contrib/README.md +++ b/contrib/README.md @@ -42,6 +42,9 @@ Various PGP files of core developers. ### [MacDeploy](/contrib/macdeploy) ### Scripts and notes for Mac builds. +### [RPM](/contrib/rpm) ### +RPM spec file for building bitcoin-core on RPM based distributions + Test and Verify Tools --------------------- From fa58c76b9ff01abfc7f037fee85e70f342981d42 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Fri, 25 Dec 2015 13:14:26 +0100 Subject: [PATCH 0006/1802] [gitian] Default reference_datetime to commit author date --- contrib/gitian-descriptors/gitian-linux.yml | 3 +-- contrib/gitian-descriptors/gitian-osx-signer.yml | 1 - contrib/gitian-descriptors/gitian-osx.yml | 3 +-- contrib/gitian-descriptors/gitian-win-signer.yml | 1 - contrib/gitian-descriptors/gitian-win.yml | 3 +-- 5 files changed, 3 insertions(+), 8 deletions(-) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index 1f2c4f9999a67..8b2ab4ebfd25b 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -5,7 +5,7 @@ suites: - "trusty" architectures: - "amd64" -packages: +packages: - "curl" - "g++-multilib" - "git-core" @@ -18,7 +18,6 @@ packages: - "binutils-gold" - "ca-certificates" - "python" -reference_datetime: "2016-01-01 00:00:00" remotes: - "url": "https://github.com/bitcoin/bitcoin.git" "dir": "bitcoin" diff --git a/contrib/gitian-descriptors/gitian-osx-signer.yml b/contrib/gitian-descriptors/gitian-osx-signer.yml index c4165470af132..ea67e1b7e5b5d 100644 --- a/contrib/gitian-descriptors/gitian-osx-signer.yml +++ b/contrib/gitian-descriptors/gitian-osx-signer.yml @@ -6,7 +6,6 @@ architectures: - "amd64" packages: - "faketime" -reference_datetime: "2016-01-01 00:00:00" remotes: - "url": "https://github.com/bitcoin/bitcoin-detached-sigs.git" "dir": "signature" diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml index 6f68ae08ce73f..74fc2e93ad3d8 100644 --- a/contrib/gitian-descriptors/gitian-osx.yml +++ b/contrib/gitian-descriptors/gitian-osx.yml @@ -5,7 +5,7 @@ suites: - "trusty" architectures: - "amd64" -packages: +packages: - "ca-certificates" - "curl" - "g++" @@ -27,7 +27,6 @@ packages: - "python-dev" - "python-setuptools" - "fonts-tuffy" -reference_datetime: "2016-01-01 00:00:00" remotes: - "url": "https://github.com/bitcoin/bitcoin.git" "dir": "bitcoin" diff --git a/contrib/gitian-descriptors/gitian-win-signer.yml b/contrib/gitian-descriptors/gitian-win-signer.yml index 27c4f01eb4ed9..6b53b89b60b44 100644 --- a/contrib/gitian-descriptors/gitian-win-signer.yml +++ b/contrib/gitian-descriptors/gitian-win-signer.yml @@ -7,7 +7,6 @@ architectures: packages: - "libssl-dev" - "autoconf" -reference_datetime: "2016-01-01 00:00:00" remotes: - "url": "https://github.com/bitcoin/bitcoin-detached-sigs.git" "dir": "signature" diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml index f0fbff3e1035d..719ca9c232bfe 100644 --- a/contrib/gitian-descriptors/gitian-win.yml +++ b/contrib/gitian-descriptors/gitian-win.yml @@ -5,7 +5,7 @@ suites: - "trusty" architectures: - "amd64" -packages: +packages: - "curl" - "g++" - "git-core" @@ -21,7 +21,6 @@ packages: - "zip" - "ca-certificates" - "python" -reference_datetime: "2016-01-01 00:00:00" remotes: - "url": "https://github.com/bitcoin/bitcoin.git" "dir": "bitcoin" From d6cc6a1830bb7e03701488ca30c46457434dec6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Thu, 11 Feb 2016 01:07:22 +0000 Subject: [PATCH 0007/1802] Use CCoinControl selection in CWallet::FundTransaction --- src/coincontrol.h | 5 ++--- src/qt/coincontroldialog.cpp | 2 +- src/wallet/wallet.cpp | 13 ++----------- 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/src/coincontrol.h b/src/coincontrol.h index 9626ad2c5b774..12fe9ce219c27 100644 --- a/src/coincontrol.h +++ b/src/coincontrol.h @@ -38,10 +38,9 @@ class CCoinControl return (setSelected.size() > 0); } - bool IsSelected(const uint256& hash, unsigned int n) const + bool IsSelected(const COutPoint& output) const { - COutPoint outpt(hash, n); - return (setSelected.count(outpt) > 0); + return (setSelected.count(output) > 0); } void Select(const COutPoint& output) diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index 7393c83c7d0df..f909499952c7e 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -796,7 +796,7 @@ void CoinControlDialog::updateView() } // set checkbox - if (coinControl->IsSelected(txhash, out.i)) + if (coinControl->IsSelected(COutPoint(txhash, out.i))) itemOutput->setCheckState(COLUMN_CHECKBOX, Qt::Checked); } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 8ea957ee33938..6c7173ede1ad4 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1669,7 +1669,7 @@ void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const isminetype mine = IsMine(pcoin->vout[i]); if (!(IsSpent(wtxid, i)) && mine != ISMINE_NO && !IsLockedCoin((*it).first, i) && (pcoin->vout[i].nValue > 0 || fIncludeZeroValue) && - (!coinControl || !coinControl->HasSelected() || coinControl->fAllowOtherInputs || coinControl->IsSelected((*it).first, i))) + (!coinControl || !coinControl->HasSelected() || coinControl->fAllowOtherInputs || coinControl->IsSelected(COutPoint((*it).first, i)))) vCoins.push_back(COutput(pcoin, i, nDepth, ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || (coinControl && coinControl->fAllowWatchOnly && (mine & ISMINE_WATCH_SOLVABLE) != ISMINE_NO))); @@ -1927,16 +1927,7 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount &nFeeRet, int& nC // Add new txins (keeping original txin scriptSig/order) BOOST_FOREACH(const CTxIn& txin, wtx.vin) { - bool found = false; - BOOST_FOREACH(const CTxIn& origTxIn, tx.vin) - { - if (txin.prevout.hash == origTxIn.prevout.hash && txin.prevout.n == origTxIn.prevout.n) - { - found = true; - break; - } - } - if (!found) + if (!coinControl.IsSelected(txin.prevout)) tx.vin.push_back(txin); } From 3252208cb10be645bae415c90fb2ed8217838490 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Wed, 9 Mar 2016 00:19:16 +0000 Subject: [PATCH 0008/1802] Improve EncodeBase58 performance --- src/base58.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/base58.cpp b/src/base58.cpp index 5e26cf8d4738f..d81c26092c305 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -68,26 +68,31 @@ std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend) { // Skip & count leading zeroes. int zeroes = 0; + int length = 0; while (pbegin != pend && *pbegin == 0) { pbegin++; zeroes++; } // Allocate enough space in big-endian base58 representation. - std::vector b58((pend - pbegin) * 138 / 100 + 1); // log(256) / log(58), rounded up. + int size = (pend - pbegin) * 138 / 100 + 1; // log(256) / log(58), rounded up. + std::vector b58(size); // Process the bytes. while (pbegin != pend) { int carry = *pbegin; + int i = 0; // Apply "b58 = b58 * 256 + ch". - for (std::vector::reverse_iterator it = b58.rbegin(); it != b58.rend(); it++) { + for (std::vector::reverse_iterator it = b58.rbegin(); (carry != 0 || i < length) && (it != b58.rend()); it++, i++) { carry += 256 * (*it); *it = carry % 58; carry /= 58; } + assert(carry == 0); + length = i; pbegin++; } // Skip leading zeroes in base58 result. - std::vector::iterator it = b58.begin(); + std::vector::iterator it = b58.begin() + (size - length); while (it != b58.end() && *it == 0) it++; // Translate the result into a string. From c3932b32700a210b5fbf36e32bddac604dec9288 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 14 Mar 2016 19:22:11 +0100 Subject: [PATCH 0009/1802] List solvability in listunspent output and improve help --- src/qt/walletmodel.cpp | 6 +++--- src/wallet/rpcwallet.cpp | 6 +++++- src/wallet/test/wallet_tests.cpp | 2 +- src/wallet/wallet.cpp | 3 ++- src/wallet/wallet.h | 5 +++-- 5 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index cf38c64eb0dee..a5b43270f3a56 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -572,7 +572,7 @@ void WalletModel::getOutputs(const std::vector& vOutpoints, std::vect if (!wallet->mapWallet.count(outpoint.hash)) continue; int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain(); if (nDepth < 0) continue; - COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth, true); + COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth, true, true); vOutputs.push_back(out); } } @@ -599,7 +599,7 @@ void WalletModel::listCoins(std::map >& mapCoins) if (!wallet->mapWallet.count(outpoint.hash)) continue; int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain(); if (nDepth < 0) continue; - COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth, true); + COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth, true, true); if (outpoint.n < out.tx->vout.size() && wallet->IsMine(out.tx->vout[outpoint.n]) == ISMINE_SPENDABLE) vCoins.push_back(out); } @@ -611,7 +611,7 @@ void WalletModel::listCoins(std::map >& mapCoins) while (wallet->IsChange(cout.tx->vout[cout.i]) && cout.tx->vin.size() > 0 && wallet->IsMine(cout.tx->vin[0])) { if (!wallet->mapWallet.count(cout.tx->vin[0].prevout.hash)) break; - cout = COutput(&wallet->mapWallet[cout.tx->vin[0].prevout.hash], cout.tx->vin[0].prevout.n, 0, true); + cout = COutput(&wallet->mapWallet[cout.tx->vin[0].prevout.hash], cout.tx->vin[0].prevout.n, 0, true, true); } CTxDestination address; diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 759f894ccbe67..077b3525472e4 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2348,7 +2348,9 @@ UniValue listunspent(const UniValue& params, bool fHelp) " \"account\" : \"account\", (string) DEPRECATED. The associated account, or \"\" for the default account\n" " \"scriptPubKey\" : \"key\", (string) the script key\n" " \"amount\" : x.xxx, (numeric) the transaction amount in " + CURRENCY_UNIT + "\n" - " \"confirmations\" : n (numeric) The number of confirmations\n" + " \"confirmations\" : n, (numeric) The number of confirmations\n" + " \"spendable\" : xxx, (bool) Whether we have the private keys to spend this output\n" + " \"solvable\" : xxx (bool) Whether we know how to spend this output, ignoring the lack of keys\n" " }\n" " ,...\n" "]\n" @@ -2425,6 +2427,7 @@ UniValue listunspent(const UniValue& params, bool fHelp) entry.push_back(Pair("amount",ValueFromAmount(nValue))); entry.push_back(Pair("confirmations",out.nDepth)); entry.push_back(Pair("spendable", out.fSpendable)); + entry.push_back(Pair("solvable", out.fSolvable)); results.push_back(entry); } @@ -2446,6 +2449,7 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) "Note that all existing inputs must have their previous output transaction be in the wallet.\n" "Note that all inputs selected must be of standard form and P2SH scripts must be" "in the wallet using importaddress or addmultisigaddress (to calculate fees).\n" + "You can see whether this is the case by checking the \"solvable\" field in the listunspent output.\n" "Only pay-to-pubkey, multisig, and P2SH versions thereof are currently supported for watch-only\n" "\nArguments:\n" "1. \"hexstring\" (string, required) The hex string of the raw transaction\n" diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index e84d5880261c4..06c9c903e4c76 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -48,7 +48,7 @@ static void add_coin(const CAmount& nValue, int nAge = 6*24, bool fIsFromMe = fa wtx->fDebitCached = true; wtx->nDebitCached = 1; } - COutput output(wtx, nInput, nAge, true); + COutput output(wtx, nInput, nAge, true, true); vCoins.push_back(output); } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index bcfefa27ff269..59008282473f8 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1675,7 +1675,8 @@ void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const (!coinControl || !coinControl->HasSelected() || coinControl->fAllowOtherInputs || coinControl->IsSelected((*it).first, i))) vCoins.push_back(COutput(pcoin, i, nDepth, ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || - (coinControl && coinControl->fAllowWatchOnly && (mine & ISMINE_WATCH_SOLVABLE) != ISMINE_NO))); + (coinControl && coinControl->fAllowWatchOnly && (mine & ISMINE_WATCH_SOLVABLE) != ISMINE_NO), + (mine & (ISMINE_SPENDABLE | ISMINE_WATCH_SOLVABLE)) != ISMINE_NO)); } } } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index d009211a923eb..37a84153b4098 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -412,10 +412,11 @@ class COutput int i; int nDepth; bool fSpendable; + bool fSolvable; - COutput(const CWalletTx *txIn, int iIn, int nDepthIn, bool fSpendableIn) + COutput(const CWalletTx *txIn, int iIn, int nDepthIn, bool fSpendableIn, bool fSolvableIn) { - tx = txIn; i = iIn; nDepth = nDepthIn; fSpendable = fSpendableIn; + tx = txIn; i = iIn; nDepth = nDepthIn; fSpendable = fSpendableIn; fSolvable = fSolvableIn; } std::string ToString() const; From 6851107b3a52ec869e5e3a2cb4eb02d6c743b8e5 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 15 Feb 2016 05:13:27 +0100 Subject: [PATCH 0010/1802] BIP9 Implementation Inspired by former implementations by Eric Lombrozo and Rusty Russell, and based on code by Jorge Timon. --- src/Makefile.am | 2 + src/chain.h | 2 - src/chainparams.cpp | 6 ++ src/consensus/params.h | 28 +++++++++ src/init.cpp | 2 +- src/main.cpp | 80 +++++++++++++++++++++-- src/main.h | 5 ++ src/miner.cpp | 11 ++-- src/primitives/block.h | 3 +- src/test/miner_tests.cpp | 33 +++++++++- src/versionbits.cpp | 133 +++++++++++++++++++++++++++++++++++++++ src/versionbits.h | 59 +++++++++++++++++ 12 files changed, 345 insertions(+), 19 deletions(-) create mode 100644 src/versionbits.cpp create mode 100644 src/versionbits.h diff --git a/src/Makefile.am b/src/Makefile.am index fa7a78f330694..7765ea43edc1a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -152,6 +152,7 @@ BITCOIN_CORE_H = \ utilmoneystr.h \ utiltime.h \ validationinterface.h \ + versionbits.h \ wallet/crypter.h \ wallet/db.h \ wallet/rpcwallet.h \ @@ -204,6 +205,7 @@ libbitcoin_server_a_SOURCES = \ txdb.cpp \ txmempool.cpp \ validationinterface.cpp \ + versionbits.cpp \ $(BITCOIN_CORE_H) if ENABLE_ZMQ diff --git a/src/chain.h b/src/chain.h index 9199983565ca7..5b9605a80bdb3 100644 --- a/src/chain.h +++ b/src/chain.h @@ -14,8 +14,6 @@ #include -#include - struct CDiskBlockPos { int nFile; diff --git a/src/chainparams.cpp b/src/chainparams.cpp index b962f6ac0a053..6501af78b3ae6 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -81,6 +81,8 @@ class CMainParams : public CChainParams { consensus.nPowTargetSpacing = 10 * 60; consensus.fPowAllowMinDifficultyBlocks = false; consensus.fPowNoRetargeting = false; + consensus.nRuleChangeActivationThreshold = 1916; // 95% of 2016 + consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing /** * The message start string is designed to be unlikely to occur in normal data. * The characters are rarely used upper ASCII, not valid as UTF-8, and produce @@ -162,6 +164,8 @@ class CTestNetParams : public CChainParams { consensus.nPowTargetSpacing = 10 * 60; consensus.fPowAllowMinDifficultyBlocks = true; consensus.fPowNoRetargeting = false; + consensus.nRuleChangeActivationThreshold = 1512; // 75% for testchains + consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing pchMessageStart[0] = 0x0b; pchMessageStart[1] = 0x11; pchMessageStart[2] = 0x09; @@ -225,6 +229,8 @@ class CRegTestParams : public CChainParams { consensus.nPowTargetSpacing = 10 * 60; consensus.fPowAllowMinDifficultyBlocks = true; consensus.fPowNoRetargeting = true; + consensus.nRuleChangeActivationThreshold = 108; // 75% for testchains + consensus.nMinerConfirmationWindow = 144; // Faster than normal for regtest (144 instead of 2016) pchMessageStart[0] = 0xfa; pchMessageStart[1] = 0xbf; diff --git a/src/consensus/params.h b/src/consensus/params.h index 335750fe80724..d5039211a30be 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -7,8 +7,28 @@ #define BITCOIN_CONSENSUS_PARAMS_H #include "uint256.h" +#include +#include namespace Consensus { + +enum DeploymentPos +{ + MAX_VERSION_BITS_DEPLOYMENTS = 0, +}; + +/** + * Struct for each individual consensus rule change using BIP9. + */ +struct BIP9Deployment { + /** Bit position to select the particular bit in nVersion. */ + int bit; + /** Start MedianTime for version bits miner confirmation. Can be a date in the past */ + int64_t nStartTime; + /** Timeout/expiry MedianTime for the deployment attempt. */ + int64_t nTimeout; +}; + /** * Parameters that influence chain consensus. */ @@ -22,6 +42,14 @@ struct Params { /** Block height and hash at which BIP34 becomes active */ int BIP34Height; uint256 BIP34Hash; + /** + * Minimum blocks including miner confirmation of the total of 2016 blocks in a retargetting period, + * (nPowTargetTimespan / nPowTargetSpacing) which is also used for BIP9 deployments. + * Examples: 1916 for 95%, 1512 for testchains. + */ + uint32_t nRuleChangeActivationThreshold; + uint32_t nMinerConfirmationWindow; + BIP9Deployment vDeployments[MAX_VERSION_BITS_DEPLOYMENTS]; /** Proof of work parameters */ uint256 powLimit; bool fPowAllowMinDifficultyBlocks; diff --git a/src/init.cpp b/src/init.cpp index 637b69ab0571e..a39256c6e3220 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -466,7 +466,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-blockmaxsize=", strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE)); strUsage += HelpMessageOpt("-blockprioritysize=", strprintf(_("Set maximum size of high-priority/low-fee transactions in bytes (default: %d)"), DEFAULT_BLOCK_PRIORITY_SIZE)); if (showDebug) - strUsage += HelpMessageOpt("-blockversion=", strprintf("Override block version to test forking scenarios (default: %d)", (int)CBlock::CURRENT_VERSION)); + strUsage += HelpMessageOpt("-blockversion=", "Override block version to test forking scenarios"); strUsage += HelpMessageGroup(_("RPC server options:")); strUsage += HelpMessageOpt("-server", _("Accept command line and JSON-RPC commands")); diff --git a/src/main.cpp b/src/main.cpp index 027a36394c34d..45e58818977d3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -34,6 +34,7 @@ #include "utilmoneystr.h" #include "utilstrencodings.h" #include "validationinterface.h" +#include "versionbits.h" #include @@ -2083,6 +2084,51 @@ void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const } } +// Protected by cs_main +static VersionBitsCache versionbitscache; + +int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params) +{ + LOCK(cs_main); + int32_t nVersion = VERSIONBITS_TOP_BITS; + + for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) { + ThresholdState state = VersionBitsState(pindexPrev, params, (Consensus::DeploymentPos)i, versionbitscache); + if (state == THRESHOLD_LOCKED_IN || state == THRESHOLD_STARTED) { + nVersion |= VersionBitsMask(params, (Consensus::DeploymentPos)i); + } + } + + return nVersion; +} + +/** + * Threshold condition checker that triggers when unknown versionbits are seen on the network. + */ +class WarningBitsConditionChecker : public AbstractThresholdConditionChecker +{ +private: + int bit; + +public: + WarningBitsConditionChecker(int bitIn) : bit(bitIn) {} + + int64_t BeginTime(const Consensus::Params& params) const { return 0; } + int64_t EndTime(const Consensus::Params& params) const { return std::numeric_limits::max(); } + int Period(const Consensus::Params& params) const { return params.nMinerConfirmationWindow; } + int Threshold(const Consensus::Params& params) const { return params.nRuleChangeActivationThreshold; } + + bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const + { + return ((pindex->nVersion & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) && + ((pindex->nVersion >> bit) & 1) != 0 && + ((ComputeBlockVersion(pindex->pprev, params) >> bit) & 1) == 0; + } +}; + +// Protected by cs_main +static ThresholdConditionCache warningcache[VERSIONBITS_NUM_BITS]; + static int64_t nTimeCheck = 0; static int64_t nTimeForks = 0; static int64_t nTimeVerify = 0; @@ -2452,24 +2498,42 @@ void static UpdateTip(CBlockIndex *pindexNew) { // Check the version of the last 100 blocks to see if we need to upgrade: static bool fWarned = false; - if (!IsInitialBlockDownload() && !fWarned) + if (!IsInitialBlockDownload()) { int nUpgraded = 0; const CBlockIndex* pindex = chainActive.Tip(); + for (int bit = 0; bit < VERSIONBITS_NUM_BITS; bit++) { + WarningBitsConditionChecker checker(bit); + ThresholdState state = checker.GetStateFor(pindex, chainParams.GetConsensus(), warningcache[bit]); + if (state == THRESHOLD_ACTIVE || state == THRESHOLD_LOCKED_IN) { + if (state == THRESHOLD_ACTIVE) { + strMiscWarning = strprintf(_("Warning: unknown new rules activated (versionbit %i)"), bit); + if (!fWarned) { + CAlert::Notify(strMiscWarning, true); + fWarned = true; + } + } else { + LogPrintf("%s: unknown new rules are about to activate (versionbit %i)\n", __func__, bit); + } + } + } for (int i = 0; i < 100 && pindex != NULL; i++) { - if (pindex->nVersion > CBlock::CURRENT_VERSION) + int32_t nExpectedVersion = ComputeBlockVersion(pindex->pprev, chainParams.GetConsensus()); + if (pindex->nVersion > VERSIONBITS_LAST_OLD_BLOCK_VERSION && (pindex->nVersion & ~nExpectedVersion) != 0) ++nUpgraded; pindex = pindex->pprev; } if (nUpgraded > 0) - LogPrintf("%s: %d of last 100 blocks above version %d\n", __func__, nUpgraded, (int)CBlock::CURRENT_VERSION); + LogPrintf("%s: %d of last 100 blocks have unexpected version\n", __func__, nUpgraded); if (nUpgraded > 100/2) { // strMiscWarning is read by GetWarnings(), called by Qt and the JSON-RPC code to warn the user: - strMiscWarning = _("Warning: This version is obsolete; upgrade required!"); - CAlert::Notify(strMiscWarning, true); - fWarned = true; + strMiscWarning = _("Warning: Unknown block versions being mined! It's possible unknown rules are in effect"); + if (!fWarned) { + CAlert::Notify(strMiscWarning, true); + fWarned = true; + } } } } @@ -3763,6 +3827,10 @@ void UnloadBlockIndex() setDirtyFileInfo.clear(); mapNodeState.clear(); recentRejects.reset(NULL); + versionbitscache.Clear(); + for (int b = 0; b < VERSIONBITS_NUM_BITS; b++) { + warningcache[b].clear(); + } BOOST_FOREACH(BlockMap::value_type& entry, mapBlockIndex) { delete entry.second; diff --git a/src/main.h b/src/main.h index 5ba2be251c45b..7670bb74d357c 100644 --- a/src/main.h +++ b/src/main.h @@ -537,6 +537,11 @@ extern CBlockTreeDB *pblocktree; */ int GetSpendHeight(const CCoinsViewCache& inputs); +/** + * Determine what nVersion a new block should use. + */ +int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params); + /** Reject codes greater or equal to this can be returned by AcceptToMemPool * for transactions, to signal internal conditions. They cannot and should not * be sent over the P2P network. diff --git a/src/miner.cpp b/src/miner.cpp index ec87e84ca7d02..ef8fd4db43d0e 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -79,11 +79,6 @@ CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& s return NULL; CBlock *pblock = &pblocktemplate->block; // pointer for convenience - // -regtest only: allow overriding block.nVersion with - // -blockversion=N to test forking scenarios - if (chainparams.MineBlocksOnDemand()) - pblock->nVersion = GetArg("-blockversion", pblock->nVersion); - // Create coinbase tx CMutableTransaction txNew; txNew.vin.resize(1); @@ -137,6 +132,12 @@ CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& s pblock->nTime = GetAdjustedTime(); const int64_t nMedianTimePast = pindexPrev->GetMedianTimePast(); + pblock->nVersion = ComputeBlockVersion(pindexPrev, chainparams.GetConsensus()); + // -regtest only: allow overriding block.nVersion with + // -blockversion=N to test forking scenarios + if (chainparams.MineBlocksOnDemand()) + pblock->nVersion = GetArg("-blockversion", pblock->nVersion); + int64_t nLockTimeCutoff = (STANDARD_LOCKTIME_VERIFY_FLAGS & LOCKTIME_MEDIAN_TIME_PAST) ? nMedianTimePast : pblock->GetBlockTime(); diff --git a/src/primitives/block.h b/src/primitives/block.h index 0e93399c08e47..42276b2bc26bc 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -21,7 +21,6 @@ class CBlockHeader { public: // header - static const int32_t CURRENT_VERSION=4; int32_t nVersion; uint256 hashPrevBlock; uint256 hashMerkleRoot; @@ -49,7 +48,7 @@ class CBlockHeader void SetNull() { - nVersion = CBlockHeader::CURRENT_VERSION; + nVersion = 0; hashPrevBlock.SetNull(); hashMerkleRoot.SetNull(); nTime = 0; diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index f3297e074de48..ab6485081ceed 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -247,13 +247,40 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) // subsidy changing int nHeight = chainActive.Height(); - chainActive.Tip()->nHeight = 209999; + // Create an actual 209999-long block chain (without valid blocks). + while (chainActive.Tip()->nHeight < 209999) { + CBlockIndex* prev = chainActive.Tip(); + CBlockIndex* next = new CBlockIndex(); + next->phashBlock = new uint256(GetRandHash()); + pcoinsTip->SetBestBlock(next->GetBlockHash()); + next->pprev = prev; + next->nHeight = prev->nHeight + 1; + next->BuildSkip(); + chainActive.SetTip(next); + } BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); delete pblocktemplate; - chainActive.Tip()->nHeight = 210000; + // Extend to a 210000-long block chain. + while (chainActive.Tip()->nHeight < 210000) { + CBlockIndex* prev = chainActive.Tip(); + CBlockIndex* next = new CBlockIndex(); + next->phashBlock = new uint256(GetRandHash()); + pcoinsTip->SetBestBlock(next->GetBlockHash()); + next->pprev = prev; + next->nHeight = prev->nHeight + 1; + next->BuildSkip(); + chainActive.SetTip(next); + } BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); delete pblocktemplate; - chainActive.Tip()->nHeight = nHeight; + // Delete the dummy blocks again. + while (chainActive.Tip()->nHeight > nHeight) { + CBlockIndex* del = chainActive.Tip(); + chainActive.SetTip(del->pprev); + pcoinsTip->SetBestBlock(del->pprev->GetBlockHash()); + delete del->phashBlock; + delete del; + } // non-final txs in mempool SetMockTime(chainActive.Tip()->GetMedianTimePast()+1); diff --git a/src/versionbits.cpp b/src/versionbits.cpp new file mode 100644 index 0000000000000..fbb60c0fc598e --- /dev/null +++ b/src/versionbits.cpp @@ -0,0 +1,133 @@ +// Copyright (c) 2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "versionbits.h" + +ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const +{ + int nPeriod = Period(params); + int nThreshold = Threshold(params); + int64_t nTimeStart = BeginTime(params); + int64_t nTimeTimeout = EndTime(params); + + // A block's state is always the same as that of the first of its period, so it is computed based on a pindexPrev whose height equals a multiple of nPeriod - 1. + if (pindexPrev != NULL) { + pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod)); + } + + // Walk backwards in steps of nPeriod to find a pindexPrev whose information is known + std::vector vToCompute; + while (cache.count(pindexPrev) == 0) { + if (pindexPrev == NULL) { + // The genesis block is by definition defined. + cache[pindexPrev] = THRESHOLD_DEFINED; + break; + } + if (pindexPrev->GetMedianTimePast() < nTimeStart) { + // Optimizaton: don't recompute down further, as we know every earlier block will be before the start time + cache[pindexPrev] = THRESHOLD_DEFINED; + break; + } + vToCompute.push_back(pindexPrev); + pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod); + } + + // At this point, cache[pindexPrev] is known + assert(cache.count(pindexPrev)); + ThresholdState state = cache[pindexPrev]; + + // Now walk forward and compute the state of descendants of pindexPrev + while (!vToCompute.empty()) { + ThresholdState stateNext = state; + pindexPrev = vToCompute.back(); + vToCompute.pop_back(); + + switch (state) { + case THRESHOLD_DEFINED: { + if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) { + stateNext = THRESHOLD_FAILED; + } else if (pindexPrev->GetMedianTimePast() >= nTimeStart) { + stateNext = THRESHOLD_STARTED; + } + break; + } + case THRESHOLD_STARTED: { + if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) { + stateNext = THRESHOLD_FAILED; + break; + } + // We need to count + const CBlockIndex* pindexCount = pindexPrev; + int count = 0; + for (int i = 0; i < nPeriod; i++) { + if (Condition(pindexCount, params)) { + count++; + } + pindexCount = pindexCount->pprev; + } + if (count >= nThreshold) { + stateNext = THRESHOLD_LOCKED_IN; + } + break; + } + case THRESHOLD_LOCKED_IN: { + // Always progresses into ACTIVE. + stateNext = THRESHOLD_ACTIVE; + break; + } + case THRESHOLD_FAILED: + case THRESHOLD_ACTIVE: { + // Nothing happens, these are terminal states. + break; + } + } + cache[pindexPrev] = state = stateNext; + } + + return state; +} + +namespace +{ +/** + * Class to implement versionbits logic. + */ +class VersionBitsConditionChecker : public AbstractThresholdConditionChecker { +private: + const Consensus::DeploymentPos id; + +protected: + int64_t BeginTime(const Consensus::Params& params) const { return params.vDeployments[id].nStartTime; } + int64_t EndTime(const Consensus::Params& params) const { return params.vDeployments[id].nTimeout; } + int Period(const Consensus::Params& params) const { return params.nMinerConfirmationWindow; } + int Threshold(const Consensus::Params& params) const { return params.nRuleChangeActivationThreshold; } + + bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const + { + return (((pindex->nVersion & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) && (pindex->nVersion & Mask(params)) != 0); + } + +public: + VersionBitsConditionChecker(Consensus::DeploymentPos id_) : id(id_) {} + uint32_t Mask(const Consensus::Params& params) const { return ((uint32_t)1) << params.vDeployments[id].bit; } +}; + +} + +ThresholdState VersionBitsState(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache) +{ + return VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, cache.caches[pos]); +} + +uint32_t VersionBitsMask(const Consensus::Params& params, Consensus::DeploymentPos pos) +{ + return VersionBitsConditionChecker(pos).Mask(params); +} + +void VersionBitsCache::Clear() +{ + for (unsigned int d = 0; d < Consensus::MAX_VERSION_BITS_DEPLOYMENTS; d++) { + caches[d].clear(); + } +} diff --git a/src/versionbits.h b/src/versionbits.h new file mode 100644 index 0000000000000..04f4738272796 --- /dev/null +++ b/src/versionbits.h @@ -0,0 +1,59 @@ +// Copyright (c) 2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_CONSENSUS_VERSIONBITS +#define BITCOIN_CONSENSUS_VERSIONBITS + +#include "chain.h" +#include + +/** What block version to use for new blocks (pre versionbits) */ +static const int32_t VERSIONBITS_LAST_OLD_BLOCK_VERSION = 4; +/** What bits to set in version for versionbits blocks */ +static const int32_t VERSIONBITS_TOP_BITS = 0x20000000UL; +/** What bitmask determines whether versionbits is in use */ +static const int32_t VERSIONBITS_TOP_MASK = 0xE0000000UL; +/** Total bits available for versionbits */ +static const int32_t VERSIONBITS_NUM_BITS = 29; + +enum ThresholdState { + THRESHOLD_DEFINED, + THRESHOLD_STARTED, + THRESHOLD_LOCKED_IN, + THRESHOLD_ACTIVE, + THRESHOLD_FAILED, +}; + +// A map that gives the state for blocks whose height is a multiple of Period(). +// The map is indexed by the block's parent, however, so all keys in the map +// will either be NULL or a block with (height + 1) % Period() == 0. +typedef std::map ThresholdConditionCache; + +/** + * Abstract class that implements BIP9-style threshold logic, and caches results. + */ +class AbstractThresholdConditionChecker { +protected: + virtual bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const =0; + virtual int64_t BeginTime(const Consensus::Params& params) const =0; + virtual int64_t EndTime(const Consensus::Params& params) const =0; + virtual int Period(const Consensus::Params& params) const =0; + virtual int Threshold(const Consensus::Params& params) const =0; + +public: + // Note that the function below takes a pindexPrev as input: they compute information for block B based on its parent. + ThresholdState GetStateFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const; +}; + +struct VersionBitsCache +{ + ThresholdConditionCache caches[Consensus::MAX_VERSION_BITS_DEPLOYMENTS]; + + void Clear(); +}; + +ThresholdState VersionBitsState(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache); +uint32_t VersionBitsMask(const Consensus::Params& params, Consensus::DeploymentPos pos); + +#endif From 732e774c0655a3a6bcb3f2f02c88b37ea1bd3e68 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 20 Feb 2016 02:57:36 +0100 Subject: [PATCH 0011/1802] Versionbits tests --- src/Makefile.test.include | 1 + src/test/versionbits_tests.cpp | 185 +++++++++++++++++++++++++++++++++ 2 files changed, 186 insertions(+) create mode 100644 src/test/versionbits_tests.cpp diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 0c4e47a147020..57f9ac50e0a01 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -83,6 +83,7 @@ BITCOIN_TESTS =\ test/timedata_tests.cpp \ test/transaction_tests.cpp \ test/txvalidationcache_tests.cpp \ + test/versionbits_tests.cpp \ test/uint256_tests.cpp \ test/univalue_tests.cpp \ test/util_tests.cpp diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp new file mode 100644 index 0000000000000..9de8461d847be --- /dev/null +++ b/src/test/versionbits_tests.cpp @@ -0,0 +1,185 @@ +// Copyright (c) 2014-2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "chain.h" +#include "random.h" +#include "versionbits.h" +#include "test/test_bitcoin.h" + +#include + +/* Define a virtual block time, one block per 10 minutes after Nov 14 2014, 0:55:36am */ +int32_t TestTime(int nHeight) { return 1415926536 + 600 * nHeight; } + +static const Consensus::Params paramsDummy = Consensus::Params(); + +class TestConditionChecker : public AbstractThresholdConditionChecker +{ +private: + mutable ThresholdConditionCache cache; + +public: + int64_t BeginTime(const Consensus::Params& params) const { return TestTime(10000); } + int64_t EndTime(const Consensus::Params& params) const { return TestTime(20000); } + int Period(const Consensus::Params& params) const { return 1000; } + int Threshold(const Consensus::Params& params) const { return 900; } + bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const { return (pindex->nVersion & 0x100); } + + ThresholdState GetStateFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateFor(pindexPrev, paramsDummy, cache); } +}; + +#define CHECKERS 6 + +class VersionBitsTester +{ + // A fake blockchain + std::vector vpblock; + + // 6 independent checkers for the same bit. + // The first one performs all checks, the second only 50%, the third only 25%, etc... + // This is to test whether lack of cached information leads to the same results. + TestConditionChecker checker[CHECKERS]; + + // Test counter (to identify failures) + int num; + +public: + VersionBitsTester() : num(0) {} + + VersionBitsTester& Reset() { + for (unsigned int i = 0; i < vpblock.size(); i++) { + delete vpblock[i]; + } + for (unsigned int i = 0; i < CHECKERS; i++) { + checker[i] = TestConditionChecker(); + } + vpblock.clear(); + return *this; + } + + ~VersionBitsTester() { + Reset(); + } + + VersionBitsTester& Mine(unsigned int height, int32_t nTime, int32_t nVersion) { + while (vpblock.size() < height) { + CBlockIndex* pindex = new CBlockIndex(); + pindex->nHeight = vpblock.size(); + pindex->pprev = vpblock.size() > 0 ? vpblock.back() : NULL; + pindex->nTime = nTime; + pindex->nVersion = nVersion; + pindex->BuildSkip(); + vpblock.push_back(pindex); + } + return *this; + } + + VersionBitsTester& TestDefined() { + for (int i = 0; i < CHECKERS; i++) { + if ((insecure_rand() & ((1 << i) - 1)) == 0) { + BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_DEFINED, strprintf("Test %i for DEFINED", num)); + } + } + num++; + return *this; + } + + VersionBitsTester& TestStarted() { + for (int i = 0; i < CHECKERS; i++) { + if ((insecure_rand() & ((1 << i) - 1)) == 0) { + BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_STARTED, strprintf("Test %i for STARTED", num)); + } + } + num++; + return *this; + } + + VersionBitsTester& TestLockedIn() { + for (int i = 0; i < CHECKERS; i++) { + if ((insecure_rand() & ((1 << i) - 1)) == 0) { + BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_LOCKED_IN, strprintf("Test %i for LOCKED_IN", num)); + } + } + num++; + return *this; + } + + VersionBitsTester& TestActive() { + for (int i = 0; i < CHECKERS; i++) { + if ((insecure_rand() & ((1 << i) - 1)) == 0) { + BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_ACTIVE, strprintf("Test %i for ACTIVE", num)); + } + } + num++; + return *this; + } + + VersionBitsTester& TestFailed() { + for (int i = 0; i < CHECKERS; i++) { + if ((insecure_rand() & ((1 << i) - 1)) == 0) { + BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_FAILED, strprintf("Test %i for FAILED", num)); + } + } + num++; + return *this; + } +}; + +BOOST_FIXTURE_TEST_SUITE(versionbits_tests, TestingSetup) + +BOOST_AUTO_TEST_CASE(versionbits_test) +{ + for (int i = 0; i < 64; i++) { + // DEFINED -> FAILED + VersionBitsTester().TestDefined() + .Mine(1, TestTime(1), 0x100).TestDefined() + .Mine(11, TestTime(11), 0x100).TestDefined() + .Mine(989, TestTime(989), 0x100).TestDefined() + .Mine(999, TestTime(20000), 0x100).TestDefined() + .Mine(1000, TestTime(20000), 0x100).TestFailed() + .Mine(1999, TestTime(30001), 0x100).TestFailed() + .Mine(2000, TestTime(30002), 0x100).TestFailed() + .Mine(2001, TestTime(30003), 0x100).TestFailed() + .Mine(2999, TestTime(30004), 0x100).TestFailed() + .Mine(3000, TestTime(30005), 0x100).TestFailed() + + // DEFINED -> STARTED -> FAILED + .Reset().TestDefined() + .Mine(1, TestTime(1), 0).TestDefined() + .Mine(1000, TestTime(10000) - 1, 0x100).TestDefined() // One second more and it would be defined + .Mine(2000, TestTime(10000), 0x100).TestStarted() // So that's what happens the next period + .Mine(2051, TestTime(10010), 0).TestStarted() // 51 old blocks + .Mine(2950, TestTime(10020), 0x100).TestStarted() // 899 new blocks + .Mine(3000, TestTime(20000), 0).TestFailed() // 50 old blocks (so 899 out of the past 1000) + .Mine(4000, TestTime(20010), 0x100).TestFailed() + + // DEFINED -> STARTED -> FAILED while threshold reached + .Reset().TestDefined() + .Mine(1, TestTime(1), 0).TestDefined() + .Mine(1000, TestTime(10000) - 1, 0x101).TestDefined() // One second more and it would be defined + .Mine(2000, TestTime(10000), 0x101).TestStarted() // So that's what happens the next period + .Mine(2999, TestTime(30000), 0x100).TestStarted() // 999 new blocks + .Mine(3000, TestTime(30000), 0x100).TestFailed() // 1 new block (so 1000 out of the past 1000 are new) + .Mine(3999, TestTime(30001), 0).TestFailed() + .Mine(4000, TestTime(30002), 0).TestFailed() + .Mine(14333, TestTime(30003), 0).TestFailed() + .Mine(24000, TestTime(40000), 0).TestFailed() + + // DEFINED -> STARTED -> LOCKEDIN at the last minute -> ACTIVE + .Reset().TestDefined() + .Mine(1, TestTime(1), 0).TestDefined() + .Mine(1000, TestTime(10000) - 1, 0x101).TestDefined() // One second more and it would be defined + .Mine(2000, TestTime(10000), 0x101).TestStarted() // So that's what happens the next period + .Mine(2050, TestTime(10010), 0x200).TestStarted() // 50 old blocks + .Mine(2950, TestTime(10020), 0x100).TestStarted() // 900 new blocks + .Mine(2999, TestTime(19999), 0x200).TestStarted() // 49 old blocks + .Mine(3000, TestTime(29999), 0x200).TestLockedIn() // 1 old block (so 900 out of the past 1000) + .Mine(3999, TestTime(30001), 0).TestLockedIn() + .Mine(4000, TestTime(30002), 0).TestActive() + .Mine(14333, TestTime(30003), 0).TestActive() + .Mine(24000, TestTime(40000), 0).TestActive(); + } +} + +BOOST_AUTO_TEST_SUITE_END() From d23f6c6a0d2dc8a3f5f159faf7a40157259a8f8f Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 3 Mar 2016 21:00:03 +0100 Subject: [PATCH 0012/1802] Softfork status report in RPC --- src/main.cpp | 6 +++++- src/main.h | 4 ++++ src/rpc/blockchain.cpp | 22 ++++++++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 45e58818977d3..e4567a8974c84 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5859,7 +5859,11 @@ bool SendMessages(CNode* pto) return strprintf("CBlockFileInfo(blocks=%u, size=%u, heights=%u...%u, time=%s...%s)", nBlocks, nSize, nHeightFirst, nHeightLast, DateTimeStrFormat("%Y-%m-%d", nTimeFirst), DateTimeStrFormat("%Y-%m-%d", nTimeLast)); } - +ThresholdState VersionBitsTipState(const Consensus::Params& params, Consensus::DeploymentPos pos) +{ + LOCK(cs_main); + return VersionBitsState(chainActive.Tip(), params, pos, versionbitscache); +} class CMainCleanup { diff --git a/src/main.h b/src/main.h index 7670bb74d357c..b66ad53c8a7a1 100644 --- a/src/main.h +++ b/src/main.h @@ -16,6 +16,7 @@ #include "net.h" #include "script/script_error.h" #include "sync.h" +#include "versionbits.h" #include #include @@ -289,6 +290,9 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa /** Convert CValidationState to a human-readable message for logging */ std::string FormatStateMessage(const CValidationState &state); +/** Get the BIP9 state for a given deployment at the current tip. */ +ThresholdState VersionBitsTipState(const Consensus::Params& params, Consensus::DeploymentPos pos); + struct CNodeStateStats { int nMisbehavior; int nSyncHeight; diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index da57973daeaf2..a110dff0d1d4a 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -604,6 +604,20 @@ static UniValue SoftForkDesc(const std::string &name, int version, CBlockIndex* return rv; } +static UniValue BIP9SoftForkDesc(const std::string& name, const Consensus::Params& consensusParams, Consensus::DeploymentPos id) +{ + UniValue rv(UniValue::VOBJ); + rv.push_back(Pair("id", name)); + switch (VersionBitsTipState(consensusParams, id)) { + case THRESHOLD_DEFINED: rv.push_back(Pair("status", "defined")); break; + case THRESHOLD_STARTED: rv.push_back(Pair("status", "started")); break; + case THRESHOLD_LOCKED_IN: rv.push_back(Pair("status", "locked_in")); break; + case THRESHOLD_ACTIVE: rv.push_back(Pair("status", "active")); break; + case THRESHOLD_FAILED: rv.push_back(Pair("status", "failed")); break; + } + return rv; +} + UniValue getblockchaininfo(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 0) @@ -634,6 +648,12 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) " },\n" " \"reject\": { ... } (object) progress toward rejecting pre-softfork blocks (same fields as \"enforce\")\n" " }, ...\n" + " ],\n" + " \"bip9_softforks\": [ (array) status of BIP9 softforks in progress\n" + " {\n" + " \"id\": \"xxxx\", (string) name of the softfork\n" + " \"status\": \"xxxx\", (string) one of \"defined\", \"started\", \"lockedin\", \"active\", \"failed\"\n" + " }\n" " ]\n" "}\n" "\nExamples:\n" @@ -657,10 +677,12 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) const Consensus::Params& consensusParams = Params().GetConsensus(); CBlockIndex* tip = chainActive.Tip(); UniValue softforks(UniValue::VARR); + UniValue bip9_softforks(UniValue::VARR); softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams)); softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams)); softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams)); obj.push_back(Pair("softforks", softforks)); + obj.push_back(Pair("bip9_softforks", bip9_softforks)); if (fPruneMode) { From 532cbb22b57f25c89df30588185b0db659871c86 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Wed, 9 Mar 2016 16:00:53 -0500 Subject: [PATCH 0013/1802] Add testing of ComputeBlockVersion --- src/chainparams.cpp | 9 +++ src/consensus/params.h | 3 +- src/test/versionbits_tests.cpp | 109 +++++++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+), 1 deletion(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 6501af78b3ae6..35e090a0b3b3e 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -83,6 +83,9 @@ class CMainParams : public CChainParams { consensus.fPowNoRetargeting = false; consensus.nRuleChangeActivationThreshold = 1916; // 95% of 2016 consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing + consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; + consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 1199145601; // January 1, 2008 + consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 1230767999; // December 31, 2008 /** * The message start string is designed to be unlikely to occur in normal data. * The characters are rarely used upper ASCII, not valid as UTF-8, and produce @@ -166,6 +169,9 @@ class CTestNetParams : public CChainParams { consensus.fPowNoRetargeting = false; consensus.nRuleChangeActivationThreshold = 1512; // 75% for testchains consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing + consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; + consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 1199145601; // January 1, 2008 + consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 1230767999; // December 31, 2008 pchMessageStart[0] = 0x0b; pchMessageStart[1] = 0x11; pchMessageStart[2] = 0x09; @@ -231,6 +237,9 @@ class CRegTestParams : public CChainParams { consensus.fPowNoRetargeting = true; consensus.nRuleChangeActivationThreshold = 108; // 75% for testchains consensus.nMinerConfirmationWindow = 144; // Faster than normal for regtest (144 instead of 2016) + consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; + consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 0; + consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 999999999999ULL; pchMessageStart[0] = 0xfa; pchMessageStart[1] = 0xbf; diff --git a/src/consensus/params.h b/src/consensus/params.h index d5039211a30be..7c3a8e84c3d35 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -14,7 +14,8 @@ namespace Consensus { enum DeploymentPos { - MAX_VERSION_BITS_DEPLOYMENTS = 0, + DEPLOYMENT_TESTDUMMY, + MAX_VERSION_BITS_DEPLOYMENTS }; /** diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp index 9de8461d847be..63dc4726bc8ea 100644 --- a/src/test/versionbits_tests.cpp +++ b/src/test/versionbits_tests.cpp @@ -6,6 +6,9 @@ #include "random.h" #include "versionbits.h" #include "test/test_bitcoin.h" +#include "chainparams.h" +#include "main.h" +#include "consensus/params.h" #include @@ -124,6 +127,8 @@ class VersionBitsTester num++; return *this; } + + CBlockIndex * Tip() { return vpblock.size() ? vpblock.back() : NULL; } }; BOOST_FIXTURE_TEST_SUITE(versionbits_tests, TestingSetup) @@ -182,4 +187,108 @@ BOOST_AUTO_TEST_CASE(versionbits_test) } } +BOOST_AUTO_TEST_CASE(versionbits_computeblockversion) +{ + // Check that ComputeBlockVersion will set the appropriate bit correctly + // on mainnet. + const Consensus::Params &mainnetParams = Params(CBaseChainParams::MAIN).GetConsensus(); + + // Use the TESTDUMMY deployment for testing purposes. + int64_t bit = mainnetParams.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit; + int64_t nStartTime = mainnetParams.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime; + int64_t nTimeout = mainnetParams.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout; + + assert(nStartTime < nTimeout); + + // In the first chain, test that the bit is set by CBV until it has failed. + // In the second chain, test the bit is set by CBV while STARTED and + // LOCKED-IN, and then no longer set while ACTIVE. + VersionBitsTester firstChain, secondChain; + + // Start generating blocks before nStartTime + int64_t nTime = nStartTime - 1; + + // Before MedianTimePast of the chain has crossed nStartTime, the bit + // should not be set. + CBlockIndex *lastBlock = NULL; + lastBlock = firstChain.Mine(2016, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip(); + BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, mainnetParams) & (1< 0) { + lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip(); + BOOST_CHECK((ComputeBlockVersion(lastBlock, mainnetParams) & (1< Date: Wed, 9 Mar 2016 09:48:20 -0500 Subject: [PATCH 0014/1802] Test versionbits deployments --- src/test/versionbits_tests.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp index 63dc4726bc8ea..1f86a06a3f7f7 100644 --- a/src/test/versionbits_tests.cpp +++ b/src/test/versionbits_tests.cpp @@ -185,6 +185,28 @@ BOOST_AUTO_TEST_CASE(versionbits_test) .Mine(14333, TestTime(30003), 0).TestActive() .Mine(24000, TestTime(40000), 0).TestActive(); } + + // Sanity checks of version bit deployments + const Consensus::Params &mainnetParams = Params(CBaseChainParams::MAIN).GetConsensus(); + for (int i=0; i<(int) Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) { + uint32_t bitmask = VersionBitsMask(mainnetParams, (Consensus::DeploymentPos)i); + // Make sure that no deployment tries to set an invalid bit. + BOOST_CHECK_EQUAL(bitmask & ~(uint32_t)VERSIONBITS_TOP_MASK, bitmask); + + // Verify that the deployment windows of different deployment using the + // same bit are disjoint. + // This test may need modification at such time as a new deployment + // is proposed that reuses the bit of an activated soft fork, before the + // end time of that soft fork. (Alternatively, the end time of that + // activated soft fork could be later changed to be earlier to avoid + // overlap.) + for (int j=i+1; j<(int) Consensus::MAX_VERSION_BITS_DEPLOYMENTS; j++) { + if (VersionBitsMask(mainnetParams, (Consensus::DeploymentPos)j) == bitmask) { + BOOST_CHECK(mainnetParams.vDeployments[j].nStartTime > mainnetParams.vDeployments[i].nTimeout || + mainnetParams.vDeployments[i].nStartTime > mainnetParams.vDeployments[j].nTimeout); + } + } + } } BOOST_AUTO_TEST_CASE(versionbits_computeblockversion) From 8c74cedef53ab791ed333f25794f8b9d2e9f51aa Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Tue, 15 Mar 2016 12:09:16 -0400 Subject: [PATCH 0015/1802] RPC test for BIP9 warning logic --- qa/pull-tester/rpc-tests.py | 1 + qa/rpc-tests/p2p-versionbits-warning.py | 160 ++++++++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100755 qa/rpc-tests/p2p-versionbits-warning.py diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index 485888e9b45eb..f15eaacbdaed8 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -115,6 +115,7 @@ 'invalidblockrequest.py', 'invalidtxrequest.py', 'abandonconflict.py', + 'p2p-versionbits-warning.py', ] testScriptsExt = [ 'bip65-cltv.py', diff --git a/qa/rpc-tests/p2p-versionbits-warning.py b/qa/rpc-tests/p2p-versionbits-warning.py new file mode 100755 index 0000000000000..061dcbf0e1e87 --- /dev/null +++ b/qa/rpc-tests/p2p-versionbits-warning.py @@ -0,0 +1,160 @@ +#!/usr/bin/env python2 +# Copyright (c) 2016 The Bitcoin Core developers +# Distributed under the MIT/X11 software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# + +from test_framework.mininode import * +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * +import time +from test_framework.blocktools import create_block, create_coinbase + +''' +Test version bits' warning system. + +Generate chains with block versions that appear to be signalling unknown +soft-forks, and test that warning alerts are generated. +''' + +VB_PERIOD = 144 # versionbits period length for regtest +VB_THRESHOLD = 108 # versionbits activation threshold for regtest +VB_TOP_BITS = 0x20000000 +VB_UNKNOWN_BIT = 27 # Choose a bit unassigned to any deployment + +# TestNode: bare-bones "peer". Used mostly as a conduit for a test to sending +# p2p messages to a node, generating the messages in the main testing logic. +class TestNode(NodeConnCB): + def __init__(self): + NodeConnCB.__init__(self) + self.connection = None + self.ping_counter = 1 + self.last_pong = msg_pong() + + def add_connection(self, conn): + self.connection = conn + + def on_inv(self, conn, message): + pass + + # Wrapper for the NodeConn's send_message function + def send_message(self, message): + self.connection.send_message(message) + + def on_pong(self, conn, message): + self.last_pong = message + + # Sync up with the node after delivery of a block + def sync_with_ping(self, timeout=30): + self.connection.send_message(msg_ping(nonce=self.ping_counter)) + received_pong = False + sleep_time = 0.05 + while not received_pong and timeout > 0: + time.sleep(sleep_time) + timeout -= sleep_time + with mininode_lock: + if self.last_pong.nonce == self.ping_counter: + received_pong = True + self.ping_counter += 1 + return received_pong + + +class VersionBitsWarningTest(BitcoinTestFramework): + def setup_chain(self): + initialize_chain_clean(self.options.tmpdir, 1) + + def setup_network(self): + self.nodes = [] + self.alert_filename = os.path.join(self.options.tmpdir, "alert.txt") + # Open and close to create zero-length file + with open(self.alert_filename, 'w') as f: + pass + self.node_options = ["-debug", "-logtimemicros=1", "-alertnotify=echo %s >> \"" + self.alert_filename + "\""] + self.nodes.append(start_node(0, self.options.tmpdir, self.node_options)) + + import re + self.vb_pattern = re.compile("^Warning.*versionbit") + + # Send numblocks blocks via peer with nVersionToUse set. + def send_blocks_with_version(self, peer, numblocks, nVersionToUse): + tip = self.nodes[0].getbestblockhash() + height = self.nodes[0].getblockcount() + block_time = self.nodes[0].getblockheader(tip)["time"]+1 + tip = int(tip, 16) + + for i in xrange(numblocks): + block = create_block(tip, create_coinbase(height+1), block_time) + block.nVersion = nVersionToUse + block.solve() + peer.send_message(msg_block(block)) + block_time += 1 + height += 1 + tip = block.sha256 + peer.sync_with_ping() + + def test_versionbits_in_alert_file(self): + with open(self.alert_filename, 'r') as f: + alert_text = f.read() + assert(self.vb_pattern.match(alert_text)) + + def run_test(self): + # Setup the p2p connection and start up the network thread. + test_node = TestNode() + + connections = [] + connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test_node)) + test_node.add_connection(connections[0]) + + NetworkThread().start() # Start up network handling in another thread + + # Test logic begins here + test_node.wait_for_verack() + + # 1. Have the node mine one period worth of blocks + self.nodes[0].generate(VB_PERIOD) + + # 2. Now build one period of blocks on the tip, with < VB_THRESHOLD + # blocks signaling some unknown bit. + nVersion = VB_TOP_BITS | (1<= VB_THRESHOLD blocks signaling + # some unknown bit + self.send_blocks_with_version(test_node, VB_THRESHOLD, nVersion) + self.nodes[0].generate(VB_PERIOD - VB_THRESHOLD) + # Might not get a versionbits-related alert yet, as we should + # have gotten a different alert due to more than 51/100 blocks + # being of unexpected version. + # Check that getinfo() shows some kind of error. + assert(len(self.nodes[0].getinfo()["errors"]) != 0) + + # Mine a period worth of expected blocks so the generic block-version warning + # is cleared, and restart the node. This should move the versionbit state + # to ACTIVE. + self.nodes[0].generate(VB_PERIOD) + stop_node(self.nodes[0], 0) + wait_bitcoinds() + # Empty out the alert file + with open(self.alert_filename, 'w') as f: + pass + self.nodes[0] = start_node(0, self.options.tmpdir, ["-debug", "-logtimemicros=1", "-alertnotify=echo %s >> \"" + self.alert_filename + "\""]) + + # Connecting one block should be enough to generate an error. + self.nodes[0].generate(1) + assert(len(self.nodes[0].getinfo()["errors"]) != 0) + stop_node(self.nodes[0], 0) + wait_bitcoinds() + self.test_versionbits_in_alert_file() + + # Test framework expects the node to still be running... + self.nodes[0] = start_node(0, self.options.tmpdir, ["-debug", "-logtimemicros=1", "-alertnotify=echo %s >> \"" + self.alert_filename + "\""]) + + +if __name__ == '__main__': + VersionBitsWarningTest().main() From fa4a52254178655f50e73b50153730a60ffafd32 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 6 Mar 2016 18:30:51 +0100 Subject: [PATCH 0016/1802] [qa] Add tests verifychain, lockunspent, getbalance, listsinceblock --- qa/rpc-tests/blockchain.py | 2 ++ qa/rpc-tests/mempool_limit.py | 1 - qa/rpc-tests/mempool_packages.py | 1 + qa/rpc-tests/wallet.py | 21 ++++++++++++++++++++- 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/qa/rpc-tests/blockchain.py b/qa/rpc-tests/blockchain.py index 7045ae435ceb4..272a5dc15482e 100755 --- a/qa/rpc-tests/blockchain.py +++ b/qa/rpc-tests/blockchain.py @@ -28,6 +28,7 @@ class BlockchainTest(BitcoinTestFramework): Test blockchain-related RPC calls: - gettxoutsetinfo + - verifychain """ @@ -44,6 +45,7 @@ def setup_network(self, split=False): def run_test(self): self._test_gettxoutsetinfo() self._test_getblockheader() + self.nodes[0].verifychain(4, 0) def _test_gettxoutsetinfo(self): node = self.nodes[0] diff --git a/qa/rpc-tests/mempool_limit.py b/qa/rpc-tests/mempool_limit.py index 7914ceea22bc4..c19a63c6996d2 100755 --- a/qa/rpc-tests/mempool_limit.py +++ b/qa/rpc-tests/mempool_limit.py @@ -38,7 +38,6 @@ def run_test(self): self.nodes[0].settxfee(0) # return to automatic fee selection txFS = self.nodes[0].signrawtransaction(txF['hex']) txid = self.nodes[0].sendrawtransaction(txFS['hex']) - self.nodes[0].lockunspent(True, [us0]) relayfee = self.nodes[0].getnetworkinfo()['relayfee'] base_fee = relayfee*100 diff --git a/qa/rpc-tests/mempool_packages.py b/qa/rpc-tests/mempool_packages.py index 6109cb026ceae..bc3f9e051cef1 100755 --- a/qa/rpc-tests/mempool_packages.py +++ b/qa/rpc-tests/mempool_packages.py @@ -7,6 +7,7 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * +from test_framework.mininode import COIN MAX_ANCESTORS = 25 MAX_DESCENDANTS = 25 diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py index 3cd495deb6092..e52d4e766801d 100755 --- a/qa/rpc-tests/wallet.py +++ b/qa/rpc-tests/wallet.py @@ -59,6 +59,15 @@ def run_test (self): self.nodes[0].generate(1) self.sync_all() + # Exercise locking of unspent outputs + unspent_0 = self.nodes[2].listunspent()[0] + unspent_0 = {"txid": unspent_0["txid"], "vout": unspent_0["vout"]} + self.nodes[2].lockunspent(False, [unspent_0]) + assert_raises(JSONRPCException, self.nodes[2].sendtoaddress, self.nodes[2].getnewaddress(), 20) + assert_equal([unspent_0], self.nodes[2].listlockunspent()) + self.nodes[2].lockunspent(True, [unspent_0]) + assert_equal(len(self.nodes[2].listlockunspent()), 0) + # Have node1 generate 100 blocks (so node0 can recover the fee) self.nodes[1].generate(100) self.sync_all() @@ -148,6 +157,10 @@ def run_test (self): assert(txid1 in self.nodes[3].getrawmempool()) + # Exercise balance rpcs + assert_equal(self.nodes[0].getwalletinfo()["unconfirmed_balance"], 1) + assert_equal(self.nodes[0].getunconfirmedbalance(), 1) + #check if we can list zero value tx as available coins #1. create rawtx #2. hex-changed one output to 0.0 @@ -251,7 +264,7 @@ def run_test (self): #check if wallet or blochchain maintenance changes the balance self.sync_all() - self.nodes[0].generate(1) + blocks = self.nodes[0].generate(2) self.sync_all() balance_nodes = [self.nodes[i].getbalance() for i in range(3)] @@ -269,6 +282,12 @@ def run_test (self): self.nodes = start_nodes(3, self.options.tmpdir, [[m]] * 3) assert_equal(balance_nodes, [self.nodes[i].getbalance() for i in range(3)]) + # Exercise listsinceblock with the last two blocks + coinbase_tx_1 = self.nodes[0].listsinceblock(blocks[0]) + assert_equal(coinbase_tx_1["lastblock"], blocks[1]) + assert_equal(len(coinbase_tx_1["transactions"]), 1) + assert_equal(coinbase_tx_1["transactions"][0]["blockhash"], blocks[1]) + assert_equal(len(self.nodes[0].listsinceblock(blocks[1])["transactions"]), 0) if __name__ == '__main__': WalletTest ().main () From fab688049402a111b32df6ca0765d3bcbb2d6ab5 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 17 Mar 2016 16:47:15 +0100 Subject: [PATCH 0017/1802] [qa] Add amount tests --- src/Makefile.test.include | 1 + src/test/amount_tests.cpp | 42 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 src/test/amount_tests.cpp diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 0c4e47a147020..000d2af61fc92 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -38,6 +38,7 @@ BITCOIN_TESTS =\ test/scriptnum10.h \ test/addrman_tests.cpp \ test/alert_tests.cpp \ + test/amount_tests.cpp \ test/allocator_tests.cpp \ test/base32_tests.cpp \ test/base58_tests.cpp \ diff --git a/src/test/amount_tests.cpp b/src/test/amount_tests.cpp new file mode 100644 index 0000000000000..59dab20633ced --- /dev/null +++ b/src/test/amount_tests.cpp @@ -0,0 +1,42 @@ +// Copyright (c) 2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "amount.h" +#include "test/test_bitcoin.h" + +#include + +BOOST_FIXTURE_TEST_SUITE(amount_tests, BasicTestingSetup) + +BOOST_AUTO_TEST_CASE(GetFeeTest) +{ + CFeeRate feeRate; + + feeRate = CFeeRate(0); + // Must always return 0 + BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0); + BOOST_CHECK_EQUAL(feeRate.GetFee(1e5), 0); + + feeRate = CFeeRate(1000); + // Must always just return the arg + BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0); + BOOST_CHECK_EQUAL(feeRate.GetFee(1), 1); + BOOST_CHECK_EQUAL(feeRate.GetFee(121), 121); + BOOST_CHECK_EQUAL(feeRate.GetFee(999), 999); + BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), 1e3); + BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), 9e3); + + feeRate = CFeeRate(123); + // Truncates the result, if not integer + BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0); + BOOST_CHECK_EQUAL(feeRate.GetFee(8), 1); // Special case: returns 1 instead of 0 + BOOST_CHECK_EQUAL(feeRate.GetFee(9), 1); + BOOST_CHECK_EQUAL(feeRate.GetFee(121), 14); + BOOST_CHECK_EQUAL(feeRate.GetFee(122), 15); + BOOST_CHECK_EQUAL(feeRate.GetFee(999), 122); + BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), 123); + BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), 1107); +} + +BOOST_AUTO_TEST_SUITE_END() From faf756ae4ed63a31f073c09f3d0f25c13971cb98 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 9 Mar 2016 12:54:55 +0100 Subject: [PATCH 0018/1802] [amount] Make GetFee() monotonic This reverts the hard-to-read and buggy code introduced in d88af560111863c3e9c1ae855dcc287f04dffb02 and adds documentation --- src/amount.cpp | 6 +++--- src/amount.h | 12 ++++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/amount.cpp b/src/amount.cpp index a3abd8cd835fb..d03ed5cfadb4c 100644 --- a/src/amount.cpp +++ b/src/amount.cpp @@ -19,10 +19,10 @@ CFeeRate::CFeeRate(const CAmount& nFeePaid, size_t nSize) CAmount CFeeRate::GetFee(size_t nSize) const { - CAmount nFee = nSatoshisPerK*nSize / 1000; + CAmount nFee = nSatoshisPerK * nSize / 1000; - if (nFee == 0 && nSatoshisPerK > 0) - nFee = nSatoshisPerK; + if (nFee == 0 && nSize != 0 && nSatoshisPerK != 0) + nFee = CAmount(1); return nFee; } diff --git a/src/amount.h b/src/amount.h index a48b17d514277..9aba6525c7f2b 100644 --- a/src/amount.h +++ b/src/amount.h @@ -42,10 +42,14 @@ class CFeeRate explicit CFeeRate(const CAmount& _nSatoshisPerK): nSatoshisPerK(_nSatoshisPerK) { } CFeeRate(const CAmount& nFeePaid, size_t nSize); CFeeRate(const CFeeRate& other) { nSatoshisPerK = other.nSatoshisPerK; } - - CAmount GetFee(size_t size) const; // unit returned is satoshis - CAmount GetFeePerK() const { return GetFee(1000); } // satoshis-per-1000-bytes - + /** + * Return the fee in satoshis for the given size in bytes. + */ + CAmount GetFee(size_t size) const; + /** + * Return the fee in satoshis for a size of 1000 bytes + */ + CAmount GetFeePerK() const { return GetFee(1000); } 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; } friend bool operator==(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK == b.nSatoshisPerK; } From e38781da40f862d4fa45bd23923d8665709e6f7a Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Thu, 17 Mar 2016 20:23:29 -0400 Subject: [PATCH 0019/1802] Tests: fix missing import in mempool_packages --- qa/rpc-tests/mempool_packages.py | 1 + 1 file changed, 1 insertion(+) diff --git a/qa/rpc-tests/mempool_packages.py b/qa/rpc-tests/mempool_packages.py index 6109cb026ceae..bc3f9e051cef1 100755 --- a/qa/rpc-tests/mempool_packages.py +++ b/qa/rpc-tests/mempool_packages.py @@ -7,6 +7,7 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * +from test_framework.mininode import COIN MAX_ANCESTORS = 25 MAX_DESCENDANTS = 25 From 5fd2318d2dbb870939e101ce45b192d00fadacc5 Mon Sep 17 00:00:00 2001 From: fanquake Date: Fri, 18 Mar 2016 09:03:58 +0800 Subject: [PATCH 0020/1802] [Depends] Miniupnpc 1.9.20160209 2016/01/24: Change miniwget to return HTTP status code Increments API_VERSION to 16 2016/01/22: Improve UPNPIGD_IsConnected() to check if WAN address is not private. Parse HTTP response status line in miniwget.c --- depends/packages/miniupnpc.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/depends/packages/miniupnpc.mk b/depends/packages/miniupnpc.mk index 3d5a6df974bf1..45fa03631f89d 100644 --- a/depends/packages/miniupnpc.mk +++ b/depends/packages/miniupnpc.mk @@ -1,8 +1,8 @@ package=miniupnpc -$(package)_version=1.9.20151026 +$(package)_version=1.9.20160209 $(package)_download_path=http://miniupnp.free.fr/files $(package)_file_name=$(package)-$($(package)_version).tar.gz -$(package)_sha256_hash=f3cf9a5a31588a917d4d9237e5bc50f84d00c5aa48e27ed50d9b88dfa6a25d47 +$(package)_sha256_hash=572171eacc1d72537ce47b6f4571260757ab7bcfdaf54c3a55c7f88594d94b6f define $(package)_set_vars $(package)_build_opts=CC="$($(package)_cc)" From c85f4757b856c617684a8fef85c95ca9973ae91c Mon Sep 17 00:00:00 2001 From: fanquake Date: Fri, 18 Mar 2016 09:06:08 +0800 Subject: [PATCH 0021/1802] [Depends] Latest config.guess & config.sub --- depends/config.guess | 90 +++++++++++++++++++++++--------------------- depends/config.sub | 12 +++--- 2 files changed, 53 insertions(+), 49 deletions(-) diff --git a/depends/config.guess b/depends/config.guess index fba6e87a0f87a..373a659a06760 100755 --- a/depends/config.guess +++ b/depends/config.guess @@ -1,8 +1,8 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2015 Free Software Foundation, Inc. +# Copyright 1992-2016 Free Software Foundation, Inc. -timestamp='2015-11-19' +timestamp='2016-02-11' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -27,7 +27,7 @@ timestamp='2015-11-19' # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess # # Please send patches to . @@ -50,7 +50,7 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2015 Free Software Foundation, Inc. +Copyright 1992-2016 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -237,6 +237,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; + *:LibertyBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE} + exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; @@ -268,42 +272,42 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "EV4.5 (21064)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "LCA4 (21066/21068)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "EV5 (21164)") - UNAME_MACHINE="alphaev5" ;; + UNAME_MACHINE=alphaev5 ;; "EV5.6 (21164A)") - UNAME_MACHINE="alphaev56" ;; + UNAME_MACHINE=alphaev56 ;; "EV5.6 (21164PC)") - UNAME_MACHINE="alphapca56" ;; + UNAME_MACHINE=alphapca56 ;; "EV5.7 (21164PC)") - UNAME_MACHINE="alphapca57" ;; + UNAME_MACHINE=alphapca57 ;; "EV6 (21264)") - UNAME_MACHINE="alphaev6" ;; + UNAME_MACHINE=alphaev6 ;; "EV6.7 (21264A)") - UNAME_MACHINE="alphaev67" ;; + UNAME_MACHINE=alphaev67 ;; "EV6.8CB (21264C)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.8AL (21264B)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.8CX (21264D)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.9A (21264/EV69A)") - UNAME_MACHINE="alphaev69" ;; + UNAME_MACHINE=alphaev69 ;; "EV7 (21364)") - UNAME_MACHINE="alphaev7" ;; + UNAME_MACHINE=alphaev7 ;; "EV7.9 (21364A)") - UNAME_MACHINE="alphaev79" ;; + UNAME_MACHINE=alphaev79 ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 @@ -376,16 +380,16 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build - SUN_ARCH="i386" + SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then - SUN_ARCH="x86_64" + SUN_ARCH=x86_64 fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` @@ -410,7 +414,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} @@ -635,13 +639,13 @@ EOF sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 + 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + 32) HP_ARCH=hppa2.0n ;; + 64) HP_ARCH=hppa2.0w ;; + '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi @@ -684,7 +688,7 @@ EOF test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac - if [ ${HP_ARCH} = "hppa2.0w" ] + if [ ${HP_ARCH} = hppa2.0w ] then eval $set_cc_for_build @@ -700,9 +704,9 @@ EOF if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then - HP_ARCH="hppa2.0w" + HP_ARCH=hppa2.0w else - HP_ARCH="hppa64" + HP_ARCH=hppa64 fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} @@ -807,14 +811,14 @@ EOF echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) @@ -919,7 +923,7 @@ EOF EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC="gnulibc1" ; fi + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arc:Linux:*:* | arceb:Linux:*:*) @@ -1285,7 +1289,7 @@ EOF UNAME_PROCESSOR=powerpc fi if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null @@ -1309,7 +1313,7 @@ EOF exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = "x86"; then + if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi @@ -1340,7 +1344,7 @@ EOF # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. - if test "$cputype" = "386"; then + if test "$cputype" = 386; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" @@ -1394,7 +1398,7 @@ EOF echo ${UNAME_MACHINE}-unknown-esx exit ;; amd64:Isilon\ OneFS:*:*) - echo x86_64-unknown-onefs + echo x86_64-unknown-onefs exit ;; esac @@ -1405,9 +1409,9 @@ This script, last modified $timestamp, has failed to recognize the operating system you are using. It is advised that you download the most up to date version of the config scripts from - http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess and - http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub If the version you run ($0) is already up to date, please send the following data and any information you think might be diff --git a/depends/config.sub b/depends/config.sub index ea8747d30fffb..6223dde931918 100755 --- a/depends/config.sub +++ b/depends/config.sub @@ -1,8 +1,8 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright 1992-2015 Free Software Foundation, Inc. +# Copyright 1992-2016 Free Software Foundation, Inc. -timestamp='2015-11-22' +timestamp='2016-01-01' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -33,7 +33,7 @@ timestamp='2015-11-22' # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases @@ -67,7 +67,7 @@ Report bugs and patches to ." version="\ GNU config.sub ($timestamp) -Copyright 1992-2015 Free Software Foundation, Inc. +Copyright 1992-2016 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -520,7 +520,7 @@ case $basic_machine in basic_machine=i386-pc os=-aros ;; - asmjs) + asmjs) basic_machine=asmjs-unknown ;; aux) @@ -1382,7 +1382,7 @@ case $os in | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -bitrig* | -openbsd* | -solidbsd* \ + | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ From 0f176927f88084f2f1ce329656878d122fb64623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Fri, 18 Mar 2016 04:14:19 +0000 Subject: [PATCH 0022/1802] Improve COutPoint less operator --- src/primitives/transaction.h | 3 ++- src/uint256.h | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 07ae39e0b444f..e124dca365932 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -34,7 +34,8 @@ class COutPoint friend bool operator<(const COutPoint& a, const COutPoint& b) { - return (a.hash < b.hash || (a.hash == b.hash && a.n < b.n)); + int cmp = a.hash.Compare(b.hash); + return cmp < 0 || (cmp == 0 && a.n < b.n); } friend bool operator==(const COutPoint& a, const COutPoint& b) diff --git a/src/uint256.h b/src/uint256.h index 4495000f2fa9b..bcdb6dd7c2958 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -42,9 +42,11 @@ class base_blob memset(data, 0, sizeof(data)); } - friend inline bool operator==(const base_blob& a, const base_blob& b) { return memcmp(a.data, b.data, sizeof(a.data)) == 0; } - friend inline bool operator!=(const base_blob& a, const base_blob& b) { return memcmp(a.data, b.data, sizeof(a.data)) != 0; } - friend inline bool operator<(const base_blob& a, const base_blob& b) { return memcmp(a.data, b.data, sizeof(a.data)) < 0; } + inline int Compare(const base_blob& other) const { return memcmp(data, other.data, sizeof(data)); } + + friend inline bool operator==(const base_blob& a, const base_blob& b) { return a.Compare(b) == 0; } + friend inline bool operator!=(const base_blob& a, const base_blob& b) { return a.Compare(b) != 0; } + friend inline bool operator<(const base_blob& a, const base_blob& b) { return a.Compare(b) < 0; } std::string GetHex() const; void SetHex(const char* psz); From 65751a3cf2421a9419172949cad9dc49b7383551 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 20 Feb 2016 23:37:13 +0100 Subject: [PATCH 0023/1802] Add CHECKSEQUENCEVERIFY softfork through BIP9 --- src/chainparams.cpp | 17 ++++++++++++++++- src/consensus/params.h | 1 + src/main.cpp | 5 +++++ src/rpc/blockchain.cpp | 1 + 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 35e090a0b3b3e..f48937d67deee 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -86,7 +86,13 @@ class CMainParams : public CChainParams { consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 1199145601; // January 1, 2008 consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 1230767999; // December 31, 2008 - /** + + // Deployment of BIP68, BIP112, and BIP113. + consensus.vDeployments[Consensus::DEPLOYMENT_CSV].bit = 0; + consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 1462060800; // May 1st, 2016 + consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 1493596800; // May 1st, 2017 + + /** * The message start string is designed to be unlikely to occur in normal data. * The characters are rarely used upper ASCII, not valid as UTF-8, and produce * a large 32-bit integer with any alignment. @@ -172,6 +178,12 @@ class CTestNetParams : public CChainParams { consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 1199145601; // January 1, 2008 consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 1230767999; // December 31, 2008 + + // Deployment of BIP68, BIP112, and BIP113. + consensus.vDeployments[Consensus::DEPLOYMENT_CSV].bit = 0; + consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 1456790400; // March 1st, 2016 + consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 1493596800; // May 1st, 2017 + pchMessageStart[0] = 0x0b; pchMessageStart[1] = 0x11; pchMessageStart[2] = 0x09; @@ -240,6 +252,9 @@ class CRegTestParams : public CChainParams { consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 0; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 999999999999ULL; + consensus.vDeployments[Consensus::DEPLOYMENT_CSV].bit = 0; + consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 0; + consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 999999999999ULL; pchMessageStart[0] = 0xfa; pchMessageStart[1] = 0xbf; diff --git a/src/consensus/params.h b/src/consensus/params.h index 7c3a8e84c3d35..4f3480b89ba69 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -15,6 +15,7 @@ namespace Consensus { enum DeploymentPos { DEPLOYMENT_TESTDUMMY, + DEPLOYMENT_CSV, // Deployment of BIP68, BIP112, and BIP113. MAX_VERSION_BITS_DEPLOYMENTS }; diff --git a/src/main.cpp b/src/main.cpp index 1bc88326b6fc7..cfa69817b6a2b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2262,6 +2262,11 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin flags |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY; } + // Start enforcing CHECKSEQUENCEVERIFY using versionbits logic. + if (VersionBitsState(pindex->pprev, chainparams.GetConsensus(), Consensus::DEPLOYMENT_CSV, versionbitscache) == THRESHOLD_ACTIVE) { + flags |= SCRIPT_VERIFY_CHECKSEQUENCEVERIFY; + } + int64_t nTime2 = GetTimeMicros(); nTimeForks += nTime2 - nTime1; LogPrint("bench", " - Fork checks: %.2fms [%.2fs]\n", 0.001 * (nTime2 - nTime1), nTimeForks * 0.000001); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index a110dff0d1d4a..f5d75c20b367f 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -681,6 +681,7 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams)); softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams)); softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams)); + bip9_softforks.push_back(BIP9SoftForkDesc("csv", consensusParams, Consensus::DEPLOYMENT_CSV)); obj.push_back(Pair("softforks", softforks)); obj.push_back(Pair("bip9_softforks", bip9_softforks)); From 478fba6d5213a3f1ffeca5feeacf28aaf6844fd6 Mon Sep 17 00:00:00 2001 From: BtcDrak Date: Tue, 16 Feb 2016 16:33:31 +0000 Subject: [PATCH 0024/1802] Soft fork logic for BIP113 --- src/main.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index cfa69817b6a2b..857bf218ba799 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3276,12 +3276,18 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn const int nHeight = pindexPrev == NULL ? 0 : pindexPrev->nHeight + 1; const Consensus::Params& consensusParams = Params().GetConsensus(); + // Start enforcing BIP113 (Median Time Past) using versionbits logic. + int nLockTimeFlags = 0; + if (VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_CSV, versionbitscache) == THRESHOLD_ACTIVE) { + nLockTimeFlags |= LOCKTIME_MEDIAN_TIME_PAST; + } + + int64_t nLockTimeCutoff = (nLockTimeFlags & LOCKTIME_MEDIAN_TIME_PAST) + ? pindexPrev->GetMedianTimePast() + : block.GetBlockTime(); + // Check that all transactions are finalized BOOST_FOREACH(const CTransaction& tx, block.vtx) { - int nLockTimeFlags = 0; - int64_t nLockTimeCutoff = (nLockTimeFlags & LOCKTIME_MEDIAN_TIME_PAST) - ? pindexPrev->GetMedianTimePast() - : block.GetBlockTime(); if (!IsFinalTx(tx, nHeight, nLockTimeCutoff)) { return state.DoS(10, false, REJECT_INVALID, "bad-txns-nonfinal", false, "non-final transaction"); } From 02c243580295a7f1c0298fcd9afc2e76b607e724 Mon Sep 17 00:00:00 2001 From: BtcDrak Date: Tue, 16 Feb 2016 16:37:43 +0000 Subject: [PATCH 0025/1802] Soft fork logic for BIP68 --- src/main.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 857bf218ba799..f74cb30574ce3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2262,9 +2262,11 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin flags |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY; } - // Start enforcing CHECKSEQUENCEVERIFY using versionbits logic. + // Start enforcing BIP68 (sequence locks) and BIP112 (CHECKSEQUENCEVERIFY) using versionbits logic. + int nLockTimeFlags = 0; if (VersionBitsState(pindex->pprev, chainparams.GetConsensus(), Consensus::DEPLOYMENT_CSV, versionbitscache) == THRESHOLD_ACTIVE) { flags |= SCRIPT_VERIFY_CHECKSEQUENCEVERIFY; + nLockTimeFlags |= LOCKTIME_VERIFY_SEQUENCE; } int64_t nTime2 = GetTimeMicros(); nTimeForks += nTime2 - nTime1; @@ -2275,7 +2277,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin CCheckQueueControl control(fScriptChecks && nScriptCheckThreads ? &scriptcheckqueue : NULL); std::vector prevheights; - int nLockTimeFlags = 0; CAmount nFees = 0; int nInputs = 0; unsigned int nSigOps = 0; From 12c89c918534f8e615e80381b692d89d6b09d174 Mon Sep 17 00:00:00 2001 From: BtcDrak Date: Fri, 19 Feb 2016 19:52:31 +0000 Subject: [PATCH 0026/1802] Policy: allow transaction version 2 relay policy. This commit introduces a way to gracefully bump the default transaction version in a two step process. --- src/policy/policy.cpp | 2 +- src/primitives/transaction.h | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index 332abc430e116..e3ed7be0008ee 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -55,7 +55,7 @@ bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType) bool IsStandardTx(const CTransaction& tx, std::string& reason) { - if (tx.nVersion > CTransaction::CURRENT_VERSION || tx.nVersion < 1) { + if (tx.nVersion > CTransaction::MAX_STANDARD_VERSION || tx.nVersion < 1) { reason = "version"; return false; } diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 07ae39e0b444f..9f7d6f394390b 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -206,8 +206,15 @@ class CTransaction void UpdateHash() const; public: + // Default transaction version. static const int32_t CURRENT_VERSION=1; + // Changing the default transaction version requires a two step process: first + // adapting relay policy by bumping MAX_STANDARD_VERSION, and then later date + // bumping the default CURRENT_VERSION at which point both CURRENT_VERSION and + // MAX_STANDARD_VERSION will be equal. + static const int32_t MAX_STANDARD_VERSION=2; + // The local variables are made const to prevent unintended modification // without updating the cached hash value. However, CTransaction is not // actually immutable; deserialization and assignment are implemented, From 19d73d540c8de4a73b5b2a05bebd762e74890a20 Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Thu, 10 Mar 2016 18:36:55 -0500 Subject: [PATCH 0027/1802] Add RPC test for BIP 68/112/113 soft fork. This RPC test will test both the activation mechanism of the first versionbits soft fork as well as testing many code branches of the consensus logic for BIP's 68, 112, and 113. --- qa/pull-tester/rpc-tests.py | 1 + qa/rpc-tests/bip68-112-113-p2p.py | 547 ++++++++++++++++++++++++++++++ 2 files changed, 548 insertions(+) create mode 100755 qa/rpc-tests/bip68-112-113-p2p.py diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index f15eaacbdaed8..cbc10abd215e0 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -83,6 +83,7 @@ #Tests testScripts = [ + 'bip68-112-113-p2p.py', 'wallet.py', 'listtransactions.py', 'receivedby.py', diff --git a/qa/rpc-tests/bip68-112-113-p2p.py b/qa/rpc-tests/bip68-112-113-p2p.py new file mode 100755 index 0000000000000..c226f4dad4976 --- /dev/null +++ b/qa/rpc-tests/bip68-112-113-p2p.py @@ -0,0 +1,547 @@ +#!/usr/bin/env python2 +# Copyright (c) 2015 The Bitcoin Core developers +# Distributed under the MIT/X11 software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# + +from test_framework.test_framework import ComparisonTestFramework +from test_framework.util import * +from test_framework.mininode import ToHex, CTransaction, NetworkThread +from test_framework.blocktools import create_coinbase, create_block +from test_framework.comptool import TestInstance, TestManager +from test_framework.script import * +from binascii import unhexlify +import cStringIO +import time + +''' +This test is meant to exercise activation of the first version bits soft fork +This soft fork will activate the following BIPS: +BIP 68 - nSequence relative lock times +BIP 112 - CHECKSEQUENCEVERIFY +BIP 113 - MedianTimePast semantics for nLockTime + +regtest lock-in with 108/144 block signalling +activation after a further 144 blocks + +mine 82 blocks whose coinbases will be used to generate inputs for our tests +mine 61 blocks to transition from DEFINED to STARTED +mine 144 blocks only 100 of which are signaling readiness in order to fail to change state this period +mine 144 blocks with 108 signaling and verify STARTED->LOCKED_IN +mine 140 blocks and seed block chain with the 82 inputs will use for our tests at height 572 +mine 3 blocks and verify still at LOCKED_IN and test that enforcement has not triggered +mine 1 block and test that enforcement has triggered (which triggers ACTIVE) +Test BIP 113 is enforced +Mine 4 blocks so next height is 580 and test BIP 68 is enforced for time and height +Mine 1 block so next height is 581 and test BIP 68 now passes time but not height +Mine 1 block so next height is 582 and test BIP 68 now passes time and height +Test that BIP 112 is enforced + +Various transactions will be used to test that the BIPs rules are not enforced before the soft fork activates +And that after the soft fork activates transactions pass and fail as they should according to the rules. +For each BIP, transactions of versions 1 and 2 will be tested. +---------------- +BIP 113: +bip113tx - modify the nLocktime variable + +BIP 68: +bip68txs - 16 txs with nSequence relative locktime of 10 with various bits set as per the relative_locktimes below + +BIP 112: +bip112txs_vary_nSequence - 16 txs with nSequence relative_locktimes of 10 evaluated against 10 OP_CSV OP_DROP +bip112txs_vary_nSequence_9 - 16 txs with nSequence relative_locktimes of 9 evaluated against 10 OP_CSV OP_DROP +bip112txs_vary_OP_CSV - 16 txs with nSequence = 10 evaluated against varying {relative_locktimes of 10} OP_CSV OP_DROP +bip112txs_vary_OP_CSV_9 - 16 txs with nSequence = 9 evaluated against varying {relative_locktimes of 10} OP_CSV OP_DROP +bip112tx_special - test negative argument to OP_CSV +''' + +base_relative_locktime = 10 +seq_disable_flag = 1<<31 +seq_random_high_bit = 1<<25 +seq_type_flag = 1<<22 +seq_random_low_bit = 1<<18 + +# b31,b25,b22,b18 represent the 31st, 25th, 22nd and 18th bits respectively in the nSequence field +# relative_locktimes[b31][b25][b22][b18] is a base_relative_locktime with the indicated bits set if their indices are 1 +relative_locktimes = [] +for b31 in xrange(2): + b25times = [] + for b25 in xrange(2): + b22times = [] + for b22 in xrange(2): + b18times = [] + for b18 in xrange(2): + rlt = base_relative_locktime + if (b31): + rlt = rlt | seq_disable_flag + if (b25): + rlt = rlt | seq_random_high_bit + if (b22): + rlt = rlt | seq_type_flag + if (b18): + rlt = rlt | seq_random_low_bit + b18times.append(rlt) + b22times.append(b18times) + b25times.append(b22times) + relative_locktimes.append(b25times) + +def all_rlt_txs(txarray): + txs = [] + for b31 in xrange(2): + for b25 in xrange(2): + for b22 in xrange(2): + for b18 in xrange(2): + txs.append(txarray[b31][b25][b22][b18]) + return txs + +class BIP68_112_113Test(ComparisonTestFramework): + def __init__(self): + self.num_nodes = 1 + + def setup_network(self): + # Must set the blockversion for this test + self.nodes = start_nodes(1, self.options.tmpdir, + extra_args=[['-debug', '-whitelist=127.0.0.1', '-blockversion=4']], + binary=[self.options.testbinary]) + + def run_test(self): + test = TestManager(self, self.options.tmpdir) + test.add_all_connections(self.nodes) + NetworkThread().start() # Start up network handling in another thread + test.run() + + def send_generic_input_tx(self, node, coinbases): + amount = Decimal("49.99") + return node.sendrawtransaction(ToHex(self.sign_transaction(node, self.create_transaction(node, node.getblock(coinbases.pop())['tx'][0], self.nodeaddress, amount)))) + + def create_transaction(self, node, txid, to_address, amount): + inputs = [{ "txid" : txid, "vout" : 0}] + outputs = { to_address : amount } + rawtx = node.createrawtransaction(inputs, outputs) + tx = CTransaction() + f = cStringIO.StringIO(unhexlify(rawtx)) + tx.deserialize(f) + return tx + + def sign_transaction(self, node, unsignedtx): + rawtx = ToHex(unsignedtx) + signresult = node.signrawtransaction(rawtx) + tx = CTransaction() + f = cStringIO.StringIO(unhexlify(signresult['hex'])) + tx.deserialize(f) + return tx + + def generate_blocks(self, number, version, test_blocks = []): + for i in xrange(number): + block = self.create_test_block([], version) + test_blocks.append([block, True]) + self.last_block_time += 600 + self.tip = block.sha256 + self.tipheight += 1 + return test_blocks + + def create_test_block(self, txs, version = 536870912): + block = create_block(self.tip, create_coinbase(self.tipheight + 1), self.last_block_time + 600) + block.nVersion = version + block.vtx.extend(txs) + block.hashMerkleRoot = block.calc_merkle_root() + block.rehash() + block.solve() + return block + + def get_bip9_status(self, key): + info = self.nodes[0].getblockchaininfo() + for row in info['bip9_softforks']: + if row['id'] == key: + return row + raise IndexError ('key:"%s" not found' % key) + + def create_bip68txs(self, bip68inputs, txversion, locktime_delta = 0): + txs = [] + assert(len(bip68inputs) >= 16) + i = 0 + for b31 in xrange(2): + b25txs = [] + for b25 in xrange(2): + b22txs = [] + for b22 in xrange(2): + b18txs = [] + for b18 in xrange(2): + tx = self.create_transaction(self.nodes[0], bip68inputs[i], self.nodeaddress, Decimal("49.98")) + i += 1 + tx.nVersion = txversion + tx.vin[0].nSequence = relative_locktimes[b31][b25][b22][b18] + locktime_delta + b18txs.append(self.sign_transaction(self.nodes[0], tx)) + b22txs.append(b18txs) + b25txs.append(b22txs) + txs.append(b25txs) + return txs + + def create_bip112special(self, input, txversion): + tx = self.create_transaction(self.nodes[0], input, self.nodeaddress, Decimal("49.98")) + tx.nVersion = txversion + signtx = self.sign_transaction(self.nodes[0], tx) + signtx.vin[0].scriptSig = CScript([-1, OP_NOP3, OP_DROP] + list(CScript(signtx.vin[0].scriptSig))) + return signtx + + def create_bip112txs(self, bip112inputs, varyOP_CSV, txversion, locktime_delta = 0): + txs = [] + assert(len(bip112inputs) >= 16) + i = 0 + for b31 in xrange(2): + b25txs = [] + for b25 in xrange(2): + b22txs = [] + for b22 in xrange(2): + b18txs = [] + for b18 in xrange(2): + tx = self.create_transaction(self.nodes[0], bip112inputs[i], self.nodeaddress, Decimal("49.98")) + i += 1 + if (varyOP_CSV): # if varying OP_CSV, nSequence is fixed + tx.vin[0].nSequence = base_relative_locktime + locktime_delta + else: # vary nSequence instead, OP_CSV is fixed + tx.vin[0].nSequence = relative_locktimes[b31][b25][b22][b18] + locktime_delta + tx.nVersion = txversion + signtx = self.sign_transaction(self.nodes[0], tx) + if (varyOP_CSV): + signtx.vin[0].scriptSig = CScript([relative_locktimes[b31][b25][b22][b18], OP_NOP3, OP_DROP] + list(CScript(signtx.vin[0].scriptSig))) + else: + signtx.vin[0].scriptSig = CScript([base_relative_locktime, OP_NOP3, OP_DROP] + list(CScript(signtx.vin[0].scriptSig))) + b18txs.append(signtx) + b22txs.append(b18txs) + b25txs.append(b22txs) + txs.append(b25txs) + return txs + + def get_tests(self): + long_past_time = int(time.time()) - 600 * 1000 # enough to build up to 1000 blocks 10 minutes apart without worrying about getting into the future + self.nodes[0].setmocktime(long_past_time - 100) # enough so that the generated blocks will still all be before long_past_time + self.coinbase_blocks = self.nodes[0].generate(1 + 16 + 2*32 + 1) # 82 blocks generated for inputs + self.nodes[0].setmocktime(0) # set time back to present so yielded blocks aren't in the future as we advance last_block_time + self.tipheight = 82 # height of the next block to build + self.last_block_time = long_past_time + self.tip = int ("0x" + self.nodes[0].getbestblockhash() + "L", 0) + self.nodeaddress = self.nodes[0].getnewaddress() + + assert_equal(self.get_bip9_status('csv')['status'], 'defined') + test_blocks = self.generate_blocks(61, 4) + yield TestInstance(test_blocks, sync_every_block=False) # 1 + # Advanced from DEFINED to STARTED, height = 143 + assert_equal(self.get_bip9_status('csv')['status'], 'started') + + # Fail to achieve LOCKED_IN 100 out of 144 signal bit 0 + # using a variety of bits to simulate multiple parallel softforks + test_blocks = self.generate_blocks(50, 536870913) # 0x20000001 (signalling ready) + test_blocks = self.generate_blocks(20, 4, test_blocks) # 0x00000004 (signalling not) + test_blocks = self.generate_blocks(50, 536871169, test_blocks) # 0x20000101 (signalling ready) + test_blocks = self.generate_blocks(24, 536936448, test_blocks) # 0x20010000 (signalling not) + yield TestInstance(test_blocks, sync_every_block=False) # 2 + # Failed to advance past STARTED, height = 287 + assert_equal(self.get_bip9_status('csv')['status'], 'started') + + # 108 out of 144 signal bit 0 to achieve lock-in + # using a variety of bits to simulate multiple parallel softforks + test_blocks = self.generate_blocks(58, 536870913) # 0x20000001 (signalling ready) + test_blocks = self.generate_blocks(26, 4, test_blocks) # 0x00000004 (signalling not) + test_blocks = self.generate_blocks(50, 536871169, test_blocks) # 0x20000101 (signalling ready) + test_blocks = self.generate_blocks(10, 536936448, test_blocks) # 0x20010000 (signalling not) + yield TestInstance(test_blocks, sync_every_block=False) # 3 + # Advanced from STARTED to LOCKED_IN, height = 431 + assert_equal(self.get_bip9_status('csv')['status'], 'locked_in') + + # 140 more version 4 blocks + test_blocks = self.generate_blocks(140, 4) + yield TestInstance(test_blocks, sync_every_block=False) # 4 + + ### Inputs at height = 572 + # Put inputs for all tests in the chain at height 572 (tip now = 571) (time increases by 600s per block) + # Note we reuse inputs for v1 and v2 txs so must test these separately + # 16 normal inputs + bip68inputs = [] + for i in xrange(16): + bip68inputs.append(self.send_generic_input_tx(self.nodes[0], self.coinbase_blocks)) + # 2 sets of 16 inputs with 10 OP_CSV OP_DROP (actually will be prepended to spending scriptSig) + bip112basicinputs = [] + for j in xrange(2): + inputs = [] + for i in xrange(16): + inputs.append(self.send_generic_input_tx(self.nodes[0], self.coinbase_blocks)) + bip112basicinputs.append(inputs) + # 2 sets of 16 varied inputs with (relative_lock_time) OP_CSV OP_DROP (actually will be prepended to spending scriptSig) + bip112diverseinputs = [] + for j in xrange(2): + inputs = [] + for i in xrange(16): + inputs.append(self.send_generic_input_tx(self.nodes[0], self.coinbase_blocks)) + bip112diverseinputs.append(inputs) + # 1 special input with -1 OP_CSV OP_DROP (actually will be prepended to spending scriptSig) + bip112specialinput = self.send_generic_input_tx(self.nodes[0], self.coinbase_blocks) + # 1 normal input + bip113input = self.send_generic_input_tx(self.nodes[0], self.coinbase_blocks) + + self.nodes[0].setmocktime(self.last_block_time + 600) + inputblockhash = self.nodes[0].generate(1)[0] # 1 block generated for inputs to be in chain at height 572 + self.nodes[0].setmocktime(0) + self.tip = int("0x" + inputblockhash + "L", 0) + self.tipheight += 1 + self.last_block_time += 600 + assert_equal(len(self.nodes[0].getblock(inputblockhash,True)["tx"]), 82+1) + + # 2 more version 4 blocks + test_blocks = self.generate_blocks(2, 4) + yield TestInstance(test_blocks, sync_every_block=False) # 5 + # Not yet advanced to ACTIVE, height = 574 (will activate for block 576, not 575) + assert_equal(self.get_bip9_status('csv')['status'], 'locked_in') + + # Test both version 1 and version 2 transactions for all tests + # BIP113 test transaction will be modified before each use to put in appropriate block time + bip113tx_v1 = self.create_transaction(self.nodes[0], bip113input, self.nodeaddress, Decimal("49.98")) + bip113tx_v1.vin[0].nSequence = 0xFFFFFFFE + bip113tx_v2 = self.create_transaction(self.nodes[0], bip113input, self.nodeaddress, Decimal("49.98")) + bip113tx_v2.vin[0].nSequence = 0xFFFFFFFE + bip113tx_v2.nVersion = 2 + + # For BIP68 test all 16 relative sequence locktimes + bip68txs_v1 = self.create_bip68txs(bip68inputs, 1) + bip68txs_v2 = self.create_bip68txs(bip68inputs, 2) + + # For BIP112 test: + # 16 relative sequence locktimes of 10 against 10 OP_CSV OP_DROP inputs + bip112txs_vary_nSequence_v1 = self.create_bip112txs(bip112basicinputs[0], False, 1) + bip112txs_vary_nSequence_v2 = self.create_bip112txs(bip112basicinputs[0], False, 2) + # 16 relative sequence locktimes of 9 against 10 OP_CSV OP_DROP inputs + bip112txs_vary_nSequence_9_v1 = self.create_bip112txs(bip112basicinputs[1], False, 1, -1) + bip112txs_vary_nSequence_9_v2 = self.create_bip112txs(bip112basicinputs[1], False, 2, -1) + # sequence lock time of 10 against 16 (relative_lock_time) OP_CSV OP_DROP inputs + bip112txs_vary_OP_CSV_v1 = self.create_bip112txs(bip112diverseinputs[0], True, 1) + bip112txs_vary_OP_CSV_v2 = self.create_bip112txs(bip112diverseinputs[0], True, 2) + # sequence lock time of 9 against 16 (relative_lock_time) OP_CSV OP_DROP inputs + bip112txs_vary_OP_CSV_9_v1 = self.create_bip112txs(bip112diverseinputs[1], True, 1, -1) + bip112txs_vary_OP_CSV_9_v2 = self.create_bip112txs(bip112diverseinputs[1], True, 2, -1) + # -1 OP_CSV OP_DROP input + bip112tx_special_v1 = self.create_bip112special(bip112specialinput, 1) + bip112tx_special_v2 = self.create_bip112special(bip112specialinput, 2) + + + ### TESTING ### + ################################## + ### Before Soft Forks Activate ### + ################################## + # All txs should pass + ### Version 1 txs ### + success_txs = [] + # add BIP113 tx and -1 CSV tx + bip113tx_v1.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block + bip113signed1 = self.sign_transaction(self.nodes[0], bip113tx_v1) + success_txs.append(bip113signed1) + success_txs.append(bip112tx_special_v1) + # add BIP 68 txs + success_txs.extend(all_rlt_txs(bip68txs_v1)) + # add BIP 112 with seq=10 txs + success_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_v1)) + success_txs.extend(all_rlt_txs(bip112txs_vary_OP_CSV_v1)) + # try BIP 112 with seq=9 txs + success_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_9_v1)) + success_txs.extend(all_rlt_txs(bip112txs_vary_OP_CSV_9_v1)) + yield TestInstance([[self.create_test_block(success_txs), True]]) # 6 + self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash()) + + ### Version 2 txs ### + success_txs = [] + # add BIP113 tx and -1 CSV tx + bip113tx_v2.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block + bip113signed2 = self.sign_transaction(self.nodes[0], bip113tx_v2) + success_txs.append(bip113signed2) + success_txs.append(bip112tx_special_v2) + # add BIP 68 txs + success_txs.extend(all_rlt_txs(bip68txs_v2)) + # add BIP 112 with seq=10 txs + success_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_v2)) + success_txs.extend(all_rlt_txs(bip112txs_vary_OP_CSV_v2)) + # try BIP 112 with seq=9 txs + success_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_9_v2)) + success_txs.extend(all_rlt_txs(bip112txs_vary_OP_CSV_9_v2)) + yield TestInstance([[self.create_test_block(success_txs), True]]) # 7 + self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash()) + + + # 1 more version 4 block to get us to height 575 so the fork should now be active for the next block + test_blocks = self.generate_blocks(1, 4) + yield TestInstance(test_blocks, sync_every_block=False) # 8 + assert_equal(self.get_bip9_status('csv')['status'], 'active') + + + ################################# + ### After Soft Forks Activate ### + ################################# + ### BIP 113 ### + # BIP 113 tests should now fail regardless of version number if nLockTime isn't satisfied by new rules + bip113tx_v1.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block + bip113signed1 = self.sign_transaction(self.nodes[0], bip113tx_v1) + bip113tx_v2.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block + bip113signed2 = self.sign_transaction(self.nodes[0], bip113tx_v2) + for bip113tx in [bip113signed1, bip113signed2]: + yield TestInstance([[self.create_test_block([bip113tx]), False]]) # 9,10 + # BIP 113 tests should now pass if the locktime is < MTP + bip113tx_v1.nLockTime = self.last_block_time - 600 * 5 - 1 # = MTP of prior block (not <) but < time put on current block + bip113signed1 = self.sign_transaction(self.nodes[0], bip113tx_v1) + bip113tx_v2.nLockTime = self.last_block_time - 600 * 5 - 1 # = MTP of prior block (not <) but < time put on current block + bip113signed2 = self.sign_transaction(self.nodes[0], bip113tx_v2) + for bip113tx in [bip113signed1, bip113signed2]: + yield TestInstance([[self.create_test_block([bip113tx]), True]]) # 11,12 + self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash()) + + # Next block height = 580 after 4 blocks of random version + test_blocks = self.generate_blocks(4, 1234) + yield TestInstance(test_blocks, sync_every_block=False) # 13 + + ### BIP 68 ### + ### Version 1 txs ### + # All still pass + success_txs = [] + success_txs.extend(all_rlt_txs(bip68txs_v1)) + yield TestInstance([[self.create_test_block(success_txs), True]]) # 14 + self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash()) + + ### Version 2 txs ### + bip68success_txs = [] + # All txs with SEQUENCE_LOCKTIME_DISABLE_FLAG set pass + for b25 in xrange(2): + for b22 in xrange(2): + for b18 in xrange(2): + bip68success_txs.append(bip68txs_v2[1][b25][b22][b18]) + yield TestInstance([[self.create_test_block(bip68success_txs), True]]) # 15 + self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash()) + # All txs without flag fail as we are at delta height = 8 < 10 and delta time = 8 * 600 < 10 * 512 + bip68timetxs = [] + for b25 in xrange(2): + for b18 in xrange(2): + bip68timetxs.append(bip68txs_v2[0][b25][1][b18]) + for tx in bip68timetxs: + yield TestInstance([[self.create_test_block([tx]), False]]) # 16 - 19 + bip68heighttxs = [] + for b25 in xrange(2): + for b18 in xrange(2): + bip68heighttxs.append(bip68txs_v2[0][b25][0][b18]) + for tx in bip68heighttxs: + yield TestInstance([[self.create_test_block([tx]), False]]) # 20 - 23 + + # Advance one block to 581 + test_blocks = self.generate_blocks(1, 1234) + yield TestInstance(test_blocks, sync_every_block=False) # 24 + + # Height txs should fail and time txs should now pass 9 * 600 > 10 * 512 + bip68success_txs.extend(bip68timetxs) + yield TestInstance([[self.create_test_block(bip68success_txs), True]]) # 25 + self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash()) + for tx in bip68heighttxs: + yield TestInstance([[self.create_test_block([tx]), False]]) # 26 - 29 + + # Advance one block to 582 + test_blocks = self.generate_blocks(1, 1234) + yield TestInstance(test_blocks, sync_every_block=False) # 30 + + # All BIP 68 txs should pass + bip68success_txs.extend(bip68heighttxs) + yield TestInstance([[self.create_test_block(bip68success_txs), True]]) # 31 + self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash()) + + + ### BIP 112 ### + ### Version 1 txs ### + # -1 OP_CSV tx should fail + yield TestInstance([[self.create_test_block([bip112tx_special_v1]), False]]) #32 + # If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in argument to OP_CSV, version 1 txs should still pass + success_txs = [] + for b25 in xrange(2): + for b22 in xrange(2): + for b18 in xrange(2): + success_txs.append(bip112txs_vary_OP_CSV_v1[1][b25][b22][b18]) + success_txs.append(bip112txs_vary_OP_CSV_9_v1[1][b25][b22][b18]) + yield TestInstance([[self.create_test_block(success_txs), True]]) # 33 + self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash()) + + # If SEQUENCE_LOCKTIME_DISABLE_FLAG is unset in argument to OP_CSV, version 1 txs should now fail + fail_txs = [] + fail_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_v1)) + fail_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_9_v1)) + for b25 in xrange(2): + for b22 in xrange(2): + for b18 in xrange(2): + fail_txs.append(bip112txs_vary_OP_CSV_v1[0][b25][b22][b18]) + fail_txs.append(bip112txs_vary_OP_CSV_9_v1[0][b25][b22][b18]) + + for tx in fail_txs: + yield TestInstance([[self.create_test_block([tx]), False]]) # 34 - 81 + + ### Version 2 txs ### + # -1 OP_CSV tx should fail + yield TestInstance([[self.create_test_block([bip112tx_special_v2]), False]]) #82 + + # If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in argument to OP_CSV, version 2 txs should pass (all sequence locks are met) + success_txs = [] + for b25 in xrange(2): + for b22 in xrange(2): + for b18 in xrange(2): + success_txs.append(bip112txs_vary_OP_CSV_v2[1][b25][b22][b18]) # 8/16 of vary_OP_CSV + success_txs.append(bip112txs_vary_OP_CSV_9_v2[1][b25][b22][b18]) # 8/16 of vary_OP_CSV_9 + + yield TestInstance([[self.create_test_block(success_txs), True]]) # 83 + self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash()) + + ## SEQUENCE_LOCKTIME_DISABLE_FLAG is unset in argument to OP_CSV for all remaining txs ## + # All txs with nSequence 11 should fail either due to earlier mismatch or failing the CSV check + fail_txs = [] + fail_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_9_v2)) # 16/16 of vary_nSequence_9 + for b25 in xrange(2): + for b22 in xrange(2): + for b18 in xrange(2): + fail_txs.append(bip112txs_vary_OP_CSV_9_v2[0][b25][b22][b18]) # 16/16 of vary_OP_CSV_9 + + for tx in fail_txs: + yield TestInstance([[self.create_test_block([tx]), False]]) # 84 - 107 + + # If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in nSequence, tx should fail + fail_txs = [] + for b25 in xrange(2): + for b22 in xrange(2): + for b18 in xrange(2): + fail_txs.append(bip112txs_vary_nSequence_v2[1][b25][b22][b18]) # 8/16 of vary_nSequence + for tx in fail_txs: + yield TestInstance([[self.create_test_block([tx]), False]]) # 108-115 + + # If sequencelock types mismatch, tx should fail + fail_txs = [] + for b25 in xrange(2): + for b18 in xrange(2): + fail_txs.append(bip112txs_vary_nSequence_v2[0][b25][1][b18]) # 12/16 of vary_nSequence + fail_txs.append(bip112txs_vary_OP_CSV_v2[0][b25][1][b18]) # 12/16 of vary_OP_CSV + for tx in fail_txs: + yield TestInstance([[self.create_test_block([tx]), False]]) # 116-123 + + # Remaining txs should pass, just test masking works properly + success_txs = [] + for b25 in xrange(2): + for b18 in xrange(2): + success_txs.append(bip112txs_vary_nSequence_v2[0][b25][0][b18]) # 16/16 of vary_nSequence + success_txs.append(bip112txs_vary_OP_CSV_v2[0][b25][0][b18]) # 16/16 of vary_OP_CSV + yield TestInstance([[self.create_test_block(success_txs), True]]) # 124 + self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash()) + + # Additional test, of checking that comparison of two time types works properly + time_txs = [] + for b25 in xrange(2): + for b18 in xrange(2): + tx = bip112txs_vary_OP_CSV_v2[0][b25][1][b18] + tx.vin[0].nSequence = base_relative_locktime | seq_type_flag + signtx = self.sign_transaction(self.nodes[0], tx) + time_txs.append(signtx) + yield TestInstance([[self.create_test_block(time_txs), True]]) # 125 + self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash()) + + ### Missing aspects of test + ## Testing empty stack fails + + +if __name__ == '__main__': + BIP68_112_113Test().main() From 68d4282774d6a60c609301cddad0b652f16df4d9 Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Thu, 17 Mar 2016 12:48:05 -0400 Subject: [PATCH 0028/1802] Fix calculation of balances and available coins. No longer consider coins which aren't in our mempool. Add test for regression in abandonconflict.py --- qa/rpc-tests/abandonconflict.py | 6 ++++++ src/wallet/wallet.cpp | 9 +++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/qa/rpc-tests/abandonconflict.py b/qa/rpc-tests/abandonconflict.py index 38028df07902c..a83aa97fcd806 100755 --- a/qa/rpc-tests/abandonconflict.py +++ b/qa/rpc-tests/abandonconflict.py @@ -83,6 +83,12 @@ def run_test(self): # inputs are still spent, but change not received newbalance = self.nodes[0].getbalance() assert(newbalance == balance - Decimal("24.9996")) + # Unconfirmed received funds that are not in mempool, also shouldn't show + # up in unconfirmed balance + unconfbalance = self.nodes[0].getunconfirmedbalance() + self.nodes[0].getbalance() + assert(unconfbalance == newbalance) + # Also shouldn't show up in listunspent + assert(not txABC2 in [utxo["txid"] for utxo in self.nodes[0].listunspent(0)]) balance = newbalance # Abandon original transaction and verify inputs are available again diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 1ef055e5521c0..f1e61c710f288 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1578,7 +1578,7 @@ CAmount CWallet::GetUnconfirmedBalance() const for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { const CWalletTx* pcoin = &(*it).second; - if (!CheckFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0)) + if (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0 && pcoin->InMempool()) nTotal += pcoin->GetAvailableCredit(); } } @@ -1623,7 +1623,7 @@ CAmount CWallet::GetUnconfirmedWatchOnlyBalance() const for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { const CWalletTx* pcoin = &(*it).second; - if (!CheckFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0)) + if (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0 && pcoin->InMempool()) nTotal += pcoin->GetAvailableWatchOnlyCredit(); } } @@ -1668,6 +1668,11 @@ void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const if (nDepth < 0) continue; + // We should not consider coins which aren't at least in our mempool + // It's possible for these to be conflicted via ancestors which we may never be able to detect + if (nDepth == 0 && !pcoin->InMempool()) + continue; + for (unsigned int i = 0; i < pcoin->vout.size(); i++) { isminetype mine = IsMine(pcoin->vout[i]); if (!(IsSpent(wtxid, i)) && mine != ISMINE_NO && From bbb9d1d1231099122a5b0ad5dd86f3f93ce22724 Mon Sep 17 00:00:00 2001 From: BtcDrak Date: Mon, 7 Mar 2016 19:44:09 +0000 Subject: [PATCH 0029/1802] Remove p2p alert handling --- src/Makefile.am | 2 - src/Makefile.test.include | 2 +- src/alert.cpp | 266 -------------------------------- src/alert.h | 113 -------------- src/main.cpp | 62 -------- src/qt/clientmodel.cpp | 1 - src/test/alert_tests.cpp | 289 +++++++---------------------------- src/test/data/alertTests.raw | Bin 1279 -> 0 bytes 8 files changed, 57 insertions(+), 678 deletions(-) delete mode 100644 src/alert.cpp delete mode 100644 src/alert.h delete mode 100644 src/test/data/alertTests.raw diff --git a/src/Makefile.am b/src/Makefile.am index 7765ea43edc1a..6ad7aabae0ef6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -87,7 +87,6 @@ endif # bitcoin core # BITCOIN_CORE_H = \ addrman.h \ - alert.h \ base58.h \ bloom.h \ chain.h \ @@ -176,7 +175,6 @@ libbitcoin_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CP libbitcoin_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_server_a_SOURCES = \ addrman.cpp \ - alert.cpp \ bloom.cpp \ chain.cpp \ checkpoints.cpp \ diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 57f9ac50e0a01..7e7bf8abeb76b 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -29,7 +29,7 @@ JSON_TEST_FILES = \ test/data/tx_valid.json \ test/data/sighash.json -RAW_TEST_FILES = test/data/alertTests.raw +RAW_TEST_FILES = GENERATED_TEST_FILES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.raw.h) diff --git a/src/alert.cpp b/src/alert.cpp deleted file mode 100644 index eb1cd5e7f6ebe..0000000000000 --- a/src/alert.cpp +++ /dev/null @@ -1,266 +0,0 @@ -// Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2015 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 "alert.h" - -#include "clientversion.h" -#include "net.h" -#include "pubkey.h" -#include "timedata.h" -#include "ui_interface.h" -#include "util.h" -#include "utilstrencodings.h" - -#include -#include -#include - -#include -#include -#include -#include - -using namespace std; - -map mapAlerts; -CCriticalSection cs_mapAlerts; - -void CUnsignedAlert::SetNull() -{ - nVersion = 1; - nRelayUntil = 0; - nExpiration = 0; - nID = 0; - nCancel = 0; - setCancel.clear(); - nMinVer = 0; - nMaxVer = 0; - setSubVer.clear(); - nPriority = 0; - - strComment.clear(); - strStatusBar.clear(); - strReserved.clear(); -} - -std::string CUnsignedAlert::ToString() const -{ - std::string strSetCancel; - BOOST_FOREACH(int n, setCancel) - strSetCancel += strprintf("%d ", n); - std::string strSetSubVer; - BOOST_FOREACH(const std::string& str, setSubVer) - strSetSubVer += "\"" + str + "\" "; - return strprintf( - "CAlert(\n" - " nVersion = %d\n" - " nRelayUntil = %d\n" - " nExpiration = %d\n" - " nID = %d\n" - " nCancel = %d\n" - " setCancel = %s\n" - " nMinVer = %d\n" - " nMaxVer = %d\n" - " setSubVer = %s\n" - " nPriority = %d\n" - " strComment = \"%s\"\n" - " strStatusBar = \"%s\"\n" - ")\n", - nVersion, - nRelayUntil, - nExpiration, - nID, - nCancel, - strSetCancel, - nMinVer, - nMaxVer, - strSetSubVer, - nPriority, - strComment, - strStatusBar); -} - -void CAlert::SetNull() -{ - CUnsignedAlert::SetNull(); - vchMsg.clear(); - vchSig.clear(); -} - -bool CAlert::IsNull() const -{ - return (nExpiration == 0); -} - -uint256 CAlert::GetHash() const -{ - return Hash(this->vchMsg.begin(), this->vchMsg.end()); -} - -bool CAlert::IsInEffect() const -{ - return (GetAdjustedTime() < nExpiration); -} - -bool CAlert::Cancels(const CAlert& alert) const -{ - if (!IsInEffect()) - return false; // this was a no-op before 31403 - return (alert.nID <= nCancel || setCancel.count(alert.nID)); -} - -bool CAlert::AppliesTo(int nVersion, const std::string& strSubVerIn) const -{ - // TODO: rework for client-version-embedded-in-strSubVer ? - return (IsInEffect() && - nMinVer <= nVersion && nVersion <= nMaxVer && - (setSubVer.empty() || setSubVer.count(strSubVerIn))); -} - -bool CAlert::AppliesToMe() const -{ - return AppliesTo(PROTOCOL_VERSION, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector())); -} - -bool CAlert::RelayTo(CNode* pnode) const -{ - if (!IsInEffect()) - return false; - // don't relay to nodes which haven't sent their version message - if (pnode->nVersion == 0) - return false; - // returns true if wasn't already contained in the set - if (pnode->setKnown.insert(GetHash()).second) - { - if (AppliesTo(pnode->nVersion, pnode->strSubVer) || - AppliesToMe() || - GetAdjustedTime() < nRelayUntil) - { - pnode->PushMessage(NetMsgType::ALERT, *this); - return true; - } - } - return false; -} - -bool CAlert::CheckSignature(const std::vector& alertKey) const -{ - CPubKey key(alertKey); - if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig)) - return error("CAlert::CheckSignature(): verify signature failed"); - - // Now unserialize the data - CDataStream sMsg(vchMsg, SER_NETWORK, PROTOCOL_VERSION); - sMsg >> *(CUnsignedAlert*)this; - return true; -} - -CAlert CAlert::getAlertByHash(const uint256 &hash) -{ - CAlert retval; - { - LOCK(cs_mapAlerts); - map::iterator mi = mapAlerts.find(hash); - if(mi != mapAlerts.end()) - retval = mi->second; - } - return retval; -} - -bool CAlert::ProcessAlert(const std::vector& alertKey, bool fThread) -{ - if (!CheckSignature(alertKey)) - return false; - if (!IsInEffect()) - return false; - - // alert.nID=max is reserved for if the alert key is - // compromised. It must have a pre-defined message, - // must never expire, must apply to all versions, - // and must cancel all previous - // alerts or it will be ignored (so an attacker can't - // send an "everything is OK, don't panic" version that - // cannot be overridden): - int maxInt = std::numeric_limits::max(); - if (nID == maxInt) - { - if (!( - nExpiration == maxInt && - nCancel == (maxInt-1) && - nMinVer == 0 && - nMaxVer == maxInt && - setSubVer.empty() && - nPriority == maxInt && - strStatusBar == "URGENT: Alert key compromised, upgrade required" - )) - return false; - } - - { - LOCK(cs_mapAlerts); - // Cancel previous alerts - for (map::iterator mi = mapAlerts.begin(); mi != mapAlerts.end();) - { - const CAlert& alert = (*mi).second; - if (Cancels(alert)) - { - LogPrint("alert", "cancelling alert %d\n", alert.nID); - uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED); - mapAlerts.erase(mi++); - } - else if (!alert.IsInEffect()) - { - LogPrint("alert", "expiring alert %d\n", alert.nID); - uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED); - mapAlerts.erase(mi++); - } - else - mi++; - } - - // Check if this alert has been cancelled - BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts) - { - const CAlert& alert = item.second; - if (alert.Cancels(*this)) - { - LogPrint("alert", "alert already cancelled by %d\n", alert.nID); - return false; - } - } - - // Add to mapAlerts - mapAlerts.insert(make_pair(GetHash(), *this)); - // Notify UI and -alertnotify if it applies to me - if(AppliesToMe()) - { - uiInterface.NotifyAlertChanged(GetHash(), CT_NEW); - Notify(strStatusBar, fThread); - } - } - - LogPrint("alert", "accepted alert %d, AppliesToMe()=%d\n", nID, AppliesToMe()); - return true; -} - -void -CAlert::Notify(const std::string& strMessage, bool fThread) -{ - std::string strCmd = GetArg("-alertnotify", ""); - if (strCmd.empty()) return; - - // Alert text should be plain ascii coming from a trusted source, but to - // be safe we first strip anything not in safeChars, then add single quotes around - // the whole string before passing it to the shell: - std::string singleQuote("'"); - std::string safeStatus = SanitizeString(strMessage); - safeStatus = singleQuote+safeStatus+singleQuote; - boost::replace_all(strCmd, "%s", safeStatus); - - if (fThread) - boost::thread t(runCommand, strCmd); // thread runs free - else - runCommand(strCmd); -} diff --git a/src/alert.h b/src/alert.h deleted file mode 100644 index 8cb86e338c5d2..0000000000000 --- a/src/alert.h +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2015 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef BITCOIN_ALERT_H -#define BITCOIN_ALERT_H - -#include "serialize.h" -#include "sync.h" - -#include -#include -#include -#include - -class CAlert; -class CNode; -class uint256; - -extern std::map mapAlerts; -extern CCriticalSection cs_mapAlerts; - -/** Alerts are for notifying old versions if they become too obsolete and - * need to upgrade. The message is displayed in the status bar. - * Alert messages are broadcast as a vector of signed data. Unserializing may - * not read the entire buffer if the alert is for a newer version, but older - * versions can still relay the original data. - */ -class CUnsignedAlert -{ -public: - int nVersion; - int64_t nRelayUntil; // when newer nodes stop relaying to newer nodes - int64_t nExpiration; - int nID; - int nCancel; - std::set setCancel; - int nMinVer; // lowest version inclusive - int nMaxVer; // highest version inclusive - std::set setSubVer; // empty matches all - int nPriority; - - // Actions - std::string strComment; - std::string strStatusBar; - std::string strReserved; - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(this->nVersion); - nVersion = this->nVersion; - READWRITE(nRelayUntil); - READWRITE(nExpiration); - READWRITE(nID); - READWRITE(nCancel); - READWRITE(setCancel); - READWRITE(nMinVer); - READWRITE(nMaxVer); - READWRITE(setSubVer); - READWRITE(nPriority); - - READWRITE(LIMITED_STRING(strComment, 65536)); - READWRITE(LIMITED_STRING(strStatusBar, 256)); - READWRITE(LIMITED_STRING(strReserved, 256)); - } - - void SetNull(); - - std::string ToString() const; -}; - -/** An alert is a combination of a serialized CUnsignedAlert and a signature. */ -class CAlert : public CUnsignedAlert -{ -public: - std::vector vchMsg; - std::vector vchSig; - - CAlert() - { - SetNull(); - } - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(vchMsg); - READWRITE(vchSig); - } - - void SetNull(); - bool IsNull() const; - uint256 GetHash() const; - bool IsInEffect() const; - bool Cancels(const CAlert& alert) const; - bool AppliesTo(int nVersion, const std::string& strSubVerIn) const; - bool AppliesToMe() const; - bool RelayTo(CNode* pnode) const; - bool CheckSignature(const std::vector& alertKey) const; - bool ProcessAlert(const std::vector& alertKey, bool fThread = true); // fThread means run -alertnotify in a free-running thread - static void Notify(const std::string& strMessage, bool fThread); - - /* - * Get copy of (active) alert object by hash. Returns a null alert if it is not found. - */ - static CAlert getAlertByHash(const uint256 &hash); -}; - -#endif // BITCOIN_ALERT_H diff --git a/src/main.cpp b/src/main.cpp index 1bc88326b6fc7..d5fb047aa0d11 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,7 +6,6 @@ #include "main.h" #include "addrman.h" -#include "alert.h" #include "arith_uint256.h" #include "chainparams.h" #include "checkpoints.h" @@ -4213,14 +4212,8 @@ void static CheckBlockIndex(const Consensus::Params& consensusParams) assert(nNodes == forward.size()); } -////////////////////////////////////////////////////////////////////////////// -// -// CAlert -// - std::string GetWarnings(const std::string& strFor) { - int nPriority = 0; string strStatusBar; string strRPC; string strGUI; @@ -4236,37 +4229,20 @@ std::string GetWarnings(const std::string& strFor) // Misc warnings like out of disk space and clock is wrong if (strMiscWarning != "") { - nPriority = 1000; strStatusBar = strGUI = strMiscWarning; } if (fLargeWorkForkFound) { - nPriority = 2000; strStatusBar = strRPC = "Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues."; strGUI = _("Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues."); } else if (fLargeWorkInvalidChainFound) { - nPriority = 2000; strStatusBar = strRPC = "Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade."; strGUI = _("Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade."); } - // Alerts - { - LOCK(cs_mapAlerts); - BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts) - { - const CAlert& alert = item.second; - if (alert.AppliesToMe() && alert.nPriority > nPriority) - { - nPriority = alert.nPriority; - strStatusBar = strGUI = alert.strStatusBar; - } - } - } - if (strFor == "gui") return strGUI; else if (strFor == "statusbar") @@ -4588,13 +4564,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } } - // Relay alerts - { - LOCK(cs_mapAlerts); - BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts) - item.second.RelayTo(pfrom); - } - pfrom->fSuccessfullyConnected = true; string remoteAddr; @@ -5302,37 +5271,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } - else if (fAlerts && strCommand == NetMsgType::ALERT) - { - CAlert alert; - vRecv >> alert; - - uint256 alertHash = alert.GetHash(); - if (pfrom->setKnown.count(alertHash) == 0) - { - if (alert.ProcessAlert(chainparams.AlertKey())) - { - // Relay - pfrom->setKnown.insert(alertHash); - { - LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) - alert.RelayTo(pnode); - } - } - else { - // Small DoS penalty so peers that send us lots of - // duplicate/expired/invalid-signature/whatever alerts - // eventually get banned. - // This isn't a Misbehaving(100) (immediate ban) because the - // peer might be an older or different implementation with - // a different signature key, etc. - Misbehaving(pfrom->GetId(), 10); - } - } - } - - else if (strCommand == NetMsgType::FILTERLOAD) { CBloomFilter filter; diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index fb502b3c81acc..71a12c27fd350 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -8,7 +8,6 @@ #include "guiconstants.h" #include "peertablemodel.h" -#include "alert.h" #include "chainparams.h" #include "checkpoints.h" #include "clientversion.h" diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp index 87d35be41299d..ed3cce2de43bb 100644 --- a/src/test/alert_tests.cpp +++ b/src/test/alert_tests.cpp @@ -4,253 +4,76 @@ // Unit tests for alert system -#include "alert.h" -#include "chain.h" #include "chainparams.h" -#include "clientversion.h" -#include "data/alertTests.raw.h" #include "main.h" // For PartitionCheck -#include "serialize.h" -#include "streams.h" -#include "utilstrencodings.h" #include "test/testutil.h" #include "test/test_bitcoin.h" -#include - -#include -#include #include -#if 0 -// -// alertTests contains 7 alerts, generated with this code: -// (SignAndSave code not shown, alert signing key is secret) -// -{ - CAlert alert; - alert.nRelayUntil = 60; - alert.nExpiration = 24 * 60 * 60; - alert.nID = 1; - alert.nCancel = 0; // cancels previous messages up to this ID number - alert.nMinVer = 0; // These versions are protocol versions - alert.nMaxVer = 999001; - alert.nPriority = 1; - alert.strComment = "Alert comment"; - alert.strStatusBar = "Alert 1"; - - SignAndSave(alert, "test/alertTests"); - - alert.setSubVer.insert(std::string("/Satoshi:0.1.0/")); - alert.strStatusBar = "Alert 1 for Satoshi 0.1.0"; - SignAndSave(alert, "test/alertTests"); - - alert.setSubVer.insert(std::string("/Satoshi:0.2.0/")); - alert.strStatusBar = "Alert 1 for Satoshi 0.1.0, 0.2.0"; - SignAndSave(alert, "test/alertTests"); - - alert.setSubVer.clear(); - ++alert.nID; - alert.nCancel = 1; - alert.nPriority = 100; - alert.strStatusBar = "Alert 2, cancels 1"; - SignAndSave(alert, "test/alertTests"); - - alert.nExpiration += 60; - ++alert.nID; - SignAndSave(alert, "test/alertTests"); - - ++alert.nID; - alert.nMinVer = 11; - alert.nMaxVer = 22; - SignAndSave(alert, "test/alertTests"); - - ++alert.nID; - alert.strStatusBar = "Alert 2 for Satoshi 0.1.0"; - alert.setSubVer.insert(std::string("/Satoshi:0.1.0/")); - SignAndSave(alert, "test/alertTests"); - - ++alert.nID; - alert.nMinVer = 0; - alert.nMaxVer = 999999; - alert.strStatusBar = "Evil Alert'; /bin/ls; echo '"; - alert.setSubVer.clear(); - SignAndSave(alert, "test/alertTests"); -} -#endif - -struct ReadAlerts : public TestingSetup -{ - ReadAlerts() - { - std::vector vch(alert_tests::alertTests, alert_tests::alertTests + sizeof(alert_tests::alertTests)); - CDataStream stream(vch, SER_DISK, CLIENT_VERSION); - try { - while (!stream.eof()) - { - CAlert alert; - stream >> alert; - alerts.push_back(alert); - } - } - catch (const std::exception&) { } - } - ~ReadAlerts() { } - - static std::vector read_lines(boost::filesystem::path filepath) - { - std::vector result; - - std::ifstream f(filepath.string().c_str()); - std::string line; - while (std::getline(f,line)) - result.push_back(line); - - return result; - } - - std::vector alerts; -}; - -BOOST_FIXTURE_TEST_SUITE(Alert_tests, ReadAlerts) - - -BOOST_AUTO_TEST_CASE(AlertApplies) -{ - SetMockTime(11); - const std::vector& alertKey = Params(CBaseChainParams::MAIN).AlertKey(); - - BOOST_FOREACH(const CAlert& alert, alerts) - { - BOOST_CHECK(alert.CheckSignature(alertKey)); - } - - BOOST_CHECK(alerts.size() >= 3); - - // Matches: - BOOST_CHECK(alerts[0].AppliesTo(1, "")); - BOOST_CHECK(alerts[0].AppliesTo(999001, "")); - BOOST_CHECK(alerts[0].AppliesTo(1, "/Satoshi:11.11.11/")); +BOOST_FIXTURE_TEST_SUITE(Alert_tests, TestingSetup) - BOOST_CHECK(alerts[1].AppliesTo(1, "/Satoshi:0.1.0/")); - BOOST_CHECK(alerts[1].AppliesTo(999001, "/Satoshi:0.1.0/")); - - BOOST_CHECK(alerts[2].AppliesTo(1, "/Satoshi:0.1.0/")); - BOOST_CHECK(alerts[2].AppliesTo(1, "/Satoshi:0.2.0/")); - - // Don't match: - BOOST_CHECK(!alerts[0].AppliesTo(-1, "")); - BOOST_CHECK(!alerts[0].AppliesTo(999002, "")); - - BOOST_CHECK(!alerts[1].AppliesTo(1, "")); - BOOST_CHECK(!alerts[1].AppliesTo(1, "Satoshi:0.1.0")); - BOOST_CHECK(!alerts[1].AppliesTo(1, "/Satoshi:0.1.0")); - BOOST_CHECK(!alerts[1].AppliesTo(1, "Satoshi:0.1.0/")); - BOOST_CHECK(!alerts[1].AppliesTo(-1, "/Satoshi:0.1.0/")); - BOOST_CHECK(!alerts[1].AppliesTo(999002, "/Satoshi:0.1.0/")); - BOOST_CHECK(!alerts[1].AppliesTo(1, "/Satoshi:0.2.0/")); - - BOOST_CHECK(!alerts[2].AppliesTo(1, "/Satoshi:0.3.0/")); - - SetMockTime(0); -} - - -BOOST_AUTO_TEST_CASE(AlertNotify) -{ - SetMockTime(11); - const std::vector& alertKey = Params(CBaseChainParams::MAIN).AlertKey(); - - boost::filesystem::path temp = GetTempPath() / - boost::filesystem::unique_path("alertnotify-%%%%.txt"); - - mapArgs["-alertnotify"] = std::string("echo %s >> ") + temp.string(); - - BOOST_FOREACH(CAlert alert, alerts) - alert.ProcessAlert(alertKey, false); - - std::vector r = read_lines(temp); - BOOST_CHECK_EQUAL(r.size(), 4u); - -// Windows built-in echo semantics are different than posixy shells. Quotes and -// whitespace are printed literally. - -#ifndef WIN32 - BOOST_CHECK_EQUAL(r[0], "Alert 1"); - BOOST_CHECK_EQUAL(r[1], "Alert 2, cancels 1"); - BOOST_CHECK_EQUAL(r[2], "Alert 2, cancels 1"); - BOOST_CHECK_EQUAL(r[3], "Evil Alert; /bin/ls; echo "); // single-quotes should be removed -#else - BOOST_CHECK_EQUAL(r[0], "'Alert 1' "); - BOOST_CHECK_EQUAL(r[1], "'Alert 2, cancels 1' "); - BOOST_CHECK_EQUAL(r[2], "'Alert 2, cancels 1' "); - BOOST_CHECK_EQUAL(r[3], "'Evil Alert; /bin/ls; echo ' "); -#endif - boost::filesystem::remove(temp); - - SetMockTime(0); -} static bool falseFunc() { return false; } BOOST_AUTO_TEST_CASE(PartitionAlert) -{ - // Test PartitionCheck - CCriticalSection csDummy; - CBlockIndex indexDummy[100]; - CChainParams& params = Params(CBaseChainParams::MAIN); - int64_t nPowTargetSpacing = params.GetConsensus().nPowTargetSpacing; - - // Generate fake blockchain timestamps relative to - // an arbitrary time: - int64_t now = 1427379054; - SetMockTime(now); - for (int i = 0; i < 100; i++) - { - indexDummy[i].phashBlock = NULL; - if (i == 0) indexDummy[i].pprev = NULL; - else indexDummy[i].pprev = &indexDummy[i-1]; - indexDummy[i].nHeight = i; - indexDummy[i].nTime = now - (100-i)*nPowTargetSpacing; - // Other members don't matter, the partition check code doesn't - // use them - } - - strMiscWarning = ""; - - // Test 1: chain with blocks every nPowTargetSpacing seconds, - // as normal, no worries: - PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); - BOOST_CHECK_MESSAGE(strMiscWarning.empty(), strMiscWarning); - - // Test 2: go 3.5 hours without a block, expect a warning: - now += 3*60*60+30*60; - SetMockTime(now); - PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); - BOOST_CHECK(!strMiscWarning.empty()); - BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning); - strMiscWarning = ""; - - // Test 3: test the "partition alerts only go off once per day" - // code: - now += 60*10; - SetMockTime(now); - PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); - BOOST_CHECK(strMiscWarning.empty()); + { + // Test PartitionCheck + CCriticalSection csDummy; + CBlockIndex indexDummy[100]; + CChainParams& params = Params(CBaseChainParams::MAIN); + int64_t nPowTargetSpacing = params.GetConsensus().nPowTargetSpacing; + + // Generate fake blockchain timestamps relative to + // an arbitrary time: + int64_t now = 1427379054; + SetMockTime(now); + for (int i = 0; i < 100; i++) + { + indexDummy[i].phashBlock = NULL; + if (i == 0) indexDummy[i].pprev = NULL; + else indexDummy[i].pprev = &indexDummy[i-1]; + indexDummy[i].nHeight = i; + indexDummy[i].nTime = now - (100-i)*nPowTargetSpacing; + // Other members don't matter, the partition check code doesn't + // use them + } - // Test 4: get 2.5 times as many blocks as expected: - now += 60*60*24; // Pretend it is a day later - SetMockTime(now); - int64_t quickSpacing = nPowTargetSpacing*2/5; - for (int i = 0; i < 100; i++) // Tweak chain timestamps: + strMiscWarning = ""; + + // Test 1: chain with blocks every nPowTargetSpacing seconds, + // as normal, no worries: + PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); + BOOST_CHECK_MESSAGE(strMiscWarning.empty(), strMiscWarning); + + // Test 2: go 3.5 hours without a block, expect a warning: + now += 3*60*60+30*60; + SetMockTime(now); + PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); + BOOST_CHECK(!strMiscWarning.empty()); + BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning); + strMiscWarning = ""; + + // Test 3: test the "partition alerts only go off once per day" + // code: + now += 60*10; + SetMockTime(now); + PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); + BOOST_CHECK(strMiscWarning.empty()); + + // Test 4: get 2.5 times as many blocks as expected: + now += 60*60*24; // Pretend it is a day later + SetMockTime(now); + int64_t quickSpacing = nPowTargetSpacing*2/5; + for (int i = 0; i < 100; i++) // Tweak chain timestamps: indexDummy[i].nTime = now - (100-i)*quickSpacing; - PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); - BOOST_CHECK(!strMiscWarning.empty()); - BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning); - strMiscWarning = ""; + PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); + BOOST_CHECK(!strMiscWarning.empty()); + BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning); + strMiscWarning = ""; - SetMockTime(0); -} + SetMockTime(0); + } -BOOST_AUTO_TEST_SUITE_END() +BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file diff --git a/src/test/data/alertTests.raw b/src/test/data/alertTests.raw deleted file mode 100644 index 01f50680b95aa307a1a013b643ded4ae0bc47162..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1279 zcmZ={WME*h0b&qn2n6vM7$78=$-oe4#}5(Vb<9aEDp5$z&&^HED`AK53>n-FT$vOZ zT6;>jOMiNBjj`hU_HgHQ?~0yVcV6r{KVN{qoVTd1?j)0f{?x_?$@^IxUUY29f16*- z{-FM@nZvZ(TZ|lvBLA-{pO8$HOBng}gA+^gi!(B<4D<~34D>;|P+cYob(un1evtxH zu>x2zgPVa1lY-RE%g6XV)mGXqWBmT=!_|Y)_kR4}7A7R>c0E!g1h&KK=J$_^x?-%R>l_4VpRoijgP z&DbIlds%@=!Hs|Q$%9_UR_lD=jto@ZWi)^P&3X0fwJdjAvK+dmdHF6@N3p;h#SLVL z0Wkw{0R?f?PV@b-k5Wyi>i4_%Bo<$lHv6ySF0|S7Vr$;KnH3w}K4Ve{5mx)@H;>VG zV)PxY7R{(M)t&dXdm1tqJ%LW&jLQ5abT(~;1uVuU5DK-_v|qEX;l z`;Ea8OG>`yYWv(O?P7~*yl?IK{6}Bi%Enc$ObUtn4ofyOb8$Z~I;nGod;9)Xj~<*9 zKa_r_FRL*-b5> Date: Sun, 6 Mar 2016 10:07:25 +0000 Subject: [PATCH 0030/1802] Update alert notification and GUI --- src/main.cpp | 28 ++++++++++++++++++++++++---- src/qt/clientmodel.cpp | 26 ++++++-------------------- src/qt/clientmodel.h | 2 +- src/ui_interface.h | 5 ++--- 4 files changed, 33 insertions(+), 28 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index d5fb047aa0d11..6c193a25e3bf2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1565,6 +1565,26 @@ bool fLargeWorkForkFound = false; bool fLargeWorkInvalidChainFound = false; CBlockIndex *pindexBestForkTip = NULL, *pindexBestForkBase = NULL; +static void AlertNotify(const std::string& strMessage, bool fThread) +{ + uiInterface.NotifyAlertChanged(); + std::string strCmd = GetArg("-alertnotify", ""); + if (strCmd.empty()) return; + + // Alert text should be plain ascii coming from a trusted source, but to + // be safe we first strip anything not in safeChars, then add single quotes around + // the whole string before passing it to the shell: + std::string singleQuote("'"); + std::string safeStatus = SanitizeString(strMessage); + safeStatus = singleQuote+safeStatus+singleQuote; + boost::replace_all(strCmd, "%s", safeStatus); + + if (fThread) + boost::thread t(runCommand, strCmd); // thread runs free + else + runCommand(strCmd); +} + void CheckForkWarningConditions() { AssertLockHeld(cs_main); @@ -1584,7 +1604,7 @@ void CheckForkWarningConditions() { std::string warning = std::string("'Warning: Large-work fork detected, forking after block ") + pindexBestForkBase->phashBlock->ToString() + std::string("'"); - CAlert::Notify(warning, true); + AlertNotify(warning, true); } if (pindexBestForkTip && pindexBestForkBase) { @@ -2115,7 +2135,7 @@ void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const if (!strWarning.empty()) { strMiscWarning = strWarning; - CAlert::Notify(strWarning, true); + AlertNotify(strWarning, true); lastAlertTime = now; } } @@ -2545,7 +2565,7 @@ void static UpdateTip(CBlockIndex *pindexNew) { if (state == THRESHOLD_ACTIVE) { strMiscWarning = strprintf(_("Warning: unknown new rules activated (versionbit %i)"), bit); if (!fWarned) { - CAlert::Notify(strMiscWarning, true); + AlertNotify(strMiscWarning, true); fWarned = true; } } else { @@ -2567,7 +2587,7 @@ void static UpdateTip(CBlockIndex *pindexNew) { // strMiscWarning is read by GetWarnings(), called by Qt and the JSON-RPC code to warn the user: strMiscWarning = _("Warning: Unknown block versions being mined! It's possible unknown rules are in effect"); if (!fWarned) { - CAlert::Notify(strMiscWarning, true); + AlertNotify(strMiscWarning, true); fWarned = true; } } diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 71a12c27fd350..d3edfedff29b6 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -121,20 +121,8 @@ void ClientModel::updateNumConnections(int numConnections) Q_EMIT numConnectionsChanged(numConnections); } -void ClientModel::updateAlert(const QString &hash, int status) +void ClientModel::updateAlert() { - // Show error message notification for new alert - if(status == CT_NEW) - { - uint256 hash_256; - hash_256.SetHex(hash.toStdString()); - CAlert alert = CAlert::getAlertByHash(hash_256); - if(!alert.IsNull()) - { - Q_EMIT message(tr("Network Alert"), QString::fromStdString(alert.strStatusBar), CClientUIInterface::ICON_ERROR); - } - } - Q_EMIT alertsChanged(getStatusBarWarnings()); } @@ -226,12 +214,10 @@ static void NotifyNumConnectionsChanged(ClientModel *clientmodel, int newNumConn Q_ARG(int, newNumConnections)); } -static void NotifyAlertChanged(ClientModel *clientmodel, const uint256 &hash, ChangeType status) +static void NotifyAlertChanged(ClientModel *clientmodel) { - qDebug() << "NotifyAlertChanged: " + QString::fromStdString(hash.GetHex()) + " status=" + QString::number(status); - QMetaObject::invokeMethod(clientmodel, "updateAlert", Qt::QueuedConnection, - Q_ARG(QString, QString::fromStdString(hash.GetHex())), - Q_ARG(int, status)); + qDebug() << "NotifyAlertChanged"; + QMetaObject::invokeMethod(clientmodel, "updateAlert", Qt::QueuedConnection); } static void BannedListChanged(ClientModel *clientmodel) @@ -265,7 +251,7 @@ void ClientModel::subscribeToCoreSignals() // Connect signals to client uiInterface.ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2)); uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this, _1)); - uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this, _1, _2)); + uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this)); uiInterface.BannedListChanged.connect(boost::bind(BannedListChanged, this)); uiInterface.NotifyBlockTip.connect(boost::bind(BlockTipChanged, this, _1, _2)); } @@ -275,7 +261,7 @@ void ClientModel::unsubscribeFromCoreSignals() // Disconnect signals from client uiInterface.ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2)); uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1)); - uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this, _1, _2)); + uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this)); uiInterface.BannedListChanged.disconnect(boost::bind(BannedListChanged, this)); uiInterface.NotifyBlockTip.disconnect(boost::bind(BlockTipChanged, this, _1, _2)); } diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 62c9f71ac7792..2fef6131c3c8e 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -103,7 +103,7 @@ class ClientModel : public QObject public Q_SLOTS: void updateTimer(); void updateNumConnections(int numConnections); - void updateAlert(const QString &hash, int status); + void updateAlert(); void updateBanlist(); }; diff --git a/src/ui_interface.h b/src/ui_interface.h index 967d243270965..0b51d52e6576e 100644 --- a/src/ui_interface.h +++ b/src/ui_interface.h @@ -83,10 +83,9 @@ class CClientUIInterface boost::signals2::signal NotifyNumConnectionsChanged; /** - * New, updated or cancelled alert. - * @note called with lock cs_mapAlerts held. + * Status bar alerts changed. */ - boost::signals2::signal NotifyAlertChanged; + boost::signals2::signal NotifyAlertChanged; /** A wallet has been loaded. */ boost::signals2::signal LoadWallet; From 01fdfeffc4515ea43748230139a3bcee2eec3865 Mon Sep 17 00:00:00 2001 From: BtcDrak Date: Sun, 6 Mar 2016 11:15:20 +0000 Subject: [PATCH 0031/1802] Remove `-alerts` option --- src/init.cpp | 3 --- src/main.cpp | 1 - src/main.h | 3 --- 3 files changed, 7 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index a39256c6e3220..b430bcd585446 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -315,7 +315,6 @@ std::string HelpMessage(HelpMessageMode mode) string strUsage = HelpMessageGroup(_("Options:")); strUsage += HelpMessageOpt("-?", _("Print this help message and exit")); strUsage += HelpMessageOpt("-version", _("Print version and exit")); - strUsage += HelpMessageOpt("-alerts", strprintf(_("Receive and display P2P network alerts (default: %u)"), DEFAULT_ALERTS)); strUsage += HelpMessageOpt("-alertnotify=", _("Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)")); strUsage += HelpMessageOpt("-blocknotify=", _("Execute command when the best block changes (%s in cmd is replaced by block hash)")); if (showDebug) @@ -1002,8 +1001,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) fAcceptDatacarrier = GetBoolArg("-datacarrier", DEFAULT_ACCEPT_DATACARRIER); nMaxDatacarrierBytes = GetArg("-datacarriersize", nMaxDatacarrierBytes); - fAlerts = GetBoolArg("-alerts", DEFAULT_ALERTS); - // Option to startup with mocktime set (used for regression testing): SetMockTime(GetArg("-mocktime", 0)); // SetMockTime(0) is a no-op diff --git a/src/main.cpp b/src/main.cpp index 6c193a25e3bf2..e78ce4cdf72e2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -74,7 +74,6 @@ bool fCheckBlockIndex = false; bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED; size_t nCoinCacheUsage = 5000 * 300; uint64_t nPruneTarget = 0; -bool fAlerts = DEFAULT_ALERTS; int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE; bool fEnableReplacement = DEFAULT_ENABLE_REPLACEMENT; diff --git a/src/main.h b/src/main.h index 6936b5379ae4b..7ec48d9d0027b 100644 --- a/src/main.h +++ b/src/main.h @@ -42,8 +42,6 @@ class CValidationState; struct CNodeStateStats; struct LockPoints; -/** Default for accepting alerts from the P2P network. */ -static const bool DEFAULT_ALERTS = true; /** Default for DEFAULT_WHITELISTRELAY. */ static const bool DEFAULT_WHITELISTRELAY = true; /** Default for DEFAULT_WHITELISTFORCERELAY. */ @@ -155,7 +153,6 @@ extern size_t nCoinCacheUsage; extern CFeeRate minRelayTxFee; /** Absolute maximum transaction fee (in satoshis) used by wallet and mempool (rejects high fee in sendrawtransaction) */ extern CAmount maxTxFee; -extern bool fAlerts; /** If the tip is older than this (in seconds), the node is considered to be in initial block download. */ extern int64_t nMaxTipAge; extern bool fEnableReplacement; From 1b77471bd62b31b6682c5e40d2d8bf88db3034c7 Mon Sep 17 00:00:00 2001 From: BtcDrak Date: Sun, 6 Mar 2016 10:38:53 +0000 Subject: [PATCH 0032/1802] Remove alert keys --- src/chainparams.cpp | 2 -- src/chainparams.h | 3 --- 2 files changed, 5 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 35e090a0b3b3e..508c4de1670bb 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -95,7 +95,6 @@ class CMainParams : public CChainParams { pchMessageStart[1] = 0xbe; pchMessageStart[2] = 0xb4; pchMessageStart[3] = 0xd9; - vAlertPubKey = ParseHex("04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284"); nDefaultPort = 8333; nPruneAfterHeight = 100000; @@ -176,7 +175,6 @@ class CTestNetParams : public CChainParams { pchMessageStart[1] = 0x11; pchMessageStart[2] = 0x09; pchMessageStart[3] = 0x07; - vAlertPubKey = ParseHex("04302390343f91cc401d56d68b123028bf52e5fca1939df127f63c6467cdf9c8e2c14b61104cf817d0b780da337893ecc4aaff1309e536162dabbdb45200ca2b0a"); nDefaultPort = 18333; nPruneAfterHeight = 1000; diff --git a/src/chainparams.h b/src/chainparams.h index 88bc666765d80..59202f548a3ca 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -54,7 +54,6 @@ class CChainParams const Consensus::Params& GetConsensus() const { return consensus; } const CMessageHeader::MessageStartChars& MessageStart() const { return pchMessageStart; } - const std::vector& AlertKey() const { return vAlertPubKey; } int GetDefaultPort() const { return nDefaultPort; } const CBlock& GenesisBlock() const { return genesis; } @@ -80,8 +79,6 @@ class CChainParams Consensus::Params consensus; CMessageHeader::MessageStartChars pchMessageStart; - //! Raw pub key bytes for the broadcast alert signing key. - std::vector vAlertPubKey; int nDefaultPort; uint64_t nPruneAfterHeight; std::vector vSeeds; From ad7210408c5d2f7d13534da4f4ff1ff3afa82b3a Mon Sep 17 00:00:00 2001 From: BtcDrak Date: Wed, 16 Mar 2016 09:13:50 +0000 Subject: [PATCH 0033/1802] Formatting --- src/test/alert_tests.cpp | 110 +++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp index ed3cce2de43bb..70f1f12273a82 100644 --- a/src/test/alert_tests.cpp +++ b/src/test/alert_tests.cpp @@ -18,62 +18,62 @@ BOOST_FIXTURE_TEST_SUITE(Alert_tests, TestingSetup) static bool falseFunc() { return false; } BOOST_AUTO_TEST_CASE(PartitionAlert) - { - // Test PartitionCheck - CCriticalSection csDummy; - CBlockIndex indexDummy[100]; - CChainParams& params = Params(CBaseChainParams::MAIN); - int64_t nPowTargetSpacing = params.GetConsensus().nPowTargetSpacing; - - // Generate fake blockchain timestamps relative to - // an arbitrary time: - int64_t now = 1427379054; - SetMockTime(now); - for (int i = 0; i < 100; i++) - { - indexDummy[i].phashBlock = NULL; - if (i == 0) indexDummy[i].pprev = NULL; - else indexDummy[i].pprev = &indexDummy[i-1]; - indexDummy[i].nHeight = i; - indexDummy[i].nTime = now - (100-i)*nPowTargetSpacing; - // Other members don't matter, the partition check code doesn't - // use them - } - - strMiscWarning = ""; - - // Test 1: chain with blocks every nPowTargetSpacing seconds, - // as normal, no worries: - PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); - BOOST_CHECK_MESSAGE(strMiscWarning.empty(), strMiscWarning); - - // Test 2: go 3.5 hours without a block, expect a warning: - now += 3*60*60+30*60; - SetMockTime(now); - PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); - BOOST_CHECK(!strMiscWarning.empty()); - BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning); - strMiscWarning = ""; - - // Test 3: test the "partition alerts only go off once per day" - // code: - now += 60*10; - SetMockTime(now); - PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); - BOOST_CHECK(strMiscWarning.empty()); - - // Test 4: get 2.5 times as many blocks as expected: - now += 60*60*24; // Pretend it is a day later - SetMockTime(now); - int64_t quickSpacing = nPowTargetSpacing*2/5; - for (int i = 0; i < 100; i++) // Tweak chain timestamps: +{ + // Test PartitionCheck + CCriticalSection csDummy; + CBlockIndex indexDummy[100]; + CChainParams& params = Params(CBaseChainParams::MAIN); + int64_t nPowTargetSpacing = params.GetConsensus().nPowTargetSpacing; + + // Generate fake blockchain timestamps relative to + // an arbitrary time: + int64_t now = 1427379054; + SetMockTime(now); + for (int i = 0; i < 100; i++) + { + indexDummy[i].phashBlock = NULL; + if (i == 0) indexDummy[i].pprev = NULL; + else indexDummy[i].pprev = &indexDummy[i-1]; + indexDummy[i].nHeight = i; + indexDummy[i].nTime = now - (100-i)*nPowTargetSpacing; + // Other members don't matter, the partition check code doesn't + // use them + } + + strMiscWarning = ""; + + // Test 1: chain with blocks every nPowTargetSpacing seconds, + // as normal, no worries: + PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); + BOOST_CHECK_MESSAGE(strMiscWarning.empty(), strMiscWarning); + + // Test 2: go 3.5 hours without a block, expect a warning: + now += 3*60*60+30*60; + SetMockTime(now); + PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); + BOOST_CHECK(!strMiscWarning.empty()); + BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning); + strMiscWarning = ""; + + // Test 3: test the "partition alerts only go off once per day" + // code: + now += 60*10; + SetMockTime(now); + PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); + BOOST_CHECK(strMiscWarning.empty()); + + // Test 4: get 2.5 times as many blocks as expected: + now += 60*60*24; // Pretend it is a day later + SetMockTime(now); + int64_t quickSpacing = nPowTargetSpacing*2/5; + for (int i = 0; i < 100; i++) // Tweak chain timestamps: indexDummy[i].nTime = now - (100-i)*quickSpacing; - PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); - BOOST_CHECK(!strMiscWarning.empty()); - BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning); - strMiscWarning = ""; + PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); + BOOST_CHECK(!strMiscWarning.empty()); + BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning); + strMiscWarning = ""; - SetMockTime(0); - } + SetMockTime(0); +} BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file From 6601ce508eaf2d0d853f35637a946938d31e8463 Mon Sep 17 00:00:00 2001 From: Thomas Kerin Date: Fri, 18 Mar 2016 18:20:04 +0000 Subject: [PATCH 0034/1802] protocol.h/cpp: Removes NetMsgType::ALERT --- src/protocol.cpp | 2 -- src/protocol.h | 7 ------- 2 files changed, 9 deletions(-) diff --git a/src/protocol.cpp b/src/protocol.cpp index c1c7c0b96bf7c..1ddb65b796814 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -28,7 +28,6 @@ const char *GETADDR="getaddr"; const char *MEMPOOL="mempool"; const char *PING="ping"; const char *PONG="pong"; -const char *ALERT="alert"; const char *NOTFOUND="notfound"; const char *FILTERLOAD="filterload"; const char *FILTERADD="filteradd"; @@ -64,7 +63,6 @@ const static std::string allNetMessageTypes[] = { NetMsgType::MEMPOOL, NetMsgType::PING, NetMsgType::PONG, - NetMsgType::ALERT, NetMsgType::NOTFOUND, NetMsgType::FILTERLOAD, NetMsgType::FILTERADD, diff --git a/src/protocol.h b/src/protocol.h index c8b8d20eaddd5..5504f213f471c 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -163,13 +163,6 @@ extern const char *PING; * @see https://bitcoin.org/en/developer-reference#pong */ extern const char *PONG; -/** - * The alert message warns nodes of problems that may affect them or the rest - * of the network. - * @since protocol version 311. - * @see https://bitcoin.org/en/developer-reference#alert - */ -extern const char *ALERT; /** * The notfound message is a reply to a getdata message which requested an * object the receiving node does not have available for relay. From cfd519e942aecd763449157a4a5ed602bcddd3a1 Mon Sep 17 00:00:00 2001 From: BtcDrak Date: Fri, 18 Mar 2016 19:11:27 +0000 Subject: [PATCH 0035/1802] Add release note documentation --- doc/release-notes.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/release-notes.md b/doc/release-notes.md index 707f2357f8c06..43e1e3fb9aabb 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -51,6 +51,8 @@ The following outputs are affected by this change: ### P2P protocol and network code +The p2p alert system has been removed in #7692 and the 'alert' message is no longer supported. + ### Validation ### Build system From c90036f6645dea7c19e033c11240567371407017 Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Thu, 17 Mar 2016 17:23:33 -0700 Subject: [PATCH 0036/1802] Always disconnect old nodes which request filtered connections. --- doc/bips.md | 2 +- src/init.cpp | 2 -- src/main.cpp | 2 +- src/main.h | 1 - 4 files changed, 2 insertions(+), 5 deletions(-) diff --git a/doc/bips.md b/doc/bips.md index e73add0130f3f..2552a7f03af24 100644 --- a/doc/bips.md +++ b/doc/bips.md @@ -17,6 +17,6 @@ BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.12.0**): * [`BIP 65`](https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki): The CHECKLOCKTIMEVERIFY softfork was merged in **v0.12.0** ([PR #6351](https://github.com/bitcoin/bitcoin/pull/6351)), and backported to **v0.11.2** and **v0.10.4**. Mempool-only CLTV was added in [PR #6124](https://github.com/bitcoin/bitcoin/pull/6124). * [`BIP 66`](https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki): The strict DER rules and associated version 3 blocks have been implemented since **v0.10.0** ([PR #5713](https://github.com/bitcoin/bitcoin/pull/5713)). * [`BIP 70`](https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki) [`71`](https://github.com/bitcoin/bips/blob/master/bip-0071.mediawiki) [`72`](https://github.com/bitcoin/bips/blob/master/bip-0072.mediawiki): Payment Protocol support has been available in Bitcoin Core GUI since **v0.9.0** ([PR #5216](https://github.com/bitcoin/bitcoin/pull/5216)). -* [`BIP 111`](https://github.com/bitcoin/bips/blob/master/bip-0111.mediawiki): `NODE_BLOOM` service bit added, but only enforced for peer versions `>=70011` as of **v0.12.0** ([PR #6579](https://github.com/bitcoin/bitcoin/pull/6579)). +* [`BIP 111`](https://github.com/bitcoin/bips/blob/master/bip-0111.mediawiki): `NODE_BLOOM` service bit added, and enforced for all peer versions as of **v0.13.0** ([PR #6579](https://github.com/bitcoin/bitcoin/pull/6579) and [PR #6641](https://github.com/bitcoin/bitcoin/pull/6641)). * [`BIP 125`](https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki): Opt-in full replace-by-fee signaling honoured in mempool and mining as of **v0.12.0** ([PR 6871](https://github.com/bitcoin/bitcoin/pull/6871)). * [`BIP 130`](https://github.com/bitcoin/bips/blob/master/bip-0130.mediawiki): direct headers announcement is negotiated with peer versions `>=70012` as of **v0.12.0** ([PR 6494](https://github.com/bitcoin/bitcoin/pull/6494)). diff --git a/src/init.cpp b/src/init.cpp index 637b69ab0571e..96bb26f6ece6c 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -369,8 +369,6 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-onlynet=", _("Only connect to nodes in network (ipv4, ipv6 or onion)")); strUsage += HelpMessageOpt("-permitbaremultisig", strprintf(_("Relay non-P2SH multisig (default: %u)"), DEFAULT_PERMIT_BAREMULTISIG)); strUsage += HelpMessageOpt("-peerbloomfilters", strprintf(_("Support filtering of blocks and transaction with bloom filters (default: %u)"), DEFAULT_PEERBLOOMFILTERS)); - if (showDebug) - strUsage += HelpMessageOpt("-enforcenodebloom", strprintf("Enforce minimum protocol version to limit use of bloom filters (default: %u)", DEFAULT_ENFORCENODEBLOOM)); strUsage += HelpMessageOpt("-port=", strprintf(_("Listen for connections on (default: %u or testnet: %u)"), Params(CBaseChainParams::MAIN).GetDefaultPort(), Params(CBaseChainParams::TESTNET).GetDefaultPort())); strUsage += HelpMessageOpt("-proxy=", _("Connect through SOCKS5 proxy")); strUsage += HelpMessageOpt("-proxyrandomize", strprintf(_("Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)"), DEFAULT_PROXYRANDOMIZE)); diff --git a/src/main.cpp b/src/main.cpp index 027a36394c34d..d74c88d235e88 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4377,7 +4377,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, if (pfrom->nVersion >= NO_BLOOM_VERSION) { Misbehaving(pfrom->GetId(), 100); return false; - } else if (GetBoolArg("-enforcenodebloom", DEFAULT_ENFORCENODEBLOOM)) { + } else { pfrom->fDisconnect = true; return false; } diff --git a/src/main.h b/src/main.h index 5ba2be251c45b..7230d326e690e 100644 --- a/src/main.h +++ b/src/main.h @@ -122,7 +122,6 @@ static const bool DEFAULT_ENABLE_REPLACEMENT = true; static const unsigned int MAX_BLOCKS_TO_ANNOUNCE = 8; static const bool DEFAULT_PEERBLOOMFILTERS = true; -static const bool DEFAULT_ENFORCENODEBLOOM = false; struct BlockHasher { From cf5c786fc3244b6aedcc4a2f839f5248f95fafa1 Mon Sep 17 00:00:00 2001 From: fanquake Date: Sat, 19 Mar 2016 15:24:00 +0800 Subject: [PATCH 0037/1802] [build-aux] Update Boost & check macros to latest serials --- build-aux/m4/ax_boost_base.m4 | 20 +- build-aux/m4/ax_boost_program_options.m4 | 7 +- build-aux/m4/ax_boost_system.m4 | 5 +- build-aux/m4/ax_check_compile_flag.m4 | 12 +- build-aux/m4/ax_check_link_flag.m4 | 13 +- build-aux/m4/ax_check_preproc_flag.m4 | 12 +- build-aux/m4/ax_gcc_func_attribute.m4 | 8 +- build-aux/m4/ax_pthread.m4 | 537 +++++++++++++++-------- 8 files changed, 395 insertions(+), 219 deletions(-) diff --git a/build-aux/m4/ax_boost_base.m4 b/build-aux/m4/ax_boost_base.m4 index 3f24d5ddc617b..45d948933d18f 100644 --- a/build-aux/m4/ax_boost_base.m4 +++ b/build-aux/m4/ax_boost_base.m4 @@ -33,7 +33,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 23 +#serial 26 AC_DEFUN([AX_BOOST_BASE], [ @@ -95,8 +95,8 @@ if test "x$want_boost" = "xyes"; then x86_64) libsubdirs="lib64 libx32 lib lib64" ;; - ppc64|s390x|sparc64|aarch64) - libsubdirs="lib64 lib lib64" + ppc64|s390x|sparc64|aarch64|ppc64le) + libsubdirs="lib64 lib lib64 ppc64le" ;; esac @@ -170,7 +170,7 @@ if test "x$want_boost" = "xyes"; then AC_MSG_RESULT(yes) succeeded=yes found_system=yes - ],[: + ],[ ]) AC_LANG_POP([C++]) @@ -179,6 +179,10 @@ if test "x$want_boost" = "xyes"; then dnl if we found no boost with system layout we search for boost libraries dnl built and installed without the --layout=system option or for a staged(not installed) version if test "x$succeeded" != "xyes"; then + CPPFLAGS="$CPPFLAGS_SAVED" + LDFLAGS="$LDFLAGS_SAVED" + BOOST_CPPFLAGS= + BOOST_LDFLAGS= _version=0 if test "$ac_boost_path" != ""; then if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then @@ -191,6 +195,12 @@ if test "x$want_boost" = "xyes"; then VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE" done + dnl if nothing found search for layout used in Windows distributions + if test -z "$BOOST_CPPFLAGS"; then + if test -d "$ac_boost_path/boost" && test -r "$ac_boost_path/boost"; then + BOOST_CPPFLAGS="-I$ac_boost_path" + fi + fi fi else if test "$cross_compiling" != yes; then @@ -253,7 +263,7 @@ if test "x$want_boost" = "xyes"; then AC_MSG_RESULT(yes) succeeded=yes found_system=yes - ],[: + ],[ ]) AC_LANG_POP([C++]) fi diff --git a/build-aux/m4/ax_boost_program_options.m4 b/build-aux/m4/ax_boost_program_options.m4 index f591441854f59..2bdb5937162e4 100644 --- a/build-aux/m4/ax_boost_program_options.m4 +++ b/build-aux/m4/ax_boost_program_options.m4 @@ -29,7 +29,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 22 +#serial 24 AC_DEFUN([AX_BOOST_PROGRAM_OPTIONS], [ @@ -63,9 +63,9 @@ AC_DEFUN([AX_BOOST_PROGRAM_OPTIONS], AC_CACHE_CHECK([whether the Boost::Program_Options library is available], ax_cv_boost_program_options, [AC_LANG_PUSH(C++) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include ]], - [[boost::program_options::options_description generic("Generic options"); + [[boost::program_options::error err("Error message"); return 0;]])], ax_cv_boost_program_options=yes, ax_cv_boost_program_options=no) AC_LANG_POP([C++]) @@ -74,7 +74,6 @@ AC_DEFUN([AX_BOOST_PROGRAM_OPTIONS], AC_DEFINE(HAVE_BOOST_PROGRAM_OPTIONS,,[define if the Boost::PROGRAM_OPTIONS library is available]) BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'` if test "x$ax_boost_user_program_options_lib" = "x"; then - ax_lib= for libextension in `ls $BOOSTLIBDIR/libboost_program_options*.so* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_program_options.*\)\.so.*$;\1;'` `ls $BOOSTLIBDIR/libboost_program_options*.dylib* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_program_options.*\)\.dylib.*$;\1;'` `ls $BOOSTLIBDIR/libboost_program_options*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_program_options.*\)\.a.*$;\1;'` ; do ax_lib=${libextension} AC_CHECK_LIB($ax_lib, exit, diff --git a/build-aux/m4/ax_boost_system.m4 b/build-aux/m4/ax_boost_system.m4 index 9c78280fcae47..1c05450cbe1d5 100644 --- a/build-aux/m4/ax_boost_system.m4 +++ b/build-aux/m4/ax_boost_system.m4 @@ -31,7 +31,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 17 +#serial 18 AC_DEFUN([AX_BOOST_SYSTEM], [ @@ -68,9 +68,10 @@ AC_DEFUN([AX_BOOST_SYSTEM], ax_cv_boost_system, [AC_LANG_PUSH([C++]) CXXFLAGS_SAVE=$CXXFLAGS + CXXFLAGS= AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include ]], - [[boost::system::system_category]])], + [[boost::system::error_category *a = 0;]])], ax_cv_boost_system=yes, ax_cv_boost_system=no) CXXFLAGS=$CXXFLAGS_SAVE AC_LANG_POP([C++]) diff --git a/build-aux/m4/ax_check_compile_flag.m4 b/build-aux/m4/ax_check_compile_flag.m4 index c3a8d695a1bcd..ca3639715e724 100644 --- a/build-aux/m4/ax_check_compile_flag.m4 +++ b/build-aux/m4/ax_check_compile_flag.m4 @@ -4,7 +4,7 @@ # # SYNOPSIS # -# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS]) +# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) # # DESCRIPTION # @@ -19,6 +19,8 @@ # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to # force the compiler to issue an error when a bad flag is given. # +# INPUT gives an alternative input source to AC_COMPILE_IFELSE. +# # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this # macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. # @@ -53,19 +55,19 @@ # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. -#serial 2 +#serial 4 AC_DEFUN([AX_CHECK_COMPILE_FLAG], -[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX +[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" - AC_COMPILE_IFELSE([AC_LANG_PROGRAM()], + AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], [AS_VAR_SET(CACHEVAR,[yes])], [AS_VAR_SET(CACHEVAR,[no])]) _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) -AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], +AS_VAR_IF(CACHEVAR,yes, [m4_default([$2], :)], [m4_default([$3], :)]) AS_VAR_POPDEF([CACHEVAR])dnl diff --git a/build-aux/m4/ax_check_link_flag.m4 b/build-aux/m4/ax_check_link_flag.m4 index e2d0d363e4c4a..eb01a6ce135ec 100644 --- a/build-aux/m4/ax_check_link_flag.m4 +++ b/build-aux/m4/ax_check_link_flag.m4 @@ -4,7 +4,7 @@ # # SYNOPSIS # -# AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS]) +# AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) # # DESCRIPTION # @@ -19,6 +19,8 @@ # EXTRA-FLAGS FLAG". This can for example be used to force the linker to # issue an error when a bad flag is given. # +# INPUT gives an alternative input source to AC_LINK_IFELSE. +# # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this # macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG. # @@ -53,18 +55,19 @@ # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. -#serial 2 +#serial 4 AC_DEFUN([AX_CHECK_LINK_FLAG], -[AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl +[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF +AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [ ax_check_save_flags=$LDFLAGS LDFLAGS="$LDFLAGS $4 $1" - AC_LINK_IFELSE([AC_LANG_PROGRAM()], + AC_LINK_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], [AS_VAR_SET(CACHEVAR,[yes])], [AS_VAR_SET(CACHEVAR,[no])]) LDFLAGS=$ax_check_save_flags]) -AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], +AS_VAR_IF(CACHEVAR,yes, [m4_default([$2], :)], [m4_default([$3], :)]) AS_VAR_POPDEF([CACHEVAR])dnl diff --git a/build-aux/m4/ax_check_preproc_flag.m4 b/build-aux/m4/ax_check_preproc_flag.m4 index b1cfef6b86dd6..ca1d5ee2b6d1a 100644 --- a/build-aux/m4/ax_check_preproc_flag.m4 +++ b/build-aux/m4/ax_check_preproc_flag.m4 @@ -4,7 +4,7 @@ # # SYNOPSIS # -# AX_CHECK_PREPROC_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS]) +# AX_CHECK_PREPROC_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) # # DESCRIPTION # @@ -19,6 +19,8 @@ # "CPPFLAGS EXTRA-FLAGS FLAG". This can for example be used to force the # preprocessor to issue an error when a bad flag is given. # +# INPUT gives an alternative input source to AC_PREPROC_IFELSE. +# # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this # macro in sync with AX_CHECK_{COMPILE,LINK}_FLAG. # @@ -53,19 +55,19 @@ # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. -#serial 2 +#serial 4 AC_DEFUN([AX_CHECK_PREPROC_FLAG], -[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX +[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]cppflags_$4_$1])dnl AC_CACHE_CHECK([whether _AC_LANG preprocessor accepts $1], CACHEVAR, [ ax_check_save_flags=$CPPFLAGS CPPFLAGS="$CPPFLAGS $4 $1" - AC_PREPROC_IFELSE([AC_LANG_PROGRAM()], + AC_PREPROC_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], [AS_VAR_SET(CACHEVAR,[yes])], [AS_VAR_SET(CACHEVAR,[no])]) CPPFLAGS=$ax_check_save_flags]) -AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], +AS_VAR_IF(CACHEVAR,yes, [m4_default([$2], :)], [m4_default([$3], :)]) AS_VAR_POPDEF([CACHEVAR])dnl diff --git a/build-aux/m4/ax_gcc_func_attribute.m4 b/build-aux/m4/ax_gcc_func_attribute.m4 index 275ca63a2c217..c788ca9bd435f 100644 --- a/build-aux/m4/ax_gcc_func_attribute.m4 +++ b/build-aux/m4/ax_gcc_func_attribute.m4 @@ -31,6 +31,7 @@ # cold # const # constructor +# constructor_priority for constructor attribute with priority # deprecated # destructor # dllexport @@ -73,7 +74,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 2 +#serial 3 AC_DEFUN([AX_GCC_FUNC_ATTRIBUTE], [ AS_VAR_PUSHDEF([ac_var], [ax_cv_have_func_attribute_$1]) @@ -103,6 +104,9 @@ AC_DEFUN([AX_GCC_FUNC_ATTRIBUTE], [ [const], [ int foo( void ) __attribute__(($1)); ], + [constructor_priority], [ + int foo( void ) __attribute__((__constructor__(65535/2))); + ], [constructor], [ int foo( void ) __attribute__(($1)); ], @@ -180,6 +184,8 @@ AC_DEFUN([AX_GCC_FUNC_ATTRIBUTE], [ [visibility], [ int foo_def( void ) __attribute__(($1("default"))); int foo_hid( void ) __attribute__(($1("hidden"))); + int foo_int( void ) __attribute__(($1("internal"))); + int foo_pro( void ) __attribute__(($1("protected"))); ], [warning], [ int foo( void ) __attribute__(($1(""))); diff --git a/build-aux/m4/ax_pthread.m4 b/build-aux/m4/ax_pthread.m4 index d383ad5c6d6a5..d218d1af73817 100644 --- a/build-aux/m4/ax_pthread.m4 +++ b/build-aux/m4/ax_pthread.m4 @@ -19,10 +19,10 @@ # is necessary on AIX to use the special cc_r compiler alias.) # # NOTE: You are assumed to not only compile your program with these flags, -# but also link it with them as well. e.g. you should link with +# but also to link with them as well. For example, you might link with # $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS # -# If you are only building threads programs, you may wish to use these +# If you are only building threaded programs, you may wish to use these # variables in your default LIBS, CFLAGS, and CC: # # LIBS="$PTHREAD_LIBS $LIBS" @@ -30,8 +30,8 @@ # CC="$PTHREAD_CC" # # In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant -# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name -# (e.g. PTHREAD_CREATE_UNDETACHED on AIX). +# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to +# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). # # Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the # PTHREAD_PRIO_INHERIT symbol is defined when compiling with @@ -82,35 +82,40 @@ # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. -#serial 21 +#serial 22 AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) AC_DEFUN([AX_PTHREAD], [ AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([AC_PROG_CC]) +AC_REQUIRE([AC_PROG_SED]) AC_LANG_PUSH([C]) ax_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h -# requires special compiler flags (e.g. on True64 or Sequent). +# requires special compiler flags (e.g. on Tru64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: -if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then - save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - save_LIBS="$LIBS" - LIBS="$PTHREAD_LIBS $LIBS" - AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) - AC_TRY_LINK_FUNC([pthread_join], [ax_pthread_ok=yes]) - AC_MSG_RESULT([$ax_pthread_ok]) - if test x"$ax_pthread_ok" = xno; then - PTHREAD_LIBS="" - PTHREAD_CFLAGS="" - fi - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" +if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then + ax_pthread_save_CC="$CC" + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"]) + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS]) + AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes]) + AC_MSG_RESULT([$ax_pthread_ok]) + if test "x$ax_pthread_ok" = "xno"; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + CC="$ax_pthread_save_CC" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" fi # We must check for the threads library under a number of different @@ -123,7 +128,7 @@ fi # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. -ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" +ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: @@ -132,186 +137,334 @@ ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mt # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) -# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) -# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) -# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) -# -pthreads: Solaris/gcc -# -mthreads: Mingw32/gcc, Lynx/gcc +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 +# (Note: HP C rejects this with "bad form for `-t' option") +# -pthreads: Solaris/gcc (Note: HP C also rejects) # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it -# doesn't hurt to check since this sometimes defines pthreads too; -# also defines -D_REENTRANT) -# ... -mt is also the pthreads flag for HP/aCC +# doesn't hurt to check since this sometimes defines pthreads and +# -D_REENTRANT too), HP C (must be checked before -lpthread, which +# is present but should not be used directly; and before -mthreads, +# because the compiler interprets this as "-mt" + "-hreads") +# -mthreads: Mingw32/gcc, Lynx/gcc # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) -case ${host_os} in - solaris*) +case $host_os in + + freebsd*) + + # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) + # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) + + ax_pthread_flags="-kthread lthread $ax_pthread_flags" + ;; + + hpux*) + + # From the cc(1) man page: "[-mt] Sets various -D flags to enable + # multi-threading and also sets -lpthread." + + ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" + ;; + + openedition*) - # On Solaris (at least, for some versions), libc contains stubbed - # (non-functional) versions of the pthreads routines, so link-based - # tests will erroneously succeed. (We need to link with -pthreads/-mt/ - # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather - # a function called by this macro, so we could check for that, but - # who knows whether they'll stub that too in a future libc.) So, - # we'll just look for -pthreads and -lpthread first: + # IBM z/OS requires a feature-test macro to be defined in order to + # enable POSIX threads at all, so give the user a hint if this is + # not set. (We don't define these ourselves, as they can affect + # other portions of the system API in unpredictable ways.) - ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags" - ;; + AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING], + [ +# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) + AX_PTHREAD_ZOS_MISSING +# endif + ], + [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])]) + ;; - darwin*) - ax_pthread_flags="-pthread $ax_pthread_flags" - ;; + solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (N.B.: The stubs are missing + # pthread_cleanup_push, or rather a function called by this macro, + # so we could check for that, but who knows whether they'll stub + # that too in a future libc.) So we'll check first for the + # standard Solaris way of linking pthreads (-mt -lpthread). + + ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags" + ;; esac -# Clang doesn't consider unrecognized options an error unless we specify -# -Werror. We throw in some extra Clang-specific options to ensure that -# this doesn't happen for GCC, which also accepts -Werror. - -AC_MSG_CHECKING([if compiler needs -Werror to reject unknown flags]) -save_CFLAGS="$CFLAGS" -ax_pthread_extra_flags="-Werror" -CFLAGS="$CFLAGS $ax_pthread_extra_flags -Wunknown-warning-option -Wsizeof-array-argument" -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int foo(void);],[foo()])], - [AC_MSG_RESULT([yes])], - [ax_pthread_extra_flags= - AC_MSG_RESULT([no])]) -CFLAGS="$save_CFLAGS" - -if test x"$ax_pthread_ok" = xno; then -for flag in $ax_pthread_flags; do - - case $flag in - none) - AC_MSG_CHECKING([whether pthreads work without any flags]) - ;; - - -*) - AC_MSG_CHECKING([whether pthreads work with $flag]) - PTHREAD_CFLAGS="$flag" - ;; - - pthread-config) - AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) - if test x"$ax_pthread_config" = xno; then continue; fi - PTHREAD_CFLAGS="`pthread-config --cflags`" - PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" - ;; - - *) - AC_MSG_CHECKING([for the pthreads library -l$flag]) - PTHREAD_LIBS="-l$flag" - ;; - esac - - save_LIBS="$LIBS" - save_CFLAGS="$CFLAGS" - LIBS="$PTHREAD_LIBS $LIBS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS $ax_pthread_extra_flags" - - # Check for various functions. We must include pthread.h, - # since some functions may be macros. (On the Sequent, we - # need a special flag -Kthread to make this header compile.) - # We check for pthread_join because it is in -lpthread on IRIX - # while pthread_create is in libc. We check for pthread_attr_init - # due to DEC craziness with -lpthreads. We check for - # pthread_cleanup_push because it is one of the few pthread - # functions on Solaris that doesn't have a non-functional libc stub. - # We try pthread_create on general principles. - AC_LINK_IFELSE([AC_LANG_PROGRAM([#include - static void routine(void *a) { a = 0; } - static void *start_routine(void *a) { return a; }], - [pthread_t th; pthread_attr_t attr; - pthread_create(&th, 0, start_routine, 0); - pthread_join(th, 0); - pthread_attr_init(&attr); - pthread_cleanup_push(routine, 0); - pthread_cleanup_pop(0) /* ; */])], - [ax_pthread_ok=yes], - []) - - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" - - AC_MSG_RESULT([$ax_pthread_ok]) - if test "x$ax_pthread_ok" = xyes; then - break; - fi - - PTHREAD_LIBS="" - PTHREAD_CFLAGS="" +# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) + +AS_IF([test "x$GCC" = "xyes"], + [ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"]) + +# The presence of a feature test macro requesting re-entrant function +# definitions is, on some systems, a strong hint that pthreads support is +# correctly enabled + +case $host_os in + darwin* | hpux* | linux* | osf* | solaris*) + ax_pthread_check_macro="_REENTRANT" + ;; + + aix* | freebsd*) + ax_pthread_check_macro="_THREAD_SAFE" + ;; + + *) + ax_pthread_check_macro="--" + ;; +esac +AS_IF([test "x$ax_pthread_check_macro" = "x--"], + [ax_pthread_check_cond=0], + [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"]) + +# Are we compiling with Clang? + +AC_CACHE_CHECK([whether $CC is Clang], + [ax_cv_PTHREAD_CLANG], + [ax_cv_PTHREAD_CLANG=no + # Note that Autoconf sets GCC=yes for Clang as well as GCC + if test "x$GCC" = "xyes"; then + AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG], + [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ +# if defined(__clang__) && defined(__llvm__) + AX_PTHREAD_CC_IS_CLANG +# endif + ], + [ax_cv_PTHREAD_CLANG=yes]) + fi + ]) +ax_pthread_clang="$ax_cv_PTHREAD_CLANG" + +ax_pthread_clang_warning=no + +# Clang needs special handling, because older versions handle the -pthread +# option in a rather... idiosyncratic way + +if test "x$ax_pthread_clang" = "xyes"; then + + # Clang takes -pthread; it has never supported any other flag + + # (Note 1: This will need to be revisited if a system that Clang + # supports has POSIX threads in a separate library. This tends not + # to be the way of modern systems, but it's conceivable.) + + # (Note 2: On some systems, notably Darwin, -pthread is not needed + # to get POSIX threads support; the API is always present and + # active. We could reasonably leave PTHREAD_CFLAGS empty. But + # -pthread does define _REENTRANT, and while the Darwin headers + # ignore this macro, third-party headers might not.) + + PTHREAD_CFLAGS="-pthread" + PTHREAD_LIBS= + + ax_pthread_ok=yes + + # However, older versions of Clang make a point of warning the user + # that, in an invocation where only linking and no compilation is + # taking place, the -pthread option has no effect ("argument unused + # during compilation"). They expect -pthread to be passed in only + # when source code is being compiled. + # + # Problem is, this is at odds with the way Automake and most other + # C build frameworks function, which is that the same flags used in + # compilation (CFLAGS) are also used in linking. Many systems + # supported by AX_PTHREAD require exactly this for POSIX threads + # support, and in fact it is often not straightforward to specify a + # flag that is used only in the compilation phase and not in + # linking. Such a scenario is extremely rare in practice. + # + # Even though use of the -pthread flag in linking would only print + # a warning, this can be a nuisance for well-run software projects + # that build with -Werror. So if the active version of Clang has + # this misfeature, we search for an option to squash it. + + AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread], + [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG], + [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown + # Create an alternate version of $ac_link that compiles and + # links in two steps (.c -> .o, .o -> exe) instead of one + # (.c -> exe), because the warning occurs only in the second + # step + ax_pthread_save_ac_link="$ac_link" + ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' + ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` + ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" + ax_pthread_save_CFLAGS="$CFLAGS" + for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do + AS_IF([test "x$ax_pthread_try" = "xunknown"], [break]) + CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" + ac_link="$ax_pthread_save_ac_link" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], + [ac_link="$ax_pthread_2step_ac_link" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], + [break]) + ]) + done + ac_link="$ax_pthread_save_ac_link" + CFLAGS="$ax_pthread_save_CFLAGS" + AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no]) + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" + ]) + + case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in + no | unknown) ;; + *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; + esac + +fi # $ax_pthread_clang = yes + +if test "x$ax_pthread_ok" = "xno"; then +for ax_pthread_try_flag in $ax_pthread_flags; do + + case $ax_pthread_try_flag in + none) + AC_MSG_CHECKING([whether pthreads work without any flags]) + ;; + + -mt,pthread) + AC_MSG_CHECKING([whether pthreads work with -mt -lpthread]) + PTHREAD_CFLAGS="-mt" + PTHREAD_LIBS="-lpthread" + ;; + + -*) + AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag]) + PTHREAD_CFLAGS="$ax_pthread_try_flag" + ;; + + pthread-config) + AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) + AS_IF([test "x$ax_pthread_config" = "xno"], [continue]) + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag]) + PTHREAD_LIBS="-l$ax_pthread_try_flag" + ;; + esac + + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include +# if $ax_pthread_check_cond +# error "$ax_pthread_check_macro must be defined" +# endif + static void routine(void *a) { a = 0; } + static void *start_routine(void *a) { return a; }], + [pthread_t th; pthread_attr_t attr; + pthread_create(&th, 0, start_routine, 0); + pthread_join(th, 0); + pthread_attr_init(&attr); + pthread_cleanup_push(routine, 0); + pthread_cleanup_pop(0) /* ; */])], + [ax_pthread_ok=yes], + []) + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + AC_MSG_RESULT([$ax_pthread_ok]) + AS_IF([test "x$ax_pthread_ok" = "xyes"], [break]) + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" done fi # Various other checks: -if test "x$ax_pthread_ok" = xyes; then - save_LIBS="$LIBS" - LIBS="$PTHREAD_LIBS $LIBS" - save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - - # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. - AC_MSG_CHECKING([for joinable pthread attribute]) - attr_name=unknown - for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do - AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], - [int attr = $attr; return attr /* ; */])], - [attr_name=$attr; break], - []) - done - AC_MSG_RESULT([$attr_name]) - if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then - AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$attr_name], - [Define to necessary symbol if this constant - uses a non-standard name on your system.]) - fi - - AC_MSG_CHECKING([if more special flags are required for pthreads]) - flag=no - case ${host_os} in - aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";; - osf* | hpux*) flag="-D_REENTRANT";; - solaris*) - if test "$GCC" = "yes"; then - flag="-D_REENTRANT" - else - # TODO: What about Clang on Solaris? - flag="-mt -D_REENTRANT" - fi - ;; - esac - AC_MSG_RESULT([$flag]) - if test "x$flag" != xno; then - PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" - fi - - AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], - [ax_cv_PTHREAD_PRIO_INHERIT], [ - AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], - [[int i = PTHREAD_PRIO_INHERIT;]])], - [ax_cv_PTHREAD_PRIO_INHERIT=yes], - [ax_cv_PTHREAD_PRIO_INHERIT=no]) - ]) - AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"], - [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])]) - - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" - - # More AIX lossage: compile with *_r variant - if test "x$GCC" != xyes; then - case $host_os in - aix*) - AS_CASE(["x/$CC"], - [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], - [#handle absolute path differently from PATH based program lookup - AS_CASE(["x$CC"], - [x/*], - [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], - [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) - ;; - esac - fi +if test "x$ax_pthread_ok" = "xyes"; then + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + AC_CACHE_CHECK([for joinable pthread attribute], + [ax_cv_PTHREAD_JOINABLE_ATTR], + [ax_cv_PTHREAD_JOINABLE_ATTR=unknown + for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], + [int attr = $ax_pthread_attr; return attr /* ; */])], + [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break], + []) + done + ]) + AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ + test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ + test "x$ax_pthread_joinable_attr_defined" != "xyes"], + [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], + [$ax_cv_PTHREAD_JOINABLE_ATTR], + [Define to necessary symbol if this constant + uses a non-standard name on your system.]) + ax_pthread_joinable_attr_defined=yes + ]) + + AC_CACHE_CHECK([whether more special flags are required for pthreads], + [ax_cv_PTHREAD_SPECIAL_FLAGS], + [ax_cv_PTHREAD_SPECIAL_FLAGS=no + case $host_os in + solaris*) + ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" + ;; + esac + ]) + AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ + test "x$ax_pthread_special_flags_added" != "xyes"], + [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" + ax_pthread_special_flags_added=yes]) + + AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], + [ax_cv_PTHREAD_PRIO_INHERIT], + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[int i = PTHREAD_PRIO_INHERIT;]])], + [ax_cv_PTHREAD_PRIO_INHERIT=yes], + [ax_cv_PTHREAD_PRIO_INHERIT=no]) + ]) + AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ + test "x$ax_pthread_prio_inherit_defined" != "xyes"], + [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.]) + ax_pthread_prio_inherit_defined=yes + ]) + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + # More AIX lossage: compile with *_r variant + if test "x$GCC" != "xyes"; then + case $host_os in + aix*) + AS_CASE(["x/$CC"], + [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], + [#handle absolute path differently from PATH based program lookup + AS_CASE(["x$CC"], + [x/*], + [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], + [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) + ;; + esac + fi fi test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" @@ -321,12 +474,12 @@ AC_SUBST([PTHREAD_CFLAGS]) AC_SUBST([PTHREAD_CC]) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: -if test x"$ax_pthread_ok" = xyes; then - ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) - : +if test "x$ax_pthread_ok" = "xyes"; then + ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) + : else - ax_pthread_ok=no - $2 + ax_pthread_ok=no + $2 fi AC_LANG_POP ])dnl AX_PTHREAD From fad13b1612b5de16d94c78c1a464d431a4f770bf Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sat, 19 Mar 2016 15:19:29 +0100 Subject: [PATCH 0038/1802] [amount] Preempt issues with negative fee rates --- src/amount.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/amount.cpp b/src/amount.cpp index d03ed5cfadb4c..68806ff062bd9 100644 --- a/src/amount.cpp +++ b/src/amount.cpp @@ -21,7 +21,7 @@ CAmount CFeeRate::GetFee(size_t nSize) const { CAmount nFee = nSatoshisPerK * nSize / 1000; - if (nFee == 0 && nSize != 0 && nSatoshisPerK != 0) + if (nFee == 0 && nSize != 0 && nSatoshisPerK > 0) nFee = CAmount(1); return nFee; From fab3890156c849e6b04309152d7a9bfcfcb98396 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 15 Nov 2015 20:41:48 +0100 Subject: [PATCH 0039/1802] [qa] rpc-test: Normalize assert() --- qa/rpc-tests/fundrawtransaction.py | 34 ++++++++++------------ qa/rpc-tests/getblocktemplate_proposals.py | 10 ++----- qa/rpc-tests/httpbasics.py | 26 ++++++++--------- qa/rpc-tests/wallet.py | 4 +-- qa/rpc-tests/zapwallettxes.py | 10 ++----- 5 files changed, 34 insertions(+), 50 deletions(-) diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py index 0287965b97f29..4458712815c57 100755 --- a/qa/rpc-tests/fundrawtransaction.py +++ b/qa/rpc-tests/fundrawtransaction.py @@ -71,7 +71,7 @@ def run_test(self): rawtxfund = self.nodes[2].fundrawtransaction(rawtx) fee = rawtxfund['fee'] dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) - assert_equal(len(dec_tx['vin']) > 0, True) #test if we have enought inputs + assert(len(dec_tx['vin']) > 0) #test if we have enought inputs ############################## # simple test with two coins # @@ -84,7 +84,7 @@ def run_test(self): rawtxfund = self.nodes[2].fundrawtransaction(rawtx) fee = rawtxfund['fee'] dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) - assert_equal(len(dec_tx['vin']) > 0, True) #test if we have enough inputs + assert(len(dec_tx['vin']) > 0) #test if we have enough inputs ############################## # simple test with two coins # @@ -97,7 +97,7 @@ def run_test(self): rawtxfund = self.nodes[2].fundrawtransaction(rawtx) fee = rawtxfund['fee'] dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) - assert_equal(len(dec_tx['vin']) > 0, True) + assert(len(dec_tx['vin']) > 0) assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '') @@ -116,7 +116,7 @@ def run_test(self): for out in dec_tx['vout']: totalOut += out['value'] - assert_equal(len(dec_tx['vin']) > 0, True) + assert(len(dec_tx['vin']) > 0) assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '') @@ -130,7 +130,7 @@ def run_test(self): utx = aUtx break - assert_equal(utx!=False, True) + assert(utx!=False) inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}] outputs = { self.nodes[0].getnewaddress() : 1.0 } @@ -159,7 +159,7 @@ def run_test(self): utx = aUtx break - assert_equal(utx!=False, True) + assert(utx!=False) inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}] outputs = { self.nodes[0].getnewaddress() : Decimal(5.0) - fee - feeTolerance } @@ -189,7 +189,7 @@ def run_test(self): utx = aUtx break - assert_equal(utx!=False, True) + assert(utx!=False) inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}] outputs = { self.nodes[0].getnewaddress() : 1.0 } @@ -234,7 +234,7 @@ def run_test(self): utx2 = aUtx - assert_equal(utx!=False, True) + assert(utx!=False) inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']},{'txid' : utx2['txid'], 'vout' : utx2['vout']} ] outputs = { self.nodes[0].getnewaddress() : 6.0 } @@ -276,7 +276,7 @@ def run_test(self): utx2 = aUtx - assert_equal(utx!=False, True) + assert(utx!=False) inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']},{'txid' : utx2['txid'], 'vout' : utx2['vout']} ] outputs = { self.nodes[0].getnewaddress() : 6.0, self.nodes[0].getnewaddress() : 1.0 } @@ -306,14 +306,11 @@ def run_test(self): rawtx = self.nodes[2].createrawtransaction(inputs, outputs) dec_tx = self.nodes[2].decoderawtransaction(rawtx) - errorString = "" try: rawtxfund = self.nodes[2].fundrawtransaction(rawtx) + raise AssertionError("Spent more than available") except JSONRPCException,e: - errorString = e.error['message'] - - assert("Insufficient" in errorString) - + assert("Insufficient" in e.error['message']) ############################################################ @@ -462,12 +459,11 @@ def run_test(self): self.is_network_split=False self.sync_all() - error = False try: self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1.2) - except: - error = True - assert(error) + raise AssertionError("Wallet unlocked without passphrase") + except JSONRPCException as e: + assert('walletpassphrase' in e.error['message']) oldBalance = self.nodes[0].getbalance() @@ -580,7 +576,7 @@ def run_test(self): assert_equal(len(res_dec["vin"]), 1) assert_equal(res_dec["vin"][0]["txid"], watchonly_txid) - assert_equal("fee" in result.keys(), True) + assert("fee" in result.keys()) assert_greater_than(result["changepos"], -1) ############################################################### diff --git a/qa/rpc-tests/getblocktemplate_proposals.py b/qa/rpc-tests/getblocktemplate_proposals.py index f83b5f140d90b..d2cb4ab8d69b9 100755 --- a/qa/rpc-tests/getblocktemplate_proposals.py +++ b/qa/rpc-tests/getblocktemplate_proposals.py @@ -120,10 +120,7 @@ def run_test(self): # Test 3: Truncated final tx lastbyte = txlist[-1].pop() - try: - assert_template(node, tmpl, txlist, 'n/a') - except JSONRPCException: - pass # Expected + assert_raises(JSONRPCException, assert_template, node, tmpl, txlist, 'n/a') txlist[-1].append(lastbyte) # Test 4: Add an invalid tx to the end (duplicate of gen tx) @@ -144,10 +141,7 @@ def run_test(self): # Test 7: Bad tx count txlist.append(b'') - try: - assert_template(node, tmpl, txlist, 'n/a') - except JSONRPCException: - pass # Expected + assert_raises(JSONRPCException, assert_template, node, tmpl, txlist, 'n/a') txlist.pop() # Test 8: Bad bits diff --git a/qa/rpc-tests/httpbasics.py b/qa/rpc-tests/httpbasics.py index eb548aee9de32..c231676ec87d7 100755 --- a/qa/rpc-tests/httpbasics.py +++ b/qa/rpc-tests/httpbasics.py @@ -37,14 +37,14 @@ def run_test(self): conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) out1 = conn.getresponse().read() - assert_equal('"error":null' in out1, True) - assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open! + assert('"error":null' in out1) + assert(conn.sock!=None) #according to http/1.1 connection must still be open! #send 2nd request without closing connection conn.request('POST', '/', '{"method": "getchaintips"}', headers) out2 = conn.getresponse().read() - assert_equal('"error":null' in out1, True) #must also response with a correct json-rpc message - assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open! + assert('"error":null' in out1) #must also response with a correct json-rpc message + assert(conn.sock!=None) #according to http/1.1 connection must still be open! conn.close() #same should be if we add keep-alive because this should be the std. behaviour @@ -54,14 +54,14 @@ def run_test(self): conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) out1 = conn.getresponse().read() - assert_equal('"error":null' in out1, True) - assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open! + assert('"error":null' in out1) + assert(conn.sock!=None) #according to http/1.1 connection must still be open! #send 2nd request without closing connection conn.request('POST', '/', '{"method": "getchaintips"}', headers) out2 = conn.getresponse().read() - assert_equal('"error":null' in out1, True) #must also response with a correct json-rpc message - assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open! + assert('"error":null' in out1) #must also response with a correct json-rpc message + assert(conn.sock!=None) #according to http/1.1 connection must still be open! conn.close() #now do the same with "Connection: close" @@ -71,8 +71,8 @@ def run_test(self): conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) out1 = conn.getresponse().read() - assert_equal('"error":null' in out1, True) - assert_equal(conn.sock!=None, False) #now the connection must be closed after the response + assert('"error":null' in out1) + assert(conn.sock==None) #now the connection must be closed after the response #node1 (2nd node) is running with disabled keep-alive option urlNode1 = urlparse.urlparse(self.nodes[1].url) @@ -83,7 +83,7 @@ def run_test(self): conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) out1 = conn.getresponse().read() - assert_equal('"error":null' in out1, True) + assert('"error":null' in out1) #node2 (third node) is running with standard keep-alive parameters which means keep-alive is on urlNode2 = urlparse.urlparse(self.nodes[2].url) @@ -94,8 +94,8 @@ def run_test(self): conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) out1 = conn.getresponse().read() - assert_equal('"error":null' in out1, True) - assert_equal(conn.sock!=None, True) #connection must be closed because bitcoind should use keep-alive by default + assert('"error":null' in out1) + assert(conn.sock!=None) #connection must be closed because bitcoind should use keep-alive by default # Check excessive request size conn = httplib.HTTPConnection(urlNode2.hostname, urlNode2.port) diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py index e52d4e766801d..f686e6be6c62d 100755 --- a/qa/rpc-tests/wallet.py +++ b/qa/rpc-tests/wallet.py @@ -252,7 +252,7 @@ def run_test (self): except JSONRPCException,e: errorString = e.error['message'] - assert_equal("Invalid amount" in errorString, True) + assert("Invalid amount" in errorString) errorString = "" try: @@ -260,7 +260,7 @@ def run_test (self): except JSONRPCException,e: errorString = e.error['message'] - assert_equal("not an integer" in errorString, True) + assert("not an integer" in errorString) #check if wallet or blochchain maintenance changes the balance self.sync_all() diff --git a/qa/rpc-tests/zapwallettxes.py b/qa/rpc-tests/zapwallettxes.py index 1ee0f79ac06ba..1ba4ded249aad 100755 --- a/qa/rpc-tests/zapwallettxes.py +++ b/qa/rpc-tests/zapwallettxes.py @@ -65,14 +65,8 @@ def run_test (self): #restart bitcoind with zapwallettxes self.nodes[0] = start_node(0,self.options.tmpdir, ["-zapwallettxes=1"]) - aException = False - try: - tx3 = self.nodes[0].gettransaction(txid3) - except JSONRPCException,e: - print e - aException = True - - assert_equal(aException, True) #there must be a expection because the unconfirmed wallettx0 must be gone by now + assert_raises(JSONRPCException, self.nodes[0].gettransaction, [txid3]) + #there must be a expection because the unconfirmed wallettx0 must be gone by now tx0 = self.nodes[0].gettransaction(txid0) assert_equal(tx0['txid'], txid0) #tx0 (confirmed) must still be available because it was confirmed From c5825d2d73ca7b0d76fb857554eea4176aed2b5f Mon Sep 17 00:00:00 2001 From: Denis Lukianov Date: Mon, 21 Mar 2016 03:16:19 +0000 Subject: [PATCH 0040/1802] Correct importaddress help reference to importpubkey --- src/wallet/rpcdump.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 9ec28e7b91449..6e50f92428e68 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -192,7 +192,7 @@ UniValue importaddress(const UniValue& params, bool fHelp) "3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n" "4. p2sh (boolean, optional, default=false) Add the P2SH version of the script as well\n" "\nNote: This call can take minutes to complete if rescan is true.\n" - "If you have the full public key, you should call importpublickey instead of this.\n" + "If you have the full public key, you should call importpubkey instead of this.\n" "\nExamples:\n" "\nImport a script with rescan\n" + HelpExampleCli("importaddress", "\"myscript\"") + From 71527a0f31ae67edad0a7fcda59c75a6ce5666ca Mon Sep 17 00:00:00 2001 From: NicolasDorier Date: Wed, 16 Mar 2016 14:30:04 +0900 Subject: [PATCH 0041/1802] Test of BIP9 fork activation of mtp, csv, sequence_lock --- qa/pull-tester/rpc-tests.py | 1 + qa/rpc-tests/bip9-softforks.py | 220 ++++++++++++++++++++++++ qa/rpc-tests/test_framework/comptool.py | 4 + 3 files changed, 225 insertions(+) create mode 100755 qa/rpc-tests/bip9-softforks.py diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index cbc10abd215e0..b32d8d93a9c25 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -119,6 +119,7 @@ 'p2p-versionbits-warning.py', ] testScriptsExt = [ + 'bip9-softforks.py', 'bip65-cltv.py', 'bip65-cltv-p2p.py', 'bip68-sequence.py', diff --git a/qa/rpc-tests/bip9-softforks.py b/qa/rpc-tests/bip9-softforks.py new file mode 100755 index 0000000000000..cbb1b7d4cee89 --- /dev/null +++ b/qa/rpc-tests/bip9-softforks.py @@ -0,0 +1,220 @@ +#!/usr/bin/env python2 +# Copyright (c) 2015 The Bitcoin Core developers +# Distributed under the MIT/X11 software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# + +from test_framework.test_framework import ComparisonTestFramework +from test_framework.util import * +from test_framework.mininode import CTransaction, NetworkThread +from test_framework.blocktools import create_coinbase, create_block +from test_framework.comptool import TestInstance, TestManager +from test_framework.script import CScript, OP_1NEGATE, OP_NOP3, OP_DROP +from binascii import hexlify, unhexlify +import cStringIO +import time +import itertools + +''' +This test is meant to exercise BIP forks +Connect to a single node. +regtest lock-in with 108/144 block signalling +activation after a further 144 blocks +mine 2 block and save coinbases for later use +mine 141 blocks to transition from DEFINED to STARTED +mine 100 blocks signalling readiness and 44 not in order to fail to change state this period +mine 108 blocks signalling readiness and 36 blocks not signalling readiness (STARTED->LOCKED_IN) +mine a further 143 blocks (LOCKED_IN) +test that enforcement has not triggered (which triggers ACTIVE) +test that enforcement has triggered +''' + + + +class BIP9SoftForksTest(ComparisonTestFramework): + + def __init__(self): + self.num_nodes = 1 + + def setup_network(self): + self.nodes = start_nodes(1, self.options.tmpdir, + extra_args=[['-debug', '-whitelist=127.0.0.1']], + binary=[self.options.testbinary]) + + def run_test(self): + self.test = TestManager(self, self.options.tmpdir) + self.test.add_all_connections(self.nodes) + NetworkThread().start() # Start up network handling in another thread + self.test.run() + + def create_transaction(self, node, coinbase, to_address, amount): + from_txid = node.getblock(coinbase)['tx'][0] + inputs = [{ "txid" : from_txid, "vout" : 0}] + outputs = { to_address : amount } + rawtx = node.createrawtransaction(inputs, outputs) + tx = CTransaction() + f = cStringIO.StringIO(unhexlify(rawtx)) + tx.deserialize(f) + tx.nVersion = 2 + return tx + + def sign_transaction(self, node, tx): + signresult = node.signrawtransaction(hexlify(tx.serialize())) + tx = CTransaction() + f = cStringIO.StringIO(unhexlify(signresult['hex'])) + tx.deserialize(f) + return tx + + def generate_blocks(self, number, version, test_blocks = []): + for i in xrange(number): + block = create_block(self.tip, create_coinbase(self.height), self.last_block_time + 1) + block.nVersion = version + block.rehash() + block.solve() + test_blocks.append([block, True]) + self.last_block_time += 1 + self.tip = block.sha256 + self.height += 1 + return test_blocks + + def get_bip9_status(self, key): + info = self.nodes[0].getblockchaininfo() + for row in info['bip9_softforks']: + if row['id'] == key: + return row + raise IndexError ('key:"%s" not found' % key) + + + def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignature): + # generate some coins for later + self.coinbase_blocks = self.nodes[0].generate(2) + self.height = 3 # height of the next block to build + self.tip = int ("0x" + self.nodes[0].getbestblockhash() + "L", 0) + self.nodeaddress = self.nodes[0].getnewaddress() + self.last_block_time = time.time() + + assert_equal(self.get_bip9_status(bipName)['status'], 'defined') + + # Test 1 + # Advance from DEFINED to STARTED + test_blocks = self.generate_blocks(141, 4) + yield TestInstance(test_blocks, sync_every_block=False) + + assert_equal(self.get_bip9_status(bipName)['status'], 'started') + + # Test 2 + # Fail to achieve LOCKED_IN 100 out of 144 signal bit 1 + # using a variety of bits to simulate multiple parallel softforks + test_blocks = self.generate_blocks(50, activated_version) # 0x20000001 (signalling ready) + test_blocks = self.generate_blocks(20, 4, test_blocks) # 0x00000004 (signalling not) + test_blocks = self.generate_blocks(50, activated_version, test_blocks) # 0x20000101 (signalling ready) + test_blocks = self.generate_blocks(24, 4, test_blocks) # 0x20010000 (signalling not) + yield TestInstance(test_blocks, sync_every_block=False) + + assert_equal(self.get_bip9_status(bipName)['status'], 'started') + + # Test 3 + # 108 out of 144 signal bit 1 to achieve LOCKED_IN + # using a variety of bits to simulate multiple parallel softforks + test_blocks = self.generate_blocks(58, activated_version) # 0x20000001 (signalling ready) + test_blocks = self.generate_blocks(26, 4, test_blocks) # 0x00000004 (signalling not) + test_blocks = self.generate_blocks(50, activated_version, test_blocks) # 0x20000101 (signalling ready) + test_blocks = self.generate_blocks(10, 4, test_blocks) # 0x20010000 (signalling not) + yield TestInstance(test_blocks, sync_every_block=False) + + assert_equal(self.get_bip9_status(bipName)['status'], 'locked_in') + + # Test 4 + # 143 more version 536870913 blocks (waiting period-1) + test_blocks = self.generate_blocks(143, 4) + yield TestInstance(test_blocks, sync_every_block=False) + + assert_equal(self.get_bip9_status(bipName)['status'], 'locked_in') + + # Test 5 + # Check that the new rule is enforced + spendtx = self.create_transaction(self.nodes[0], + self.coinbase_blocks[0], self.nodeaddress, 1.0) + invalidate(spendtx) + spendtx = self.sign_transaction(self.nodes[0], spendtx) + spendtx.rehash() + invalidatePostSignature(spendtx) + spendtx.rehash() + block = create_block(self.tip, create_coinbase(self.height), self.last_block_time + 1) + block.nVersion = activated_version + block.vtx.append(spendtx) + block.hashMerkleRoot = block.calc_merkle_root() + block.rehash() + block.solve() + + self.last_block_time += 1 + self.tip = block.sha256 + self.height += 1 + yield TestInstance([[block, True]]) + + assert_equal(self.get_bip9_status(bipName)['status'], 'active') + + # Test 6 + # Check that the new sequence lock rules are enforced + spendtx = self.create_transaction(self.nodes[0], + self.coinbase_blocks[1], self.nodeaddress, 1.0) + invalidate(spendtx) + spendtx = self.sign_transaction(self.nodes[0], spendtx) + spendtx.rehash() + invalidatePostSignature(spendtx) + spendtx.rehash() + + block = create_block(self.tip, create_coinbase(self.height), self.last_block_time + 1) + block.nVersion = 5 + block.vtx.append(spendtx) + block.hashMerkleRoot = block.calc_merkle_root() + block.rehash() + block.solve() + self.last_block_time += 1 + yield TestInstance([[block, False]]) + + # Restart all + stop_nodes(self.nodes) + wait_bitcoinds() + shutil.rmtree(self.options.tmpdir) + self.setup_chain() + self.setup_network() + self.test.clear_all_connections() + self.test.add_all_connections(self.nodes) + NetworkThread().start() # Start up network handling in another thread + + + + def get_tests(self): + for test in itertools.chain( + self.test_BIP('csv', 536870913, self.sequence_lock_invalidate, self.donothing), + self.test_BIP('csv', 536870913, self.mtp_invalidate, self.donothing), + self.test_BIP('csv', 536870913, self.donothing, self.csv_invalidate) + ): + yield test + + def donothing(self, tx): + return + + def csv_invalidate(self, tx): + '''Modify the signature in vin 0 of the tx to fail CSV + Prepends -1 CSV DROP in the scriptSig itself. + ''' + tx.vin[0].scriptSig = CScript([OP_1NEGATE, OP_NOP3, OP_DROP] + + list(CScript(tx.vin[0].scriptSig))) + + def sequence_lock_invalidate(self, tx): + '''Modify the nSequence to make it fails once sequence lock rule is activated (high timespan) + ''' + tx.vin[0].nSequence = 0x00FFFFFF + tx.nLockTime = 0 + + def mtp_invalidate(self, tx): + '''Modify the nLockTime to make it fails once MTP rule is activated + ''' + # Disable Sequence lock, Activate nLockTime + tx.vin[0].nSequence = 0x90FFFFFF + tx.nLockTime = self.last_block_time + +if __name__ == '__main__': + BIP9SoftForksTest().main() \ No newline at end of file diff --git a/qa/rpc-tests/test_framework/comptool.py b/qa/rpc-tests/test_framework/comptool.py index a4cd4d0a89780..d8fcd807f6266 100755 --- a/qa/rpc-tests/test_framework/comptool.py +++ b/qa/rpc-tests/test_framework/comptool.py @@ -193,6 +193,10 @@ def add_all_connections(self, nodes): # associated NodeConn test_node.add_connection(self.connections[-1]) + def clear_all_connections(self): + self.connections = [] + self.test_nodes = [] + def wait_for_disconnections(self): def disconnected(): return all(node.closed for node in self.test_nodes) From fe00ca758a0f1ab2db3f7441c04780630a9df11a Mon Sep 17 00:00:00 2001 From: Andrew C Date: Sat, 12 Mar 2016 11:41:51 -0500 Subject: [PATCH 0042/1802] Create generatetoaddress rpc Creates the generatetoaddress rpc which is virtually identical to the generate rpc except that it takes an argument for the address to mine to. It does not rely on wallet functionality. The mining code shared by generate and generatetoaddress has been moved to another method to reduce duplication. --- src/rpc/client.cpp | 3 ++ src/rpc/mining.cpp | 109 +++++++++++++++++++++++++++++++-------------- src/rpc/server.cpp | 1 + src/rpc/server.h | 1 + 4 files changed, 81 insertions(+), 33 deletions(-) diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 45fb6c16428b7..89420b93d7fb2 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -29,6 +29,9 @@ static const CRPCConvertParam vRPCConvertParams[] = { "getaddednodeinfo", 0 }, { "generate", 0 }, { "generate", 1 }, + { "generatetoaddress", 0 }, + { "generatetoaddress", 1 }, + { "generatetoaddress", 2 }, { "getnetworkhashps", 0 }, { "getnetworkhashps", 1 }, { "sendtoaddress", 1 }, diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index c33082fca0c04..a2abbb323d5ce 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -3,6 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "base58.h" #include "amount.h" #include "chain.h" #include "chainparams.h" @@ -93,42 +94,12 @@ UniValue getnetworkhashps(const UniValue& params, bool fHelp) return GetNetworkHashPS(params.size() > 0 ? params[0].get_int() : 120, params.size() > 1 ? params[1].get_int() : -1); } -UniValue generate(const UniValue& params, bool fHelp) +UniValue generateBlocks(boost::shared_ptr coinbaseScript, int nGenerate, uint64_t nMaxTries, bool keepScript) { - if (fHelp || params.size() < 1 || params.size() > 2) - throw runtime_error( - "generate numblocks ( maxtries )\n" - "\nMine up to numblocks blocks immediately (before the RPC call returns)\n" - "\nArguments:\n" - "1. numblocks (numeric, required) How many blocks are generated immediately.\n" - "2. maxtries (numeric, optional) How many iterations to try (default = 1000000).\n" - "\nResult\n" - "[ blockhashes ] (array) hashes of blocks generated\n" - "\nExamples:\n" - "\nGenerate 11 blocks\n" - + HelpExampleCli("generate", "11") - ); - static const int nInnerLoopCount = 0x10000; int nHeightStart = 0; int nHeightEnd = 0; int nHeight = 0; - int nGenerate = params[0].get_int(); - uint64_t nMaxTries = 1000000; - if (params.size() > 1) { - nMaxTries = params[1].get_int(); - } - - boost::shared_ptr coinbaseScript; - GetMainSignals().ScriptForMining(coinbaseScript); - - // If the keypool is exhausted, no script is returned at all. Catch this. - if (!coinbaseScript) - throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first"); - - //throw an error if no script was provided - if (coinbaseScript->reserveScript.empty()) - throw JSONRPCError(RPC_INTERNAL_ERROR, "No coinbase script available (mining requires a wallet)"); { // Don't keep cs_main locked LOCK(cs_main); @@ -164,12 +135,84 @@ UniValue generate(const UniValue& params, bool fHelp) ++nHeight; blockHashes.push_back(pblock->GetHash().GetHex()); - //mark script as important because it was used at least for one coinbase output - coinbaseScript->KeepScript(); + //mark script as important because it was used at least for one coinbase output if the script came from the wallet + if (keepScript) + { + coinbaseScript->KeepScript(); + } } return blockHashes; } +UniValue generate(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "generate numblocks ( maxtries )\n" + "\nMine up to numblocks blocks immediately (before the RPC call returns)\n" + "\nArguments:\n" + "1. numblocks (numeric, required) How many blocks are generated immediately.\n" + "2. maxtries (numeric, optional) How many iterations to try (default = 1000000).\n" + "\nResult\n" + "[ blockhashes ] (array) hashes of blocks generated\n" + "\nExamples:\n" + "\nGenerate 11 blocks\n" + + HelpExampleCli("generate", "11") + ); + + int nGenerate = params[0].get_int(); + uint64_t nMaxTries = 1000000; + if (params.size() > 1) { + nMaxTries = params[1].get_int(); + } + + boost::shared_ptr coinbaseScript; + GetMainSignals().ScriptForMining(coinbaseScript); + + // If the keypool is exhausted, no script is returned at all. Catch this. + if (!coinbaseScript) + throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first"); + + //throw an error if no script was provided + if (coinbaseScript->reserveScript.empty()) + throw JSONRPCError(RPC_INTERNAL_ERROR, "No coinbase script available (mining requires a wallet)"); + + return generateBlocks(coinbaseScript, nGenerate, nMaxTries, true); +} + +UniValue generatetoaddress(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() < 2 || params.size() > 3) + throw runtime_error( + "generatetoaddress numblocks address (maxtries)\n" + "\nMine blocks immediately to a specified address (before the RPC call returns)\n" + "\nArguments:\n" + "1. numblocks (numeric, required) How many blocks are generated immediately.\n" + "2. address (string, required) The address to send the newly generated bitcoin to.\n" + "3. maxtries (numeric, optional) How many iterations to try (default = 1000000).\n" + "\nResult\n" + "[ blockhashes ] (array) hashes of blocks generated\n" + "\nExamples:\n" + "\nGenerate 11 blocks to myaddress\n" + + HelpExampleCli("generatetoaddress", "11 \"myaddress\"") + ); + + int nGenerate = params[0].get_int(); + uint64_t nMaxTries = 1000000; + if (params.size() > 2) { + nMaxTries = params[2].get_int(); + } + + CBitcoinAddress address(params[1].get_str()); + if (!address.IsValid()) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Error: Invalid address"); + + boost::shared_ptr coinbaseScript(new CReserveScript()); + coinbaseScript->reserveScript = GetScriptForDestination(address.Get()); + + return generateBlocks(coinbaseScript, nGenerate, nMaxTries, false); +} + UniValue getmininginfo(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 0) diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 33fa1437e253b..1303a3bb1331f 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -299,6 +299,7 @@ static const CRPCCommand vRPCCommands[] = /* Coin generation */ { "generating", "generate", &generate, true }, + { "generating", "generatetoaddress", &generatetoaddress, true }, /* Raw transactions */ { "rawtransactions", "createrawtransaction", &createrawtransaction, true }, diff --git a/src/rpc/server.h b/src/rpc/server.h index 38cb32e7f234d..35e114feef3ff 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -193,6 +193,7 @@ extern UniValue listbanned(const UniValue& params, bool fHelp); extern UniValue clearbanned(const UniValue& params, bool fHelp); extern UniValue generate(const UniValue& params, bool fHelp); +extern UniValue generatetoaddress(const UniValue& params, bool fHelp); extern UniValue getnetworkhashps(const UniValue& params, bool fHelp); extern UniValue getmininginfo(const UniValue& params, bool fHelp); extern UniValue prioritisetransaction(const UniValue& params, bool fHelp); From d5c5c713e67368802b6a4ab2b6b69962364c251b Mon Sep 17 00:00:00 2001 From: Andrew C Date: Mon, 14 Mar 2016 17:54:34 -0400 Subject: [PATCH 0043/1802] RPC tests for generatetoaddress Adds two RPC tests for the generatetoaddress RPC, one in the wallet, and one when the wallet is disabled. The wallet RPC Test mines Bitcoin to another node's address and checks that that node has received the Bitcoin. The RPC test without the wallet mines Bitcoin to an arbitrary address and checks that it works. It then mines to an arbitrary invalid address and checks that that fails. --- qa/rpc-tests/disablewallet.py | 14 ++++++++++++++ qa/rpc-tests/wallet.py | 12 ++++++++++++ 2 files changed, 26 insertions(+) diff --git a/qa/rpc-tests/disablewallet.py b/qa/rpc-tests/disablewallet.py index 6964348d55a61..5af8158467969 100755 --- a/qa/rpc-tests/disablewallet.py +++ b/qa/rpc-tests/disablewallet.py @@ -29,5 +29,19 @@ def run_test (self): x = self.nodes[0].validateaddress('mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ') assert(x['isvalid'] == True) + # Checking mining to an address without a wallet + try: + self.nodes[0].generatetoaddress(1, 'mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ') + except JSONRPCException,e: + assert("Invalid address" not in e.error['message']) + assert("ProcessNewBlock, block not accepted" not in e.error['message']) + assert("Couldn't create new block" not in e.error['message']) + + try: + self.nodes[0].generatetoaddress(1, '3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy') + raise AssertionError("Must not mine to invalid address!") + except JSONRPCException,e: + assert("Invalid address" in e.error['message']) + if __name__ == '__main__': DisableWalletTest ().main () diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py index f686e6be6c62d..df176601a54b3 100755 --- a/qa/rpc-tests/wallet.py +++ b/qa/rpc-tests/wallet.py @@ -262,6 +262,18 @@ def run_test (self): assert("not an integer" in errorString) + # Mine a block from node0 to an address from node1 + cbAddr = self.nodes[1].getnewaddress() + blkHash = self.nodes[0].generatetoaddress(1, cbAddr)[0] + cbTxId = self.nodes[0].getblock(blkHash)['tx'][0] + self.sync_all() + + # Check that the txid and balance is found by node1 + try: + self.nodes[1].gettransaction(cbTxId) + except JSONRPCException,e: + assert("Invalid or non-wallet transaction id" not in e.error['message']) + #check if wallet or blochchain maintenance changes the balance self.sync_all() blocks = self.nodes[0].generate(2) From 9e072a6e66efbda7d39bf61eded21d2b324323be Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Fri, 12 Feb 2016 15:57:15 -0500 Subject: [PATCH 0044/1802] Implement "feefilter" P2P message. The "feefilter" p2p message is used to inform other nodes of your mempool min fee which is the feerate that any new transaction must meet to be accepted to your mempool. This will allow them to filter invs to you according to this feerate. --- src/init.cpp | 1 + src/main.cpp | 73 +++++++++++++++++++++++----- src/main.h | 8 ++- src/net.cpp | 20 +++++--- src/net.h | 10 +++- src/policy/fees.cpp | 19 ++++++++ src/policy/fees.h | 13 +++++ src/protocol.cpp | 4 +- src/protocol.h | 7 ++- src/rpc/rawtransaction.cpp | 5 +- src/test/txvalidationcache_tests.cpp | 2 +- src/txmempool.cpp | 10 ++++ src/txmempool.h | 1 + src/version.h | 5 +- src/wallet/wallet.cpp | 6 ++- 15 files changed, 152 insertions(+), 32 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index f53d7d3c3c548..38ac91b2af8b4 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -330,6 +330,7 @@ std::string HelpMessage(HelpMessageMode mode) } strUsage += HelpMessageOpt("-datadir=", _("Specify data directory")); strUsage += HelpMessageOpt("-dbcache=", strprintf(_("Set database cache size in megabytes (%d to %d, default: %d)"), nMinDbCache, nMaxDbCache, nDefaultDbCache)); + strUsage += HelpMessageOpt("-feefilter", strprintf(_("Tell other nodes to filter invs to us by our mempool min fee (default: %u)"), DEFAULT_FEEFILTER)); strUsage += HelpMessageOpt("-loadblock=", _("Imports blocks from external blk000??.dat file on startup")); strUsage += HelpMessageOpt("-maxorphantx=", strprintf(_("Keep at most unconnectable transactions in memory (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS)); strUsage += HelpMessageOpt("-maxmempool=", strprintf(_("Keep the transaction memory pool below megabytes (default: %u)"), DEFAULT_MAX_MEMPOOL_SIZE)); diff --git a/src/main.cpp b/src/main.cpp index fc443cfb72006..36189f4ffc628 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,10 +17,12 @@ #include "init.h" #include "merkleblock.h" #include "net.h" +#include "policy/fees.h" #include "policy/policy.h" #include "pow.h" #include "primitives/block.h" #include "primitives/transaction.h" +#include "random.h" #include "script/script.h" #include "script/sigcache.h" #include "script/standard.h" @@ -81,6 +83,7 @@ CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE); CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE; CTxMemPool mempool(::minRelayTxFee); +FeeFilterRounder filterRounder(::minRelayTxFee); struct COrphanTx { CTransaction tx; @@ -987,7 +990,7 @@ std::string FormatStateMessage(const CValidationState &state) } bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const CTransaction& tx, bool fLimitFree, - bool* pfMissingInputs, bool fOverrideMempoolLimit, const CAmount nAbsurdFee, + bool* pfMissingInputs, CFeeRate* txFeeRate, bool fOverrideMempoolLimit, const CAmount& nAbsurdFee, std::vector& vHashTxnToUncache) { const uint256 hash = tx.GetHash(); @@ -1144,6 +1147,9 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainActive.Height(), pool.HasNoInputsOf(tx), inChainInputValue, fSpendsCoinbase, nSigOps, lp); unsigned int nSize = entry.GetTxSize(); + if (txFeeRate) { + *txFeeRate = CFeeRate(nFees, nSize); + } // Check that the transaction doesn't have an excessive number of // sigops, making it impossible to mine. Since the coinbase transaction @@ -1392,10 +1398,10 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C } bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree, - bool* pfMissingInputs, bool fOverrideMempoolLimit, const CAmount nAbsurdFee) + bool* pfMissingInputs, CFeeRate* txFeeRate, bool fOverrideMempoolLimit, const CAmount nAbsurdFee) { std::vector vHashTxToUncache; - bool res = AcceptToMemoryPoolWorker(pool, state, tx, fLimitFree, pfMissingInputs, fOverrideMempoolLimit, nAbsurdFee, vHashTxToUncache); + bool res = AcceptToMemoryPoolWorker(pool, state, tx, fLimitFree, pfMissingInputs, txFeeRate, fOverrideMempoolLimit, nAbsurdFee, vHashTxToUncache); if (!res) { BOOST_FOREACH(const uint256& hashTx, vHashTxToUncache) pcoinsTip->Uncache(hashTx); @@ -2620,7 +2626,7 @@ bool static DisconnectTip(CValidationState& state, const Consensus::Params& cons // ignore validation errors in resurrected transactions list removed; CValidationState stateDummy; - if (tx.IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL, true)) { + if (tx.IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL, NULL, true)) { mempool.removeRecursive(tx, removed); } else if (mempool.exists(tx.GetHash())) { vHashUpdate.push_back(tx.GetHash()); @@ -4916,10 +4922,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, pfrom->setAskFor.erase(inv.hash); mapAlreadyAskedFor.erase(inv); - if (!AlreadyHave(inv) && AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs)) - { + CFeeRate txFeeRate = CFeeRate(0); + if (!AlreadyHave(inv) && AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs, &txFeeRate)) { mempool.check(pcoinsTip); - RelayTransaction(tx); + RelayTransaction(tx, txFeeRate); vWorkQueue.push_back(inv.hash); LogPrint("mempool", "AcceptToMemoryPool: peer=%d: accepted %s (poolsz %u txn, %u kB)\n", @@ -4950,10 +4956,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, if (setMisbehaving.count(fromPeer)) continue; - if (AcceptToMemoryPool(mempool, stateDummy, orphanTx, true, &fMissingInputs2)) - { + CFeeRate orphanFeeRate = CFeeRate(0); + if (AcceptToMemoryPool(mempool, stateDummy, orphanTx, true, &fMissingInputs2, &orphanFeeRate)) { LogPrint("mempool", " accepted orphan tx %s\n", orphanHash.ToString()); - RelayTransaction(orphanTx); + RelayTransaction(orphanTx, orphanFeeRate); vWorkQueue.push_back(orphanHash); vEraseQueue.push_back(orphanHash); } @@ -5006,7 +5012,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int nDoS = 0; if (!state.IsInvalid(nDoS) || nDoS == 0) { LogPrintf("Force relaying tx %s from whitelisted peer=%d\n", tx.GetHash().ToString(), pfrom->id); - RelayTransaction(tx); + RelayTransaction(tx, txFeeRate); } else { LogPrintf("Not relaying invalid transaction %s from whitelisted peer=%d (%s)\n", tx.GetHash().ToString(), pfrom->id, FormatStateMessage(state)); } @@ -5200,6 +5206,13 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, if (!fInMemPool) continue; // another thread removed since queryHashes, maybe... if (!pfrom->pfilter->IsRelevantAndUpdate(tx)) continue; } + if (pfrom->minFeeFilter) { + CFeeRate feeRate; + mempool.lookupFeeRate(hash, feeRate); + LOCK(pfrom->cs_feeFilter); + if (feeRate.GetFeePerK() < pfrom->minFeeFilter) + continue; + } vInv.push_back(inv); if (vInv.size() == MAX_INV_SZ) { pfrom->PushMessage(NetMsgType::INV, vInv); @@ -5362,8 +5375,19 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } } - else - { + else if (strCommand == NetMsgType::FEEFILTER) { + CAmount newFeeFilter = 0; + vRecv >> newFeeFilter; + if (MoneyRange(newFeeFilter)) { + { + LOCK(pfrom->cs_feeFilter); + pfrom->minFeeFilter = newFeeFilter; + } + LogPrint("net", "received: feefilter of %s from peer=%d\n", CFeeRate(newFeeFilter).ToString(), pfrom->id); + } + } + + else { // Ignore unknown commands for extensibility LogPrint("net", "Unknown command \"%s\" from peer=%d\n", SanitizeString(strCommand), pfrom->id); } @@ -5845,6 +5869,29 @@ bool SendMessages(CNode* pto) if (!vGetData.empty()) pto->PushMessage(NetMsgType::GETDATA, vGetData); + // + // Message: feefilter + // + // We don't want white listed peers to filter txs to us if we have -whitelistforcerelay + if (pto->nVersion >= FEEFILTER_VERSION && GetBoolArg("-feefilter", DEFAULT_FEEFILTER) && + !(pto->fWhitelisted && GetBoolArg("-whitelistforcerelay", DEFAULT_WHITELISTFORCERELAY))) { + CAmount currentFilter = mempool.GetMinFee(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFeePerK(); + int64_t timeNow = GetTimeMicros(); + if (timeNow > pto->nextSendTimeFeeFilter) { + CAmount filterToSend = filterRounder.round(currentFilter); + if (filterToSend != pto->lastSentFeeFilter) { + pto->PushMessage(NetMsgType::FEEFILTER, filterToSend); + pto->lastSentFeeFilter = filterToSend; + } + pto->nextSendTimeFeeFilter = PoissonNextSend(timeNow, AVG_FEEFILTER_BROADCAST_INTERVAL); + } + // If the fee filter has changed substantially and it's still more than MAX_FEEFILTER_CHANGE_DELAY + // until scheduled broadcast, then move the broadcast to within MAX_FEEFILTER_CHANGE_DELAY. + else if (timeNow + MAX_FEEFILTER_CHANGE_DELAY * 1000000 < pto->nextSendTimeFeeFilter && + (currentFilter < 3 * pto->lastSentFeeFilter / 4 || currentFilter > 4 * pto->lastSentFeeFilter / 3)) { + pto->nextSendTimeFeeFilter = timeNow + (insecure_rand() % MAX_FEEFILTER_CHANGE_DELAY) * 1000000; + } + } } return true; } diff --git a/src/main.h b/src/main.h index a011ba4e55b7d..0bfcfab2132e5 100644 --- a/src/main.h +++ b/src/main.h @@ -102,6 +102,10 @@ static const unsigned int AVG_ADDRESS_BROADCAST_INTERVAL = 30; /** Average delay between trickled inventory broadcasts in seconds. * Blocks, whitelisted receivers, and a random 25% of transactions bypass this. */ static const unsigned int AVG_INVENTORY_BROADCAST_INTERVAL = 5; +/** Average delay between feefilter broadcasts in seconds. */ +static const unsigned int AVG_FEEFILTER_BROADCAST_INTERVAL = 10 * 60; +/** Maximum feefilter broadcast delay after significant change. */ +static const unsigned int MAX_FEEFILTER_CHANGE_DELAY = 5 * 60; static const unsigned int DEFAULT_LIMITFREERELAY = 15; static const bool DEFAULT_RELAYPRIORITY = true; @@ -117,6 +121,8 @@ static const unsigned int DEFAULT_BANSCORE_THRESHOLD = 100; static const bool DEFAULT_TESTSAFEMODE = false; /** Default for -mempoolreplacement */ static const bool DEFAULT_ENABLE_REPLACEMENT = true; +/** Default for using fee filter */ +static const bool DEFAULT_FEEFILTER = true; /** Maximum number of headers to announce when relaying blocks with headers message.*/ static const unsigned int MAX_BLOCKS_TO_ANNOUNCE = 8; @@ -282,7 +288,7 @@ void PruneAndFlush(); /** (try to) add transaction to memory pool **/ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree, - bool* pfMissingInputs, bool fOverrideMempoolLimit=false, const CAmount nAbsurdFee=0); + bool* pfMissingInputs, CFeeRate* txFeeRate, bool fOverrideMempoolLimit=false, const CAmount nAbsurdFee=0); /** Convert CValidationState to a human-readable message for logging */ std::string FormatStateMessage(const CValidationState &state); diff --git a/src/net.cpp b/src/net.cpp index b589692d1b45f..e8cc753a486d0 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2053,20 +2053,15 @@ class CNetCleanup instance_of_cnetcleanup; - - - - - -void RelayTransaction(const CTransaction& tx) +void RelayTransaction(const CTransaction& tx, CFeeRate feerate) { CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss.reserve(10000); ss << tx; - RelayTransaction(tx, ss); + RelayTransaction(tx, feerate, ss); } -void RelayTransaction(const CTransaction& tx, const CDataStream& ss) +void RelayTransaction(const CTransaction& tx, CFeeRate feerate, const CDataStream& ss) { CInv inv(MSG_TX, tx.GetHash()); { @@ -2087,6 +2082,11 @@ void RelayTransaction(const CTransaction& tx, const CDataStream& ss) { if(!pnode->fRelayTxes) continue; + { + LOCK(pnode->cs_feeFilter); + if (feerate.GetFeePerK() < pnode->minFeeFilter) + continue; + } LOCK(pnode->cs_filter); if (pnode->pfilter) { @@ -2390,6 +2390,10 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa nPingUsecTime = 0; fPingQueued = false; nMinPingUsecTime = std::numeric_limits::max(); + minFeeFilter = 0; + lastSentFeeFilter = 0; + nextSendTimeFeeFilter = 0; + BOOST_FOREACH(const std::string &msg, getAllNetMessageTypes()) mapRecvBytesPerMsgCmd[msg] = 0; mapRecvBytesPerMsgCmd[NET_MESSAGE_COMMAND_OTHER] = 0; diff --git a/src/net.h b/src/net.h index ec296e2abacd5..ab9eb68d8577a 100644 --- a/src/net.h +++ b/src/net.h @@ -6,6 +6,7 @@ #ifndef BITCOIN_NET_H #define BITCOIN_NET_H +#include "amount.h" #include "bloom.h" #include "compat.h" #include "limitedmap.h" @@ -415,6 +416,11 @@ class CNode int64_t nMinPingUsecTime; // Whether a ping is requested. bool fPingQueued; + // Minimum fee rate with which to filter inv's to this node + CAmount minFeeFilter; + CCriticalSection cs_feeFilter; + CAmount lastSentFeeFilter; + int64_t nextSendTimeFeeFilter; CNode(SOCKET hSocketIn, const CAddress &addrIn, const std::string &addrNameIn = "", bool fInboundIn = false); ~CNode(); @@ -766,8 +772,8 @@ class CNode class CTransaction; -void RelayTransaction(const CTransaction& tx); -void RelayTransaction(const CTransaction& tx, const CDataStream& ss); +void RelayTransaction(const CTransaction& tx, CFeeRate feerate); +void RelayTransaction(const CTransaction& tx, CFeeRate feerate, const CDataStream& ss); /** Access to the (IP) address database (peers.dat) */ class CAddrDB diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index de3c060d6a6d9..7b0e8b7d08cf7 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -8,6 +8,7 @@ #include "amount.h" #include "primitives/transaction.h" +#include "random.h" #include "streams.h" #include "txmempool.h" #include "util.h" @@ -580,3 +581,21 @@ void CBlockPolicyEstimator::Read(CAutoFile& filein) priStats.Read(filein); nBestSeenHeight = nFileBestSeenHeight; } + +FeeFilterRounder::FeeFilterRounder(const CFeeRate& minIncrementalFee) +{ + CAmount minFeeLimit = minIncrementalFee.GetFeePerK() / 2; + feeset.insert(0); + for (double bucketBoundary = minFeeLimit; bucketBoundary <= MAX_FEERATE; bucketBoundary *= FEE_SPACING) { + feeset.insert(bucketBoundary); + } +} + +CAmount FeeFilterRounder::round(CAmount currentMinFee) +{ + std::set::iterator it = feeset.lower_bound(currentMinFee); + if ((it != feeset.begin() && insecure_rand() % 3 != 0) || it == feeset.end()) { + it--; + } + return *it; +} diff --git a/src/policy/fees.h b/src/policy/fees.h index 3fa31c39e745b..cdd984de7d5fc 100644 --- a/src/policy/fees.h +++ b/src/policy/fees.h @@ -286,4 +286,17 @@ class CBlockPolicyEstimator CFeeRate feeLikely, feeUnlikely; double priLikely, priUnlikely; }; + +class FeeFilterRounder +{ +public: + /** Create new FeeFilterRounder */ + FeeFilterRounder(const CFeeRate& minIncrementalFee); + + /** Quantize a minimum fee for privacy purpose before broadcast **/ + CAmount round(CAmount currentMinFee); + +private: + std::set feeset; +}; #endif /*BITCOIN_POLICYESTIMATOR_H */ diff --git a/src/protocol.cpp b/src/protocol.cpp index 1ddb65b796814..8c4bd057254a3 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -34,6 +34,7 @@ const char *FILTERADD="filteradd"; const char *FILTERCLEAR="filterclear"; const char *REJECT="reject"; const char *SENDHEADERS="sendheaders"; +const char *FEEFILTER="feefilter"; }; static const char* ppszTypeName[] = @@ -68,7 +69,8 @@ const static std::string allNetMessageTypes[] = { NetMsgType::FILTERADD, NetMsgType::FILTERCLEAR, NetMsgType::REJECT, - NetMsgType::SENDHEADERS + NetMsgType::SENDHEADERS, + NetMsgType::FEEFILTER }; const static std::vector allNetMessageTypesVec(allNetMessageTypes, allNetMessageTypes+ARRAYLEN(allNetMessageTypes)); diff --git a/src/protocol.h b/src/protocol.h index 5504f213f471c..1b049e52af8a6 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -211,7 +211,12 @@ extern const char *REJECT; * @see https://bitcoin.org/en/developer-reference#sendheaders */ extern const char *SENDHEADERS; - +/** + * The feefilter message tells the receiving peer not to inv us any txs + * which do not meet the specified min fee rate. + * @since protocol version 70013 as described by BIP133 + */ +extern const char *FEEFILTER; }; /* Get a vector of all valid message types (see above) */ diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index de89fdeb0f144..c72339313caf8 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -818,11 +818,12 @@ UniValue sendrawtransaction(const UniValue& params, bool fHelp) const CCoins* existingCoins = view.AccessCoins(hashTx); bool fHaveMempool = mempool.exists(hashTx); bool fHaveChain = existingCoins && existingCoins->nHeight < 1000000000; + CFeeRate txFeeRate = CFeeRate(0); if (!fHaveMempool && !fHaveChain) { // push to local node and sync with wallets CValidationState state; bool fMissingInputs; - if (!AcceptToMemoryPool(mempool, state, tx, false, &fMissingInputs, false, nMaxRawTxFee)) { + if (!AcceptToMemoryPool(mempool, state, tx, false, &fMissingInputs, &txFeeRate, false, nMaxRawTxFee)) { if (state.IsInvalid()) { throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason())); } else { @@ -835,7 +836,7 @@ UniValue sendrawtransaction(const UniValue& params, bool fHelp) } else if (fHaveChain) { throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain"); } - RelayTransaction(tx); + RelayTransaction(tx, txFeeRate); return hashTx.GetHex(); } diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp index c29e30792a2a9..237b26329b1c1 100644 --- a/src/test/txvalidationcache_tests.cpp +++ b/src/test/txvalidationcache_tests.cpp @@ -23,7 +23,7 @@ ToMemPool(CMutableTransaction& tx) LOCK(cs_main); CValidationState state; - return AcceptToMemoryPool(mempool, state, tx, false, NULL, true, 0); + return AcceptToMemoryPool(mempool, state, tx, false, NULL, NULL, true, 0); } BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup) diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 088e5edde5813..52c7793118331 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -771,6 +771,16 @@ bool CTxMemPool::lookup(uint256 hash, CTransaction& result) const return true; } +bool CTxMemPool::lookupFeeRate(const uint256& hash, CFeeRate& feeRate) const +{ + LOCK(cs); + indexed_transaction_set::const_iterator i = mapTx.find(hash); + if (i == mapTx.end()) + return false; + feeRate = CFeeRate(i->GetFee(), i->GetTxSize()); + return true; +} + CFeeRate CTxMemPool::estimateFee(int nBlocks) const { LOCK(cs); diff --git a/src/txmempool.h b/src/txmempool.h index 665bb44cf3e75..9dbb37dad068f 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -600,6 +600,7 @@ class CTxMemPool } bool lookup(uint256 hash, CTransaction& result) const; + bool lookupFeeRate(const uint256& hash, CFeeRate& feeRate) const; /** Estimate fee rate needed to get into the next nBlocks * If no answer can be given at nBlocks, return an estimate diff --git a/src/version.h b/src/version.h index af2eb8eab64ea..0e1d8a63ced6e 100644 --- a/src/version.h +++ b/src/version.h @@ -9,7 +9,7 @@ * network protocol versioning */ -static const int PROTOCOL_VERSION = 70012; +static const int PROTOCOL_VERSION = 70013; //! initial proto version, to be increased after version/verack negotiation static const int INIT_PROTO_VERSION = 209; @@ -36,4 +36,7 @@ static const int NO_BLOOM_VERSION = 70011; //! "sendheaders" command and announcing blocks with headers starts with this version static const int SENDHEADERS_VERSION = 70012; +//! "feefilter" tells peers to filter invs to you by fee starts with this version +static const int FEEFILTER_VERSION = 70013; + #endif // BITCOIN_VERSION_H diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 1ef055e5521c0..654e617071b2a 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1268,7 +1268,9 @@ bool CWalletTx::RelayWalletTransaction() { if (GetDepthInMainChain() == 0 && !isAbandoned() && InMempool()) { LogPrintf("Relaying wtx %s\n", GetHash().ToString()); - RelayTransaction((CTransaction)*this); + CFeeRate feeRate; + mempool.lookupFeeRate(GetHash(), feeRate); + RelayTransaction((CTransaction)*this, feeRate); return true; } } @@ -3231,5 +3233,5 @@ int CMerkleTx::GetBlocksToMaturity() const bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, CAmount nAbsurdFee) { CValidationState state; - return ::AcceptToMemoryPool(mempool, state, *this, fLimitFree, NULL, false, nAbsurdFee); + return ::AcceptToMemoryPool(mempool, state, *this, fLimitFree, NULL, NULL, false, nAbsurdFee); } From 5fa66e4682a59047d2ed2934760ccc052fd85f50 Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Fri, 4 Mar 2016 15:08:10 -0500 Subject: [PATCH 0045/1802] Create SingleNodeConnCB class for RPC tests --- qa/rpc-tests/maxuploadtarget.py | 1 - qa/rpc-tests/test_framework/comptool.py | 14 --------- qa/rpc-tests/test_framework/mininode.py | 40 +++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/qa/rpc-tests/maxuploadtarget.py b/qa/rpc-tests/maxuploadtarget.py index 2517bed4706ed..e4127500cd89b 100755 --- a/qa/rpc-tests/maxuploadtarget.py +++ b/qa/rpc-tests/maxuploadtarget.py @@ -7,7 +7,6 @@ from test_framework.mininode import * from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * -from test_framework.comptool import wait_until import time ''' diff --git a/qa/rpc-tests/test_framework/comptool.py b/qa/rpc-tests/test_framework/comptool.py index a4cd4d0a89780..e3f9b4323546c 100755 --- a/qa/rpc-tests/test_framework/comptool.py +++ b/qa/rpc-tests/test_framework/comptool.py @@ -27,20 +27,6 @@ global mininode_lock -def wait_until(predicate, attempts=float('inf'), timeout=float('inf')): - attempt = 0 - elapsed = 0 - - while attempt < attempts and elapsed < timeout: - with mininode_lock: - if predicate(): - return True - attempt += 1 - elapsed += 0.05 - time.sleep(0.05) - - return False - class RejectResult(object): ''' Outcome that expects rejection of a transaction or block. diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index 934d0c7a7557a..5b6bb190e40e1 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -1008,6 +1008,20 @@ def __repr__(self): return "msg_reject: %s %d %s [%064x]" \ % (self.message, self.code, self.reason, self.data) +# Helper function +def wait_until(predicate, attempts=float('inf'), timeout=float('inf')): + attempt = 0 + elapsed = 0 + + while attempt < attempts and elapsed < timeout: + with mininode_lock: + if predicate(): + return True + attempt += 1 + elapsed += 0.05 + time.sleep(0.05) + + return False # This is what a callback should look like for NodeConn # Reimplement the on_* functions to provide handling for events @@ -1085,6 +1099,32 @@ def on_close(self, conn): pass def on_mempool(self, conn): pass def on_pong(self, conn, message): pass +# More useful callbacks and functions for NodeConnCB's which have a single NodeConn +class SingleNodeConnCB(NodeConnCB): + def __init__(self): + NodeConnCB.__init__(self) + self.connection = None + self.ping_counter = 1 + self.last_pong = msg_pong() + + def add_connection(self, conn): + self.connection = conn + + # Wrapper for the NodeConn's send_message function + def send_message(self, message): + self.connection.send_message(message) + + def on_pong(self, conn, message): + self.last_pong = message + + # Sync up with the node + def sync_with_ping(self, timeout=30): + def received_pong(): + return (self.last_pong.nonce == self.ping_counter) + self.send_message(msg_ping(nonce=self.ping_counter)) + success = wait_until(received_pong, timeout) + self.ping_counter += 1 + return success # The actual NodeConn class # This class provides an interface for a p2p connection to a specified node From b536a6fc83ee20cfb80da8bcb5f21c664ec7b5fe Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Fri, 4 Mar 2016 16:11:49 -0500 Subject: [PATCH 0046/1802] Add p2p test for feefilter --- qa/pull-tester/rpc-tests.py | 3 +- qa/rpc-tests/p2p-feefilter.py | 99 +++++++++++++++++++++++++ qa/rpc-tests/test_framework/mininode.py | 21 +++++- 3 files changed, 121 insertions(+), 2 deletions(-) create mode 100755 qa/rpc-tests/p2p-feefilter.py diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index f15eaacbdaed8..74be96da74641 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -127,7 +127,6 @@ 'getblocktemplate_proposals.py', 'txn_doublespend.py', 'txn_clone.py --mineblock', - 'pruning.py', 'forknotify.py', 'invalidateblock.py', # 'rpcbind_test.py', #temporary, bug in libevent, see #6655 @@ -137,6 +136,8 @@ 'mempool_packages.py', 'maxuploadtarget.py', 'replace-by-fee.py', + 'p2p-feefilter.py', + 'pruning.py', # leave pruning last as it takes a REALLY long time ] #Enable ZMQ tests diff --git a/qa/rpc-tests/p2p-feefilter.py b/qa/rpc-tests/p2p-feefilter.py new file mode 100755 index 0000000000000..f85c18dcd5140 --- /dev/null +++ b/qa/rpc-tests/p2p-feefilter.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python2 +# Copyright (c) 2016 The Bitcoin Core developers +# Distributed under the MIT/X11 software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# + +from test_framework.mininode import * +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * +import time + +''' +FeeFilterTest -- test processing of feefilter messages +''' + +def hashToHex(hash): + return format(hash, '064x').decode('utf-8') + +# Wait up to 60 secs to see if the testnode has received all the expected invs +def allInvsMatch(invsExpected, testnode): + for x in xrange(60): + with mininode_lock: + if (sorted(invsExpected) == sorted(testnode.txinvs)): + return True; + time.sleep(1) + return False; + +# TestNode: bare-bones "peer". Used to track which invs are received from a node +# and to send the node feefilter messages. +class TestNode(SingleNodeConnCB): + def __init__(self): + SingleNodeConnCB.__init__(self) + self.txinvs = [] + + def on_inv(self, conn, message): + for i in message.inv: + if (i.type == 1): + self.txinvs.append(hashToHex(i.hash)) + + def clear_invs(self): + with mininode_lock: + self.txinvs = [] + + def send_filter(self, feerate): + self.send_message(msg_feefilter(feerate)) + self.sync_with_ping() + +class FeeFilterTest(BitcoinTestFramework): + def setup_network(self): + # Node1 will be used to generate txs which should be relayed from Node0 + # to our test node + self.nodes = [] + self.nodes.append(start_node(0, self.options.tmpdir, ["-debug", "-logtimemicros"])) + self.nodes.append(start_node(1, self.options.tmpdir, ["-debug", "-logtimemicros"])) + connect_nodes(self.nodes[0], 1) + + def run_test(self): + node1 = self.nodes[1] + # Get out of IBD + node1.generate(1) + sync_blocks(self.nodes) + + # Setup the p2p connections and start up the network thread. + test_node = TestNode() + connection = NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test_node) + test_node.add_connection(connection) + NetworkThread().start() + test_node.wait_for_verack() + + # Test that invs are received for all txs at feerate of 20 sat/byte + node1.settxfee(Decimal("0.00020000")) + txids = [node1.sendtoaddress(node1.getnewaddress(), 1) for x in xrange(3)] + assert(allInvsMatch(txids, test_node)) + test_node.clear_invs() + + # Set a filter of 15 sat/byte + test_node.send_filter(15000) + + # Test that txs are still being received (paying 20 sat/byte) + txids = [node1.sendtoaddress(node1.getnewaddress(), 1) for x in xrange(3)] + assert(allInvsMatch(txids, test_node)) + test_node.clear_invs() + + # Change tx fee rate to 10 sat/byte and test they are no longer received + node1.settxfee(Decimal("0.00010000")) + [node1.sendtoaddress(node1.getnewaddress(), 1) for x in xrange(3)] + sync_mempools(self.nodes) # must be sure node 0 has received all txs + time.sleep(10) # wait 10 secs to be sure its doesn't relay any + assert(allInvsMatch([], test_node)) + test_node.clear_invs() + + # Remove fee filter and check that txs are received again + test_node.send_filter(0) + txids = [node1.sendtoaddress(node1.getnewaddress(), 1) for x in xrange(3)] + assert(allInvsMatch(txids, test_node)) + test_node.clear_invs() + +if __name__ == '__main__': + FeeFilterTest().main() diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index 5b6bb190e40e1..20386c642c67b 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -1023,6 +1023,23 @@ def wait_until(predicate, attempts=float('inf'), timeout=float('inf')): return False +class msg_feefilter(object): + command = "feefilter" + + def __init__(self, feerate=0L): + self.feerate = feerate + + def deserialize(self, f): + self.feerate = struct.unpack(" Date: Fri, 4 Mar 2016 16:25:19 -0500 Subject: [PATCH 0047/1802] modify release-notes.md and bips.md --- doc/bips.md | 1 + doc/release-notes.md | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/doc/bips.md b/doc/bips.md index 2552a7f03af24..b8efabbcf251c 100644 --- a/doc/bips.md +++ b/doc/bips.md @@ -20,3 +20,4 @@ BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.12.0**): * [`BIP 111`](https://github.com/bitcoin/bips/blob/master/bip-0111.mediawiki): `NODE_BLOOM` service bit added, and enforced for all peer versions as of **v0.13.0** ([PR #6579](https://github.com/bitcoin/bitcoin/pull/6579) and [PR #6641](https://github.com/bitcoin/bitcoin/pull/6641)). * [`BIP 125`](https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki): Opt-in full replace-by-fee signaling honoured in mempool and mining as of **v0.12.0** ([PR 6871](https://github.com/bitcoin/bitcoin/pull/6871)). * [`BIP 130`](https://github.com/bitcoin/bips/blob/master/bip-0130.mediawiki): direct headers announcement is negotiated with peer versions `>=70012` as of **v0.12.0** ([PR 6494](https://github.com/bitcoin/bitcoin/pull/6494)). +* [`BIP 133`](https://github.com/bitcoin/bips/blob/master/bip-0133.mediawiki): feefilter messages are respected and sent for peer versions `>=70013` as of **v0.13.0** ([PR 7542](https://github.com/bitcoin/bitcoin/pull/7542)). diff --git a/doc/release-notes.md b/doc/release-notes.md index 43e1e3fb9aabb..806d174ebf7fc 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -53,6 +53,15 @@ The following outputs are affected by this change: The p2p alert system has been removed in #7692 and the 'alert' message is no longer supported. + +Fee filtering of invs (BIP 133) +------------------------------------ + +The optional new p2p message "feefilter" is implemented and the protocol +version is bumped to 70013. Upon receiving a feefilter message from a peer, +a node will not send invs for any transactions which do not meet the filter +feerate. [BIP 133](https://github.com/bitcoin/bips/blob/master/bip-0133.mediawiki) + ### Validation ### Build system From 25340b7cd58c3451ae91c7b501fdff70ef05ec80 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 15 Mar 2016 10:30:37 +0100 Subject: [PATCH 0048/1802] [Wallet] refactor wallet/init interaction --- src/init.cpp | 86 ++--------------------- src/init.h | 2 - src/test/test_bitcoin.cpp | 1 - src/wallet/wallet.cpp | 143 ++++++++++++++++++++++++++++---------- src/wallet/wallet.h | 11 ++- 5 files changed, 118 insertions(+), 125 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 637b69ab0571e..957583870784d 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -63,9 +63,6 @@ using namespace std; -#ifdef ENABLE_WALLET -CWallet* pwalletMain = NULL; -#endif bool fFeeEstimatesInitialized = false; static const bool DEFAULT_PROXYRANDOMIZE = true; static const bool DEFAULT_REST_ENABLE = false; @@ -946,56 +943,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) nBytesPerSigOp = GetArg("-bytespersigop", nBytesPerSigOp); #ifdef ENABLE_WALLET - if (mapArgs.count("-mintxfee")) - { - CAmount n = 0; - if (ParseMoney(mapArgs["-mintxfee"], n) && n > 0) - CWallet::minTxFee = CFeeRate(n); - else - return InitError(AmountErrMsg("mintxfee", mapArgs["-mintxfee"])); - } - if (mapArgs.count("-fallbackfee")) - { - CAmount nFeePerK = 0; - if (!ParseMoney(mapArgs["-fallbackfee"], nFeePerK)) - return InitError(strprintf(_("Invalid amount for -fallbackfee=: '%s'"), mapArgs["-fallbackfee"])); - if (nFeePerK > HIGH_TX_FEE_PER_KB) - InitWarning(_("-fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available.")); - CWallet::fallbackFee = CFeeRate(nFeePerK); - } - if (mapArgs.count("-paytxfee")) - { - CAmount nFeePerK = 0; - if (!ParseMoney(mapArgs["-paytxfee"], nFeePerK)) - return InitError(AmountErrMsg("paytxfee", mapArgs["-paytxfee"])); - if (nFeePerK > HIGH_TX_FEE_PER_KB) - InitWarning(_("-paytxfee is set very high! This is the transaction fee you will pay if you send a transaction.")); - payTxFee = CFeeRate(nFeePerK, 1000); - if (payTxFee < ::minRelayTxFee) - { - return InitError(strprintf(_("Invalid amount for -paytxfee=: '%s' (must be at least %s)"), - mapArgs["-paytxfee"], ::minRelayTxFee.ToString())); - } - } - if (mapArgs.count("-maxtxfee")) - { - CAmount nMaxFee = 0; - if (!ParseMoney(mapArgs["-maxtxfee"], nMaxFee)) - return InitError(AmountErrMsg("maxtxfee", mapArgs["-maxtxfee"])); - if (nMaxFee > HIGH_MAX_TX_FEE) - InitWarning(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction.")); - maxTxFee = nMaxFee; - if (CFeeRate(maxTxFee, 1000) < ::minRelayTxFee) - { - return InitError(strprintf(_("Invalid amount for -maxtxfee=: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"), - mapArgs["-maxtxfee"], ::minRelayTxFee.ToString())); - } - } - nTxConfirmTarget = GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET); - bSpendZeroConfChange = GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE); - fSendFreeTransactions = GetBoolArg("-sendfreetransactions", DEFAULT_SEND_FREE_TRANSACTIONS); - - std::string strWalletFile = GetArg("-wallet", DEFAULT_WALLET_DAT); + if (!CWallet::ParameterInteraction()) + return false; #endif // ENABLE_WALLET fIsBareMultisigStd = GetBoolArg("-permitbaremultisig", DEFAULT_PERMIT_BAREMULTISIG); @@ -1032,11 +981,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) return InitError(strprintf(_("Initialization sanity check failed. %s is shutting down."), _(PACKAGE_NAME))); std::string strDataDir = GetDataDir().string(); -#ifdef ENABLE_WALLET - // Wallet file must be a plain filename without a directory - if (strWalletFile != boost::filesystem::basename(strWalletFile) + boost::filesystem::extension(strWalletFile)) - return InitError(strprintf(_("Wallet %s resides outside data directory %s"), strWalletFile, strDataDir)); -#endif + // Make sure only a single Bitcoin process is using the data directory. boost::filesystem::path pathLockFile = GetDataDir() / ".lock"; FILE* file = fopen(pathLockFile.string().c_str(), "a"); // empty lock file; created if it doesn't exist. @@ -1097,20 +1042,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // ********************************************************* Step 5: verify wallet database integrity #ifdef ENABLE_WALLET if (!fDisableWallet) { - LogPrintf("Using wallet %s\n", strWalletFile); - uiInterface.InitMessage(_("Verifying wallet...")); - - std::string warningString; - std::string errorString; - - if (!CWallet::Verify(strWalletFile, warningString, errorString)) + if (!CWallet::Verify()) return false; - - if (!warningString.empty()) - InitWarning(warningString); - if (!errorString.empty()) - return InitError(errorString); - } // (!fDisableWallet) #endif // ENABLE_WALLET // ********************************************************* Step 6: network initialization @@ -1421,16 +1354,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) pwalletMain = NULL; LogPrintf("Wallet disabled!\n"); } else { - std::string warningString; - std::string errorString; - pwalletMain = CWallet::InitLoadWallet(fDisableWallet, strWalletFile, warningString, errorString); - if (!warningString.empty()) - InitWarning(warningString); - if (!errorString.empty()) - { - LogPrintf("%s", errorString); - return InitError(errorString); - } + CWallet::InitLoadWallet(); if (!pwalletMain) return false; } diff --git a/src/init.h b/src/init.h index af1b94b72a520..63e07ccb3c66a 100644 --- a/src/init.h +++ b/src/init.h @@ -16,8 +16,6 @@ namespace boost class thread_group; } // namespace boost -extern CWallet* pwalletMain; - void StartShutdown(); bool ShutdownRequested(); /** Interrupt threads */ diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index 39586d7bb4992..9159a4499feb8 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -29,7 +29,6 @@ #include CClientUIInterface uiInterface; // Declared but not defined in ui_interface.h -CWallet* pwalletMain; extern bool fPrintToConsole; extern void noui_connect(); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index bcfefa27ff269..026bf9ac598ab 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -33,6 +33,7 @@ using namespace std; +CWallet* pwalletMain = NULL; /** Transaction fee set by the user */ CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE); unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET; @@ -364,8 +365,33 @@ void CWallet::Flush(bool shutdown) bitdb.Flush(shutdown); } -bool CWallet::Verify(const string& walletFile, string& warningString, string& errorString) +bool static UIError(const std::string &str) { + uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_ERROR); + return false; +} + +void static UIWarning(const std::string &str) +{ + uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_WARNING); +} + +static std::string AmountErrMsg(const char * const optname, const std::string& strValue) +{ + return strprintf(_("Invalid amount for -%s=: '%s'"), optname, strValue); +} + +bool CWallet::Verify() +{ + std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT); + + LogPrintf("Using wallet %s\n", walletFile); + uiInterface.InitMessage(_("Verifying wallet...")); + + // Wallet file must be a plain filename without a directory + if (walletFile != boost::filesystem::basename(walletFile) + boost::filesystem::extension(walletFile)) + return UIError(strprintf(_("Wallet %s resides outside data directory %s"), walletFile, GetDataDir().string())); + if (!bitdb.Open(GetDataDir())) { // try moving the database env out of the way @@ -381,9 +407,7 @@ bool CWallet::Verify(const string& walletFile, string& warningString, string& er // try again if (!bitdb.Open(GetDataDir())) { // if it still fails, it probably means we can't even create the database env - string msg = strprintf(_("Error initializing wallet database environment %s!"), GetDataDir()); - errorString += msg; - return true; + return UIError(strprintf(_("Error initializing wallet database environment %s!"), GetDataDir())); } } @@ -399,14 +423,14 @@ bool CWallet::Verify(const string& walletFile, string& warningString, string& er CDBEnv::VerifyResult r = bitdb.Verify(walletFile, CWalletDB::Recover); if (r == CDBEnv::RECOVER_OK) { - warningString += strprintf(_("Warning: Wallet file corrupt, data salvaged!" + UIWarning(strprintf(_("Warning: Wallet file corrupt, data salvaged!" " Original %s saved as %s in %s; if" " your balance or transactions are incorrect you should" " restore from a backup."), - walletFile, "wallet.{timestamp}.bak", GetDataDir()); + walletFile, "wallet.{timestamp}.bak", GetDataDir())); } if (r == CDBEnv::RECOVER_FAIL) - errorString += strprintf(_("%s corrupt, salvage failed"), walletFile); + return UIError(strprintf(_("%s corrupt, salvage failed"), walletFile)); } return true; @@ -2992,20 +3016,20 @@ std::string CWallet::GetWalletHelpString(bool showDebug) return strUsage; } -CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWalletFile, std::string& warningString, std::string& errorString) +bool CWallet::InitLoadWallet() { + std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT); + // needed to restore wallet transaction meta data after -zapwallettxes std::vector vWtx; if (GetBoolArg("-zapwallettxes", false)) { uiInterface.InitMessage(_("Zapping all transactions from wallet...")); - CWallet *tempWallet = new CWallet(strWalletFile); + CWallet *tempWallet = new CWallet(walletFile); DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx); if (nZapWalletRet != DB_LOAD_OK) { - errorString = strprintf(_("Error loading %s: Wallet corrupted"), strWalletFile); - uiInterface.InitMessage(strprintf(_("Error loading %s: Wallet corrupted"), strWalletFile)); - return NULL; + return UIError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile)); } delete tempWallet; @@ -3016,32 +3040,27 @@ CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWall int64_t nStart = GetTimeMillis(); bool fFirstRun = true; - CWallet *walletInstance = new CWallet(strWalletFile); + CWallet *walletInstance = new CWallet(walletFile); DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun); if (nLoadWalletRet != DB_LOAD_OK) { if (nLoadWalletRet == DB_CORRUPT) - errorString += strprintf(_("Error loading %s: Wallet corrupted"), strWalletFile) + "\n"; + return UIError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile)); else if (nLoadWalletRet == DB_NONCRITICAL_ERROR) { - warningString += strprintf(_("Error reading %s! All keys read correctly, but transaction data" + UIWarning(strprintf(_("Error reading %s! All keys read correctly, but transaction data" " or address book entries might be missing or incorrect."), - strWalletFile); + walletFile)); } else if (nLoadWalletRet == DB_TOO_NEW) - errorString += strprintf(_("Error loading %s: Wallet requires newer version of %s"), - strWalletFile, _(PACKAGE_NAME)) + - "\n"; + return UIError(strprintf(_("Error loading %s: Wallet requires newer version of %s"), + walletFile, _(PACKAGE_NAME))); else if (nLoadWalletRet == DB_NEED_REWRITE) { - errorString += strprintf(_("Wallet needed to be rewritten: restart %s to complete"), _(PACKAGE_NAME)) + "\n"; - LogPrintf("%s", errorString); + return UIError(strprintf(_("Wallet needed to be rewritten: restart %s to complete"), _(PACKAGE_NAME))); } else - errorString += strprintf(_("Error loading %s"), strWalletFile) + "\n"; - - if (!errorString.empty()) - return NULL; + return UIError(strprintf(_("Error loading %s"), walletFile)); } if (GetBoolArg("-upgradewallet", fFirstRun)) @@ -3057,8 +3076,7 @@ CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWall LogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion); if (nMaxVersion < walletInstance->GetVersion()) { - errorString += _("Cannot downgrade wallet") + "\n"; - return NULL; + return UIError(_("Cannot downgrade wallet")); } walletInstance->SetMaxVersion(nMaxVersion); } @@ -3072,10 +3090,7 @@ CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWall if (walletInstance->GetKeyFromPool(newDefaultKey)) { walletInstance->SetDefaultKey(newDefaultKey); if (!walletInstance->SetAddressBook(walletInstance->vchDefaultKey.GetID(), "", "receive")) - { - errorString += _("Cannot write default address") += "\n"; - return NULL; - } + return UIError(_("Cannot write default address") += "\n"); } walletInstance->SetBestChain(chainActive.GetLocator()); @@ -3090,7 +3105,7 @@ CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWall pindexRescan = chainActive.Genesis(); else { - CWalletDB walletdb(strWalletFile); + CWalletDB walletdb(walletFile); CBlockLocator locator; if (walletdb.ReadBestBlock(locator)) pindexRescan = FindForkInGlobalIndex(chainActive, locator); @@ -3109,10 +3124,7 @@ CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWall block = block->pprev; if (pindexRescan != block) - { - errorString = _("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)"); - return NULL; - } + return UIError(_("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)")); } uiInterface.InitMessage(_("Rescanning...")); @@ -3126,7 +3138,7 @@ CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWall // Restore wallet transaction metadata after -zapwallettxes=1 if (GetBoolArg("-zapwallettxes", false) && GetArg("-zapwallettxes", "1") != "2") { - CWalletDB walletdb(strWalletFile); + CWalletDB walletdb(walletFile); BOOST_FOREACH(const CWalletTx& wtxOld, vWtx) { @@ -3150,7 +3162,62 @@ CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWall } walletInstance->SetBroadcastTransactions(GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST)); - return walletInstance; + pwalletMain = walletInstance; + return true; +} + +bool CWallet::ParameterInteraction() +{ + if (mapArgs.count("-mintxfee")) + { + CAmount n = 0; + if (ParseMoney(mapArgs["-mintxfee"], n) && n > 0) + CWallet::minTxFee = CFeeRate(n); + else + return UIError(AmountErrMsg("mintxfee", mapArgs["-mintxfee"])); + } + if (mapArgs.count("-fallbackfee")) + { + CAmount nFeePerK = 0; + if (!ParseMoney(mapArgs["-fallbackfee"], nFeePerK)) + return UIError(strprintf(_("Invalid amount for -fallbackfee=: '%s'"), mapArgs["-fallbackfee"])); + if (nFeePerK > HIGH_TX_FEE_PER_KB) + UIWarning(_("-fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available.")); + CWallet::fallbackFee = CFeeRate(nFeePerK); + } + if (mapArgs.count("-paytxfee")) + { + CAmount nFeePerK = 0; + if (!ParseMoney(mapArgs["-paytxfee"], nFeePerK)) + return UIError(AmountErrMsg("paytxfee", mapArgs["-paytxfee"])); + if (nFeePerK > HIGH_TX_FEE_PER_KB) + UIWarning(_("-paytxfee is set very high! This is the transaction fee you will pay if you send a transaction.")); + payTxFee = CFeeRate(nFeePerK, 1000); + if (payTxFee < ::minRelayTxFee) + { + return UIError(strprintf(_("Invalid amount for -paytxfee=: '%s' (must be at least %s)"), + mapArgs["-paytxfee"], ::minRelayTxFee.ToString())); + } + } + if (mapArgs.count("-maxtxfee")) + { + CAmount nMaxFee = 0; + if (!ParseMoney(mapArgs["-maxtxfee"], nMaxFee)) + return UIError(AmountErrMsg("maxtxfee", mapArgs["-maxtxfee"])); + if (nMaxFee > HIGH_MAX_TX_FEE) + UIWarning(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction.")); + maxTxFee = nMaxFee; + if (CFeeRate(maxTxFee, 1000) < ::minRelayTxFee) + { + return UIError(strprintf(_("Invalid amount for -maxtxfee=: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"), + mapArgs["-maxtxfee"], ::minRelayTxFee.ToString())); + } + } + nTxConfirmTarget = GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET); + bSpendZeroConfChange = GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE); + fSendFreeTransactions = GetBoolArg("-sendfreetransactions", DEFAULT_SEND_FREE_TRANSACTIONS); + + return true; } CKeyPool::CKeyPool() diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index d009211a923eb..257d6f2e70839 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -28,6 +28,8 @@ #include +extern CWallet* pwalletMain; + /** * Settings */ @@ -840,7 +842,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface void Flush(bool shutdown=false); //! Verify the wallet database and perform salvage if required - static bool Verify(const std::string& walletFile, std::string& warningString, std::string& errorString); + static bool Verify(); /** * Address book entry changed. @@ -875,8 +877,11 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface /* Returns the wallets help message */ static std::string GetWalletHelpString(bool showDebug); - /* initializes the wallet, returns a new CWallet instance or a null pointer in case of an error */ - static CWallet* InitLoadWallet(bool fDisableWallet, const std::string& strWalletFile, std::string& warningString, std::string& errorString); + /* Initializes the wallet, returns a new CWallet instance or a null pointer in case of an error */ + static bool InitLoadWallet(); + + /* Wallets parameter interaction */ + static bool ParameterInteraction(); }; /** A key allocated from the key pool. */ From 4856f1d6712cdb2eac8712e379fd1e351583d78f Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 22 Mar 2016 08:40:10 +0100 Subject: [PATCH 0049/1802] [Qt] Debug window: replace "Build date" with "Datadir" The build date does only makes sense for custom/self-compiled bitcoin-core versions because we are using static build-dates for our deterministic release builds. Having a quick option to get the current datadir is much more valuable for debug purposes. --- src/qt/clientmodel.cpp | 5 +++++ src/qt/clientmodel.h | 1 + src/qt/forms/debugwindow.ui | 7 +++++-- src/qt/rpcconsole.cpp | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index d3edfedff29b6..65637cd61fe73 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -193,6 +193,11 @@ QString ClientModel::formatClientStartupTime() const return QDateTime::fromTime_t(nClientStartupTime).toString(); } +QString ClientModel::dataDir() const +{ + return QString::fromStdString(GetDataDir().string()); +} + void ClientModel::updateBanlist() { banTableModel->refresh(); diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 2fef6131c3c8e..db010f05cbd65 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -76,6 +76,7 @@ class ClientModel : public QObject bool isReleaseVersion() const; QString clientName() const; QString formatClientStartupTime() const; + QString dataDir() const; private: OptionsModel *optionsModel; diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui index a5ac0a7d26b8e..c17efcf1b367a 100644 --- a/src/qt/forms/debugwindow.ui +++ b/src/qt/forms/debugwindow.ui @@ -141,12 +141,12 @@ - Build date + Datadir - + IBeamCursor @@ -156,6 +156,9 @@ Qt::PlainText + + true + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index e8ee3042dbd2d..42112c42f11ee 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -444,7 +444,7 @@ void RPCConsole::setClientModel(ClientModel *model) ui->clientVersion->setText(model->formatFullVersion()); ui->clientUserAgent->setText(model->formatSubVersion()); ui->clientName->setText(model->clientName()); - ui->buildDate->setText(model->formatBuildDate()); + ui->dataDir->setText(model->dataDir()); ui->startupTime->setText(model->formatClientStartupTime()); ui->networkName->setText(QString::fromStdString(Params().NetworkIDString())); From bb16c8894becfba8764b13d448ba6e7e7f1608c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Tue, 8 Mar 2016 00:15:17 +0000 Subject: [PATCH 0050/1802] Prevent multiple calls to CWallet::AvailableCoins --- src/wallet/wallet.cpp | 10 ++++++---- src/wallet/wallet.h | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 654e617071b2a..51a2ad78d71e8 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1841,10 +1841,9 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int return true; } -bool CWallet::SelectCoins(const CAmount& nTargetValue, set >& setCoinsRet, CAmount& nValueRet, const CCoinControl* coinControl) const +bool CWallet::SelectCoins(const vector& vAvailableCoins, const CAmount& nTargetValue, set >& setCoinsRet, CAmount& nValueRet, const CCoinControl* coinControl) const { - vector vCoins; - AvailableCoins(vCoins, true, coinControl); + vector vCoins(vAvailableCoins); // coin control -> return all selected outputs (we want all selected to go into the transaction for sure) if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs) @@ -2010,6 +2009,9 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt { LOCK2(cs_main, cs_wallet); { + std::vector vAvailableCoins; + AvailableCoins(vAvailableCoins, true, coinControl); + nFeeRet = 0; // Start with no fee and loop until there is enough fee while (true) @@ -2059,7 +2061,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt // Choose coins to use set > setCoins; CAmount nValueIn = 0; - if (!SelectCoins(nValueToSelect, setCoins, nValueIn, coinControl)) + if (!SelectCoins(vAvailableCoins, nValueToSelect, setCoins, nValueIn, coinControl)) { strFailReason = _("Insufficient funds"); return false; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index d009211a923eb..e37d972a154f2 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -544,7 +544,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface * all coins from coinControl are selected; Never select unconfirmed coins * if they are not ours */ - bool SelectCoins(const CAmount& nTargetValue, std::set >& setCoinsRet, CAmount& nValueRet, const CCoinControl *coinControl = NULL) const; + bool SelectCoins(const std::vector& vAvailableCoins, const CAmount& nTargetValue, std::set >& setCoinsRet, CAmount& nValueRet, const CCoinControl *coinControl = NULL) const; CWalletDB *pwalletdbEncryption; From f11c5a3cbd2833be124e66272aea274fda534626 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 23 Mar 2016 11:55:46 +0100 Subject: [PATCH 0051/1802] devtools: make github-merge.py use py3 This makes github-merge.py the first developer tool to go all Python 3 (for context see #7717). The changes are straightforward as the script already was `from __future__ import division,print_function,unicode_literals`. However urllib2 changed name, and json will only accept unicode data not bytes. This retains py2 compatibility for now: not strictly necessary as it's not used by the build system - but it was easy. --- contrib/devtools/github-merge.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/contrib/devtools/github-merge.py b/contrib/devtools/github-merge.py index c8dcaae268b8e..9a62fccbbb555 100755 --- a/contrib/devtools/github-merge.py +++ b/contrib/devtools/github-merge.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # Copyright (c) 2016 Bitcoin Core Developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -19,6 +19,11 @@ from sys import stdin,stdout,stderr import argparse import subprocess +import json,codecs +try: + from urllib.request import Request,urlopen +except: + from urllib2 import Request,urlopen # External tools (can be overridden using environment) GIT = os.getenv('GIT','git') @@ -38,7 +43,7 @@ def git_config_get(option, default=None): Get named configuration option from git repository. ''' try: - return subprocess.check_output([GIT,'config','--get',option]).rstrip() + return subprocess.check_output([GIT,'config','--get',option]).rstrip().decode('utf-8') except subprocess.CalledProcessError as e: return default @@ -47,18 +52,19 @@ def retrieve_pr_title(repo,pull): Retrieve pull request title from github. Return None if no title can be found, or an error happens. ''' - import urllib2,json try: - req = urllib2.Request("https://api.github.com/repos/"+repo+"/pulls/"+pull) - result = urllib2.urlopen(req) - result = json.load(result) - return result['title'] + req = Request("https://api.github.com/repos/"+repo+"/pulls/"+pull) + result = urlopen(req) + reader = codecs.getreader('utf-8') + obj = json.load(reader(result)) + return obj['title'] except Exception as e: print('Warning: unable to retrieve pull title from github: %s' % e) return None def ask_prompt(text): print(text,end=" ",file=stderr) + stderr.flush() reply = stdin.readline().rstrip() print("",file=stderr) return reply From 7eb702954ed0e297c5ded548e6c4f11f55313b7a Mon Sep 17 00:00:00 2001 From: instagibbs Date: Thu, 18 Feb 2016 16:31:12 -0800 Subject: [PATCH 0052/1802] Add importprunedfunds rpc call --- qa/pull-tester/rpc-tests.py | 2 + qa/rpc-tests/importprunedfunds.py | 119 ++++++++++++++++++++++++++++++ src/merkleblock.cpp | 14 ++-- src/merkleblock.h | 9 ++- src/rpc/rawtransaction.cpp | 3 +- src/test/bloom_tests.cpp | 23 +++--- src/test/pmt_tests.cpp | 8 +- src/wallet/rpcdump.cpp | 67 +++++++++++++++++ src/wallet/rpcwallet.cpp | 2 + 9 files changed, 224 insertions(+), 23 deletions(-) create mode 100755 qa/rpc-tests/importprunedfunds.py diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index 74be96da74641..10b51fef7a718 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -116,6 +116,7 @@ 'invalidtxrequest.py', 'abandonconflict.py', 'p2p-versionbits-warning.py', + 'importprunedfunds.py', ] testScriptsExt = [ 'bip65-cltv.py', @@ -127,6 +128,7 @@ 'getblocktemplate_proposals.py', 'txn_doublespend.py', 'txn_clone.py --mineblock', + 'pruning.py', 'forknotify.py', 'invalidateblock.py', # 'rpcbind_test.py', #temporary, bug in libevent, see #6655 diff --git a/qa/rpc-tests/importprunedfunds.py b/qa/rpc-tests/importprunedfunds.py new file mode 100755 index 0000000000000..bac144cd75aef --- /dev/null +++ b/qa/rpc-tests/importprunedfunds.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python2 +# Copyright (c) 2014-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * +import decimal + +class ImportPrunedFundsTest(BitcoinTestFramework): + + def setup_chain(self): + print("Initializing test directory "+self.options.tmpdir) + initialize_chain_clean(self.options.tmpdir, 4) + + def setup_network(self, split=False): + self.nodes = start_nodes(2, self.options.tmpdir) + connect_nodes_bi(self.nodes,0,1) + self.is_network_split=False + self.sync_all() + + def run_test (self): + import time + begintime = int(time.time()) + + print "Mining blocks..." + self.nodes[0].generate(101) + + # sync + self.sync_all() + + # address + address1 = self.nodes[0].getnewaddress() + # pubkey + address2 = self.nodes[0].getnewaddress() + address2_pubkey = self.nodes[0].validateaddress(address2)['pubkey'] # Using pubkey + # privkey + address3 = self.nodes[0].getnewaddress() + address3_privkey = self.nodes[0].dumpprivkey(address3) # Using privkey + + #Check only one address + address_info = self.nodes[0].validateaddress(address1) + assert_equal(address_info['ismine'], True) + + self.sync_all() + + #Node 1 sync test + assert_equal(self.nodes[1].getblockcount(),101) + + #Address Test - before import + address_info = self.nodes[1].validateaddress(address1) + assert_equal(address_info['iswatchonly'], False) + assert_equal(address_info['ismine'], False) + + address_info = self.nodes[1].validateaddress(address2) + assert_equal(address_info['iswatchonly'], False) + assert_equal(address_info['ismine'], False) + + address_info = self.nodes[1].validateaddress(address3) + assert_equal(address_info['iswatchonly'], False) + assert_equal(address_info['ismine'], False) + + #Send funds to self + txnid1 = self.nodes[0].sendtoaddress(address1, 0.1) + self.nodes[0].generate(1) + rawtxn1 = self.nodes[0].gettransaction(txnid1)['hex'] + proof1 = self.nodes[0].gettxoutproof([txnid1]) + + txnid2 = self.nodes[0].sendtoaddress(address2, 0.05) + self.nodes[0].generate(1) + rawtxn2 = self.nodes[0].gettransaction(txnid2)['hex'] + proof2 = self.nodes[0].gettxoutproof([txnid2]) + + + txnid3 = self.nodes[0].sendtoaddress(address3, 0.025) + self.nodes[0].generate(1) + rawtxn3 = self.nodes[0].gettransaction(txnid3)['hex'] + proof3 = self.nodes[0].gettxoutproof([txnid3]) + + self.sync_all() + + #Import with no affiliated address + try: + result1 = self.nodes[1].importprunedfunds(rawtxn1, proof1, "") + except JSONRPCException,e: + errorString = e.error['message'] + + assert('No addresses' in errorString) + + balance1 = self.nodes[1].getbalance("", 0, True) + assert_equal(balance1, Decimal(0)) + + #Import with affiliated address with no rescan + self.nodes[1].importaddress(address2, "", False) + result2 = self.nodes[1].importprunedfunds(rawtxn2, proof2, "") + balance2 = Decimal(self.nodes[1].getbalance("", 0, True)) + assert_equal(balance2, Decimal('0.05')) + + #Import with private key with no rescan + self.nodes[1].importprivkey(address3_privkey, "", False) + result3 = self.nodes[1].importprunedfunds(rawtxn3, proof3, "") + balance3 = Decimal(self.nodes[1].getbalance("", 0, False)) + assert_equal(balance3, Decimal('0.025')) + balance3 = Decimal(self.nodes[1].getbalance("", 0, True)) + assert_equal(balance3, Decimal('0.075')) + + #Addresses Test - after import + address_info = self.nodes[1].validateaddress(address1) + assert_equal(address_info['iswatchonly'], False) + assert_equal(address_info['ismine'], False) + address_info = self.nodes[1].validateaddress(address2) + assert_equal(address_info['iswatchonly'], True) + assert_equal(address_info['ismine'], False) + address_info = self.nodes[1].validateaddress(address3) + assert_equal(address_info['iswatchonly'], False) + assert_equal(address_info['ismine'], True) + +if __name__ == '__main__': + ImportPrunedFundsTest ().main () diff --git a/src/merkleblock.cpp b/src/merkleblock.cpp index 8447f924e4d55..dca4973cc4d88 100644 --- a/src/merkleblock.cpp +++ b/src/merkleblock.cpp @@ -95,7 +95,7 @@ void CPartialMerkleTree::TraverseAndBuild(int height, unsigned int pos, const st } } -uint256 CPartialMerkleTree::TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector &vMatch) { +uint256 CPartialMerkleTree::TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector &vMatch, std::vector &vnIndex) { if (nBitsUsed >= vBits.size()) { // overflowed the bits array - failure fBad = true; @@ -110,14 +110,16 @@ uint256 CPartialMerkleTree::TraverseAndExtract(int height, unsigned int pos, uns return uint256(); } const uint256 &hash = vHash[nHashUsed++]; - if (height==0 && fParentOfMatch) // in case of height 0, we have a matched txid + if (height==0 && fParentOfMatch) { // in case of height 0, we have a matched txid vMatch.push_back(hash); + vnIndex.push_back(pos); + } return hash; } else { // otherwise, descend into the subtrees to extract matched txids and hashes - uint256 left = TraverseAndExtract(height-1, pos*2, nBitsUsed, nHashUsed, vMatch), right; + uint256 left = TraverseAndExtract(height-1, pos*2, nBitsUsed, nHashUsed, vMatch, vnIndex), right; if (pos*2+1 < CalcTreeWidth(height-1)) { - right = TraverseAndExtract(height-1, pos*2+1, nBitsUsed, nHashUsed, vMatch); + right = TraverseAndExtract(height-1, pos*2+1, nBitsUsed, nHashUsed, vMatch, vnIndex); if (right == left) { // The left and right branches should never be identical, as the transaction // hashes covered by them must each be unique. @@ -147,7 +149,7 @@ CPartialMerkleTree::CPartialMerkleTree(const std::vector &vTxid, const CPartialMerkleTree::CPartialMerkleTree() : nTransactions(0), fBad(true) {} -uint256 CPartialMerkleTree::ExtractMatches(std::vector &vMatch) { +uint256 CPartialMerkleTree::ExtractMatches(std::vector &vMatch, std::vector &vnIndex) { vMatch.clear(); // An empty set will not work if (nTransactions == 0) @@ -167,7 +169,7 @@ uint256 CPartialMerkleTree::ExtractMatches(std::vector &vMatch) { nHeight++; // traverse the partial tree unsigned int nBitsUsed = 0, nHashUsed = 0; - uint256 hashMerkleRoot = TraverseAndExtract(nHeight, 0, nBitsUsed, nHashUsed, vMatch); + uint256 hashMerkleRoot = TraverseAndExtract(nHeight, 0, nBitsUsed, nHashUsed, vMatch, vnIndex); // verify that no problems occurred during the tree traversal if (fBad) return uint256(); diff --git a/src/merkleblock.h b/src/merkleblock.h index 996cd12624fdd..835cbcce5550d 100644 --- a/src/merkleblock.h +++ b/src/merkleblock.h @@ -75,9 +75,9 @@ class CPartialMerkleTree /** * recursive function that traverses tree nodes, consuming the bits and hashes produced by TraverseAndBuild. - * it returns the hash of the respective node. + * it returns the hash of the respective node and its respective index. */ - uint256 TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector &vMatch); + uint256 TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector &vMatch, std::vector &vnIndex); public: @@ -110,10 +110,11 @@ class CPartialMerkleTree CPartialMerkleTree(); /** - * extract the matching txid's represented by this partial merkle tree. + * extract the matching txid's represented by this partial merkle tree + * and their respective indices within the partial tree. * returns the merkle root, or 0 in case of failure */ - uint256 ExtractMatches(std::vector &vMatch); + uint256 ExtractMatches(std::vector &vMatch, std::vector &vnIndex); }; diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index c72339313caf8..34dd3b30f50ff 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -303,7 +303,8 @@ UniValue verifytxoutproof(const UniValue& params, bool fHelp) UniValue res(UniValue::VARR); vector vMatch; - if (merkleBlock.txn.ExtractMatches(vMatch) != merkleBlock.header.hashMerkleRoot) + vector vIndex; + if (merkleBlock.txn.ExtractMatches(vMatch, vIndex) != merkleBlock.header.hashMerkleRoot) return res; LOCK(cs_main); diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp index 98f9de7673831..9557000ddcc11 100644 --- a/src/test/bloom_tests.cpp +++ b/src/test/bloom_tests.cpp @@ -204,7 +204,8 @@ BOOST_AUTO_TEST_CASE(merkle_block_1) BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 8); vector vMatched; - BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched) == block.hashMerkleRoot); + vector vIndex; + BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot); BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size()); for (unsigned int i = 0; i < vMatched.size(); i++) BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second); @@ -221,7 +222,7 @@ BOOST_AUTO_TEST_CASE(merkle_block_1) BOOST_CHECK(merkleBlock.vMatchedTxn[0].second == uint256S("0xdd1fd2a6fc16404faf339881a90adbde7f4f728691ac62e8f168809cdfae1053")); BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 7); - BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched) == block.hashMerkleRoot); + BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot); BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size()); for (unsigned int i = 0; i < vMatched.size(); i++) BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second); @@ -249,7 +250,8 @@ BOOST_AUTO_TEST_CASE(merkle_block_2) BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 0); vector vMatched; - BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched) == block.hashMerkleRoot); + vector vIndex; + BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot); BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size()); for (unsigned int i = 0; i < vMatched.size(); i++) BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second); @@ -275,7 +277,7 @@ BOOST_AUTO_TEST_CASE(merkle_block_2) BOOST_CHECK(merkleBlock.vMatchedTxn[3].second == uint256S("0x3c1d7e82342158e4109df2e0b6348b6e84e403d8b4046d7007663ace63cddb23")); BOOST_CHECK(merkleBlock.vMatchedTxn[3].first == 3); - BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched) == block.hashMerkleRoot); + BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot); BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size()); for (unsigned int i = 0; i < vMatched.size(); i++) BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second); @@ -303,7 +305,8 @@ BOOST_AUTO_TEST_CASE(merkle_block_2_with_update_none) BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 0); vector vMatched; - BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched) == block.hashMerkleRoot); + vector vIndex; + BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot); BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size()); for (unsigned int i = 0; i < vMatched.size(); i++) BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second); @@ -326,7 +329,7 @@ BOOST_AUTO_TEST_CASE(merkle_block_2_with_update_none) BOOST_CHECK(merkleBlock.vMatchedTxn[2].second == uint256S("0x3c1d7e82342158e4109df2e0b6348b6e84e403d8b4046d7007663ace63cddb23")); BOOST_CHECK(merkleBlock.vMatchedTxn[2].first == 3); - BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched) == block.hashMerkleRoot); + BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot); BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size()); for (unsigned int i = 0; i < vMatched.size(); i++) BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second); @@ -353,7 +356,8 @@ BOOST_AUTO_TEST_CASE(merkle_block_3_and_serialize) BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 0); vector vMatched; - BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched) == block.hashMerkleRoot); + vector vIndex; + BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot); BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size()); for (unsigned int i = 0; i < vMatched.size(); i++) BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second); @@ -392,7 +396,8 @@ BOOST_AUTO_TEST_CASE(merkle_block_4) BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 6); vector vMatched; - BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched) == block.hashMerkleRoot); + vector vIndex; + BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot); BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size()); for (unsigned int i = 0; i < vMatched.size(); i++) BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second); @@ -409,7 +414,7 @@ BOOST_AUTO_TEST_CASE(merkle_block_4) BOOST_CHECK(merkleBlock.vMatchedTxn[1] == pair); - BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched) == block.hashMerkleRoot); + BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot); BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size()); for (unsigned int i = 0; i < vMatched.size(); i++) BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second); diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index 113b9437e0490..2f3f607889498 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -88,7 +88,8 @@ BOOST_AUTO_TEST_CASE(pmt_test1) // extract merkle root and matched txids from copy std::vector vMatchTxid2; - uint256 merkleRoot2 = pmt2.ExtractMatches(vMatchTxid2); + std::vector vIndex; + uint256 merkleRoot2 = pmt2.ExtractMatches(vMatchTxid2, vIndex); // check that it has the same merkle root as the original, and a valid one BOOST_CHECK(merkleRoot1 == merkleRoot2); @@ -102,7 +103,7 @@ BOOST_AUTO_TEST_CASE(pmt_test1) CPartialMerkleTreeTester pmt3(pmt2); pmt3.Damage(); std::vector vMatchTxid3; - uint256 merkleRoot3 = pmt3.ExtractMatches(vMatchTxid3); + uint256 merkleRoot3 = pmt3.ExtractMatches(vMatchTxid3, vIndex); BOOST_CHECK(merkleRoot3 != merkleRoot1); } } @@ -122,7 +123,8 @@ BOOST_AUTO_TEST_CASE(pmt_malleability) CPartialMerkleTree tree(vTxid, vMatch); std::vector vTxid2; - BOOST_CHECK(tree.ExtractMatches(vTxid).IsNull()); + std::vector vIndex; + BOOST_CHECK(tree.ExtractMatches(vTxid, vIndex).IsNull()); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 6e50f92428e68..899ed1b3d744b 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -13,6 +13,8 @@ #include "util.h" #include "utiltime.h" #include "wallet.h" +#include "merkleblock.h" +#include "core_io.h" #include #include @@ -243,6 +245,71 @@ UniValue importaddress(const UniValue& params, bool fHelp) return NullUniValue; } +UniValue importprunedfunds(const UniValue& params, bool fHelp) +{ + if (!EnsureWalletIsAvailable(fHelp)) + return NullUniValue; + + if (fHelp || params.size() < 2 || params.size() > 3) + throw runtime_error( + "importprunedfunds\n" + "\nImports funds without rescan. Corresponding address or script must previously be included in wallet. Aimed towards pruned wallets. The end-user is responsible to import additional transactions that subsequently spend the imported outputs or rescan after the point in the blockchain the transaction is included.\n" + "\nArguments:\n" + "1. \"rawtransaction\" (string, required) A raw transaction in hex funding an already-existing address in wallet\n" + "2. \"txoutproof\" (string, required) The hex output from gettxoutproof that contains the transaction\n" + "3. \"label\" (string, optional) An optional label\n" + ); + + CTransaction tx; + if (!DecodeHexTx(tx, params[0].get_str())) + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); + uint256 hashTx = tx.GetHash(); + CWalletTx wtx(pwalletMain,tx); + + CDataStream ssMB(ParseHexV(params[1], "proof"), SER_NETWORK, PROTOCOL_VERSION); + CMerkleBlock merkleBlock; + ssMB >> merkleBlock; + + string strLabel = ""; + if (params.size() == 3) + strLabel = params[2].get_str(); + + //Search partial merkle tree in proof for our transaction and index in valid block + vector vMatch; + vector vIndex; + unsigned int txnIndex = 0; + if (merkleBlock.txn.ExtractMatches(vMatch, vIndex) == merkleBlock.header.hashMerkleRoot) { + + LOCK(cs_main); + + if (!mapBlockIndex.count(merkleBlock.header.GetHash()) || !chainActive.Contains(mapBlockIndex[merkleBlock.header.GetHash()])) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found in chain"); + + vector::const_iterator it; + if ((it = std::find(vMatch.begin(), vMatch.end(), hashTx))==vMatch.end()) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction given doesn't exist in proof"); + } + + txnIndex = vIndex[it - vMatch.begin()]; + } + else { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Something wrong with merkleblock"); + } + + wtx.nIndex = txnIndex; + wtx.hashBlock = merkleBlock.header.GetHash(); + + LOCK2(cs_main, pwalletMain->cs_wallet); + + if (pwalletMain->IsMine(tx)) { + CWalletDB walletdb(pwalletMain->strWalletFile, "r+", false); + pwalletMain->AddToWallet(wtx, false, &walletdb); + return NullUniValue; + } + + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No addresses in wallet correspond to included transaction"); +} + UniValue importpubkey(const UniValue& params, bool fHelp) { if (!EnsureWalletIsAvailable(fHelp)) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 759f894ccbe67..fbe95a14c2e34 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2503,6 +2503,7 @@ extern UniValue importaddress(const UniValue& params, bool fHelp); extern UniValue importpubkey(const UniValue& params, bool fHelp); extern UniValue dumpwallet(const UniValue& params, bool fHelp); extern UniValue importwallet(const UniValue& params, bool fHelp); +extern UniValue importprunedfunds(const UniValue& params, bool fHelp); const CRPCCommand vWalletRPCCommands[] = { // category name actor (function) okSafeMode @@ -2529,6 +2530,7 @@ const CRPCCommand vWalletRPCCommands[] = { "wallet", "importprivkey", &importprivkey, true }, { "wallet", "importwallet", &importwallet, true }, { "wallet", "importaddress", &importaddress, true }, + { "wallet", "importprunedfunds", &importprunedfunds, true }, { "wallet", "importpubkey", &importpubkey, true }, { "wallet", "keypoolrefill", &keypoolrefill, true }, { "wallet", "listaccounts", &listaccounts, false }, From f1bb13c93da5d4bedf9dd2cd7357008376e9a2b4 Mon Sep 17 00:00:00 2001 From: instagibbs Date: Mon, 7 Mar 2016 08:51:06 -0500 Subject: [PATCH 0053/1802] Added companion removeprunedfunds call. --- qa/rpc-tests/importprunedfunds.py | 21 +++++++++++++++++ src/wallet/rpcdump.cpp | 38 ++++++++++++++++++++++++++++++ src/wallet/rpcwallet.cpp | 2 ++ src/wallet/wallet.cpp | 25 ++++++++++++++++++++ src/wallet/wallet.h | 1 + src/wallet/walletdb.cpp | 39 +++++++++++++++++++++++++++++++ src/wallet/walletdb.h | 1 + 7 files changed, 127 insertions(+) diff --git a/qa/rpc-tests/importprunedfunds.py b/qa/rpc-tests/importprunedfunds.py index bac144cd75aef..5cbdcde9aa997 100755 --- a/qa/rpc-tests/importprunedfunds.py +++ b/qa/rpc-tests/importprunedfunds.py @@ -115,5 +115,26 @@ def run_test (self): assert_equal(address_info['iswatchonly'], False) assert_equal(address_info['ismine'], True) + #Remove transactions + + try: + self.nodes[1].removeprunedfunds(txnid1) + except JSONRPCException,e: + errorString = e.error['message'] + + assert('does not exist' in errorString) + + balance1 = Decimal(self.nodes[1].getbalance("", 0, True)) + assert_equal(balance1, Decimal('0.075')) + + + self.nodes[1].removeprunedfunds(txnid2) + balance2 = Decimal(self.nodes[1].getbalance("", 0, True)) + assert_equal(balance2, Decimal('0.025')) + + self.nodes[1].removeprunedfunds(txnid3) + balance3 = Decimal(self.nodes[1].getbalance("", 0, True)) + assert_equal(balance3, Decimal('0.0')) + if __name__ == '__main__': ImportPrunedFundsTest ().main () diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 899ed1b3d744b..bb40cf724536a 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -310,6 +310,44 @@ UniValue importprunedfunds(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No addresses in wallet correspond to included transaction"); } +UniValue removeprunedfunds(const UniValue& params, bool fHelp) +{ + if (!EnsureWalletIsAvailable(fHelp)) + return NullUniValue; + + if (fHelp || params.size() != 1) + throw runtime_error( + "removeprunedfunds \"txid\"\n" + "\nDeletes the specified transaction from the wallet. Meant for use with pruned wallets and as a companion to importprunedfunds. This will effect wallet balances.\n" + "\nArguments:\n" + "1. \"txid\" (string, required) The hex-encoded id of the transaction you are deleting\n" + "\nExamples:\n" + + HelpExampleCli("removeprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"") + + "\nAs a JSON-RPC call\n" + + HelpExampleRpc("removprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"") + ); + + LOCK2(cs_main, pwalletMain->cs_wallet); + + uint256 hash; + hash.SetHex(params[0].get_str()); + vector vHash; + vHash.push_back(hash); + vector vHashOut; + + if(pwalletMain->ZapSelectTx(vHash, vHashOut) != DB_LOAD_OK) { + throw JSONRPCError(RPC_INTERNAL_ERROR, "Could not properly delete the transaction."); + } + + if(vHashOut.empty()) { + throw JSONRPCError(RPC_INTERNAL_ERROR, "Transaction does not exist in wallet."); + } + + ThreadFlushWalletDB(pwalletMain->strWalletFile); + + return NullUniValue; +} + UniValue importpubkey(const UniValue& params, bool fHelp) { if (!EnsureWalletIsAvailable(fHelp)) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index fbe95a14c2e34..29f7802c5c88a 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2504,6 +2504,7 @@ extern UniValue importpubkey(const UniValue& params, bool fHelp); extern UniValue dumpwallet(const UniValue& params, bool fHelp); extern UniValue importwallet(const UniValue& params, bool fHelp); extern UniValue importprunedfunds(const UniValue& params, bool fHelp); +extern UniValue removeprunedfunds(const UniValue& params, bool fHelp); const CRPCCommand vWalletRPCCommands[] = { // category name actor (function) okSafeMode @@ -2552,6 +2553,7 @@ const CRPCCommand vWalletRPCCommands[] = { "wallet", "walletlock", &walletlock, true }, { "wallet", "walletpassphrasechange", &walletpassphrasechange, true }, { "wallet", "walletpassphrase", &walletpassphrase, true }, + { "wallet", "removeprunedfunds", &removeprunedfunds, true }, }; void walletRegisterRPCCommands() diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 7d1928dd6a268..801ef986841d5 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2362,6 +2362,31 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet) return DB_LOAD_OK; } +DBErrors CWallet::ZapSelectTx(vector& vHashIn, vector& vHashOut) +{ + if (!fFileBacked) + return DB_LOAD_OK; + DBErrors nZapSelectTxRet = CWalletDB(strWalletFile,"cr+").ZapSelectTx(this, vHashIn, vHashOut); + if (nZapSelectTxRet == DB_NEED_REWRITE) + { + if (CDB::Rewrite(strWalletFile, "\x04pool")) + { + LOCK(cs_wallet); + setKeyPool.clear(); + // Note: can't top-up keypool here, because wallet is locked. + // User will be prompted to unlock wallet the next operation + // that requires a new key. + } + } + + if (nZapSelectTxRet != DB_LOAD_OK) + return nZapSelectTxRet; + + MarkDirty(); + + return DB_LOAD_OK; + +} DBErrors CWallet::ZapWalletTx(std::vector& vWtx) { diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index e37d972a154f2..5db36f52d1722 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -792,6 +792,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface DBErrors LoadWallet(bool& fFirstRunRet); DBErrors ZapWalletTx(std::vector& vWtx); + DBErrors ZapSelectTx(std::vector& vHashIn, std::vector& vHashOut); bool SetAddressBook(const CTxDestination& address, const std::string& strName, const std::string& purpose); diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 0a4a1dae2f059..f2b5408e92b5d 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -785,6 +785,45 @@ DBErrors CWalletDB::FindWalletTx(CWallet* pwallet, vector& vTxHash, vec return result; } +DBErrors CWalletDB::ZapSelectTx(CWallet* pwallet, vector& vTxHashIn, vector& vTxHashOut) +{ + // build list of wallet TXs and hashes + vector vTxHash; + vector vWtx; + DBErrors err = FindWalletTx(pwallet, vTxHash, vWtx); + if (err != DB_LOAD_OK) { + return err; + } + + std::sort(vTxHash.begin(), vTxHash.end()); + std::sort(vTxHashIn.begin(), vTxHashIn.end()); + + // erase each matching wallet TX + bool delerror = false; + vector::iterator it = vTxHashIn.begin(); + BOOST_FOREACH (uint256 hash, vTxHash) { + while (it < vTxHashIn.end() && (*it) < hash) { + it++; + } + if (it == vTxHashIn.end()) { + break; + } + else if ((*it) == hash) { + pwallet->mapWallet.erase(hash); + if(!EraseTx(hash)) { + LogPrint("db", "Transaction was found for deletion but returned database error: %s\n", hash.GetHex()); + delerror = true; + } + vTxHashOut.push_back(hash); + } + } + + if (delerror) { + return DB_CORRUPT; + } + return DB_LOAD_OK; +} + DBErrors CWalletDB::ZapWalletTx(CWallet* pwallet, vector& vWtx) { // build list of wallet TXs diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 7e8cc4084e973..fe6c366343599 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -130,6 +130,7 @@ class CWalletDB : public CDB DBErrors LoadWallet(CWallet* pwallet); DBErrors FindWalletTx(CWallet* pwallet, std::vector& vTxHash, std::vector& vWtx); DBErrors ZapWalletTx(CWallet* pwallet, std::vector& vWtx); + DBErrors ZapSelectTx(CWallet* pwallet, std::vector& vHashIn, std::vector& vHashOut); static bool Recover(CDBEnv& dbenv, const std::string& filename, bool fOnlyKeys); static bool Recover(CDBEnv& dbenv, const std::string& filename); From 263de3d1c80c8a0aa54acd4d6708a4078d479b70 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 17 Mar 2016 17:46:06 +0100 Subject: [PATCH 0054/1802] [Wallet][RPC] add abandoned status to listtransactions --- src/wallet/rpcwallet.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 759f894ccbe67..8f7c649839758 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -1346,6 +1346,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe entry.push_back(Pair("fee", ValueFromAmount(-nFee))); if (fLong) WalletTxToJSON(wtx, entry); + entry.push_back(Pair("abandoned", wtx.isAbandoned())); ret.push_back(entry); } } From df9e9233dc4fce68e48beb45699cd255911578c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Wed, 23 Mar 2016 15:44:18 +0000 Subject: [PATCH 0055/1802] Fix lockunspents help message --- src/wallet/rpcwallet.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 8f7c649839758..1d23505961374 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2099,16 +2099,17 @@ UniValue lockunspent(const UniValue& params, bool fHelp) if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( - "lockunspent unlock [{\"txid\":\"txid\",\"vout\":n},...]\n" + "lockunspent unlock ([{\"txid\":\"txid\",\"vout\":n},...])\n" "\nUpdates list of temporarily unspendable outputs.\n" "Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.\n" + "If no transaction outputs are specified when unlocking then all current locked transaction outputs are unlocked.\n" "A locked transaction output will not be chosen by automatic coin selection, when spending bitcoins.\n" "Locks are stored in memory only. Nodes start with zero locked outputs, and the locked output list\n" "is always cleared (by virtue of process exit) when a node stops or fails.\n" "Also see the listunspent call\n" "\nArguments:\n" "1. unlock (boolean, required) Whether to unlock (true) or lock (false) the specified transactions\n" - "2. \"transactions\" (string, required) A json array of objects. Each object the txid (string) vout (numeric)\n" + "2. \"transactions\" (string, optional) A json array of objects. Each object the txid (string) vout (numeric)\n" " [ (json array of json objects)\n" " {\n" " \"txid\":\"id\", (string) The transaction id\n" From fc737d127fb53dbfd31d3d677e157b27f17d5b09 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 24 Mar 2016 21:48:45 +0100 Subject: [PATCH 0056/1802] [Qt] remove unused formatBuildDate method --- src/qt/clientmodel.cpp | 5 ----- src/qt/clientmodel.h | 1 - 2 files changed, 6 deletions(-) diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 65637cd61fe73..697736cc880bb 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -173,11 +173,6 @@ QString ClientModel::formatSubVersion() const return QString::fromStdString(strSubVersion); } -QString ClientModel::formatBuildDate() const -{ - return QString::fromStdString(CLIENT_DATE); -} - bool ClientModel::isReleaseVersion() const { return CLIENT_VERSION_IS_RELEASE; diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index db010f05cbd65..109f95a2a7112 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -72,7 +72,6 @@ class ClientModel : public QObject QString formatFullVersion() const; QString formatSubVersion() const; - QString formatBuildDate() const; bool isReleaseVersion() const; QString clientName() const; QString formatClientStartupTime() const; From 018b60c5ea703ed12edcde034a185f79e77e5576 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 25 Mar 2016 14:21:24 +0100 Subject: [PATCH 0057/1802] test_framework: detect failure of bitcoind startup Replace the `bitcoin-cli -rpcwait` after spawning bitcoind with our own loop that detects when bitcoind exits prematurely. And if one node fails to start, stop the others. This prevents a hang in such a case (see #7463). --- qa/rpc-tests/test_framework/util.py | 60 +++++++++++++++++++---------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index 8d4bd52b94f9b..f069c32a607ba 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -16,6 +16,7 @@ import subprocess import time import re +import errno from . import coverage from .authproxy import AuthServiceProxy, JSONRPCException @@ -130,11 +131,33 @@ def initialize_datadir(dirname, n): f.write("listenonion=0\n") return datadir +def rpc_url(i, rpchost=None): + return "http://rt:rt@%s:%d" % (rpchost or '127.0.0.1', rpc_port(i)) + +def wait_for_bitcoind_start(process, url, i): + ''' + Wait for bitcoind to start. This means that RPC is accessible and fully initialized. + Raise an exception if bitcoind exits during initialization. + ''' + while True: + if process.poll() is not None: + raise Exception('bitcoind exited with status %i during initialization' % process.returncode) + try: + rpc = get_rpc_proxy(url, i) + blocks = rpc.getblockcount() + break # break out of loop on success + except IOError as e: + if e.errno != errno.ECONNREFUSED: # Port not yet open? + raise # unknown IO error + except JSONRPCException as e: # Initialization phase + if e.error['code'] != -28: # RPC in warmup? + raise # unkown JSON RPC exception + time.sleep(0.25) + def initialize_chain(test_dir): """ Create (or copy from cache) a 200-block-long chain and 4 wallets. - bitcoind and bitcoin-cli must be in search path. """ if (not os.path.isdir(os.path.join("cache","node0")) @@ -147,7 +170,6 @@ def initialize_chain(test_dir): if os.path.isdir(os.path.join("cache","node"+str(i))): shutil.rmtree(os.path.join("cache","node"+str(i))) - devnull = open(os.devnull, "w") # Create cache directories, run bitcoinds: for i in range(4): datadir=initialize_datadir("cache", i) @@ -156,19 +178,15 @@ def initialize_chain(test_dir): args.append("-connect=127.0.0.1:"+str(p2p_port(0))) bitcoind_processes[i] = subprocess.Popen(args) if os.getenv("PYTHON_DEBUG", ""): - print "initialize_chain: bitcoind started, calling bitcoin-cli -rpcwait getblockcount" - subprocess.check_call([ os.getenv("BITCOINCLI", "bitcoin-cli"), "-datadir="+datadir, - "-rpcwait", "getblockcount"], stdout=devnull) + print "initialize_chain: bitcoind started, waiting for RPC to come up" + wait_for_bitcoind_start(bitcoind_processes[i], rpc_url(i), i) if os.getenv("PYTHON_DEBUG", ""): - print "initialize_chain: bitcoin-cli -rpcwait getblockcount completed" - devnull.close() + print "initialize_chain: RPC succesfully started" rpcs = [] - for i in range(4): try: - url = "http://rt:rt@127.0.0.1:%d" % (rpc_port(i),) - rpcs.append(get_rpc_proxy(url, i)) + rpcs.append(get_rpc_proxy(rpc_url(i), i)) except: sys.stderr.write("Error connecting to "+url+"\n") sys.exit(1) @@ -243,17 +261,12 @@ def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary= args = [ binary, "-datadir="+datadir, "-server", "-keypool=1", "-discover=0", "-rest", "-mocktime="+str(get_mocktime()) ] if extra_args is not None: args.extend(extra_args) bitcoind_processes[i] = subprocess.Popen(args) - devnull = open(os.devnull, "w") if os.getenv("PYTHON_DEBUG", ""): - print "start_node: bitcoind started, calling bitcoin-cli -rpcwait getblockcount" - subprocess.check_call([ os.getenv("BITCOINCLI", "bitcoin-cli"), "-datadir="+datadir] + - _rpchost_to_args(rpchost) + - ["-rpcwait", "getblockcount"], stdout=devnull) + print "start_node: bitcoind started, waiting for RPC to come up" + url = rpc_url(i, rpchost) + wait_for_bitcoind_start(bitcoind_processes[i], url, i) if os.getenv("PYTHON_DEBUG", ""): - print "start_node: calling bitcoin-cli -rpcwait getblockcount returned" - devnull.close() - url = "http://rt:rt@%s:%d" % (rpchost or '127.0.0.1', rpc_port(i)) - + print "start_node: RPC succesfully started" proxy = get_rpc_proxy(url, i, timeout=timewait) if COVERAGE_DIR: @@ -267,7 +280,14 @@ def start_nodes(num_nodes, dirname, extra_args=None, rpchost=None, binary=None): """ if extra_args is None: extra_args = [ None for i in range(num_nodes) ] if binary is None: binary = [ None for i in range(num_nodes) ] - return [ start_node(i, dirname, extra_args[i], rpchost, binary=binary[i]) for i in range(num_nodes) ] + rpcs = [] + try: + for i in range(num_nodes): + rpcs.append(start_node(i, dirname, extra_args[i], rpchost, binary=binary[i])) + except: # If one node failed to start, stop the others + stop_nodes(rpcs) + raise + return rpcs def log_filename(dirname, n_node, logname): return os.path.join(dirname, "node"+str(n_node), "regtest", logname) From d7b80b54fbb73acc92ddee84697ac4cc10d4d336 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 28 Mar 2016 11:44:19 +0200 Subject: [PATCH 0058/1802] test_framework: Avoid infinite loop in encoding Decimal Avoid an infinite loop in encoding, by ensuring EncodeDecimal returns a string. round(Decimal) used to convert it to float, but it no longer does in python 3.x. Strings are supported since #6380, so just use that. --- qa/rpc-tests/test_framework/authproxy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qa/rpc-tests/test_framework/authproxy.py b/qa/rpc-tests/test_framework/authproxy.py index fba469a0dd0b6..cfc254da09630 100644 --- a/qa/rpc-tests/test_framework/authproxy.py +++ b/qa/rpc-tests/test_framework/authproxy.py @@ -61,7 +61,7 @@ def __init__(self, rpc_error): def EncodeDecimal(o): if isinstance(o, decimal.Decimal): - return round(o, 8) + return str(o) raise TypeError(repr(o) + " is not JSON serializable") class AuthServiceProxy(object): From e7e48ba66cb597621a30945da9ca7fc36a6dc84c Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Mon, 28 Mar 2016 12:28:49 +0200 Subject: [PATCH 0059/1802] test_framework: Py3.4 compat: Specify timeout parameter by name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changed in version 3.4: The strict parameter was removed. HTTP 0.9-style “Simple Responses” are not longer supported. (https://docs.python.org/3/library/http.client.html) Source: https://github.com/jgarzik/python-bitcoinrpc/commit/7ebeebb4f61917fe590d980cb4f9aefdce2c8f25 --- qa/rpc-tests/test_framework/authproxy.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/qa/rpc-tests/test_framework/authproxy.py b/qa/rpc-tests/test_framework/authproxy.py index cfc254da09630..1eb2772592265 100644 --- a/qa/rpc-tests/test_framework/authproxy.py +++ b/qa/rpc-tests/test_framework/authproxy.py @@ -92,11 +92,10 @@ def __init__(self, service_url, service_name=None, timeout=HTTP_TIMEOUT, connect self.__conn = connection elif self.__url.scheme == 'https': self.__conn = httplib.HTTPSConnection(self.__url.hostname, port, - None, None, False, - timeout) + timeout=timeout) else: self.__conn = httplib.HTTPConnection(self.__url.hostname, port, - False, timeout) + timeout=timeout) def __getattr__(self, name): if name.startswith('__') and name.endswith('__'): From fa3fafc96076afb15fa77e01d5f6aff88a333a7e Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 28 Mar 2016 21:47:13 +0200 Subject: [PATCH 0060/1802] [qa] wallet: Wait for reindex to catch up --- qa/rpc-tests/wallet.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py index df176601a54b3..e6ce39711913a 100755 --- a/qa/rpc-tests/wallet.py +++ b/qa/rpc-tests/wallet.py @@ -279,6 +279,7 @@ def run_test (self): blocks = self.nodes[0].generate(2) self.sync_all() balance_nodes = [self.nodes[i].getbalance() for i in range(3)] + block_count = self.nodes[0].getblockcount() maintenance = [ '-rescan', @@ -292,6 +293,9 @@ def run_test (self): stop_nodes(self.nodes) wait_bitcoinds() self.nodes = start_nodes(3, self.options.tmpdir, [[m]] * 3) + while m == '-reindex' and [block_count] * 3 != [self.nodes[i].getblockcount() for i in range(3)]: + # reindex will leave rpc warm up "early"; Wait for it to finish + time.sleep(0.1) assert_equal(balance_nodes, [self.nodes[i].getbalance() for i in range(3)]) # Exercise listsinceblock with the last two blocks From cef8bdf5d747d42c3be473d7ef38052eebd5e9bd Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 24 Mar 2016 21:43:14 +0100 Subject: [PATCH 0061/1802] [Wallet][RPC] add missing abandon status documentation --- src/wallet/rpcwallet.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 1d23505961374..d6b63bf12f22a 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -1439,6 +1439,7 @@ UniValue listtransactions(const UniValue& params, bool fHelp) " \"vout\": n, (numeric) the vout value\n" " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n" " 'send' category of transactions.\n" + " \"abandoned\": xxx (bool) 'true' if the transaction has been abandoned (inputs are respendable).\n" " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and \n" " 'receive' category of transactions. Negative confirmations indicate the\n" " transaction conflicts with the block chain\n" From 7d5e31a82bbf39b9e1a5f0afe5ad9cbf4df9778b Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 29 Mar 2016 11:17:47 +0200 Subject: [PATCH 0062/1802] [Qt] remove trailing output-index from transaction-id The trailing output-index leads to cases where the user can't look-up the transaction ID in various systems. --- src/qt/transactiondesc.cpp | 3 ++- src/qt/transactionrecord.cpp | 7 +++---- src/qt/transactionrecord.h | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 5cb4cd5af72b2..5abefc144e842 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -240,7 +240,8 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco if (wtx.mapValue.count("comment") && !wtx.mapValue["comment"].empty()) strHTML += "
" + tr("Comment") + ":
" + GUIUtil::HtmlEscape(wtx.mapValue["comment"], true) + "
"; - strHTML += "" + tr("Transaction ID") + ": " + TransactionRecord::formatSubTxId(wtx.GetHash(), rec->idx) + "
"; + strHTML += "" + tr("Transaction ID") + ": " + rec->getTxID() + "
"; + strHTML += "" + tr("Output index") + ": " + QString::number(rec->getOutputIndex()) + "
"; // Message from normal bitcoin:URI (bitcoin:123...?message=example) Q_FOREACH (const PAIRTYPE(std::string, std::string)& r, wtx.vOrderForm) diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 5b16b108e66dd..97b77cc93d1be 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -260,11 +260,10 @@ bool TransactionRecord::statusUpdateNeeded() QString TransactionRecord::getTxID() const { - return formatSubTxId(hash, idx); + return QString::fromStdString(hash.ToString()); } -QString TransactionRecord::formatSubTxId(const uint256 &hash, int vout) +int TransactionRecord::getOutputIndex() const { - return QString::fromStdString(hash.ToString() + strprintf("-%03d", vout)); + return idx; } - diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h index 49753ee31f815..95ab98c10df4e 100644 --- a/src/qt/transactionrecord.h +++ b/src/qt/transactionrecord.h @@ -128,8 +128,8 @@ class TransactionRecord /** Return the unique identifier for this transaction (part) */ QString getTxID() const; - /** Format subtransaction id */ - static QString formatSubTxId(const uint256 &hash, int vout); + /** Return the output index of the subtransaction */ + int getOutputIndex() const; /** Update status from core wallet tx. */ From e1523cee5808bb792cd99f037f06b736af4e23fb Mon Sep 17 00:00:00 2001 From: mruddy Date: Tue, 29 Mar 2016 14:40:00 +0000 Subject: [PATCH 0063/1802] P2P: add maxtimeadjustment command line option --- src/init.cpp | 2 ++ src/timedata.cpp | 2 +- src/timedata.h | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/init.cpp b/src/init.cpp index 38ac91b2af8b4..0fb7146128a3f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -27,6 +27,7 @@ #include "script/standard.h" #include "script/sigcache.h" #include "scheduler.h" +#include "timedata.h" #include "txdb.h" #include "txmempool.h" #include "torcontrol.h" @@ -365,6 +366,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-maxconnections=", strprintf(_("Maintain at most connections to peers (default: %u)"), DEFAULT_MAX_PEER_CONNECTIONS)); strUsage += HelpMessageOpt("-maxreceivebuffer=", strprintf(_("Maximum per-connection receive buffer, *1000 bytes (default: %u)"), DEFAULT_MAXRECEIVEBUFFER)); strUsage += HelpMessageOpt("-maxsendbuffer=", strprintf(_("Maximum per-connection send buffer, *1000 bytes (default: %u)"), DEFAULT_MAXSENDBUFFER)); + strUsage += HelpMessageOpt("-maxtimeadjustment", strprintf(_("Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)"), DEFAULT_MAX_TIME_ADJUSTMENT)); strUsage += HelpMessageOpt("-onion=", strprintf(_("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)"), "-proxy")); strUsage += HelpMessageOpt("-onlynet=", _("Only connect to nodes in network (ipv4, ipv6 or onion)")); strUsage += HelpMessageOpt("-permitbaremultisig", strprintf(_("Relay non-P2SH multisig (default: %u)"), DEFAULT_PERMIT_BAREMULTISIG)); diff --git a/src/timedata.cpp b/src/timedata.cpp index 4d2f8d1e3b664..b6bcf86fbf261 100644 --- a/src/timedata.cpp +++ b/src/timedata.cpp @@ -83,7 +83,7 @@ void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample) int64_t nMedian = vTimeOffsets.median(); std::vector vSorted = vTimeOffsets.sorted(); // Only let other nodes change our time by so much - if (abs64(nMedian) < 70 * 60) + if (abs64(nMedian) <= std::max(0, GetArg("-maxtimeadjustment", DEFAULT_MAX_TIME_ADJUSTMENT))) { nTimeOffset = nMedian; } diff --git a/src/timedata.h b/src/timedata.h index 2296baf11bb92..9f2499c85c442 100644 --- a/src/timedata.h +++ b/src/timedata.h @@ -10,6 +10,8 @@ #include #include +static const int64_t DEFAULT_MAX_TIME_ADJUSTMENT = 70 * 60; + class CNetAddr; /** From faa9f01461fea8e3665371f658d7f0dc919851eb Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Tue, 29 Mar 2016 16:48:42 +0200 Subject: [PATCH 0064/1802] [qa] Don't run pruning.py twice --- qa/pull-tester/rpc-tests.py | 1 - 1 file changed, 1 deletion(-) diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index 10b51fef7a718..d5d5f106103f2 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -128,7 +128,6 @@ 'getblocktemplate_proposals.py', 'txn_doublespend.py', 'txn_clone.py --mineblock', - 'pruning.py', 'forknotify.py', 'invalidateblock.py', # 'rpcbind_test.py', #temporary, bug in libevent, see #6655 From 18f05c765c800126b74a6d5b7f33cef7c9aae1b7 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sun, 20 Mar 2016 17:51:52 +0000 Subject: [PATCH 0065/1802] build: python 3 compatibility Ubuntu 16.04 "xenial xerus" does not come with Python 2.x by default. It is possible to install a python-2.7 package, but this has its own problem: no `python` or `python2` symlink (see #7717). This fixes the following scripts to work with python 3: - `make check` (bctest,py, bitcoin-util-test.py) - `make translate` (extract_strings_qt.py) - `make symbols-check` (symbol-check.py) - `make security-check` (security-check.py) Explicitly call the python commands using $(PYTHON) instead of relying on the interpreter line at the top of the scripts. --- Makefile.am | 6 +- configure.ac | 2 +- contrib/devtools/security-check.py | 34 +++---- contrib/devtools/symbol-check.py | 63 ++++++------- contrib/macdeploy/custom_dsstore.py | 6 +- contrib/macdeploy/macdeployqtplus | 136 ++++++++++++++-------------- share/qt/extract_strings_qt.py | 9 +- src/Makefile.qt.include | 2 +- src/Makefile.test.include | 2 +- src/test/bctest.py | 2 +- src/test/bitcoin-util-test.py | 2 +- 11 files changed, 135 insertions(+), 129 deletions(-) diff --git a/Makefile.am b/Makefile.am index d6cbd7cb1221c..0929a59ed2de6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -110,7 +110,7 @@ osx_volname: if BUILD_DARWIN $(OSX_DMG): $(OSX_APP_BUILT) $(OSX_PACKAGING) - $(OSX_DEPLOY_SCRIPT) $(OSX_APP) -add-qt-tr $(OSX_QT_TRANSLATIONS) -translations-dir=$(QT_TRANSLATION_DIR) -dmg -fancy $(OSX_FANCY_PLIST) -verbose 2 -volname $(OSX_VOLNAME) + $(PYTHON) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) -add-qt-tr $(OSX_QT_TRANSLATIONS) -translations-dir=$(QT_TRANSLATION_DIR) -dmg -fancy $(OSX_FANCY_PLIST) -verbose 2 -volname $(OSX_VOLNAME) deploydir: $(OSX_DMG) else @@ -134,10 +134,10 @@ $(APP_DIST_DIR)/.background/$(OSX_BACKGROUND_IMAGE): $(OSX_BACKGROUND_IMAGE_DPIF $(TIFFCP) -c none $(OSX_BACKGROUND_IMAGE_DPIFILES) $@ $(APP_DIST_DIR)/.DS_Store: $(OSX_DSSTORE_GEN) - $< "$@" "$(OSX_VOLNAME)" + $(PYTHON) $< "$@" "$(OSX_VOLNAME)" $(APP_DIST_DIR)/$(OSX_APP)/Contents/MacOS/Bitcoin-Qt: $(OSX_APP_BUILT) $(OSX_PACKAGING) - INSTALLNAMETOOL=$(INSTALLNAMETOOL) OTOOL=$(OTOOL) STRIP=$(STRIP) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) -translations-dir=$(QT_TRANSLATION_DIR) -add-qt-tr $(OSX_QT_TRANSLATIONS) -verbose 2 + INSTALLNAMETOOL=$(INSTALLNAMETOOL) OTOOL=$(OTOOL) STRIP=$(STRIP) $(PYTHON) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) -translations-dir=$(QT_TRANSLATION_DIR) -add-qt-tr $(OSX_QT_TRANSLATIONS) -verbose 2 deploydir: $(APP_DIST_EXTRAS) endif diff --git a/configure.ac b/configure.ac index 939dfeaabfce9..8596307f38bf5 100644 --- a/configure.ac +++ b/configure.ac @@ -60,7 +60,7 @@ AC_PATH_TOOL(STRIP, strip) AC_PATH_TOOL(GCOV, gcov) AC_PATH_PROG(LCOV, lcov) AC_PATH_PROG(JAVA, java) -AC_PATH_PROG(PYTHON, python) +AC_PATH_PROGS([PYTHON], [python3 python2.7 python2 python]) AC_PATH_PROG(GENHTML, genhtml) AC_PATH_PROG([GIT], [git]) AC_PATH_PROG(CCACHE,ccache) diff --git a/contrib/devtools/security-check.py b/contrib/devtools/security-check.py index 0319f739c4936..301fea85c1f6f 100755 --- a/contrib/devtools/security-check.py +++ b/contrib/devtools/security-check.py @@ -5,7 +5,7 @@ Otherwise the exit status will be 1 and it will log which executables failed which checks. Needs `readelf` (for ELF) and `objdump` (for PE). ''' -from __future__ import division,print_function +from __future__ import division,print_function,unicode_literals import subprocess import sys import os @@ -23,9 +23,9 @@ def check_ELF_PIE(executable): raise IOError('Error opening file') ok = False - for line in stdout.split('\n'): + for line in stdout.split(b'\n'): line = line.split() - if len(line)>=2 and line[0] == 'Type:' and line[1] == 'DYN': + if len(line)>=2 and line[0] == b'Type:' and line[1] == b'DYN': ok = True return ok @@ -38,17 +38,17 @@ def get_ELF_program_headers(executable): in_headers = False count = 0 headers = [] - for line in stdout.split('\n'): - if line.startswith('Program Headers:'): + for line in stdout.split(b'\n'): + if line.startswith(b'Program Headers:'): in_headers = True - if line == '': + if line == b'': in_headers = False if in_headers: if count == 1: # header line - ofs_typ = line.find('Type') - ofs_offset = line.find('Offset') - ofs_flags = line.find('Flg') - ofs_align = line.find('Align') + ofs_typ = line.find(b'Type') + ofs_offset = line.find(b'Offset') + ofs_flags = line.find(b'Flg') + ofs_align = line.find(b'Align') if ofs_typ == -1 or ofs_offset == -1 or ofs_flags == -1 or ofs_align == -1: raise ValueError('Cannot parse elfread -lW output') elif count > 1: @@ -65,9 +65,9 @@ def check_ELF_NX(executable): have_wx = False have_gnu_stack = False for (typ, flags) in get_ELF_program_headers(executable): - if typ == 'GNU_STACK': + if typ == b'GNU_STACK': have_gnu_stack = True - if 'W' in flags and 'E' in flags: # section is both writable and executable + if b'W' in flags and b'E' in flags: # section is both writable and executable have_wx = True return have_gnu_stack and not have_wx @@ -84,7 +84,7 @@ def check_ELF_RELRO(executable): # However, the dynamic linker need to write to this area so these are RW. # Glibc itself takes care of mprotecting this area R after relocations are finished. # See also http://permalink.gmane.org/gmane.comp.gnu.binutils/71347 - if typ == 'GNU_RELRO': + if typ == b'GNU_RELRO': have_gnu_relro = True have_bindnow = False @@ -92,9 +92,9 @@ def check_ELF_RELRO(executable): (stdout, stderr) = p.communicate() if p.returncode: raise IOError('Error opening file') - for line in stdout.split('\n'): + for line in stdout.split(b'\n'): tokens = line.split() - if len(tokens)>1 and tokens[1] == '(BIND_NOW)' or (len(tokens)>2 and tokens[1] == '(FLAGS)' and 'BIND_NOW' in tokens[2]): + if len(tokens)>1 and tokens[1] == b'(BIND_NOW)' or (len(tokens)>2 and tokens[1] == b'(FLAGS)' and b'BIND_NOW' in tokens[2]): have_bindnow = True return have_gnu_relro and have_bindnow @@ -107,8 +107,8 @@ def check_ELF_Canary(executable): if p.returncode: raise IOError('Error opening file') ok = False - for line in stdout.split('\n'): - if '__stack_chk_fail' in line: + for line in stdout.split(b'\n'): + if b'__stack_chk_fail' in line: ok = True return ok diff --git a/contrib/devtools/symbol-check.py b/contrib/devtools/symbol-check.py index 4ad5136f79ee5..e26c0fbb94455 100755 --- a/contrib/devtools/symbol-check.py +++ b/contrib/devtools/symbol-check.py @@ -11,7 +11,7 @@ find ../gitian-builder/build -type f -executable | xargs python contrib/devtools/symbol-check.py ''' -from __future__ import division, print_function +from __future__ import division, print_function, unicode_literals import subprocess import re import sys @@ -47,28 +47,28 @@ # Ignore symbols that are exported as part of every executable IGNORE_EXPORTS = { -'_edata', '_end', '_init', '__bss_start', '_fini', '_IO_stdin_used' +b'_edata', b'_end', b'_init', b'__bss_start', b'_fini', b'_IO_stdin_used' } READELF_CMD = os.getenv('READELF', '/usr/bin/readelf') CPPFILT_CMD = os.getenv('CPPFILT', '/usr/bin/c++filt') # Allowed NEEDED libraries ALLOWED_LIBRARIES = { # bitcoind and bitcoin-qt -'libgcc_s.so.1', # GCC base support -'libc.so.6', # C library -'libpthread.so.0', # threading -'libanl.so.1', # DNS resolve -'libm.so.6', # math library -'librt.so.1', # real-time (clock) -'ld-linux-x86-64.so.2', # 64-bit dynamic linker -'ld-linux.so.2', # 32-bit dynamic linker +b'libgcc_s.so.1', # GCC base support +b'libc.so.6', # C library +b'libpthread.so.0', # threading +b'libanl.so.1', # DNS resolve +b'libm.so.6', # math library +b'librt.so.1', # real-time (clock) +b'ld-linux-x86-64.so.2', # 64-bit dynamic linker +b'ld-linux.so.2', # 32-bit dynamic linker # bitcoin-qt only -'libX11-xcb.so.1', # part of X11 -'libX11.so.6', # part of X11 -'libxcb.so.1', # part of X11 -'libfontconfig.so.1', # font support -'libfreetype.so.6', # font parsing -'libdl.so.2' # programming interface to dynamic linker +b'libX11-xcb.so.1', # part of X11 +b'libX11.so.6', # part of X11 +b'libxcb.so.1', # part of X11 +b'libfontconfig.so.1', # font support +b'libfreetype.so.6', # font parsing +b'libdl.so.2' # programming interface to dynamic linker } class CPPFilt(object): @@ -81,7 +81,8 @@ def __init__(self): self.proc = subprocess.Popen(CPPFILT_CMD, stdin=subprocess.PIPE, stdout=subprocess.PIPE) def __call__(self, mangled): - self.proc.stdin.write(mangled + '\n') + self.proc.stdin.write(mangled + b'\n') + self.proc.stdin.flush() return self.proc.stdout.readline().rstrip() def close(self): @@ -99,24 +100,24 @@ def read_symbols(executable, imports=True): if p.returncode: raise IOError('Could not read symbols for %s: %s' % (executable, stderr.strip())) syms = [] - for line in stdout.split('\n'): + for line in stdout.split(b'\n'): line = line.split() - if len(line)>7 and re.match('[0-9]+:$', line[0]): - (sym, _, version) = line[7].partition('@') - is_import = line[6] == 'UND' - if version.startswith('@'): + if len(line)>7 and re.match(b'[0-9]+:$', line[0]): + (sym, _, version) = line[7].partition(b'@') + is_import = line[6] == b'UND' + if version.startswith(b'@'): version = version[1:] if is_import == imports: syms.append((sym, version)) return syms def check_version(max_versions, version): - if '_' in version: - (lib, _, ver) = version.rpartition('_') + if b'_' in version: + (lib, _, ver) = version.rpartition(b'_') else: lib = version ver = '0' - ver = tuple([int(x) for x in ver.split('.')]) + ver = tuple([int(x) for x in ver.split(b'.')]) if not lib in max_versions: return False return ver <= max_versions[lib] @@ -127,10 +128,10 @@ def read_libraries(filename): if p.returncode: raise IOError('Error opening file') libraries = [] - for line in stdout.split('\n'): + for line in stdout.split(b'\n'): tokens = line.split() - if len(tokens)>2 and tokens[1] == '(NEEDED)': - match = re.match('^Shared library: \[(.*)\]$', ' '.join(tokens[2:])) + if len(tokens)>2 and tokens[1] == b'(NEEDED)': + match = re.match(b'^Shared library: \[(.*)\]$', b' '.join(tokens[2:])) if match: libraries.append(match.group(1)) else: @@ -144,18 +145,18 @@ def read_libraries(filename): # Check imported symbols for sym,version in read_symbols(filename, True): if version and not check_version(MAX_VERSIONS, version): - print('%s: symbol %s from unsupported version %s' % (filename, cppfilt(sym), version)) + print('%s: symbol %s from unsupported version %s' % (filename, cppfilt(sym).decode('utf-8'), version.decode('utf-8'))) retval = 1 # Check exported symbols for sym,version in read_symbols(filename, False): if sym in IGNORE_EXPORTS: continue - print('%s: export of symbol %s not allowed' % (filename, cppfilt(sym))) + print('%s: export of symbol %s not allowed' % (filename, cppfilt(sym).decode('utf-8'))) retval = 1 # Check dependency libraries for library_name in read_libraries(filename): if library_name not in ALLOWED_LIBRARIES: - print('%s: NEEDED library %s is not allowed' % (filename, library_name)) + print('%s: NEEDED library %s is not allowed' % (filename, library_name.decode('utf-8'))) retval = 1 exit(retval) diff --git a/contrib/macdeploy/custom_dsstore.py b/contrib/macdeploy/custom_dsstore.py index 8481e903a0d12..03e2325fc0c3c 100755 --- a/contrib/macdeploy/custom_dsstore.py +++ b/contrib/macdeploy/custom_dsstore.py @@ -2,7 +2,7 @@ # Copyright (c) 2013-2015 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. - +from __future__ import division,print_function,unicode_literals import biplist from ds_store import DSStore from mac_alias import Alias @@ -14,7 +14,7 @@ ds = DSStore.open(output_file, 'w+') ds['.']['bwsp'] = { 'ShowStatusBar': False, - 'WindowBounds': '{{300, 280}, {500, 343}}', + 'WindowBounds': b'{{300, 280}, {500, 343}}', 'ContainerShowSidebar': False, 'SidebarWidth': 0, 'ShowTabView': False, @@ -28,7 +28,7 @@ 'gridOffsetX': 0.0, 'textSize': 12.0, 'viewOptionsVersion': 1, - 'backgroundImageAlias': '\x00\x00\x00\x00\x02\x1e\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd1\x94\\\xb0H+\x00\x05\x00\x00\x00\x98\x0fbackground.tiff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x99\xd19\xb0\xf8\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\r\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b.background\x00\x00\x10\x00\x08\x00\x00\xd1\x94\\\xb0\x00\x00\x00\x11\x00\x08\x00\x00\xd19\xb0\xf8\x00\x00\x00\x01\x00\x04\x00\x00\x00\x98\x00\x0e\x00 \x00\x0f\x00b\x00a\x00c\x00k\x00g\x00r\x00o\x00u\x00n\x00d\x00.\x00t\x00i\x00f\x00f\x00\x0f\x00\x02\x00\x00\x00\x12\x00\x1c/.background/background.tiff\x00\x14\x01\x06\x00\x00\x00\x00\x01\x06\x00\x02\x00\x00\x0cMacintosh HD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xce\x97\xab\xc3H+\x00\x00\x01\x88[\x88\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02u\xab\x8d\xd1\x94\\\xb0devrddsk\xff\xff\xff\xff\x00\x00\t \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07bitcoin\x00\x00\x10\x00\x08\x00\x00\xce\x97\xab\xc3\x00\x00\x00\x11\x00\x08\x00\x00\xd1\x94\\\xb0\x00\x00\x00\x01\x00\x14\x01\x88[\x88\x00\x16\xa9\t\x00\x08\xfaR\x00\x08\xfaQ\x00\x02d\x8e\x00\x0e\x00\x02\x00\x00\x00\x0f\x00\x1a\x00\x0c\x00M\x00a\x00c\x00i\x00n\x00t\x00o\x00s\x00h\x00 \x00H\x00D\x00\x13\x00\x01/\x00\x00\x15\x00\x02\x00\x14\xff\xff\x00\x00\xff\xff\x00\x00', + 'backgroundImageAlias': b'\x00\x00\x00\x00\x02\x1e\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd1\x94\\\xb0H+\x00\x05\x00\x00\x00\x98\x0fbackground.tiff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x99\xd19\xb0\xf8\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\r\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b.background\x00\x00\x10\x00\x08\x00\x00\xd1\x94\\\xb0\x00\x00\x00\x11\x00\x08\x00\x00\xd19\xb0\xf8\x00\x00\x00\x01\x00\x04\x00\x00\x00\x98\x00\x0e\x00 \x00\x0f\x00b\x00a\x00c\x00k\x00g\x00r\x00o\x00u\x00n\x00d\x00.\x00t\x00i\x00f\x00f\x00\x0f\x00\x02\x00\x00\x00\x12\x00\x1c/.background/background.tiff\x00\x14\x01\x06\x00\x00\x00\x00\x01\x06\x00\x02\x00\x00\x0cMacintosh HD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xce\x97\xab\xc3H+\x00\x00\x01\x88[\x88\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02u\xab\x8d\xd1\x94\\\xb0devrddsk\xff\xff\xff\xff\x00\x00\t \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07bitcoin\x00\x00\x10\x00\x08\x00\x00\xce\x97\xab\xc3\x00\x00\x00\x11\x00\x08\x00\x00\xd1\x94\\\xb0\x00\x00\x00\x01\x00\x14\x01\x88[\x88\x00\x16\xa9\t\x00\x08\xfaR\x00\x08\xfaQ\x00\x02d\x8e\x00\x0e\x00\x02\x00\x00\x00\x0f\x00\x1a\x00\x0c\x00M\x00a\x00c\x00i\x00n\x00t\x00o\x00s\x00h\x00 \x00H\x00D\x00\x13\x00\x01/\x00\x00\x15\x00\x02\x00\x14\xff\xff\x00\x00\xff\xff\x00\x00', 'backgroundColorBlue': 1.0, 'iconSize': 96.0, 'backgroundColorGreen': 1.0, diff --git a/contrib/macdeploy/macdeployqtplus b/contrib/macdeploy/macdeployqtplus index 7e6270c743e3f..685ed8e5b89c0 100755 --- a/contrib/macdeploy/macdeployqtplus +++ b/contrib/macdeploy/macdeployqtplus @@ -1,5 +1,5 @@ #!/usr/bin/env python - +from __future__ import division, print_function, unicode_literals # # Copyright (C) 2011 Patrick "p2k" Schneider # @@ -201,7 +201,7 @@ class DeploymentInfo(object): def getFrameworks(binaryPath, verbose): if verbose >= 3: - print "Inspecting with otool: " + binaryPath + print("Inspecting with otool: " + binaryPath) otoolbin=os.getenv("OTOOL", "otool") otool = subprocess.Popen([otoolbin, "-L", binaryPath], stdout=subprocess.PIPE, stderr=subprocess.PIPE) o_stdout, o_stderr = otool.communicate() @@ -222,8 +222,8 @@ def getFrameworks(binaryPath, verbose): info = FrameworkInfo.fromOtoolLibraryLine(line.strip()) if info is not None: if verbose >= 3: - print "Found framework:" - print info + print("Found framework:") + print(info) libraries.append(info) return libraries @@ -234,24 +234,24 @@ def runInstallNameTool(action, *args): def changeInstallName(oldName, newName, binaryPath, verbose): if verbose >= 3: - print "Using install_name_tool:" - print " in", binaryPath - print " change reference", oldName - print " to", newName + print("Using install_name_tool:") + print(" in", binaryPath) + print(" change reference", oldName) + print(" to", newName) runInstallNameTool("change", oldName, newName, binaryPath) def changeIdentification(id, binaryPath, verbose): if verbose >= 3: - print "Using install_name_tool:" - print " change identification in", binaryPath - print " to", id + print("Using install_name_tool:") + print(" change identification in", binaryPath) + print(" to", id) runInstallNameTool("id", id, binaryPath) def runStrip(binaryPath, verbose): stripbin=os.getenv("STRIP", "strip") if verbose >= 3: - print "Using strip:" - print " stripped", binaryPath + print("Using strip:") + print(" stripped", binaryPath) subprocess.check_call([stripbin, "-x", binaryPath]) def copyFramework(framework, path, verbose): @@ -274,8 +274,8 @@ def copyFramework(framework, path, verbose): shutil.copy2(fromPath, toPath) if verbose >= 3: - print "Copied:", fromPath - print " to:", toPath + print("Copied:", fromPath) + print(" to:", toPath) permissions = os.stat(toPath) if not permissions.st_mode & stat.S_IWRITE: @@ -288,14 +288,14 @@ def copyFramework(framework, path, verbose): if not os.path.exists(linkfrom): os.symlink(linkto, linkfrom) if verbose >= 2: - print "Linked:", linkfrom, "->", linkto + print("Linked:", linkfrom, "->", linkto) fromResourcesDir = framework.sourceResourcesDirectory if os.path.exists(fromResourcesDir): toResourcesDir = os.path.join(path, framework.destinationResourcesDirectory) shutil.copytree(fromResourcesDir, toResourcesDir, symlinks=True) if verbose >= 3: - print "Copied resources:", fromResourcesDir - print " to:", toResourcesDir + print("Copied resources:", fromResourcesDir) + print(" to:", toResourcesDir) fromContentsDir = framework.sourceVersionContentsDirectory if not os.path.exists(fromContentsDir): fromContentsDir = framework.sourceContentsDirectory @@ -304,16 +304,16 @@ def copyFramework(framework, path, verbose): shutil.copytree(fromContentsDir, toContentsDir, symlinks=True) contentslinkfrom = os.path.join(path, framework.destinationContentsDirectory) if verbose >= 3: - print "Copied Contents:", fromContentsDir - print " to:", toContentsDir + print("Copied Contents:", fromContentsDir) + print(" to:", toContentsDir) elif framework.frameworkName.startswith("libQtGui"): # Copy qt_menu.nib (applies to non-framework layout) qtMenuNibSourcePath = os.path.join(framework.frameworkDirectory, "Resources", "qt_menu.nib") qtMenuNibDestinationPath = os.path.join(path, "Contents", "Resources", "qt_menu.nib") if os.path.exists(qtMenuNibSourcePath) and not os.path.exists(qtMenuNibDestinationPath): shutil.copytree(qtMenuNibSourcePath, qtMenuNibDestinationPath, symlinks=True) if verbose >= 3: - print "Copied for libQtGui:", qtMenuNibSourcePath - print " to:", qtMenuNibDestinationPath + print("Copied for libQtGui:", qtMenuNibSourcePath) + print(" to:", qtMenuNibDestinationPath) return toPath @@ -326,7 +326,7 @@ def deployFrameworks(frameworks, bundlePath, binaryPath, strip, verbose, deploym deploymentInfo.deployedFrameworks.append(framework.frameworkName) if verbose >= 2: - print "Processing", framework.frameworkName, "..." + print("Processing", framework.frameworkName, "...") # Get the Qt path from one of the Qt frameworks if deploymentInfo.qtPath is None and framework.isQtFramework(): @@ -334,7 +334,7 @@ def deployFrameworks(frameworks, bundlePath, binaryPath, strip, verbose, deploym if framework.installName.startswith("@executable_path") or framework.installName.startswith(bundlePath): if verbose >= 2: - print framework.frameworkName, "already deployed, skipping." + print(framework.frameworkName, "already deployed, skipping.") continue # install_name_tool the new id into the binary @@ -366,7 +366,7 @@ def deployFrameworks(frameworks, bundlePath, binaryPath, strip, verbose, deploym def deployFrameworksForAppBundle(applicationBundle, strip, verbose): frameworks = getFrameworks(applicationBundle.binaryPath, verbose) if len(frameworks) == 0 and verbose >= 1: - print "Warning: Could not find any external frameworks to deploy in %s." % (applicationBundle.path) + print("Warning: Could not find any external frameworks to deploy in %s." % (applicationBundle.path)) return DeploymentInfo() else: return deployFrameworks(frameworks, applicationBundle.path, applicationBundle.binaryPath, strip, verbose) @@ -444,7 +444,7 @@ def deployPlugins(appBundleInfo, deploymentInfo, strip, verbose): for pluginDirectory, pluginName in plugins: if verbose >= 2: - print "Processing plugin", os.path.join(pluginDirectory, pluginName), "..." + print("Processing plugin", os.path.join(pluginDirectory, pluginName), "...") sourcePath = os.path.join(deploymentInfo.pluginPath, pluginDirectory, pluginName) destinationDirectory = os.path.join(appBundleInfo.pluginPath, pluginDirectory) @@ -454,8 +454,8 @@ def deployPlugins(appBundleInfo, deploymentInfo, strip, verbose): destinationPath = os.path.join(destinationDirectory, pluginName) shutil.copy2(sourcePath, destinationPath) if verbose >= 3: - print "Copied:", sourcePath - print " to:", destinationPath + print("Copied:", sourcePath) + print(" to:", destinationPath) if strip: runStrip(destinationPath, verbose) @@ -525,7 +525,7 @@ if config.translations_dir and config.translations_dir[0]: for p in config.add_resources: if verbose >= 3: - print "Checking for \"%s\"..." % p + print("Checking for \"%s\"..." % p) if not os.path.exists(p): if verbose >= 1: sys.stderr.write("Error: Could not find additional resource file \"%s\"\n" % (p)) @@ -535,7 +535,7 @@ for p in config.add_resources: if len(config.fancy) == 1: if verbose >= 3: - print "Fancy: Importing plistlib..." + print("Fancy: Importing plistlib...") try: import plistlib except ImportError: @@ -545,7 +545,7 @@ if len(config.fancy) == 1: p = config.fancy[0] if verbose >= 3: - print "Fancy: Loading \"%s\"..." % p + print("Fancy: Loading \"%s\"..." % p) if not os.path.exists(p): if verbose >= 1: sys.stderr.write("Error: Could not find fancy disk image plist at \"%s\"\n" % (p)) @@ -559,23 +559,23 @@ if len(config.fancy) == 1: sys.exit(1) try: - assert not fancy.has_key("window_bounds") or (isinstance(fancy["window_bounds"], list) and len(fancy["window_bounds"]) == 4) - assert not fancy.has_key("background_picture") or isinstance(fancy["background_picture"], str) - assert not fancy.has_key("icon_size") or isinstance(fancy["icon_size"], int) - assert not fancy.has_key("applications_symlink") or isinstance(fancy["applications_symlink"], bool) - if fancy.has_key("items_position"): + assert "window_bounds" not in fancy or (isinstance(fancy["window_bounds"], list) and len(fancy["window_bounds"]) == 4) + assert "background_picture" not in fancy or isinstance(fancy["background_picture"], str) + assert "icon_size" not in fancy or isinstance(fancy["icon_size"], int) + assert "applications_symlink" not in fancy or isinstance(fancy["applications_symlink"], bool) + if "items_position" in fancy: assert isinstance(fancy["items_position"], dict) - for key, value in fancy["items_position"].iteritems(): + for key, value in fancy["items_position"].items(): assert isinstance(value, list) and len(value) == 2 and isinstance(value[0], int) and isinstance(value[1], int) except: if verbose >= 1: sys.stderr.write("Error: Bad format of fancy disk image plist at \"%s\"\n" % (p)) sys.exit(1) - if fancy.has_key("background_picture"): + if "background_picture" in fancy: bp = fancy["background_picture"] if verbose >= 3: - print "Fancy: Resolving background picture \"%s\"..." % bp + print("Fancy: Resolving background picture \"%s\"..." % bp) if not os.path.exists(bp): bp = os.path.join(os.path.dirname(p), bp) if not os.path.exists(bp): @@ -591,7 +591,7 @@ else: if os.path.exists("dist"): if verbose >= 2: - print "+ Removing old dist folder +" + print("+ Removing old dist folder +") shutil.rmtree("dist") @@ -607,9 +607,9 @@ else: target = os.path.join("dist", "Bitcoin-Qt.app") if verbose >= 2: - print "+ Copying source bundle +" + print("+ Copying source bundle +") if verbose >= 3: - print app_bundle, "->", target + print(app_bundle, "->", target) os.mkdir("dist") shutil.copytree(app_bundle, target, symlinks=True) @@ -619,7 +619,7 @@ applicationBundle = ApplicationBundleInfo(target) # ------------------------------------------------ if verbose >= 2: - print "+ Deploying frameworks +" + print("+ Deploying frameworks +") try: deploymentInfo = deployFrameworksForAppBundle(applicationBundle, config.strip, verbose) @@ -638,7 +638,7 @@ except RuntimeError as e: if config.plugins: if verbose >= 2: - print "+ Deploying plugins +" + print("+ Deploying plugins +") try: deployPlugins(applicationBundle, deploymentInfo, config.strip, verbose) @@ -664,7 +664,7 @@ else: for lng_file in add_qt_tr: p = os.path.join(qt_tr_dir, lng_file) if verbose >= 3: - print "Checking for \"%s\"..." % p + print("Checking for \"%s\"..." % p) if not os.path.exists(p): if verbose >= 1: sys.stderr.write("Error: Could not find Qt translation file \"%s\"\n" % (lng_file)) @@ -673,7 +673,7 @@ else: # ------------------------------------------------ if verbose >= 2: - print "+ Installing qt.conf +" + print("+ Installing qt.conf +") f = open(os.path.join(applicationBundle.resourcesPath, "qt.conf"), "wb") f.write(qt_conf) @@ -682,22 +682,22 @@ f.close() # ------------------------------------------------ if len(add_qt_tr) > 0 and verbose >= 2: - print "+ Adding Qt translations +" + print("+ Adding Qt translations +") for lng_file in add_qt_tr: if verbose >= 3: - print os.path.join(qt_tr_dir, lng_file), "->", os.path.join(applicationBundle.resourcesPath, lng_file) + print(os.path.join(qt_tr_dir, lng_file), "->", os.path.join(applicationBundle.resourcesPath, lng_file)) shutil.copy2(os.path.join(qt_tr_dir, lng_file), os.path.join(applicationBundle.resourcesPath, lng_file)) # ------------------------------------------------ if len(config.add_resources) > 0 and verbose >= 2: - print "+ Adding additional resources +" + print("+ Adding additional resources +") for p in config.add_resources: t = os.path.join(applicationBundle.resourcesPath, os.path.basename(p)) if verbose >= 3: - print p, "->", t + print(p, "->", t) if os.path.isdir(p): shutil.copytree(p, t, symlinks=True) else: @@ -706,10 +706,10 @@ for p in config.add_resources: # ------------------------------------------------ if config.sign and 'CODESIGNARGS' not in os.environ: - print "You must set the CODESIGNARGS environment variable. Skipping signing." + print("You must set the CODESIGNARGS environment variable. Skipping signing.") elif config.sign: if verbose >= 1: - print "Code-signing app bundle %s"%(target,) + print("Code-signing app bundle %s"%(target,)) subprocess.check_call("codesign --force %s %s"%(os.environ['CODESIGNARGS'], target), shell=True) # ------------------------------------------------ @@ -734,7 +734,7 @@ if config.dmg is not None: def runHDIUtil(verb, image_basename, **kwargs): hdiutil_args = ["hdiutil", verb, image_basename + ".dmg"] - if kwargs.has_key("capture_stdout"): + if "capture_stdout" in kwargs: del kwargs["capture_stdout"] run = subprocess.check_output else: @@ -744,7 +744,7 @@ if config.dmg is not None: hdiutil_args.append("-verbose") run = subprocess.check_call - for key, value in kwargs.iteritems(): + for key, value in kwargs.items(): hdiutil_args.append("-" + key) if not value is True: hdiutil_args.append(str(value)) @@ -753,9 +753,9 @@ if config.dmg is not None: if verbose >= 2: if fancy is None: - print "+ Creating .dmg disk image +" + print("+ Creating .dmg disk image +") else: - print "+ Preparing .dmg disk image +" + print("+ Preparing .dmg disk image +") if config.dmg != "": dmg_name = config.dmg @@ -770,7 +770,7 @@ if config.dmg is not None: sys.exit(e.returncode) else: if verbose >= 3: - print "Determining size of \"dist\"..." + print("Determining size of \"dist\"...") size = 0 for path, dirs, files in os.walk("dist"): for file in files: @@ -778,14 +778,14 @@ if config.dmg is not None: size += int(size * 0.15) if verbose >= 3: - print "Creating temp image for modification..." + print("Creating temp image for modification...") try: runHDIUtil("create", dmg_name + ".temp", srcfolder="dist", format="UDRW", size=size, volname=volname, ov=True) except subprocess.CalledProcessError as e: sys.exit(e.returncode) if verbose >= 3: - print "Attaching temp image..." + print("Attaching temp image...") try: output = runHDIUtil("attach", dmg_name + ".temp", readwrite=True, noverify=True, noautoopen=True, capture_stdout=True) except subprocess.CalledProcessError as e: @@ -796,13 +796,13 @@ if config.dmg is not None: disk_name = m.group(1) if verbose >= 2: - print "+ Applying fancy settings +" + print("+ Applying fancy settings +") - if fancy.has_key("background_picture"): + if "background_picture" in fancy: bg_path = os.path.join(disk_root, ".background", os.path.basename(fancy["background_picture"])) os.mkdir(os.path.dirname(bg_path)) if verbose >= 3: - print fancy["background_picture"], "->", bg_path + print(fancy["background_picture"], "->", bg_path) shutil.copy2(fancy["background_picture"], bg_path) else: bg_path = None @@ -839,8 +839,8 @@ if config.dmg is not None: itemscript = Template('set position of item "${item}" of container window to {${position}}') items_positions = [] - if fancy.has_key("items_position"): - for name, position in fancy["items_position"].iteritems(): + if "items_position" in fancy: + for name, position in fancy["items_position"].items(): params = { "item" : name, "position" : ",".join([str(p) for p in position]) } items_positions.append(itemscript.substitute(params)) @@ -851,9 +851,9 @@ if config.dmg is not None: "background_commands" : "", "items_positions" : "\n ".join(items_positions) } - if fancy.has_key("window_bounds"): + if "window_bounds" in fancy: params["window.bounds"] = ",".join([str(p) for p in fancy["window_bounds"]]) - if fancy.has_key("icon_size"): + if "icon_size" in fancy: params["icon_size"] = str(fancy["icon_size"]) if bg_path is not None: # Set background file, then call SetFile to make it invisible. @@ -873,7 +873,7 @@ if config.dmg is not None: print("Error running osascript.") if verbose >= 2: - print "+ Finalizing .dmg disk image +" + print("+ Finalizing .dmg disk image +") time.sleep(5) try: @@ -886,6 +886,6 @@ if config.dmg is not None: # ------------------------------------------------ if verbose >= 2: - print "+ Done +" + print("+ Done +") sys.exit(0) diff --git a/share/qt/extract_strings_qt.py b/share/qt/extract_strings_qt.py index 2a6e4b930cb20..7728a4377590b 100755 --- a/share/qt/extract_strings_qt.py +++ b/share/qt/extract_strings_qt.py @@ -1,8 +1,9 @@ #!/usr/bin/python ''' -Extract _("...") strings for translation and convert to Qt4 stringdefs so that +Extract _("...") strings for translation and convert to Qt stringdefs so that they can be picked up by Qt linguist. ''' +from __future__ import division,print_function,unicode_literals from subprocess import Popen, PIPE import glob import operator @@ -52,10 +53,14 @@ def parse_po(text): # xgettext -n --keyword=_ $FILES XGETTEXT=os.getenv('XGETTEXT', 'xgettext') +if not XGETTEXT: + print('Cannot extract strings: xgettext utility is not installed or not configured.',file=sys.stderr) + print('Please install package "gettext" and re-run \'./configure\'.',file=sys.stderr) + exit(1) child = Popen([XGETTEXT,'--output=-','-n','--keyword=_'] + files, stdout=PIPE) (out, err) = child.communicate() -messages = parse_po(out) +messages = parse_po(out.decode('utf-8')) f = open(OUT_CPP, 'w') f.write(""" diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index ca4e1e70d085e..357e4c47ff360 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -391,7 +391,7 @@ SECONDARY: $(QT_QM) qt/bitcoinstrings.cpp: $(libbitcoin_server_a_SOURCES) $(libbitcoin_wallet_a_SOURCES) @test -n $(XGETTEXT) || echo "xgettext is required for updating translations" - $(AM_V_GEN) cd $(srcdir); XGETTEXT=$(XGETTEXT) PACKAGE_NAME="$(PACKAGE_NAME)" COPYRIGHT_HOLDERS="$(COPYRIGHT_HOLDERS)" COPYRIGHT_HOLDERS_SUBSTITUTION="$(COPYRIGHT_HOLDERS_SUBSTITUTION)" ../share/qt/extract_strings_qt.py $^ + $(AM_V_GEN) cd $(srcdir); XGETTEXT=$(XGETTEXT) PACKAGE_NAME="$(PACKAGE_NAME)" COPYRIGHT_HOLDERS="$(COPYRIGHT_HOLDERS)" COPYRIGHT_HOLDERS_SUBSTITUTION="$(COPYRIGHT_HOLDERS_SUBSTITUTION)" $(PYTHON) ../share/qt/extract_strings_qt.py $^ translate: qt/bitcoinstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_QT_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM) @test -n $(LUPDATE) || echo "lupdate is required for updating translations" diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 57f9ac50e0a01..86b27ae687d33 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -129,7 +129,7 @@ bitcoin_test_clean : FORCE check-local: @echo "Running test/bitcoin-util-test.py..." - $(AM_V_at)srcdir=$(srcdir) PYTHONPATH=$(builddir)/test $(srcdir)/test/bitcoin-util-test.py + $(AM_V_at)srcdir=$(srcdir) PYTHONPATH=$(builddir)/test $(PYTHON) $(srcdir)/test/bitcoin-util-test.py $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C secp256k1 check if EMBEDDED_UNIVALUE $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C univalue check diff --git a/src/test/bctest.py b/src/test/bctest.py index 3a8d0ea51bf1b..8105b87ffa34c 100644 --- a/src/test/bctest.py +++ b/src/test/bctest.py @@ -1,7 +1,7 @@ # Copyright 2014 BitPay, Inc. # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. - +from __future__ import division,print_function,unicode_literals import subprocess import os import json diff --git a/src/test/bitcoin-util-test.py b/src/test/bitcoin-util-test.py index 20afb16a9ebe2..95dd3e81b4369 100755 --- a/src/test/bitcoin-util-test.py +++ b/src/test/bitcoin-util-test.py @@ -2,7 +2,7 @@ # Copyright 2014 BitPay, Inc. # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. - +from __future__ import division,print_function,unicode_literals import os import bctest import buildenv From 3e55b3a00450279522900ca96e5cf79162169019 Mon Sep 17 00:00:00 2001 From: accraze Date: Wed, 30 Mar 2016 07:29:56 -0700 Subject: [PATCH 0066/1802] [doc] added depends cross compile info --- doc/build-unix.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/doc/build-unix.md b/doc/build-unix.md index 5b519b80442d0..c1e92d8d15f65 100644 --- a/doc/build-unix.md +++ b/doc/build-unix.md @@ -248,3 +248,26 @@ Additional Configure Flags A list of additional configure flags can be displayed with: ./configure --help + + + +ARM Cross-compilation +------------------- +These steps can be performed on, for example, an Ubuntu VM. The depends system +will also work on other Linux distributions, however the commands for +installing the toolchain will be different. + +First install the toolchain: + + sudo apt-get install g++-arm-linux-gnueabihf + +To build executables for ARM: + + cd depends + make HOST=arm-linux-gnueabihf NO_QT=1 + cd .. + ./configure --prefix=$PWD/depends/arm-linux-gnueabihf --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++ + make + + +For further documentation on the depends system see [README.md](../depends/README.md) in the depends directory. \ No newline at end of file From ae2156f1235eb3c5ba294544ab04b5dd7509c7ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Wed, 30 Mar 2016 20:26:10 +0200 Subject: [PATCH 0067/1802] Clear the input line after activating autocomplete --- src/qt/rpcconsole.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 42112c42f11ee..d8647d902a0e7 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -459,6 +459,8 @@ void RPCConsole::setClientModel(ClientModel *model) autoCompleter = new QCompleter(wordList, this); ui->lineEdit->setCompleter(autoCompleter); + // clear the lineEdit after activating from QCompleter + connect(autoCompleter, SIGNAL(activated(const QString&)), ui->lineEdit, SLOT(clear()), Qt::QueuedConnection); } } From 40234ba89f00afe96daf807acf61e6a23f8a81fa Mon Sep 17 00:00:00 2001 From: BtcDrak Date: Wed, 30 Mar 2016 19:38:02 +0100 Subject: [PATCH 0068/1802] Fix comments in tests --- qa/rpc-tests/bip68-112-113-p2p.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/qa/rpc-tests/bip68-112-113-p2p.py b/qa/rpc-tests/bip68-112-113-p2p.py index c226f4dad4976..7d3c59be3ee8f 100755 --- a/qa/rpc-tests/bip68-112-113-p2p.py +++ b/qa/rpc-tests/bip68-112-113-p2p.py @@ -383,9 +383,9 @@ def get_tests(self): for bip113tx in [bip113signed1, bip113signed2]: yield TestInstance([[self.create_test_block([bip113tx]), False]]) # 9,10 # BIP 113 tests should now pass if the locktime is < MTP - bip113tx_v1.nLockTime = self.last_block_time - 600 * 5 - 1 # = MTP of prior block (not <) but < time put on current block + bip113tx_v1.nLockTime = self.last_block_time - 600 * 5 - 1 # < MTP of prior block bip113signed1 = self.sign_transaction(self.nodes[0], bip113tx_v1) - bip113tx_v2.nLockTime = self.last_block_time - 600 * 5 - 1 # = MTP of prior block (not <) but < time put on current block + bip113tx_v2.nLockTime = self.last_block_time - 600 * 5 - 1 # < MTP of prior block bip113signed2 = self.sign_transaction(self.nodes[0], bip113tx_v2) for bip113tx in [bip113signed1, bip113signed2]: yield TestInstance([[self.create_test_block([bip113tx]), True]]) # 11,12 @@ -490,7 +490,7 @@ def get_tests(self): self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash()) ## SEQUENCE_LOCKTIME_DISABLE_FLAG is unset in argument to OP_CSV for all remaining txs ## - # All txs with nSequence 11 should fail either due to earlier mismatch or failing the CSV check + # All txs with nSequence 9 should fail either due to earlier mismatch or failing the CSV check fail_txs = [] fail_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_9_v2)) # 16/16 of vary_nSequence_9 for b25 in xrange(2): From fb8a8cf2e610920e9eee61c19ed6080af064bb43 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 29 Mar 2016 19:43:02 +0200 Subject: [PATCH 0069/1802] rpc: Register calls where they are defined Split out methods to every module, apart from 'help' and 'stop' which are implemented in rpcserver.cpp itself. - This makes it easier to add or remove RPC commands - no longer everything that includes rpcserver.h has to be rebuilt when there's a change there. - Cleans up `rpc/server.h` by getting rid of the huge cluttered list of function definitions. - Removes most of the bitcoin-specific code from rpcserver.cpp and .h. Continues #7307 for the non-wallet. --- src/Makefile.am | 1 + src/init.cpp | 4 ++- src/rest.cpp | 3 ++ src/rpc/blockchain.cpp | 28 +++++++++++++++++ src/rpc/mining.cpp | 24 ++++++++++++++ src/rpc/misc.cpp | 18 +++++++++++ src/rpc/net.cpp | 22 +++++++++++++ src/rpc/rawtransaction.cpp | 20 ++++++++++++ src/rpc/register.h | 32 +++++++++++++++++++ src/rpc/server.cpp | 64 -------------------------------------- src/rpc/server.h | 59 ----------------------------------- src/test/rpc_tests.cpp | 2 +- src/test/test_bitcoin.cpp | 7 ++++- src/wallet/rpcwallet.cpp | 14 +++------ src/wallet/rpcwallet.h | 4 ++- 15 files changed, 165 insertions(+), 137 deletions(-) create mode 100644 src/rpc/register.h diff --git a/src/Makefile.am b/src/Makefile.am index 6ad7aabae0ef6..1e54512cbddc1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -130,6 +130,7 @@ BITCOIN_CORE_H = \ rpc/client.h \ rpc/protocol.h \ rpc/server.h \ + rpc/register.h \ scheduler.h \ script/sigcache.h \ script/sign.h \ diff --git a/src/init.cpp b/src/init.cpp index 38ac91b2af8b4..0c371b288a5a3 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -24,6 +24,7 @@ #include "net.h" #include "policy/policy.h" #include "rpc/server.h" +#include "rpc/register.h" #include "script/standard.h" #include "script/sigcache.h" #include "scheduler.h" @@ -913,10 +914,11 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) fPruneMode = true; } + RegisterAllCoreRPCCommands(tableRPC); #ifdef ENABLE_WALLET bool fDisableWallet = GetBoolArg("-disablewallet", false); if (!fDisableWallet) - walletRegisterRPCCommands(); + RegisterWalletRPCCommands(tableRPC); #endif nConnectTimeout = GetArg("-timeout", DEFAULT_CONNECT_TIMEOUT); diff --git a/src/rest.cpp b/src/rest.cpp index ebdccc94021b7..2dff8d7daddfc 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -273,6 +273,9 @@ static bool rest_block_notxdetails(HTTPRequest* req, const std::string& strURIPa return rest_block(req, strURIPart, false); } +// A bit of a hack - dependency on a function defined in rpc/blockchain.cpp +UniValue getblockchaininfo(const UniValue& params, bool fHelp); + static bool rest_chaininfo(HTTPRequest* req, const std::string& strURIPart) { if (!CheckWarmup(req)) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index a110dff0d1d4a..b947609b1a1b7 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -911,3 +911,31 @@ UniValue reconsiderblock(const UniValue& params, bool fHelp) return NullUniValue; } + +static const CRPCCommand commands[] = +{ // category name actor (function) okSafeMode + // --------------------- ------------------------ ----------------------- ---------- + { "blockchain", "getblockchaininfo", &getblockchaininfo, true }, + { "blockchain", "getbestblockhash", &getbestblockhash, true }, + { "blockchain", "getblockcount", &getblockcount, true }, + { "blockchain", "getblock", &getblock, true }, + { "blockchain", "getblockhash", &getblockhash, true }, + { "blockchain", "getblockheader", &getblockheader, true }, + { "blockchain", "getchaintips", &getchaintips, true }, + { "blockchain", "getdifficulty", &getdifficulty, true }, + { "blockchain", "getmempoolinfo", &getmempoolinfo, true }, + { "blockchain", "getrawmempool", &getrawmempool, true }, + { "blockchain", "gettxout", &gettxout, true }, + { "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true }, + { "blockchain", "verifychain", &verifychain, true }, + + /* Not shown in help */ + { "hidden", "invalidateblock", &invalidateblock, true }, + { "hidden", "reconsiderblock", &reconsiderblock, true }, +}; + +void RegisterBlockchainRPCCommands(CRPCTable &tableRPC) +{ + for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) + tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); +} diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index a2abbb323d5ce..b63ee2288918b 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -781,3 +781,27 @@ UniValue estimatesmartpriority(const UniValue& params, bool fHelp) result.push_back(Pair("blocks", answerFound)); return result; } + +static const CRPCCommand commands[] = +{ // category name actor (function) okSafeMode + // --------------------- ------------------------ ----------------------- ---------- + { "mining", "getnetworkhashps", &getnetworkhashps, true }, + { "mining", "getmininginfo", &getmininginfo, true }, + { "mining", "prioritisetransaction", &prioritisetransaction, true }, + { "mining", "getblocktemplate", &getblocktemplate, true }, + { "mining", "submitblock", &submitblock, true }, + + { "generating", "generate", &generate, true }, + { "generating", "generatetoaddress", &generatetoaddress, true }, + + { "util", "estimatefee", &estimatefee, true }, + { "util", "estimatepriority", &estimatepriority, true }, + { "util", "estimatesmartfee", &estimatesmartfee, true }, + { "util", "estimatesmartpriority", &estimatesmartpriority, true }, +}; + +void RegisterMiningRPCCommands(CRPCTable &tableRPC) +{ + for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) + tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); +} diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 0aab9c30434f8..e8a099b4452c4 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -396,3 +396,21 @@ UniValue setmocktime(const UniValue& params, bool fHelp) return NullUniValue; } + +static const CRPCCommand commands[] = +{ // category name actor (function) okSafeMode + // --------------------- ------------------------ ----------------------- ---------- + { "control", "getinfo", &getinfo, true }, /* uses wallet if enabled */ + { "util", "validateaddress", &validateaddress, true }, /* uses wallet if enabled */ + { "util", "createmultisig", &createmultisig, true }, + { "util", "verifymessage", &verifymessage, true }, + + /* Not shown in help */ + { "hidden", "setmocktime", &setmocktime, true }, +}; + +void RegisterMiscRPCCommands(CRPCTable &tableRPC) +{ + for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) + tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); +} diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 065214a98addd..017cd6ca32187 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -626,3 +626,25 @@ UniValue clearbanned(const UniValue& params, bool fHelp) return NullUniValue; } + +static const CRPCCommand commands[] = +{ // category name actor (function) okSafeMode + // --------------------- ------------------------ ----------------------- ---------- + { "network", "getconnectioncount", &getconnectioncount, true }, + { "network", "ping", &ping, true }, + { "network", "getpeerinfo", &getpeerinfo, true }, + { "network", "addnode", &addnode, true }, + { "network", "disconnectnode", &disconnectnode, true }, + { "network", "getaddednodeinfo", &getaddednodeinfo, true }, + { "network", "getnettotals", &getnettotals, true }, + { "network", "getnetworkinfo", &getnetworkinfo, true }, + { "network", "setban", &setban, true }, + { "network", "listbanned", &listbanned, true }, + { "network", "clearbanned", &clearbanned, true }, +}; + +void RegisterNetRPCCommands(CRPCTable &tableRPC) +{ + for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) + tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); +} diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 34dd3b30f50ff..de8cd68f66267 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -841,3 +841,23 @@ UniValue sendrawtransaction(const UniValue& params, bool fHelp) return hashTx.GetHex(); } + +static const CRPCCommand commands[] = +{ // category name actor (function) okSafeMode + // --------------------- ------------------------ ----------------------- ---------- + { "rawtransactions", "getrawtransaction", &getrawtransaction, true }, + { "rawtransactions", "createrawtransaction", &createrawtransaction, true }, + { "rawtransactions", "decoderawtransaction", &decoderawtransaction, true }, + { "rawtransactions", "decodescript", &decodescript, true }, + { "rawtransactions", "sendrawtransaction", &sendrawtransaction, false }, + { "rawtransactions", "signrawtransaction", &signrawtransaction, false }, /* uses wallet if enabled */ + + { "blockchain", "gettxoutproof", &gettxoutproof, true }, + { "blockchain", "verifytxoutproof", &verifytxoutproof, true }, +}; + +void RegisterRawTransactionRPCCommands(CRPCTable &tableRPC) +{ + for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) + tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); +} diff --git a/src/rpc/register.h b/src/rpc/register.h new file mode 100644 index 0000000000000..01aa58a25d850 --- /dev/null +++ b/src/rpc/register.h @@ -0,0 +1,32 @@ +// Copyright (c) 2009-2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_RPCREGISTER_H +#define BITCOIN_RPCREGISTER_H + +/** These are in one header file to avoid creating tons of single-function + * headers for everything under src/rpc/ */ +class CRPCTable; + +/** Register block chain RPC commands */ +void RegisterBlockchainRPCCommands(CRPCTable &tableRPC); +/** Register P2P networking RPC commands */ +void RegisterNetRPCCommands(CRPCTable &tableRPC); +/** Register miscellaneous RPC commands */ +void RegisterMiscRPCCommands(CRPCTable &tableRPC); +/** Register mining RPC commands */ +void RegisterMiningRPCCommands(CRPCTable &tableRPC); +/** Register raw transaction RPC commands */ +void RegisterRawTransactionRPCCommands(CRPCTable &tableRPC); + +static inline void RegisterAllCoreRPCCommands(CRPCTable &tableRPC) +{ + RegisterBlockchainRPCCommands(tableRPC); + RegisterNetRPCCommands(tableRPC); + RegisterMiscRPCCommands(tableRPC); + RegisterMiningRPCCommands(tableRPC); + RegisterRawTransactionRPCCommands(tableRPC); +} + +#endif diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 1303a3bb1331f..8326fe14d2150 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -256,72 +256,8 @@ static const CRPCCommand vRPCCommands[] = { // category name actor (function) okSafeMode // --------------------- ------------------------ ----------------------- ---------- /* Overall control/query calls */ - { "control", "getinfo", &getinfo, true }, /* uses wallet if enabled */ { "control", "help", &help, true }, { "control", "stop", &stop, true }, - - /* P2P networking */ - { "network", "getnetworkinfo", &getnetworkinfo, true }, - { "network", "addnode", &addnode, true }, - { "network", "disconnectnode", &disconnectnode, true }, - { "network", "getaddednodeinfo", &getaddednodeinfo, true }, - { "network", "getconnectioncount", &getconnectioncount, true }, - { "network", "getnettotals", &getnettotals, true }, - { "network", "getpeerinfo", &getpeerinfo, true }, - { "network", "ping", &ping, true }, - { "network", "setban", &setban, true }, - { "network", "listbanned", &listbanned, true }, - { "network", "clearbanned", &clearbanned, true }, - - /* Block chain and UTXO */ - { "blockchain", "getblockchaininfo", &getblockchaininfo, true }, - { "blockchain", "getbestblockhash", &getbestblockhash, true }, - { "blockchain", "getblockcount", &getblockcount, true }, - { "blockchain", "getblock", &getblock, true }, - { "blockchain", "getblockhash", &getblockhash, true }, - { "blockchain", "getblockheader", &getblockheader, true }, - { "blockchain", "getchaintips", &getchaintips, true }, - { "blockchain", "getdifficulty", &getdifficulty, true }, - { "blockchain", "getmempoolinfo", &getmempoolinfo, true }, - { "blockchain", "getrawmempool", &getrawmempool, true }, - { "blockchain", "gettxout", &gettxout, true }, - { "blockchain", "gettxoutproof", &gettxoutproof, true }, - { "blockchain", "verifytxoutproof", &verifytxoutproof, true }, - { "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true }, - { "blockchain", "verifychain", &verifychain, true }, - - /* Mining */ - { "mining", "getblocktemplate", &getblocktemplate, true }, - { "mining", "getmininginfo", &getmininginfo, true }, - { "mining", "getnetworkhashps", &getnetworkhashps, true }, - { "mining", "prioritisetransaction", &prioritisetransaction, true }, - { "mining", "submitblock", &submitblock, true }, - - /* Coin generation */ - { "generating", "generate", &generate, true }, - { "generating", "generatetoaddress", &generatetoaddress, true }, - - /* Raw transactions */ - { "rawtransactions", "createrawtransaction", &createrawtransaction, true }, - { "rawtransactions", "decoderawtransaction", &decoderawtransaction, true }, - { "rawtransactions", "decodescript", &decodescript, true }, - { "rawtransactions", "getrawtransaction", &getrawtransaction, true }, - { "rawtransactions", "sendrawtransaction", &sendrawtransaction, false }, - { "rawtransactions", "signrawtransaction", &signrawtransaction, false }, /* uses wallet if enabled */ - - /* Utility functions */ - { "util", "createmultisig", &createmultisig, true }, - { "util", "validateaddress", &validateaddress, true }, /* uses wallet if enabled */ - { "util", "verifymessage", &verifymessage, true }, - { "util", "estimatefee", &estimatefee, true }, - { "util", "estimatepriority", &estimatepriority, true }, - { "util", "estimatesmartfee", &estimatesmartfee, true }, - { "util", "estimatesmartpriority", &estimatesmartpriority, true }, - - /* Not shown in help */ - { "hidden", "invalidateblock", &invalidateblock, true }, - { "hidden", "reconsiderblock", &reconsiderblock, true }, - { "hidden", "setmocktime", &setmocktime, true }, }; CRPCTable::CRPCTable() diff --git a/src/rpc/server.h b/src/rpc/server.h index 35e114feef3ff..a7ed710ce60ad 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -181,65 +181,6 @@ extern std::string HelpExampleRpc(const std::string& methodname, const std::stri extern void EnsureWalletIsUnlocked(); -extern UniValue getconnectioncount(const UniValue& params, bool fHelp); // in rpc/net.cpp -extern UniValue getpeerinfo(const UniValue& params, bool fHelp); -extern UniValue ping(const UniValue& params, bool fHelp); -extern UniValue addnode(const UniValue& params, bool fHelp); -extern UniValue disconnectnode(const UniValue& params, bool fHelp); -extern UniValue getaddednodeinfo(const UniValue& params, bool fHelp); -extern UniValue getnettotals(const UniValue& params, bool fHelp); -extern UniValue setban(const UniValue& params, bool fHelp); -extern UniValue listbanned(const UniValue& params, bool fHelp); -extern UniValue clearbanned(const UniValue& params, bool fHelp); - -extern UniValue generate(const UniValue& params, bool fHelp); -extern UniValue generatetoaddress(const UniValue& params, bool fHelp); -extern UniValue getnetworkhashps(const UniValue& params, bool fHelp); -extern UniValue getmininginfo(const UniValue& params, bool fHelp); -extern UniValue prioritisetransaction(const UniValue& params, bool fHelp); -extern UniValue getblocktemplate(const UniValue& params, bool fHelp); -extern UniValue submitblock(const UniValue& params, bool fHelp); -extern UniValue estimatefee(const UniValue& params, bool fHelp); -extern UniValue estimatepriority(const UniValue& params, bool fHelp); -extern UniValue estimatesmartfee(const UniValue& params, bool fHelp); -extern UniValue estimatesmartpriority(const UniValue& params, bool fHelp); - -extern UniValue verifymessage(const UniValue& params, bool fHelp); -extern UniValue createmultisig(const UniValue& params, bool fHelp); -extern UniValue validateaddress(const UniValue& params, bool fHelp); -extern UniValue getinfo(const UniValue& params, bool fHelp); -extern UniValue getblockchaininfo(const UniValue& params, bool fHelp); -extern UniValue getnetworkinfo(const UniValue& params, bool fHelp); -extern UniValue setmocktime(const UniValue& params, bool fHelp); - -extern UniValue getrawtransaction(const UniValue& params, bool fHelp); // in rpc/rawtransaction.cpp -extern UniValue listunspent(const UniValue& params, bool fHelp); -extern UniValue lockunspent(const UniValue& params, bool fHelp); -extern UniValue listlockunspent(const UniValue& params, bool fHelp); -extern UniValue createrawtransaction(const UniValue& params, bool fHelp); -extern UniValue decoderawtransaction(const UniValue& params, bool fHelp); -extern UniValue decodescript(const UniValue& params, bool fHelp); -extern UniValue signrawtransaction(const UniValue& params, bool fHelp); -extern UniValue sendrawtransaction(const UniValue& params, bool fHelp); -extern UniValue gettxoutproof(const UniValue& params, bool fHelp); -extern UniValue verifytxoutproof(const UniValue& params, bool fHelp); - -extern UniValue getblockcount(const UniValue& params, bool fHelp); // in rpc/blockchain.cpp -extern UniValue getbestblockhash(const UniValue& params, bool fHelp); -extern UniValue getdifficulty(const UniValue& params, bool fHelp); -extern UniValue settxfee(const UniValue& params, bool fHelp); -extern UniValue getmempoolinfo(const UniValue& params, bool fHelp); -extern UniValue getrawmempool(const UniValue& params, bool fHelp); -extern UniValue getblockhash(const UniValue& params, bool fHelp); -extern UniValue getblockheader(const UniValue& params, bool fHelp); -extern UniValue getblock(const UniValue& params, bool fHelp); -extern UniValue gettxoutsetinfo(const UniValue& params, bool fHelp); -extern UniValue gettxout(const UniValue& params, bool fHelp); -extern UniValue verifychain(const UniValue& params, bool fHelp); -extern UniValue getchaintips(const UniValue& params, bool fHelp); -extern UniValue invalidateblock(const UniValue& params, bool fHelp); -extern UniValue reconsiderblock(const UniValue& params, bool fHelp); - bool StartRPC(); void InterruptRPC(); void StopRPC(); diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index d6309ca384c75..1976ee2cb61f1 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -36,7 +36,7 @@ UniValue CallRPC(string args) string strMethod = vArgs[0]; vArgs.erase(vArgs.begin()); UniValue params = RPCConvertValues(strMethod, vArgs); - + BOOST_CHECK(tableRPC[strMethod]); rpcfn_type method = tableRPC[strMethod]->actor; try { UniValue result = (*method)(params, false); diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index dadc8b948f48f..1f2e034b01a12 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -17,6 +17,8 @@ #include "txdb.h" #include "txmempool.h" #include "ui_interface.h" +#include "rpc/server.h" +#include "rpc/register.h" #ifdef ENABLE_WALLET #include "wallet/db.h" #include "wallet/wallet.h" @@ -53,9 +55,12 @@ BasicTestingSetup::~BasicTestingSetup() TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(chainName) { const CChainParams& chainparams = Params(); + // Ideally we'd move all the RPC tests to the functional testing framework + // instead of unit tests, but for now we need these here. + RegisterAllCoreRPCCommands(tableRPC); #ifdef ENABLE_WALLET bitdb.MakeMock(); - walletRegisterRPCCommands(); + RegisterWalletRPCCommands(tableRPC); #endif ClearDatadirCache(); pathTemp = GetTempPath() / strprintf("test_bitcoin_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000))); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index a1733bae77b93..61c9846e114b3 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2509,7 +2509,7 @@ extern UniValue importwallet(const UniValue& params, bool fHelp); extern UniValue importprunedfunds(const UniValue& params, bool fHelp); extern UniValue removeprunedfunds(const UniValue& params, bool fHelp); -const CRPCCommand vWalletRPCCommands[] = +static const CRPCCommand commands[] = { // category name actor (function) okSafeMode // --------------------- ------------------------ ----------------------- ---------- { "rawtransactions", "fundrawtransaction", &fundrawtransaction, false }, @@ -2559,14 +2559,8 @@ const CRPCCommand vWalletRPCCommands[] = { "wallet", "removeprunedfunds", &removeprunedfunds, true }, }; -void walletRegisterRPCCommands() +void RegisterWalletRPCCommands(CRPCTable &tableRPC) { - unsigned int vcidx; - for (vcidx = 0; vcidx < ARRAYLEN(vWalletRPCCommands); vcidx++) - { - const CRPCCommand *pcmd; - - pcmd = &vWalletRPCCommands[vcidx]; - tableRPC.appendCommand(pcmd->name, pcmd); - } + for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) + tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); } diff --git a/src/wallet/rpcwallet.h b/src/wallet/rpcwallet.h index 42e8021afa7f4..a5de7e2de1456 100644 --- a/src/wallet/rpcwallet.h +++ b/src/wallet/rpcwallet.h @@ -5,6 +5,8 @@ #ifndef BITCOIN_WALLET_RPCWALLET_H #define BITCOIN_WALLET_RPCWALLET_H -void walletRegisterRPCCommands(); +class CRPCTable; + +void RegisterWalletRPCCommands(CRPCTable &tableRPC); #endif //BITCOIN_WALLET_RPCWALLET_H From eff736e55e84441f9509285e83a1a6ee9a0c6e69 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 29 Mar 2016 16:46:20 +0200 Subject: [PATCH 0070/1802] Reformat version in UpdateTip and other messages Also remove the hardly-readable nBits from UpdateTip's log message. --- src/main.cpp | 8 ++++---- src/primitives/block.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 36189f4ffc628..d22b4c80e2217 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2549,8 +2549,8 @@ void static UpdateTip(CBlockIndex *pindexNew) { nTimeBestReceived = GetTime(); mempool.AddTransactionsUpdated(1); - LogPrintf("%s: new best=%s height=%d bits=%d log2_work=%.8g tx=%lu date=%s progress=%f cache=%.1fMiB(%utx)\n", __func__, - chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), chainActive.Tip()->nBits, + LogPrintf("%s: new best=%s height=%d version=0x%08x log2_work=%.8g tx=%lu date='%s' progress=%f cache=%.1fMiB(%utx)\n", __func__, + chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), chainActive.Tip()->nVersion, log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)chainActive.Tip()->nChainTx, DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()), Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.Tip()), pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize()); @@ -3284,8 +3284,8 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta // Reject outdated version blocks when 95% (75% on testnet) of the network has upgraded: for (int32_t version = 2; version < 5; ++version) // check for version 2, 3 and 4 upgrades if (block.nVersion < version && IsSuperMajority(version, pindexPrev, consensusParams.nMajorityRejectBlockOutdated, consensusParams)) - return state.Invalid(false, REJECT_OBSOLETE, strprintf("bad-version(v%d)", version - 1), - strprintf("rejected nVersion=%d block", version - 1)); + return state.Invalid(false, REJECT_OBSOLETE, strprintf("bad-version(0x%08x)", version - 1), + strprintf("rejected nVersion=0x%08x block", version - 1)); return true; } diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp index 59e949d71a329..6fb33230a53e0 100644 --- a/src/primitives/block.cpp +++ b/src/primitives/block.cpp @@ -18,7 +18,7 @@ uint256 CBlockHeader::GetHash() const std::string CBlock::ToString() const { std::stringstream s; - s << strprintf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%u)\n", + s << strprintf("CBlock(hash=%s, ver=0x%08x, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%u)\n", GetHash().ToString(), nVersion, hashPrevBlock.ToString(), From fa524d9ddbad0a03f9eb974100fb3b6001045645 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sat, 19 Mar 2016 21:36:32 +0100 Subject: [PATCH 0071/1802] [qa] Use python2/3 syntax --- qa/pull-tester/rpc-tests.py | 8 +-- qa/rpc-tests/bip65-cltv-p2p.py | 4 +- qa/rpc-tests/bip68-112-113-p2p.py | 6 +-- qa/rpc-tests/bip9-softforks.py | 8 +-- qa/rpc-tests/bipdersig-p2p.py | 4 +- qa/rpc-tests/decodescript.py | 4 +- qa/rpc-tests/disablewallet.py | 4 +- qa/rpc-tests/fundrawtransaction.py | 8 +-- qa/rpc-tests/importprunedfunds.py | 4 +- qa/rpc-tests/keypool.py | 6 +-- qa/rpc-tests/listtransactions.py | 4 +- qa/rpc-tests/rawtransactions.py | 2 +- qa/rpc-tests/rest.py | 9 ++-- qa/rpc-tests/smartfees.py | 2 +- qa/rpc-tests/test_framework/blockstore.py | 7 +-- qa/rpc-tests/test_framework/blocktools.py | 4 +- qa/rpc-tests/test_framework/comptool.py | 6 +-- qa/rpc-tests/test_framework/mininode.py | 51 ++++++++++--------- qa/rpc-tests/test_framework/socks5.py | 2 +- qa/rpc-tests/test_framework/test_framework.py | 4 +- qa/rpc-tests/wallet.py | 6 +-- 21 files changed, 78 insertions(+), 75 deletions(-) diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index d794dbe806cb3..6d3bda10ee6d8 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -32,13 +32,13 @@ from tests_config import * #If imported values are not defined then set to zero (or disabled) -if not vars().has_key('ENABLE_WALLET'): +if 'ENABLE_WALLET' not in vars(): ENABLE_WALLET=0 -if not vars().has_key('ENABLE_BITCOIND'): +if 'ENABLE_BITCOIND' not in vars(): ENABLE_BITCOIND=0 -if not vars().has_key('ENABLE_UTILS'): +if 'ENABLE_UTILS' not in vars(): ENABLE_UTILS=0 -if not vars().has_key('ENABLE_ZMQ'): +if 'ENABLE_ZMQ' not in vars(): ENABLE_ZMQ=0 # python-zmq may not be installed. Handle this gracefully and with some helpful info diff --git a/qa/rpc-tests/bip65-cltv-p2p.py b/qa/rpc-tests/bip65-cltv-p2p.py index bbd518cf5ff8e..316c5fe0904cc 100755 --- a/qa/rpc-tests/bip65-cltv-p2p.py +++ b/qa/rpc-tests/bip65-cltv-p2p.py @@ -11,7 +11,7 @@ from test_framework.comptool import TestInstance, TestManager from test_framework.script import CScript, OP_1NEGATE, OP_CHECKLOCKTIMEVERIFY, OP_DROP from binascii import unhexlify -import cStringIO +from io import BytesIO import time def cltv_invalidate(tx): @@ -60,7 +60,7 @@ def create_transaction(self, node, coinbase, to_address, amount): rawtx = node.createrawtransaction(inputs, outputs) signresult = node.signrawtransaction(rawtx) tx = CTransaction() - f = cStringIO.StringIO(unhexlify(signresult['hex'])) + f = BytesIO(unhexlify(signresult['hex'])) tx.deserialize(f) return tx diff --git a/qa/rpc-tests/bip68-112-113-p2p.py b/qa/rpc-tests/bip68-112-113-p2p.py index 7d3c59be3ee8f..f391cb0b7aab4 100755 --- a/qa/rpc-tests/bip68-112-113-p2p.py +++ b/qa/rpc-tests/bip68-112-113-p2p.py @@ -11,7 +11,7 @@ from test_framework.comptool import TestInstance, TestManager from test_framework.script import * from binascii import unhexlify -import cStringIO +from io import BytesIO import time ''' @@ -119,7 +119,7 @@ def create_transaction(self, node, txid, to_address, amount): outputs = { to_address : amount } rawtx = node.createrawtransaction(inputs, outputs) tx = CTransaction() - f = cStringIO.StringIO(unhexlify(rawtx)) + f = BytesIO(unhexlify(rawtx)) tx.deserialize(f) return tx @@ -127,7 +127,7 @@ def sign_transaction(self, node, unsignedtx): rawtx = ToHex(unsignedtx) signresult = node.signrawtransaction(rawtx) tx = CTransaction() - f = cStringIO.StringIO(unhexlify(signresult['hex'])) + f = BytesIO(unhexlify(signresult['hex'])) tx.deserialize(f) return tx diff --git a/qa/rpc-tests/bip9-softforks.py b/qa/rpc-tests/bip9-softforks.py index cbb1b7d4cee89..445c04494442a 100755 --- a/qa/rpc-tests/bip9-softforks.py +++ b/qa/rpc-tests/bip9-softforks.py @@ -11,7 +11,7 @@ from test_framework.comptool import TestInstance, TestManager from test_framework.script import CScript, OP_1NEGATE, OP_NOP3, OP_DROP from binascii import hexlify, unhexlify -import cStringIO +from io import BytesIO import time import itertools @@ -53,7 +53,7 @@ def create_transaction(self, node, coinbase, to_address, amount): outputs = { to_address : amount } rawtx = node.createrawtransaction(inputs, outputs) tx = CTransaction() - f = cStringIO.StringIO(unhexlify(rawtx)) + f = BytesIO(unhexlify(rawtx)) tx.deserialize(f) tx.nVersion = 2 return tx @@ -61,7 +61,7 @@ def create_transaction(self, node, coinbase, to_address, amount): def sign_transaction(self, node, tx): signresult = node.signrawtransaction(hexlify(tx.serialize())) tx = CTransaction() - f = cStringIO.StringIO(unhexlify(signresult['hex'])) + f = BytesIO(unhexlify(signresult['hex'])) tx.deserialize(f) return tx @@ -217,4 +217,4 @@ def mtp_invalidate(self, tx): tx.nLockTime = self.last_block_time if __name__ == '__main__': - BIP9SoftForksTest().main() \ No newline at end of file + BIP9SoftForksTest().main() diff --git a/qa/rpc-tests/bipdersig-p2p.py b/qa/rpc-tests/bipdersig-p2p.py index 544e4a96701f3..f0d81a6f441c0 100755 --- a/qa/rpc-tests/bipdersig-p2p.py +++ b/qa/rpc-tests/bipdersig-p2p.py @@ -11,7 +11,7 @@ from test_framework.comptool import TestInstance, TestManager from test_framework.script import CScript from binascii import unhexlify -import cStringIO +from io import BytesIO import time # A canonical signature consists of: @@ -68,7 +68,7 @@ def create_transaction(self, node, coinbase, to_address, amount): rawtx = node.createrawtransaction(inputs, outputs) signresult = node.signrawtransaction(rawtx) tx = CTransaction() - f = cStringIO.StringIO(unhexlify(signresult['hex'])) + f = BytesIO(unhexlify(signresult['hex'])) tx.deserialize(f) return tx diff --git a/qa/rpc-tests/decodescript.py b/qa/rpc-tests/decodescript.py index 490808d49dd53..2dfafac2fc180 100755 --- a/qa/rpc-tests/decodescript.py +++ b/qa/rpc-tests/decodescript.py @@ -7,7 +7,7 @@ from test_framework.util import * from test_framework.mininode import * from binascii import hexlify, unhexlify -from cStringIO import StringIO +from io import BytesIO class DecodeScriptTest(BitcoinTestFramework): """Tests decoding scripts via RPC command "decodescript".""" @@ -131,7 +131,7 @@ def decoderawtransaction_asm_sighashtype(self): assert_equal('OP_DUP OP_HASH160 dc863734a218bfe83ef770ee9d41a27f824a6e56 OP_EQUALVERIFY OP_CHECKSIG', rpc_result['vout'][0]['scriptPubKey']['asm']) assert_equal('OP_HASH160 2a5edea39971049a540474c6a99edf0aa4074c58 OP_EQUAL', rpc_result['vout'][1]['scriptPubKey']['asm']) txSave = CTransaction() - txSave.deserialize(StringIO(unhexlify(tx))) + txSave.deserialize(BytesIO(unhexlify(tx))) # make sure that a specifically crafted op_return value will not pass all the IsDERSignature checks and then get decoded as a sighash type tx = '01000000015ded05872fdbda629c7d3d02b194763ce3b9b1535ea884e3c8e765d42e316724020000006b48304502204c10d4064885c42638cbff3585915b322de33762598321145ba033fc796971e2022100bb153ad3baa8b757e30a2175bd32852d2e1cb9080f84d7e32fcdfd667934ef1b012103163c0ff73511ea1743fb5b98384a2ff09dd06949488028fd819f4d83f56264efffffffff0200000000000000000b6a0930060201000201000180380100000000001976a9141cabd296e753837c086da7a45a6c2fe0d49d7b7b88ac00000000' diff --git a/qa/rpc-tests/disablewallet.py b/qa/rpc-tests/disablewallet.py index 5af8158467969..cb868029fa327 100755 --- a/qa/rpc-tests/disablewallet.py +++ b/qa/rpc-tests/disablewallet.py @@ -32,7 +32,7 @@ def run_test (self): # Checking mining to an address without a wallet try: self.nodes[0].generatetoaddress(1, 'mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ') - except JSONRPCException,e: + except JSONRPCException as e: assert("Invalid address" not in e.error['message']) assert("ProcessNewBlock, block not accepted" not in e.error['message']) assert("Couldn't create new block" not in e.error['message']) @@ -40,7 +40,7 @@ def run_test (self): try: self.nodes[0].generatetoaddress(1, '3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy') raise AssertionError("Must not mine to invalid address!") - except JSONRPCException,e: + except JSONRPCException as e: assert("Invalid address" in e.error['message']) if __name__ == '__main__': diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py index 4458712815c57..82f2f4f5c52b8 100755 --- a/qa/rpc-tests/fundrawtransaction.py +++ b/qa/rpc-tests/fundrawtransaction.py @@ -209,7 +209,7 @@ def run_test(self): matchingOuts = 0 for i, out in enumerate(dec_tx['vout']): totalOut += out['value'] - if outputs.has_key(out['scriptPubKey']['addresses'][0]): + if out['scriptPubKey']['addresses'][0] in outputs: matchingOuts+=1 else: assert_equal(i, rawtxfund['changepos']) @@ -249,7 +249,7 @@ def run_test(self): matchingOuts = 0 for out in dec_tx['vout']: totalOut += out['value'] - if outputs.has_key(out['scriptPubKey']['addresses'][0]): + if out['scriptPubKey']['addresses'][0] in outputs: matchingOuts+=1 assert_equal(matchingOuts, 1) @@ -291,7 +291,7 @@ def run_test(self): matchingOuts = 0 for out in dec_tx['vout']: totalOut += out['value'] - if outputs.has_key(out['scriptPubKey']['addresses'][0]): + if out['scriptPubKey']['addresses'][0] in outputs: matchingOuts+=1 assert_equal(matchingOuts, 2) @@ -309,7 +309,7 @@ def run_test(self): try: rawtxfund = self.nodes[2].fundrawtransaction(rawtx) raise AssertionError("Spent more than available") - except JSONRPCException,e: + except JSONRPCException as e: assert("Insufficient" in e.error['message']) diff --git a/qa/rpc-tests/importprunedfunds.py b/qa/rpc-tests/importprunedfunds.py index 5cbdcde9aa997..db875800d4f0f 100755 --- a/qa/rpc-tests/importprunedfunds.py +++ b/qa/rpc-tests/importprunedfunds.py @@ -82,7 +82,7 @@ def run_test (self): #Import with no affiliated address try: result1 = self.nodes[1].importprunedfunds(rawtxn1, proof1, "") - except JSONRPCException,e: + except JSONRPCException as e: errorString = e.error['message'] assert('No addresses' in errorString) @@ -119,7 +119,7 @@ def run_test (self): try: self.nodes[1].removeprunedfunds(txnid1) - except JSONRPCException,e: + except JSONRPCException as e: errorString = e.error['message'] assert('does not exist' in errorString) diff --git a/qa/rpc-tests/keypool.py b/qa/rpc-tests/keypool.py index 95d0d6832a91f..5253d49c308f7 100755 --- a/qa/rpc-tests/keypool.py +++ b/qa/rpc-tests/keypool.py @@ -46,7 +46,7 @@ def run_test(self): try: addr = nodes[0].getnewaddress() raise AssertionError('Keypool should be exhausted after one address') - except JSONRPCException,e: + except JSONRPCException as e: assert(e.error['code']==-12) # put three new keys in the keypool @@ -66,7 +66,7 @@ def run_test(self): try: addr = nodes[0].getrawchangeaddress() raise AssertionError('Keypool should be exhausted after three addresses') - except JSONRPCException,e: + except JSONRPCException as e: assert(e.error['code']==-12) # refill keypool with three new addresses @@ -84,7 +84,7 @@ def run_test(self): try: nodes[0].generate(1) raise AssertionError('Keypool should be exhausted after three addesses') - except JSONRPCException,e: + except JSONRPCException as e: assert(e.error['code']==-12) def setup_chain(self): diff --git a/qa/rpc-tests/listtransactions.py b/qa/rpc-tests/listtransactions.py index da1e98dc33df0..c4eca519b7cf9 100755 --- a/qa/rpc-tests/listtransactions.py +++ b/qa/rpc-tests/listtransactions.py @@ -8,12 +8,12 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * from test_framework.mininode import CTransaction, COIN -import cStringIO +from io import BytesIO import binascii def txFromHex(hexstring): tx = CTransaction() - f = cStringIO.StringIO(binascii.unhexlify(hexstring)) + f = BytesIO(binascii.unhexlify(hexstring)) tx.deserialize(f) return tx diff --git a/qa/rpc-tests/rawtransactions.py b/qa/rpc-tests/rawtransactions.py index dd9e5e28a526f..9f660c8bdadeb 100755 --- a/qa/rpc-tests/rawtransactions.py +++ b/qa/rpc-tests/rawtransactions.py @@ -59,7 +59,7 @@ def run_test(self): errorString = "" try: rawtx = self.nodes[2].sendrawtransaction(rawtx['hex']) - except JSONRPCException,e: + except JSONRPCException as e: errorString = e.error['message'] assert("Missing inputs" in errorString) diff --git a/qa/rpc-tests/rest.py b/qa/rpc-tests/rest.py index 8c835365010e8..3c8a405bdd044 100755 --- a/qa/rpc-tests/rest.py +++ b/qa/rpc-tests/rest.py @@ -11,8 +11,9 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * from struct import * +from io import BytesIO +from codecs import encode import binascii -import StringIO try: import http.client as httplib @@ -146,7 +147,7 @@ def run_test(self): binaryRequest += pack("i", 0) bin_response = http_post_call(url.hostname, url.port, '/rest/getutxos'+self.FORMAT_SEPARATOR+'bin', binaryRequest) - output = StringIO.StringIO() + output = BytesIO() output.write(bin_response) output.seek(0) chainHeight = unpack("i", output.read(4))[0] @@ -233,7 +234,7 @@ def run_test(self): assert_equal(response_hex.status, 200) assert_greater_than(int(response_hex.getheader('content-length')), 160) response_hex_str = response_hex.read() - assert_equal(response_str.encode("hex")[0:160], response_hex_str[0:160]) + assert_equal(encode(response_str, "hex")[0:160], response_hex_str[0:160]) # compare with hex block header response_header_hex = http_get_call(url.hostname, url.port, '/rest/headers/1/'+bb_hash+self.FORMAT_SEPARATOR+"hex", True) @@ -241,7 +242,7 @@ def run_test(self): assert_greater_than(int(response_header_hex.getheader('content-length')), 160) response_header_hex_str = response_header_hex.read() assert_equal(response_hex_str[0:160], response_header_hex_str[0:160]) - assert_equal(response_header_str.encode("hex")[0:160], response_header_hex_str[0:160]) + assert_equal(encode(response_header_str, "hex")[0:160], response_header_hex_str[0:160]) # check json format block_json_string = http_get_call(url.hostname, url.port, '/rest/block/'+bb_hash+self.FORMAT_SEPARATOR+'json') diff --git a/qa/rpc-tests/smartfees.py b/qa/rpc-tests/smartfees.py index b209ae0c16338..6274cd05301e6 100755 --- a/qa/rpc-tests/smartfees.py +++ b/qa/rpc-tests/smartfees.py @@ -105,7 +105,7 @@ def check_estimates(node, fees_seen, max_invalid, print_estimates = True): print([str(all_estimates[e-1]) for e in [1,2,3,6,15,25]]) delta = 1.0e-6 # account for rounding error last_e = max(fees_seen) - for e in filter(lambda x: x >= 0, all_estimates): + for e in [x for x in all_estimates if x >= 0]: # Estimates should be within the bounds of what transactions fees actually were: if float(e)+delta < min(fees_seen) or float(e)-delta > max(fees_seen): raise AssertionError("Estimated fee (%f) out of range (%f,%f)" diff --git a/qa/rpc-tests/test_framework/blockstore.py b/qa/rpc-tests/test_framework/blockstore.py index b9775b477cc28..73d9ffbb2fe05 100644 --- a/qa/rpc-tests/test_framework/blockstore.py +++ b/qa/rpc-tests/test_framework/blockstore.py @@ -3,8 +3,9 @@ # and for constructing a getheaders message # -from mininode import * +from .mininode import * import dbm +from io import BytesIO class BlockStore(object): def __init__(self, datadir): @@ -21,7 +22,7 @@ def get(self, blockhash): serialized_block = self.blockDB[repr(blockhash)] except KeyError: return None - f = cStringIO.StringIO(serialized_block) + f = BytesIO(serialized_block) ret = CBlock() ret.deserialize(f) ret.calc_sha256() @@ -115,7 +116,7 @@ def get(self, txhash): serialized_tx = self.txDB[repr(txhash)] except KeyError: return None - f = cStringIO.StringIO(serialized_tx) + f = BytesIO(serialized_tx) ret = CTransaction() ret.deserialize(f) ret.calc_sha256() diff --git a/qa/rpc-tests/test_framework/blocktools.py b/qa/rpc-tests/test_framework/blocktools.py index b075f69c4751c..425e6dcdde419 100644 --- a/qa/rpc-tests/test_framework/blocktools.py +++ b/qa/rpc-tests/test_framework/blocktools.py @@ -4,8 +4,8 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. # -from mininode import * -from script import CScript, OP_TRUE, OP_CHECKSIG +from .mininode import * +from .script import CScript, OP_TRUE, OP_CHECKSIG # Create a block (with regtest difficulty) def create_block(hashprev, coinbase, nTime=None): diff --git a/qa/rpc-tests/test_framework/comptool.py b/qa/rpc-tests/test_framework/comptool.py index f19edbf06900b..6279070fbc1bb 100755 --- a/qa/rpc-tests/test_framework/comptool.py +++ b/qa/rpc-tests/test_framework/comptool.py @@ -4,9 +4,9 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. # -from mininode import * -from blockstore import BlockStore, TxStore -from util import p2p_port +from .mininode import * +from .blockstore import BlockStore, TxStore +from .util import p2p_port ''' This is a tool for comparing two or more bitcoinds to each other diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index 20386c642c67b..07d1827dfe285 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -24,7 +24,8 @@ import time import sys import random -import cStringIO +from io import BytesIO +from codecs import encode import hashlib from threading import RLock from threading import Thread @@ -75,12 +76,12 @@ def deser_string(f): def ser_string(s): if len(s) < 253: - return chr(len(s)) + s + return struct.pack("B", len(s)) + s elif len(s) < 0x10000: - return chr(253) + struct.pack(" Date: Sun, 20 Mar 2016 18:18:32 +0100 Subject: [PATCH 0072/1802] [qa] rpc-tests: Properly use integers, floats --- qa/rpc-tests/bip65-cltv-p2p.py | 2 +- qa/rpc-tests/bip68-sequence.py | 6 +-- qa/rpc-tests/bip9-softforks.py | 2 +- qa/rpc-tests/bipdersig-p2p.py | 2 +- qa/rpc-tests/fundrawtransaction.py | 2 +- qa/rpc-tests/listtransactions.py | 2 +- qa/rpc-tests/maxuploadtarget.py | 2 +- qa/rpc-tests/p2p-acceptblock.py | 2 +- qa/rpc-tests/p2p-fullblocktest.py | 4 +- qa/rpc-tests/pruning.py | 6 +-- qa/rpc-tests/replace-by-fee.py | 50 +++++++++++------------ qa/rpc-tests/smartfees.py | 2 +- qa/rpc-tests/test_framework/blocktools.py | 2 +- qa/rpc-tests/test_framework/mininode.py | 4 +- qa/rpc-tests/test_framework/netutil.py | 2 +- 15 files changed, 45 insertions(+), 45 deletions(-) diff --git a/qa/rpc-tests/bip65-cltv-p2p.py b/qa/rpc-tests/bip65-cltv-p2p.py index 316c5fe0904cc..54559c3541f2e 100755 --- a/qa/rpc-tests/bip65-cltv-p2p.py +++ b/qa/rpc-tests/bip65-cltv-p2p.py @@ -70,7 +70,7 @@ def get_tests(self): height = 3 # height of the next block to build self.tip = int ("0x" + self.nodes[0].getbestblockhash() + "L", 0) self.nodeaddress = self.nodes[0].getnewaddress() - self.last_block_time = time.time() + self.last_block_time = int(time.time()) ''' 98 more version 3 blocks ''' test_blocks = [] diff --git a/qa/rpc-tests/bip68-sequence.py b/qa/rpc-tests/bip68-sequence.py index 84f941da33f6d..377a35b6872c7 100755 --- a/qa/rpc-tests/bip68-sequence.py +++ b/qa/rpc-tests/bip68-sequence.py @@ -61,7 +61,7 @@ def test_disable_flag(self): utxo = utxos[0] tx1 = CTransaction() - value = satoshi_round(utxo["amount"] - self.relayfee)*COIN + value = int(satoshi_round(utxo["amount"] - self.relayfee)*COIN) # Check that the disable flag disables relative locktime. # If sequence locks were used, this would require 1 block for the @@ -179,8 +179,8 @@ def test_sequence_lock_confirmed_inputs(self): tx.vin.append(CTxIn(COutPoint(int(utxos[j]["txid"], 16), utxos[j]["vout"]), nSequence=sequence_value)) value += utxos[j]["amount"]*COIN # Overestimate the size of the tx - signatures should be less than 120 bytes, and leave 50 for the output - tx_size = len(ToHex(tx))/2 + 120*num_inputs + 50 - tx.vout.append(CTxOut(value-self.relayfee*tx_size*COIN/1000, CScript([b'a']))) + tx_size = len(ToHex(tx))//2 + 120*num_inputs + 50 + tx.vout.append(CTxOut(int(value-self.relayfee*tx_size*COIN/1000), CScript([b'a']))) rawtx = self.nodes[0].signrawtransaction(ToHex(tx))["hex"] try: diff --git a/qa/rpc-tests/bip9-softforks.py b/qa/rpc-tests/bip9-softforks.py index 445c04494442a..98975e719335c 100755 --- a/qa/rpc-tests/bip9-softforks.py +++ b/qa/rpc-tests/bip9-softforks.py @@ -91,7 +91,7 @@ def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignatu self.height = 3 # height of the next block to build self.tip = int ("0x" + self.nodes[0].getbestblockhash() + "L", 0) self.nodeaddress = self.nodes[0].getnewaddress() - self.last_block_time = time.time() + self.last_block_time = int(time.time()) assert_equal(self.get_bip9_status(bipName)['status'], 'defined') diff --git a/qa/rpc-tests/bipdersig-p2p.py b/qa/rpc-tests/bipdersig-p2p.py index f0d81a6f441c0..95be385d93fb0 100755 --- a/qa/rpc-tests/bipdersig-p2p.py +++ b/qa/rpc-tests/bipdersig-p2p.py @@ -78,7 +78,7 @@ def get_tests(self): height = 3 # height of the next block to build self.tip = int ("0x" + self.nodes[0].getbestblockhash() + "L", 0) self.nodeaddress = self.nodes[0].getnewaddress() - self.last_block_time = time.time() + self.last_block_time = int(time.time()) ''' 98 more version 2 blocks ''' test_blocks = [] diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py index 82f2f4f5c52b8..82c9e48a49735 100755 --- a/qa/rpc-tests/fundrawtransaction.py +++ b/qa/rpc-tests/fundrawtransaction.py @@ -48,7 +48,7 @@ def run_test(self): watchonly_address = self.nodes[0].getnewaddress() watchonly_pubkey = self.nodes[0].validateaddress(watchonly_address)["pubkey"] - watchonly_amount = 200 + watchonly_amount = Decimal(200) self.nodes[3].importpubkey(watchonly_pubkey, "", True) watchonly_txid = self.nodes[0].sendtoaddress(watchonly_address, watchonly_amount) self.nodes[0].sendtoaddress(self.nodes[3].getnewaddress(), watchonly_amount / 10) diff --git a/qa/rpc-tests/listtransactions.py b/qa/rpc-tests/listtransactions.py index c4eca519b7cf9..8fe72d95d1d0d 100755 --- a/qa/rpc-tests/listtransactions.py +++ b/qa/rpc-tests/listtransactions.py @@ -192,7 +192,7 @@ def get_unconfirmed_utxo_entry(node, txid_to_match): # Replace tx3, and check that tx4 becomes unknown tx3_b = tx3_modified - tx3_b.vout[0].nValue -= 0.004 * COIN # bump the fee + tx3_b.vout[0].nValue -= int(Decimal("0.004") * COIN) # bump the fee tx3_b = binascii.hexlify(tx3_b.serialize()).decode('utf-8') tx3_b_signed = self.nodes[0].signrawtransaction(tx3_b)['hex'] txid_3b = self.nodes[0].sendrawtransaction(tx3_b_signed, True) diff --git a/qa/rpc-tests/maxuploadtarget.py b/qa/rpc-tests/maxuploadtarget.py index e4127500cd89b..be45fecb5b32a 100755 --- a/qa/rpc-tests/maxuploadtarget.py +++ b/qa/rpc-tests/maxuploadtarget.py @@ -177,7 +177,7 @@ def run_test(self): max_bytes_per_day = 200*1024*1024 daily_buffer = 144 * MAX_BLOCK_SIZE max_bytes_available = max_bytes_per_day - daily_buffer - success_count = max_bytes_available / old_block_size + success_count = max_bytes_available // old_block_size # 144MB will be reserved for relaying new blocks, so expect this to # succeed for ~70 tries. diff --git a/qa/rpc-tests/p2p-acceptblock.py b/qa/rpc-tests/p2p-acceptblock.py index bf355780c19c4..e429fcc5fe9d4 100755 --- a/qa/rpc-tests/p2p-acceptblock.py +++ b/qa/rpc-tests/p2p-acceptblock.py @@ -150,7 +150,7 @@ def run_test(self): # 2. Send one block that builds on each tip. # This should be accepted. blocks_h2 = [] # the height 2 blocks on each node's chain - block_time = time.time() + 1 + block_time = int(time.time()) + 1 for i in xrange(2): blocks_h2.append(create_block(tips[i], create_coinbase(2), block_time)) blocks_h2[i].solve() diff --git a/qa/rpc-tests/p2p-fullblocktest.py b/qa/rpc-tests/p2p-fullblocktest.py index b1e8ca53ee1cf..131350c98ddf0 100755 --- a/qa/rpc-tests/p2p-fullblocktest.py +++ b/qa/rpc-tests/p2p-fullblocktest.py @@ -269,7 +269,7 @@ def update_block(block_number, new_transactions): # \-> b3 (1) -> b4 (2) # Test that a block with a lot of checksigs is okay - lots_of_checksigs = CScript([OP_CHECKSIG] * (1000000 / 50 - 1)) + lots_of_checksigs = CScript([OP_CHECKSIG] * (1000000 // 50 - 1)) tip(13) block(15, spend=out5, script=lots_of_checksigs) yield accepted() @@ -277,7 +277,7 @@ def update_block(block_number, new_transactions): # Test that a block with too many checksigs is rejected out6 = get_spendable_output() - too_many_checksigs = CScript([OP_CHECKSIG] * (1000000 / 50)) + too_many_checksigs = CScript([OP_CHECKSIG] * (1000000 // 50)) block(16, spend=out6, script=too_many_checksigs) yield rejected(RejectResult(16, 'bad-blk-sigops')) diff --git a/qa/rpc-tests/pruning.py b/qa/rpc-tests/pruning.py index b0f4b88aee551..dd2adea950f23 100755 --- a/qa/rpc-tests/pruning.py +++ b/qa/rpc-tests/pruning.py @@ -15,7 +15,7 @@ from test_framework.util import * def calc_usage(blockdir): - return sum(os.path.getsize(blockdir+f) for f in os.listdir(blockdir) if os.path.isfile(blockdir+f))/(1024*1024) + return sum(os.path.getsize(blockdir+f) for f in os.listdir(blockdir) if os.path.isfile(blockdir+f)) / (1024. * 1024.) class PruneTest(BitcoinTestFramework): @@ -56,7 +56,7 @@ def create_big_chain(self): self.nodes[1].generate(200) sync_blocks(self.nodes[0:2]) self.nodes[0].generate(150) - # Then mine enough full blocks to create more than 550MB of data + # Then mine enough full blocks to create more than 550MiB of data for i in xrange(645): self.mine_full_block(self.nodes[0], self.address[0]) @@ -66,7 +66,7 @@ def test_height_min(self): if not os.path.isfile(self.prunedir+"blk00000.dat"): raise AssertionError("blk00000.dat is missing, pruning too early") print "Success" - print "Though we're already using more than 550MB, current usage:", calc_usage(self.prunedir) + print "Though we're already using more than 550MiB, current usage:", calc_usage(self.prunedir) print "Mining 25 more blocks should cause the first block file to be pruned" # Pruning doesn't run until we're allocating another chunk, 20 full blocks past the height cutoff will ensure this for i in xrange(25): diff --git a/qa/rpc-tests/replace-by-fee.py b/qa/rpc-tests/replace-by-fee.py index eded24f405395..b951900c4dbd9 100755 --- a/qa/rpc-tests/replace-by-fee.py +++ b/qa/rpc-tests/replace-by-fee.py @@ -119,7 +119,7 @@ def run_test(self): def test_simple_doublespend(self): """Simple doublespend""" - tx0_outpoint = make_utxo(self.nodes[0], 1.1*COIN) + tx0_outpoint = make_utxo(self.nodes[0], int(1.1*COIN)) tx1a = CTransaction() tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)] @@ -143,7 +143,7 @@ def test_simple_doublespend(self): # Extra 0.1 BTC fee tx1b = CTransaction() tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)] - tx1b.vout = [CTxOut(0.9*COIN, CScript([b'b']))] + tx1b.vout = [CTxOut(int(0.9*COIN), CScript([b'b']))] tx1b_hex = txToHex(tx1b) tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True) @@ -235,7 +235,7 @@ def branch(prevout, initial_value, max_txs, tree_width=5, fee=0.0001*COIN, _tota _total_txs=_total_txs): yield x - fee = 0.0001*COIN + fee = int(0.0001*COIN) n = MAX_REPLACEMENT_LIMIT tree_txs = list(branch(tx0_outpoint, initial_nValue, n, fee=fee)) assert_equal(len(tree_txs), n) @@ -268,7 +268,7 @@ def branch(prevout, initial_value, max_txs, tree_width=5, fee=0.0001*COIN, _tota # Try again, but with more total transactions than the "max txs # double-spent at once" anti-DoS limit. for n in (MAX_REPLACEMENT_LIMIT+1, MAX_REPLACEMENT_LIMIT*2): - fee = 0.0001*COIN + fee = int(0.0001*COIN) tx0_outpoint = make_utxo(self.nodes[0], initial_nValue) tree_txs = list(branch(tx0_outpoint, initial_nValue, n, fee=fee)) assert_equal(len(tree_txs), n) @@ -291,7 +291,7 @@ def branch(prevout, initial_value, max_txs, tree_width=5, fee=0.0001*COIN, _tota def test_replacement_feeperkb(self): """Replacement requires fee-per-KB to be higher""" - tx0_outpoint = make_utxo(self.nodes[0], 1.1*COIN) + tx0_outpoint = make_utxo(self.nodes[0], int(1.1*COIN)) tx1a = CTransaction() tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)] @@ -303,7 +303,7 @@ def test_replacement_feeperkb(self): # rejected. tx1b = CTransaction() tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)] - tx1b.vout = [CTxOut(0.001*COIN, CScript([b'a'*999000]))] + tx1b.vout = [CTxOut(int(0.001*COIN), CScript([b'a'*999000]))] tx1b_hex = txToHex(tx1b) try: @@ -315,12 +315,12 @@ def test_replacement_feeperkb(self): def test_spends_of_conflicting_outputs(self): """Replacements that spend conflicting tx outputs are rejected""" - utxo1 = make_utxo(self.nodes[0], 1.2*COIN) - utxo2 = make_utxo(self.nodes[0], 3.0*COIN) + utxo1 = make_utxo(self.nodes[0], int(1.2*COIN)) + utxo2 = make_utxo(self.nodes[0], 3*COIN) tx1a = CTransaction() tx1a.vin = [CTxIn(utxo1, nSequence=0)] - tx1a.vout = [CTxOut(1.1*COIN, CScript([b'a']))] + tx1a.vout = [CTxOut(int(1.1*COIN), CScript([b'a']))] tx1a_hex = txToHex(tx1a) tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True) @@ -343,7 +343,7 @@ def test_spends_of_conflicting_outputs(self): # Spend tx1a's output to test the indirect case. tx1b = CTransaction() tx1b.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0)] - tx1b.vout = [CTxOut(1.0*COIN, CScript([b'a']))] + tx1b.vout = [CTxOut(1*COIN, CScript([b'a']))] tx1b_hex = txToHex(tx1b) tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True) tx1b_txid = int(tx1b_txid, 16) @@ -363,12 +363,12 @@ def test_spends_of_conflicting_outputs(self): def test_new_unconfirmed_inputs(self): """Replacements that add new unconfirmed inputs are rejected""" - confirmed_utxo = make_utxo(self.nodes[0], 1.1*COIN) - unconfirmed_utxo = make_utxo(self.nodes[0], 0.1*COIN, False) + confirmed_utxo = make_utxo(self.nodes[0], int(1.1*COIN)) + unconfirmed_utxo = make_utxo(self.nodes[0], int(0.1*COIN), False) tx1 = CTransaction() tx1.vin = [CTxIn(confirmed_utxo)] - tx1.vout = [CTxOut(1.0*COIN, CScript([b'a']))] + tx1.vout = [CTxOut(1*COIN, CScript([b'a']))] tx1_hex = txToHex(tx1) tx1_txid = self.nodes[0].sendrawtransaction(tx1_hex, True) @@ -392,7 +392,7 @@ def test_too_many_replacements(self): # Start by creating a single transaction with many outputs initial_nValue = 10*COIN utxo = make_utxo(self.nodes[0], initial_nValue) - fee = 0.0001*COIN + fee = int(0.0001*COIN) split_value = int((initial_nValue-fee)/(MAX_REPLACEMENT_LIMIT+1)) actual_fee = initial_nValue - split_value*(MAX_REPLACEMENT_LIMIT+1) @@ -445,7 +445,7 @@ def test_too_many_replacements(self): def test_opt_in(self): """ Replacing should only work if orig tx opted in """ - tx0_outpoint = make_utxo(self.nodes[0], 1.1*COIN) + tx0_outpoint = make_utxo(self.nodes[0], int(1.1*COIN)) # Create a non-opting in transaction tx1a = CTransaction() @@ -457,7 +457,7 @@ def test_opt_in(self): # Shouldn't be able to double-spend tx1b = CTransaction() tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)] - tx1b.vout = [CTxOut(0.9*COIN, CScript([b'b']))] + tx1b.vout = [CTxOut(int(0.9*COIN), CScript([b'b']))] tx1b_hex = txToHex(tx1b) try: @@ -468,7 +468,7 @@ def test_opt_in(self): print tx1b_txid assert(False) - tx1_outpoint = make_utxo(self.nodes[0], 1.1*COIN) + tx1_outpoint = make_utxo(self.nodes[0], int(1.1*COIN)) # Create a different non-opting in transaction tx2a = CTransaction() @@ -480,7 +480,7 @@ def test_opt_in(self): # Still shouldn't be able to double-spend tx2b = CTransaction() tx2b.vin = [CTxIn(tx1_outpoint, nSequence=0)] - tx2b.vout = [CTxOut(0.9*COIN, CScript([b'b']))] + tx2b.vout = [CTxOut(int(0.9*COIN), CScript([b'b']))] tx2b_hex = txToHex(tx2b) try: @@ -500,19 +500,19 @@ def test_opt_in(self): tx3a = CTransaction() tx3a.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0xffffffff), CTxIn(COutPoint(tx2a_txid, 0), nSequence=0xfffffffd)] - tx3a.vout = [CTxOut(0.9*COIN, CScript([b'c'])), CTxOut(0.9*COIN, CScript([b'd']))] + tx3a.vout = [CTxOut(int(0.9*COIN), CScript([b'c'])), CTxOut(int(0.9*COIN), CScript([b'd']))] tx3a_hex = txToHex(tx3a) self.nodes[0].sendrawtransaction(tx3a_hex, True) tx3b = CTransaction() tx3b.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0)] - tx3b.vout = [CTxOut(0.5*COIN, CScript([b'e']))] + tx3b.vout = [CTxOut(int(0.5*COIN), CScript([b'e']))] tx3b_hex = txToHex(tx3b) tx3c = CTransaction() tx3c.vin = [CTxIn(COutPoint(tx2a_txid, 0), nSequence=0)] - tx3c.vout = [CTxOut(0.5*COIN, CScript([b'f']))] + tx3c.vout = [CTxOut(int(0.5*COIN), CScript([b'f']))] tx3c_hex = txToHex(tx3c) self.nodes[0].sendrawtransaction(tx3b_hex, True) @@ -525,7 +525,7 @@ def test_prioritised_transactions(self): # correctly used by replacement logic # 1. Check that feeperkb uses modified fees - tx0_outpoint = make_utxo(self.nodes[0], 1.1*COIN) + tx0_outpoint = make_utxo(self.nodes[0], int(1.1*COIN)) tx1a = CTransaction() tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)] @@ -536,7 +536,7 @@ def test_prioritised_transactions(self): # Higher fee, but the actual fee per KB is much lower. tx1b = CTransaction() tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)] - tx1b.vout = [CTxOut(0.001*COIN, CScript([b'a'*740000]))] + tx1b.vout = [CTxOut(int(0.001*COIN), CScript([b'a'*740000]))] tx1b_hex = txToHex(tx1b) # Verify tx1b cannot replace tx1a. @@ -556,7 +556,7 @@ def test_prioritised_transactions(self): assert(tx1b_txid in self.nodes[0].getrawmempool()) # 2. Check that absolute fee checks use modified fee. - tx1_outpoint = make_utxo(self.nodes[0], 1.1*COIN) + tx1_outpoint = make_utxo(self.nodes[0], int(1.1*COIN)) tx2a = CTransaction() tx2a.vin = [CTxIn(tx1_outpoint, nSequence=0)] @@ -567,7 +567,7 @@ def test_prioritised_transactions(self): # Lower fee, but we'll prioritise it tx2b = CTransaction() tx2b.vin = [CTxIn(tx1_outpoint, nSequence=0)] - tx2b.vout = [CTxOut(1.01*COIN, CScript([b'a']))] + tx2b.vout = [CTxOut(int(1.01*COIN), CScript([b'a']))] tx2b.rehash() tx2b_hex = txToHex(tx2b) diff --git a/qa/rpc-tests/smartfees.py b/qa/rpc-tests/smartfees.py index 6274cd05301e6..2c064ad8a03a9 100755 --- a/qa/rpc-tests/smartfees.py +++ b/qa/rpc-tests/smartfees.py @@ -219,7 +219,7 @@ def transact_and_mine(self, numblocks, mining_node): from_index = random.randint(1,2) (txhex, fee) = small_txpuzzle_randfee(self.nodes[from_index], self.confutxo, self.memutxo, Decimal("0.005"), min_fee, min_fee) - tx_kbytes = (len(txhex)/2)/1000.0 + tx_kbytes = (len(txhex) // 2) / 1000.0 self.fees_per_kb.append(float(fee)/tx_kbytes) sync_mempools(self.nodes[0:3],.1) mined = mining_node.getblock(mining_node.generate(1)[0],True)["tx"] diff --git a/qa/rpc-tests/test_framework/blocktools.py b/qa/rpc-tests/test_framework/blocktools.py index 425e6dcdde419..afa0f5f9ba5ec 100644 --- a/qa/rpc-tests/test_framework/blocktools.py +++ b/qa/rpc-tests/test_framework/blocktools.py @@ -29,7 +29,7 @@ def serialize_script_num(value): neg = value < 0 absvalue = -value if neg else value while (absvalue): - r.append(chr(absvalue & 0xff)) + r.append(int(absvalue & 0xff)) absvalue >>= 8 if r[-1] & 0x80: r.append(0x80 if neg else 0) diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index 07d1827dfe285..0c40730f9005e 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -641,7 +641,7 @@ class msg_version(object): def __init__(self): self.nVersion = MY_VERSION self.nServices = 1 - self.nTime = time.time() + self.nTime = int(time.time()) self.addrTo = CAddress() self.addrFrom = CAddress() self.nNonce = random.getrandbits(64) @@ -986,7 +986,7 @@ class msg_reject(object): def __init__(self): self.message = "" - self.code = "" + self.code = 0 self.reason = "" self.data = 0L diff --git a/qa/rpc-tests/test_framework/netutil.py b/qa/rpc-tests/test_framework/netutil.py index 50daa8793732a..4e4c81d397199 100644 --- a/qa/rpc-tests/test_framework/netutil.py +++ b/qa/rpc-tests/test_framework/netutil.py @@ -45,7 +45,7 @@ def _convert_ip_port(array): # convert host from mangled-per-four-bytes form as used by kernel host = binascii.unhexlify(host) host_out = '' - for x in range(0, len(host)/4): + for x in range(0, len(host) // 4): (val,) = struct.unpack('=I', host[x*4:(x+1)*4]) host_out += '%08x' % val From faaa3c9b6546d9a64cece4ff0223f0b167feb6ff Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 31 Mar 2016 18:33:15 +0200 Subject: [PATCH 0073/1802] [qa] mininode: Catch exceptions in got_data --- qa/rpc-tests/test_framework/mininode.py | 75 +++++++++++++------------ 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index 0c40730f9005e..b06905301f4a8 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -1252,43 +1252,46 @@ def handle_write(self): self.sendbuf = self.sendbuf[sent:] def got_data(self): - while True: - if len(self.recvbuf) < 4: - return - if self.recvbuf[:4] != self.MAGIC_BYTES[self.network]: - raise ValueError("got garbage %s" % repr(self.recvbuf)) - if self.ver_recv < 209: - if len(self.recvbuf) < 4 + 12 + 4: - return - command = self.recvbuf[4:4+12].split("\x00", 1)[0] - msglen = struct.unpack(" Date: Fri, 1 Apr 2016 21:31:48 +0200 Subject: [PATCH 0074/1802] Fix typo: Optimizaton -> Optimization --- src/versionbits.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/versionbits.cpp b/src/versionbits.cpp index fbb60c0fc598e..78feb8ab0c6d2 100644 --- a/src/versionbits.cpp +++ b/src/versionbits.cpp @@ -25,7 +25,7 @@ ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* break; } if (pindexPrev->GetMedianTimePast() < nTimeStart) { - // Optimizaton: don't recompute down further, as we know every earlier block will be before the start time + // Optimization: don't recompute down further, as we know every earlier block will be before the start time cache[pindexPrev] = THRESHOLD_DEFINED; break; } From 10d3ae102afb89b3f50cd27f9ee657e5a542eb1b Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 1 Apr 2016 14:35:57 +0200 Subject: [PATCH 0075/1802] devtools: Auto-set branch to merge to in github-merge As we are already using the API to retrieve the pull request title, also retrieve the base branch. This makes sure that pull requests for 0.12 automatically end up in 0.12, and pull requests for master automatically end up in master, and so on. It is still possible to override the branch from the command line or using the `githubmerge.branch` git option. --- contrib/devtools/github-merge.py | 34 +++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/contrib/devtools/github-merge.py b/contrib/devtools/github-merge.py index 9a62fccbbb555..f82362fe417e3 100755 --- a/contrib/devtools/github-merge.py +++ b/contrib/devtools/github-merge.py @@ -47,9 +47,9 @@ def git_config_get(option, default=None): except subprocess.CalledProcessError as e: return default -def retrieve_pr_title(repo,pull): +def retrieve_pr_info(repo,pull): ''' - Retrieve pull request title from github. + Retrieve pull request information from github. Return None if no title can be found, or an error happens. ''' try: @@ -57,9 +57,9 @@ def retrieve_pr_title(repo,pull): result = urlopen(req) reader = codecs.getreader('utf-8') obj = json.load(reader(result)) - return obj['title'] + return obj except Exception as e: - print('Warning: unable to retrieve pull title from github: %s' % e) + print('Warning: unable to retrieve pull information from github: %s' % e) return None def ask_prompt(text): @@ -69,13 +69,13 @@ def ask_prompt(text): print("",file=stderr) return reply -def parse_arguments(branch): +def parse_arguments(): epilog = ''' In addition, you can set the following git configuration variables: githubmerge.repository (mandatory), user.signingkey (mandatory), githubmerge.host (default: git@github.com), - githubmerge.branch (default: master), + githubmerge.branch (no default), githubmerge.testcmd (default: none). ''' parser = argparse.ArgumentParser(description='Utility to merge, sign and push github pull requests', @@ -83,14 +83,14 @@ def parse_arguments(branch): parser.add_argument('pull', metavar='PULL', type=int, nargs=1, help='Pull request ID to merge') parser.add_argument('branch', metavar='BRANCH', type=str, nargs='?', - default=branch, help='Branch to merge against (default: '+branch+')') + default=None, help='Branch to merge against (default: githubmerge.branch setting, or base branch for pull, or \'master\')') return parser.parse_args() def main(): # Extract settings from git repo repo = git_config_get('githubmerge.repository') host = git_config_get('githubmerge.host','git@github.com') - branch = git_config_get('githubmerge.branch','master') + opt_branch = git_config_get('githubmerge.branch',None) testcmd = git_config_get('githubmerge.testcmd') signingkey = git_config_get('user.signingkey') if repo is None: @@ -105,9 +105,20 @@ def main(): host_repo = host+":"+repo # shortcut for push/pull target # Extract settings from command line - args = parse_arguments(branch) + args = parse_arguments() pull = str(args.pull[0]) - branch = args.branch + + # Receive pull information from github + info = retrieve_pr_info(repo,pull) + if info is None: + exit(1) + title = info['title'] + # precedence order for destination branch argument: + # - command line argument + # - githubmerge.branch setting + # - base branch for pull (as retrieved from github) + # - 'master' + branch = args.branch or opt_branch or info['base']['ref'] or 'master' # Initialize source branches head_branch = 'pull/'+pull+'/head' @@ -147,7 +158,6 @@ def main(): try: # Create unsigned merge commit. - title = retrieve_pr_title(repo,pull) if title: firstline = 'Merge #%s: %s' % (pull,title) else: @@ -165,7 +175,7 @@ def main(): print("ERROR: Creating merge failed (already merged?).",file=stderr) exit(4) - print('%s#%s%s %s' % (ATTR_RESET+ATTR_PR,pull,ATTR_RESET,title)) + print('%s#%s%s %s %sinto %s%s' % (ATTR_RESET+ATTR_PR,pull,ATTR_RESET,title,ATTR_RESET+ATTR_PR,branch,ATTR_RESET)) subprocess.check_call([GIT,'log','--graph','--topo-order','--pretty=format:'+COMMIT_FORMAT,base_branch+'..'+head_branch]) print() # Run test command if configured. From 444480649f08e6037f8ac178224b30a82e9ad72e Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sat, 2 Apr 2016 11:51:49 +0200 Subject: [PATCH 0076/1802] [qa] mininode: Combine struct.pack format strings --- qa/rpc-tests/test_framework/mininode.py | 30 ++++++++++++------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index b06905301f4a8..53f5e8805aa77 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -78,10 +78,10 @@ def ser_string(s): if len(s) < 253: return struct.pack("B", len(s)) + s elif len(s) < 0x10000: - return struct.pack("B", 253) + struct.pack(" Date: Mon, 21 Mar 2016 18:29:17 +0100 Subject: [PATCH 0077/1802] [ui] Move InitError, InitWarning, AmountErrMsg --- src/Makefile.am | 1 + src/init.cpp | 18 ------------ src/test/test_bitcoin.cpp | 2 -- src/ui_interface.cpp | 24 +++++++++++++++ src/ui_interface.h | 8 +++++ src/wallet/wallet.cpp | 61 +++++++++++++++------------------------ 6 files changed, 56 insertions(+), 58 deletions(-) create mode 100644 src/ui_interface.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 1e54512cbddc1..10aa550a02bef 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -323,6 +323,7 @@ libbitcoin_util_a_SOURCES = \ rpc/protocol.cpp \ support/cleanse.cpp \ sync.cpp \ + ui_interface.cpp \ util.cpp \ utilmoneystr.cpp \ utilstrencodings.cpp \ diff --git a/src/init.cpp b/src/init.cpp index 3667820a21fe6..038b28cc3a574 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -94,7 +94,6 @@ enum BindFlags { }; static const char* FEE_ESTIMATES_FILENAME="fee_estimates.dat"; -CClientUIInterface uiInterface; // Declared but not defined in ui_interface.h ////////////////////////////////////////////////////////////////////////////// // @@ -266,18 +265,6 @@ void HandleSIGHUP(int) fReopenDebugLog = true; } -bool static InitError(const std::string &str) -{ - uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_ERROR); - return false; -} - -bool static InitWarning(const std::string &str) -{ - uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_WARNING); - return true; -} - bool static Bind(const CService &addr, unsigned int flags) { if (!(flags & BF_EXPLICIT) && IsLimited(addr)) return false; @@ -742,11 +729,6 @@ static std::string ResolveErrMsg(const char * const optname, const std::string& return strprintf(_("Cannot resolve -%s address: '%s'"), optname, strBind); } -static std::string AmountErrMsg(const char * const optname, const std::string& strValue) -{ - return strprintf(_("Invalid amount for -%s=: '%s'"), optname, strValue); -} - void InitLogging() { fPrintToConsole = GetBoolArg("-printtoconsole", false); diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index 97b99962527e6..730f04f97faf9 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -30,8 +30,6 @@ #include #include -CClientUIInterface uiInterface; // Declared but not defined in ui_interface.h - extern bool fPrintToConsole; extern void noui_connect(); diff --git a/src/ui_interface.cpp b/src/ui_interface.cpp new file mode 100644 index 0000000000000..c778e40a9053a --- /dev/null +++ b/src/ui_interface.cpp @@ -0,0 +1,24 @@ +// Copyright (c) 2010-2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "ui_interface.h" +#include "util.h" + +CClientUIInterface uiInterface; + +bool InitError(const std::string& str) +{ + uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_ERROR); + return false; +} + +void InitWarning(const std::string& str) +{ + uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_WARNING); +} + +std::string AmountErrMsg(const char* const optname, const std::string& strValue) +{ + return strprintf(_("Invalid amount for -%s=: '%s'"), optname, strValue); +} diff --git a/src/ui_interface.h b/src/ui_interface.h index 0b51d52e6576e..a27918c50766d 100644 --- a/src/ui_interface.h +++ b/src/ui_interface.h @@ -100,6 +100,14 @@ class CClientUIInterface boost::signals2::signal BannedListChanged; }; +/** Show warning message **/ +void InitWarning(const std::string& str); + +/** Show error message **/ +bool InitError(const std::string& str); + +std::string AmountErrMsg(const char* const optname, const std::string& strValue); + extern CClientUIInterface uiInterface; #endif // BITCOIN_UI_INTERFACE_H diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index e8c946671044c..21d641f24720a 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -23,6 +23,7 @@ #include "timedata.h" #include "txmempool.h" #include "util.h" +#include "ui_interface.h" #include "utilmoneystr.h" #include @@ -365,22 +366,6 @@ void CWallet::Flush(bool shutdown) bitdb.Flush(shutdown); } -bool static UIError(const std::string &str) -{ - uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_ERROR); - return false; -} - -void static UIWarning(const std::string &str) -{ - uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_WARNING); -} - -static std::string AmountErrMsg(const char * const optname, const std::string& strValue) -{ - return strprintf(_("Invalid amount for -%s=: '%s'"), optname, strValue); -} - bool CWallet::Verify() { std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT); @@ -390,7 +375,7 @@ bool CWallet::Verify() // Wallet file must be a plain filename without a directory if (walletFile != boost::filesystem::basename(walletFile) + boost::filesystem::extension(walletFile)) - return UIError(strprintf(_("Wallet %s resides outside data directory %s"), walletFile, GetDataDir().string())); + return InitError(strprintf(_("Wallet %s resides outside data directory %s"), walletFile, GetDataDir().string())); if (!bitdb.Open(GetDataDir())) { @@ -407,7 +392,7 @@ bool CWallet::Verify() // try again if (!bitdb.Open(GetDataDir())) { // if it still fails, it probably means we can't even create the database env - return UIError(strprintf(_("Error initializing wallet database environment %s!"), GetDataDir())); + return InitError(strprintf(_("Error initializing wallet database environment %s!"), GetDataDir())); } } @@ -423,14 +408,14 @@ bool CWallet::Verify() CDBEnv::VerifyResult r = bitdb.Verify(walletFile, CWalletDB::Recover); if (r == CDBEnv::RECOVER_OK) { - UIWarning(strprintf(_("Warning: Wallet file corrupt, data salvaged!" + InitWarning(strprintf(_("Warning: Wallet file corrupt, data salvaged!" " Original %s saved as %s in %s; if" " your balance or transactions are incorrect you should" " restore from a backup."), walletFile, "wallet.{timestamp}.bak", GetDataDir())); } if (r == CDBEnv::RECOVER_FAIL) - return UIError(strprintf(_("%s corrupt, salvage failed"), walletFile)); + return InitError(strprintf(_("%s corrupt, salvage failed"), walletFile)); } return true; @@ -3055,7 +3040,7 @@ bool CWallet::InitLoadWallet() CWallet *tempWallet = new CWallet(walletFile); DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx); if (nZapWalletRet != DB_LOAD_OK) { - return UIError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile)); + return InitError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile)); } delete tempWallet; @@ -3071,22 +3056,22 @@ bool CWallet::InitLoadWallet() if (nLoadWalletRet != DB_LOAD_OK) { if (nLoadWalletRet == DB_CORRUPT) - return UIError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile)); + return InitError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile)); else if (nLoadWalletRet == DB_NONCRITICAL_ERROR) { - UIWarning(strprintf(_("Error reading %s! All keys read correctly, but transaction data" + InitWarning(strprintf(_("Error reading %s! All keys read correctly, but transaction data" " or address book entries might be missing or incorrect."), walletFile)); } else if (nLoadWalletRet == DB_TOO_NEW) - return UIError(strprintf(_("Error loading %s: Wallet requires newer version of %s"), + return InitError(strprintf(_("Error loading %s: Wallet requires newer version of %s"), walletFile, _(PACKAGE_NAME))); else if (nLoadWalletRet == DB_NEED_REWRITE) { - return UIError(strprintf(_("Wallet needed to be rewritten: restart %s to complete"), _(PACKAGE_NAME))); + return InitError(strprintf(_("Wallet needed to be rewritten: restart %s to complete"), _(PACKAGE_NAME))); } else - return UIError(strprintf(_("Error loading %s"), walletFile)); + return InitError(strprintf(_("Error loading %s"), walletFile)); } if (GetBoolArg("-upgradewallet", fFirstRun)) @@ -3102,7 +3087,7 @@ bool CWallet::InitLoadWallet() LogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion); if (nMaxVersion < walletInstance->GetVersion()) { - return UIError(_("Cannot downgrade wallet")); + return InitError(_("Cannot downgrade wallet")); } walletInstance->SetMaxVersion(nMaxVersion); } @@ -3116,7 +3101,7 @@ bool CWallet::InitLoadWallet() if (walletInstance->GetKeyFromPool(newDefaultKey)) { walletInstance->SetDefaultKey(newDefaultKey); if (!walletInstance->SetAddressBook(walletInstance->vchDefaultKey.GetID(), "", "receive")) - return UIError(_("Cannot write default address") += "\n"); + return InitError(_("Cannot write default address") += "\n"); } walletInstance->SetBestChain(chainActive.GetLocator()); @@ -3150,7 +3135,7 @@ bool CWallet::InitLoadWallet() block = block->pprev; if (pindexRescan != block) - return UIError(_("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)")); + return InitError(_("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)")); } uiInterface.InitMessage(_("Rescanning...")); @@ -3200,28 +3185,28 @@ bool CWallet::ParameterInteraction() if (ParseMoney(mapArgs["-mintxfee"], n) && n > 0) CWallet::minTxFee = CFeeRate(n); else - return UIError(AmountErrMsg("mintxfee", mapArgs["-mintxfee"])); + return InitError(AmountErrMsg("mintxfee", mapArgs["-mintxfee"])); } if (mapArgs.count("-fallbackfee")) { CAmount nFeePerK = 0; if (!ParseMoney(mapArgs["-fallbackfee"], nFeePerK)) - return UIError(strprintf(_("Invalid amount for -fallbackfee=: '%s'"), mapArgs["-fallbackfee"])); + return InitError(strprintf(_("Invalid amount for -fallbackfee=: '%s'"), mapArgs["-fallbackfee"])); if (nFeePerK > HIGH_TX_FEE_PER_KB) - UIWarning(_("-fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available.")); + InitWarning(_("-fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available.")); CWallet::fallbackFee = CFeeRate(nFeePerK); } if (mapArgs.count("-paytxfee")) { CAmount nFeePerK = 0; if (!ParseMoney(mapArgs["-paytxfee"], nFeePerK)) - return UIError(AmountErrMsg("paytxfee", mapArgs["-paytxfee"])); + return InitError(AmountErrMsg("paytxfee", mapArgs["-paytxfee"])); if (nFeePerK > HIGH_TX_FEE_PER_KB) - UIWarning(_("-paytxfee is set very high! This is the transaction fee you will pay if you send a transaction.")); + InitWarning(_("-paytxfee is set very high! This is the transaction fee you will pay if you send a transaction.")); payTxFee = CFeeRate(nFeePerK, 1000); if (payTxFee < ::minRelayTxFee) { - return UIError(strprintf(_("Invalid amount for -paytxfee=: '%s' (must be at least %s)"), + return InitError(strprintf(_("Invalid amount for -paytxfee=: '%s' (must be at least %s)"), mapArgs["-paytxfee"], ::minRelayTxFee.ToString())); } } @@ -3229,13 +3214,13 @@ bool CWallet::ParameterInteraction() { CAmount nMaxFee = 0; if (!ParseMoney(mapArgs["-maxtxfee"], nMaxFee)) - return UIError(AmountErrMsg("maxtxfee", mapArgs["-maxtxfee"])); + return InitError(AmountErrMsg("maxtxfee", mapArgs["-maxtxfee"])); if (nMaxFee > HIGH_MAX_TX_FEE) - UIWarning(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction.")); + InitWarning(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction.")); maxTxFee = nMaxFee; if (CFeeRate(maxTxFee, 1000) < ::minRelayTxFee) { - return UIError(strprintf(_("Invalid amount for -maxtxfee=: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"), + return InitError(strprintf(_("Invalid amount for -maxtxfee=: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"), mapArgs["-maxtxfee"], ::minRelayTxFee.ToString())); } } From 4b9dfd6d81581e1b821d3a503335a1fa78471655 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Sat, 2 Apr 2016 18:54:12 +0200 Subject: [PATCH 0078/1802] Add note about using the Qt official binary installer. --- doc/build-osx.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/doc/build-osx.md b/doc/build-osx.md index c3cb1b78917d2..296e0aa1f0726 100644 --- a/doc/build-osx.md +++ b/doc/build-osx.md @@ -1,6 +1,6 @@ Mac OS X Build Instructions and Notes ==================================== -This guide will show you how to build bitcoind (headless client) for OS X. +This guide will show you how to build Bitcoin Core for OS X. Notes ----- @@ -114,6 +114,16 @@ you can monitor its process by looking at the debug.log file, like this: Other commands: ------- - ./bitcoind -daemon # to start the bitcoin daemon. + ./bitcoind -daemon # to start the bitcoin daemon. ./bitcoin-cli --help # for a list of command-line options. ./bitcoin-cli help # When the daemon is running, to get a list of RPC commands + +Using Qt official installer while building +------------------------------------------ + +If you prefer to use the latest Qt installed from the official binary +installer over the brew version, you have to make several changes to +the installed tree and its binaries (all these changes are contained +in the brew version already). The changes needed are described in +[#7714](https://github.com/bitcoin/bitcoin/issues/7714). We do not +support building Bitcoin Core this way though. From 190c1e234d0454d4eb93536992674770fc1e68bb Mon Sep 17 00:00:00 2001 From: JeremyRand Date: Sat, 2 Apr 2016 22:10:28 +0000 Subject: [PATCH 0079/1802] Doc: change Precise to Trusty in gitian-building.md https://github.com/bitcoin/bitcoin/commit/2cecb2460002bc645e47e8517b21099b0faec818 changed "precise" to "trusty" in the shell command, but didn't change the text above it accordingly. This commit fixes that. --- doc/gitian-building.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/gitian-building.md b/doc/gitian-building.md index 54993d13a99b7..69d79b3c68ab7 100644 --- a/doc/gitian-building.md +++ b/doc/gitian-building.md @@ -313,7 +313,7 @@ Setting up the Gitian image ------------------------- Gitian needs a virtual image of the operating system to build in. -Currently this is Ubuntu Precise x86_64. +Currently this is Ubuntu Trusty x86_64. This image will be copied and used every time that a build is started to make sure that the build is deterministic. Creating the image will take a while, but only has to be done once. From fada0c422c081ba53a324aaf63c0a750cb56498e Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 3 Apr 2016 11:49:36 +0200 Subject: [PATCH 0080/1802] [doc] Fix doxygen comments for members --- doc/developer-notes.md | 6 ++++++ src/chainparams.cpp | 4 ++-- src/main.cpp | 8 ++++---- src/main.h | 14 ++++++------- src/policy/fees.h | 4 ++-- src/rpc/client.cpp | 4 ++-- src/script/interpreter.cpp | 12 ++++++------ src/script/standard.h | 2 +- src/txmempool.h | 40 +++++++++++++++++++------------------- src/utiltime.cpp | 2 +- src/wallet/wallet.h | 8 ++++---- 11 files changed, 55 insertions(+), 49 deletions(-) diff --git a/doc/developer-notes.md b/doc/developer-notes.md index 358792251b675..8affb2158a913 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -71,6 +71,12 @@ To describe a member or variable use: int var; //!< Detailed description after the member ``` +or +```cpp +//! Description before the member +int var; +``` + Also OK: ```c++ /// diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 965d131695b65..5c7d190125cc3 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -266,8 +266,8 @@ class CRegTestParams : public CChainParams { assert(consensus.hashGenesisBlock == uint256S("0x0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206")); assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); - vFixedSeeds.clear(); //! Regtest mode doesn't have any fixed seeds. - vSeeds.clear(); //! Regtest mode doesn't have any DNS seeds. + vFixedSeeds.clear(); //!< Regtest mode doesn't have any fixed seeds. + vSeeds.clear(); //!< Regtest mode doesn't have any DNS seeds. fMiningRequiresPeers = false; fDefaultConsistencyChecks = true; diff --git a/src/main.cpp b/src/main.cpp index 2c0b3bfee7aa6..b68c6affae7f9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -194,10 +194,10 @@ namespace { /** Blocks that are in flight, and that are in the queue to be downloaded. Protected by cs_main. */ struct QueuedBlock { uint256 hash; - CBlockIndex *pindex; //! Optional. - int64_t nTime; //! Time of "getdata" request in microseconds. - bool fValidatedHeaders; //! Whether this block has validated headers at the time of request. - int64_t nTimeDisconnect; //! The timeout for this block request (for disconnecting a slow peer) + CBlockIndex* pindex; //!< Optional. + int64_t nTime; //!< Time of "getdata" request in microseconds. + bool fValidatedHeaders; //!< Whether this block has validated headers at the time of request. + int64_t nTimeDisconnect; //!< The timeout for this block request (for disconnecting a slow peer) }; map::iterator> > mapBlocksInFlight; diff --git a/src/main.h b/src/main.h index 0bfcfab2132e5..3ea9dc500ca64 100644 --- a/src/main.h +++ b/src/main.h @@ -469,13 +469,13 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, class CBlockFileInfo { public: - unsigned int nBlocks; //! number of blocks stored in file - unsigned int nSize; //! number of used bytes of block file - unsigned int nUndoSize; //! number of used bytes in the undo file - unsigned int nHeightFirst; //! lowest height of block in file - unsigned int nHeightLast; //! highest height of block in file - uint64_t nTimeFirst; //! earliest time of block in file - uint64_t nTimeLast; //! latest time of block in file + unsigned int nBlocks; //!< number of blocks stored in file + unsigned int nSize; //!< number of used bytes of block file + unsigned int nUndoSize; //!< number of used bytes in the undo file + unsigned int nHeightFirst; //!< lowest height of block in file + unsigned int nHeightLast; //!< highest height of block in file + uint64_t nTimeFirst; //!< earliest time of block in file + uint64_t nTimeLast; //!< latest time of block in file ADD_SERIALIZE_METHODS; diff --git a/src/policy/fees.h b/src/policy/fees.h index cdd984de7d5fc..463f62f710603 100644 --- a/src/policy/fees.h +++ b/src/policy/fees.h @@ -265,8 +265,8 @@ class CBlockPolicyEstimator void Read(CAutoFile& filein); private: - CFeeRate minTrackedFee; //! Passed to constructor to avoid dependency on main - double minTrackedPriority; //! Set to AllowFreeThreshold + CFeeRate minTrackedFee; //!< Passed to constructor to avoid dependency on main + double minTrackedPriority; //!< Set to AllowFreeThreshold unsigned int nBestSeenHeight; struct TxStatsInfo { diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 89420b93d7fb2..033987af59efb 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -18,8 +18,8 @@ using namespace std; class CRPCConvertParam { public: - std::string methodName; //! method whose params want conversion - int paramIdx; //! 0-based idx of param to convert + std::string methodName; //!< method whose params want conversion + int paramIdx; //!< 0-based idx of param to convert }; static const CRPCConvertParam vRPCConvertParams[] = diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 149a4f0156315..9c47f7c6c9577 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1015,12 +1015,12 @@ namespace { */ class CTransactionSignatureSerializer { private: - const CTransaction &txTo; //! reference to the spending transaction (the one being serialized) - const CScript &scriptCode; //! output script being consumed - const unsigned int nIn; //! input index of txTo being signed - const bool fAnyoneCanPay; //! whether the hashtype has the SIGHASH_ANYONECANPAY flag set - const bool fHashSingle; //! whether the hashtype is SIGHASH_SINGLE - const bool fHashNone; //! whether the hashtype is SIGHASH_NONE + const CTransaction& txTo; //!< reference to the spending transaction (the one being serialized) + const CScript& scriptCode; //!< output script being consumed + const unsigned int nIn; //!< input index of txTo being signed + const bool fAnyoneCanPay; //!< whether the hashtype has the SIGHASH_ANYONECANPAY flag set + const bool fHashSingle; //!< whether the hashtype is SIGHASH_SINGLE + const bool fHashNone; //!< whether the hashtype is SIGHASH_NONE public: CTransactionSignatureSerializer(const CTransaction &txToIn, const CScript &scriptCodeIn, unsigned int nInIn, int nHashTypeIn) : diff --git a/src/script/standard.h b/src/script/standard.h index 64bf010ec199e..f348da8e1982b 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -27,7 +27,7 @@ class CScriptID : public uint160 CScriptID(const uint160& in) : uint160(in) {} }; -static const unsigned int MAX_OP_RETURN_RELAY = 83; //! bytes (+1 for OP_RETURN, +2 for the pushdata opcodes) +static const unsigned int MAX_OP_RETURN_RELAY = 83; //!< bytes (+1 for OP_RETURN, +2 for the pushdata opcodes) extern bool fAcceptDatacarrier; extern unsigned nMaxDatacarrierBytes; diff --git a/src/txmempool.h b/src/txmempool.h index 9dbb37dad068f..de4ba0b371a42 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -74,28 +74,28 @@ class CTxMemPoolEntry { private: CTransaction tx; - CAmount nFee; //! Cached to avoid expensive parent-transaction lookups - size_t nTxSize; //! ... and avoid recomputing tx size - size_t nModSize; //! ... and modified size for priority - size_t nUsageSize; //! ... and total memory usage - int64_t nTime; //! Local time when entering the mempool - double entryPriority; //! Priority when entering the mempool - unsigned int entryHeight; //! Chain height when entering the mempool - bool hadNoDependencies; //! Not dependent on any other txs when it entered the mempool - CAmount inChainInputValue; //! Sum of all txin values that are already in blockchain - bool spendsCoinbase; //! keep track of transactions that spend a coinbase - unsigned int sigOpCount; //! Legacy sig ops plus P2SH sig op count - int64_t feeDelta; //! Used for determining the priority of the transaction for mining in a block - LockPoints lockPoints; //! Track the height and time at which tx was final + CAmount nFee; //!< Cached to avoid expensive parent-transaction lookups + size_t nTxSize; //!< ... and avoid recomputing tx size + size_t nModSize; //!< ... and modified size for priority + size_t nUsageSize; //!< ... and total memory usage + int64_t nTime; //!< Local time when entering the mempool + double entryPriority; //!< Priority when entering the mempool + unsigned int entryHeight; //!< Chain height when entering the mempool + bool hadNoDependencies; //!< Not dependent on any other txs when it entered the mempool + CAmount inChainInputValue; //!< Sum of all txin values that are already in blockchain + bool spendsCoinbase; //!< keep track of transactions that spend a coinbase + unsigned int sigOpCount; //!< Legacy sig ops plus P2SH sig op count + int64_t feeDelta; //!< Used for determining the priority of the transaction for mining in a block + LockPoints lockPoints; //!< Track the height and time at which tx was final // Information about descendants of this transaction that are in the // mempool; if we remove this transaction we must remove all of these // descendants as well. if nCountWithDescendants is 0, treat this entry as // dirty, and nSizeWithDescendants and nModFeesWithDescendants will not be // correct. - uint64_t nCountWithDescendants; //! number of descendant transactions - uint64_t nSizeWithDescendants; //! ... and size - CAmount nModFeesWithDescendants; //! ... and total fees (all including us) + uint64_t nCountWithDescendants; //!< number of descendant transactions + uint64_t nSizeWithDescendants; //!< ... and size + CAmount nModFeesWithDescendants; //!< ... and total fees (all including us) // Analogous statistics for ancestor transactions uint64_t nCountWithAncestors; @@ -399,18 +399,18 @@ class CInPoint class CTxMemPool { private: - uint32_t nCheckFrequency; //! Value n means that n times in 2^32 we check. + uint32_t nCheckFrequency; //!< Value n means that n times in 2^32 we check. unsigned int nTransactionsUpdated; CBlockPolicyEstimator* minerPolicyEstimator; - uint64_t totalTxSize; //! sum of all mempool tx' byte sizes - uint64_t cachedInnerUsage; //! sum of dynamic memory usage of all the map elements (NOT the maps themselves) + uint64_t totalTxSize; //!< sum of all mempool tx' byte sizes + uint64_t cachedInnerUsage; //!< sum of dynamic memory usage of all the map elements (NOT the maps themselves) CFeeRate minReasonableRelayFee; mutable int64_t lastRollingFeeUpdate; mutable bool blockSinceLastRollingFeeBump; - mutable double rollingMinimumFeeRate; //! minimum fee to get into the pool, decreases exponentially + mutable double rollingMinimumFeeRate; //!< minimum fee to get into the pool, decreases exponentially void trackPackageRemoved(const CFeeRate& rate); diff --git a/src/utiltime.cpp b/src/utiltime.cpp index 91b40d9991106..da590f8889346 100644 --- a/src/utiltime.cpp +++ b/src/utiltime.cpp @@ -14,7 +14,7 @@ using namespace std; -static int64_t nMockTime = 0; //! For unit testing +static int64_t nMockTime = 0; //!< For unit testing int64_t GetTime() { diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 867f33a7b5708..96d5d4e1e015b 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -228,11 +228,11 @@ class CWalletTx : public CMerkleTx mapValue_t mapValue; std::vector > vOrderForm; unsigned int fTimeReceivedIsTxTime; - unsigned int nTimeReceived; //! time received by this node + unsigned int nTimeReceived; //!< time received by this node unsigned int nTimeSmart; char fFromMe; std::string strFromAccount; - int64_t nOrderPos; //! position in ordered transaction list + int64_t nOrderPos; //!< position in ordered transaction list // memory only mutable bool fDebitCached; @@ -324,7 +324,7 @@ class CWalletTx : public CMerkleTx } READWRITE(*(CMerkleTx*)this); - std::vector vUnused; //! Used to be vtxPrev + std::vector vUnused; //!< Used to be vtxPrev READWRITE(vUnused); READWRITE(mapValue); READWRITE(vOrderForm); @@ -465,7 +465,7 @@ class CAccountingEntry std::string strOtherAccount; std::string strComment; mapValue_t mapValue; - int64_t nOrderPos; //! position in ordered transaction list + int64_t nOrderPos; //!< position in ordered transaction list uint64_t nEntryNo; CAccountingEntry() From faef3b710fe2ced7cc94a82847c547865a64fd92 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 3 Apr 2016 14:39:48 +0200 Subject: [PATCH 0081/1802] [travis] Print the commit which was evaluated --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 31b3d6d96e70f..3f1af53011cb6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -64,6 +64,7 @@ before_script: - if [ -n "$OSX_SDK" -a -f depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then tar -C depends/SDKs -xf depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz; fi - make $MAKEJOBS -C depends HOST=$HOST $DEP_OPTS script: + - export TRAVIS_COMMIT_LOG=`git log --format=fuller -1` - if [ -n "$USE_SHELL" ]; then export CONFIG_SHELL="$USE_SHELL"; fi - OUTDIR=$BASE_OUTDIR/$TRAVIS_PULL_REQUEST/$TRAVIS_JOB_NUMBER-$HOST - BITCOIN_CONFIG_ALL="--disable-dependency-tracking --prefix=$TRAVIS_BUILD_DIR/depends/$HOST --bindir=$OUTDIR/bin --libdir=$OUTDIR/lib" @@ -79,4 +80,6 @@ script: - if [ "$RUN_TESTS" = "true" ]; then make check; fi - if [ "$RUN_TESTS" = "true" ]; then qa/pull-tester/rpc-tests.py --coverage; fi after_script: + - echo "Commit, which was evaluated by travis in this build job:" + - echo $TRAVIS_COMMIT_LOG - if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then (echo "Upload goes here. Something like: scp -r $BASE_OUTDIR server" || echo "upload failed"); fi From f063863d1fc964aec80d8a0acfde623543573823 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 31 Mar 2016 14:50:10 +0200 Subject: [PATCH 0082/1802] build: Remove unnecessary executables from gitian release This removes the following executables from the binary gitian release: - test_bitcoin-qt[.exe] - bench_bitcoin[.exe] @jonasschnelli and me discussed this on IRC a few days ago - unlike the normal `bitcoin_tests` which is useful to see if it is safe to run bitcoin on a certain OS/environment combination, there is no good reason to include these. Better to leave them out to reduce the download size. Sizes from the 0.12 release: ``` 2.4M bitcoin-0.12.0/bin/bench_bitcoin.exe 22M bitcoin-0.12.0/bin/test_bitcoin-qt.exe ``` --- configure.ac | 21 ++++++++++++--------- contrib/gitian-descriptors/gitian-linux.yml | 2 +- contrib/gitian-descriptors/gitian-osx.yml | 2 +- contrib/gitian-descriptors/gitian-win.yml | 2 +- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/configure.ac b/configure.ac index 1e894f57675d8..ec5656814f074 100644 --- a/configure.ac +++ b/configure.ac @@ -98,6 +98,11 @@ AC_ARG_ENABLE(tests, [use_tests=$enableval], [use_tests=yes]) +AC_ARG_ENABLE(gui-tests, + AS_HELP_STRING([--disable-gui-tests],[do not compile GUI tests (default is to compile if GUI and tests enabled)]), + [use_gui_tests=$enableval], + [use_gui_tests=$use_tests]) + AC_ARG_ENABLE(bench, AS_HELP_STRING([--disable-bench],[do not compile benchmarks (default is to compile)]), [use_bench=$enableval], @@ -919,8 +924,8 @@ else fi dnl these are only used when qt is enabled +BUILD_TEST_QT="" if test x$bitcoin_enable_qt != xno; then - BUILD_QT=qt dnl enable dbus support AC_MSG_CHECKING([whether to build GUI with support for D-Bus]) if test x$bitcoin_enable_qt_dbus != xno; then @@ -950,9 +955,9 @@ if test x$bitcoin_enable_qt != xno; then fi AC_MSG_CHECKING([whether to build test_bitcoin-qt]) - if test x$use_tests$bitcoin_enable_qt_test = xyesyes; then + if test x$use_gui_tests$bitcoin_enable_qt_test = xyesyes; then AC_MSG_RESULT([yes]) - BUILD_TEST_QT="test" + BUILD_TEST_QT="yes" else AC_MSG_RESULT([no]) fi @@ -963,9 +968,10 @@ AM_CONDITIONAL([ENABLE_ZMQ], [test "x$use_zmq" = "xyes"]) AC_MSG_CHECKING([whether to build test_bitcoin]) if test x$use_tests = xyes; then AC_MSG_RESULT([yes]) - BUILD_TEST="test" + BUILD_TEST="yes" else AC_MSG_RESULT([no]) + BUILD_TEST="" fi AC_MSG_CHECKING([whether to reduce exports]) @@ -983,9 +989,9 @@ AM_CONDITIONAL([TARGET_DARWIN], [test x$TARGET_OS = xdarwin]) AM_CONDITIONAL([BUILD_DARWIN], [test x$BUILD_OS = xdarwin]) AM_CONDITIONAL([TARGET_WINDOWS], [test x$TARGET_OS = xwindows]) AM_CONDITIONAL([ENABLE_WALLET],[test x$enable_wallet = xyes]) -AM_CONDITIONAL([ENABLE_TESTS],[test x$use_tests = xyes]) +AM_CONDITIONAL([ENABLE_TESTS],[test x$BUILD_TEST = xyes]) AM_CONDITIONAL([ENABLE_QT],[test x$bitcoin_enable_qt = xyes]) -AM_CONDITIONAL([ENABLE_QT_TESTS],[test x$use_tests$bitcoin_enable_qt_test = xyesyes]) +AM_CONDITIONAL([ENABLE_QT_TESTS],[test x$BUILD_TEST_QT = xyes]) AM_CONDITIONAL([ENABLE_BENCH],[test x$use_bench = xyes]) AM_CONDITIONAL([USE_QRCODE], [test x$use_qr = xyes]) AM_CONDITIONAL([USE_LCOV],[test x$use_lcov = xyes]) @@ -1026,9 +1032,6 @@ AC_SUBST(USE_QRCODE) AC_SUBST(BOOST_LIBS) AC_SUBST(TESTDEFS) AC_SUBST(LEVELDB_TARGET_FLAGS) -AC_SUBST(BUILD_TEST) -AC_SUBST(BUILD_QT) -AC_SUBST(BUILD_TEST_QT) AC_SUBST(MINIUPNPC_CPPFLAGS) AC_SUBST(MINIUPNPC_LIBS) AC_CONFIG_FILES([Makefile src/Makefile share/setup.nsi share/qt/Info.plist src/test/buildenv.py]) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index 1f2c4f9999a67..13941f5d55ea3 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -26,7 +26,7 @@ files: [] script: | WRAP_DIR=$HOME/wrapped HOSTS="i686-pc-linux-gnu x86_64-unknown-linux-gnu" - CONFIGFLAGS="--enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++" + CONFIGFLAGS="--enable-glibc-back-compat --enable-reduce-exports --disable-bench --disable-gui-tests LDFLAGS=-static-libstdc++" FAKETIME_HOST_PROGS="" FAKETIME_PROGS="date ar ranlib nm strip" diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml index 6f68ae08ce73f..c430932f9da0e 100644 --- a/contrib/gitian-descriptors/gitian-osx.yml +++ b/contrib/gitian-descriptors/gitian-osx.yml @@ -36,7 +36,7 @@ files: script: | WRAP_DIR=$HOME/wrapped HOSTS="x86_64-apple-darwin11" - CONFIGFLAGS="--enable-reduce-exports GENISOIMAGE=$WRAP_DIR/genisoimage" + 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 f0fbff3e1035d..9f7322f0b5a21 100644 --- a/contrib/gitian-descriptors/gitian-win.yml +++ b/contrib/gitian-descriptors/gitian-win.yml @@ -29,7 +29,7 @@ files: [] script: | WRAP_DIR=$HOME/wrapped HOSTS="x86_64-w64-mingw32 i686-w64-mingw32" - CONFIGFLAGS="--enable-reduce-exports" + CONFIGFLAGS="--enable-reduce-exports --disable-gui-tests" FAKETIME_HOST_PROGS="g++ ar ranlib nm windres strip" FAKETIME_PROGS="date makensis zip" From 60361ca4816dd5b2d10408db3194fb77fcac8720 Mon Sep 17 00:00:00 2001 From: mruddy Date: Sun, 3 Apr 2016 14:30:00 +0000 Subject: [PATCH 0083/1802] RPC: fix generatetoaddress failing to parse address and add unit test --- src/rpc/client.cpp | 1 - src/test/rpc_tests.cpp | 24 ++++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 89420b93d7fb2..b040d2bc80149 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -30,7 +30,6 @@ static const CRPCConvertParam vRPCConvertParams[] = { "generate", 0 }, { "generate", 1 }, { "generatetoaddress", 0 }, - { "generatetoaddress", 1 }, { "generatetoaddress", 2 }, { "getnetworkhashps", 0 }, { "getnetworkhashps", 1 }, diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index 1976ee2cb61f1..bbda6a48f4d5a 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -11,6 +11,7 @@ #include "test/test_bitcoin.h" #include +#include #include #include @@ -308,4 +309,27 @@ BOOST_AUTO_TEST_CASE(rpc_ban) BOOST_CHECK_EQUAL(adr.get_str(), "2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/128"); } +BOOST_AUTO_TEST_CASE(rpc_convert_values_generatetoaddress) +{ + UniValue result; + + BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", boost::assign::list_of("101")("mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a"))); + BOOST_CHECK_EQUAL(result[0].get_int(), 101); + BOOST_CHECK_EQUAL(result[1].get_str(), "mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a"); + + BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", boost::assign::list_of("101")("mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU"))); + BOOST_CHECK_EQUAL(result[0].get_int(), 101); + BOOST_CHECK_EQUAL(result[1].get_str(), "mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU"); + + BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", boost::assign::list_of("1")("mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a")("9"))); + BOOST_CHECK_EQUAL(result[0].get_int(), 1); + BOOST_CHECK_EQUAL(result[1].get_str(), "mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a"); + BOOST_CHECK_EQUAL(result[2].get_int(), 9); + + BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", boost::assign::list_of("1")("mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU")("9"))); + BOOST_CHECK_EQUAL(result[0].get_int(), 1); + BOOST_CHECK_EQUAL(result[1].get_str(), "mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU"); + BOOST_CHECK_EQUAL(result[2].get_int(), 9); +} + BOOST_AUTO_TEST_SUITE_END() From fa24456d0c4cd0f6571bcf3d8f1f51d8d4242a3e Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 3 Apr 2016 20:35:57 +0200 Subject: [PATCH 0084/1802] [qa] httpbasics: Actually test second connection --- qa/rpc-tests/httpbasics.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/qa/rpc-tests/httpbasics.py b/qa/rpc-tests/httpbasics.py index c231676ec87d7..eff4c6e808bbd 100755 --- a/qa/rpc-tests/httpbasics.py +++ b/qa/rpc-tests/httpbasics.py @@ -37,13 +37,13 @@ def run_test(self): conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) out1 = conn.getresponse().read() - assert('"error":null' in out1) + assert(b'"error":null' in out1) assert(conn.sock!=None) #according to http/1.1 connection must still be open! #send 2nd request without closing connection conn.request('POST', '/', '{"method": "getchaintips"}', headers) - out2 = conn.getresponse().read() - assert('"error":null' in out1) #must also response with a correct json-rpc message + out1 = conn.getresponse().read() + assert(b'"error":null' in out1) #must also response with a correct json-rpc message assert(conn.sock!=None) #according to http/1.1 connection must still be open! conn.close() @@ -54,13 +54,13 @@ def run_test(self): conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) out1 = conn.getresponse().read() - assert('"error":null' in out1) + assert(b'"error":null' in out1) assert(conn.sock!=None) #according to http/1.1 connection must still be open! #send 2nd request without closing connection conn.request('POST', '/', '{"method": "getchaintips"}', headers) - out2 = conn.getresponse().read() - assert('"error":null' in out1) #must also response with a correct json-rpc message + out1 = conn.getresponse().read() + assert(b'"error":null' in out1) #must also response with a correct json-rpc message assert(conn.sock!=None) #according to http/1.1 connection must still be open! conn.close() @@ -71,7 +71,7 @@ def run_test(self): conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) out1 = conn.getresponse().read() - assert('"error":null' in out1) + assert(b'"error":null' in out1) assert(conn.sock==None) #now the connection must be closed after the response #node1 (2nd node) is running with disabled keep-alive option @@ -83,7 +83,7 @@ def run_test(self): conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) out1 = conn.getresponse().read() - assert('"error":null' in out1) + assert(b'"error":null' in out1) #node2 (third node) is running with standard keep-alive parameters which means keep-alive is on urlNode2 = urlparse.urlparse(self.nodes[2].url) @@ -94,7 +94,7 @@ def run_test(self): conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) out1 = conn.getresponse().read() - assert('"error":null' in out1) + assert(b'"error":null' in out1) assert(conn.sock!=None) #connection must be closed because bitcoind should use keep-alive by default # Check excessive request size From fac724c78f281168ea174c36cada4f95112aea6d Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 20 Mar 2016 18:56:13 +0100 Subject: [PATCH 0085/1802] [qa] maxblocksinflight: Actually enable test --- qa/rpc-tests/maxblocksinflight.py | 56 ++++++++++++++----------------- 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/qa/rpc-tests/maxblocksinflight.py b/qa/rpc-tests/maxblocksinflight.py index 0313bce736b1f..ad633f661dd51 100755 --- a/qa/rpc-tests/maxblocksinflight.py +++ b/qa/rpc-tests/maxblocksinflight.py @@ -41,40 +41,36 @@ def add_new_connection(self, connection): self.disconnectOkay = False def run(self): - try: - fail = False - self.connection.rpc.generate(1) # Leave IBD - - numBlocksToGenerate = [ 8, 16, 128, 1024 ] - for count in range(len(numBlocksToGenerate)): - current_invs = [] - for i in range(numBlocksToGenerate[count]): - current_invs.append(CInv(2, random.randrange(0, 1<<256))) - if len(current_invs) >= 50000: - self.connection.send_message(msg_inv(current_invs)) - current_invs = [] - if len(current_invs) > 0: + self.connection.rpc.generate(1) # Leave IBD + + numBlocksToGenerate = [8, 16, 128, 1024] + for count in range(len(numBlocksToGenerate)): + current_invs = [] + for i in range(numBlocksToGenerate[count]): + current_invs.append(CInv(2, random.randrange(0, 1 << 256))) + if len(current_invs) >= 50000: self.connection.send_message(msg_inv(current_invs)) - - # Wait and see how many blocks were requested - time.sleep(2) - - total_requests = 0 - with mininode_lock: - for key in self.blockReqCounts: - total_requests += self.blockReqCounts[key] - if self.blockReqCounts[key] > 1: - raise AssertionError("Error, test failed: block %064x requested more than once" % key) - if total_requests > MAX_REQUESTS: - raise AssertionError("Error, too many blocks (%d) requested" % total_requests) - print "Round %d: success (total requests: %d)" % (count, total_requests) - except AssertionError as e: - print "TEST FAILED: ", e.args + current_invs = [] + if len(current_invs) > 0: + self.connection.send_message(msg_inv(current_invs)) + + # Wait and see how many blocks were requested + time.sleep(2) + + total_requests = 0 + with mininode_lock: + for key in self.blockReqCounts: + total_requests += self.blockReqCounts[key] + if self.blockReqCounts[key] > 1: + raise AssertionError("Error, test failed: block %064x requested more than once" % key) + if total_requests > MAX_REQUESTS: + raise AssertionError("Error, too many blocks (%d) requested" % total_requests) + print "Round %d: success (total requests: %d)" % (count, total_requests) self.disconnectOkay = True self.connection.disconnect_node() - + class MaxBlocksInFlightTest(BitcoinTestFramework): def add_options(self, parser): parser.add_option("--testbinary", dest="testbinary", @@ -86,7 +82,7 @@ def setup_chain(self): initialize_chain_clean(self.options.tmpdir, 1) def setup_network(self): - self.nodes = start_nodes(1, self.options.tmpdir, + self.nodes = start_nodes(1, self.options.tmpdir, extra_args=[['-debug', '-whitelist=127.0.0.1']], binary=[self.options.testbinary]) From ffff866da83209dcaa463d8b9539d3f539f83a97 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 3 Apr 2016 21:20:14 +0200 Subject: [PATCH 0086/1802] [qa] Remove misleading "errorString syntax" --- qa/rpc-tests/importprunedfunds.py | 10 ++++++---- qa/rpc-tests/rawtransactions.py | 6 +++--- qa/rpc-tests/wallet.py | 19 +++++++------------ 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/qa/rpc-tests/importprunedfunds.py b/qa/rpc-tests/importprunedfunds.py index db875800d4f0f..a9324196ee488 100755 --- a/qa/rpc-tests/importprunedfunds.py +++ b/qa/rpc-tests/importprunedfunds.py @@ -83,9 +83,10 @@ def run_test (self): try: result1 = self.nodes[1].importprunedfunds(rawtxn1, proof1, "") except JSONRPCException as e: - errorString = e.error['message'] + assert('No addresses' in e.error['message']) + else: + assert(False) - assert('No addresses' in errorString) balance1 = self.nodes[1].getbalance("", 0, True) assert_equal(balance1, Decimal(0)) @@ -120,9 +121,10 @@ def run_test (self): try: self.nodes[1].removeprunedfunds(txnid1) except JSONRPCException as e: - errorString = e.error['message'] + assert('does not exist' in e.error['message']) + else: + assert(False) - assert('does not exist' in errorString) balance1 = Decimal(self.nodes[1].getbalance("", 0, True)) assert_equal(balance1, Decimal('0.075')) diff --git a/qa/rpc-tests/rawtransactions.py b/qa/rpc-tests/rawtransactions.py index 9f660c8bdadeb..762a6d6a30c21 100755 --- a/qa/rpc-tests/rawtransactions.py +++ b/qa/rpc-tests/rawtransactions.py @@ -56,13 +56,13 @@ def run_test(self): rawtx = self.nodes[2].createrawtransaction(inputs, outputs) rawtx = self.nodes[2].signrawtransaction(rawtx) - errorString = "" try: rawtx = self.nodes[2].sendrawtransaction(rawtx['hex']) except JSONRPCException as e: - errorString = e.error['message'] + assert("Missing inputs" in e.error['message']) + else: + assert(False) - assert("Missing inputs" in errorString) ######################### # RAW TX MULTISIG TESTS # diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py index cb876aae5cb90..8fdcea50b6329 100755 --- a/qa/rpc-tests/wallet.py +++ b/qa/rpc-tests/wallet.py @@ -245,22 +245,20 @@ def run_test (self): txObj = self.nodes[0].gettransaction(txId) assert_equal(txObj['amount'], Decimal('-0.0001')) - #this should fail - errorString = "" try: txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "1f-4") except JSONRPCException as e: - errorString = e.error['message'] + assert("Invalid amount" in e.error['message']) + else: + raise AssertionError("Must not parse invalid amounts") - assert("Invalid amount" in errorString) - errorString = "" try: - self.nodes[0].generate("2") #use a string to as block amount parameter must fail because it's not interpreted as amount + self.nodes[0].generate("2") + raise AssertionError("Must not accept strings as numeric") except JSONRPCException as e: - errorString = e.error['message'] + assert("not an integer" in e.error['message']) - assert("not an integer" in errorString) # Mine a block from node0 to an address from node1 cbAddr = self.nodes[1].getnewaddress() @@ -269,10 +267,7 @@ def run_test (self): self.sync_all() # Check that the txid and balance is found by node1 - try: - self.nodes[1].gettransaction(cbTxId) - except JSONRPCException as e: - assert("Invalid or non-wallet transaction id" not in e.error['message']) + self.nodes[1].gettransaction(cbTxId) #check if wallet or blochchain maintenance changes the balance self.sync_all() From 8efed3bc93a15fc715fd4f3cca50f44685872b5e Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 17 Mar 2016 17:54:54 +0100 Subject: [PATCH 0087/1802] [Qt] Support for abandoned/abandoning transactions --- src/Makefile.qt.include | 3 +- src/qt/bitcoin.qrc | 1 + src/qt/guiconstants.h | 2 ++ src/qt/res/icons/transaction_abandoned.png | Bin 0 -> 1473 bytes src/qt/transactiondesc.cpp | 2 +- src/qt/transactionrecord.cpp | 2 ++ src/qt/transactionrecord.h | 1 + src/qt/transactiontablemodel.cpp | 10 +++++++ src/qt/transactionview.cpp | 33 +++++++++++++++++++-- src/qt/transactionview.h | 2 ++ src/qt/walletmodel.cpp | 15 ++++++++++ src/qt/walletmodel.h | 3 ++ 12 files changed, 70 insertions(+), 4 deletions(-) create mode 100644 src/qt/res/icons/transaction_abandoned.png diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index ca4e1e70d085e..247ca3f1d41f6 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -268,7 +268,8 @@ RES_ICONS = \ qt/res/icons/tx_output.png \ qt/res/icons/tx_mined.png \ qt/res/icons/warning.png \ - qt/res/icons/verify.png + qt/res/icons/verify.png \ + qt/res/icons/transaction_abandoned.png BITCOIN_QT_CPP = \ qt/bantablemodel.cpp \ diff --git a/src/qt/bitcoin.qrc b/src/qt/bitcoin.qrc index dcd3b4ae2ce09..24b0bae3ec144 100644 --- a/src/qt/bitcoin.qrc +++ b/src/qt/bitcoin.qrc @@ -49,6 +49,7 @@ res/icons/fontbigger.png res/icons/fontsmaller.png res/icons/chevron.png + res/icons/transaction_abandoned.png res/movies/spinner-000.png diff --git a/src/qt/guiconstants.h b/src/qt/guiconstants.h index 5ceffcd70af58..4b2c10dd48e43 100644 --- a/src/qt/guiconstants.h +++ b/src/qt/guiconstants.h @@ -29,6 +29,8 @@ static const bool DEFAULT_SPLASHSCREEN = true; #define COLOR_TX_STATUS_OPENUNTILDATE QColor(64, 64, 255) /* Transaction list -- TX status decoration - offline */ #define COLOR_TX_STATUS_OFFLINE QColor(192, 192, 192) +/* Transaction list -- TX status decoration - danger, tx needs attention */ +#define COLOR_TX_STATUS_DANGER QColor(200, 100, 100) /* Transaction list -- TX status decoration - default color */ #define COLOR_BLACK QColor(0, 0, 0) diff --git a/src/qt/res/icons/transaction_abandoned.png b/src/qt/res/icons/transaction_abandoned.png new file mode 100644 index 0000000000000000000000000000000000000000..8ca6445c20f263b3dd479806a524e3f09b8f9e63 GIT binary patch literal 1473 zcmchX`8(8k0LMSynaoU+ab$|ek)tO~D$$@ah8aiFk|SEjIxB=3gH0I63^{UbMX?sC zZJ%}I2uX;qb*;sq7)x%$jF53HQLLVRY5#$Jp7;Cx`uY9K>yFhWQyf+n3jn~GT`;!U zCF@HusNHSSckci|B*Dy>Y8x`NFhcdl-@>;o`R}hiX`$rdLBrX{x>Tyos9;o{;Ex$5 zD5rafqo_i{1@%d)M6|T>19{`)%?D%O3||+g5?1dU#vIaXDWuk*Djz(tRjwhg;w&EK z?9jI>JZB76wwg%i{7)~ww&adPsY(_0t0hjxWhnulXh7IQQ3hDZ3d1r4S(oUaebDtl zl{Lnarf83cxZgClcU~x_+q-~DXbc3g#p|p)9dc+0;m#(8zz-L`u&%1vCq7ObcW;bS zY%wZoC$*-hP9BNLq(BVb&Fn*9R>SdP1BzOBVj z5FUwaSYS%Y9HR`c3M>XUYt+*f(OdHpxld%~(z{b#z1NZdIrPoB4Fmy_W*M*y*ov%C zRLZtQ^_~;Jl3hf(6_ZUTeJGfAE?=p>QtI688XO^=|LUd_xR0!MK{_wWDxUWc_HV8f& zm|D!xuya#V^@8t7p%*d_d&PrF6s&H_xnRzTyt1uTLN(=VXJ$*9a?~LS@IQuS4pj@R zd9#^8v;dxH8*h~qDAvrAXYf|rc%r1hs%BpHKZ3579+1642FG|-XSMq zPXpTs7brFu@Ll6P?Jm)8Kx*1nzEs9O=OiS5vXr7v-sb`s4S-uSW?c$ zGVL5W_>-ip!4JBQa`QDP`BIJE!jM%@f);p3PJD)7{<%IhHJGvR7$QKWdf3;wL12I! zwv26?;#Xk7c$Mk%B)BSDEJ`ji%5lAF?x_Qc!CjgDAl+8`!D>LZsN;7Q6XRdbd$J9m1Zbk@h) z7WwvvFS14JuMIev*{_EawY?Mo+w0L(PE8iAYbx=AOZ*?3tmXR6B*lX~ zWG2n}a^n7qE`&G)V0w2qY?5p;Cmo6ajPp%2HO{lA1 2 * 60 && wtx.GetRequestCount() == 0) return tr("%1/offline").arg(nDepth); else if (nDepth == 0) - return tr("0/unconfirmed, %1").arg((wtx.InMempool() ? tr("in memory pool") : tr("not in memory pool"))); + return tr("0/unconfirmed, %1").arg((wtx.InMempool() ? tr("in memory pool") : tr("not in memory pool"))) + (wtx.isAbandoned() ? ", "+tr("abandoned") : ""); else if (nDepth < 6) return tr("%1/unconfirmed").arg(nDepth); else diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 5b16b108e66dd..1efeda93ec8f5 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -239,6 +239,8 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx) else if (status.depth == 0) { status.status = TransactionStatus::Unconfirmed; + if (wtx.isAbandoned()) + status.status = TransactionStatus::Abandoned; } else if (status.depth < RecommendedNumConfirmations) { diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h index 49753ee31f815..330cd48cfa92a 100644 --- a/src/qt/transactionrecord.h +++ b/src/qt/transactionrecord.h @@ -33,6 +33,7 @@ class TransactionStatus Unconfirmed, /**< Not yet mined into a block **/ Confirming, /**< Confirmed, but waiting for the recommended number of confirmations **/ Conflicted, /**< Conflicts with other transaction or mempool **/ + Abandoned, /**< Abandoned from the wallet **/ /// Generated (mined) transactions Immature, /**< Mined but waiting for maturity */ MaturesWarning, /**< Transaction will likely not mature because no nodes have confirmed */ diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index d2a52b3022c79..b29ecf83486b0 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -312,6 +312,9 @@ QString TransactionTableModel::formatTxStatus(const TransactionRecord *wtx) cons case TransactionStatus::Unconfirmed: status = tr("Unconfirmed"); break; + case TransactionStatus::Abandoned: + status = tr("Abandoned"); + break; case TransactionStatus::Confirming: status = tr("Confirming (%1 of %2 recommended confirmations)").arg(wtx->status.depth).arg(TransactionRecord::RecommendedNumConfirmations); break; @@ -468,6 +471,8 @@ QVariant TransactionTableModel::txStatusDecoration(const TransactionRecord *wtx) return COLOR_TX_STATUS_OFFLINE; case TransactionStatus::Unconfirmed: return QIcon(":/icons/transaction_0"); + case TransactionStatus::Abandoned: + return QIcon(":/icons/transaction_abandoned"); case TransactionStatus::Confirming: switch(wtx->status.depth) { @@ -573,6 +578,11 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const case Qt::TextAlignmentRole: return column_alignments[index.column()]; case Qt::ForegroundRole: + // Use the "danger" color for abandoned transactions + if(rec->status.status == TransactionStatus::Abandoned) + { + return COLOR_TX_STATUS_DANGER; + } // Non-confirmed (but not immature) as transactions are grey if(!rec->status.countsForBalance && rec->status.status != TransactionStatus::Immature) { diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index a4d4c7a35fe9b..a352228c36fb5 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -37,7 +37,7 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *parent) : QWidget(parent), model(0), transactionProxyModel(0), - transactionView(0) + transactionView(0), abandonAction(0) { // Build filter row setContentsMargins(0,0,0,0); @@ -137,6 +137,7 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa transactionView = view; // Actions + abandonAction = new QAction(tr("Abandon transaction"), this); QAction *copyAddressAction = new QAction(tr("Copy address"), this); QAction *copyLabelAction = new QAction(tr("Copy label"), this); QAction *copyAmountAction = new QAction(tr("Copy amount"), this); @@ -153,8 +154,10 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa contextMenu->addAction(copyTxIDAction); contextMenu->addAction(copyTxHexAction); contextMenu->addAction(copyTxPlainText); - contextMenu->addAction(editLabelAction); contextMenu->addAction(showDetailsAction); + contextMenu->addSeparator(); + contextMenu->addAction(abandonAction); + contextMenu->addAction(editLabelAction); mapperThirdPartyTxUrls = new QSignalMapper(this); @@ -170,6 +173,7 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa connect(view, SIGNAL(doubleClicked(QModelIndex)), this, SIGNAL(doubleClicked(QModelIndex))); connect(view, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint))); + connect(abandonAction, SIGNAL(triggered()), this, SLOT(abandonTx())); connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(copyAddress())); connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(copyLabel())); connect(copyAmountAction, SIGNAL(triggered()), this, SLOT(copyAmount())); @@ -360,12 +364,37 @@ void TransactionView::exportClicked() void TransactionView::contextualMenu(const QPoint &point) { QModelIndex index = transactionView->indexAt(point); + QModelIndexList selection = transactionView->selectionModel()->selectedRows(0); + + // check if transaction can be abandoned, disable context menu action in case it doesn't + uint256 hash; + hash.SetHex(selection.at(0).data(TransactionTableModel::TxHashRole).toString().toStdString()); + abandonAction->setEnabled(model->transactionCanBeAbandoned(hash)); + if(index.isValid()) { contextMenu->exec(QCursor::pos()); } } +void TransactionView::abandonTx() +{ + if(!transactionView || !transactionView->selectionModel()) + return; + QModelIndexList selection = transactionView->selectionModel()->selectedRows(0); + + // get the hash from the TxHashRole (QVariant / QString) + uint256 hash; + QString hashQStr = selection.at(0).data(TransactionTableModel::TxHashRole).toString(); + hash.SetHex(hashQStr.toStdString()); + + // Abandon the wallet transaction over the walletModel + model->abandonTransaction(hash); + + // Update the table + model->getTransactionTableModel()->updateTransaction(hashQStr, CT_UPDATED, false); +} + void TransactionView::copyAddress() { GUIUtil::copyEntryData(transactionView, 0, TransactionTableModel::AddressRole); diff --git a/src/qt/transactionview.h b/src/qt/transactionview.h index 2cfbd471b099b..e9b9d5b6bc9e2 100644 --- a/src/qt/transactionview.h +++ b/src/qt/transactionview.h @@ -75,6 +75,7 @@ class TransactionView : public QWidget QFrame *dateRangeWidget; QDateTimeEdit *dateFrom; QDateTimeEdit *dateTo; + QAction *abandonAction; QWidget *createDateRangeWidget(); @@ -97,6 +98,7 @@ private Q_SLOTS: void copyTxPlainText(); void openThirdPartyTxUrl(QString url); void updateWatchOnlyColumn(bool fHaveWatchOnly); + void abandonTx(); Q_SIGNALS: void doubleClicked(const QModelIndex&); diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index cf38c64eb0dee..ce230d6aedbce 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -668,3 +668,18 @@ bool WalletModel::saveReceiveRequest(const std::string &sAddress, const int64_t else return wallet->AddDestData(dest, key, sRequest); } + +bool WalletModel::transactionCanBeAbandoned(uint256 hash) const +{ + LOCK2(cs_main, wallet->cs_wallet); + const CWalletTx *wtx = wallet->GetWalletTx(hash); + if (!wtx || wtx->isAbandoned() || wtx->GetDepthInMainChain() > 0 || wtx->InMempool()) + return false; + return true; +} + +bool WalletModel::abandonTransaction(uint256 hash) const +{ + LOCK2(cs_main, wallet->cs_wallet); + return wallet->AbandonTransaction(hash); +} diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index 7a47eda86f70d..e5470bf618eea 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -200,6 +200,9 @@ class WalletModel : public QObject void loadReceiveRequests(std::vector& vReceiveRequests); bool saveReceiveRequest(const std::string &sAddress, const int64_t nId, const std::string &sRequest); + bool transactionCanBeAbandoned(uint256 hash) const; + bool abandonTransaction(uint256 hash) const; + private: CWallet *wallet; bool fHaveWatchOnly; From 0087f2684891d9f208a1d91758e662d0538d54ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Sat, 2 Apr 2016 16:32:42 +0200 Subject: [PATCH 0088/1802] Use relative paths instead of absolute paths --- src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index 1e54512cbddc1..d91e959cffe79 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -479,7 +479,7 @@ endif %.pb.cc %.pb.h: %.proto @test -f $(PROTOC) - $(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$(abspath $( Date: Mon, 4 Apr 2016 22:21:00 +0000 Subject: [PATCH 0089/1802] RPC: add versionHex in getblock and getblockheader JSON results; expand data in getblockchaininfo bip9_softforks field. --- qa/rpc-tests/blockchain.py | 1 + src/rpc/blockchain.cpp | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/qa/rpc-tests/blockchain.py b/qa/rpc-tests/blockchain.py index 272a5dc15482e..8f59ee741c366 100755 --- a/qa/rpc-tests/blockchain.py +++ b/qa/rpc-tests/blockchain.py @@ -82,6 +82,7 @@ def _test_getblockheader(self): assert isinstance(header['mediantime'], int) assert isinstance(header['nonce'], int) assert isinstance(header['version'], int) + assert isinstance(int(header['versionHex'], 16), int) assert isinstance(header['difficulty'], Decimal) if __name__ == '__main__': diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index f1c9d9f7ab528..34637b9f7e398 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -70,6 +70,7 @@ UniValue blockheaderToJSON(const CBlockIndex* blockindex) result.push_back(Pair("confirmations", confirmations)); result.push_back(Pair("height", blockindex->nHeight)); result.push_back(Pair("version", blockindex->nVersion)); + result.push_back(Pair("versionHex", strprintf("%08x", blockindex->nVersion))); result.push_back(Pair("merkleroot", blockindex->hashMerkleRoot.GetHex())); result.push_back(Pair("time", (int64_t)blockindex->nTime)); result.push_back(Pair("mediantime", (int64_t)blockindex->GetMedianTimePast())); @@ -98,6 +99,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION))); result.push_back(Pair("height", blockindex->nHeight)); result.push_back(Pair("version", block.nVersion)); + result.push_back(Pair("versionHex", strprintf("%08x", block.nVersion))); result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex())); UniValue txs(UniValue::VARR); BOOST_FOREACH(const CTransaction&tx, block.vtx) @@ -316,6 +318,7 @@ UniValue getblockheader(const UniValue& params, bool fHelp) " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n" " \"height\" : n, (numeric) The block height or index\n" " \"version\" : n, (numeric) The block version\n" + " \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n" " \"merkleroot\" : \"xxxx\", (string) The merkle root\n" " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n" " \"mediantime\" : ttt, (numeric) The median block time in seconds since epoch (Jan 1 1970 GMT)\n" @@ -375,6 +378,7 @@ UniValue getblock(const UniValue& params, bool fHelp) " \"size\" : n, (numeric) The block size\n" " \"height\" : n, (numeric) The block height or index\n" " \"version\" : n, (numeric) The block version\n" + " \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n" " \"merkleroot\" : \"xxxx\", (string) The merkle root\n" " \"tx\" : [ (array of string) The transaction ids\n" " \"transactionid\" (string) The transaction id\n" @@ -608,13 +612,20 @@ static UniValue BIP9SoftForkDesc(const std::string& name, const Consensus::Param { UniValue rv(UniValue::VOBJ); rv.push_back(Pair("id", name)); - switch (VersionBitsTipState(consensusParams, id)) { + const ThresholdState thresholdState = VersionBitsTipState(consensusParams, id); + switch (thresholdState) { case THRESHOLD_DEFINED: rv.push_back(Pair("status", "defined")); break; case THRESHOLD_STARTED: rv.push_back(Pair("status", "started")); break; case THRESHOLD_LOCKED_IN: rv.push_back(Pair("status", "locked_in")); break; case THRESHOLD_ACTIVE: rv.push_back(Pair("status", "active")); break; case THRESHOLD_FAILED: rv.push_back(Pair("status", "failed")); break; } + if (THRESHOLD_STARTED == thresholdState) + { + rv.push_back(Pair("bit", consensusParams.vDeployments[id].bit)); + } + rv.push_back(Pair("startTime", consensusParams.vDeployments[id].nStartTime)); + rv.push_back(Pair("timeout", consensusParams.vDeployments[id].nTimeout)); return rv; } @@ -653,6 +664,9 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) " {\n" " \"id\": \"xxxx\", (string) name of the softfork\n" " \"status\": \"xxxx\", (string) one of \"defined\", \"started\", \"lockedin\", \"active\", \"failed\"\n" + " \"bit\": xx, (numeric) the bit, 0-28, in the block version field used to signal this soft fork\n" + " \"startTime\": xx, (numeric) the minimum median time past of a block at which the bit gains its meaning\n" + " \"timeout\": xx (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in\n" " }\n" " ]\n" "}\n" From dc4ec6d3dbb5018cdc059eebb55994fab5d23679 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Mon, 4 Apr 2016 15:48:18 -0400 Subject: [PATCH 0090/1802] depends: create a hostid and buildid and add option for salts These add very simple sanity checks to ensure that the build/host toolchains have not changed since the last run. If they have, all ids will change and packages will be rebuilt. For more complicated usage (like parsing dpkg), HOST_ID_SALT/BUILD_ID_SALT may be used to introduce arbitrary data to the ids. --- depends/Makefile | 18 +++++++++++++++++- depends/README.md | 2 ++ depends/funcs.mk | 2 +- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/depends/Makefile b/depends/Makefile index ef5a20e6c36aa..7ae14524e1f12 100644 --- a/depends/Makefile +++ b/depends/Makefile @@ -15,6 +15,8 @@ BASEDIR = $(CURDIR) HASH_LENGTH:=11 DOWNLOAD_CONNECT_TIMEOUT:=10 DOWNLOAD_RETRIES:=3 +HOST_ID_SALT ?= salt +BUILD_ID_SALT ?= salt host:=$(BUILD) ifneq ($(HOST),) @@ -73,6 +75,20 @@ include builders/$(build_os).mk include builders/default.mk include packages/packages.mk +build_id_string:=$(BUILD_ID_SALT) +build_id_string+=$(shell $(build_CC) --version 2>/dev/null) +build_id_string+=$(shell $(build_AR) --version 2>/dev/null) +build_id_string+=$(shell $(build_CXX) --version 2>/dev/null) +build_id_string+=$(shell $(build_RANLIB) --version 2>/dev/null) +build_id_string+=$(shell $(build_STRIP) --version 2>/dev/null) + +$(host_arch)_$(host_os)_id_string:=$(HOST_ID_SALT) +$(host_arch)_$(host_os)_id_string+=$(shell $(host_CC) --version 2>/dev/null) +$(host_arch)_$(host_os)_id_string+=$(shell $(host_AR) --version 2>/dev/null) +$(host_arch)_$(host_os)_id_string+=$(shell $(host_CXX) --version 2>/dev/null) +$(host_arch)_$(host_os)_id_string+=$(shell $(host_RANLIB) --version 2>/dev/null) +$(host_arch)_$(host_os)_id_string+=$(shell $(host_STRIP) --version 2>/dev/null) + qt_packages_$(NO_QT) = $(qt_packages) $(qt_$(host_os)_packages) qt_native_packages_$(NO_QT) = $(qt_native_packages) wallet_packages_$(NO_WALLET) = $(wallet_packages) @@ -90,7 +106,7 @@ include funcs.mk toolchain_path=$($($(host_arch)_$(host_os)_native_toolchain)_prefixbin) final_build_id_long+=$(shell $(build_SHA256SUM) config.site.in) -final_build_id+=$(shell echo -n $(final_build_id_long) | $(build_SHA256SUM) | cut -c-$(HASH_LENGTH)) +final_build_id+=$(shell echo -n "$(final_build_id_long)" | $(build_SHA256SUM) | cut -c-$(HASH_LENGTH)) $(host_prefix)/.stamp_$(final_build_id): $(native_packages) $(packages) $(AT)rm -rf $(@D) $(AT)mkdir -p $(@D) diff --git a/depends/README.md b/depends/README.md index d85e652c60f23..271bbd80bfc4a 100644 --- a/depends/README.md +++ b/depends/README.md @@ -38,6 +38,8 @@ The following can be set when running make: make FOO=bar NO_WALLET: Don't download/build/cache libs needed to enable the wallet NO_UPNP: Don't download/build/cache packages needed for enabling upnp DEBUG: disable some optimizations and enable more runtime checking + HOST_ID_SALT: Optional salt to use when generating host package ids + BUILD_ID_SALT: Optional salt to use when generating build package ids If some packages are not built, for example `make NO_WALLET=1`, the appropriate options will be passed to bitcoin's configure. In this case, `--disable-wallet`. diff --git a/depends/funcs.mk b/depends/funcs.mk index 050a9b132137e..45bb96dd4438b 100644 --- a/depends/funcs.mk +++ b/depends/funcs.mk @@ -39,7 +39,7 @@ define int_get_build_id $(eval $(1)_dependencies += $($(1)_$(host_arch)_$(host_os)_dependencies) $($(1)_$(host_os)_dependencies)) $(eval $(1)_all_dependencies:=$(call int_get_all_dependencies,$(1),$($($(1)_type)_native_toolchain) $($(1)_dependencies))) $(foreach dep,$($(1)_all_dependencies),$(eval $(1)_build_id_deps+=$(dep)-$($(dep)_version)-$($(dep)_recipe_hash))) -$(eval $(1)_build_id_long:=$(1)-$($(1)_version)-$($(1)_recipe_hash)-$(release_type) $($(1)_build_id_deps)) +$(eval $(1)_build_id_long:=$(1)-$($(1)_version)-$($(1)_recipe_hash)-$(release_type) $($(1)_build_id_deps) $($($(1)_type)_id_string)) $(eval $(1)_build_id:=$(shell echo -n "$($(1)_build_id_long)" | $(build_SHA256SUM) | cut -c-$(HASH_LENGTH))) final_build_id_long+=$($(package)_build_id_long) From fe740f14690f70fbb84287595049afc719a5bd3b Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 3 Mar 2016 01:01:30 -0500 Subject: [PATCH 0091/1802] depends: fix fallback downloads In some cases, failed downloads wouldn't trigger a fallback download attempt. Namely, checksum mismatches. --- depends/funcs.mk | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/depends/funcs.mk b/depends/funcs.mk index 45bb96dd4438b..15e404e42dcf3 100644 --- a/depends/funcs.mk +++ b/depends/funcs.mk @@ -19,15 +19,19 @@ define int_get_all_dependencies $(sort $(foreach dep,$(2),$(2) $(call int_get_all_dependencies,$(1),$($(dep)_dependencies)))) endef -define fetch_file -(test -f $$($(1)_source_dir)/$(4) || \ - ( mkdir -p $$($(1)_download_dir) && echo Fetching $(1)... && \ - ( $(build_DOWNLOAD) "$$($(1)_download_dir)/$(4).temp" "$(2)/$(3)" || \ - $(build_DOWNLOAD) "$$($(1)_download_dir)/$(4).temp" "$(FALLBACK_DOWNLOAD_PATH)/$(3)" ) && \ +define fetch_file_inner + ( mkdir -p $$($(1)_download_dir) && echo Fetching $(3) from $(2) && \ + $(build_DOWNLOAD) "$$($(1)_download_dir)/$(4).temp" "$(2)/$(3)" && \ echo "$(5) $$($(1)_download_dir)/$(4).temp" > $$($(1)_download_dir)/.$(4).hash && \ $(build_SHA256SUM) -c $$($(1)_download_dir)/.$(4).hash && \ mv $$($(1)_download_dir)/$(4).temp $$($(1)_source_dir)/$(4) && \ - rm -rf $$($(1)_download_dir) )) + rm -rf $$($(1)_download_dir) ) +endef + +define fetch_file + ( test -f $$($(1)_source_dir)/$(4) || \ + ( $(call fetch_file_inner,$(1),$(2),$(3),$(4),$(5)) || \ + $(call fetch_file_inner,$(1),$(FALLBACK_DOWNLOAD_PATH),$(3),$(4),$(5)))) endef define int_get_build_recipe_hash From bb717f43756cf2754b6ed6fc54d52b535ed25fb2 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Mon, 4 Apr 2016 15:44:02 -0400 Subject: [PATCH 0092/1802] depends: fix "unexpected operator" error during "make download" --- depends/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/depends/Makefile b/depends/Makefile index 7ae14524e1f12..3ddfc85a450d0 100644 --- a/depends/Makefile +++ b/depends/Makefile @@ -147,9 +147,9 @@ endef define check_or_remove_sources mkdir -p $($(package)_source_dir); cd $($(package)_source_dir); \ - $(build_SHA256SUM) -c $($(package)_fetched) >/dev/null 2>/dev/null || \ - ( if test -f $($(package)_all_sources); then echo "Checksum missing or mismatched for $(package) source. Forcing re-download."; fi; \ - rm -f $($(package)_all_sources) $($(1)_fetched)) + test -f $($(package)_fetched) && ( $(build_SHA256SUM) -c $($(package)_fetched) >/dev/null 2>/dev/null || \ + ( echo "Checksum missing or mismatched for $(package) source. Forcing re-download."; \ + rm -f $($(package)_all_sources) $($(1)_fetched))) || true endef check-packages: From 11d9f6b8b82df04e9cf0ba7d8434eaa3fe394ee5 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Mon, 4 Apr 2016 18:20:20 -0400 Subject: [PATCH 0093/1802] depends: qt/cctools: fix checksum checksum tests Checksums were being verified after download, but not again before extraction --- depends/packages/native_cctools.mk | 4 ++++ depends/packages/qt.mk | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/depends/packages/native_cctools.mk b/depends/packages/native_cctools.mk index 1c1bcf199a0bd..b5603a8d48c60 100644 --- a/depends/packages/native_cctools.mk +++ b/depends/packages/native_cctools.mk @@ -17,6 +17,10 @@ $(call fetch_file,$(package),$($(package)_clang_download_path),$($(package)_clan endef define $(package)_extract_cmds + mkdir -p $($(package)_extract_dir) && \ + echo "$($(package)_sha256_hash) $($(package)_source)" > $($(package)_extract_dir)/.$($(package)_file_name).hash && \ + echo "$($(package)_clang_sha256_hash) $($(package)_source_dir)/$($(package)_clang_file_name)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \ + $(build_SHA256SUM) -c $($(package)_extract_dir)/.$($(package)_file_name).hash && \ mkdir -p toolchain/bin toolchain/lib/clang/3.5/include && \ tar --strip-components=1 -C toolchain -xf $($(package)_source_dir)/$($(package)_clang_file_name) && \ echo "#!/bin/sh" > toolchain/bin/$(host)-dsymutil && \ diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index 901b761fde142..77df77b73f7f0 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -108,8 +108,8 @@ endef define $(package)_extract_cmds mkdir -p $($(package)_extract_dir) && \ echo "$($(package)_sha256_hash) $($(package)_source)" > $($(package)_extract_dir)/.$($(package)_file_name).hash && \ - echo "$($(package)_qttranslations_sha256_hash) $($(package)_source_dir)/$($(package)_qttranslations_file_name)" > $($(package)_extract_dir)/.$($(package)_file_name).hash && \ - echo "$($(package)_qttools_sha256_hash) $($(package)_source_dir)/$($(package)_qttools_file_name)" > $($(package)_extract_dir)/.$($(package)_file_name).hash && \ + echo "$($(package)_qttranslations_sha256_hash) $($(package)_source_dir)/$($(package)_qttranslations_file_name)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \ + echo "$($(package)_qttools_sha256_hash) $($(package)_source_dir)/$($(package)_qttools_file_name)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \ $(build_SHA256SUM) -c $($(package)_extract_dir)/.$($(package)_file_name).hash && \ mkdir qtbase && \ tar --strip-components=1 -xf $($(package)_source) -C qtbase && \ From fac9ca2ec69bc629dbbd81c83e5bf67690e52c96 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Tue, 5 Apr 2016 12:49:53 +0200 Subject: [PATCH 0094/1802] [travis] echo $TRAVIS_COMMIT_RANGE --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3f1af53011cb6..95ef36bf028ee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -80,6 +80,6 @@ script: - if [ "$RUN_TESTS" = "true" ]; then make check; fi - if [ "$RUN_TESTS" = "true" ]; then qa/pull-tester/rpc-tests.py --coverage; fi after_script: - - echo "Commit, which was evaluated by travis in this build job:" + - echo $TRAVIS_COMMIT_RANGE - echo $TRAVIS_COMMIT_LOG - if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then (echo "Upload goes here. Something like: scp -r $BASE_OUTDIR server" || echo "upload failed"); fi From c7c664191fd6ca4843cfe9d00abf8f2362b9550f Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 5 Apr 2016 14:54:18 +0200 Subject: [PATCH 0095/1802] Fix JSON pretty printing in script_tests --- src/test/script_tests.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 30e3f37e14c28..8f927f8f91303 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -381,6 +381,18 @@ class TestBuilder return creditTx.vout[0].scriptPubKey; } }; + +std::string JSONPrettyPrint(const UniValue& univalue) +{ + std::string ret = univalue.write(4); + // Workaround for libunivalue pretty printer, which puts a space between comma's and newlines + size_t pos = 0; + while ((pos = ret.find(" \n", pos)) != std::string::npos) { + ret.replace(pos, 2, "\n"); + pos++; + } + return ret; +} } BOOST_AUTO_TEST_CASE(script_build) @@ -651,11 +663,11 @@ BOOST_AUTO_TEST_CASE(script_build) for (unsigned int idx = 0; idx < json_good.size(); idx++) { const UniValue& tv = json_good[idx]; - tests_good.insert(tv.get_array().write(1,4)); + tests_good.insert(JSONPrettyPrint(tv.get_array())); } for (unsigned int idx = 0; idx < json_bad.size(); idx++) { const UniValue& tv = json_bad[idx]; - tests_bad.insert(tv.get_array().write(1,4)); + tests_bad.insert(JSONPrettyPrint(tv.get_array())); } } @@ -664,7 +676,7 @@ BOOST_AUTO_TEST_CASE(script_build) BOOST_FOREACH(TestBuilder& test, good) { test.Test(true); - std::string str = test.GetJSON().write(1,4); + std::string str = JSONPrettyPrint(test.GetJSON()); #ifndef UPDATE_JSON_TESTS if (tests_good.count(str) == 0) { BOOST_CHECK_MESSAGE(false, "Missing auto script_valid test: " + test.GetComment()); @@ -674,7 +686,7 @@ BOOST_AUTO_TEST_CASE(script_build) } BOOST_FOREACH(TestBuilder& test, bad) { test.Test(false); - std::string str = test.GetJSON().write(1,4); + std::string str = JSONPrettyPrint(test.GetJSON()); #ifndef UPDATE_JSON_TESTS if (tests_bad.count(str) == 0) { BOOST_CHECK_MESSAGE(false, "Missing auto script_invalid test: " + test.GetComment()); From d03e46625ac95954bb9ecbc2cf73ffd8de6b8a13 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 5 Apr 2016 14:26:01 +0200 Subject: [PATCH 0096/1802] Fix formatting of NOPs for generated script tests --- src/core_write.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core_write.cpp b/src/core_write.cpp index b660e86c30b5d..6f9e2266a3966 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -35,7 +35,7 @@ string FormatScript(const CScript& script) } else if ((op >= OP_1 && op <= OP_16) || op == OP_1NEGATE) { ret += strprintf("%i ", op - OP_1NEGATE - 1); continue; - } else if (op >= OP_NOP && op <= OP_CHECKMULTISIGVERIFY) { + } else if (op >= OP_NOP && op <= OP_NOP10) { string str(GetOpName(op)); if (str.substr(0, 3) == string("OP_")) { ret += str.substr(3, string::npos) + " "; @@ -45,7 +45,7 @@ string FormatScript(const CScript& script) if (vch.size() > 0) { ret += strprintf("0x%x 0x%x ", HexStr(it2, it - vch.size()), HexStr(it - vch.size(), it)); } else { - ret += strprintf("0x%x", HexStr(it2, it)); + ret += strprintf("0x%x ", HexStr(it2, it)); } continue; } From 269281b7cc56e728fa64803fc7509ab3a0ce1805 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 5 Apr 2016 14:08:13 +0200 Subject: [PATCH 0097/1802] Fix some misconstructed tests They claimed to be testing P2SH scripts with non-push scriptSigs, but 1) they were not enabling P2SH 2) they have push-only scriptSigs Fix this, and add a few more related cases. --- src/test/data/script_invalid.json | 16 ++++++++-------- src/test/data/script_valid.json | 12 ++++++++++++ src/test/script_tests.cpp | 14 ++++++++++---- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/test/data/script_invalid.json b/src/test/data/script_invalid.json index 9e91132984ead..b9f150eacb236 100644 --- a/src/test/data/script_invalid.json +++ b/src/test/data/script_invalid.json @@ -845,18 +845,18 @@ "SIG_PUSHONLY" ], [ - "0x47 0x304402203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022054e1c258c2981cdfba5df1f46661fb6541c44f77ca0092f3600331abfffb125101 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac", - "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", - "", + "0x47 0x3044022018a2a81a93add5cb5f5da76305718e4ea66045ec4888b28d84cb22fae7f4645b02201e6daa5ed5d2e4b2b2027cf7ffd43d8d9844dd49f74ef86899ec8e669dfd39aa01 NOP8 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac", + "HASH160 0x14 0x215640c2f72f0d16b4eced26762035a42ffed39a EQUAL", + "P2SH", "P2SH(P2PK) with non-push scriptSig but no SIGPUSHONLY", - "EVAL_FALSE" + "SIG_PUSHONLY" ], [ - "0x47 0x304402203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022054e1c258c2981cdfba5df1f46661fb6541c44f77ca0092f3600331abfffb125101 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac", - "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", + "0x47 0x3044022018a2a81a93add5cb5f5da76305718e4ea66045ec4888b28d84cb22fae7f4645b02201e6daa5ed5d2e4b2b2027cf7ffd43d8d9844dd49f74ef86899ec8e669dfd39aa01 NOP8 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac", + "HASH160 0x14 0x215640c2f72f0d16b4eced26762035a42ffed39a EQUAL", "SIGPUSHONLY", - "P2SH(P2PK) with non-push scriptSig", - "EVAL_FALSE" + "P2SH(P2PK) with non-push scriptSig but not P2SH", + "SIG_PUSHONLY" ], [ "11 0x47 0x304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001", diff --git a/src/test/data/script_valid.json b/src/test/data/script_valid.json index e5f0d17b0473e..29ccbd92ff930 100644 --- a/src/test/data/script_valid.json +++ b/src/test/data/script_valid.json @@ -882,6 +882,18 @@ "", "2-of-2 with two identical keys and sigs pushed using OP_DUP but no SIGPUSHONLY" ], +[ + "0x47 0x3044022018a2a81a93add5cb5f5da76305718e4ea66045ec4888b28d84cb22fae7f4645b02201e6daa5ed5d2e4b2b2027cf7ffd43d8d9844dd49f74ef86899ec8e669dfd39aa01 NOP8 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac", + "HASH160 0x14 0x215640c2f72f0d16b4eced26762035a42ffed39a EQUAL", + "", + "P2SH(P2PK) with non-push scriptSig but no P2SH or SIGPUSHONLY" +], +[ + "0x47 0x304402203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022054e1c258c2981cdfba5df1f46661fb6541c44f77ca0092f3600331abfffb125101 NOP8", + "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", + "", + "P2PK with non-push scriptSig but with P2SH validation" +], [ "0 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG", diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 8f927f8f91303..4ecb56de84981 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -628,12 +628,18 @@ BOOST_AUTO_TEST_CASE(script_build) bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG, "2-of-2 with two identical keys and sigs pushed using OP_DUP", SCRIPT_VERIFY_SIGPUSHONLY ).Num(0).PushSig(keys.key1).Add(CScript() << OP_DUP).ScriptError(SCRIPT_ERR_SIG_PUSHONLY)); + good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG, + "P2SH(P2PK) with non-push scriptSig but no P2SH or SIGPUSHONLY", 0, true + ).PushSig(keys.key2).Add(CScript() << OP_NOP8).PushRedeem()); + good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG, + "P2PK with non-push scriptSig but with P2SH validation", 0 + ).PushSig(keys.key2).Add(CScript() << OP_NOP8)); bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG, - "P2SH(P2PK) with non-push scriptSig but no SIGPUSHONLY", 0 - ).PushSig(keys.key2).PushRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE)); + "P2SH(P2PK) with non-push scriptSig but no SIGPUSHONLY", SCRIPT_VERIFY_P2SH, true + ).PushSig(keys.key2).Add(CScript() << OP_NOP8).PushRedeem().ScriptError(SCRIPT_ERR_SIG_PUSHONLY)); bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG, - "P2SH(P2PK) with non-push scriptSig", SCRIPT_VERIFY_SIGPUSHONLY - ).PushSig(keys.key2).PushRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE)); + "P2SH(P2PK) with non-push scriptSig but not P2SH", SCRIPT_VERIFY_SIGPUSHONLY, true + ).PushSig(keys.key2).Add(CScript() << OP_NOP8).PushRedeem().ScriptError(SCRIPT_ERR_SIG_PUSHONLY)); good.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG, "2-of-2 with two identical keys and sigs pushed", SCRIPT_VERIFY_SIGPUSHONLY ).Num(0).PushSig(keys.key1).PushSig(keys.key1)); From 3373c43505cf76b63e7aa81b0d745d14765bd610 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Tue, 29 Mar 2016 15:16:16 -0300 Subject: [PATCH 0098/1802] [doc] Update port in tor.md Tor Browser Bundle spawns the Tor process and listens on port 9150, it doesn't randomly pick a port. [ci skip] (cherry picked from commit 1b63cf98347b2a62915425576930f55c2126c2ff) --- doc/tor.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/tor.md b/doc/tor.md index be4125544986d..43e922718b7dd 100644 --- a/doc/tor.md +++ b/doc/tor.md @@ -3,7 +3,7 @@ TOR SUPPORT IN BITCOIN It is possible to run Bitcoin as a Tor hidden service, and connect to such services. -The following directions assume you have a Tor proxy running on port 9050. Many distributions default to having a SOCKS proxy listening on port 9050, but others may not. In particular, the Tor Browser Bundle defaults to listening on a random port. See [Tor Project FAQ:TBBSocksPort](https://www.torproject.org/docs/faq.html.en#TBBSocksPort) for how to properly +The following directions assume you have a Tor proxy running on port 9050. Many distributions default to having a SOCKS proxy listening on port 9050, but others may not. In particular, the Tor Browser Bundle defaults to listening on port 9150. See [Tor Project FAQ:TBBSocksPort](https://www.torproject.org/docs/faq.html.en#TBBSocksPort) for how to properly configure Tor. From 76da7613517d05aca31c2cee42b5ebf3d5c54974 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 5 Apr 2016 15:45:10 +0200 Subject: [PATCH 0099/1802] Make script_error a mandatory 4th field for script_tests --- src/test/data/script_invalid.json | 1106 ++++++++++++------------- src/test/data/script_valid.json | 1246 +++++++++++++++-------------- src/test/script_tests.cpp | 15 +- 3 files changed, 1200 insertions(+), 1167 deletions(-) diff --git a/src/test/data/script_invalid.json b/src/test/data/script_invalid.json index b9f150eacb236..1427cb630a6f2 100644 --- a/src/test/data/script_invalid.json +++ b/src/test/data/script_invalid.json @@ -1,524 +1,524 @@ [ -["Format is: [scriptSig, scriptPubKey, flags, ... comments]"], +["Format is: [scriptSig, scriptPubKey, flags, expected_scripterror, ... comments]"], ["It is evaluated as if there was a crediting coinbase transaction with two 0"], ["pushes as scriptSig, and one output of 0 satoshi and given scriptPubKey,"], ["followed by a spending transaction which spends this output as only input (and"], ["correct prevout hash), using the given scriptSig. All nLockTimes are 0, all"], ["nSequences are max."], -["", "DEPTH", "P2SH,STRICTENC", "Test the test: we should have an empty stack after scriptSig evaluation", "EVAL_FALSE"], -[" ", "DEPTH", "P2SH,STRICTENC", "and multiple spaces should not change that.", "EVAL_FALSE"], -[" ", "DEPTH", "P2SH,STRICTENC", "", "EVAL_FALSE"], -[" ", "DEPTH", "P2SH,STRICTENC", "", "EVAL_FALSE"], - -["", "", "P2SH,STRICTENC","", "EVAL_FALSE"], -["", "NOP", "P2SH,STRICTENC","", "EVAL_FALSE"], -["", "NOP DEPTH", "P2SH,STRICTENC", "", "EVAL_FALSE"], -["NOP", "", "P2SH,STRICTENC", "", "EVAL_FALSE"], -["NOP", "DEPTH", "P2SH,STRICTENC", "", "EVAL_FALSE"], -["NOP","NOP", "P2SH,STRICTENC", "", "EVAL_FALSE"], -["NOP","NOP DEPTH", "P2SH,STRICTENC", "", "EVAL_FALSE"], - -["DEPTH", "", "P2SH,STRICTENC", "", "EVAL_FALSE"], - -["0x4c01","0x01 NOP", "P2SH,STRICTENC", "PUSHDATA1 with not enough bytes","BAD_OPCODE"], -["0x4d0200ff","0x01 NOP", "P2SH,STRICTENC", "PUSHDATA2 with not enough bytes","BAD_OPCODE"], -["0x4e03000000ffff","0x01 NOP", "P2SH,STRICTENC", "PUSHDATA4 with not enough bytes","BAD_OPCODE"], - -["1", "IF 0x50 ENDIF 1", "P2SH,STRICTENC", "0x50 is reserved","BAD_OPCODE"], -["0x52", "0x5f ADD 0x60 EQUAL", "P2SH,STRICTENC", "0x51 through 0x60 push 1 through 16 onto stack","EVAL_FALSE"], -["0","NOP", "P2SH,STRICTENC","","EVAL_FALSE"], -["1", "IF VER ELSE 1 ENDIF", "P2SH,STRICTENC", "VER non-functional", "BAD_OPCODE"], -["0", "IF VERIF ELSE 1 ENDIF", "P2SH,STRICTENC", "VERIF illegal everywhere", "BAD_OPCODE"], -["0", "IF ELSE 1 ELSE VERIF ENDIF", "P2SH,STRICTENC", "VERIF illegal everywhere", "BAD_OPCODE"], -["0", "IF VERNOTIF ELSE 1 ENDIF", "P2SH,STRICTENC", "VERNOTIF illegal everywhere", "BAD_OPCODE"], -["0", "IF ELSE 1 ELSE VERNOTIF ENDIF", "P2SH,STRICTENC", "VERNOTIF illegal everywhere", "BAD_OPCODE"], - -["1 IF", "1 ENDIF", "P2SH,STRICTENC", "IF/ENDIF can't span scriptSig/scriptPubKey", "UNBALANCED_CONDITIONAL"], -["1 IF 0 ENDIF", "1 ENDIF", "P2SH,STRICTENC", "", "UNBALANCED_CONDITIONAL"], -["1 ELSE 0 ENDIF", "1", "P2SH,STRICTENC", "", "UNBALANCED_CONDITIONAL"], -["0 NOTIF", "123", "P2SH,STRICTENC", "", "UNBALANCED_CONDITIONAL"], - -["0", "DUP IF ENDIF", "P2SH,STRICTENC", "", "EVAL_FALSE"], -["0", "IF 1 ENDIF", "P2SH,STRICTENC", "", "EVAL_FALSE"], -["0", "DUP IF ELSE ENDIF", "P2SH,STRICTENC", "", "EVAL_FALSE"], -["0", "IF 1 ELSE ENDIF", "P2SH,STRICTENC", "", "EVAL_FALSE"], -["0", "NOTIF ELSE 1 ENDIF", "P2SH,STRICTENC", "", "EVAL_FALSE"], - -["0 1", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "", "EVAL_FALSE"], -["0 0", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "", "EVAL_FALSE"], -["1 0", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "", "EVAL_FALSE"], -["0 1", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "", "EVAL_FALSE"], - -["0 0", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "", "EVAL_FALSE"], -["0 1", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "", "EVAL_FALSE"], -["1 1", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "", "EVAL_FALSE"], -["0 0", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "", "EVAL_FALSE"], - -["1", "IF RETURN ELSE ELSE 1 ENDIF", "P2SH,STRICTENC", "Multiple ELSEs", "OP_RETURN"], -["1", "IF 1 ELSE ELSE RETURN ENDIF", "P2SH,STRICTENC", "", "OP_RETURN"], - -["1", "ENDIF", "P2SH,STRICTENC", "Malformed IF/ELSE/ENDIF sequence", "UNBALANCED_CONDITIONAL"], -["1", "ELSE ENDIF", "P2SH,STRICTENC", "", "UNBALANCED_CONDITIONAL"], -["1", "ENDIF ELSE", "P2SH,STRICTENC", "", "UNBALANCED_CONDITIONAL"], -["1", "ENDIF ELSE IF", "P2SH,STRICTENC", "", "UNBALANCED_CONDITIONAL"], -["1", "IF ELSE ENDIF ELSE", "P2SH,STRICTENC", "", "UNBALANCED_CONDITIONAL"], -["1", "IF ELSE ENDIF ELSE ENDIF", "P2SH,STRICTENC", "", "UNBALANCED_CONDITIONAL"], -["1", "IF ENDIF ENDIF", "P2SH,STRICTENC", "", "UNBALANCED_CONDITIONAL"], -["1", "IF ELSE ELSE ENDIF ENDIF", "P2SH,STRICTENC", "", "UNBALANCED_CONDITIONAL"], - -["1", "RETURN", "P2SH,STRICTENC", "", "OP_RETURN"], -["1", "DUP IF RETURN ENDIF", "P2SH,STRICTENC", "", "OP_RETURN"], - -["1", "RETURN 'data'", "P2SH,STRICTENC", "canonical prunable txout format", "OP_RETURN"], -["0 IF", "RETURN ENDIF 1", "P2SH,STRICTENC", "still prunable because IF/ENDIF can't span scriptSig/scriptPubKey", "UNBALANCED_CONDITIONAL"], - -["0", "VERIFY 1", "P2SH,STRICTENC", "", "VERIFY"], -["1", "VERIFY", "P2SH,STRICTENC", "", "EVAL_FALSE"], -["1", "VERIFY 0", "P2SH,STRICTENC", "", "EVAL_FALSE"], - -["1 TOALTSTACK", "FROMALTSTACK 1", "P2SH,STRICTENC", "alt stack not shared between sig/pubkey", "INVALID_ALTSTACK_OPERATION"], - -["IFDUP", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["DROP", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["DUP", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1", "DUP 1 ADD 2 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC", "", "EVAL_FALSE"], -["NOP", "NIP", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["NOP", "1 NIP", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["NOP", "1 0 NIP", "P2SH,STRICTENC", "", "EVAL_FALSE"], -["NOP", "OVER 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1", "OVER", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["0 1", "OVER DEPTH 3 EQUALVERIFY", "P2SH,STRICTENC", "", "EVAL_FALSE"], -["19 20 21", "PICK 19 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["NOP", "0 PICK", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1", "-1 PICK", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["19 20 21", "0 PICK 20 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "", "EQUALVERIFY"], -["19 20 21", "1 PICK 21 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "", "EQUALVERIFY"], -["19 20 21", "2 PICK 22 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "", "EQUALVERIFY"], -["NOP", "0 ROLL", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1", "-1 ROLL", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["19 20 21", "0 ROLL 20 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "", "EQUALVERIFY"], -["19 20 21", "1 ROLL 21 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "", "EQUALVERIFY"], -["19 20 21", "2 ROLL 22 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "", "EQUALVERIFY"], -["NOP", "ROT 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["NOP", "1 ROT 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["NOP", "1 2 ROT 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["NOP", "0 1 2 ROT", "P2SH,STRICTENC", "", "EVAL_FALSE"], -["NOP", "SWAP 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1", "SWAP 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["0 1", "SWAP 1 EQUALVERIFY", "P2SH,STRICTENC", "", "EQUALVERIFY"], -["NOP", "TUCK 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1", "TUCK 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1 0", "TUCK DEPTH 3 EQUALVERIFY SWAP 2DROP", "P2SH,STRICTENC", "", "EVAL_FALSE"], -["NOP", "2DUP 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1", "2DUP 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["NOP", "3DUP 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1", "3DUP 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1 2", "3DUP 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["NOP", "2OVER 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1", "2 3 2OVER 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["NOP", "2SWAP 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1", "2 3 2SWAP 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], - -["'a' 'b'", "CAT", "P2SH,STRICTENC", "CAT disabled", "DISABLED_OPCODE"], -["'a' 'b' 0", "IF CAT ELSE 1 ENDIF", "P2SH,STRICTENC", "CAT disabled", "DISABLED_OPCODE"], -["'abc' 1 1", "SUBSTR", "P2SH,STRICTENC", "SUBSTR disabled", "DISABLED_OPCODE"], -["'abc' 1 1 0", "IF SUBSTR ELSE 1 ENDIF", "P2SH,STRICTENC", "SUBSTR disabled", "DISABLED_OPCODE"], -["'abc' 2 0", "IF LEFT ELSE 1 ENDIF", "P2SH,STRICTENC", "LEFT disabled", "DISABLED_OPCODE"], -["'abc' 2 0", "IF RIGHT ELSE 1 ENDIF", "P2SH,STRICTENC", "RIGHT disabled", "DISABLED_OPCODE"], - -["NOP", "SIZE 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], - -["'abc'", "IF INVERT ELSE 1 ENDIF", "P2SH,STRICTENC", "INVERT disabled", "DISABLED_OPCODE"], -["1 2 0 IF AND ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "AND disabled", "DISABLED_OPCODE"], -["1 2 0 IF OR ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "OR disabled", "DISABLED_OPCODE"], -["1 2 0 IF XOR ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "XOR disabled", "DISABLED_OPCODE"], -["2 0 IF 2MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "2MUL disabled", "DISABLED_OPCODE"], -["2 0 IF 2DIV ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "2DIV disabled", "DISABLED_OPCODE"], -["2 2 0 IF MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "MUL disabled", "DISABLED_OPCODE"], -["2 2 0 IF DIV ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DIV disabled", "DISABLED_OPCODE"], -["2 2 0 IF MOD ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "MOD disabled", "DISABLED_OPCODE"], -["2 2 0 IF LSHIFT ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "LSHIFT disabled", "DISABLED_OPCODE"], -["2 2 0 IF RSHIFT ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "RSHIFT disabled", "DISABLED_OPCODE"], - -["", "EQUAL NOT", "P2SH,STRICTENC", "EQUAL must error when there are no stack items", "INVALID_STACK_OPERATION"], -["0", "EQUAL NOT", "P2SH,STRICTENC", "EQUAL must error when there are not 2 stack items", "INVALID_STACK_OPERATION"], -["0 1","EQUAL", "P2SH,STRICTENC", "", "EVAL_FALSE"], -["1 1 ADD", "0 EQUAL", "P2SH,STRICTENC", "", "EVAL_FALSE"], -["11 1 ADD 12 SUB", "11 EQUAL", "P2SH,STRICTENC", "", "EVAL_FALSE"], - -["2147483648 0 ADD", "NOP", "P2SH,STRICTENC", "arithmetic operands must be in range [-2^31...2^31] ", "UNKNOWN_ERROR"], -["-2147483648 0 ADD", "NOP", "P2SH,STRICTENC", "arithmetic operands must be in range [-2^31...2^31] ", "UNKNOWN_ERROR"], -["2147483647 DUP ADD", "4294967294 NUMEQUAL", "P2SH,STRICTENC", "NUMEQUAL must be in numeric range", "UNKNOWN_ERROR"], -["'abcdef' NOT", "0 EQUAL", "P2SH,STRICTENC", "NOT is an arithmetic operand", "UNKNOWN_ERROR"], - -["2 DUP MUL", "4 EQUAL", "P2SH,STRICTENC", "disabled", "DISABLED_OPCODE"], -["2 DUP DIV", "1 EQUAL", "P2SH,STRICTENC", "disabled", "DISABLED_OPCODE"], -["2 2MUL", "4 EQUAL", "P2SH,STRICTENC", "disabled", "DISABLED_OPCODE"], -["2 2DIV", "1 EQUAL", "P2SH,STRICTENC", "disabled", "DISABLED_OPCODE"], -["7 3 MOD", "1 EQUAL", "P2SH,STRICTENC", "disabled", "DISABLED_OPCODE"], -["2 2 LSHIFT", "8 EQUAL", "P2SH,STRICTENC", "disabled", "DISABLED_OPCODE"], -["2 1 RSHIFT", "1 EQUAL", "P2SH,STRICTENC", "disabled", "DISABLED_OPCODE"], - -["1","NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 2 EQUAL", "P2SH,STRICTENC", "", "EVAL_FALSE"], -["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_11' EQUAL", "P2SH,STRICTENC", "", "EVAL_FALSE"], +["", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE", "Test the test: we should have an empty stack after scriptSig evaluation"], +[" ", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE", "and multiple spaces should not change that."], +[" ", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE"], +[" ", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE"], + +["", "", "P2SH,STRICTENC","EVAL_FALSE"], +["", "NOP", "P2SH,STRICTENC","EVAL_FALSE"], +["", "NOP DEPTH", "P2SH,STRICTENC", "EVAL_FALSE"], +["NOP", "", "P2SH,STRICTENC", "EVAL_FALSE"], +["NOP", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE"], +["NOP","NOP", "P2SH,STRICTENC", "EVAL_FALSE"], +["NOP","NOP DEPTH", "P2SH,STRICTENC", "EVAL_FALSE"], + +["DEPTH", "", "P2SH,STRICTENC", "EVAL_FALSE"], + +["0x4c01","0x01 NOP", "P2SH,STRICTENC","BAD_OPCODE", "PUSHDATA1 with not enough bytes"], +["0x4d0200ff","0x01 NOP", "P2SH,STRICTENC","BAD_OPCODE", "PUSHDATA2 with not enough bytes"], +["0x4e03000000ffff","0x01 NOP", "P2SH,STRICTENC","BAD_OPCODE", "PUSHDATA4 with not enough bytes"], + +["1", "IF 0x50 ENDIF 1", "P2SH,STRICTENC","BAD_OPCODE", "0x50 is reserved"], +["0x52", "0x5f ADD 0x60 EQUAL", "P2SH,STRICTENC","EVAL_FALSE", "0x51 through 0x60 push 1 through 16 onto stack"], +["0","NOP", "P2SH,STRICTENC","EVAL_FALSE",""], +["1", "IF VER ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "VER non-functional"], +["0", "IF VERIF ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "VERIF illegal everywhere"], +["0", "IF ELSE 1 ELSE VERIF ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "VERIF illegal everywhere"], +["0", "IF VERNOTIF ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "VERNOTIF illegal everywhere"], +["0", "IF ELSE 1 ELSE VERNOTIF ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "VERNOTIF illegal everywhere"], + +["1 IF", "1 ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "IF/ENDIF can't span scriptSig/scriptPubKey"], +["1 IF 0 ENDIF", "1 ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], +["1 ELSE 0 ENDIF", "1", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], +["0 NOTIF", "123", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], + +["0", "DUP IF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], +["0", "IF 1 ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], +["0", "DUP IF ELSE ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], +["0", "IF 1 ELSE ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], +["0", "NOTIF ELSE 1 ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], + +["0 1", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], +["0 0", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], +["1 0", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], +["0 1", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], + +["0 0", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], +["0 1", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], +["1 1", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], +["0 0", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], + +["1", "IF RETURN ELSE ELSE 1 ENDIF", "P2SH,STRICTENC", "OP_RETURN", "Multiple ELSEs"], +["1", "IF 1 ELSE ELSE RETURN ENDIF", "P2SH,STRICTENC", "OP_RETURN"], + +["1", "ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "Malformed IF/ELSE/ENDIF sequence"], +["1", "ELSE ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], +["1", "ENDIF ELSE", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], +["1", "ENDIF ELSE IF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], +["1", "IF ELSE ENDIF ELSE", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], +["1", "IF ELSE ENDIF ELSE ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], +["1", "IF ENDIF ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], +["1", "IF ELSE ELSE ENDIF ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], + +["1", "RETURN", "P2SH,STRICTENC", "OP_RETURN"], +["1", "DUP IF RETURN ENDIF", "P2SH,STRICTENC", "OP_RETURN"], + +["1", "RETURN 'data'", "P2SH,STRICTENC", "OP_RETURN", "canonical prunable txout format"], +["0 IF", "RETURN ENDIF 1", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "still prunable because IF/ENDIF can't span scriptSig/scriptPubKey"], + +["0", "VERIFY 1", "P2SH,STRICTENC", "VERIFY"], +["1", "VERIFY", "P2SH,STRICTENC", "EVAL_FALSE"], +["1", "VERIFY 0", "P2SH,STRICTENC", "EVAL_FALSE"], + +["1 TOALTSTACK", "FROMALTSTACK 1", "P2SH,STRICTENC", "INVALID_ALTSTACK_OPERATION", "alt stack not shared between sig/pubkey"], + +["IFDUP", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["DROP", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["DUP", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "DUP 1 ADD 2 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], +["NOP", "NIP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "1 NIP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "1 0 NIP", "P2SH,STRICTENC", "EVAL_FALSE"], +["NOP", "OVER 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "OVER", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["0 1", "OVER DEPTH 3 EQUALVERIFY", "P2SH,STRICTENC", "EVAL_FALSE"], +["19 20 21", "PICK 19 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "0 PICK", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "-1 PICK", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["19 20 21", "0 PICK 20 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "EQUALVERIFY"], +["19 20 21", "1 PICK 21 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "EQUALVERIFY"], +["19 20 21", "2 PICK 22 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "EQUALVERIFY"], +["NOP", "0 ROLL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "-1 ROLL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["19 20 21", "0 ROLL 20 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "EQUALVERIFY"], +["19 20 21", "1 ROLL 21 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "EQUALVERIFY"], +["19 20 21", "2 ROLL 22 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "EQUALVERIFY"], +["NOP", "ROT 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "1 ROT 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "1 2 ROT 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "0 1 2 ROT", "P2SH,STRICTENC", "EVAL_FALSE"], +["NOP", "SWAP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "SWAP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["0 1", "SWAP 1 EQUALVERIFY", "P2SH,STRICTENC", "EQUALVERIFY"], +["NOP", "TUCK 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "TUCK 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1 0", "TUCK DEPTH 3 EQUALVERIFY SWAP 2DROP", "P2SH,STRICTENC", "EVAL_FALSE"], +["NOP", "2DUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "2DUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "3DUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "3DUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1 2", "3DUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "2OVER 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "2 3 2OVER 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "2SWAP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "2 3 2SWAP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], + +["'a' 'b'", "CAT", "P2SH,STRICTENC", "DISABLED_OPCODE", "CAT disabled"], +["'a' 'b' 0", "IF CAT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "CAT disabled"], +["'abc' 1 1", "SUBSTR", "P2SH,STRICTENC", "DISABLED_OPCODE", "SUBSTR disabled"], +["'abc' 1 1 0", "IF SUBSTR ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "SUBSTR disabled"], +["'abc' 2 0", "IF LEFT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "LEFT disabled"], +["'abc' 2 0", "IF RIGHT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "RIGHT disabled"], + +["NOP", "SIZE 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], + +["'abc'", "IF INVERT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "INVERT disabled"], +["1 2 0 IF AND ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "AND disabled"], +["1 2 0 IF OR ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "OR disabled"], +["1 2 0 IF XOR ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "XOR disabled"], +["2 0 IF 2MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "2MUL disabled"], +["2 0 IF 2DIV ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "2DIV disabled"], +["2 2 0 IF MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "MUL disabled"], +["2 2 0 IF DIV ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "DIV disabled"], +["2 2 0 IF MOD ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "MOD disabled"], +["2 2 0 IF LSHIFT ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "LSHIFT disabled"], +["2 2 0 IF RSHIFT ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "RSHIFT disabled"], + +["", "EQUAL NOT", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "EQUAL must error when there are no stack items"], +["0", "EQUAL NOT", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "EQUAL must error when there are not 2 stack items"], +["0 1","EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], +["1 1 ADD", "0 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], +["11 1 ADD 12 SUB", "11 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], + +["2147483648 0 ADD", "NOP", "P2SH,STRICTENC", "UNKNOWN_ERROR", "arithmetic operands must be in range [-2^31...2^31] "], +["-2147483648 0 ADD", "NOP", "P2SH,STRICTENC", "UNKNOWN_ERROR", "arithmetic operands must be in range [-2^31...2^31] "], +["2147483647 DUP ADD", "4294967294 NUMEQUAL", "P2SH,STRICTENC", "UNKNOWN_ERROR", "NUMEQUAL must be in numeric range"], +["'abcdef' NOT", "0 EQUAL", "P2SH,STRICTENC", "UNKNOWN_ERROR", "NOT is an arithmetic operand"], + +["2 DUP MUL", "4 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], +["2 DUP DIV", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], +["2 2MUL", "4 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], +["2 2DIV", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], +["7 3 MOD", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], +["2 2 LSHIFT", "8 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], +["2 1 RSHIFT", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], + +["1","NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 2 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], +["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_11' EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], ["Ensure 100% coverage of discouraged NOPS"], -["1", "NOP1", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "", "DISCOURAGE_UPGRADABLE_NOPS"], -["1", "CHECKLOCKTIMEVERIFY", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "", "DISCOURAGE_UPGRADABLE_NOPS"], -["1", "NOP3", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "", "DISCOURAGE_UPGRADABLE_NOPS"], -["1", "NOP4", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "", "DISCOURAGE_UPGRADABLE_NOPS"], -["1", "NOP5", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "", "DISCOURAGE_UPGRADABLE_NOPS"], -["1", "NOP6", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "", "DISCOURAGE_UPGRADABLE_NOPS"], -["1", "NOP7", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "", "DISCOURAGE_UPGRADABLE_NOPS"], -["1", "NOP8", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "", "DISCOURAGE_UPGRADABLE_NOPS"], -["1", "NOP9", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "", "DISCOURAGE_UPGRADABLE_NOPS"], -["1", "NOP10", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "", "DISCOURAGE_UPGRADABLE_NOPS"], - -["NOP10", "1", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "Discouraged NOP10 in scriptSig", "DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP1", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], +["1", "CHECKLOCKTIMEVERIFY", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP3", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP4", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP5", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP6", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP7", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP8", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP9", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP10", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], + +["NOP10", "1", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS", "Discouraged NOP10 in scriptSig"], ["1 0x01 0xb9", "HASH160 0x14 0x15727299b05b45fdaf9ac9ecf7565cfe27c3e567 EQUAL", - "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "Discouraged NOP10 in redeemScript", "DISCOURAGE_UPGRADABLE_NOPS"], - -["0x50","1", "P2SH,STRICTENC", "opcode 0x50 is reserved", "BAD_OPCODE"], -["1", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "opcodes above NOP10 invalid if executed", "BAD_OPCODE"], -["1", "IF 0xbb ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xbe ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xbf ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xc0 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xc1 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xc2 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xc3 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xc4 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xc5 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xc6 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xc7 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xc8 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xc9 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xca ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xcb ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xcc ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xcd ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xce ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xcf ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xd0 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xd1 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xd2 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xd3 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xd4 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xd5 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xd6 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xd7 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xd8 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xd9 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xda ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xdb ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xdc ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xdd ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xde ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xdf ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xe0 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xe1 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xe2 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xe3 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xe4 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xe5 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xe6 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xe7 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xe8 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xe9 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xea ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xeb ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xec ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xed ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xee ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xef ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xf0 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xf1 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xf2 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xf3 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xf4 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xf5 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xf6 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xf7 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xf8 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xf9 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xfa ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xfb ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xfc ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xfd ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xfe ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], -["1", "IF 0xff ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"], - -["1 IF 1 ELSE", "0xff ENDIF", "P2SH,STRICTENC", "invalid because scriptSig and scriptPubKey are processed separately", "UNBALANCED_CONDITIONAL"], - -["NOP", "RIPEMD160", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["NOP", "SHA1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["NOP", "SHA256", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["NOP", "HASH160", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["NOP", "HASH256", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], + "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS", "Discouraged NOP10 in redeemScript"], + +["0x50","1", "P2SH,STRICTENC", "BAD_OPCODE", "opcode 0x50 is reserved"], +["1", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "opcodes above NOP10 invalid if executed"], +["1", "IF 0xbb ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xbe ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xbf ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xc0 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xc1 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xc2 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xc3 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xc4 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xc5 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xc6 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xc7 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xc8 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xc9 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xca ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xcb ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xcc ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xcd ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xce ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xcf ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xd0 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xd1 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xd2 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xd3 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xd4 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xd5 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xd6 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xd7 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xd8 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xd9 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xda ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xdb ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xdc ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xdd ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xde ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xdf ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xe0 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xe1 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xe2 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xe3 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xe4 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xe5 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xe6 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xe7 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xe8 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xe9 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xea ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xeb ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xec ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xed ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xee ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xef ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xf0 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xf1 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xf2 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xf3 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xf4 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xf5 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xf6 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xf7 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xf8 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xf9 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xfa ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xfb ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xfc ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xfd ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xfe ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xff ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], + +["1 IF 1 ELSE", "0xff ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "invalid because scriptSig and scriptPubKey are processed separately"], + +["NOP", "RIPEMD160", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "SHA1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "SHA256", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "HASH160", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "HASH256", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["NOP", "'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'", "P2SH,STRICTENC", -">520 byte push", -"PUSH_SIZE"], +"PUSH_SIZE", +">520 byte push"], ["0", "IF 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' ENDIF 1", "P2SH,STRICTENC", -">520 byte push in non-executed IF branch", -"PUSH_SIZE"], +"PUSH_SIZE", +">520 byte push in non-executed IF branch"], ["1", "0x61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "P2SH,STRICTENC", -">201 opcodes executed. 0x61 is NOP", -"OP_COUNT"], +"OP_COUNT", +">201 opcodes executed. 0x61 is NOP"], ["0", "IF 0x6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161 ENDIF 1", "P2SH,STRICTENC", -">201 opcodes including non-executed IF branch. 0x61 is NOP", -"OP_COUNT"], +"OP_COUNT", +">201 opcodes including non-executed IF branch. 0x61 is NOP"], ["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", "1 2 3 4 5 6 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", "P2SH,STRICTENC", -">1,000 stack size (0x6f is 3DUP)", -"STACK_SIZE"], +"STACK_SIZE", +">1,000 stack size (0x6f is 3DUP)"], ["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", "1 TOALTSTACK 2 TOALTSTACK 3 4 5 6 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", "P2SH,STRICTENC", -">1,000 stack+altstack size", -"STACK_SIZE"], +"STACK_SIZE", +">1,000 stack+altstack size"], ["NOP", "0 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f 2DUP 0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "P2SH,STRICTENC", -"10,001-byte scriptPubKey", -"SCRIPT_SIZE"], - -["NOP1","NOP10", "P2SH,STRICTENC", "", "EVAL_FALSE"], - -["1","VER", "P2SH,STRICTENC", "OP_VER is reserved", "BAD_OPCODE"], -["1","VERIF", "P2SH,STRICTENC", "OP_VERIF is reserved", "BAD_OPCODE"], -["1","VERNOTIF", "P2SH,STRICTENC", "OP_VERNOTIF is reserved", "BAD_OPCODE"], -["1","RESERVED", "P2SH,STRICTENC", "OP_RESERVED is reserved", "BAD_OPCODE"], -["1","RESERVED1", "P2SH,STRICTENC", "OP_RESERVED1 is reserved", "BAD_OPCODE"], -["1","RESERVED2", "P2SH,STRICTENC", "OP_RESERVED2 is reserved", "BAD_OPCODE"], -["1","0xba", "P2SH,STRICTENC", "0xba == OP_NOP10 + 1", "BAD_OPCODE"], - -["2147483648", "1ADD 1", "P2SH,STRICTENC", "We cannot do math on 5-byte integers", "UNKNOWN_ERROR"], -["2147483648", "NEGATE 1", "P2SH,STRICTENC", "We cannot do math on 5-byte integers", "UNKNOWN_ERROR"], -["-2147483648", "1ADD 1", "P2SH,STRICTENC", "Because we use a sign bit, -2147483648 is also 5 bytes", "UNKNOWN_ERROR"], -["2147483647", "1ADD 1SUB 1", "P2SH,STRICTENC", "We cannot do math on 5-byte integers, even if the result is 4-bytes", "UNKNOWN_ERROR"], -["2147483648", "1SUB 1", "P2SH,STRICTENC", "We cannot do math on 5-byte integers, even if the result is 4-bytes", "UNKNOWN_ERROR"], - -["2147483648 1", "BOOLOR 1", "P2SH,STRICTENC", "We cannot do BOOLOR on 5-byte integers (but we can still do IF etc)", "UNKNOWN_ERROR"], -["2147483648 1", "BOOLAND 1", "P2SH,STRICTENC", "We cannot do BOOLAND on 5-byte integers", "UNKNOWN_ERROR"], - -["1", "1 ENDIF", "P2SH,STRICTENC", "ENDIF without IF", "UNBALANCED_CONDITIONAL"], -["1", "IF 1", "P2SH,STRICTENC", "IF without ENDIF", "UNBALANCED_CONDITIONAL"], -["1 IF 1", "ENDIF", "P2SH,STRICTENC", "IFs don't carry over", "UNBALANCED_CONDITIONAL"], - -["NOP", "IF 1 ENDIF", "P2SH,STRICTENC", "The following tests check the if(stack.size() < N) tests in each opcode", "UNBALANCED_CONDITIONAL"], -["NOP", "NOTIF 1 ENDIF", "P2SH,STRICTENC", "They are here to catch copy-and-paste errors", "UNBALANCED_CONDITIONAL"], -["NOP", "VERIFY 1", "P2SH,STRICTENC", "Most of them are duplicated elsewhere,", "INVALID_STACK_OPERATION"], - -["NOP", "TOALTSTACK 1", "P2SH,STRICTENC", "but, hey, more is always better, right?", "INVALID_STACK_OPERATION"], -["1", "FROMALTSTACK", "P2SH,STRICTENC", "", "INVALID_ALTSTACK_OPERATION"], -["1", "2DROP 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1", "2DUP", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1 1", "3DUP", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1 1 1", "2OVER", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1 1 1 1 1", "2ROT", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1 1 1", "2SWAP", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["NOP", "IFDUP 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["NOP", "DROP 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["NOP", "DUP 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1", "NIP", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1", "OVER", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1 1 1 3", "PICK", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["0", "PICK 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1 1 1 3", "ROLL", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["0", "ROLL 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1 1", "ROT", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1", "SWAP", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1", "TUCK", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], - -["NOP", "SIZE 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], - -["1", "EQUAL 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1", "EQUALVERIFY 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], - -["NOP", "1ADD 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["NOP", "1SUB 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["NOP", "NEGATE 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["NOP", "ABS 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["NOP", "NOT 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["NOP", "0NOTEQUAL 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], - -["1", "ADD", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1", "SUB", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1", "BOOLAND", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1", "BOOLOR", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1", "NUMEQUAL", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1", "NUMEQUALVERIFY 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1", "NUMNOTEQUAL", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1", "LESSTHAN", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1", "GREATERTHAN", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1", "LESSTHANOREQUAL", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1", "GREATERTHANOREQUAL", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1", "MIN", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1", "MAX", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["1 1", "WITHIN", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], - -["NOP", "RIPEMD160 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["NOP", "SHA1 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["NOP", "SHA256 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["NOP", "HASH160 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], -["NOP", "HASH256 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"], +"SCRIPT_SIZE", +"10,001-byte scriptPubKey"], + +["NOP1","NOP10", "P2SH,STRICTENC", "EVAL_FALSE"], + +["1","VER", "P2SH,STRICTENC", "BAD_OPCODE", "OP_VER is reserved"], +["1","VERIF", "P2SH,STRICTENC", "BAD_OPCODE", "OP_VERIF is reserved"], +["1","VERNOTIF", "P2SH,STRICTENC", "BAD_OPCODE", "OP_VERNOTIF is reserved"], +["1","RESERVED", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED is reserved"], +["1","RESERVED1", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED1 is reserved"], +["1","RESERVED2", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED2 is reserved"], +["1","0xba", "P2SH,STRICTENC", "BAD_OPCODE", "0xba == OP_NOP10 + 1"], + +["2147483648", "1ADD 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers"], +["2147483648", "NEGATE 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers"], +["-2147483648", "1ADD 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "Because we use a sign bit, -2147483648 is also 5 bytes"], +["2147483647", "1ADD 1SUB 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers, even if the result is 4-bytes"], +["2147483648", "1SUB 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers, even if the result is 4-bytes"], + +["2147483648 1", "BOOLOR 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do BOOLOR on 5-byte integers (but we can still do IF etc)"], +["2147483648 1", "BOOLAND 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do BOOLAND on 5-byte integers"], + +["1", "1 ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "ENDIF without IF"], +["1", "IF 1", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "IF without ENDIF"], +["1 IF 1", "ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "IFs don't carry over"], + +["NOP", "IF 1 ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "The following tests check the if(stack.size() < N) tests in each opcode"], +["NOP", "NOTIF 1 ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "They are here to catch copy-and-paste errors"], +["NOP", "VERIFY 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "Most of them are duplicated elsewhere,"], + +["NOP", "TOALTSTACK 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "but, hey, more is always better, right?"], +["1", "FROMALTSTACK", "P2SH,STRICTENC", "INVALID_ALTSTACK_OPERATION"], +["1", "2DROP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "2DUP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1 1", "3DUP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1 1 1", "2OVER", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1 1 1 1 1", "2ROT", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1 1 1", "2SWAP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "IFDUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "DROP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "DUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "NIP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "OVER", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1 1 1 3", "PICK", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["0", "PICK 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1 1 1 3", "ROLL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["0", "ROLL 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1 1", "ROT", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "SWAP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "TUCK", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], + +["NOP", "SIZE 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], + +["1", "EQUAL 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "EQUALVERIFY 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], + +["NOP", "1ADD 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "1SUB 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "NEGATE 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "ABS 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "NOT 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "0NOTEQUAL 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], + +["1", "ADD", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "SUB", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "BOOLAND", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "BOOLOR", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "NUMEQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "NUMEQUALVERIFY 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "NUMNOTEQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "LESSTHAN", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "GREATERTHAN", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "LESSTHANOREQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "GREATERTHANOREQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "MIN", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "MAX", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1 1", "WITHIN", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], + +["NOP", "RIPEMD160 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "SHA1 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "SHA256 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "HASH160 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "HASH256 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["Increase CHECKSIG and CHECKMULTISIG negative test coverage"], -["", "CHECKSIG NOT", "STRICTENC", "CHECKSIG must error when there are no stack items", "INVALID_STACK_OPERATION"], -["0", "CHECKSIG NOT", "STRICTENC", "CHECKSIG must error when there are not 2 stack items", "INVALID_STACK_OPERATION"], -["", "CHECKMULTISIG NOT", "STRICTENC", "CHECKMULTISIG must error when there are no stack items", "INVALID_STACK_OPERATION"], -["", "-1 CHECKMULTISIG NOT", "STRICTENC", "CHECKMULTISIG must error when the specified number of pubkeys is negative", "PUBKEY_COUNT"], -["", "1 CHECKMULTISIG NOT", "STRICTENC", "CHECKMULTISIG must error when there are not enough pubkeys on the stack", "INVALID_STACK_OPERATION"], -["", "-1 0 CHECKMULTISIG NOT", "STRICTENC", "CHECKMULTISIG must error when the specified number of signatures is negative", "SIG_COUNT"], -["", "1 'pk1' 1 CHECKMULTISIG NOT", "STRICTENC", "CHECKMULTISIG must error when there are not enough signatures on the stack", "INVALID_STACK_OPERATION"], -["", "'dummy' 'sig1' 1 'pk1' 1 CHECKMULTISIG IF 1 ENDIF", "", "CHECKMULTISIG must push false to stack when signature is invalid when NOT in strict enc mode","EVAL_FALSE"], +["", "CHECKSIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKSIG must error when there are no stack items"], +["0", "CHECKSIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKSIG must error when there are not 2 stack items"], +["", "CHECKMULTISIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKMULTISIG must error when there are no stack items"], +["", "-1 CHECKMULTISIG NOT", "STRICTENC", "PUBKEY_COUNT", "CHECKMULTISIG must error when the specified number of pubkeys is negative"], +["", "1 CHECKMULTISIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKMULTISIG must error when there are not enough pubkeys on the stack"], +["", "-1 0 CHECKMULTISIG NOT", "STRICTENC", "SIG_COUNT", "CHECKMULTISIG must error when the specified number of signatures is negative"], +["", "1 'pk1' 1 CHECKMULTISIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKMULTISIG must error when there are not enough signatures on the stack"], +["", "'dummy' 'sig1' 1 'pk1' 1 CHECKMULTISIG IF 1 ENDIF", "", "EVAL_FALSE", "CHECKMULTISIG must push false to stack when signature is invalid when NOT in strict enc mode"], ["", "0 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG", "P2SH,STRICTENC", -"202 CHECKMULTISIGS, fails due to 201 op limit", -"OP_COUNT"], +"OP_COUNT", +"202 CHECKMULTISIGS, fails due to 201 op limit"], ["1", "0 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY", "P2SH,STRICTENC", -"", -"INVALID_STACK_OPERATION"], +"INVALID_STACK_OPERATION", +""], ["", "NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG", "P2SH,STRICTENC", -"Fails due to 201 sig op limit", -"OP_COUNT"], +"OP_COUNT", +"Fails due to 201 sig op limit"], ["1", "NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY", "P2SH,STRICTENC", -"", -"OP_COUNT"], +"OP_COUNT", +""], -["0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21", "21 CHECKMULTISIG 1", "P2SH,STRICTENC", "nPubKeys > 20", "PUBKEY_COUNT"], -["0 'sig' 1 0", "CHECKMULTISIG 1", "P2SH,STRICTENC", "nSigs > nPubKeys", "SIG_COUNT"], +["0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21", "21 CHECKMULTISIG 1", "P2SH,STRICTENC", "PUBKEY_COUNT", "nPubKeys > 20"], +["0 'sig' 1 0", "CHECKMULTISIG 1", "P2SH,STRICTENC", "SIG_COUNT", "nSigs > nPubKeys"], -["NOP 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "Tests for Script.IsPushOnly()", "SIG_PUSHONLY"], -["NOP1 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "", "SIG_PUSHONLY"], +["NOP 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "SIG_PUSHONLY", "Tests for Script.IsPushOnly()"], +["NOP1 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "SIG_PUSHONLY"], -["0 0x01 0x50", "HASH160 0x14 0xece424a6bb6ddf4db592c0faed60685047a361b1 EQUAL", "P2SH,STRICTENC", "OP_RESERVED in P2SH should fail", "BAD_OPCODE"], -["0 0x01 VER", "HASH160 0x14 0x0f4d7845db968f2a81b530b6f3c1d6246d4c7e01 EQUAL", "P2SH,STRICTENC", "OP_VER in P2SH should fail", "BAD_OPCODE"], +["0 0x01 0x50", "HASH160 0x14 0xece424a6bb6ddf4db592c0faed60685047a361b1 EQUAL", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED in P2SH should fail"], +["0 0x01 VER", "HASH160 0x14 0x0f4d7845db968f2a81b530b6f3c1d6246d4c7e01 EQUAL", "P2SH,STRICTENC", "BAD_OPCODE", "OP_VER in P2SH should fail"], -["0x00", "'00' EQUAL", "P2SH,STRICTENC", "Basic OP_0 execution", "EVAL_FALSE"], +["0x00", "'00' EQUAL", "P2SH,STRICTENC", "EVAL_FALSE", "Basic OP_0 execution"], ["MINIMALDATA enforcement for PUSHDATAs"], -["0x4c 0x00", "DROP 1", "MINIMALDATA", "Empty vector minimally represented by OP_0", "MINIMALDATA"], -["0x01 0x81", "DROP 1", "MINIMALDATA", "-1 minimally represented by OP_1NEGATE", "MINIMALDATA"], -["0x01 0x01", "DROP 1", "MINIMALDATA", "1 to 16 minimally represented by OP_1 to OP_16", "MINIMALDATA"], -["0x01 0x02", "DROP 1", "MINIMALDATA", "", "MINIMALDATA"], -["0x01 0x03", "DROP 1", "MINIMALDATA", "", "MINIMALDATA"], -["0x01 0x04", "DROP 1", "MINIMALDATA", "", "MINIMALDATA"], -["0x01 0x05", "DROP 1", "MINIMALDATA", "", "MINIMALDATA"], -["0x01 0x06", "DROP 1", "MINIMALDATA", "", "MINIMALDATA"], -["0x01 0x07", "DROP 1", "MINIMALDATA", "", "MINIMALDATA"], -["0x01 0x08", "DROP 1", "MINIMALDATA", "", "MINIMALDATA"], -["0x01 0x09", "DROP 1", "MINIMALDATA", "", "MINIMALDATA"], -["0x01 0x0a", "DROP 1", "MINIMALDATA", "", "MINIMALDATA"], -["0x01 0x0b", "DROP 1", "MINIMALDATA", "", "MINIMALDATA"], -["0x01 0x0c", "DROP 1", "MINIMALDATA", "", "MINIMALDATA"], -["0x01 0x0d", "DROP 1", "MINIMALDATA", "", "MINIMALDATA"], -["0x01 0x0e", "DROP 1", "MINIMALDATA", "", "MINIMALDATA"], -["0x01 0x0f", "DROP 1", "MINIMALDATA", "", "MINIMALDATA"], -["0x01 0x10", "DROP 1", "MINIMALDATA", "", "MINIMALDATA"], +["0x4c 0x00", "DROP 1", "MINIMALDATA", "MINIMALDATA", "Empty vector minimally represented by OP_0"], +["0x01 0x81", "DROP 1", "MINIMALDATA", "MINIMALDATA", "-1 minimally represented by OP_1NEGATE"], +["0x01 0x01", "DROP 1", "MINIMALDATA", "MINIMALDATA", "1 to 16 minimally represented by OP_1 to OP_16"], +["0x01 0x02", "DROP 1", "MINIMALDATA", "MINIMALDATA"], +["0x01 0x03", "DROP 1", "MINIMALDATA", "MINIMALDATA"], +["0x01 0x04", "DROP 1", "MINIMALDATA", "MINIMALDATA"], +["0x01 0x05", "DROP 1", "MINIMALDATA", "MINIMALDATA"], +["0x01 0x06", "DROP 1", "MINIMALDATA", "MINIMALDATA"], +["0x01 0x07", "DROP 1", "MINIMALDATA", "MINIMALDATA"], +["0x01 0x08", "DROP 1", "MINIMALDATA", "MINIMALDATA"], +["0x01 0x09", "DROP 1", "MINIMALDATA", "MINIMALDATA"], +["0x01 0x0a", "DROP 1", "MINIMALDATA", "MINIMALDATA"], +["0x01 0x0b", "DROP 1", "MINIMALDATA", "MINIMALDATA"], +["0x01 0x0c", "DROP 1", "MINIMALDATA", "MINIMALDATA"], +["0x01 0x0d", "DROP 1", "MINIMALDATA", "MINIMALDATA"], +["0x01 0x0e", "DROP 1", "MINIMALDATA", "MINIMALDATA"], +["0x01 0x0f", "DROP 1", "MINIMALDATA", "MINIMALDATA"], +["0x01 0x10", "DROP 1", "MINIMALDATA", "MINIMALDATA"], ["0x4c 0x48 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "DROP 1", "MINIMALDATA", - "PUSHDATA1 of 72 bytes minimally represented by direct push", - "MINIMALDATA"], + "MINIMALDATA", + "PUSHDATA1 of 72 bytes minimally represented by direct push"], ["0x4d 0xFF00 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "DROP 1", "MINIMALDATA", - "PUSHDATA2 of 255 bytes minimally represented by PUSHDATA1", - "MINIMALDATA"], + "MINIMALDATA", + "PUSHDATA2 of 255 bytes minimally represented by PUSHDATA1"], ["0x4e 0x00010000 0x11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "DROP 1", "MINIMALDATA", - "PUSHDATA4 of 256 bytes minimally represented by PUSHDATA2", - "MINIMALDATA"], + "MINIMALDATA", + "PUSHDATA4 of 256 bytes minimally represented by PUSHDATA2"], ["MINIMALDATA enforcement for numeric arguments"], -["0x01 0x00", "NOT DROP 1", "MINIMALDATA", "numequals 0", "UNKNOWN_ERROR"], -["0x02 0x0000", "NOT DROP 1", "MINIMALDATA", "numequals 0", "UNKNOWN_ERROR"], -["0x01 0x80", "NOT DROP 1", "MINIMALDATA", "0x80 (negative zero) numequals 0", "UNKNOWN_ERROR"], -["0x02 0x0080", "NOT DROP 1", "MINIMALDATA", "numequals 0", "UNKNOWN_ERROR"], -["0x02 0x0500", "NOT DROP 1", "MINIMALDATA", "numequals 5", "UNKNOWN_ERROR"], -["0x03 0x050000", "NOT DROP 1", "MINIMALDATA", "numequals 5", "UNKNOWN_ERROR"], -["0x02 0x0580", "NOT DROP 1", "MINIMALDATA", "numequals -5", "UNKNOWN_ERROR"], -["0x03 0x050080", "NOT DROP 1", "MINIMALDATA", "numequals -5", "UNKNOWN_ERROR"], -["0x03 0xff7f80", "NOT DROP 1", "MINIMALDATA", "Minimal encoding is 0xffff", "UNKNOWN_ERROR"], -["0x03 0xff7f00", "NOT DROP 1", "MINIMALDATA", "Minimal encoding is 0xff7f", "UNKNOWN_ERROR"], -["0x04 0xffff7f80", "NOT DROP 1", "MINIMALDATA", "Minimal encoding is 0xffffff", "UNKNOWN_ERROR"], -["0x04 0xffff7f00", "NOT DROP 1", "MINIMALDATA", "Minimal encoding is 0xffff7f", "UNKNOWN_ERROR"], +["0x01 0x00", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals 0"], +["0x02 0x0000", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals 0"], +["0x01 0x80", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "0x80 (negative zero) numequals 0"], +["0x02 0x0080", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals 0"], +["0x02 0x0500", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals 5"], +["0x03 0x050000", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals 5"], +["0x02 0x0580", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals -5"], +["0x03 0x050080", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals -5"], +["0x03 0xff7f80", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "Minimal encoding is 0xffff"], +["0x03 0xff7f00", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "Minimal encoding is 0xff7f"], +["0x04 0xffff7f80", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "Minimal encoding is 0xffffff"], +["0x04 0xffff7f00", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "Minimal encoding is 0xffff7f"], ["Test every numeric-accepting opcode for correct handling of the numeric minimal encoding rule"], -["1 0x02 0x0000", "PICK DROP", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["1 0x02 0x0000", "ROLL DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0x02 0x0000", "1ADD DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0x02 0x0000", "1SUB DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0x02 0x0000", "NEGATE DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0x02 0x0000", "ABS DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0x02 0x0000", "NOT DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0x02 0x0000", "0NOTEQUAL DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], - -["0 0x02 0x0000", "ADD DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0x02 0x0000 0", "ADD DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0 0x02 0x0000", "SUB DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0x02 0x0000 0", "SUB DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0 0x02 0x0000", "BOOLAND DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0x02 0x0000 0", "BOOLAND DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0 0x02 0x0000", "BOOLOR DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0x02 0x0000 0", "BOOLOR DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0 0x02 0x0000", "NUMEQUAL DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0x02 0x0000 1", "NUMEQUAL DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0 0x02 0x0000", "NUMEQUALVERIFY 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0x02 0x0000 0", "NUMEQUALVERIFY 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0 0x02 0x0000", "NUMNOTEQUAL DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0x02 0x0000 0", "NUMNOTEQUAL DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0 0x02 0x0000", "LESSTHAN DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0x02 0x0000 0", "LESSTHAN DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0 0x02 0x0000", "GREATERTHAN DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0x02 0x0000 0", "GREATERTHAN DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0 0x02 0x0000", "LESSTHANOREQUAL DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0x02 0x0000 0", "LESSTHANOREQUAL DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0 0x02 0x0000", "GREATERTHANOREQUAL DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0x02 0x0000 0", "GREATERTHANOREQUAL DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0 0x02 0x0000", "MIN DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0x02 0x0000 0", "MIN DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0 0x02 0x0000", "MAX DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0x02 0x0000 0", "MAX DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], - -["0x02 0x0000 0 0", "WITHIN DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0 0x02 0x0000 0", "WITHIN DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0 0 0x02 0x0000", "WITHIN DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], - -["0 0 0x02 0x0000", "CHECKMULTISIG DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0 0x02 0x0000 0", "CHECKMULTISIG DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0 0x02 0x0000 0 1", "CHECKMULTISIG DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0 0 0x02 0x0000", "CHECKMULTISIGVERIFY 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], -["0 0x02 0x0000 0", "CHECKMULTISIGVERIFY 1", "MINIMALDATA", "", "UNKNOWN_ERROR"], +["1 0x02 0x0000", "PICK DROP", "MINIMALDATA", "UNKNOWN_ERROR"], +["1 0x02 0x0000", "ROLL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000", "1ADD DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000", "1SUB DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000", "NEGATE DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000", "ABS DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000", "0NOTEQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], + +["0 0x02 0x0000", "ADD DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000 0", "ADD DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000", "SUB DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000 0", "SUB DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000", "BOOLAND DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000 0", "BOOLAND DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000", "BOOLOR DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000 0", "BOOLOR DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000", "NUMEQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000 1", "NUMEQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000", "NUMEQUALVERIFY 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000 0", "NUMEQUALVERIFY 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000", "NUMNOTEQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000 0", "NUMNOTEQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000", "LESSTHAN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000 0", "LESSTHAN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000", "GREATERTHAN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000 0", "GREATERTHAN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000", "LESSTHANOREQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000 0", "LESSTHANOREQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000", "GREATERTHANOREQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000 0", "GREATERTHANOREQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000", "MIN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000 0", "MIN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000", "MAX DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000 0", "MAX DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], + +["0x02 0x0000 0 0", "WITHIN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000 0", "WITHIN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0 0x02 0x0000", "WITHIN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], + +["0 0 0x02 0x0000", "CHECKMULTISIG DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000 0", "CHECKMULTISIG DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000 0 1", "CHECKMULTISIG DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0 0x02 0x0000", "CHECKMULTISIGVERIFY 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000 0", "CHECKMULTISIGVERIFY 1", "MINIMALDATA", "UNKNOWN_ERROR"], ["Order of CHECKMULTISIG evaluation tests, inverted by swapping the order of"], @@ -528,349 +528,349 @@ "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501", "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0 2 CHECKMULTISIG NOT", "STRICTENC", - "2-of-2 CHECKMULTISIG NOT with the first pubkey invalid, and both signatures validly encoded.", - "PUBKEYTYPE" + "PUBKEYTYPE", + "2-of-2 CHECKMULTISIG NOT with the first pubkey invalid, and both signatures validly encoded." ], [ "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 1", "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT", "STRICTENC", - "2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but first signature invalid.", - "SIG_DER" + "SIG_DER", + "2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but first signature invalid." ], [ "0 0x47 0x304402205451ce65ad844dbb978b8bdedf5082e33b43cae8279c30f2c74d9e9ee49a94f802203fe95a7ccf74da7a232ee523ef4a53cb4d14bdd16289680cdb97a63819b8f42f01 0x46 0x304402205451ce65ad844dbb978b8bdedf5082e33b43cae8279c30f2c74d9e9ee49a94f802203fe95a7ccf74da7a232ee523ef4a53cb4d14bdd16289680cdb97a63819b8f42f", "2 0x21 0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5 0x21 0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5 0x21 0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5 3 CHECKMULTISIG", "P2SH,STRICTENC", - "2-of-3 with one valid and one invalid signature due to parse error, nSigs > validSigs", - "SIG_DER" + "SIG_DER", + "2-of-3 with one valid and one invalid signature due to parse error, nSigs > validSigs" ], ["Increase DERSIG test coverage"], -["0x4a 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "DERSIG", "Overly long signature is incorrectly encoded for DERSIG", "SIG_DER"], -["0x25 0x30220220000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "DERSIG", "Missing S is incorrectly encoded for DERSIG", "SIG_DER"], -["0x27 0x3024021077777777777777777777777777777777020a7777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "S with invalid S length is incorrectly encoded for DERSIG", "SIG_DER"], -["0x27 0x302403107777777777777777777777777777777702107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "Non-integer R is incorrectly encoded for DERSIG", "SIG_DER"], -["0x27 0x302402107777777777777777777777777777777703107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "Non-integer S is incorrectly encoded for DERSIG", "SIG_DER"], -["0x17 0x3014020002107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "Zero-length R is incorrectly encoded for DERSIG", "SIG_DER"], -["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "DERSIG", "Zero-length S is incorrectly encoded for DERSIG", "SIG_DER"], -["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "Negative S is incorrectly encoded for DERSIG", "SIG_DER"], +["0x4a 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Overly long signature is incorrectly encoded for DERSIG"], +["0x25 0x30220220000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Missing S is incorrectly encoded for DERSIG"], +["0x27 0x3024021077777777777777777777777777777777020a7777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "S with invalid S length is incorrectly encoded for DERSIG"], +["0x27 0x302403107777777777777777777777777777777702107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Non-integer R is incorrectly encoded for DERSIG"], +["0x27 0x302402107777777777777777777777777777777703107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Non-integer S is incorrectly encoded for DERSIG"], +["0x17 0x3014020002107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Zero-length R is incorrectly encoded for DERSIG"], +["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Zero-length S is incorrectly encoded for DERSIG"], +["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Negative S is incorrectly encoded for DERSIG"], ["Automatically generated test cases"], [ "0x47 0x304402200a5c6163f07b8c3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "", - "P2PK, bad sig", - "EVAL_FALSE" + "EVAL_FALSE", + "P2PK, bad sig" ], [ "0x47 0x3044022034bb0494b50b8ef130e2185bb220265b9284ef5b4b8a8da4d8415df489c83b5102206259a26d9cc0a125ac26af6153b17c02956855ebe1467412f066e402f5f05d1201 0x21 0x03363d90d446b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640", "DUP HASH160 0x14 0xc0834c0c158f53be706d234c38fd52de7eece656 EQUALVERIFY CHECKSIG", "", - "P2PKH, bad pubkey", - "EQUALVERIFY" + "EQUALVERIFY", + "P2PKH, bad pubkey" ], [ "0x47 0x304402204710a85181663b32d25c70ec2bbd14adff5ddfff6cb50d09e155ef5f541fc86c0220056b0cc949be9386ecc5f6c2ac0493269031dbb185781db90171b54ac127790201", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", "", - "P2PK anyonecanpay marked with normal hashtype", - "EVAL_FALSE" + "EVAL_FALSE", + "P2PK anyonecanpay marked with normal hashtype" ], [ "0x47 0x3044022003fef42ed6c7be8917441218f525a60e2431be978e28b7aca4d7a532cc413ae8022067a1f82c74e8d69291b90d148778405c6257bbcfc2353cc38a3e1f22bf44254601 0x23 0x210279be667ef9dcbbac54a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac", "HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL", "P2SH", - "P2SH(P2PK), bad redeemscript", - "EVAL_FALSE" + "EVAL_FALSE", + "P2SH(P2PK), bad redeemscript" ], [ "0x47 0x304402204e2eb034be7b089534ac9e798cf6a2c79f38bcb34d1b179efd6f2de0841735db022071461beb056b5a7be1819da6a3e3ce3662831ecc298419ca101eb6887b5dd6a401 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac", "HASH160 0x14 0x2df519943d5acc0ef5222091f9dfe3543f489a82 EQUAL", "P2SH", - "P2SH(P2PKH), bad sig", - "EQUALVERIFY" + "EQUALVERIFY", + "P2SH(P2PKH), bad sig" ], [ "0 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402200a358f750934b3feb822f1966bfcd8bbec9eeaa3a8ca941e11ee5960e181fa01022050bf6b5a8e7750f70354ae041cb68a7bade67ec6c3ab19eb359638974410626e01 0", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", "", - "3-of-3, 2 sigs", - "EVAL_FALSE" + "EVAL_FALSE", + "3-of-3, 2 sigs" ], [ "0 0x47 0x304402205b7d2c2f177ae76cfbbf14d589c113b0b35db753d305d5562dd0b61cbf366cfb02202e56f93c4f08a27f986cd424ffc48a462c3202c4902104d4d0ff98ed28f4bf8001 0 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae", "HASH160 0x14 0xc9e4a896d149702d0d1695434feddd52e24ad78d EQUAL", "P2SH", - "P2SH(2-of-3), 1 sig", - "EVAL_FALSE" + "EVAL_FALSE", + "P2SH(2-of-3), 1 sig" ], [ "0x47 0x304402200060558477337b9022e70534f1fea71a318caf836812465a2509931c5e7c4987022078ec32bd50ac9e03a349ba953dfd9fe1c8d2dd8bdb1d38ddca844d3d5c78c11801", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "DERSIG", - "P2PK with too much R padding", - "SIG_DER" + "SIG_DER", + "P2PK with too much R padding" ], [ "0x48 0x304502202de8c03fc525285c9c535631019a5f2af7c6454fa9eb392a3756a4917c420edd02210046130bf2baf7cfc065067c8b9e33a066d9c15edcea9feb0ca2d233e3597925b401", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "DERSIG", - "P2PK with too much S padding", - "SIG_DER" + "SIG_DER", + "P2PK with too much S padding" ], [ "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "DERSIG", - "P2PK with too little R padding", - "SIG_DER" + "SIG_DER", + "P2PK with too little R padding" ], [ "0x47 0x30440220005ece1335e7f757a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT", "DERSIG", - "P2PK NOT with bad sig with too much R padding", - "SIG_DER" + "SIG_DER", + "P2PK NOT with bad sig with too much R padding" ], [ "0x47 0x30440220005ece1335e7f657a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT", "", - "P2PK NOT with too much R padding but no DERSIG", - "EVAL_FALSE" + "EVAL_FALSE", + "P2PK NOT with too much R padding but no DERSIG" ], [ "0x47 0x30440220005ece1335e7f657a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT", "DERSIG", - "P2PK NOT with too much R padding", - "SIG_DER" + "SIG_DER", + "P2PK NOT with too much R padding" ], [ "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "DERSIG", - "BIP66 example 1, with DERSIG", - "SIG_DER" + "SIG_DER", + "BIP66 example 1, with DERSIG" ], [ "0x47 0x304402208e43c0b91f7c1e5bc58e41c8185f8a6086e111b0090187968a86f2822462d3c902200a58f4076b1133b18ff1dc83ee51676e44c60cc608d9534e0df5ace0424fc0be01", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", "", - "BIP66 example 2, without DERSIG", - "EVAL_FALSE" + "EVAL_FALSE", + "BIP66 example 2, without DERSIG" ], [ "0x47 0x304402208e43c0b91f7c1e5bc58e41c8185f8a6086e111b0090187968a86f2822462d3c902200a58f4076b1133b18ff1dc83ee51676e44c60cc608d9534e0df5ace0424fc0be01", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", "DERSIG", - "BIP66 example 2, with DERSIG", - "SIG_DER" + "SIG_DER", + "BIP66 example 2, with DERSIG" ], [ "0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "", - "BIP66 example 3, without DERSIG", - "EVAL_FALSE" + "EVAL_FALSE", + "BIP66 example 3, without DERSIG" ], [ "0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "DERSIG", - "BIP66 example 3, with DERSIG", - "EVAL_FALSE" + "EVAL_FALSE", + "BIP66 example 3, with DERSIG" ], [ "1", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "", - "BIP66 example 5, without DERSIG", - "EVAL_FALSE" + "EVAL_FALSE", + "BIP66 example 5, without DERSIG" ], [ "1", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "DERSIG", - "BIP66 example 5, with DERSIG", - "SIG_DER" + "SIG_DER", + "BIP66 example 5, with DERSIG" ], [ "1", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", "DERSIG", - "BIP66 example 6, with DERSIG", - "SIG_DER" + "SIG_DER", + "BIP66 example 6, with DERSIG" ], [ "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0x47 0x3044022027c2714269ca5aeecc4d70edc88ba5ee0e3da4986e9216028f489ab4f1b8efce022022bd545b4951215267e4c5ceabd4c5350331b2e4a0b6494c56f361fa5a57a1a201", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG", "DERSIG", - "BIP66 example 7, with DERSIG", - "SIG_DER" + "SIG_DER", + "BIP66 example 7, with DERSIG" ], [ "0 0x47 0x30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201 0x47 0x3044022079ea80afd538d9ada421b5101febeb6bc874e01dde5bca108c1d0479aec339a4022004576db8f66130d1df686ccf00935703689d69cf539438da1edab208b0d63c4801", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT", "", - "BIP66 example 8, without DERSIG", - "EVAL_FALSE" + "EVAL_FALSE", + "BIP66 example 8, without DERSIG" ], [ "0 0x47 0x30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201 0x47 0x3044022079ea80afd538d9ada421b5101febeb6bc874e01dde5bca108c1d0479aec339a4022004576db8f66130d1df686ccf00935703689d69cf539438da1edab208b0d63c4801", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT", "DERSIG", - "BIP66 example 8, with DERSIG", - "SIG_DER" + "SIG_DER", + "BIP66 example 8, with DERSIG" ], [ "0 0 0x47 0x3044022081aa9d436f2154e8b6d600516db03d78de71df685b585a9807ead4210bd883490220534bb6bdf318a419ac0749660b60e78d17d515558ef369bf872eff405b676b2e01", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG", "", - "BIP66 example 9, without DERSIG", - "EVAL_FALSE" + "EVAL_FALSE", + "BIP66 example 9, without DERSIG" ], [ "0 0 0x47 0x3044022081aa9d436f2154e8b6d600516db03d78de71df685b585a9807ead4210bd883490220534bb6bdf318a419ac0749660b60e78d17d515558ef369bf872eff405b676b2e01", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG", "DERSIG", - "BIP66 example 9, with DERSIG", - "SIG_DER" + "SIG_DER", + "BIP66 example 9, with DERSIG" ], [ "0 0 0x47 0x30440220da6f441dc3b4b2c84cfa8db0cd5b34ed92c9e01686de5a800d40498b70c0dcac02207c2cf91b0c32b860c4cd4994be36cfb84caf8bb7c3a8e4d96a31b2022c5299c501", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT", "DERSIG", - "BIP66 example 10, with DERSIG", - "SIG_DER" + "SIG_DER", + "BIP66 example 10, with DERSIG" ], [ "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG", "", - "BIP66 example 11, without DERSIG", - "EVAL_FALSE" + "EVAL_FALSE", + "BIP66 example 11, without DERSIG" ], [ "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG", "DERSIG", - "BIP66 example 11, with DERSIG", - "EVAL_FALSE" + "EVAL_FALSE", + "BIP66 example 11, with DERSIG" ], [ "0x48 0x304402203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022054e1c258c2981cdfba5df1f46661fb6541c44f77ca0092f3600331abfffb12510101", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", "DERSIG", - "P2PK with multi-byte hashtype, with DERSIG", - "SIG_DER" + "SIG_DER", + "P2PK with multi-byte hashtype, with DERSIG" ], [ "0x48 0x304502203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022100ab1e3da73d67e32045a20e0b999e049978ea8d6ee5480d485fcf2ce0d03b2ef001", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", "LOW_S", - "P2PK with high S", - "SIG_HIGH_S" + "SIG_HIGH_S", + "P2PK with high S" ], [ "0x47 0x3044022057292e2d4dfe775becdd0a9e6547997c728cdf35390f6a017da56d654d374e4902206b643be2fc53763b4e284845bfea2c597d2dc7759941dce937636c9d341b71ed01", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "STRICTENC", - "P2PK with hybrid pubkey", - "PUBKEYTYPE" + "PUBKEYTYPE", + "P2PK with hybrid pubkey" ], [ "0x47 0x30440220035d554e3153c14950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", "", - "P2PK NOT with hybrid pubkey but no STRICTENC", - "EVAL_FALSE" + "EVAL_FALSE", + "P2PK NOT with hybrid pubkey but no STRICTENC" ], [ "0x47 0x30440220035d554e3153c14950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", "STRICTENC", - "P2PK NOT with hybrid pubkey", - "PUBKEYTYPE" + "PUBKEYTYPE", + "P2PK NOT with hybrid pubkey" ], [ "0x47 0x30440220035d554e3153c04950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", "STRICTENC", - "P2PK NOT with invalid hybrid pubkey", - "PUBKEYTYPE" + "PUBKEYTYPE", + "P2PK NOT with invalid hybrid pubkey" ], [ "0 0x47 0x3044022079c7824d6c868e0e1a273484e28c2654a27d043c8a27f49f52cb72efed0759090220452bbbf7089574fa082095a4fc1b3a16bafcf97a3a34d745fafc922cce66b27201", "1 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 2 CHECKMULTISIG", "STRICTENC", - "1-of-2 with the first 1 hybrid pubkey", - "PUBKEYTYPE" + "PUBKEYTYPE", + "1-of-2 with the first 1 hybrid pubkey" ], [ "0x47 0x304402206177d513ec2cda444c021a1f4f656fc4c72ba108ae063e157eb86dc3575784940220666fc66702815d0e5413bb9b1df22aed44f5f1efb8b99d41dd5dc9a5be6d205205", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", "STRICTENC", - "P2PK with undefined hashtype", - "SIG_HASHTYPE" + "SIG_HASHTYPE", + "P2PK with undefined hashtype" ], [ "0x47 0x304402207409b5b320296e5e2136a7b281a7f803028ca4ca44e2b83eebd46932677725de02202d4eea1c8d3c98e6f42614f54764e6e5e6542e213eb4d079737e9a8b6e9812ec05", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG NOT", "STRICTENC", - "P2PK NOT with invalid sig and undefined hashtype", - "SIG_HASHTYPE" + "SIG_HASHTYPE", + "P2PK NOT with invalid sig and undefined hashtype" ], [ "1 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402200a358f750934b3feb822f1966bfcd8bbec9eeaa3a8ca941e11ee5960e181fa01022050bf6b5a8e7750f70354ae041cb68a7bade67ec6c3ab19eb359638974410626e01 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", "NULLDUMMY", - "3-of-3 with nonzero dummy", - "SIG_NULLDUMMY" + "SIG_NULLDUMMY", + "3-of-3 with nonzero dummy" ], [ "1 0x47 0x304402201bb2edab700a5d020236df174fefed78087697143731f659bea59642c759c16d022061f42cdbae5bcd3e8790f20bf76687443436e94a634321c16a72aa54cbc7c2ea01 0x47 0x304402204bb4a64f2a6e5c7fb2f07fef85ee56fde5e6da234c6a984262307a20e99842d702206f8303aaba5e625d223897e2ffd3f88ef1bcffef55f38dc3768e5f2e94c923f901 0x47 0x3044022040c2809b71fffb155ec8b82fe7a27f666bd97f941207be4e14ade85a1249dd4d02204d56c85ec525dd18e29a0533d5ddf61b6b1bb32980c2f63edf951aebf7a27bfe01", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG NOT", "NULLDUMMY", - "3-of-3 NOT with invalid sig with nonzero dummy", - "SIG_NULLDUMMY" + "SIG_NULLDUMMY", + "3-of-3 NOT with invalid sig with nonzero dummy" ], [ "0 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901 DUP", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG", "SIGPUSHONLY", - "2-of-2 with two identical keys and sigs pushed using OP_DUP", - "SIG_PUSHONLY" + "SIG_PUSHONLY", + "2-of-2 with two identical keys and sigs pushed using OP_DUP" ], [ "0x47 0x3044022018a2a81a93add5cb5f5da76305718e4ea66045ec4888b28d84cb22fae7f4645b02201e6daa5ed5d2e4b2b2027cf7ffd43d8d9844dd49f74ef86899ec8e669dfd39aa01 NOP8 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac", "HASH160 0x14 0x215640c2f72f0d16b4eced26762035a42ffed39a EQUAL", "P2SH", - "P2SH(P2PK) with non-push scriptSig but no SIGPUSHONLY", - "SIG_PUSHONLY" + "SIG_PUSHONLY", + "P2SH(P2PK) with non-push scriptSig but no SIGPUSHONLY" ], [ "0x47 0x3044022018a2a81a93add5cb5f5da76305718e4ea66045ec4888b28d84cb22fae7f4645b02201e6daa5ed5d2e4b2b2027cf7ffd43d8d9844dd49f74ef86899ec8e669dfd39aa01 NOP8 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac", "HASH160 0x14 0x215640c2f72f0d16b4eced26762035a42ffed39a EQUAL", "SIGPUSHONLY", - "P2SH(P2PK) with non-push scriptSig but not P2SH", - "SIG_PUSHONLY" + "SIG_PUSHONLY", + "P2SH(P2PK) with non-push scriptSig but not P2SH" ], [ "11 0x47 0x304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "CLEANSTACK,P2SH", - "P2PK with unnecessary input", - "CLEANSTACK" + "CLEANSTACK", + "P2PK with unnecessary input" ], [ "11 0x47 0x304402202f7505132be14872581f35d74b759212d9da40482653f1ffa3116c3294a4a51702206adbf347a2240ca41c66522b1a22a41693610b76a8e7770645dc721d1635854f01 0x43 0x410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac", "HASH160 0x14 0x31edc23bdafda4639e669f89ad6b2318dd79d032 EQUAL", "CLEANSTACK,P2SH", - "P2SH with unnecessary input", - "CLEANSTACK" + "CLEANSTACK", + "P2SH with unnecessary input" ], ["The End"] diff --git a/src/test/data/script_valid.json b/src/test/data/script_valid.json index 29ccbd92ff930..4e86ee78ba604 100644 --- a/src/test/data/script_valid.json +++ b/src/test/data/script_valid.json @@ -1,674 +1,674 @@ [ -["Format is: [scriptSig, scriptPubKey, flags, ... comments]"], +["Format is: [scriptSig, scriptPubKey, flags, expected_scripterror, ... comments]"], ["It is evaluated as if there was a crediting coinbase transaction with two 0"], ["pushes as scriptSig, and one output of 0 satoshi and given scriptPubKey,"], ["followed by a spending transaction which spends this output as only input (and"], ["correct prevout hash), using the given scriptSig. All nLockTimes are 0, all"], ["nSequences are max."], -["", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "Test the test: we should have an empty stack after scriptSig evaluation"], -[" ", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "and multiple spaces should not change that."], -[" ", "DEPTH 0 EQUAL", "P2SH,STRICTENC"], -[" ", "DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["1 2", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC", "Similarly whitespace around and between symbols"], -["1 2", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC"], -[" 1 2", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC"], -["1 2 ", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC"], -[" 1 2 ", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC"], - -["1", "", "P2SH,STRICTENC"], -["0x02 0x01 0x00", "", "P2SH,STRICTENC", "all bytes are significant, not only the last one"], -["0x09 0x00000000 0x00000000 0x10", "", "P2SH,STRICTENC", "equals zero when cast to Int64"], - -["0x01 0x0b", "11 EQUAL", "P2SH,STRICTENC", "push 1 byte"], -["0x02 0x417a", "'Az' EQUAL", "P2SH,STRICTENC"], +["", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK", "Test the test: we should have an empty stack after scriptSig evaluation"], +[" ", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK", "and multiple spaces should not change that."], +[" ", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +[" ", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["1 2", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC", "OK", "Similarly whitespace around and between symbols"], +["1 2", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC", "OK"], +[" 1 2", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC", "OK"], +["1 2 ", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC", "OK"], +[" 1 2 ", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC", "OK"], + +["1", "", "P2SH,STRICTENC", "OK"], +["0x02 0x01 0x00", "", "P2SH,STRICTENC", "OK", "all bytes are significant, not only the last one"], +["0x09 0x00000000 0x00000000 0x10", "", "P2SH,STRICTENC", "OK", "equals zero when cast to Int64"], + +["0x01 0x0b", "11 EQUAL", "P2SH,STRICTENC", "OK", "push 1 byte"], +["0x02 0x417a", "'Az' EQUAL", "P2SH,STRICTENC", "OK"], ["0x4b 0x417a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a", - "'Azzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' EQUAL", "P2SH,STRICTENC", "push 75 bytes"], - -["0x4c 0x01 0x07","7 EQUAL", "P2SH,STRICTENC", "0x4c is OP_PUSHDATA1"], -["0x4d 0x0100 0x08","8 EQUAL", "P2SH,STRICTENC", "0x4d is OP_PUSHDATA2"], -["0x4e 0x01000000 0x09","9 EQUAL", "P2SH,STRICTENC", "0x4e is OP_PUSHDATA4"], - -["0x4c 0x00","0 EQUAL", "P2SH,STRICTENC"], -["0x4d 0x0000","0 EQUAL", "P2SH,STRICTENC"], -["0x4e 0x00000000","0 EQUAL", "P2SH,STRICTENC"], -["0x4f 1000 ADD","999 EQUAL", "P2SH,STRICTENC"], -["0", "IF 0x50 ENDIF 1", "P2SH,STRICTENC", "0x50 is reserved (ok if not executed)"], -["0x51", "0x5f ADD 0x60 EQUAL", "P2SH,STRICTENC", "0x51 through 0x60 push 1 through 16 onto stack"], -["1","NOP", "P2SH,STRICTENC"], -["0", "IF VER ELSE 1 ENDIF", "P2SH,STRICTENC", "VER non-functional (ok if not executed)"], -["0", "IF RESERVED RESERVED1 RESERVED2 ELSE 1 ENDIF", "P2SH,STRICTENC", "RESERVED ok in un-executed IF"], - -["1", "DUP IF ENDIF", "P2SH,STRICTENC"], -["1", "IF 1 ENDIF", "P2SH,STRICTENC"], -["1", "DUP IF ELSE ENDIF", "P2SH,STRICTENC"], -["1", "IF 1 ELSE ENDIF", "P2SH,STRICTENC"], -["0", "IF ELSE 1 ENDIF", "P2SH,STRICTENC"], - -["1 1", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"], -["1 0", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"], -["1 1", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"], -["0 0", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"], - -["1 0", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"], -["1 1", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"], -["1 0", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"], -["0 1", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"], - -["0", "IF 0 ELSE 1 ELSE 0 ENDIF", "P2SH,STRICTENC", "Multiple ELSE's are valid and executed inverts on each ELSE encountered"], -["1", "IF 1 ELSE 0 ELSE ENDIF", "P2SH,STRICTENC"], -["1", "IF ELSE 0 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["1", "IF 1 ELSE 0 ELSE 1 ENDIF ADD 2 EQUAL", "P2SH,STRICTENC"], -["'' 1", "IF SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ENDIF 0x14 0x68ca4fec736264c13b859bac43d5173df6871682 EQUAL", "P2SH,STRICTENC"], - -["1", "NOTIF 0 ELSE 1 ELSE 0 ENDIF", "P2SH,STRICTENC", "Multiple ELSE's are valid and execution inverts on each ELSE encountered"], -["0", "NOTIF 1 ELSE 0 ELSE ENDIF", "P2SH,STRICTENC"], -["0", "NOTIF ELSE 0 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "NOTIF 1 ELSE 0 ELSE 1 ENDIF ADD 2 EQUAL", "P2SH,STRICTENC"], -["'' 0", "NOTIF SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ENDIF 0x14 0x68ca4fec736264c13b859bac43d5173df6871682 EQUAL", "P2SH,STRICTENC"], - -["0", "IF 1 IF RETURN ELSE RETURN ELSE RETURN ENDIF ELSE 1 IF 1 ELSE RETURN ELSE 1 ENDIF ELSE RETURN ENDIF ADD 2 EQUAL", "P2SH,STRICTENC", "Nested ELSE ELSE"], -["1", "NOTIF 0 NOTIF RETURN ELSE RETURN ELSE RETURN ENDIF ELSE 0 NOTIF 1 ELSE RETURN ELSE 1 ENDIF ELSE RETURN ENDIF ADD 2 EQUAL", "P2SH,STRICTENC"], - -["0", "IF RETURN ENDIF 1", "P2SH,STRICTENC", "RETURN only works if executed"], - -["1 1", "VERIFY", "P2SH,STRICTENC"], -["1 0x05 0x01 0x00 0x00 0x00 0x00", "VERIFY", "P2SH,STRICTENC", "values >4 bytes can be cast to boolean"], -["1 0x01 0x80", "IF 0 ENDIF", "P2SH,STRICTENC", "negative 0 is false"], - -["10 0 11 TOALTSTACK DROP FROMALTSTACK", "ADD 21 EQUAL", "P2SH,STRICTENC"], -["'gavin_was_here' TOALTSTACK 11 FROMALTSTACK", "'gavin_was_here' EQUALVERIFY 11 EQUAL", "P2SH,STRICTENC"], - -["0 IFDUP", "DEPTH 1 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC"], -["1 IFDUP", "DEPTH 2 EQUALVERIFY 1 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC"], -["0x05 0x0100000000 IFDUP", "DEPTH 2 EQUALVERIFY 0x05 0x0100000000 EQUAL", "P2SH,STRICTENC", "IFDUP dups non ints"], -["0 DROP", "DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["0", "DUP 1 ADD 1 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC"], -["0 1", "NIP", "P2SH,STRICTENC"], -["1 0", "OVER DEPTH 3 EQUALVERIFY", "P2SH,STRICTENC"], -["22 21 20", "0 PICK 20 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC"], -["22 21 20", "1 PICK 21 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC"], -["22 21 20", "2 PICK 22 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC"], -["22 21 20", "0 ROLL 20 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC"], -["22 21 20", "1 ROLL 21 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC"], -["22 21 20", "2 ROLL 22 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC"], -["22 21 20", "ROT 22 EQUAL", "P2SH,STRICTENC"], -["22 21 20", "ROT DROP 20 EQUAL", "P2SH,STRICTENC"], -["22 21 20", "ROT DROP DROP 21 EQUAL", "P2SH,STRICTENC"], -["22 21 20", "ROT ROT 21 EQUAL", "P2SH,STRICTENC"], -["22 21 20", "ROT ROT ROT 20 EQUAL", "P2SH,STRICTENC"], -["25 24 23 22 21 20", "2ROT 24 EQUAL", "P2SH,STRICTENC"], -["25 24 23 22 21 20", "2ROT DROP 25 EQUAL", "P2SH,STRICTENC"], -["25 24 23 22 21 20", "2ROT 2DROP 20 EQUAL", "P2SH,STRICTENC"], -["25 24 23 22 21 20", "2ROT 2DROP DROP 21 EQUAL", "P2SH,STRICTENC"], -["25 24 23 22 21 20", "2ROT 2DROP 2DROP 22 EQUAL", "P2SH,STRICTENC"], -["25 24 23 22 21 20", "2ROT 2DROP 2DROP DROP 23 EQUAL", "P2SH,STRICTENC"], -["25 24 23 22 21 20", "2ROT 2ROT 22 EQUAL", "P2SH,STRICTENC"], -["25 24 23 22 21 20", "2ROT 2ROT 2ROT 20 EQUAL", "P2SH,STRICTENC"], -["1 0", "SWAP 1 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC"], -["0 1", "TUCK DEPTH 3 EQUALVERIFY SWAP 2DROP", "P2SH,STRICTENC"], -["13 14", "2DUP ROT EQUALVERIFY EQUAL", "P2SH,STRICTENC"], -["-1 0 1 2", "3DUP DEPTH 7 EQUALVERIFY ADD ADD 3 EQUALVERIFY 2DROP 0 EQUALVERIFY", "P2SH,STRICTENC"], -["1 2 3 5", "2OVER ADD ADD 8 EQUALVERIFY ADD ADD 6 EQUAL", "P2SH,STRICTENC"], -["1 3 5 7", "2SWAP ADD 4 EQUALVERIFY ADD 12 EQUAL", "P2SH,STRICTENC"], -["0", "SIZE 0 EQUAL", "P2SH,STRICTENC"], -["1", "SIZE 1 EQUAL", "P2SH,STRICTENC"], -["127", "SIZE 1 EQUAL", "P2SH,STRICTENC"], -["128", "SIZE 2 EQUAL", "P2SH,STRICTENC"], -["32767", "SIZE 2 EQUAL", "P2SH,STRICTENC"], -["32768", "SIZE 3 EQUAL", "P2SH,STRICTENC"], -["8388607", "SIZE 3 EQUAL", "P2SH,STRICTENC"], -["8388608", "SIZE 4 EQUAL", "P2SH,STRICTENC"], -["2147483647", "SIZE 4 EQUAL", "P2SH,STRICTENC"], -["2147483648", "SIZE 5 EQUAL", "P2SH,STRICTENC"], -["549755813887", "SIZE 5 EQUAL", "P2SH,STRICTENC"], -["549755813888", "SIZE 6 EQUAL", "P2SH,STRICTENC"], -["9223372036854775807", "SIZE 8 EQUAL", "P2SH,STRICTENC"], -["-1", "SIZE 1 EQUAL", "P2SH,STRICTENC"], -["-127", "SIZE 1 EQUAL", "P2SH,STRICTENC"], -["-128", "SIZE 2 EQUAL", "P2SH,STRICTENC"], -["-32767", "SIZE 2 EQUAL", "P2SH,STRICTENC"], -["-32768", "SIZE 3 EQUAL", "P2SH,STRICTENC"], -["-8388607", "SIZE 3 EQUAL", "P2SH,STRICTENC"], -["-8388608", "SIZE 4 EQUAL", "P2SH,STRICTENC"], -["-2147483647", "SIZE 4 EQUAL", "P2SH,STRICTENC"], -["-2147483648", "SIZE 5 EQUAL", "P2SH,STRICTENC"], -["-549755813887", "SIZE 5 EQUAL", "P2SH,STRICTENC"], -["-549755813888", "SIZE 6 EQUAL", "P2SH,STRICTENC"], -["-9223372036854775807", "SIZE 8 EQUAL", "P2SH,STRICTENC"], -["'abcdefghijklmnopqrstuvwxyz'", "SIZE 26 EQUAL", "P2SH,STRICTENC"], - -["42", "SIZE 1 EQUALVERIFY 42 EQUAL", "P2SH,STRICTENC", "SIZE does not consume argument"], - -["2 -2 ADD", "0 EQUAL", "P2SH,STRICTENC"], -["2147483647 -2147483647 ADD", "0 EQUAL", "P2SH,STRICTENC"], -["-1 -1 ADD", "-2 EQUAL", "P2SH,STRICTENC"], - -["0 0","EQUAL", "P2SH,STRICTENC"], -["1 1 ADD", "2 EQUAL", "P2SH,STRICTENC"], -["1 1ADD", "2 EQUAL", "P2SH,STRICTENC"], -["111 1SUB", "110 EQUAL", "P2SH,STRICTENC"], -["111 1 ADD 12 SUB", "100 EQUAL", "P2SH,STRICTENC"], -["0 ABS", "0 EQUAL", "P2SH,STRICTENC"], -["16 ABS", "16 EQUAL", "P2SH,STRICTENC"], -["-16 ABS", "-16 NEGATE EQUAL", "P2SH,STRICTENC"], -["0 NOT", "NOP", "P2SH,STRICTENC"], -["1 NOT", "0 EQUAL", "P2SH,STRICTENC"], -["11 NOT", "0 EQUAL", "P2SH,STRICTENC"], -["0 0NOTEQUAL", "0 EQUAL", "P2SH,STRICTENC"], -["1 0NOTEQUAL", "1 EQUAL", "P2SH,STRICTENC"], -["111 0NOTEQUAL", "1 EQUAL", "P2SH,STRICTENC"], -["-111 0NOTEQUAL", "1 EQUAL", "P2SH,STRICTENC"], -["1 1 BOOLAND", "NOP", "P2SH,STRICTENC"], -["1 0 BOOLAND", "NOT", "P2SH,STRICTENC"], -["0 1 BOOLAND", "NOT", "P2SH,STRICTENC"], -["0 0 BOOLAND", "NOT", "P2SH,STRICTENC"], -["16 17 BOOLAND", "NOP", "P2SH,STRICTENC"], -["1 1 BOOLOR", "NOP", "P2SH,STRICTENC"], -["1 0 BOOLOR", "NOP", "P2SH,STRICTENC"], -["0 1 BOOLOR", "NOP", "P2SH,STRICTENC"], -["0 0 BOOLOR", "NOT", "P2SH,STRICTENC"], -["16 17 BOOLOR", "NOP", "P2SH,STRICTENC"], -["11 10 1 ADD", "NUMEQUAL", "P2SH,STRICTENC"], -["11 10 1 ADD", "NUMEQUALVERIFY 1", "P2SH,STRICTENC"], -["11 10 1 ADD", "NUMNOTEQUAL NOT", "P2SH,STRICTENC"], -["111 10 1 ADD", "NUMNOTEQUAL", "P2SH,STRICTENC"], -["11 10", "LESSTHAN NOT", "P2SH,STRICTENC"], -["4 4", "LESSTHAN NOT", "P2SH,STRICTENC"], -["10 11", "LESSTHAN", "P2SH,STRICTENC"], -["-11 11", "LESSTHAN", "P2SH,STRICTENC"], -["-11 -10", "LESSTHAN", "P2SH,STRICTENC"], -["11 10", "GREATERTHAN", "P2SH,STRICTENC"], -["4 4", "GREATERTHAN NOT", "P2SH,STRICTENC"], -["10 11", "GREATERTHAN NOT", "P2SH,STRICTENC"], -["-11 11", "GREATERTHAN NOT", "P2SH,STRICTENC"], -["-11 -10", "GREATERTHAN NOT", "P2SH,STRICTENC"], -["11 10", "LESSTHANOREQUAL NOT", "P2SH,STRICTENC"], -["4 4", "LESSTHANOREQUAL", "P2SH,STRICTENC"], -["10 11", "LESSTHANOREQUAL", "P2SH,STRICTENC"], -["-11 11", "LESSTHANOREQUAL", "P2SH,STRICTENC"], -["-11 -10", "LESSTHANOREQUAL", "P2SH,STRICTENC"], -["11 10", "GREATERTHANOREQUAL", "P2SH,STRICTENC"], -["4 4", "GREATERTHANOREQUAL", "P2SH,STRICTENC"], -["10 11", "GREATERTHANOREQUAL NOT", "P2SH,STRICTENC"], -["-11 11", "GREATERTHANOREQUAL NOT", "P2SH,STRICTENC"], -["-11 -10", "GREATERTHANOREQUAL NOT", "P2SH,STRICTENC"], -["1 0 MIN", "0 NUMEQUAL", "P2SH,STRICTENC"], -["0 1 MIN", "0 NUMEQUAL", "P2SH,STRICTENC"], -["-1 0 MIN", "-1 NUMEQUAL", "P2SH,STRICTENC"], -["0 -2147483647 MIN", "-2147483647 NUMEQUAL", "P2SH,STRICTENC"], -["2147483647 0 MAX", "2147483647 NUMEQUAL", "P2SH,STRICTENC"], -["0 100 MAX", "100 NUMEQUAL", "P2SH,STRICTENC"], -["-100 0 MAX", "0 NUMEQUAL", "P2SH,STRICTENC"], -["0 -2147483647 MAX", "0 NUMEQUAL", "P2SH,STRICTENC"], -["0 0 1", "WITHIN", "P2SH,STRICTENC"], -["1 0 1", "WITHIN NOT", "P2SH,STRICTENC"], -["0 -2147483647 2147483647", "WITHIN", "P2SH,STRICTENC"], -["-1 -100 100", "WITHIN", "P2SH,STRICTENC"], -["11 -100 100", "WITHIN", "P2SH,STRICTENC"], -["-2147483647 -100 100", "WITHIN NOT", "P2SH,STRICTENC"], -["2147483647 -100 100", "WITHIN NOT", "P2SH,STRICTENC"], - -["2147483647 2147483647 SUB", "0 EQUAL", "P2SH,STRICTENC"], -["2147483647 DUP ADD", "4294967294 EQUAL", "P2SH,STRICTENC", ">32 bit EQUAL is valid"], -["2147483647 NEGATE DUP ADD", "-4294967294 EQUAL", "P2SH,STRICTENC"], - -["''", "RIPEMD160 0x14 0x9c1185a5c5e9fc54612808977ee8f548b2258d31 EQUAL", "P2SH,STRICTENC"], -["'a'", "RIPEMD160 0x14 0x0bdc9d2d256b3ee9daae347be6f4dc835a467ffe EQUAL", "P2SH,STRICTENC"], -["'abcdefghijklmnopqrstuvwxyz'", "RIPEMD160 0x14 0xf71c27109c692c1b56bbdceb5b9d2865b3708dbc EQUAL", "P2SH,STRICTENC"], -["''", "SHA1 0x14 0xda39a3ee5e6b4b0d3255bfef95601890afd80709 EQUAL", "P2SH,STRICTENC"], -["'a'", "SHA1 0x14 0x86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 EQUAL", "P2SH,STRICTENC"], -["'abcdefghijklmnopqrstuvwxyz'", "SHA1 0x14 0x32d10c7b8cf96570ca04ce37f2a19d84240d3a89 EQUAL", "P2SH,STRICTENC"], -["''", "SHA256 0x20 0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 EQUAL", "P2SH,STRICTENC"], -["'a'", "SHA256 0x20 0xca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb EQUAL", "P2SH,STRICTENC"], -["'abcdefghijklmnopqrstuvwxyz'", "SHA256 0x20 0x71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73 EQUAL", "P2SH,STRICTENC"], -["''", "DUP HASH160 SWAP SHA256 RIPEMD160 EQUAL", "P2SH,STRICTENC"], -["''", "DUP HASH256 SWAP SHA256 SHA256 EQUAL", "P2SH,STRICTENC"], -["''", "NOP HASH160 0x14 0xb472a266d0bd89c13706a4132ccfb16f7c3b9fcb EQUAL", "P2SH,STRICTENC"], -["'a'", "HASH160 NOP 0x14 0x994355199e516ff76c4fa4aab39337b9d84cf12b EQUAL", "P2SH,STRICTENC"], -["'abcdefghijklmnopqrstuvwxyz'", "HASH160 0x4c 0x14 0xc286a1af0947f58d1ad787385b1c2c4a976f9e71 EQUAL", "P2SH,STRICTENC"], -["''", "HASH256 0x20 0x5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456 EQUAL", "P2SH,STRICTENC"], -["'a'", "HASH256 0x20 0xbf5d3affb73efd2ec6c36ad3112dd933efed63c4e1cbffcfa88e2759c144f2d8 EQUAL", "P2SH,STRICTENC"], -["'abcdefghijklmnopqrstuvwxyz'", "HASH256 0x4c 0x20 0xca139bc10c2f660da42666f72e89a225936fc60f193c161124a672050c434671 EQUAL", "P2SH,STRICTENC"], - - -["1","NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 1 EQUAL", "P2SH,STRICTENC"], -["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_10' EQUAL", "P2SH,STRICTENC"], - -["1", "NOP", "P2SH,STRICTENC,DISCOURAGE_UPGRADABLE_NOPS", "Discourage NOPx flag allows OP_NOP"], - -["0", "IF NOP10 ENDIF 1", "P2SH,STRICTENC,DISCOURAGE_UPGRADABLE_NOPS", + "'Azzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' EQUAL", "P2SH,STRICTENC", "OK", "push 75 bytes"], + +["0x4c 0x01 0x07","7 EQUAL", "P2SH,STRICTENC", "OK", "0x4c is OP_PUSHDATA1"], +["0x4d 0x0100 0x08","8 EQUAL", "P2SH,STRICTENC", "OK", "0x4d is OP_PUSHDATA2"], +["0x4e 0x01000000 0x09","9 EQUAL", "P2SH,STRICTENC", "OK", "0x4e is OP_PUSHDATA4"], + +["0x4c 0x00","0 EQUAL", "P2SH,STRICTENC", "OK"], +["0x4d 0x0000","0 EQUAL", "P2SH,STRICTENC", "OK"], +["0x4e 0x00000000","0 EQUAL", "P2SH,STRICTENC", "OK"], +["0x4f 1000 ADD","999 EQUAL", "P2SH,STRICTENC", "OK"], +["0", "IF 0x50 ENDIF 1", "P2SH,STRICTENC", "OK", "0x50 is reserved (ok if not executed)"], +["0x51", "0x5f ADD 0x60 EQUAL", "P2SH,STRICTENC", "OK", "0x51 through 0x60 push 1 through 16 onto stack"], +["1","NOP", "P2SH,STRICTENC", "OK"], +["0", "IF VER ELSE 1 ENDIF", "P2SH,STRICTENC", "OK", "VER non-functional (ok if not executed)"], +["0", "IF RESERVED RESERVED1 RESERVED2 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK", "RESERVED ok in un-executed IF"], + +["1", "DUP IF ENDIF", "P2SH,STRICTENC", "OK"], +["1", "IF 1 ENDIF", "P2SH,STRICTENC", "OK"], +["1", "DUP IF ELSE ENDIF", "P2SH,STRICTENC", "OK"], +["1", "IF 1 ELSE ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], + +["1 1", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "OK"], +["1 0", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "OK"], +["1 1", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "OK"], +["0 0", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "OK"], + +["1 0", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "OK"], +["1 1", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "OK"], +["1 0", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "OK"], +["0 1", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "OK"], + +["0", "IF 0 ELSE 1 ELSE 0 ENDIF", "P2SH,STRICTENC", "OK", "Multiple ELSE's are valid and executed inverts on each ELSE encountered"], +["1", "IF 1 ELSE 0 ELSE ENDIF", "P2SH,STRICTENC", "OK"], +["1", "IF ELSE 0 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["1", "IF 1 ELSE 0 ELSE 1 ENDIF ADD 2 EQUAL", "P2SH,STRICTENC", "OK"], +["'' 1", "IF SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ENDIF 0x14 0x68ca4fec736264c13b859bac43d5173df6871682 EQUAL", "P2SH,STRICTENC", "OK"], + +["1", "NOTIF 0 ELSE 1 ELSE 0 ENDIF", "P2SH,STRICTENC", "OK", "Multiple ELSE's are valid and execution inverts on each ELSE encountered"], +["0", "NOTIF 1 ELSE 0 ELSE ENDIF", "P2SH,STRICTENC", "OK"], +["0", "NOTIF ELSE 0 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "NOTIF 1 ELSE 0 ELSE 1 ENDIF ADD 2 EQUAL", "P2SH,STRICTENC", "OK"], +["'' 0", "NOTIF SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ENDIF 0x14 0x68ca4fec736264c13b859bac43d5173df6871682 EQUAL", "P2SH,STRICTENC", "OK"], + +["0", "IF 1 IF RETURN ELSE RETURN ELSE RETURN ENDIF ELSE 1 IF 1 ELSE RETURN ELSE 1 ENDIF ELSE RETURN ENDIF ADD 2 EQUAL", "P2SH,STRICTENC", "OK", "Nested ELSE ELSE"], +["1", "NOTIF 0 NOTIF RETURN ELSE RETURN ELSE RETURN ENDIF ELSE 0 NOTIF 1 ELSE RETURN ELSE 1 ENDIF ELSE RETURN ENDIF ADD 2 EQUAL", "P2SH,STRICTENC", "OK"], + +["0", "IF RETURN ENDIF 1", "P2SH,STRICTENC", "OK", "RETURN only works if executed"], + +["1 1", "VERIFY", "P2SH,STRICTENC", "OK"], +["1 0x05 0x01 0x00 0x00 0x00 0x00", "VERIFY", "P2SH,STRICTENC", "OK", "values >4 bytes can be cast to boolean"], +["1 0x01 0x80", "IF 0 ENDIF", "P2SH,STRICTENC", "OK", "negative 0 is false"], + +["10 0 11 TOALTSTACK DROP FROMALTSTACK", "ADD 21 EQUAL", "P2SH,STRICTENC", "OK"], +["'gavin_was_here' TOALTSTACK 11 FROMALTSTACK", "'gavin_was_here' EQUALVERIFY 11 EQUAL", "P2SH,STRICTENC", "OK"], + +["0 IFDUP", "DEPTH 1 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC", "OK"], +["1 IFDUP", "DEPTH 2 EQUALVERIFY 1 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC", "OK"], +["0x05 0x0100000000 IFDUP", "DEPTH 2 EQUALVERIFY 0x05 0x0100000000 EQUAL", "P2SH,STRICTENC", "OK", "IFDUP dups non ints"], +["0 DROP", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["0", "DUP 1 ADD 1 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC", "OK"], +["0 1", "NIP", "P2SH,STRICTENC", "OK"], +["1 0", "OVER DEPTH 3 EQUALVERIFY", "P2SH,STRICTENC", "OK"], +["22 21 20", "0 PICK 20 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "OK"], +["22 21 20", "1 PICK 21 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "OK"], +["22 21 20", "2 PICK 22 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "OK"], +["22 21 20", "0 ROLL 20 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "OK"], +["22 21 20", "1 ROLL 21 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "OK"], +["22 21 20", "2 ROLL 22 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "OK"], +["22 21 20", "ROT 22 EQUAL", "P2SH,STRICTENC", "OK"], +["22 21 20", "ROT DROP 20 EQUAL", "P2SH,STRICTENC", "OK"], +["22 21 20", "ROT DROP DROP 21 EQUAL", "P2SH,STRICTENC", "OK"], +["22 21 20", "ROT ROT 21 EQUAL", "P2SH,STRICTENC", "OK"], +["22 21 20", "ROT ROT ROT 20 EQUAL", "P2SH,STRICTENC", "OK"], +["25 24 23 22 21 20", "2ROT 24 EQUAL", "P2SH,STRICTENC", "OK"], +["25 24 23 22 21 20", "2ROT DROP 25 EQUAL", "P2SH,STRICTENC", "OK"], +["25 24 23 22 21 20", "2ROT 2DROP 20 EQUAL", "P2SH,STRICTENC", "OK"], +["25 24 23 22 21 20", "2ROT 2DROP DROP 21 EQUAL", "P2SH,STRICTENC", "OK"], +["25 24 23 22 21 20", "2ROT 2DROP 2DROP 22 EQUAL", "P2SH,STRICTENC", "OK"], +["25 24 23 22 21 20", "2ROT 2DROP 2DROP DROP 23 EQUAL", "P2SH,STRICTENC", "OK"], +["25 24 23 22 21 20", "2ROT 2ROT 22 EQUAL", "P2SH,STRICTENC", "OK"], +["25 24 23 22 21 20", "2ROT 2ROT 2ROT 20 EQUAL", "P2SH,STRICTENC", "OK"], +["1 0", "SWAP 1 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC", "OK"], +["0 1", "TUCK DEPTH 3 EQUALVERIFY SWAP 2DROP", "P2SH,STRICTENC", "OK"], +["13 14", "2DUP ROT EQUALVERIFY EQUAL", "P2SH,STRICTENC", "OK"], +["-1 0 1 2", "3DUP DEPTH 7 EQUALVERIFY ADD ADD 3 EQUALVERIFY 2DROP 0 EQUALVERIFY", "P2SH,STRICTENC", "OK"], +["1 2 3 5", "2OVER ADD ADD 8 EQUALVERIFY ADD ADD 6 EQUAL", "P2SH,STRICTENC", "OK"], +["1 3 5 7", "2SWAP ADD 4 EQUALVERIFY ADD 12 EQUAL", "P2SH,STRICTENC", "OK"], +["0", "SIZE 0 EQUAL", "P2SH,STRICTENC", "OK"], +["1", "SIZE 1 EQUAL", "P2SH,STRICTENC", "OK"], +["127", "SIZE 1 EQUAL", "P2SH,STRICTENC", "OK"], +["128", "SIZE 2 EQUAL", "P2SH,STRICTENC", "OK"], +["32767", "SIZE 2 EQUAL", "P2SH,STRICTENC", "OK"], +["32768", "SIZE 3 EQUAL", "P2SH,STRICTENC", "OK"], +["8388607", "SIZE 3 EQUAL", "P2SH,STRICTENC", "OK"], +["8388608", "SIZE 4 EQUAL", "P2SH,STRICTENC", "OK"], +["2147483647", "SIZE 4 EQUAL", "P2SH,STRICTENC", "OK"], +["2147483648", "SIZE 5 EQUAL", "P2SH,STRICTENC", "OK"], +["549755813887", "SIZE 5 EQUAL", "P2SH,STRICTENC", "OK"], +["549755813888", "SIZE 6 EQUAL", "P2SH,STRICTENC", "OK"], +["9223372036854775807", "SIZE 8 EQUAL", "P2SH,STRICTENC", "OK"], +["-1", "SIZE 1 EQUAL", "P2SH,STRICTENC", "OK"], +["-127", "SIZE 1 EQUAL", "P2SH,STRICTENC", "OK"], +["-128", "SIZE 2 EQUAL", "P2SH,STRICTENC", "OK"], +["-32767", "SIZE 2 EQUAL", "P2SH,STRICTENC", "OK"], +["-32768", "SIZE 3 EQUAL", "P2SH,STRICTENC", "OK"], +["-8388607", "SIZE 3 EQUAL", "P2SH,STRICTENC", "OK"], +["-8388608", "SIZE 4 EQUAL", "P2SH,STRICTENC", "OK"], +["-2147483647", "SIZE 4 EQUAL", "P2SH,STRICTENC", "OK"], +["-2147483648", "SIZE 5 EQUAL", "P2SH,STRICTENC", "OK"], +["-549755813887", "SIZE 5 EQUAL", "P2SH,STRICTENC", "OK"], +["-549755813888", "SIZE 6 EQUAL", "P2SH,STRICTENC", "OK"], +["-9223372036854775807", "SIZE 8 EQUAL", "P2SH,STRICTENC", "OK"], +["'abcdefghijklmnopqrstuvwxyz'", "SIZE 26 EQUAL", "P2SH,STRICTENC", "OK"], + +["42", "SIZE 1 EQUALVERIFY 42 EQUAL", "P2SH,STRICTENC", "OK", "SIZE does not consume argument"], + +["2 -2 ADD", "0 EQUAL", "P2SH,STRICTENC", "OK"], +["2147483647 -2147483647 ADD", "0 EQUAL", "P2SH,STRICTENC", "OK"], +["-1 -1 ADD", "-2 EQUAL", "P2SH,STRICTENC", "OK"], + +["0 0","EQUAL", "P2SH,STRICTENC", "OK"], +["1 1 ADD", "2 EQUAL", "P2SH,STRICTENC", "OK"], +["1 1ADD", "2 EQUAL", "P2SH,STRICTENC", "OK"], +["111 1SUB", "110 EQUAL", "P2SH,STRICTENC", "OK"], +["111 1 ADD 12 SUB", "100 EQUAL", "P2SH,STRICTENC", "OK"], +["0 ABS", "0 EQUAL", "P2SH,STRICTENC", "OK"], +["16 ABS", "16 EQUAL", "P2SH,STRICTENC", "OK"], +["-16 ABS", "-16 NEGATE EQUAL", "P2SH,STRICTENC", "OK"], +["0 NOT", "NOP", "P2SH,STRICTENC", "OK"], +["1 NOT", "0 EQUAL", "P2SH,STRICTENC", "OK"], +["11 NOT", "0 EQUAL", "P2SH,STRICTENC", "OK"], +["0 0NOTEQUAL", "0 EQUAL", "P2SH,STRICTENC", "OK"], +["1 0NOTEQUAL", "1 EQUAL", "P2SH,STRICTENC", "OK"], +["111 0NOTEQUAL", "1 EQUAL", "P2SH,STRICTENC", "OK"], +["-111 0NOTEQUAL", "1 EQUAL", "P2SH,STRICTENC", "OK"], +["1 1 BOOLAND", "NOP", "P2SH,STRICTENC", "OK"], +["1 0 BOOLAND", "NOT", "P2SH,STRICTENC", "OK"], +["0 1 BOOLAND", "NOT", "P2SH,STRICTENC", "OK"], +["0 0 BOOLAND", "NOT", "P2SH,STRICTENC", "OK"], +["16 17 BOOLAND", "NOP", "P2SH,STRICTENC", "OK"], +["1 1 BOOLOR", "NOP", "P2SH,STRICTENC", "OK"], +["1 0 BOOLOR", "NOP", "P2SH,STRICTENC", "OK"], +["0 1 BOOLOR", "NOP", "P2SH,STRICTENC", "OK"], +["0 0 BOOLOR", "NOT", "P2SH,STRICTENC", "OK"], +["16 17 BOOLOR", "NOP", "P2SH,STRICTENC", "OK"], +["11 10 1 ADD", "NUMEQUAL", "P2SH,STRICTENC", "OK"], +["11 10 1 ADD", "NUMEQUALVERIFY 1", "P2SH,STRICTENC", "OK"], +["11 10 1 ADD", "NUMNOTEQUAL NOT", "P2SH,STRICTENC", "OK"], +["111 10 1 ADD", "NUMNOTEQUAL", "P2SH,STRICTENC", "OK"], +["11 10", "LESSTHAN NOT", "P2SH,STRICTENC", "OK"], +["4 4", "LESSTHAN NOT", "P2SH,STRICTENC", "OK"], +["10 11", "LESSTHAN", "P2SH,STRICTENC", "OK"], +["-11 11", "LESSTHAN", "P2SH,STRICTENC", "OK"], +["-11 -10", "LESSTHAN", "P2SH,STRICTENC", "OK"], +["11 10", "GREATERTHAN", "P2SH,STRICTENC", "OK"], +["4 4", "GREATERTHAN NOT", "P2SH,STRICTENC", "OK"], +["10 11", "GREATERTHAN NOT", "P2SH,STRICTENC", "OK"], +["-11 11", "GREATERTHAN NOT", "P2SH,STRICTENC", "OK"], +["-11 -10", "GREATERTHAN NOT", "P2SH,STRICTENC", "OK"], +["11 10", "LESSTHANOREQUAL NOT", "P2SH,STRICTENC", "OK"], +["4 4", "LESSTHANOREQUAL", "P2SH,STRICTENC", "OK"], +["10 11", "LESSTHANOREQUAL", "P2SH,STRICTENC", "OK"], +["-11 11", "LESSTHANOREQUAL", "P2SH,STRICTENC", "OK"], +["-11 -10", "LESSTHANOREQUAL", "P2SH,STRICTENC", "OK"], +["11 10", "GREATERTHANOREQUAL", "P2SH,STRICTENC", "OK"], +["4 4", "GREATERTHANOREQUAL", "P2SH,STRICTENC", "OK"], +["10 11", "GREATERTHANOREQUAL NOT", "P2SH,STRICTENC", "OK"], +["-11 11", "GREATERTHANOREQUAL NOT", "P2SH,STRICTENC", "OK"], +["-11 -10", "GREATERTHANOREQUAL NOT", "P2SH,STRICTENC", "OK"], +["1 0 MIN", "0 NUMEQUAL", "P2SH,STRICTENC", "OK"], +["0 1 MIN", "0 NUMEQUAL", "P2SH,STRICTENC", "OK"], +["-1 0 MIN", "-1 NUMEQUAL", "P2SH,STRICTENC", "OK"], +["0 -2147483647 MIN", "-2147483647 NUMEQUAL", "P2SH,STRICTENC", "OK"], +["2147483647 0 MAX", "2147483647 NUMEQUAL", "P2SH,STRICTENC", "OK"], +["0 100 MAX", "100 NUMEQUAL", "P2SH,STRICTENC", "OK"], +["-100 0 MAX", "0 NUMEQUAL", "P2SH,STRICTENC", "OK"], +["0 -2147483647 MAX", "0 NUMEQUAL", "P2SH,STRICTENC", "OK"], +["0 0 1", "WITHIN", "P2SH,STRICTENC", "OK"], +["1 0 1", "WITHIN NOT", "P2SH,STRICTENC", "OK"], +["0 -2147483647 2147483647", "WITHIN", "P2SH,STRICTENC", "OK"], +["-1 -100 100", "WITHIN", "P2SH,STRICTENC", "OK"], +["11 -100 100", "WITHIN", "P2SH,STRICTENC", "OK"], +["-2147483647 -100 100", "WITHIN NOT", "P2SH,STRICTENC", "OK"], +["2147483647 -100 100", "WITHIN NOT", "P2SH,STRICTENC", "OK"], + +["2147483647 2147483647 SUB", "0 EQUAL", "P2SH,STRICTENC", "OK"], +["2147483647 DUP ADD", "4294967294 EQUAL", "P2SH,STRICTENC", "OK", ">32 bit EQUAL is valid"], +["2147483647 NEGATE DUP ADD", "-4294967294 EQUAL", "P2SH,STRICTENC", "OK"], + +["''", "RIPEMD160 0x14 0x9c1185a5c5e9fc54612808977ee8f548b2258d31 EQUAL", "P2SH,STRICTENC", "OK"], +["'a'", "RIPEMD160 0x14 0x0bdc9d2d256b3ee9daae347be6f4dc835a467ffe EQUAL", "P2SH,STRICTENC", "OK"], +["'abcdefghijklmnopqrstuvwxyz'", "RIPEMD160 0x14 0xf71c27109c692c1b56bbdceb5b9d2865b3708dbc EQUAL", "P2SH,STRICTENC", "OK"], +["''", "SHA1 0x14 0xda39a3ee5e6b4b0d3255bfef95601890afd80709 EQUAL", "P2SH,STRICTENC", "OK"], +["'a'", "SHA1 0x14 0x86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 EQUAL", "P2SH,STRICTENC", "OK"], +["'abcdefghijklmnopqrstuvwxyz'", "SHA1 0x14 0x32d10c7b8cf96570ca04ce37f2a19d84240d3a89 EQUAL", "P2SH,STRICTENC", "OK"], +["''", "SHA256 0x20 0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 EQUAL", "P2SH,STRICTENC", "OK"], +["'a'", "SHA256 0x20 0xca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb EQUAL", "P2SH,STRICTENC", "OK"], +["'abcdefghijklmnopqrstuvwxyz'", "SHA256 0x20 0x71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73 EQUAL", "P2SH,STRICTENC", "OK"], +["''", "DUP HASH160 SWAP SHA256 RIPEMD160 EQUAL", "P2SH,STRICTENC", "OK"], +["''", "DUP HASH256 SWAP SHA256 SHA256 EQUAL", "P2SH,STRICTENC", "OK"], +["''", "NOP HASH160 0x14 0xb472a266d0bd89c13706a4132ccfb16f7c3b9fcb EQUAL", "P2SH,STRICTENC", "OK"], +["'a'", "HASH160 NOP 0x14 0x994355199e516ff76c4fa4aab39337b9d84cf12b EQUAL", "P2SH,STRICTENC", "OK"], +["'abcdefghijklmnopqrstuvwxyz'", "HASH160 0x4c 0x14 0xc286a1af0947f58d1ad787385b1c2c4a976f9e71 EQUAL", "P2SH,STRICTENC", "OK"], +["''", "HASH256 0x20 0x5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456 EQUAL", "P2SH,STRICTENC", "OK"], +["'a'", "HASH256 0x20 0xbf5d3affb73efd2ec6c36ad3112dd933efed63c4e1cbffcfa88e2759c144f2d8 EQUAL", "P2SH,STRICTENC", "OK"], +["'abcdefghijklmnopqrstuvwxyz'", "HASH256 0x4c 0x20 0xca139bc10c2f660da42666f72e89a225936fc60f193c161124a672050c434671 EQUAL", "P2SH,STRICTENC", "OK"], + + +["1","NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 1 EQUAL", "P2SH,STRICTENC", "OK"], +["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_10' EQUAL", "P2SH,STRICTENC", "OK"], + +["1", "NOP", "P2SH,STRICTENC,DISCOURAGE_UPGRADABLE_NOPS", "OK", "Discourage NOPx flag allows OP_NOP"], + +["0", "IF NOP10 ENDIF 1", "P2SH,STRICTENC,DISCOURAGE_UPGRADABLE_NOPS", "OK", "Discouraged NOPs are allowed if not executed"], -["0", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "opcodes above NOP10 invalid if executed"], -["0", "IF 0xbb ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xbe ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xbf ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xc0 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xc1 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xc2 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xc3 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xc4 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xc5 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xc6 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xc7 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xc8 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xc9 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xca ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xcb ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xcc ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xcd ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xce ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xcf ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xd0 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xd1 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xd2 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xd3 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xd4 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xd5 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xd6 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xd7 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xd8 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xd9 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xda ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xdb ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xdc ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xdd ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xde ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xdf ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xe0 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xe1 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xe2 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xe3 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xe4 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xe5 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xe6 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xe7 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xe8 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xe9 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xea ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xeb ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xec ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xed ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xee ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xef ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xf0 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xf1 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xf2 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xf3 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xf4 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xf5 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xf6 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xf7 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xf8 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xf9 ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xfa ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xfb ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xfc ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xfd ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xfe ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0", "IF 0xff ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "OK", "opcodes above NOP10 invalid if executed"], +["0", "IF 0xbb ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xbe ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xbf ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xc0 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xc1 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xc2 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xc3 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xc4 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xc5 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xc6 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xc7 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xc8 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xc9 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xca ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xcb ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xcc ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xcd ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xce ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xcf ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xd0 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xd1 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xd2 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xd3 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xd4 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xd5 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xd6 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xd7 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xd8 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xd9 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xda ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xdb ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xdc ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xdd ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xde ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xdf ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xe0 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xe1 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xe2 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xe3 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xe4 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xe5 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xe6 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xe7 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xe8 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xe9 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xea ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xeb ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xec ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xed ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xee ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xef ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xf0 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xf1 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xf2 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xf3 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xf4 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xf5 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xf6 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xf7 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xf8 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xf9 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xfa ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xfb ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xfc ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xfd ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xfe ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xff ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["NOP", "'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'", -"P2SH,STRICTENC", +"P2SH,STRICTENC", "OK", "520 byte push"], ["1", "0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", -"P2SH,STRICTENC", +"P2SH,STRICTENC", "OK", "201 opcodes executed. 0x61 is NOP"], ["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", "1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", -"P2SH,STRICTENC", +"P2SH,STRICTENC", "OK", "1,000 stack size (0x6f is 3DUP)"], ["1 TOALTSTACK 2 TOALTSTACK 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", "1 2 3 4 5 6 7 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", -"P2SH,STRICTENC", +"P2SH,STRICTENC", "OK", "1,000 stack size (altstack cleared between scriptSig/scriptPubKey)"], ["'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", "'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f 2DUP 0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", -"P2SH,STRICTENC", +"P2SH,STRICTENC", "OK", "Max-size (10,000-byte), max-push(520 bytes), max-opcodes(201), max stack size(1,000 items). 0x6f is 3DUP, 0x61 is NOP"], ["0", "IF 0x5050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050 ENDIF 1", -"P2SH,STRICTENC", +"P2SH,STRICTENC", "OK", ">201 opcodes, but RESERVED (0x50) doesn't count towards opcode limit."], -["NOP","1", "P2SH,STRICTENC"], - -["1", "0x01 0x01 EQUAL", "P2SH,STRICTENC", "The following is useful for checking implementations of BN_bn2mpi"], -["127", "0x01 0x7F EQUAL", "P2SH,STRICTENC"], -["128", "0x02 0x8000 EQUAL", "P2SH,STRICTENC", "Leave room for the sign bit"], -["32767", "0x02 0xFF7F EQUAL", "P2SH,STRICTENC"], -["32768", "0x03 0x008000 EQUAL", "P2SH,STRICTENC"], -["8388607", "0x03 0xFFFF7F EQUAL", "P2SH,STRICTENC"], -["8388608", "0x04 0x00008000 EQUAL", "P2SH,STRICTENC"], -["2147483647", "0x04 0xFFFFFF7F EQUAL", "P2SH,STRICTENC"], -["2147483648", "0x05 0x0000008000 EQUAL", "P2SH,STRICTENC"], -["549755813887", "0x05 0xFFFFFFFF7F EQUAL", "P2SH,STRICTENC"], -["549755813888", "0x06 0xFFFFFFFF7F EQUAL", "P2SH,STRICTENC"], -["9223372036854775807", "0x08 0xFFFFFFFFFFFFFF7F EQUAL", "P2SH,STRICTENC"], -["-1", "0x01 0x81 EQUAL", "P2SH,STRICTENC", "Numbers are little-endian with the MSB being a sign bit"], -["-127", "0x01 0xFF EQUAL", "P2SH,STRICTENC"], -["-128", "0x02 0x8080 EQUAL", "P2SH,STRICTENC"], -["-32767", "0x02 0xFFFF EQUAL", "P2SH,STRICTENC"], -["-32768", "0x03 0x008080 EQUAL", "P2SH,STRICTENC"], -["-8388607", "0x03 0xFFFFFF EQUAL", "P2SH,STRICTENC"], -["-8388608", "0x04 0x00008080 EQUAL", "P2SH,STRICTENC"], -["-2147483647", "0x04 0xFFFFFFFF EQUAL", "P2SH,STRICTENC"], -["-2147483648", "0x05 0x0000008080 EQUAL", "P2SH,STRICTENC"], -["-4294967295", "0x05 0xFFFFFFFF80 EQUAL", "P2SH,STRICTENC"], -["-549755813887", "0x05 0xFFFFFFFFFF EQUAL", "P2SH,STRICTENC"], -["-549755813888", "0x06 0x000000008080 EQUAL", "P2SH,STRICTENC"], -["-9223372036854775807", "0x08 0xFFFFFFFFFFFFFFFF EQUAL", "P2SH,STRICTENC"], - -["2147483647", "1ADD 2147483648 EQUAL", "P2SH,STRICTENC", "We can do math on 4-byte integers, and compare 5-byte ones"], -["2147483647", "1ADD 1", "P2SH,STRICTENC"], -["-2147483647", "1ADD 1", "P2SH,STRICTENC"], - -["1", "0x02 0x0100 EQUAL NOT", "P2SH,STRICTENC", "Not the same byte array..."], -["1", "0x02 0x0100 NUMEQUAL", "P2SH,STRICTENC", "... but they are numerically equal"], -["11", "0x4c 0x03 0x0b0000 NUMEQUAL", "P2SH,STRICTENC"], -["0", "0x01 0x80 EQUAL NOT", "P2SH,STRICTENC"], -["0", "0x01 0x80 NUMEQUAL", "P2SH,STRICTENC", "Zero numerically equals negative zero"], -["0", "0x02 0x0080 NUMEQUAL", "P2SH,STRICTENC"], -["0x03 0x000080", "0x04 0x00000080 NUMEQUAL", "P2SH,STRICTENC"], -["0x03 0x100080", "0x04 0x10000080 NUMEQUAL", "P2SH,STRICTENC"], -["0x03 0x100000", "0x04 0x10000000 NUMEQUAL", "P2SH,STRICTENC"], - -["NOP", "NOP 1", "P2SH,STRICTENC", "The following tests check the if(stack.size() < N) tests in each opcode"], -["1", "IF 1 ENDIF", "P2SH,STRICTENC", "They are here to catch copy-and-paste errors"], -["0", "NOTIF 1 ENDIF", "P2SH,STRICTENC", "Most of them are duplicated elsewhere,"], -["1", "VERIFY 1", "P2SH,STRICTENC", "but, hey, more is always better, right?"], - -["0", "TOALTSTACK 1", "P2SH,STRICTENC"], -["1", "TOALTSTACK FROMALTSTACK", "P2SH,STRICTENC"], -["0 0", "2DROP 1", "P2SH,STRICTENC"], -["0 1", "2DUP", "P2SH,STRICTENC"], -["0 0 1", "3DUP", "P2SH,STRICTENC"], -["0 1 0 0", "2OVER", "P2SH,STRICTENC"], -["0 1 0 0 0 0", "2ROT", "P2SH,STRICTENC"], -["0 1 0 0", "2SWAP", "P2SH,STRICTENC"], -["1", "IFDUP", "P2SH,STRICTENC"], -["NOP", "DEPTH 1", "P2SH,STRICTENC"], -["0", "DROP 1", "P2SH,STRICTENC"], -["1", "DUP", "P2SH,STRICTENC"], -["0 1", "NIP", "P2SH,STRICTENC"], -["1 0", "OVER", "P2SH,STRICTENC"], -["1 0 0 0 3", "PICK", "P2SH,STRICTENC"], -["1 0", "PICK", "P2SH,STRICTENC"], -["1 0 0 0 3", "ROLL", "P2SH,STRICTENC"], -["1 0", "ROLL", "P2SH,STRICTENC"], -["1 0 0", "ROT", "P2SH,STRICTENC"], -["1 0", "SWAP", "P2SH,STRICTENC"], -["0 1", "TUCK", "P2SH,STRICTENC"], - -["1", "SIZE", "P2SH,STRICTENC"], - -["0 0", "EQUAL", "P2SH,STRICTENC"], -["0 0", "EQUALVERIFY 1", "P2SH,STRICTENC"], -["0 0 1", "EQUAL EQUAL", "P2SH,STRICTENC", "OP_0 and bools must have identical byte representations"], - -["0", "1ADD", "P2SH,STRICTENC"], -["2", "1SUB", "P2SH,STRICTENC"], -["-1", "NEGATE", "P2SH,STRICTENC"], -["-1", "ABS", "P2SH,STRICTENC"], -["0", "NOT", "P2SH,STRICTENC"], -["-1", "0NOTEQUAL", "P2SH,STRICTENC"], - -["1 0", "ADD", "P2SH,STRICTENC"], -["1 0", "SUB", "P2SH,STRICTENC"], -["-1 -1", "BOOLAND", "P2SH,STRICTENC"], -["-1 0", "BOOLOR", "P2SH,STRICTENC"], -["0 0", "NUMEQUAL", "P2SH,STRICTENC"], -["0 0", "NUMEQUALVERIFY 1", "P2SH,STRICTENC"], -["-1 0", "NUMNOTEQUAL", "P2SH,STRICTENC"], -["-1 0", "LESSTHAN", "P2SH,STRICTENC"], -["1 0", "GREATERTHAN", "P2SH,STRICTENC"], -["0 0", "LESSTHANOREQUAL", "P2SH,STRICTENC"], -["0 0", "GREATERTHANOREQUAL", "P2SH,STRICTENC"], -["-1 0", "MIN", "P2SH,STRICTENC"], -["1 0", "MAX", "P2SH,STRICTENC"], -["-1 -1 0", "WITHIN", "P2SH,STRICTENC"], - -["0", "RIPEMD160", "P2SH,STRICTENC"], -["0", "SHA1", "P2SH,STRICTENC"], -["0", "SHA256", "P2SH,STRICTENC"], -["0", "HASH160", "P2SH,STRICTENC"], -["0", "HASH256", "P2SH,STRICTENC"], -["NOP", "CODESEPARATOR 1", "P2SH,STRICTENC"], - -["NOP", "NOP1 1", "P2SH,STRICTENC"], -["NOP", "CHECKLOCKTIMEVERIFY 1", "P2SH,STRICTENC"], -["NOP", "NOP3 1", "P2SH,STRICTENC"], -["NOP", "NOP4 1", "P2SH,STRICTENC"], -["NOP", "NOP5 1", "P2SH,STRICTENC"], -["NOP", "NOP6 1", "P2SH,STRICTENC"], -["NOP", "NOP7 1", "P2SH,STRICTENC"], -["NOP", "NOP8 1", "P2SH,STRICTENC"], -["NOP", "NOP9 1", "P2SH,STRICTENC"], -["NOP", "NOP10 1", "P2SH,STRICTENC"], - -["", "0 0 0 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "CHECKMULTISIG is allowed to have zero keys and/or sigs"], -["", "0 0 0 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 0 1 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "Zero sigs means no sigs are checked"], -["", "0 0 0 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], - -["", "0 0 0 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "CHECKMULTISIG is allowed to have zero keys and/or sigs"], -["", "0 0 0 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 0 1 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "Zero sigs means no sigs are checked"], -["", "0 0 0 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], - -["", "0 0 'a' 'b' 2 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "Test from up to 20 pubkeys, all not checked"], -["", "0 0 'a' 'b' 'c' 3 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 4 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 5 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 6 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 7 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 8 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 9 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 10 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 11 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 12 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 13 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 14 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 15 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 16 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 17 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 18 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 19 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 2 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 3 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 4 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 5 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 6 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 7 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 8 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 9 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 10 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 11 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 12 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 13 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 14 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 15 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 16 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 17 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 18 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 19 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["NOP","1", "P2SH,STRICTENC", "OK"], + +["1", "0x01 0x01 EQUAL", "P2SH,STRICTENC", "OK", "The following is useful for checking implementations of BN_bn2mpi"], +["127", "0x01 0x7F EQUAL", "P2SH,STRICTENC", "OK"], +["128", "0x02 0x8000 EQUAL", "P2SH,STRICTENC", "OK", "Leave room for the sign bit"], +["32767", "0x02 0xFF7F EQUAL", "P2SH,STRICTENC", "OK"], +["32768", "0x03 0x008000 EQUAL", "P2SH,STRICTENC", "OK"], +["8388607", "0x03 0xFFFF7F EQUAL", "P2SH,STRICTENC", "OK"], +["8388608", "0x04 0x00008000 EQUAL", "P2SH,STRICTENC", "OK"], +["2147483647", "0x04 0xFFFFFF7F EQUAL", "P2SH,STRICTENC", "OK"], +["2147483648", "0x05 0x0000008000 EQUAL", "P2SH,STRICTENC", "OK"], +["549755813887", "0x05 0xFFFFFFFF7F EQUAL", "P2SH,STRICTENC", "OK"], +["549755813888", "0x06 0xFFFFFFFF7F EQUAL", "P2SH,STRICTENC", "OK"], +["9223372036854775807", "0x08 0xFFFFFFFFFFFFFF7F EQUAL", "P2SH,STRICTENC", "OK"], +["-1", "0x01 0x81 EQUAL", "P2SH,STRICTENC", "OK", "Numbers are little-endian with the MSB being a sign bit"], +["-127", "0x01 0xFF EQUAL", "P2SH,STRICTENC", "OK"], +["-128", "0x02 0x8080 EQUAL", "P2SH,STRICTENC", "OK"], +["-32767", "0x02 0xFFFF EQUAL", "P2SH,STRICTENC", "OK"], +["-32768", "0x03 0x008080 EQUAL", "P2SH,STRICTENC", "OK"], +["-8388607", "0x03 0xFFFFFF EQUAL", "P2SH,STRICTENC", "OK"], +["-8388608", "0x04 0x00008080 EQUAL", "P2SH,STRICTENC", "OK"], +["-2147483647", "0x04 0xFFFFFFFF EQUAL", "P2SH,STRICTENC", "OK"], +["-2147483648", "0x05 0x0000008080 EQUAL", "P2SH,STRICTENC", "OK"], +["-4294967295", "0x05 0xFFFFFFFF80 EQUAL", "P2SH,STRICTENC", "OK"], +["-549755813887", "0x05 0xFFFFFFFFFF EQUAL", "P2SH,STRICTENC", "OK"], +["-549755813888", "0x06 0x000000008080 EQUAL", "P2SH,STRICTENC", "OK"], +["-9223372036854775807", "0x08 0xFFFFFFFFFFFFFFFF EQUAL", "P2SH,STRICTENC", "OK"], + +["2147483647", "1ADD 2147483648 EQUAL", "P2SH,STRICTENC", "OK", "We can do math on 4-byte integers, and compare 5-byte ones"], +["2147483647", "1ADD 1", "P2SH,STRICTENC", "OK"], +["-2147483647", "1ADD 1", "P2SH,STRICTENC", "OK"], + +["1", "0x02 0x0100 EQUAL NOT", "P2SH,STRICTENC", "OK", "Not the same byte array..."], +["1", "0x02 0x0100 NUMEQUAL", "P2SH,STRICTENC", "OK", "... but they are numerically equal"], +["11", "0x4c 0x03 0x0b0000 NUMEQUAL", "P2SH,STRICTENC", "OK"], +["0", "0x01 0x80 EQUAL NOT", "P2SH,STRICTENC", "OK"], +["0", "0x01 0x80 NUMEQUAL", "P2SH,STRICTENC", "OK", "Zero numerically equals negative zero"], +["0", "0x02 0x0080 NUMEQUAL", "P2SH,STRICTENC", "OK"], +["0x03 0x000080", "0x04 0x00000080 NUMEQUAL", "P2SH,STRICTENC", "OK"], +["0x03 0x100080", "0x04 0x10000080 NUMEQUAL", "P2SH,STRICTENC", "OK"], +["0x03 0x100000", "0x04 0x10000000 NUMEQUAL", "P2SH,STRICTENC", "OK"], + +["NOP", "NOP 1", "P2SH,STRICTENC", "OK", "The following tests check the if(stack.size() < N) tests in each opcode"], +["1", "IF 1 ENDIF", "P2SH,STRICTENC", "OK", "They are here to catch copy-and-paste errors"], +["0", "NOTIF 1 ENDIF", "P2SH,STRICTENC", "OK", "Most of them are duplicated elsewhere,"], +["1", "VERIFY 1", "P2SH,STRICTENC", "OK", "but, hey, more is always better, right?"], + +["0", "TOALTSTACK 1", "P2SH,STRICTENC", "OK"], +["1", "TOALTSTACK FROMALTSTACK", "P2SH,STRICTENC", "OK"], +["0 0", "2DROP 1", "P2SH,STRICTENC", "OK"], +["0 1", "2DUP", "P2SH,STRICTENC", "OK"], +["0 0 1", "3DUP", "P2SH,STRICTENC", "OK"], +["0 1 0 0", "2OVER", "P2SH,STRICTENC", "OK"], +["0 1 0 0 0 0", "2ROT", "P2SH,STRICTENC", "OK"], +["0 1 0 0", "2SWAP", "P2SH,STRICTENC", "OK"], +["1", "IFDUP", "P2SH,STRICTENC", "OK"], +["NOP", "DEPTH 1", "P2SH,STRICTENC", "OK"], +["0", "DROP 1", "P2SH,STRICTENC", "OK"], +["1", "DUP", "P2SH,STRICTENC", "OK"], +["0 1", "NIP", "P2SH,STRICTENC", "OK"], +["1 0", "OVER", "P2SH,STRICTENC", "OK"], +["1 0 0 0 3", "PICK", "P2SH,STRICTENC", "OK"], +["1 0", "PICK", "P2SH,STRICTENC", "OK"], +["1 0 0 0 3", "ROLL", "P2SH,STRICTENC", "OK"], +["1 0", "ROLL", "P2SH,STRICTENC", "OK"], +["1 0 0", "ROT", "P2SH,STRICTENC", "OK"], +["1 0", "SWAP", "P2SH,STRICTENC", "OK"], +["0 1", "TUCK", "P2SH,STRICTENC", "OK"], + +["1", "SIZE", "P2SH,STRICTENC", "OK"], + +["0 0", "EQUAL", "P2SH,STRICTENC", "OK"], +["0 0", "EQUALVERIFY 1", "P2SH,STRICTENC", "OK"], +["0 0 1", "EQUAL EQUAL", "P2SH,STRICTENC", "OK", "OP_0 and bools must have identical byte representations"], + +["0", "1ADD", "P2SH,STRICTENC", "OK"], +["2", "1SUB", "P2SH,STRICTENC", "OK"], +["-1", "NEGATE", "P2SH,STRICTENC", "OK"], +["-1", "ABS", "P2SH,STRICTENC", "OK"], +["0", "NOT", "P2SH,STRICTENC", "OK"], +["-1", "0NOTEQUAL", "P2SH,STRICTENC", "OK"], + +["1 0", "ADD", "P2SH,STRICTENC", "OK"], +["1 0", "SUB", "P2SH,STRICTENC", "OK"], +["-1 -1", "BOOLAND", "P2SH,STRICTENC", "OK"], +["-1 0", "BOOLOR", "P2SH,STRICTENC", "OK"], +["0 0", "NUMEQUAL", "P2SH,STRICTENC", "OK"], +["0 0", "NUMEQUALVERIFY 1", "P2SH,STRICTENC", "OK"], +["-1 0", "NUMNOTEQUAL", "P2SH,STRICTENC", "OK"], +["-1 0", "LESSTHAN", "P2SH,STRICTENC", "OK"], +["1 0", "GREATERTHAN", "P2SH,STRICTENC", "OK"], +["0 0", "LESSTHANOREQUAL", "P2SH,STRICTENC", "OK"], +["0 0", "GREATERTHANOREQUAL", "P2SH,STRICTENC", "OK"], +["-1 0", "MIN", "P2SH,STRICTENC", "OK"], +["1 0", "MAX", "P2SH,STRICTENC", "OK"], +["-1 -1 0", "WITHIN", "P2SH,STRICTENC", "OK"], + +["0", "RIPEMD160", "P2SH,STRICTENC", "OK"], +["0", "SHA1", "P2SH,STRICTENC", "OK"], +["0", "SHA256", "P2SH,STRICTENC", "OK"], +["0", "HASH160", "P2SH,STRICTENC", "OK"], +["0", "HASH256", "P2SH,STRICTENC", "OK"], +["NOP", "CODESEPARATOR 1", "P2SH,STRICTENC", "OK"], + +["NOP", "NOP1 1", "P2SH,STRICTENC", "OK"], +["NOP", "CHECKLOCKTIMEVERIFY 1", "P2SH,STRICTENC", "OK"], +["NOP", "NOP3 1", "P2SH,STRICTENC", "OK"], +["NOP", "NOP4 1", "P2SH,STRICTENC", "OK"], +["NOP", "NOP5 1", "P2SH,STRICTENC", "OK"], +["NOP", "NOP6 1", "P2SH,STRICTENC", "OK"], +["NOP", "NOP7 1", "P2SH,STRICTENC", "OK"], +["NOP", "NOP8 1", "P2SH,STRICTENC", "OK"], +["NOP", "NOP9 1", "P2SH,STRICTENC", "OK"], +["NOP", "NOP10 1", "P2SH,STRICTENC", "OK"], + +["", "0 0 0 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK", "CHECKMULTISIG is allowed to have zero keys and/or sigs"], +["", "0 0 0 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 0 1 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK", "Zero sigs means no sigs are checked"], +["", "0 0 0 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], + +["", "0 0 0 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK", "CHECKMULTISIG is allowed to have zero keys and/or sigs"], +["", "0 0 0 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 0 1 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK", "Zero sigs means no sigs are checked"], +["", "0 0 0 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], + +["", "0 0 'a' 'b' 2 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK", "Test from up to 20 pubkeys, all not checked"], +["", "0 0 'a' 'b' 'c' 3 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 4 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 5 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 6 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 7 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 8 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 9 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 10 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 11 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 12 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 13 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 14 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 15 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 16 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 17 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 18 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 19 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 2 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 3 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 4 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 5 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 6 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 7 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 8 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 9 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 10 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 11 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 12 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 13 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 14 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 15 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 16 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 17 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 18 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 19 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"], ["", "0 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG", -"P2SH,STRICTENC", +"P2SH,STRICTENC", "OK", "nOpCount is incremented by the number of keys evaluated in addition to the usual one op per op. In this case we have zero keys, so we can execute 201 CHECKMULTISIGS"], ["1", "0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY", -"P2SH,STRICTENC"], +"P2SH,STRICTENC", "OK"], ["", "NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG", -"P2SH,STRICTENC", +"P2SH,STRICTENC", "OK", "Even though there are no signatures being checked nOpCount is incremented by the number of keys."], ["1", "NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY", -"P2SH,STRICTENC"], +"P2SH,STRICTENC", "OK"], -["0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "Very basic P2SH"], -["0x4c 0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC"], +["0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "OK", "Very basic P2SH"], +["0x4c 0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "OK"], ["0x40 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242", "0x4d 0x4000 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242 EQUAL", -"P2SH,STRICTENC", +"P2SH,STRICTENC", "OK", "Basic PUSH signedness check"], ["0x4c 0x40 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242", "0x4d 0x4000 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242 EQUAL", -"P2SH,STRICTENC", +"P2SH,STRICTENC", "OK", "Basic PUSHDATA1 signedness check"], ["all PUSHDATA forms are equivalent"], -["0x4c 0x4b 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "0x4b 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 EQUAL", "", "PUSHDATA1 of 75 bytes equals direct push of it"], -["0x4d 0xFF00 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "0x4c 0xFF 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 EQUAL", "", "PUSHDATA2 of 255 bytes equals PUSHDATA1 of it"], +["0x4c 0x4b 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "0x4b 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 EQUAL", "", "OK", "PUSHDATA1 of 75 bytes equals direct push of it"], +["0x4d 0xFF00 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "0x4c 0xFF 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 EQUAL", "", "OK", "PUSHDATA2 of 255 bytes equals PUSHDATA1 of it"], -["0x00", "SIZE 0 EQUAL", "P2SH,STRICTENC", "Basic OP_0 execution"], +["0x00", "SIZE 0 EQUAL", "P2SH,STRICTENC", "OK", "Basic OP_0 execution"], ["Numeric pushes"], -["0x01 0x81", "0x4f EQUAL", "", "OP1_NEGATE pushes 0x81"], -["0x01 0x01", "0x51 EQUAL", "", "OP_1 pushes 0x01"], -["0x01 0x02", "0x52 EQUAL", "", "OP_2 pushes 0x02"], -["0x01 0x03", "0x53 EQUAL", "", "OP_3 pushes 0x03"], -["0x01 0x04", "0x54 EQUAL", "", "OP_4 pushes 0x04"], -["0x01 0x05", "0x55 EQUAL", "", "OP_5 pushes 0x05"], -["0x01 0x06", "0x56 EQUAL", "", "OP_6 pushes 0x06"], -["0x01 0x07", "0x57 EQUAL", "", "OP_7 pushes 0x07"], -["0x01 0x08", "0x58 EQUAL", "", "OP_8 pushes 0x08"], -["0x01 0x09", "0x59 EQUAL", "", "OP_9 pushes 0x09"], -["0x01 0x0a", "0x5a EQUAL", "", "OP_10 pushes 0x0a"], -["0x01 0x0b", "0x5b EQUAL", "", "OP_11 pushes 0x0b"], -["0x01 0x0c", "0x5c EQUAL", "", "OP_12 pushes 0x0c"], -["0x01 0x0d", "0x5d EQUAL", "", "OP_13 pushes 0x0d"], -["0x01 0x0e", "0x5e EQUAL", "", "OP_14 pushes 0x0e"], -["0x01 0x0f", "0x5f EQUAL", "", "OP_15 pushes 0x0f"], -["0x01 0x10", "0x60 EQUAL", "", "OP_16 pushes 0x10"], +["0x01 0x81", "0x4f EQUAL", "", "OK", "OP1_NEGATE pushes 0x81"], +["0x01 0x01", "0x51 EQUAL", "", "OK", "OP_1 pushes 0x01"], +["0x01 0x02", "0x52 EQUAL", "", "OK", "OP_2 pushes 0x02"], +["0x01 0x03", "0x53 EQUAL", "", "OK", "OP_3 pushes 0x03"], +["0x01 0x04", "0x54 EQUAL", "", "OK", "OP_4 pushes 0x04"], +["0x01 0x05", "0x55 EQUAL", "", "OK", "OP_5 pushes 0x05"], +["0x01 0x06", "0x56 EQUAL", "", "OK", "OP_6 pushes 0x06"], +["0x01 0x07", "0x57 EQUAL", "", "OK", "OP_7 pushes 0x07"], +["0x01 0x08", "0x58 EQUAL", "", "OK", "OP_8 pushes 0x08"], +["0x01 0x09", "0x59 EQUAL", "", "OK", "OP_9 pushes 0x09"], +["0x01 0x0a", "0x5a EQUAL", "", "OK", "OP_10 pushes 0x0a"], +["0x01 0x0b", "0x5b EQUAL", "", "OK", "OP_11 pushes 0x0b"], +["0x01 0x0c", "0x5c EQUAL", "", "OK", "OP_12 pushes 0x0c"], +["0x01 0x0d", "0x5d EQUAL", "", "OK", "OP_13 pushes 0x0d"], +["0x01 0x0e", "0x5e EQUAL", "", "OK", "OP_14 pushes 0x0e"], +["0x01 0x0f", "0x5f EQUAL", "", "OK", "OP_15 pushes 0x0f"], +["0x01 0x10", "0x60 EQUAL", "", "OK", "OP_16 pushes 0x10"], ["Equivalency of different numeric encodings"], -["0x02 0x8000", "128 NUMEQUAL", "", "0x8000 equals 128"], -["0x01 0x00", "0 NUMEQUAL", "", "0x00 numequals 0"], -["0x01 0x80", "0 NUMEQUAL", "", "0x80 (negative zero) numequals 0"], -["0x02 0x0080", "0 NUMEQUAL", "", "0x0080 numequals 0"], -["0x02 0x0500", "5 NUMEQUAL", "", "0x0500 numequals 5"], -["0x03 0xff7f80", "0x02 0xffff NUMEQUAL", "", ""], -["0x03 0xff7f00", "0x02 0xff7f NUMEQUAL", "", ""], -["0x04 0xffff7f80", "0x03 0xffffff NUMEQUAL", "", ""], -["0x04 0xffff7f00", "0x03 0xffff7f NUMEQUAL", "", ""], +["0x02 0x8000", "128 NUMEQUAL", "", "OK", "0x8000 equals 128"], +["0x01 0x00", "0 NUMEQUAL", "", "OK", "0x00 numequals 0"], +["0x01 0x80", "0 NUMEQUAL", "", "OK", "0x80 (negative zero) numequals 0"], +["0x02 0x0080", "0 NUMEQUAL", "", "OK", "0x0080 numequals 0"], +["0x02 0x0500", "5 NUMEQUAL", "", "OK", "0x0500 numequals 5"], +["0x03 0xff7f80", "0x02 0xffff NUMEQUAL", "", "OK", ""], +["0x03 0xff7f00", "0x02 0xff7f NUMEQUAL", "", "OK", ""], +["0x04 0xffff7f80", "0x03 0xffffff NUMEQUAL", "", "OK", ""], +["0x04 0xffff7f00", "0x03 0xffff7f NUMEQUAL", "", "OK", ""], ["Unevaluated non-minimal pushes are ignored"], -["0 IF 0x4c 0x00 ENDIF 1", "", "MINIMALDATA", "non-minimal PUSHDATA1 ignored"], -["0 IF 0x4d 0x0000 ENDIF 1", "", "MINIMALDATA", "non-minimal PUSHDATA2 ignored"], -["0 IF 0x4c 0x00000000 ENDIF 1", "", "MINIMALDATA", "non-minimal PUSHDATA4 ignored"], -["0 IF 0x01 0x81 ENDIF 1", "", "MINIMALDATA", "1NEGATE equiv"], -["0 IF 0x01 0x01 ENDIF 1", "", "MINIMALDATA", "OP_1 equiv"], -["0 IF 0x01 0x02 ENDIF 1", "", "MINIMALDATA", "OP_2 equiv"], -["0 IF 0x01 0x03 ENDIF 1", "", "MINIMALDATA", "OP_3 equiv"], -["0 IF 0x01 0x04 ENDIF 1", "", "MINIMALDATA", "OP_4 equiv"], -["0 IF 0x01 0x05 ENDIF 1", "", "MINIMALDATA", "OP_5 equiv"], -["0 IF 0x01 0x06 ENDIF 1", "", "MINIMALDATA", "OP_6 equiv"], -["0 IF 0x01 0x07 ENDIF 1", "", "MINIMALDATA", "OP_7 equiv"], -["0 IF 0x01 0x08 ENDIF 1", "", "MINIMALDATA", "OP_8 equiv"], -["0 IF 0x01 0x09 ENDIF 1", "", "MINIMALDATA", "OP_9 equiv"], -["0 IF 0x01 0x0a ENDIF 1", "", "MINIMALDATA", "OP_10 equiv"], -["0 IF 0x01 0x0b ENDIF 1", "", "MINIMALDATA", "OP_11 equiv"], -["0 IF 0x01 0x0c ENDIF 1", "", "MINIMALDATA", "OP_12 equiv"], -["0 IF 0x01 0x0d ENDIF 1", "", "MINIMALDATA", "OP_13 equiv"], -["0 IF 0x01 0x0e ENDIF 1", "", "MINIMALDATA", "OP_14 equiv"], -["0 IF 0x01 0x0f ENDIF 1", "", "MINIMALDATA", "OP_15 equiv"], -["0 IF 0x01 0x10 ENDIF 1", "", "MINIMALDATA", "OP_16 equiv"], +["0 IF 0x4c 0x00 ENDIF 1", "", "MINIMALDATA", "OK", "non-minimal PUSHDATA1 ignored"], +["0 IF 0x4d 0x0000 ENDIF 1", "", "MINIMALDATA", "OK", "non-minimal PUSHDATA2 ignored"], +["0 IF 0x4c 0x00000000 ENDIF 1", "", "MINIMALDATA", "OK", "non-minimal PUSHDATA4 ignored"], +["0 IF 0x01 0x81 ENDIF 1", "", "MINIMALDATA", "OK", "1NEGATE equiv"], +["0 IF 0x01 0x01 ENDIF 1", "", "MINIMALDATA", "OK", "OP_1 equiv"], +["0 IF 0x01 0x02 ENDIF 1", "", "MINIMALDATA", "OK", "OP_2 equiv"], +["0 IF 0x01 0x03 ENDIF 1", "", "MINIMALDATA", "OK", "OP_3 equiv"], +["0 IF 0x01 0x04 ENDIF 1", "", "MINIMALDATA", "OK", "OP_4 equiv"], +["0 IF 0x01 0x05 ENDIF 1", "", "MINIMALDATA", "OK", "OP_5 equiv"], +["0 IF 0x01 0x06 ENDIF 1", "", "MINIMALDATA", "OK", "OP_6 equiv"], +["0 IF 0x01 0x07 ENDIF 1", "", "MINIMALDATA", "OK", "OP_7 equiv"], +["0 IF 0x01 0x08 ENDIF 1", "", "MINIMALDATA", "OK", "OP_8 equiv"], +["0 IF 0x01 0x09 ENDIF 1", "", "MINIMALDATA", "OK", "OP_9 equiv"], +["0 IF 0x01 0x0a ENDIF 1", "", "MINIMALDATA", "OK", "OP_10 equiv"], +["0 IF 0x01 0x0b ENDIF 1", "", "MINIMALDATA", "OK", "OP_11 equiv"], +["0 IF 0x01 0x0c ENDIF 1", "", "MINIMALDATA", "OK", "OP_12 equiv"], +["0 IF 0x01 0x0d ENDIF 1", "", "MINIMALDATA", "OK", "OP_13 equiv"], +["0 IF 0x01 0x0e ENDIF 1", "", "MINIMALDATA", "OK", "OP_14 equiv"], +["0 IF 0x01 0x0f ENDIF 1", "", "MINIMALDATA", "OK", "OP_15 equiv"], +["0 IF 0x01 0x10 ENDIF 1", "", "MINIMALDATA", "OK", "OP_16 equiv"], ["Numeric minimaldata rules are only applied when a stack item is numerically evaluated; the push itself is allowed"], -["0x01 0x00", "1", "MINIMALDATA"], -["0x01 0x80", "1", "MINIMALDATA"], -["0x02 0x0180", "1", "MINIMALDATA"], -["0x02 0x0100", "1", "MINIMALDATA"], -["0x02 0x0200", "1", "MINIMALDATA"], -["0x02 0x0300", "1", "MINIMALDATA"], -["0x02 0x0400", "1", "MINIMALDATA"], -["0x02 0x0500", "1", "MINIMALDATA"], -["0x02 0x0600", "1", "MINIMALDATA"], -["0x02 0x0700", "1", "MINIMALDATA"], -["0x02 0x0800", "1", "MINIMALDATA"], -["0x02 0x0900", "1", "MINIMALDATA"], -["0x02 0x0a00", "1", "MINIMALDATA"], -["0x02 0x0b00", "1", "MINIMALDATA"], -["0x02 0x0c00", "1", "MINIMALDATA"], -["0x02 0x0d00", "1", "MINIMALDATA"], -["0x02 0x0e00", "1", "MINIMALDATA"], -["0x02 0x0f00", "1", "MINIMALDATA"], -["0x02 0x1000", "1", "MINIMALDATA"], +["0x01 0x00", "1", "MINIMALDATA", "OK"], +["0x01 0x80", "1", "MINIMALDATA", "OK"], +["0x02 0x0180", "1", "MINIMALDATA", "OK"], +["0x02 0x0100", "1", "MINIMALDATA", "OK"], +["0x02 0x0200", "1", "MINIMALDATA", "OK"], +["0x02 0x0300", "1", "MINIMALDATA", "OK"], +["0x02 0x0400", "1", "MINIMALDATA", "OK"], +["0x02 0x0500", "1", "MINIMALDATA", "OK"], +["0x02 0x0600", "1", "MINIMALDATA", "OK"], +["0x02 0x0700", "1", "MINIMALDATA", "OK"], +["0x02 0x0800", "1", "MINIMALDATA", "OK"], +["0x02 0x0900", "1", "MINIMALDATA", "OK"], +["0x02 0x0a00", "1", "MINIMALDATA", "OK"], +["0x02 0x0b00", "1", "MINIMALDATA", "OK"], +["0x02 0x0c00", "1", "MINIMALDATA", "OK"], +["0x02 0x0d00", "1", "MINIMALDATA", "OK"], +["0x02 0x0e00", "1", "MINIMALDATA", "OK"], +["0x02 0x0f00", "1", "MINIMALDATA", "OK"], +["0x02 0x1000", "1", "MINIMALDATA", "OK"], ["Valid version of the 'Test every numeric-accepting opcode for correct handling of the numeric minimal encoding rule' script_invalid test"], -["1 0x02 0x0000", "PICK DROP", ""], -["1 0x02 0x0000", "ROLL DROP 1", ""], -["0x02 0x0000", "1ADD DROP 1", ""], -["0x02 0x0000", "1SUB DROP 1", ""], -["0x02 0x0000", "NEGATE DROP 1", ""], -["0x02 0x0000", "ABS DROP 1", ""], -["0x02 0x0000", "NOT DROP 1", ""], -["0x02 0x0000", "0NOTEQUAL DROP 1", ""], - -["0 0x02 0x0000", "ADD DROP 1", ""], -["0x02 0x0000 0", "ADD DROP 1", ""], -["0 0x02 0x0000", "SUB DROP 1", ""], -["0x02 0x0000 0", "SUB DROP 1", ""], -["0 0x02 0x0000", "BOOLAND DROP 1", ""], -["0x02 0x0000 0", "BOOLAND DROP 1", ""], -["0 0x02 0x0000", "BOOLOR DROP 1", ""], -["0x02 0x0000 0", "BOOLOR DROP 1", ""], -["0 0x02 0x0000", "NUMEQUAL DROP 1", ""], -["0x02 0x0000 1", "NUMEQUAL DROP 1", ""], -["0 0x02 0x0000", "NUMEQUALVERIFY 1", ""], -["0x02 0x0000 0", "NUMEQUALVERIFY 1", ""], -["0 0x02 0x0000", "NUMNOTEQUAL DROP 1", ""], -["0x02 0x0000 0", "NUMNOTEQUAL DROP 1", ""], -["0 0x02 0x0000", "LESSTHAN DROP 1", ""], -["0x02 0x0000 0", "LESSTHAN DROP 1", ""], -["0 0x02 0x0000", "GREATERTHAN DROP 1", ""], -["0x02 0x0000 0", "GREATERTHAN DROP 1", ""], -["0 0x02 0x0000", "LESSTHANOREQUAL DROP 1", ""], -["0x02 0x0000 0", "LESSTHANOREQUAL DROP 1", ""], -["0 0x02 0x0000", "GREATERTHANOREQUAL DROP 1", ""], -["0x02 0x0000 0", "GREATERTHANOREQUAL DROP 1", ""], -["0 0x02 0x0000", "MIN DROP 1", ""], -["0x02 0x0000 0", "MIN DROP 1", ""], -["0 0x02 0x0000", "MAX DROP 1", ""], -["0x02 0x0000 0", "MAX DROP 1", ""], - -["0x02 0x0000 0 0", "WITHIN DROP 1", ""], -["0 0x02 0x0000 0", "WITHIN DROP 1", ""], -["0 0 0x02 0x0000", "WITHIN DROP 1", ""], - -["0 0 0x02 0x0000", "CHECKMULTISIG DROP 1", ""], -["0 0x02 0x0000 0", "CHECKMULTISIG DROP 1", ""], -["0 0x02 0x0000 0 1", "CHECKMULTISIG DROP 1", ""], -["0 0 0x02 0x0000", "CHECKMULTISIGVERIFY 1", ""], -["0 0x02 0x0000 0", "CHECKMULTISIGVERIFY 1", ""], +["1 0x02 0x0000", "PICK DROP", "", "OK"], +["1 0x02 0x0000", "ROLL DROP 1", "", "OK"], +["0x02 0x0000", "1ADD DROP 1", "", "OK"], +["0x02 0x0000", "1SUB DROP 1", "", "OK"], +["0x02 0x0000", "NEGATE DROP 1", "", "OK"], +["0x02 0x0000", "ABS DROP 1", "", "OK"], +["0x02 0x0000", "NOT DROP 1", "", "OK"], +["0x02 0x0000", "0NOTEQUAL DROP 1", "", "OK"], + +["0 0x02 0x0000", "ADD DROP 1", "", "OK"], +["0x02 0x0000 0", "ADD DROP 1", "", "OK"], +["0 0x02 0x0000", "SUB DROP 1", "", "OK"], +["0x02 0x0000 0", "SUB DROP 1", "", "OK"], +["0 0x02 0x0000", "BOOLAND DROP 1", "", "OK"], +["0x02 0x0000 0", "BOOLAND DROP 1", "", "OK"], +["0 0x02 0x0000", "BOOLOR DROP 1", "", "OK"], +["0x02 0x0000 0", "BOOLOR DROP 1", "", "OK"], +["0 0x02 0x0000", "NUMEQUAL DROP 1", "", "OK"], +["0x02 0x0000 1", "NUMEQUAL DROP 1", "", "OK"], +["0 0x02 0x0000", "NUMEQUALVERIFY 1", "", "OK"], +["0x02 0x0000 0", "NUMEQUALVERIFY 1", "", "OK"], +["0 0x02 0x0000", "NUMNOTEQUAL DROP 1", "", "OK"], +["0x02 0x0000 0", "NUMNOTEQUAL DROP 1", "", "OK"], +["0 0x02 0x0000", "LESSTHAN DROP 1", "", "OK"], +["0x02 0x0000 0", "LESSTHAN DROP 1", "", "OK"], +["0 0x02 0x0000", "GREATERTHAN DROP 1", "", "OK"], +["0x02 0x0000 0", "GREATERTHAN DROP 1", "", "OK"], +["0 0x02 0x0000", "LESSTHANOREQUAL DROP 1", "", "OK"], +["0x02 0x0000 0", "LESSTHANOREQUAL DROP 1", "", "OK"], +["0 0x02 0x0000", "GREATERTHANOREQUAL DROP 1", "", "OK"], +["0x02 0x0000 0", "GREATERTHANOREQUAL DROP 1", "", "OK"], +["0 0x02 0x0000", "MIN DROP 1", "", "OK"], +["0x02 0x0000 0", "MIN DROP 1", "", "OK"], +["0 0x02 0x0000", "MAX DROP 1", "", "OK"], +["0x02 0x0000 0", "MAX DROP 1", "", "OK"], + +["0x02 0x0000 0 0", "WITHIN DROP 1", "", "OK"], +["0 0x02 0x0000 0", "WITHIN DROP 1", "", "OK"], +["0 0 0x02 0x0000", "WITHIN DROP 1", "", "OK"], + +["0 0 0x02 0x0000", "CHECKMULTISIG DROP 1", "", "OK"], +["0 0x02 0x0000 0", "CHECKMULTISIG DROP 1", "", "OK"], +["0 0x02 0x0000 0 1", "CHECKMULTISIG DROP 1", "", "OK"], +["0 0 0x02 0x0000", "CHECKMULTISIGVERIFY 1", "", "OK"], +["0 0x02 0x0000 0", "CHECKMULTISIGVERIFY 1", "", "OK"], ["While not really correctly DER encoded, the empty signature is allowed by"], ["STRICTENC to provide a compact way to provide a delibrately invalid signature."], -["0", "0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 CHECKSIG NOT", "STRICTENC"], -["0 0", "1 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 1 CHECKMULTISIG NOT", "STRICTENC"], +["0", "0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 CHECKSIG NOT", "STRICTENC", "OK"], +["0 0", "1 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 1 CHECKMULTISIG NOT", "STRICTENC", "OK"], ["CHECKMULTISIG evaluation order tests. CHECKMULTISIG evaluates signatures and"], ["pubkeys in a specific order, and will exit early if the number of signatures"], @@ -681,241 +681,277 @@ [ "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501", "2 0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT", - "STRICTENC", + "STRICTENC", "OK", "2-of-2 CHECKMULTISIG NOT with the second pubkey invalid, and both signatures validly encoded. Valid pubkey fails, and CHECKMULTISIG exits early, prior to evaluation of second invalid pubkey." ], [ "0 0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501", "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT", - "STRICTENC", + "STRICTENC", "OK", "2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but second signature invalid. Valid pubkey fails, and CHECKMULTISIG exits early, prior to evaluation of second invalid signature." ], ["Increase test coverage for DERSIG"], -["0x4a 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "", "Overly long signature is correctly encoded"], -["0x25 0x30220220000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "", "Missing S is correctly encoded"], -["0x27 0x3024021077777777777777777777777777777777020a7777777777777777777777777777777701", "0 CHECKSIG NOT", "", "S with invalid S length is correctly encoded"], -["0x27 0x302403107777777777777777777777777777777702107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "Non-integer R is correctly encoded"], -["0x27 0x302402107777777777777777777777777777777703107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "Non-integer S is correctly encoded"], -["0x17 0x3014020002107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "Zero-length R is correctly encoded"], -["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "", "Zero-length S is correctly encoded for DERSIG"], -["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "", "Negative S is correctly encoded"], +["0x4a 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "", "OK", "Overly long signature is correctly encoded"], +["0x25 0x30220220000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "", "OK", "Missing S is correctly encoded"], +["0x27 0x3024021077777777777777777777777777777777020a7777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "S with invalid S length is correctly encoded"], +["0x27 0x302403107777777777777777777777777777777702107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "Non-integer R is correctly encoded"], +["0x27 0x302402107777777777777777777777777777777703107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "Non-integer S is correctly encoded"], +["0x17 0x3014020002107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "Zero-length R is correctly encoded"], +["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "", "OK", "Zero-length S is correctly encoded for DERSIG"], +["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "Negative S is correctly encoded"], ["Automatically generated test cases"], [ "0x47 0x304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "", + "OK", "P2PK" ], [ "0x47 0x304402206e05a6fe23c59196ffe176c9ddc31e73a9885638f9d1328d47c0c703863b8876022076feb53811aa5b04e0e79f938eb19906cc5e67548bc555a8e8b8b0fc603d840c01 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508", "DUP HASH160 0x14 0x1018853670f9f3b0582c5b9ee8ce93764ac32b93 EQUALVERIFY CHECKSIG", "", + "OK", "P2PKH" ], [ "0x47 0x304402204710a85181663b32d25c70ec2bbd14adff5ddfff6cb50d09e155ef5f541fc86c0220056b0cc949be9386ecc5f6c2ac0493269031dbb185781db90171b54ac127790281", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", "", + "OK", "P2PK anyonecanpay" ], [ "0x47 0x3044022003fef42ed6c7be8917441218f525a60e2431be978e28b7aca4d7a532cc413ae8022067a1f82c74e8d69291b90d148778405c6257bbcfc2353cc38a3e1f22bf44254601 0x23 0x210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac", "HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL", "P2SH", + "OK", "P2SH(P2PK)" ], [ "0x47 0x304402204e2eb034be7b089534ac9e798cf6a2c79f38bcb34d1b179efd6f2de0841735db022071461beb056b5a7be1819da6a3e3ce3662831ecc298419ca101eb6887b5dd6a401 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac", "HASH160 0x14 0x2df519943d5acc0ef5222091f9dfe3543f489a82 EQUAL", "", + "OK", "P2SH(P2PKH), bad sig but no VERIFY_P2SH" ], [ "0 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402200a358f750934b3feb822f1966bfcd8bbec9eeaa3a8ca941e11ee5960e181fa01022050bf6b5a8e7750f70354ae041cb68a7bade67ec6c3ab19eb359638974410626e01 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", "", + "OK", "3-of-3" ], [ "0 0x47 0x304402205b7d2c2f177ae76cfbbf14d589c113b0b35db753d305d5562dd0b61cbf366cfb02202e56f93c4f08a27f986cd424ffc48a462c3202c4902104d4d0ff98ed28f4bf8001 0x47 0x30440220563e5b3b1fc11662a84bc5ea2a32cc3819703254060ba30d639a1aaf2d5068ad0220601c1f47ddc76d93284dd9ed68f7c9974c4a0ea7cbe8a247d6bc3878567a5fca01 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae", "HASH160 0x14 0xc9e4a896d149702d0d1695434feddd52e24ad78d EQUAL", "P2SH", + "OK", "P2SH(2-of-3)" ], [ "0x47 0x304402200060558477337b9022e70534f1fea71a318caf836812465a2509931c5e7c4987022078ec32bd50ac9e03a349ba953dfd9fe1c8d2dd8bdb1d38ddca844d3d5c78c11801", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "", + "OK", "P2PK with too much R padding but no DERSIG" ], [ "0x48 0x304502202de8c03fc525285c9c535631019a5f2af7c6454fa9eb392a3756a4917c420edd02210046130bf2baf7cfc065067c8b9e33a066d9c15edcea9feb0ca2d233e3597925b401", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "", + "OK", "P2PK with too much S padding but no DERSIG" ], [ "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "", + "OK", "P2PK with too little R padding but no DERSIG" ], [ "0x47 0x30440220005ece1335e7f757a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT", "", + "OK", "P2PK NOT with bad sig with too much R padding but no DERSIG" ], [ "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "", + "OK", "BIP66 example 1, without DERSIG" ], [ "0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", "", + "OK", "BIP66 example 4, without DERSIG" ], [ "0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", "DERSIG", + "OK", "BIP66 example 4, with DERSIG" ], [ "1", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", "", + "OK", "BIP66 example 6, without DERSIG" ], [ "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0x47 0x3044022027c2714269ca5aeecc4d70edc88ba5ee0e3da4986e9216028f489ab4f1b8efce022022bd545b4951215267e4c5ceabd4c5350331b2e4a0b6494c56f361fa5a57a1a201", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG", "", + "OK", "BIP66 example 7, without DERSIG" ], [ "0 0 0x47 0x30440220da6f441dc3b4b2c84cfa8db0cd5b34ed92c9e01686de5a800d40498b70c0dcac02207c2cf91b0c32b860c4cd4994be36cfb84caf8bb7c3a8e4d96a31b2022c5299c501", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT", "", + "OK", "BIP66 example 10, without DERSIG" ], [ "0 0x47 0x30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201 0", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT", "", + "OK", "BIP66 example 12, without DERSIG" ], [ "0 0x47 0x30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201 0", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT", "DERSIG", + "OK", "BIP66 example 12, with DERSIG" ], [ "0x48 0x304402203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022054e1c258c2981cdfba5df1f46661fb6541c44f77ca0092f3600331abfffb12510101", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", "", + "OK", "P2PK with multi-byte hashtype, without DERSIG" ], [ "0x48 0x304502203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022100ab1e3da73d67e32045a20e0b999e049978ea8d6ee5480d485fcf2ce0d03b2ef001", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", "", + "OK", "P2PK with high S but no LOW_S" ], [ "0x47 0x3044022057292e2d4dfe775becdd0a9e6547997c728cdf35390f6a017da56d654d374e4902206b643be2fc53763b4e284845bfea2c597d2dc7759941dce937636c9d341b71ed01", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "", + "OK", "P2PK with hybrid pubkey but no STRICTENC" ], [ "0x47 0x30440220035d554e3153c04950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", "", + "OK", "P2PK NOT with invalid hybrid pubkey but no STRICTENC" ], [ "0 0x47 0x304402202e79441ad1baf5a07fb86bae3753184f6717d9692680947ea8b6e8b777c69af1022079a262e13d868bb5a0964fefe3ba26942e1b0669af1afb55ef3344bc9d4fc4c401", "1 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG", "", + "OK", "1-of-2 with the second 1 hybrid pubkey and no STRICTENC" ], [ "0 0x47 0x304402202e79441ad1baf5a07fb86bae3753184f6717d9692680947ea8b6e8b777c69af1022079a262e13d868bb5a0964fefe3ba26942e1b0669af1afb55ef3344bc9d4fc4c401", "1 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG", "STRICTENC", + "OK", "1-of-2 with the second 1 hybrid pubkey" ], [ "0x47 0x304402206177d513ec2cda444c021a1f4f656fc4c72ba108ae063e157eb86dc3575784940220666fc66702815d0e5413bb9b1df22aed44f5f1efb8b99d41dd5dc9a5be6d205205", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", "", + "OK", "P2PK with undefined hashtype but no STRICTENC" ], [ "0x47 0x304402207409b5b320296e5e2136a7b281a7f803028ca4ca44e2b83eebd46932677725de02202d4eea1c8d3c98e6f42614f54764e6e5e6542e213eb4d079737e9a8b6e9812ec05", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG NOT", "", + "OK", "P2PK NOT with invalid sig and undefined hashtype but no STRICTENC" ], [ "1 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402200a358f750934b3feb822f1966bfcd8bbec9eeaa3a8ca941e11ee5960e181fa01022050bf6b5a8e7750f70354ae041cb68a7bade67ec6c3ab19eb359638974410626e01 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", "", + "OK", "3-of-3 with nonzero dummy but no NULLDUMMY" ], [ "1 0x47 0x304402201bb2edab700a5d020236df174fefed78087697143731f659bea59642c759c16d022061f42cdbae5bcd3e8790f20bf76687443436e94a634321c16a72aa54cbc7c2ea01 0x47 0x304402204bb4a64f2a6e5c7fb2f07fef85ee56fde5e6da234c6a984262307a20e99842d702206f8303aaba5e625d223897e2ffd3f88ef1bcffef55f38dc3768e5f2e94c923f901 0x47 0x3044022040c2809b71fffb155ec8b82fe7a27f666bd97f941207be4e14ade85a1249dd4d02204d56c85ec525dd18e29a0533d5ddf61b6b1bb32980c2f63edf951aebf7a27bfe01", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG NOT", "", + "OK", "3-of-3 NOT with invalid sig and nonzero dummy but no NULLDUMMY" ], [ "0 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901 DUP", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG", "", + "OK", "2-of-2 with two identical keys and sigs pushed using OP_DUP but no SIGPUSHONLY" ], [ "0x47 0x3044022018a2a81a93add5cb5f5da76305718e4ea66045ec4888b28d84cb22fae7f4645b02201e6daa5ed5d2e4b2b2027cf7ffd43d8d9844dd49f74ef86899ec8e669dfd39aa01 NOP8 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac", "HASH160 0x14 0x215640c2f72f0d16b4eced26762035a42ffed39a EQUAL", "", + "OK", "P2SH(P2PK) with non-push scriptSig but no P2SH or SIGPUSHONLY" ], [ "0x47 0x304402203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022054e1c258c2981cdfba5df1f46661fb6541c44f77ca0092f3600331abfffb125101 NOP8", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", "", + "OK", "P2PK with non-push scriptSig but with P2SH validation" ], [ "0 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG", "SIGPUSHONLY", + "OK", "2-of-2 with two identical keys and sigs pushed" ], [ "11 0x47 0x304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "P2SH", + "OK", "P2PK with unnecessary input but no CLEANSTACK" ], [ "11 0x47 0x304402202f7505132be14872581f35d74b759212d9da40482653f1ffa3116c3294a4a51702206adbf347a2240ca41c66522b1a22a41693610b76a8e7770645dc721d1635854f01 0x43 0x410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac", "HASH160 0x14 0x31edc23bdafda4639e669f89ad6b2318dd79d032 EQUAL", "P2SH", + "OK", "P2SH with unnecessary input but no CLEANSTACK" ], [ "0x47 0x304402202f7505132be14872581f35d74b759212d9da40482653f1ffa3116c3294a4a51702206adbf347a2240ca41c66522b1a22a41693610b76a8e7770645dc721d1635854f01 0x43 0x410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac", "HASH160 0x14 0x31edc23bdafda4639e669f89ad6b2318dd79d032 EQUAL", "CLEANSTACK,P2SH", + "OK", "P2SH with CLEANSTACK" ], diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 4ecb56de84981..006d8aa644beb 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -263,7 +263,7 @@ class TestBuilder } public: - TestBuilder(const CScript& redeemScript, const std::string& comment_, int flags_, bool P2SH = false) : scriptPubKey(redeemScript), havePush(false), comment(comment_), flags(flags_), scriptError(-1) + TestBuilder(const CScript& redeemScript, const std::string& comment_, int flags_, bool P2SH = false) : scriptPubKey(redeemScript), havePush(false), comment(comment_), flags(flags_), scriptError(SCRIPT_ERR_OK) { if (P2SH) { creditTx = BuildCreditingTransaction(CScript() << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL); @@ -365,9 +365,8 @@ class TestBuilder array.push_back(FormatScript(spendTx.vin[0].scriptSig)); array.push_back(FormatScript(creditTx.vout[0].scriptPubKey)); array.push_back(FormatScriptFlags(flags)); + array.push_back(FormatScriptError((ScriptError_t)scriptError)); array.push_back(comment); - if (scriptError != -1) - array.push_back(FormatScriptError((ScriptError_t)scriptError)); return array; } @@ -715,7 +714,7 @@ BOOST_AUTO_TEST_CASE(script_valid) { // Read tests from test/data/script_valid.json // Format is an array of arrays - // Inner arrays are [ "scriptSig", "scriptPubKey", "flags" ] + // Inner arrays are [ "scriptSig", "scriptPubKey", "flags", "expected_scripterror" ] // ... where scriptSig and scriptPubKey are stringified // scripts. UniValue tests = read_json(std::string(json_tests::script_valid, json_tests::script_valid + sizeof(json_tests::script_valid))); @@ -735,6 +734,7 @@ BOOST_AUTO_TEST_CASE(script_valid) string scriptPubKeyString = test[1].get_str(); CScript scriptPubKey = ParseScript(scriptPubKeyString); unsigned int scriptflags = ParseScriptFlags(test[2].get_str()); + BOOST_CHECK_EQUAL(test[3].get_str(), "OK"); DoTest(scriptPubKey, scriptSig, scriptflags, true, strTest, SCRIPT_ERR_OK); } @@ -747,7 +747,7 @@ BOOST_AUTO_TEST_CASE(script_invalid) for (unsigned int idx = 0; idx < tests.size(); idx++) { UniValue test = tests[idx]; string strTest = test.write(); - if (test.size() < 3) // Allow size > 2; extra stuff ignored (useful for comments) + if (test.size() < 4) // Allow size > 2; extra stuff ignored (useful for comments) { if (test.size() != 1) { BOOST_ERROR("Bad test: " << strTest); @@ -759,10 +759,7 @@ BOOST_AUTO_TEST_CASE(script_invalid) string scriptPubKeyString = test[1].get_str(); CScript scriptPubKey = ParseScript(scriptPubKeyString); unsigned int scriptflags = ParseScriptFlags(test[2].get_str()); - int scriptError = -1; // Expected script error is optional, and follows comment - if (test.size() >= 5 && test[4].get_str() != "") { - scriptError = ParseScriptError(test[4].get_str()); - } + int scriptError = ParseScriptError(test[3].get_str()); DoTest(scriptPubKey, scriptSig, scriptflags, false, strTest, scriptError); } From 009b503792737ab03aeb6e15060bc4f499500a96 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 5 Apr 2016 15:50:17 +0200 Subject: [PATCH 0100/1802] Get rid of expect in script_tests as it's implied by scripterror --- src/test/script_tests.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 006d8aa644beb..6340af2081f95 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -145,13 +145,14 @@ CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CMu return txSpend; } -void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, int flags, bool expect, const std::string& message, int scriptError) +void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, int flags, const std::string& message, int scriptError) { + bool expect = (scriptError == SCRIPT_ERR_OK); ScriptError err; CMutableTransaction tx = BuildSpendingTransaction(scriptSig, BuildCreditingTransaction(scriptPubKey)); CMutableTransaction tx2 = tx; BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, flags, MutableTransactionSignatureChecker(&tx, 0), &err) == expect, message); - BOOST_CHECK_MESSAGE(scriptError == -1 || err == scriptError, std::string(FormatScriptError(err)) + " where " + std::string(FormatScriptError((ScriptError_t)scriptError)) + " expected: " + message); + BOOST_CHECK_MESSAGE(err == scriptError, std::string(FormatScriptError(err)) + " where " + std::string(FormatScriptError((ScriptError_t)scriptError)) + " expected: " + message); #if defined(HAVE_CONSENSUS_LIB) CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); stream << tx2; @@ -349,11 +350,11 @@ class TestBuilder return *this; } - TestBuilder& Test(bool expect) + TestBuilder& Test() { TestBuilder copy = *this; // Make a copy so we can rollback the push. DoPush(); - DoTest(creditTx.vout[0].scriptPubKey, spendTx.vin[0].scriptSig, flags, expect, comment, expect ? SCRIPT_ERR_OK : scriptError); + DoTest(creditTx.vout[0].scriptPubKey, spendTx.vin[0].scriptSig, flags, comment, scriptError); *this = copy; return *this; } @@ -680,7 +681,7 @@ BOOST_AUTO_TEST_CASE(script_build) std::string strBad; BOOST_FOREACH(TestBuilder& test, good) { - test.Test(true); + test.Test(); std::string str = JSONPrettyPrint(test.GetJSON()); #ifndef UPDATE_JSON_TESTS if (tests_good.count(str) == 0) { @@ -690,7 +691,7 @@ BOOST_AUTO_TEST_CASE(script_build) strGood += str + ",\n"; } BOOST_FOREACH(TestBuilder& test, bad) { - test.Test(false); + test.Test(); std::string str = JSONPrettyPrint(test.GetJSON()); #ifndef UPDATE_JSON_TESTS if (tests_bad.count(str) == 0) { @@ -736,7 +737,7 @@ BOOST_AUTO_TEST_CASE(script_valid) unsigned int scriptflags = ParseScriptFlags(test[2].get_str()); BOOST_CHECK_EQUAL(test[3].get_str(), "OK"); - DoTest(scriptPubKey, scriptSig, scriptflags, true, strTest, SCRIPT_ERR_OK); + DoTest(scriptPubKey, scriptSig, scriptflags, strTest, SCRIPT_ERR_OK); } } @@ -761,7 +762,7 @@ BOOST_AUTO_TEST_CASE(script_invalid) unsigned int scriptflags = ParseScriptFlags(test[2].get_str()); int scriptError = ParseScriptError(test[3].get_str()); - DoTest(scriptPubKey, scriptSig, scriptflags, false, strTest, scriptError); + DoTest(scriptPubKey, scriptSig, scriptflags, strTest, scriptError); } } From dde46d3ae1de18700e089bc1861cf1e18649dc5d Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 5 Apr 2016 16:11:47 +0200 Subject: [PATCH 0101/1802] Merge script_valid and script_invalid tests --- src/Makefile.test.include | 3 +- src/test/data/script_invalid.json | 877 ------------------ .../{script_valid.json => script_tests.json} | 865 +++++++++++++++++ src/test/script_tests.cpp | 601 ++++++------ 4 files changed, 1143 insertions(+), 1203 deletions(-) delete mode 100644 src/test/data/script_invalid.json rename src/test/data/{script_valid.json => script_tests.json} (54%) diff --git a/src/Makefile.test.include b/src/Makefile.test.include index d806fb219e4f8..f025b18c7e690 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -20,11 +20,10 @@ EXTRA_DIST += \ test/data/txcreatesign.hex JSON_TEST_FILES = \ - test/data/script_valid.json \ + test/data/script_tests.json \ test/data/base58_keys_valid.json \ test/data/base58_encode_decode.json \ test/data/base58_keys_invalid.json \ - test/data/script_invalid.json \ test/data/tx_invalid.json \ test/data/tx_valid.json \ test/data/sighash.json diff --git a/src/test/data/script_invalid.json b/src/test/data/script_invalid.json deleted file mode 100644 index 1427cb630a6f2..0000000000000 --- a/src/test/data/script_invalid.json +++ /dev/null @@ -1,877 +0,0 @@ -[ -["Format is: [scriptSig, scriptPubKey, flags, expected_scripterror, ... comments]"], -["It is evaluated as if there was a crediting coinbase transaction with two 0"], -["pushes as scriptSig, and one output of 0 satoshi and given scriptPubKey,"], -["followed by a spending transaction which spends this output as only input (and"], -["correct prevout hash), using the given scriptSig. All nLockTimes are 0, all"], -["nSequences are max."], - -["", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE", "Test the test: we should have an empty stack after scriptSig evaluation"], -[" ", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE", "and multiple spaces should not change that."], -[" ", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE"], -[" ", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE"], - -["", "", "P2SH,STRICTENC","EVAL_FALSE"], -["", "NOP", "P2SH,STRICTENC","EVAL_FALSE"], -["", "NOP DEPTH", "P2SH,STRICTENC", "EVAL_FALSE"], -["NOP", "", "P2SH,STRICTENC", "EVAL_FALSE"], -["NOP", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE"], -["NOP","NOP", "P2SH,STRICTENC", "EVAL_FALSE"], -["NOP","NOP DEPTH", "P2SH,STRICTENC", "EVAL_FALSE"], - -["DEPTH", "", "P2SH,STRICTENC", "EVAL_FALSE"], - -["0x4c01","0x01 NOP", "P2SH,STRICTENC","BAD_OPCODE", "PUSHDATA1 with not enough bytes"], -["0x4d0200ff","0x01 NOP", "P2SH,STRICTENC","BAD_OPCODE", "PUSHDATA2 with not enough bytes"], -["0x4e03000000ffff","0x01 NOP", "P2SH,STRICTENC","BAD_OPCODE", "PUSHDATA4 with not enough bytes"], - -["1", "IF 0x50 ENDIF 1", "P2SH,STRICTENC","BAD_OPCODE", "0x50 is reserved"], -["0x52", "0x5f ADD 0x60 EQUAL", "P2SH,STRICTENC","EVAL_FALSE", "0x51 through 0x60 push 1 through 16 onto stack"], -["0","NOP", "P2SH,STRICTENC","EVAL_FALSE",""], -["1", "IF VER ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "VER non-functional"], -["0", "IF VERIF ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "VERIF illegal everywhere"], -["0", "IF ELSE 1 ELSE VERIF ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "VERIF illegal everywhere"], -["0", "IF VERNOTIF ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "VERNOTIF illegal everywhere"], -["0", "IF ELSE 1 ELSE VERNOTIF ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "VERNOTIF illegal everywhere"], - -["1 IF", "1 ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "IF/ENDIF can't span scriptSig/scriptPubKey"], -["1 IF 0 ENDIF", "1 ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], -["1 ELSE 0 ENDIF", "1", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], -["0 NOTIF", "123", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], - -["0", "DUP IF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], -["0", "IF 1 ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], -["0", "DUP IF ELSE ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], -["0", "IF 1 ELSE ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], -["0", "NOTIF ELSE 1 ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], - -["0 1", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], -["0 0", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], -["1 0", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], -["0 1", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], - -["0 0", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], -["0 1", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], -["1 1", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], -["0 0", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], - -["1", "IF RETURN ELSE ELSE 1 ENDIF", "P2SH,STRICTENC", "OP_RETURN", "Multiple ELSEs"], -["1", "IF 1 ELSE ELSE RETURN ENDIF", "P2SH,STRICTENC", "OP_RETURN"], - -["1", "ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "Malformed IF/ELSE/ENDIF sequence"], -["1", "ELSE ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], -["1", "ENDIF ELSE", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], -["1", "ENDIF ELSE IF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], -["1", "IF ELSE ENDIF ELSE", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], -["1", "IF ELSE ENDIF ELSE ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], -["1", "IF ENDIF ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], -["1", "IF ELSE ELSE ENDIF ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], - -["1", "RETURN", "P2SH,STRICTENC", "OP_RETURN"], -["1", "DUP IF RETURN ENDIF", "P2SH,STRICTENC", "OP_RETURN"], - -["1", "RETURN 'data'", "P2SH,STRICTENC", "OP_RETURN", "canonical prunable txout format"], -["0 IF", "RETURN ENDIF 1", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "still prunable because IF/ENDIF can't span scriptSig/scriptPubKey"], - -["0", "VERIFY 1", "P2SH,STRICTENC", "VERIFY"], -["1", "VERIFY", "P2SH,STRICTENC", "EVAL_FALSE"], -["1", "VERIFY 0", "P2SH,STRICTENC", "EVAL_FALSE"], - -["1 TOALTSTACK", "FROMALTSTACK 1", "P2SH,STRICTENC", "INVALID_ALTSTACK_OPERATION", "alt stack not shared between sig/pubkey"], - -["IFDUP", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["DROP", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["DUP", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1", "DUP 1 ADD 2 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], -["NOP", "NIP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["NOP", "1 NIP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["NOP", "1 0 NIP", "P2SH,STRICTENC", "EVAL_FALSE"], -["NOP", "OVER 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1", "OVER", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["0 1", "OVER DEPTH 3 EQUALVERIFY", "P2SH,STRICTENC", "EVAL_FALSE"], -["19 20 21", "PICK 19 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["NOP", "0 PICK", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1", "-1 PICK", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["19 20 21", "0 PICK 20 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "EQUALVERIFY"], -["19 20 21", "1 PICK 21 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "EQUALVERIFY"], -["19 20 21", "2 PICK 22 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "EQUALVERIFY"], -["NOP", "0 ROLL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1", "-1 ROLL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["19 20 21", "0 ROLL 20 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "EQUALVERIFY"], -["19 20 21", "1 ROLL 21 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "EQUALVERIFY"], -["19 20 21", "2 ROLL 22 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "EQUALVERIFY"], -["NOP", "ROT 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["NOP", "1 ROT 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["NOP", "1 2 ROT 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["NOP", "0 1 2 ROT", "P2SH,STRICTENC", "EVAL_FALSE"], -["NOP", "SWAP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1", "SWAP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["0 1", "SWAP 1 EQUALVERIFY", "P2SH,STRICTENC", "EQUALVERIFY"], -["NOP", "TUCK 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1", "TUCK 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1 0", "TUCK DEPTH 3 EQUALVERIFY SWAP 2DROP", "P2SH,STRICTENC", "EVAL_FALSE"], -["NOP", "2DUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1", "2DUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["NOP", "3DUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1", "3DUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1 2", "3DUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["NOP", "2OVER 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1", "2 3 2OVER 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["NOP", "2SWAP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1", "2 3 2SWAP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], - -["'a' 'b'", "CAT", "P2SH,STRICTENC", "DISABLED_OPCODE", "CAT disabled"], -["'a' 'b' 0", "IF CAT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "CAT disabled"], -["'abc' 1 1", "SUBSTR", "P2SH,STRICTENC", "DISABLED_OPCODE", "SUBSTR disabled"], -["'abc' 1 1 0", "IF SUBSTR ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "SUBSTR disabled"], -["'abc' 2 0", "IF LEFT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "LEFT disabled"], -["'abc' 2 0", "IF RIGHT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "RIGHT disabled"], - -["NOP", "SIZE 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], - -["'abc'", "IF INVERT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "INVERT disabled"], -["1 2 0 IF AND ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "AND disabled"], -["1 2 0 IF OR ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "OR disabled"], -["1 2 0 IF XOR ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "XOR disabled"], -["2 0 IF 2MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "2MUL disabled"], -["2 0 IF 2DIV ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "2DIV disabled"], -["2 2 0 IF MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "MUL disabled"], -["2 2 0 IF DIV ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "DIV disabled"], -["2 2 0 IF MOD ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "MOD disabled"], -["2 2 0 IF LSHIFT ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "LSHIFT disabled"], -["2 2 0 IF RSHIFT ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "RSHIFT disabled"], - -["", "EQUAL NOT", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "EQUAL must error when there are no stack items"], -["0", "EQUAL NOT", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "EQUAL must error when there are not 2 stack items"], -["0 1","EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], -["1 1 ADD", "0 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], -["11 1 ADD 12 SUB", "11 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], - -["2147483648 0 ADD", "NOP", "P2SH,STRICTENC", "UNKNOWN_ERROR", "arithmetic operands must be in range [-2^31...2^31] "], -["-2147483648 0 ADD", "NOP", "P2SH,STRICTENC", "UNKNOWN_ERROR", "arithmetic operands must be in range [-2^31...2^31] "], -["2147483647 DUP ADD", "4294967294 NUMEQUAL", "P2SH,STRICTENC", "UNKNOWN_ERROR", "NUMEQUAL must be in numeric range"], -["'abcdef' NOT", "0 EQUAL", "P2SH,STRICTENC", "UNKNOWN_ERROR", "NOT is an arithmetic operand"], - -["2 DUP MUL", "4 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], -["2 DUP DIV", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], -["2 2MUL", "4 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], -["2 2DIV", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], -["7 3 MOD", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], -["2 2 LSHIFT", "8 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], -["2 1 RSHIFT", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], - -["1","NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 2 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], -["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_11' EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], - -["Ensure 100% coverage of discouraged NOPS"], -["1", "NOP1", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], -["1", "CHECKLOCKTIMEVERIFY", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], -["1", "NOP3", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], -["1", "NOP4", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], -["1", "NOP5", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], -["1", "NOP6", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], -["1", "NOP7", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], -["1", "NOP8", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], -["1", "NOP9", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], -["1", "NOP10", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], - -["NOP10", "1", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS", "Discouraged NOP10 in scriptSig"], - -["1 0x01 0xb9", "HASH160 0x14 0x15727299b05b45fdaf9ac9ecf7565cfe27c3e567 EQUAL", - "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS", "Discouraged NOP10 in redeemScript"], - -["0x50","1", "P2SH,STRICTENC", "BAD_OPCODE", "opcode 0x50 is reserved"], -["1", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "opcodes above NOP10 invalid if executed"], -["1", "IF 0xbb ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xbe ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xbf ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xc0 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xc1 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xc2 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xc3 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xc4 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xc5 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xc6 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xc7 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xc8 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xc9 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xca ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xcb ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xcc ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xcd ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xce ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xcf ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xd0 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xd1 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xd2 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xd3 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xd4 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xd5 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xd6 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xd7 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xd8 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xd9 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xda ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xdb ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xdc ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xdd ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xde ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xdf ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xe0 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xe1 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xe2 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xe3 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xe4 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xe5 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xe6 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xe7 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xe8 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xe9 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xea ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xeb ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xec ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xed ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xee ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xef ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xf0 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xf1 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xf2 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xf3 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xf4 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xf5 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xf6 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xf7 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xf8 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xf9 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xfa ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xfb ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xfc ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xfd ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xfe ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xff ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], - -["1 IF 1 ELSE", "0xff ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "invalid because scriptSig and scriptPubKey are processed separately"], - -["NOP", "RIPEMD160", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["NOP", "SHA1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["NOP", "SHA256", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["NOP", "HASH160", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["NOP", "HASH256", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], - -["NOP", -"'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'", -"P2SH,STRICTENC", -"PUSH_SIZE", -">520 byte push"], -["0", -"IF 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' ENDIF 1", -"P2SH,STRICTENC", -"PUSH_SIZE", -">520 byte push in non-executed IF branch"], -["1", -"0x61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", -"P2SH,STRICTENC", -"OP_COUNT", -">201 opcodes executed. 0x61 is NOP"], -["0", -"IF 0x6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161 ENDIF 1", -"P2SH,STRICTENC", -"OP_COUNT", -">201 opcodes including non-executed IF branch. 0x61 is NOP"], -["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", -"1 2 3 4 5 6 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", -"P2SH,STRICTENC", -"STACK_SIZE", -">1,000 stack size (0x6f is 3DUP)"], -["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", -"1 TOALTSTACK 2 TOALTSTACK 3 4 5 6 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", -"P2SH,STRICTENC", -"STACK_SIZE", -">1,000 stack+altstack size"], -["NOP", -"0 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f 2DUP 0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", -"P2SH,STRICTENC", -"SCRIPT_SIZE", -"10,001-byte scriptPubKey"], - -["NOP1","NOP10", "P2SH,STRICTENC", "EVAL_FALSE"], - -["1","VER", "P2SH,STRICTENC", "BAD_OPCODE", "OP_VER is reserved"], -["1","VERIF", "P2SH,STRICTENC", "BAD_OPCODE", "OP_VERIF is reserved"], -["1","VERNOTIF", "P2SH,STRICTENC", "BAD_OPCODE", "OP_VERNOTIF is reserved"], -["1","RESERVED", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED is reserved"], -["1","RESERVED1", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED1 is reserved"], -["1","RESERVED2", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED2 is reserved"], -["1","0xba", "P2SH,STRICTENC", "BAD_OPCODE", "0xba == OP_NOP10 + 1"], - -["2147483648", "1ADD 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers"], -["2147483648", "NEGATE 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers"], -["-2147483648", "1ADD 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "Because we use a sign bit, -2147483648 is also 5 bytes"], -["2147483647", "1ADD 1SUB 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers, even if the result is 4-bytes"], -["2147483648", "1SUB 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers, even if the result is 4-bytes"], - -["2147483648 1", "BOOLOR 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do BOOLOR on 5-byte integers (but we can still do IF etc)"], -["2147483648 1", "BOOLAND 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do BOOLAND on 5-byte integers"], - -["1", "1 ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "ENDIF without IF"], -["1", "IF 1", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "IF without ENDIF"], -["1 IF 1", "ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "IFs don't carry over"], - -["NOP", "IF 1 ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "The following tests check the if(stack.size() < N) tests in each opcode"], -["NOP", "NOTIF 1 ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "They are here to catch copy-and-paste errors"], -["NOP", "VERIFY 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "Most of them are duplicated elsewhere,"], - -["NOP", "TOALTSTACK 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "but, hey, more is always better, right?"], -["1", "FROMALTSTACK", "P2SH,STRICTENC", "INVALID_ALTSTACK_OPERATION"], -["1", "2DROP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1", "2DUP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1 1", "3DUP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1 1 1", "2OVER", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1 1 1 1 1", "2ROT", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1 1 1", "2SWAP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["NOP", "IFDUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["NOP", "DROP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["NOP", "DUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1", "NIP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1", "OVER", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1 1 1 3", "PICK", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["0", "PICK 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1 1 1 3", "ROLL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["0", "ROLL 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1 1", "ROT", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1", "SWAP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1", "TUCK", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], - -["NOP", "SIZE 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], - -["1", "EQUAL 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1", "EQUALVERIFY 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], - -["NOP", "1ADD 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["NOP", "1SUB 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["NOP", "NEGATE 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["NOP", "ABS 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["NOP", "NOT 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["NOP", "0NOTEQUAL 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], - -["1", "ADD", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1", "SUB", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1", "BOOLAND", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1", "BOOLOR", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1", "NUMEQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1", "NUMEQUALVERIFY 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1", "NUMNOTEQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1", "LESSTHAN", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1", "GREATERTHAN", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1", "LESSTHANOREQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1", "GREATERTHANOREQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1", "MIN", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1", "MAX", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["1 1", "WITHIN", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], - -["NOP", "RIPEMD160 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["NOP", "SHA1 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["NOP", "SHA256 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["NOP", "HASH160 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], -["NOP", "HASH256 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], - -["Increase CHECKSIG and CHECKMULTISIG negative test coverage"], -["", "CHECKSIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKSIG must error when there are no stack items"], -["0", "CHECKSIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKSIG must error when there are not 2 stack items"], -["", "CHECKMULTISIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKMULTISIG must error when there are no stack items"], -["", "-1 CHECKMULTISIG NOT", "STRICTENC", "PUBKEY_COUNT", "CHECKMULTISIG must error when the specified number of pubkeys is negative"], -["", "1 CHECKMULTISIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKMULTISIG must error when there are not enough pubkeys on the stack"], -["", "-1 0 CHECKMULTISIG NOT", "STRICTENC", "SIG_COUNT", "CHECKMULTISIG must error when the specified number of signatures is negative"], -["", "1 'pk1' 1 CHECKMULTISIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKMULTISIG must error when there are not enough signatures on the stack"], -["", "'dummy' 'sig1' 1 'pk1' 1 CHECKMULTISIG IF 1 ENDIF", "", "EVAL_FALSE", "CHECKMULTISIG must push false to stack when signature is invalid when NOT in strict enc mode"], - -["", -"0 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG", -"P2SH,STRICTENC", -"OP_COUNT", -"202 CHECKMULTISIGS, fails due to 201 op limit"], - -["1", -"0 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY", -"P2SH,STRICTENC", -"INVALID_STACK_OPERATION", -""], - -["", -"NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG", -"P2SH,STRICTENC", -"OP_COUNT", -"Fails due to 201 sig op limit"], - -["1", -"NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY", -"P2SH,STRICTENC", -"OP_COUNT", -""], - - -["0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21", "21 CHECKMULTISIG 1", "P2SH,STRICTENC", "PUBKEY_COUNT", "nPubKeys > 20"], -["0 'sig' 1 0", "CHECKMULTISIG 1", "P2SH,STRICTENC", "SIG_COUNT", "nSigs > nPubKeys"], - - -["NOP 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "SIG_PUSHONLY", "Tests for Script.IsPushOnly()"], -["NOP1 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "SIG_PUSHONLY"], - -["0 0x01 0x50", "HASH160 0x14 0xece424a6bb6ddf4db592c0faed60685047a361b1 EQUAL", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED in P2SH should fail"], -["0 0x01 VER", "HASH160 0x14 0x0f4d7845db968f2a81b530b6f3c1d6246d4c7e01 EQUAL", "P2SH,STRICTENC", "BAD_OPCODE", "OP_VER in P2SH should fail"], - -["0x00", "'00' EQUAL", "P2SH,STRICTENC", "EVAL_FALSE", "Basic OP_0 execution"], - -["MINIMALDATA enforcement for PUSHDATAs"], - -["0x4c 0x00", "DROP 1", "MINIMALDATA", "MINIMALDATA", "Empty vector minimally represented by OP_0"], -["0x01 0x81", "DROP 1", "MINIMALDATA", "MINIMALDATA", "-1 minimally represented by OP_1NEGATE"], -["0x01 0x01", "DROP 1", "MINIMALDATA", "MINIMALDATA", "1 to 16 minimally represented by OP_1 to OP_16"], -["0x01 0x02", "DROP 1", "MINIMALDATA", "MINIMALDATA"], -["0x01 0x03", "DROP 1", "MINIMALDATA", "MINIMALDATA"], -["0x01 0x04", "DROP 1", "MINIMALDATA", "MINIMALDATA"], -["0x01 0x05", "DROP 1", "MINIMALDATA", "MINIMALDATA"], -["0x01 0x06", "DROP 1", "MINIMALDATA", "MINIMALDATA"], -["0x01 0x07", "DROP 1", "MINIMALDATA", "MINIMALDATA"], -["0x01 0x08", "DROP 1", "MINIMALDATA", "MINIMALDATA"], -["0x01 0x09", "DROP 1", "MINIMALDATA", "MINIMALDATA"], -["0x01 0x0a", "DROP 1", "MINIMALDATA", "MINIMALDATA"], -["0x01 0x0b", "DROP 1", "MINIMALDATA", "MINIMALDATA"], -["0x01 0x0c", "DROP 1", "MINIMALDATA", "MINIMALDATA"], -["0x01 0x0d", "DROP 1", "MINIMALDATA", "MINIMALDATA"], -["0x01 0x0e", "DROP 1", "MINIMALDATA", "MINIMALDATA"], -["0x01 0x0f", "DROP 1", "MINIMALDATA", "MINIMALDATA"], -["0x01 0x10", "DROP 1", "MINIMALDATA", "MINIMALDATA"], - -["0x4c 0x48 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "DROP 1", "MINIMALDATA", - "MINIMALDATA", - "PUSHDATA1 of 72 bytes minimally represented by direct push"], - -["0x4d 0xFF00 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "DROP 1", "MINIMALDATA", - "MINIMALDATA", - "PUSHDATA2 of 255 bytes minimally represented by PUSHDATA1"], - -["0x4e 0x00010000 0x11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "DROP 1", "MINIMALDATA", - "MINIMALDATA", - "PUSHDATA4 of 256 bytes minimally represented by PUSHDATA2"], - -["MINIMALDATA enforcement for numeric arguments"], - -["0x01 0x00", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals 0"], -["0x02 0x0000", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals 0"], -["0x01 0x80", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "0x80 (negative zero) numequals 0"], -["0x02 0x0080", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals 0"], -["0x02 0x0500", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals 5"], -["0x03 0x050000", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals 5"], -["0x02 0x0580", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals -5"], -["0x03 0x050080", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals -5"], -["0x03 0xff7f80", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "Minimal encoding is 0xffff"], -["0x03 0xff7f00", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "Minimal encoding is 0xff7f"], -["0x04 0xffff7f80", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "Minimal encoding is 0xffffff"], -["0x04 0xffff7f00", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "Minimal encoding is 0xffff7f"], - -["Test every numeric-accepting opcode for correct handling of the numeric minimal encoding rule"], - -["1 0x02 0x0000", "PICK DROP", "MINIMALDATA", "UNKNOWN_ERROR"], -["1 0x02 0x0000", "ROLL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0x02 0x0000", "1ADD DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0x02 0x0000", "1SUB DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0x02 0x0000", "NEGATE DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0x02 0x0000", "ABS DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0x02 0x0000", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0x02 0x0000", "0NOTEQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], - -["0 0x02 0x0000", "ADD DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0x02 0x0000 0", "ADD DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0 0x02 0x0000", "SUB DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0x02 0x0000 0", "SUB DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0 0x02 0x0000", "BOOLAND DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0x02 0x0000 0", "BOOLAND DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0 0x02 0x0000", "BOOLOR DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0x02 0x0000 0", "BOOLOR DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0 0x02 0x0000", "NUMEQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0x02 0x0000 1", "NUMEQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0 0x02 0x0000", "NUMEQUALVERIFY 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0x02 0x0000 0", "NUMEQUALVERIFY 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0 0x02 0x0000", "NUMNOTEQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0x02 0x0000 0", "NUMNOTEQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0 0x02 0x0000", "LESSTHAN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0x02 0x0000 0", "LESSTHAN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0 0x02 0x0000", "GREATERTHAN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0x02 0x0000 0", "GREATERTHAN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0 0x02 0x0000", "LESSTHANOREQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0x02 0x0000 0", "LESSTHANOREQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0 0x02 0x0000", "GREATERTHANOREQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0x02 0x0000 0", "GREATERTHANOREQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0 0x02 0x0000", "MIN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0x02 0x0000 0", "MIN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0 0x02 0x0000", "MAX DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0x02 0x0000 0", "MAX DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], - -["0x02 0x0000 0 0", "WITHIN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0 0x02 0x0000 0", "WITHIN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0 0 0x02 0x0000", "WITHIN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], - -["0 0 0x02 0x0000", "CHECKMULTISIG DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0 0x02 0x0000 0", "CHECKMULTISIG DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0 0x02 0x0000 0 1", "CHECKMULTISIG DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0 0 0x02 0x0000", "CHECKMULTISIGVERIFY 1", "MINIMALDATA", "UNKNOWN_ERROR"], -["0 0x02 0x0000 0", "CHECKMULTISIGVERIFY 1", "MINIMALDATA", "UNKNOWN_ERROR"], - - -["Order of CHECKMULTISIG evaluation tests, inverted by swapping the order of"], -["pubkeys/signatures so they fail due to the STRICTENC rules on validly encoded"], -["signatures and pubkeys."], -[ - "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501", - "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0 2 CHECKMULTISIG NOT", - "STRICTENC", - "PUBKEYTYPE", - "2-of-2 CHECKMULTISIG NOT with the first pubkey invalid, and both signatures validly encoded." -], -[ - "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 1", - "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT", - "STRICTENC", - "SIG_DER", - "2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but first signature invalid." -], -[ - "0 0x47 0x304402205451ce65ad844dbb978b8bdedf5082e33b43cae8279c30f2c74d9e9ee49a94f802203fe95a7ccf74da7a232ee523ef4a53cb4d14bdd16289680cdb97a63819b8f42f01 0x46 0x304402205451ce65ad844dbb978b8bdedf5082e33b43cae8279c30f2c74d9e9ee49a94f802203fe95a7ccf74da7a232ee523ef4a53cb4d14bdd16289680cdb97a63819b8f42f", - "2 0x21 0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5 0x21 0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5 0x21 0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5 3 CHECKMULTISIG", - "P2SH,STRICTENC", - "SIG_DER", - "2-of-3 with one valid and one invalid signature due to parse error, nSigs > validSigs" -], - -["Increase DERSIG test coverage"], -["0x4a 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Overly long signature is incorrectly encoded for DERSIG"], -["0x25 0x30220220000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Missing S is incorrectly encoded for DERSIG"], -["0x27 0x3024021077777777777777777777777777777777020a7777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "S with invalid S length is incorrectly encoded for DERSIG"], -["0x27 0x302403107777777777777777777777777777777702107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Non-integer R is incorrectly encoded for DERSIG"], -["0x27 0x302402107777777777777777777777777777777703107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Non-integer S is incorrectly encoded for DERSIG"], -["0x17 0x3014020002107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Zero-length R is incorrectly encoded for DERSIG"], -["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Zero-length S is incorrectly encoded for DERSIG"], -["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Negative S is incorrectly encoded for DERSIG"], - -["Automatically generated test cases"], -[ - "0x47 0x304402200a5c6163f07b8c3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001", - "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", - "", - "EVAL_FALSE", - "P2PK, bad sig" -], -[ - "0x47 0x3044022034bb0494b50b8ef130e2185bb220265b9284ef5b4b8a8da4d8415df489c83b5102206259a26d9cc0a125ac26af6153b17c02956855ebe1467412f066e402f5f05d1201 0x21 0x03363d90d446b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640", - "DUP HASH160 0x14 0xc0834c0c158f53be706d234c38fd52de7eece656 EQUALVERIFY CHECKSIG", - "", - "EQUALVERIFY", - "P2PKH, bad pubkey" -], -[ - "0x47 0x304402204710a85181663b32d25c70ec2bbd14adff5ddfff6cb50d09e155ef5f541fc86c0220056b0cc949be9386ecc5f6c2ac0493269031dbb185781db90171b54ac127790201", - "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", - "", - "EVAL_FALSE", - "P2PK anyonecanpay marked with normal hashtype" -], -[ - "0x47 0x3044022003fef42ed6c7be8917441218f525a60e2431be978e28b7aca4d7a532cc413ae8022067a1f82c74e8d69291b90d148778405c6257bbcfc2353cc38a3e1f22bf44254601 0x23 0x210279be667ef9dcbbac54a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac", - "HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL", - "P2SH", - "EVAL_FALSE", - "P2SH(P2PK), bad redeemscript" -], -[ - "0x47 0x304402204e2eb034be7b089534ac9e798cf6a2c79f38bcb34d1b179efd6f2de0841735db022071461beb056b5a7be1819da6a3e3ce3662831ecc298419ca101eb6887b5dd6a401 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac", - "HASH160 0x14 0x2df519943d5acc0ef5222091f9dfe3543f489a82 EQUAL", - "P2SH", - "EQUALVERIFY", - "P2SH(P2PKH), bad sig" -], -[ - "0 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402200a358f750934b3feb822f1966bfcd8bbec9eeaa3a8ca941e11ee5960e181fa01022050bf6b5a8e7750f70354ae041cb68a7bade67ec6c3ab19eb359638974410626e01 0", - "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", - "", - "EVAL_FALSE", - "3-of-3, 2 sigs" -], -[ - "0 0x47 0x304402205b7d2c2f177ae76cfbbf14d589c113b0b35db753d305d5562dd0b61cbf366cfb02202e56f93c4f08a27f986cd424ffc48a462c3202c4902104d4d0ff98ed28f4bf8001 0 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae", - "HASH160 0x14 0xc9e4a896d149702d0d1695434feddd52e24ad78d EQUAL", - "P2SH", - "EVAL_FALSE", - "P2SH(2-of-3), 1 sig" -], -[ - "0x47 0x304402200060558477337b9022e70534f1fea71a318caf836812465a2509931c5e7c4987022078ec32bd50ac9e03a349ba953dfd9fe1c8d2dd8bdb1d38ddca844d3d5c78c11801", - "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", - "DERSIG", - "SIG_DER", - "P2PK with too much R padding" -], -[ - "0x48 0x304502202de8c03fc525285c9c535631019a5f2af7c6454fa9eb392a3756a4917c420edd02210046130bf2baf7cfc065067c8b9e33a066d9c15edcea9feb0ca2d233e3597925b401", - "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", - "DERSIG", - "SIG_DER", - "P2PK with too much S padding" -], -[ - "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201", - "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", - "DERSIG", - "SIG_DER", - "P2PK with too little R padding" -], -[ - "0x47 0x30440220005ece1335e7f757a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601", - "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT", - "DERSIG", - "SIG_DER", - "P2PK NOT with bad sig with too much R padding" -], -[ - "0x47 0x30440220005ece1335e7f657a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601", - "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT", - "", - "EVAL_FALSE", - "P2PK NOT with too much R padding but no DERSIG" -], -[ - "0x47 0x30440220005ece1335e7f657a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601", - "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT", - "DERSIG", - "SIG_DER", - "P2PK NOT with too much R padding" -], -[ - "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201", - "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", - "DERSIG", - "SIG_DER", - "BIP66 example 1, with DERSIG" -], -[ - "0x47 0x304402208e43c0b91f7c1e5bc58e41c8185f8a6086e111b0090187968a86f2822462d3c902200a58f4076b1133b18ff1dc83ee51676e44c60cc608d9534e0df5ace0424fc0be01", - "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", - "", - "EVAL_FALSE", - "BIP66 example 2, without DERSIG" -], -[ - "0x47 0x304402208e43c0b91f7c1e5bc58e41c8185f8a6086e111b0090187968a86f2822462d3c902200a58f4076b1133b18ff1dc83ee51676e44c60cc608d9534e0df5ace0424fc0be01", - "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", - "DERSIG", - "SIG_DER", - "BIP66 example 2, with DERSIG" -], -[ - "0", - "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", - "", - "EVAL_FALSE", - "BIP66 example 3, without DERSIG" -], -[ - "0", - "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", - "DERSIG", - "EVAL_FALSE", - "BIP66 example 3, with DERSIG" -], -[ - "1", - "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", - "", - "EVAL_FALSE", - "BIP66 example 5, without DERSIG" -], -[ - "1", - "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", - "DERSIG", - "SIG_DER", - "BIP66 example 5, with DERSIG" -], -[ - "1", - "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", - "DERSIG", - "SIG_DER", - "BIP66 example 6, with DERSIG" -], -[ - "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0x47 0x3044022027c2714269ca5aeecc4d70edc88ba5ee0e3da4986e9216028f489ab4f1b8efce022022bd545b4951215267e4c5ceabd4c5350331b2e4a0b6494c56f361fa5a57a1a201", - "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG", - "DERSIG", - "SIG_DER", - "BIP66 example 7, with DERSIG" -], -[ - "0 0x47 0x30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201 0x47 0x3044022079ea80afd538d9ada421b5101febeb6bc874e01dde5bca108c1d0479aec339a4022004576db8f66130d1df686ccf00935703689d69cf539438da1edab208b0d63c4801", - "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT", - "", - "EVAL_FALSE", - "BIP66 example 8, without DERSIG" -], -[ - "0 0x47 0x30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201 0x47 0x3044022079ea80afd538d9ada421b5101febeb6bc874e01dde5bca108c1d0479aec339a4022004576db8f66130d1df686ccf00935703689d69cf539438da1edab208b0d63c4801", - "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT", - "DERSIG", - "SIG_DER", - "BIP66 example 8, with DERSIG" -], -[ - "0 0 0x47 0x3044022081aa9d436f2154e8b6d600516db03d78de71df685b585a9807ead4210bd883490220534bb6bdf318a419ac0749660b60e78d17d515558ef369bf872eff405b676b2e01", - "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG", - "", - "EVAL_FALSE", - "BIP66 example 9, without DERSIG" -], -[ - "0 0 0x47 0x3044022081aa9d436f2154e8b6d600516db03d78de71df685b585a9807ead4210bd883490220534bb6bdf318a419ac0749660b60e78d17d515558ef369bf872eff405b676b2e01", - "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG", - "DERSIG", - "SIG_DER", - "BIP66 example 9, with DERSIG" -], -[ - "0 0 0x47 0x30440220da6f441dc3b4b2c84cfa8db0cd5b34ed92c9e01686de5a800d40498b70c0dcac02207c2cf91b0c32b860c4cd4994be36cfb84caf8bb7c3a8e4d96a31b2022c5299c501", - "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT", - "DERSIG", - "SIG_DER", - "BIP66 example 10, with DERSIG" -], -[ - "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0", - "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG", - "", - "EVAL_FALSE", - "BIP66 example 11, without DERSIG" -], -[ - "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0", - "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG", - "DERSIG", - "EVAL_FALSE", - "BIP66 example 11, with DERSIG" -], -[ - "0x48 0x304402203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022054e1c258c2981cdfba5df1f46661fb6541c44f77ca0092f3600331abfffb12510101", - "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", - "DERSIG", - "SIG_DER", - "P2PK with multi-byte hashtype, with DERSIG" -], -[ - "0x48 0x304502203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022100ab1e3da73d67e32045a20e0b999e049978ea8d6ee5480d485fcf2ce0d03b2ef001", - "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", - "LOW_S", - "SIG_HIGH_S", - "P2PK with high S" -], -[ - "0x47 0x3044022057292e2d4dfe775becdd0a9e6547997c728cdf35390f6a017da56d654d374e4902206b643be2fc53763b4e284845bfea2c597d2dc7759941dce937636c9d341b71ed01", - "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", - "STRICTENC", - "PUBKEYTYPE", - "P2PK with hybrid pubkey" -], -[ - "0x47 0x30440220035d554e3153c14950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101", - "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", - "", - "EVAL_FALSE", - "P2PK NOT with hybrid pubkey but no STRICTENC" -], -[ - "0x47 0x30440220035d554e3153c14950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101", - "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", - "STRICTENC", - "PUBKEYTYPE", - "P2PK NOT with hybrid pubkey" -], -[ - "0x47 0x30440220035d554e3153c04950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101", - "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", - "STRICTENC", - "PUBKEYTYPE", - "P2PK NOT with invalid hybrid pubkey" -], -[ - "0 0x47 0x3044022079c7824d6c868e0e1a273484e28c2654a27d043c8a27f49f52cb72efed0759090220452bbbf7089574fa082095a4fc1b3a16bafcf97a3a34d745fafc922cce66b27201", - "1 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 2 CHECKMULTISIG", - "STRICTENC", - "PUBKEYTYPE", - "1-of-2 with the first 1 hybrid pubkey" -], -[ - "0x47 0x304402206177d513ec2cda444c021a1f4f656fc4c72ba108ae063e157eb86dc3575784940220666fc66702815d0e5413bb9b1df22aed44f5f1efb8b99d41dd5dc9a5be6d205205", - "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", - "STRICTENC", - "SIG_HASHTYPE", - "P2PK with undefined hashtype" -], -[ - "0x47 0x304402207409b5b320296e5e2136a7b281a7f803028ca4ca44e2b83eebd46932677725de02202d4eea1c8d3c98e6f42614f54764e6e5e6542e213eb4d079737e9a8b6e9812ec05", - "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG NOT", - "STRICTENC", - "SIG_HASHTYPE", - "P2PK NOT with invalid sig and undefined hashtype" -], -[ - "1 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402200a358f750934b3feb822f1966bfcd8bbec9eeaa3a8ca941e11ee5960e181fa01022050bf6b5a8e7750f70354ae041cb68a7bade67ec6c3ab19eb359638974410626e01 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901", - "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", - "NULLDUMMY", - "SIG_NULLDUMMY", - "3-of-3 with nonzero dummy" -], -[ - "1 0x47 0x304402201bb2edab700a5d020236df174fefed78087697143731f659bea59642c759c16d022061f42cdbae5bcd3e8790f20bf76687443436e94a634321c16a72aa54cbc7c2ea01 0x47 0x304402204bb4a64f2a6e5c7fb2f07fef85ee56fde5e6da234c6a984262307a20e99842d702206f8303aaba5e625d223897e2ffd3f88ef1bcffef55f38dc3768e5f2e94c923f901 0x47 0x3044022040c2809b71fffb155ec8b82fe7a27f666bd97f941207be4e14ade85a1249dd4d02204d56c85ec525dd18e29a0533d5ddf61b6b1bb32980c2f63edf951aebf7a27bfe01", - "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG NOT", - "NULLDUMMY", - "SIG_NULLDUMMY", - "3-of-3 NOT with invalid sig with nonzero dummy" -], -[ - "0 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901 DUP", - "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG", - "SIGPUSHONLY", - "SIG_PUSHONLY", - "2-of-2 with two identical keys and sigs pushed using OP_DUP" -], -[ - "0x47 0x3044022018a2a81a93add5cb5f5da76305718e4ea66045ec4888b28d84cb22fae7f4645b02201e6daa5ed5d2e4b2b2027cf7ffd43d8d9844dd49f74ef86899ec8e669dfd39aa01 NOP8 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac", - "HASH160 0x14 0x215640c2f72f0d16b4eced26762035a42ffed39a EQUAL", - "P2SH", - "SIG_PUSHONLY", - "P2SH(P2PK) with non-push scriptSig but no SIGPUSHONLY" -], -[ - "0x47 0x3044022018a2a81a93add5cb5f5da76305718e4ea66045ec4888b28d84cb22fae7f4645b02201e6daa5ed5d2e4b2b2027cf7ffd43d8d9844dd49f74ef86899ec8e669dfd39aa01 NOP8 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac", - "HASH160 0x14 0x215640c2f72f0d16b4eced26762035a42ffed39a EQUAL", - "SIGPUSHONLY", - "SIG_PUSHONLY", - "P2SH(P2PK) with non-push scriptSig but not P2SH" -], -[ - "11 0x47 0x304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001", - "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", - "CLEANSTACK,P2SH", - "CLEANSTACK", - "P2PK with unnecessary input" -], -[ - "11 0x47 0x304402202f7505132be14872581f35d74b759212d9da40482653f1ffa3116c3294a4a51702206adbf347a2240ca41c66522b1a22a41693610b76a8e7770645dc721d1635854f01 0x43 0x410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac", - "HASH160 0x14 0x31edc23bdafda4639e669f89ad6b2318dd79d032 EQUAL", - "CLEANSTACK,P2SH", - "CLEANSTACK", - "P2SH with unnecessary input" -], - -["The End"] -] diff --git a/src/test/data/script_valid.json b/src/test/data/script_tests.json similarity index 54% rename from src/test/data/script_valid.json rename to src/test/data/script_tests.json index 4e86ee78ba604..e69cc9e41371e 100644 --- a/src/test/data/script_valid.json +++ b/src/test/data/script_tests.json @@ -701,6 +701,556 @@ ["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "", "OK", "Zero-length S is correctly encoded for DERSIG"], ["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "Negative S is correctly encoded"], +["", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE", "Test the test: we should have an empty stack after scriptSig evaluation"], +[" ", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE", "and multiple spaces should not change that."], +[" ", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE"], +[" ", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE"], + +["", "", "P2SH,STRICTENC","EVAL_FALSE"], +["", "NOP", "P2SH,STRICTENC","EVAL_FALSE"], +["", "NOP DEPTH", "P2SH,STRICTENC", "EVAL_FALSE"], +["NOP", "", "P2SH,STRICTENC", "EVAL_FALSE"], +["NOP", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE"], +["NOP","NOP", "P2SH,STRICTENC", "EVAL_FALSE"], +["NOP","NOP DEPTH", "P2SH,STRICTENC", "EVAL_FALSE"], + +["DEPTH", "", "P2SH,STRICTENC", "EVAL_FALSE"], + +["0x4c01","0x01 NOP", "P2SH,STRICTENC","BAD_OPCODE", "PUSHDATA1 with not enough bytes"], +["0x4d0200ff","0x01 NOP", "P2SH,STRICTENC","BAD_OPCODE", "PUSHDATA2 with not enough bytes"], +["0x4e03000000ffff","0x01 NOP", "P2SH,STRICTENC","BAD_OPCODE", "PUSHDATA4 with not enough bytes"], + +["1", "IF 0x50 ENDIF 1", "P2SH,STRICTENC","BAD_OPCODE", "0x50 is reserved"], +["0x52", "0x5f ADD 0x60 EQUAL", "P2SH,STRICTENC","EVAL_FALSE", "0x51 through 0x60 push 1 through 16 onto stack"], +["0","NOP", "P2SH,STRICTENC","EVAL_FALSE",""], +["1", "IF VER ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "VER non-functional"], +["0", "IF VERIF ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "VERIF illegal everywhere"], +["0", "IF ELSE 1 ELSE VERIF ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "VERIF illegal everywhere"], +["0", "IF VERNOTIF ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "VERNOTIF illegal everywhere"], +["0", "IF ELSE 1 ELSE VERNOTIF ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "VERNOTIF illegal everywhere"], + +["1 IF", "1 ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "IF/ENDIF can't span scriptSig/scriptPubKey"], +["1 IF 0 ENDIF", "1 ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], +["1 ELSE 0 ENDIF", "1", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], +["0 NOTIF", "123", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], + +["0", "DUP IF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], +["0", "IF 1 ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], +["0", "DUP IF ELSE ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], +["0", "IF 1 ELSE ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], +["0", "NOTIF ELSE 1 ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], + +["0 1", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], +["0 0", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], +["1 0", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], +["0 1", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], + +["0 0", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], +["0 1", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], +["1 1", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], +["0 0", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"], + +["1", "IF RETURN ELSE ELSE 1 ENDIF", "P2SH,STRICTENC", "OP_RETURN", "Multiple ELSEs"], +["1", "IF 1 ELSE ELSE RETURN ENDIF", "P2SH,STRICTENC", "OP_RETURN"], + +["1", "ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "Malformed IF/ELSE/ENDIF sequence"], +["1", "ELSE ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], +["1", "ENDIF ELSE", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], +["1", "ENDIF ELSE IF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], +["1", "IF ELSE ENDIF ELSE", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], +["1", "IF ELSE ENDIF ELSE ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], +["1", "IF ENDIF ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], +["1", "IF ELSE ELSE ENDIF ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"], + +["1", "RETURN", "P2SH,STRICTENC", "OP_RETURN"], +["1", "DUP IF RETURN ENDIF", "P2SH,STRICTENC", "OP_RETURN"], + +["1", "RETURN 'data'", "P2SH,STRICTENC", "OP_RETURN", "canonical prunable txout format"], +["0 IF", "RETURN ENDIF 1", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "still prunable because IF/ENDIF can't span scriptSig/scriptPubKey"], + +["0", "VERIFY 1", "P2SH,STRICTENC", "VERIFY"], +["1", "VERIFY", "P2SH,STRICTENC", "EVAL_FALSE"], +["1", "VERIFY 0", "P2SH,STRICTENC", "EVAL_FALSE"], + +["1 TOALTSTACK", "FROMALTSTACK 1", "P2SH,STRICTENC", "INVALID_ALTSTACK_OPERATION", "alt stack not shared between sig/pubkey"], + +["IFDUP", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["DROP", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["DUP", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "DUP 1 ADD 2 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], +["NOP", "NIP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "1 NIP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "1 0 NIP", "P2SH,STRICTENC", "EVAL_FALSE"], +["NOP", "OVER 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "OVER", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["0 1", "OVER DEPTH 3 EQUALVERIFY", "P2SH,STRICTENC", "EVAL_FALSE"], +["19 20 21", "PICK 19 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "0 PICK", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "-1 PICK", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["19 20 21", "0 PICK 20 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "EQUALVERIFY"], +["19 20 21", "1 PICK 21 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "EQUALVERIFY"], +["19 20 21", "2 PICK 22 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "EQUALVERIFY"], +["NOP", "0 ROLL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "-1 ROLL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["19 20 21", "0 ROLL 20 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "EQUALVERIFY"], +["19 20 21", "1 ROLL 21 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "EQUALVERIFY"], +["19 20 21", "2 ROLL 22 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "EQUALVERIFY"], +["NOP", "ROT 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "1 ROT 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "1 2 ROT 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "0 1 2 ROT", "P2SH,STRICTENC", "EVAL_FALSE"], +["NOP", "SWAP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "SWAP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["0 1", "SWAP 1 EQUALVERIFY", "P2SH,STRICTENC", "EQUALVERIFY"], +["NOP", "TUCK 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "TUCK 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1 0", "TUCK DEPTH 3 EQUALVERIFY SWAP 2DROP", "P2SH,STRICTENC", "EVAL_FALSE"], +["NOP", "2DUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "2DUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "3DUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "3DUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1 2", "3DUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "2OVER 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "2 3 2OVER 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "2SWAP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "2 3 2SWAP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], + +["'a' 'b'", "CAT", "P2SH,STRICTENC", "DISABLED_OPCODE", "CAT disabled"], +["'a' 'b' 0", "IF CAT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "CAT disabled"], +["'abc' 1 1", "SUBSTR", "P2SH,STRICTENC", "DISABLED_OPCODE", "SUBSTR disabled"], +["'abc' 1 1 0", "IF SUBSTR ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "SUBSTR disabled"], +["'abc' 2 0", "IF LEFT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "LEFT disabled"], +["'abc' 2 0", "IF RIGHT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "RIGHT disabled"], + +["NOP", "SIZE 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], + +["'abc'", "IF INVERT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "INVERT disabled"], +["1 2 0 IF AND ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "AND disabled"], +["1 2 0 IF OR ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "OR disabled"], +["1 2 0 IF XOR ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "XOR disabled"], +["2 0 IF 2MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "2MUL disabled"], +["2 0 IF 2DIV ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "2DIV disabled"], +["2 2 0 IF MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "MUL disabled"], +["2 2 0 IF DIV ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "DIV disabled"], +["2 2 0 IF MOD ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "MOD disabled"], +["2 2 0 IF LSHIFT ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "LSHIFT disabled"], +["2 2 0 IF RSHIFT ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "RSHIFT disabled"], + +["", "EQUAL NOT", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "EQUAL must error when there are no stack items"], +["0", "EQUAL NOT", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "EQUAL must error when there are not 2 stack items"], +["0 1","EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], +["1 1 ADD", "0 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], +["11 1 ADD 12 SUB", "11 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], + +["2147483648 0 ADD", "NOP", "P2SH,STRICTENC", "UNKNOWN_ERROR", "arithmetic operands must be in range [-2^31...2^31] "], +["-2147483648 0 ADD", "NOP", "P2SH,STRICTENC", "UNKNOWN_ERROR", "arithmetic operands must be in range [-2^31...2^31] "], +["2147483647 DUP ADD", "4294967294 NUMEQUAL", "P2SH,STRICTENC", "UNKNOWN_ERROR", "NUMEQUAL must be in numeric range"], +["'abcdef' NOT", "0 EQUAL", "P2SH,STRICTENC", "UNKNOWN_ERROR", "NOT is an arithmetic operand"], + +["2 DUP MUL", "4 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], +["2 DUP DIV", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], +["2 2MUL", "4 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], +["2 2DIV", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], +["7 3 MOD", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], +["2 2 LSHIFT", "8 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], +["2 1 RSHIFT", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], + +["1","NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 2 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], +["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_11' EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], + +["Ensure 100% coverage of discouraged NOPS"], +["1", "NOP1", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], +["1", "CHECKLOCKTIMEVERIFY", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP3", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP4", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP5", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP6", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP7", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP8", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP9", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP10", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], + +["NOP10", "1", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS", "Discouraged NOP10 in scriptSig"], + +["1 0x01 0xb9", "HASH160 0x14 0x15727299b05b45fdaf9ac9ecf7565cfe27c3e567 EQUAL", + "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS", "Discouraged NOP10 in redeemScript"], + +["0x50","1", "P2SH,STRICTENC", "BAD_OPCODE", "opcode 0x50 is reserved"], +["1", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "opcodes above NOP10 invalid if executed"], +["1", "IF 0xbb ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xbe ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xbf ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xc0 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xc1 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xc2 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xc3 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xc4 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xc5 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xc6 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xc7 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xc8 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xc9 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xca ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xcb ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xcc ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xcd ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xce ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xcf ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xd0 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xd1 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xd2 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xd3 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xd4 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xd5 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xd6 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xd7 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xd8 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xd9 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xda ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xdb ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xdc ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xdd ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xde ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xdf ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xe0 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xe1 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xe2 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xe3 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xe4 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xe5 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xe6 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xe7 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xe8 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xe9 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xea ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xeb ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xec ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xed ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xee ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xef ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xf0 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xf1 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xf2 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xf3 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xf4 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xf5 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xf6 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xf7 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xf8 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xf9 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xfa ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xfb ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xfc ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xfd ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xfe ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xff ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], + +["1 IF 1 ELSE", "0xff ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "invalid because scriptSig and scriptPubKey are processed separately"], + +["NOP", "RIPEMD160", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "SHA1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "SHA256", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "HASH160", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "HASH256", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], + +["NOP", +"'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'", +"P2SH,STRICTENC", +"PUSH_SIZE", +">520 byte push"], +["0", +"IF 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' ENDIF 1", +"P2SH,STRICTENC", +"PUSH_SIZE", +">520 byte push in non-executed IF branch"], +["1", +"0x61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", +"P2SH,STRICTENC", +"OP_COUNT", +">201 opcodes executed. 0x61 is NOP"], +["0", +"IF 0x6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161 ENDIF 1", +"P2SH,STRICTENC", +"OP_COUNT", +">201 opcodes including non-executed IF branch. 0x61 is NOP"], +["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +"1 2 3 4 5 6 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +"P2SH,STRICTENC", +"STACK_SIZE", +">1,000 stack size (0x6f is 3DUP)"], +["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +"1 TOALTSTACK 2 TOALTSTACK 3 4 5 6 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +"P2SH,STRICTENC", +"STACK_SIZE", +">1,000 stack+altstack size"], +["NOP", +"0 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f 2DUP 0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", +"P2SH,STRICTENC", +"SCRIPT_SIZE", +"10,001-byte scriptPubKey"], + +["NOP1","NOP10", "P2SH,STRICTENC", "EVAL_FALSE"], + +["1","VER", "P2SH,STRICTENC", "BAD_OPCODE", "OP_VER is reserved"], +["1","VERIF", "P2SH,STRICTENC", "BAD_OPCODE", "OP_VERIF is reserved"], +["1","VERNOTIF", "P2SH,STRICTENC", "BAD_OPCODE", "OP_VERNOTIF is reserved"], +["1","RESERVED", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED is reserved"], +["1","RESERVED1", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED1 is reserved"], +["1","RESERVED2", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED2 is reserved"], +["1","0xba", "P2SH,STRICTENC", "BAD_OPCODE", "0xba == OP_NOP10 + 1"], + +["2147483648", "1ADD 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers"], +["2147483648", "NEGATE 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers"], +["-2147483648", "1ADD 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "Because we use a sign bit, -2147483648 is also 5 bytes"], +["2147483647", "1ADD 1SUB 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers, even if the result is 4-bytes"], +["2147483648", "1SUB 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers, even if the result is 4-bytes"], + +["2147483648 1", "BOOLOR 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do BOOLOR on 5-byte integers (but we can still do IF etc)"], +["2147483648 1", "BOOLAND 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do BOOLAND on 5-byte integers"], + +["1", "1 ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "ENDIF without IF"], +["1", "IF 1", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "IF without ENDIF"], +["1 IF 1", "ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "IFs don't carry over"], + +["NOP", "IF 1 ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "The following tests check the if(stack.size() < N) tests in each opcode"], +["NOP", "NOTIF 1 ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "They are here to catch copy-and-paste errors"], +["NOP", "VERIFY 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "Most of them are duplicated elsewhere,"], + +["NOP", "TOALTSTACK 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "but, hey, more is always better, right?"], +["1", "FROMALTSTACK", "P2SH,STRICTENC", "INVALID_ALTSTACK_OPERATION"], +["1", "2DROP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "2DUP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1 1", "3DUP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1 1 1", "2OVER", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1 1 1 1 1", "2ROT", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1 1 1", "2SWAP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "IFDUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "DROP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "DUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "NIP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "OVER", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1 1 1 3", "PICK", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["0", "PICK 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1 1 1 3", "ROLL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["0", "ROLL 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1 1", "ROT", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "SWAP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "TUCK", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], + +["NOP", "SIZE 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], + +["1", "EQUAL 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "EQUALVERIFY 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], + +["NOP", "1ADD 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "1SUB 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "NEGATE 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "ABS 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "NOT 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "0NOTEQUAL 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], + +["1", "ADD", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "SUB", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "BOOLAND", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "BOOLOR", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "NUMEQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "NUMEQUALVERIFY 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "NUMNOTEQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "LESSTHAN", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "GREATERTHAN", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "LESSTHANOREQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "GREATERTHANOREQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "MIN", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1", "MAX", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["1 1", "WITHIN", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], + +["NOP", "RIPEMD160 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "SHA1 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "SHA256 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "HASH160 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["NOP", "HASH256 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], + +["Increase CHECKSIG and CHECKMULTISIG negative test coverage"], +["", "CHECKSIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKSIG must error when there are no stack items"], +["0", "CHECKSIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKSIG must error when there are not 2 stack items"], +["", "CHECKMULTISIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKMULTISIG must error when there are no stack items"], +["", "-1 CHECKMULTISIG NOT", "STRICTENC", "PUBKEY_COUNT", "CHECKMULTISIG must error when the specified number of pubkeys is negative"], +["", "1 CHECKMULTISIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKMULTISIG must error when there are not enough pubkeys on the stack"], +["", "-1 0 CHECKMULTISIG NOT", "STRICTENC", "SIG_COUNT", "CHECKMULTISIG must error when the specified number of signatures is negative"], +["", "1 'pk1' 1 CHECKMULTISIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKMULTISIG must error when there are not enough signatures on the stack"], +["", "'dummy' 'sig1' 1 'pk1' 1 CHECKMULTISIG IF 1 ENDIF", "", "EVAL_FALSE", "CHECKMULTISIG must push false to stack when signature is invalid when NOT in strict enc mode"], + +["", +"0 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG", +"P2SH,STRICTENC", +"OP_COUNT", +"202 CHECKMULTISIGS, fails due to 201 op limit"], + +["1", +"0 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY", +"P2SH,STRICTENC", +"INVALID_STACK_OPERATION", +""], + +["", +"NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG", +"P2SH,STRICTENC", +"OP_COUNT", +"Fails due to 201 sig op limit"], + +["1", +"NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY", +"P2SH,STRICTENC", +"OP_COUNT", +""], + + +["0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21", "21 CHECKMULTISIG 1", "P2SH,STRICTENC", "PUBKEY_COUNT", "nPubKeys > 20"], +["0 'sig' 1 0", "CHECKMULTISIG 1", "P2SH,STRICTENC", "SIG_COUNT", "nSigs > nPubKeys"], + + +["NOP 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "SIG_PUSHONLY", "Tests for Script.IsPushOnly()"], +["NOP1 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "SIG_PUSHONLY"], + +["0 0x01 0x50", "HASH160 0x14 0xece424a6bb6ddf4db592c0faed60685047a361b1 EQUAL", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED in P2SH should fail"], +["0 0x01 VER", "HASH160 0x14 0x0f4d7845db968f2a81b530b6f3c1d6246d4c7e01 EQUAL", "P2SH,STRICTENC", "BAD_OPCODE", "OP_VER in P2SH should fail"], + +["0x00", "'00' EQUAL", "P2SH,STRICTENC", "EVAL_FALSE", "Basic OP_0 execution"], + +["MINIMALDATA enforcement for PUSHDATAs"], + +["0x4c 0x00", "DROP 1", "MINIMALDATA", "MINIMALDATA", "Empty vector minimally represented by OP_0"], +["0x01 0x81", "DROP 1", "MINIMALDATA", "MINIMALDATA", "-1 minimally represented by OP_1NEGATE"], +["0x01 0x01", "DROP 1", "MINIMALDATA", "MINIMALDATA", "1 to 16 minimally represented by OP_1 to OP_16"], +["0x01 0x02", "DROP 1", "MINIMALDATA", "MINIMALDATA"], +["0x01 0x03", "DROP 1", "MINIMALDATA", "MINIMALDATA"], +["0x01 0x04", "DROP 1", "MINIMALDATA", "MINIMALDATA"], +["0x01 0x05", "DROP 1", "MINIMALDATA", "MINIMALDATA"], +["0x01 0x06", "DROP 1", "MINIMALDATA", "MINIMALDATA"], +["0x01 0x07", "DROP 1", "MINIMALDATA", "MINIMALDATA"], +["0x01 0x08", "DROP 1", "MINIMALDATA", "MINIMALDATA"], +["0x01 0x09", "DROP 1", "MINIMALDATA", "MINIMALDATA"], +["0x01 0x0a", "DROP 1", "MINIMALDATA", "MINIMALDATA"], +["0x01 0x0b", "DROP 1", "MINIMALDATA", "MINIMALDATA"], +["0x01 0x0c", "DROP 1", "MINIMALDATA", "MINIMALDATA"], +["0x01 0x0d", "DROP 1", "MINIMALDATA", "MINIMALDATA"], +["0x01 0x0e", "DROP 1", "MINIMALDATA", "MINIMALDATA"], +["0x01 0x0f", "DROP 1", "MINIMALDATA", "MINIMALDATA"], +["0x01 0x10", "DROP 1", "MINIMALDATA", "MINIMALDATA"], + +["0x4c 0x48 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "DROP 1", "MINIMALDATA", + "MINIMALDATA", + "PUSHDATA1 of 72 bytes minimally represented by direct push"], + +["0x4d 0xFF00 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "DROP 1", "MINIMALDATA", + "MINIMALDATA", + "PUSHDATA2 of 255 bytes minimally represented by PUSHDATA1"], + +["0x4e 0x00010000 0x11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "DROP 1", "MINIMALDATA", + "MINIMALDATA", + "PUSHDATA4 of 256 bytes minimally represented by PUSHDATA2"], + +["MINIMALDATA enforcement for numeric arguments"], + +["0x01 0x00", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals 0"], +["0x02 0x0000", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals 0"], +["0x01 0x80", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "0x80 (negative zero) numequals 0"], +["0x02 0x0080", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals 0"], +["0x02 0x0500", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals 5"], +["0x03 0x050000", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals 5"], +["0x02 0x0580", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals -5"], +["0x03 0x050080", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals -5"], +["0x03 0xff7f80", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "Minimal encoding is 0xffff"], +["0x03 0xff7f00", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "Minimal encoding is 0xff7f"], +["0x04 0xffff7f80", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "Minimal encoding is 0xffffff"], +["0x04 0xffff7f00", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "Minimal encoding is 0xffff7f"], + +["Test every numeric-accepting opcode for correct handling of the numeric minimal encoding rule"], + +["1 0x02 0x0000", "PICK DROP", "MINIMALDATA", "UNKNOWN_ERROR"], +["1 0x02 0x0000", "ROLL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000", "1ADD DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000", "1SUB DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000", "NEGATE DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000", "ABS DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000", "0NOTEQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], + +["0 0x02 0x0000", "ADD DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000 0", "ADD DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000", "SUB DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000 0", "SUB DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000", "BOOLAND DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000 0", "BOOLAND DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000", "BOOLOR DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000 0", "BOOLOR DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000", "NUMEQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000 1", "NUMEQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000", "NUMEQUALVERIFY 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000 0", "NUMEQUALVERIFY 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000", "NUMNOTEQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000 0", "NUMNOTEQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000", "LESSTHAN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000 0", "LESSTHAN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000", "GREATERTHAN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000 0", "GREATERTHAN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000", "LESSTHANOREQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000 0", "LESSTHANOREQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000", "GREATERTHANOREQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000 0", "GREATERTHANOREQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000", "MIN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000 0", "MIN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000", "MAX DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0x02 0x0000 0", "MAX DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], + +["0x02 0x0000 0 0", "WITHIN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000 0", "WITHIN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0 0x02 0x0000", "WITHIN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], + +["0 0 0x02 0x0000", "CHECKMULTISIG DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000 0", "CHECKMULTISIG DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000 0 1", "CHECKMULTISIG DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0 0x02 0x0000", "CHECKMULTISIGVERIFY 1", "MINIMALDATA", "UNKNOWN_ERROR"], +["0 0x02 0x0000 0", "CHECKMULTISIGVERIFY 1", "MINIMALDATA", "UNKNOWN_ERROR"], + + +["Order of CHECKMULTISIG evaluation tests, inverted by swapping the order of"], +["pubkeys/signatures so they fail due to the STRICTENC rules on validly encoded"], +["signatures and pubkeys."], +[ + "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501", + "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0 2 CHECKMULTISIG NOT", + "STRICTENC", + "PUBKEYTYPE", + "2-of-2 CHECKMULTISIG NOT with the first pubkey invalid, and both signatures validly encoded." +], +[ + "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 1", + "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT", + "STRICTENC", + "SIG_DER", + "2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but first signature invalid." +], +[ + "0 0x47 0x304402205451ce65ad844dbb978b8bdedf5082e33b43cae8279c30f2c74d9e9ee49a94f802203fe95a7ccf74da7a232ee523ef4a53cb4d14bdd16289680cdb97a63819b8f42f01 0x46 0x304402205451ce65ad844dbb978b8bdedf5082e33b43cae8279c30f2c74d9e9ee49a94f802203fe95a7ccf74da7a232ee523ef4a53cb4d14bdd16289680cdb97a63819b8f42f", + "2 0x21 0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5 0x21 0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5 0x21 0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5 3 CHECKMULTISIG", + "P2SH,STRICTENC", + "SIG_DER", + "2-of-3 with one valid and one invalid signature due to parse error, nSigs > validSigs" +], + +["Increase DERSIG test coverage"], +["0x4a 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Overly long signature is incorrectly encoded for DERSIG"], +["0x25 0x30220220000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Missing S is incorrectly encoded for DERSIG"], +["0x27 0x3024021077777777777777777777777777777777020a7777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "S with invalid S length is incorrectly encoded for DERSIG"], +["0x27 0x302403107777777777777777777777777777777702107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Non-integer R is incorrectly encoded for DERSIG"], +["0x27 0x302402107777777777777777777777777777777703107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Non-integer S is incorrectly encoded for DERSIG"], +["0x17 0x3014020002107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Zero-length R is incorrectly encoded for DERSIG"], +["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Zero-length S is incorrectly encoded for DERSIG"], +["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Negative S is incorrectly encoded for DERSIG"], + ["Automatically generated test cases"], [ "0x47 0x304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001", @@ -709,6 +1259,13 @@ "OK", "P2PK" ], +[ + "0x47 0x304402200a5c6163f07b8c3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001", + "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", + "", + "EVAL_FALSE", + "P2PK, bad sig" +], [ "0x47 0x304402206e05a6fe23c59196ffe176c9ddc31e73a9885638f9d1328d47c0c703863b8876022076feb53811aa5b04e0e79f938eb19906cc5e67548bc555a8e8b8b0fc603d840c01 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508", "DUP HASH160 0x14 0x1018853670f9f3b0582c5b9ee8ce93764ac32b93 EQUALVERIFY CHECKSIG", @@ -716,6 +1273,13 @@ "OK", "P2PKH" ], +[ + "0x47 0x3044022034bb0494b50b8ef130e2185bb220265b9284ef5b4b8a8da4d8415df489c83b5102206259a26d9cc0a125ac26af6153b17c02956855ebe1467412f066e402f5f05d1201 0x21 0x03363d90d446b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640", + "DUP HASH160 0x14 0xc0834c0c158f53be706d234c38fd52de7eece656 EQUALVERIFY CHECKSIG", + "", + "EQUALVERIFY", + "P2PKH, bad pubkey" +], [ "0x47 0x304402204710a85181663b32d25c70ec2bbd14adff5ddfff6cb50d09e155ef5f541fc86c0220056b0cc949be9386ecc5f6c2ac0493269031dbb185781db90171b54ac127790281", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", @@ -723,6 +1287,13 @@ "OK", "P2PK anyonecanpay" ], +[ + "0x47 0x304402204710a85181663b32d25c70ec2bbd14adff5ddfff6cb50d09e155ef5f541fc86c0220056b0cc949be9386ecc5f6c2ac0493269031dbb185781db90171b54ac127790201", + "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", + "", + "EVAL_FALSE", + "P2PK anyonecanpay marked with normal hashtype" +], [ "0x47 0x3044022003fef42ed6c7be8917441218f525a60e2431be978e28b7aca4d7a532cc413ae8022067a1f82c74e8d69291b90d148778405c6257bbcfc2353cc38a3e1f22bf44254601 0x23 0x210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac", "HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL", @@ -730,6 +1301,13 @@ "OK", "P2SH(P2PK)" ], +[ + "0x47 0x3044022003fef42ed6c7be8917441218f525a60e2431be978e28b7aca4d7a532cc413ae8022067a1f82c74e8d69291b90d148778405c6257bbcfc2353cc38a3e1f22bf44254601 0x23 0x210279be667ef9dcbbac54a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac", + "HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL", + "P2SH", + "EVAL_FALSE", + "P2SH(P2PK), bad redeemscript" +], [ "0x47 0x304402204e2eb034be7b089534ac9e798cf6a2c79f38bcb34d1b179efd6f2de0841735db022071461beb056b5a7be1819da6a3e3ce3662831ecc298419ca101eb6887b5dd6a401 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac", "HASH160 0x14 0x2df519943d5acc0ef5222091f9dfe3543f489a82 EQUAL", @@ -737,6 +1315,13 @@ "OK", "P2SH(P2PKH), bad sig but no VERIFY_P2SH" ], +[ + "0x47 0x304402204e2eb034be7b089534ac9e798cf6a2c79f38bcb34d1b179efd6f2de0841735db022071461beb056b5a7be1819da6a3e3ce3662831ecc298419ca101eb6887b5dd6a401 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac", + "HASH160 0x14 0x2df519943d5acc0ef5222091f9dfe3543f489a82 EQUAL", + "P2SH", + "EQUALVERIFY", + "P2SH(P2PKH), bad sig" +], [ "0 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402200a358f750934b3feb822f1966bfcd8bbec9eeaa3a8ca941e11ee5960e181fa01022050bf6b5a8e7750f70354ae041cb68a7bade67ec6c3ab19eb359638974410626e01 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", @@ -744,6 +1329,13 @@ "OK", "3-of-3" ], +[ + "0 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402200a358f750934b3feb822f1966bfcd8bbec9eeaa3a8ca941e11ee5960e181fa01022050bf6b5a8e7750f70354ae041cb68a7bade67ec6c3ab19eb359638974410626e01 0", + "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", + "", + "EVAL_FALSE", + "3-of-3, 2 sigs" +], [ "0 0x47 0x304402205b7d2c2f177ae76cfbbf14d589c113b0b35db753d305d5562dd0b61cbf366cfb02202e56f93c4f08a27f986cd424ffc48a462c3202c4902104d4d0ff98ed28f4bf8001 0x47 0x30440220563e5b3b1fc11662a84bc5ea2a32cc3819703254060ba30d639a1aaf2d5068ad0220601c1f47ddc76d93284dd9ed68f7c9974c4a0ea7cbe8a247d6bc3878567a5fca01 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae", "HASH160 0x14 0xc9e4a896d149702d0d1695434feddd52e24ad78d EQUAL", @@ -751,6 +1343,13 @@ "OK", "P2SH(2-of-3)" ], +[ + "0 0x47 0x304402205b7d2c2f177ae76cfbbf14d589c113b0b35db753d305d5562dd0b61cbf366cfb02202e56f93c4f08a27f986cd424ffc48a462c3202c4902104d4d0ff98ed28f4bf8001 0 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae", + "HASH160 0x14 0xc9e4a896d149702d0d1695434feddd52e24ad78d EQUAL", + "P2SH", + "EVAL_FALSE", + "P2SH(2-of-3), 1 sig" +], [ "0x47 0x304402200060558477337b9022e70534f1fea71a318caf836812465a2509931c5e7c4987022078ec32bd50ac9e03a349ba953dfd9fe1c8d2dd8bdb1d38ddca844d3d5c78c11801", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", @@ -758,6 +1357,13 @@ "OK", "P2PK with too much R padding but no DERSIG" ], +[ + "0x47 0x304402200060558477337b9022e70534f1fea71a318caf836812465a2509931c5e7c4987022078ec32bd50ac9e03a349ba953dfd9fe1c8d2dd8bdb1d38ddca844d3d5c78c11801", + "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", + "DERSIG", + "SIG_DER", + "P2PK with too much R padding" +], [ "0x48 0x304502202de8c03fc525285c9c535631019a5f2af7c6454fa9eb392a3756a4917c420edd02210046130bf2baf7cfc065067c8b9e33a066d9c15edcea9feb0ca2d233e3597925b401", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", @@ -765,6 +1371,13 @@ "OK", "P2PK with too much S padding but no DERSIG" ], +[ + "0x48 0x304502202de8c03fc525285c9c535631019a5f2af7c6454fa9eb392a3756a4917c420edd02210046130bf2baf7cfc065067c8b9e33a066d9c15edcea9feb0ca2d233e3597925b401", + "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", + "DERSIG", + "SIG_DER", + "P2PK with too much S padding" +], [ "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", @@ -772,6 +1385,13 @@ "OK", "P2PK with too little R padding but no DERSIG" ], +[ + "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201", + "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", + "DERSIG", + "SIG_DER", + "P2PK with too little R padding" +], [ "0x47 0x30440220005ece1335e7f757a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT", @@ -779,6 +1399,27 @@ "OK", "P2PK NOT with bad sig with too much R padding but no DERSIG" ], +[ + "0x47 0x30440220005ece1335e7f757a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601", + "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT", + "DERSIG", + "SIG_DER", + "P2PK NOT with bad sig with too much R padding" +], +[ + "0x47 0x30440220005ece1335e7f657a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601", + "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT", + "", + "EVAL_FALSE", + "P2PK NOT with too much R padding but no DERSIG" +], +[ + "0x47 0x30440220005ece1335e7f657a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601", + "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT", + "DERSIG", + "SIG_DER", + "P2PK NOT with too much R padding" +], [ "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", @@ -786,6 +1427,41 @@ "OK", "BIP66 example 1, without DERSIG" ], +[ + "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201", + "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", + "DERSIG", + "SIG_DER", + "BIP66 example 1, with DERSIG" +], +[ + "0x47 0x304402208e43c0b91f7c1e5bc58e41c8185f8a6086e111b0090187968a86f2822462d3c902200a58f4076b1133b18ff1dc83ee51676e44c60cc608d9534e0df5ace0424fc0be01", + "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", + "", + "EVAL_FALSE", + "BIP66 example 2, without DERSIG" +], +[ + "0x47 0x304402208e43c0b91f7c1e5bc58e41c8185f8a6086e111b0090187968a86f2822462d3c902200a58f4076b1133b18ff1dc83ee51676e44c60cc608d9534e0df5ace0424fc0be01", + "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", + "DERSIG", + "SIG_DER", + "BIP66 example 2, with DERSIG" +], +[ + "0", + "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", + "", + "EVAL_FALSE", + "BIP66 example 3, without DERSIG" +], +[ + "0", + "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", + "DERSIG", + "EVAL_FALSE", + "BIP66 example 3, with DERSIG" +], [ "0", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", @@ -800,6 +1476,20 @@ "OK", "BIP66 example 4, with DERSIG" ], +[ + "1", + "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", + "", + "EVAL_FALSE", + "BIP66 example 5, without DERSIG" +], +[ + "1", + "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", + "DERSIG", + "SIG_DER", + "BIP66 example 5, with DERSIG" +], [ "1", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", @@ -807,6 +1497,13 @@ "OK", "BIP66 example 6, without DERSIG" ], +[ + "1", + "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", + "DERSIG", + "SIG_DER", + "BIP66 example 6, with DERSIG" +], [ "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0x47 0x3044022027c2714269ca5aeecc4d70edc88ba5ee0e3da4986e9216028f489ab4f1b8efce022022bd545b4951215267e4c5ceabd4c5350331b2e4a0b6494c56f361fa5a57a1a201", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG", @@ -814,6 +1511,41 @@ "OK", "BIP66 example 7, without DERSIG" ], +[ + "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0x47 0x3044022027c2714269ca5aeecc4d70edc88ba5ee0e3da4986e9216028f489ab4f1b8efce022022bd545b4951215267e4c5ceabd4c5350331b2e4a0b6494c56f361fa5a57a1a201", + "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG", + "DERSIG", + "SIG_DER", + "BIP66 example 7, with DERSIG" +], +[ + "0 0x47 0x30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201 0x47 0x3044022079ea80afd538d9ada421b5101febeb6bc874e01dde5bca108c1d0479aec339a4022004576db8f66130d1df686ccf00935703689d69cf539438da1edab208b0d63c4801", + "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT", + "", + "EVAL_FALSE", + "BIP66 example 8, without DERSIG" +], +[ + "0 0x47 0x30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201 0x47 0x3044022079ea80afd538d9ada421b5101febeb6bc874e01dde5bca108c1d0479aec339a4022004576db8f66130d1df686ccf00935703689d69cf539438da1edab208b0d63c4801", + "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT", + "DERSIG", + "SIG_DER", + "BIP66 example 8, with DERSIG" +], +[ + "0 0 0x47 0x3044022081aa9d436f2154e8b6d600516db03d78de71df685b585a9807ead4210bd883490220534bb6bdf318a419ac0749660b60e78d17d515558ef369bf872eff405b676b2e01", + "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG", + "", + "EVAL_FALSE", + "BIP66 example 9, without DERSIG" +], +[ + "0 0 0x47 0x3044022081aa9d436f2154e8b6d600516db03d78de71df685b585a9807ead4210bd883490220534bb6bdf318a419ac0749660b60e78d17d515558ef369bf872eff405b676b2e01", + "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG", + "DERSIG", + "SIG_DER", + "BIP66 example 9, with DERSIG" +], [ "0 0 0x47 0x30440220da6f441dc3b4b2c84cfa8db0cd5b34ed92c9e01686de5a800d40498b70c0dcac02207c2cf91b0c32b860c4cd4994be36cfb84caf8bb7c3a8e4d96a31b2022c5299c501", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT", @@ -821,6 +1553,27 @@ "OK", "BIP66 example 10, without DERSIG" ], +[ + "0 0 0x47 0x30440220da6f441dc3b4b2c84cfa8db0cd5b34ed92c9e01686de5a800d40498b70c0dcac02207c2cf91b0c32b860c4cd4994be36cfb84caf8bb7c3a8e4d96a31b2022c5299c501", + "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT", + "DERSIG", + "SIG_DER", + "BIP66 example 10, with DERSIG" +], +[ + "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0", + "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG", + "", + "EVAL_FALSE", + "BIP66 example 11, without DERSIG" +], +[ + "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0", + "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG", + "DERSIG", + "EVAL_FALSE", + "BIP66 example 11, with DERSIG" +], [ "0 0x47 0x30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201 0", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT", @@ -842,6 +1595,13 @@ "OK", "P2PK with multi-byte hashtype, without DERSIG" ], +[ + "0x48 0x304402203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022054e1c258c2981cdfba5df1f46661fb6541c44f77ca0092f3600331abfffb12510101", + "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", + "DERSIG", + "SIG_DER", + "P2PK with multi-byte hashtype, with DERSIG" +], [ "0x48 0x304502203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022100ab1e3da73d67e32045a20e0b999e049978ea8d6ee5480d485fcf2ce0d03b2ef001", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", @@ -849,6 +1609,13 @@ "OK", "P2PK with high S but no LOW_S" ], +[ + "0x48 0x304502203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022100ab1e3da73d67e32045a20e0b999e049978ea8d6ee5480d485fcf2ce0d03b2ef001", + "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", + "LOW_S", + "SIG_HIGH_S", + "P2PK with high S" +], [ "0x47 0x3044022057292e2d4dfe775becdd0a9e6547997c728cdf35390f6a017da56d654d374e4902206b643be2fc53763b4e284845bfea2c597d2dc7759941dce937636c9d341b71ed01", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", @@ -856,6 +1623,27 @@ "OK", "P2PK with hybrid pubkey but no STRICTENC" ], +[ + "0x47 0x3044022057292e2d4dfe775becdd0a9e6547997c728cdf35390f6a017da56d654d374e4902206b643be2fc53763b4e284845bfea2c597d2dc7759941dce937636c9d341b71ed01", + "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", + "STRICTENC", + "PUBKEYTYPE", + "P2PK with hybrid pubkey" +], +[ + "0x47 0x30440220035d554e3153c14950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101", + "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", + "", + "EVAL_FALSE", + "P2PK NOT with hybrid pubkey but no STRICTENC" +], +[ + "0x47 0x30440220035d554e3153c14950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101", + "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", + "STRICTENC", + "PUBKEYTYPE", + "P2PK NOT with hybrid pubkey" +], [ "0x47 0x30440220035d554e3153c04950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", @@ -863,6 +1651,13 @@ "OK", "P2PK NOT with invalid hybrid pubkey but no STRICTENC" ], +[ + "0x47 0x30440220035d554e3153c04950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101", + "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", + "STRICTENC", + "PUBKEYTYPE", + "P2PK NOT with invalid hybrid pubkey" +], [ "0 0x47 0x304402202e79441ad1baf5a07fb86bae3753184f6717d9692680947ea8b6e8b777c69af1022079a262e13d868bb5a0964fefe3ba26942e1b0669af1afb55ef3344bc9d4fc4c401", "1 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG", @@ -877,6 +1672,13 @@ "OK", "1-of-2 with the second 1 hybrid pubkey" ], +[ + "0 0x47 0x3044022079c7824d6c868e0e1a273484e28c2654a27d043c8a27f49f52cb72efed0759090220452bbbf7089574fa082095a4fc1b3a16bafcf97a3a34d745fafc922cce66b27201", + "1 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 2 CHECKMULTISIG", + "STRICTENC", + "PUBKEYTYPE", + "1-of-2 with the first 1 hybrid pubkey" +], [ "0x47 0x304402206177d513ec2cda444c021a1f4f656fc4c72ba108ae063e157eb86dc3575784940220666fc66702815d0e5413bb9b1df22aed44f5f1efb8b99d41dd5dc9a5be6d205205", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", @@ -884,6 +1686,13 @@ "OK", "P2PK with undefined hashtype but no STRICTENC" ], +[ + "0x47 0x304402206177d513ec2cda444c021a1f4f656fc4c72ba108ae063e157eb86dc3575784940220666fc66702815d0e5413bb9b1df22aed44f5f1efb8b99d41dd5dc9a5be6d205205", + "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", + "STRICTENC", + "SIG_HASHTYPE", + "P2PK with undefined hashtype" +], [ "0x47 0x304402207409b5b320296e5e2136a7b281a7f803028ca4ca44e2b83eebd46932677725de02202d4eea1c8d3c98e6f42614f54764e6e5e6542e213eb4d079737e9a8b6e9812ec05", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG NOT", @@ -891,6 +1700,13 @@ "OK", "P2PK NOT with invalid sig and undefined hashtype but no STRICTENC" ], +[ + "0x47 0x304402207409b5b320296e5e2136a7b281a7f803028ca4ca44e2b83eebd46932677725de02202d4eea1c8d3c98e6f42614f54764e6e5e6542e213eb4d079737e9a8b6e9812ec05", + "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG NOT", + "STRICTENC", + "SIG_HASHTYPE", + "P2PK NOT with invalid sig and undefined hashtype" +], [ "1 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402200a358f750934b3feb822f1966bfcd8bbec9eeaa3a8ca941e11ee5960e181fa01022050bf6b5a8e7750f70354ae041cb68a7bade67ec6c3ab19eb359638974410626e01 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", @@ -898,6 +1714,13 @@ "OK", "3-of-3 with nonzero dummy but no NULLDUMMY" ], +[ + "1 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402200a358f750934b3feb822f1966bfcd8bbec9eeaa3a8ca941e11ee5960e181fa01022050bf6b5a8e7750f70354ae041cb68a7bade67ec6c3ab19eb359638974410626e01 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901", + "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", + "NULLDUMMY", + "SIG_NULLDUMMY", + "3-of-3 with nonzero dummy" +], [ "1 0x47 0x304402201bb2edab700a5d020236df174fefed78087697143731f659bea59642c759c16d022061f42cdbae5bcd3e8790f20bf76687443436e94a634321c16a72aa54cbc7c2ea01 0x47 0x304402204bb4a64f2a6e5c7fb2f07fef85ee56fde5e6da234c6a984262307a20e99842d702206f8303aaba5e625d223897e2ffd3f88ef1bcffef55f38dc3768e5f2e94c923f901 0x47 0x3044022040c2809b71fffb155ec8b82fe7a27f666bd97f941207be4e14ade85a1249dd4d02204d56c85ec525dd18e29a0533d5ddf61b6b1bb32980c2f63edf951aebf7a27bfe01", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG NOT", @@ -905,6 +1728,13 @@ "OK", "3-of-3 NOT with invalid sig and nonzero dummy but no NULLDUMMY" ], +[ + "1 0x47 0x304402201bb2edab700a5d020236df174fefed78087697143731f659bea59642c759c16d022061f42cdbae5bcd3e8790f20bf76687443436e94a634321c16a72aa54cbc7c2ea01 0x47 0x304402204bb4a64f2a6e5c7fb2f07fef85ee56fde5e6da234c6a984262307a20e99842d702206f8303aaba5e625d223897e2ffd3f88ef1bcffef55f38dc3768e5f2e94c923f901 0x47 0x3044022040c2809b71fffb155ec8b82fe7a27f666bd97f941207be4e14ade85a1249dd4d02204d56c85ec525dd18e29a0533d5ddf61b6b1bb32980c2f63edf951aebf7a27bfe01", + "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG NOT", + "NULLDUMMY", + "SIG_NULLDUMMY", + "3-of-3 NOT with invalid sig with nonzero dummy" +], [ "0 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901 DUP", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG", @@ -912,6 +1742,13 @@ "OK", "2-of-2 with two identical keys and sigs pushed using OP_DUP but no SIGPUSHONLY" ], +[ + "0 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901 DUP", + "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG", + "SIGPUSHONLY", + "SIG_PUSHONLY", + "2-of-2 with two identical keys and sigs pushed using OP_DUP" +], [ "0x47 0x3044022018a2a81a93add5cb5f5da76305718e4ea66045ec4888b28d84cb22fae7f4645b02201e6daa5ed5d2e4b2b2027cf7ffd43d8d9844dd49f74ef86899ec8e669dfd39aa01 NOP8 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac", "HASH160 0x14 0x215640c2f72f0d16b4eced26762035a42ffed39a EQUAL", @@ -926,6 +1763,20 @@ "OK", "P2PK with non-push scriptSig but with P2SH validation" ], +[ + "0x47 0x3044022018a2a81a93add5cb5f5da76305718e4ea66045ec4888b28d84cb22fae7f4645b02201e6daa5ed5d2e4b2b2027cf7ffd43d8d9844dd49f74ef86899ec8e669dfd39aa01 NOP8 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac", + "HASH160 0x14 0x215640c2f72f0d16b4eced26762035a42ffed39a EQUAL", + "P2SH", + "SIG_PUSHONLY", + "P2SH(P2PK) with non-push scriptSig but no SIGPUSHONLY" +], +[ + "0x47 0x3044022018a2a81a93add5cb5f5da76305718e4ea66045ec4888b28d84cb22fae7f4645b02201e6daa5ed5d2e4b2b2027cf7ffd43d8d9844dd49f74ef86899ec8e669dfd39aa01 NOP8 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac", + "HASH160 0x14 0x215640c2f72f0d16b4eced26762035a42ffed39a EQUAL", + "SIGPUSHONLY", + "SIG_PUSHONLY", + "P2SH(P2PK) with non-push scriptSig but not P2SH" +], [ "0 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG", @@ -940,6 +1791,13 @@ "OK", "P2PK with unnecessary input but no CLEANSTACK" ], +[ + "11 0x47 0x304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001", + "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", + "CLEANSTACK,P2SH", + "CLEANSTACK", + "P2PK with unnecessary input" +], [ "11 0x47 0x304402202f7505132be14872581f35d74b759212d9da40482653f1ffa3116c3294a4a51702206adbf347a2240ca41c66522b1a22a41693610b76a8e7770645dc721d1635854f01 0x43 0x410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac", "HASH160 0x14 0x31edc23bdafda4639e669f89ad6b2318dd79d032 EQUAL", @@ -947,6 +1805,13 @@ "OK", "P2SH with unnecessary input but no CLEANSTACK" ], +[ + "11 0x47 0x304402202f7505132be14872581f35d74b759212d9da40482653f1ffa3116c3294a4a51702206adbf347a2240ca41c66522b1a22a41693610b76a8e7770645dc721d1635854f01 0x43 0x410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac", + "HASH160 0x14 0x31edc23bdafda4639e669f89ad6b2318dd79d032 EQUAL", + "CLEANSTACK,P2SH", + "CLEANSTACK", + "P2SH with unnecessary input" +], [ "0x47 0x304402202f7505132be14872581f35d74b759212d9da40482653f1ffa3116c3294a4a51702206adbf347a2240ca41c66522b1a22a41693610b76a8e7770645dc721d1635854f01 0x43 0x410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac", "HASH160 0x14 0x31edc23bdafda4639e669f89ad6b2318dd79d032 EQUAL", diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 6340af2081f95..d42187f9127c2 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -2,8 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "data/script_invalid.json.h" -#include "data/script_valid.json.h" +#include "data/script_tests.json.h" #include "core_io.h" #include "key.h" @@ -399,356 +398,310 @@ BOOST_AUTO_TEST_CASE(script_build) { const KeyData keys; - std::vector good; - std::vector bad; - - good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, - "P2PK", 0 - ).PushSig(keys.key0)); - bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, - "P2PK, bad sig", 0 - ).PushSig(keys.key0).DamagePush(10).ScriptError(SCRIPT_ERR_EVAL_FALSE)); - - good.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << ToByteVector(keys.pubkey1C.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG, - "P2PKH", 0 - ).PushSig(keys.key1).Push(keys.pubkey1C)); - bad.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << ToByteVector(keys.pubkey2C.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG, - "P2PKH, bad pubkey", 0 - ).PushSig(keys.key2).Push(keys.pubkey2C).DamagePush(5).ScriptError(SCRIPT_ERR_EQUALVERIFY)); - - good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG, - "P2PK anyonecanpay", 0 - ).PushSig(keys.key1, SIGHASH_ALL | SIGHASH_ANYONECANPAY)); - bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG, - "P2PK anyonecanpay marked with normal hashtype", 0 - ).PushSig(keys.key1, SIGHASH_ALL | SIGHASH_ANYONECANPAY).EditPush(70, "81", "01").ScriptError(SCRIPT_ERR_EVAL_FALSE)); - - good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG, - "P2SH(P2PK)", SCRIPT_VERIFY_P2SH, true - ).PushSig(keys.key0).PushRedeem()); - bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG, - "P2SH(P2PK), bad redeemscript", SCRIPT_VERIFY_P2SH, true - ).PushSig(keys.key0).PushRedeem().DamagePush(10).ScriptError(SCRIPT_ERR_EVAL_FALSE)); - - good.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << ToByteVector(keys.pubkey1.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG, - "P2SH(P2PKH), bad sig but no VERIFY_P2SH", 0, true - ).PushSig(keys.key0).DamagePush(10).PushRedeem()); - bad.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << ToByteVector(keys.pubkey1.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG, - "P2SH(P2PKH), bad sig", SCRIPT_VERIFY_P2SH, true - ).PushSig(keys.key0).DamagePush(10).PushRedeem().ScriptError(SCRIPT_ERR_EQUALVERIFY)); - - good.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG, - "3-of-3", 0 - ).Num(0).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2)); - bad.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG, - "3-of-3, 2 sigs", 0 - ).Num(0).PushSig(keys.key0).PushSig(keys.key1).Num(0).ScriptError(SCRIPT_ERR_EVAL_FALSE)); - - good.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG, - "P2SH(2-of-3)", SCRIPT_VERIFY_P2SH, true - ).Num(0).PushSig(keys.key1).PushSig(keys.key2).PushRedeem()); - bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG, - "P2SH(2-of-3), 1 sig", SCRIPT_VERIFY_P2SH, true - ).Num(0).PushSig(keys.key1).Num(0).PushRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE)); - - good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG, - "P2PK with too much R padding but no DERSIG", 0 - ).PushSig(keys.key1, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000")); - bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG, - "P2PK with too much R padding", SCRIPT_VERIFY_DERSIG - ).PushSig(keys.key1, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000").ScriptError(SCRIPT_ERR_SIG_DER)); - good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG, - "P2PK with too much S padding but no DERSIG", 0 - ).PushSig(keys.key1, SIGHASH_ALL).EditPush(1, "44", "45").EditPush(37, "20", "2100")); - bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG, - "P2PK with too much S padding", SCRIPT_VERIFY_DERSIG - ).PushSig(keys.key1, SIGHASH_ALL).EditPush(1, "44", "45").EditPush(37, "20", "2100").ScriptError(SCRIPT_ERR_SIG_DER)); - good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG, - "P2PK with too little R padding but no DERSIG", 0 - ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220")); - bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG, - "P2PK with too little R padding", SCRIPT_VERIFY_DERSIG - ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").ScriptError(SCRIPT_ERR_SIG_DER)); - good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG << OP_NOT, - "P2PK NOT with bad sig with too much R padding but no DERSIG", 0 - ).PushSig(keys.key2, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000").DamagePush(10)); - bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG << OP_NOT, - "P2PK NOT with bad sig with too much R padding", SCRIPT_VERIFY_DERSIG - ).PushSig(keys.key2, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000").DamagePush(10).ScriptError(SCRIPT_ERR_SIG_DER)); - bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG << OP_NOT, - "P2PK NOT with too much R padding but no DERSIG", 0 - ).PushSig(keys.key2, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000").ScriptError(SCRIPT_ERR_EVAL_FALSE)); - bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG << OP_NOT, - "P2PK NOT with too much R padding", SCRIPT_VERIFY_DERSIG - ).PushSig(keys.key2, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000").ScriptError(SCRIPT_ERR_SIG_DER)); - - good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG, - "BIP66 example 1, without DERSIG", 0 - ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220")); - bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG, - "BIP66 example 1, with DERSIG", SCRIPT_VERIFY_DERSIG - ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").ScriptError(SCRIPT_ERR_SIG_DER)); - bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT, - "BIP66 example 2, without DERSIG", 0 - ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").ScriptError(SCRIPT_ERR_EVAL_FALSE)); - bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT, - "BIP66 example 2, with DERSIG", SCRIPT_VERIFY_DERSIG - ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").ScriptError(SCRIPT_ERR_SIG_DER)); - bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG, - "BIP66 example 3, without DERSIG", 0 - ).Num(0).ScriptError(SCRIPT_ERR_EVAL_FALSE)); - bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG, - "BIP66 example 3, with DERSIG", SCRIPT_VERIFY_DERSIG - ).Num(0).ScriptError(SCRIPT_ERR_EVAL_FALSE)); - good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT, - "BIP66 example 4, without DERSIG", 0 - ).Num(0)); - good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT, - "BIP66 example 4, with DERSIG", SCRIPT_VERIFY_DERSIG - ).Num(0)); - bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG, - "BIP66 example 5, without DERSIG", 0 - ).Num(1).ScriptError(SCRIPT_ERR_EVAL_FALSE)); - bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG, - "BIP66 example 5, with DERSIG", SCRIPT_VERIFY_DERSIG - ).Num(1).ScriptError(SCRIPT_ERR_SIG_DER)); - good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT, - "BIP66 example 6, without DERSIG", 0 - ).Num(1)); - bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT, - "BIP66 example 6, with DERSIG", SCRIPT_VERIFY_DERSIG - ).Num(1).ScriptError(SCRIPT_ERR_SIG_DER)); - good.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG, - "BIP66 example 7, without DERSIG", 0 - ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").PushSig(keys.key2)); - bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG, - "BIP66 example 7, with DERSIG", SCRIPT_VERIFY_DERSIG - ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").PushSig(keys.key2).ScriptError(SCRIPT_ERR_SIG_DER)); - bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT, - "BIP66 example 8, without DERSIG", 0 - ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").PushSig(keys.key2).ScriptError(SCRIPT_ERR_EVAL_FALSE)); - bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT, - "BIP66 example 8, with DERSIG", SCRIPT_VERIFY_DERSIG - ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").PushSig(keys.key2).ScriptError(SCRIPT_ERR_SIG_DER)); - bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG, - "BIP66 example 9, without DERSIG", 0 - ).Num(0).Num(0).PushSig(keys.key2, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").ScriptError(SCRIPT_ERR_EVAL_FALSE)); - bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG, - "BIP66 example 9, with DERSIG", SCRIPT_VERIFY_DERSIG - ).Num(0).Num(0).PushSig(keys.key2, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").ScriptError(SCRIPT_ERR_SIG_DER)); - good.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT, - "BIP66 example 10, without DERSIG", 0 - ).Num(0).Num(0).PushSig(keys.key2, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220")); - bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT, - "BIP66 example 10, with DERSIG", SCRIPT_VERIFY_DERSIG - ).Num(0).Num(0).PushSig(keys.key2, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").ScriptError(SCRIPT_ERR_SIG_DER)); - bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG, - "BIP66 example 11, without DERSIG", 0 - ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").Num(0).ScriptError(SCRIPT_ERR_EVAL_FALSE)); - bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG, - "BIP66 example 11, with DERSIG", SCRIPT_VERIFY_DERSIG - ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").Num(0).ScriptError(SCRIPT_ERR_EVAL_FALSE)); - good.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT, - "BIP66 example 12, without DERSIG", 0 - ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").Num(0)); - good.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT, - "BIP66 example 12, with DERSIG", SCRIPT_VERIFY_DERSIG - ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").Num(0)); - good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG, - "P2PK with multi-byte hashtype, without DERSIG", 0 - ).PushSig(keys.key2, SIGHASH_ALL).EditPush(70, "01", "0101")); - bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG, - "P2PK with multi-byte hashtype, with DERSIG", SCRIPT_VERIFY_DERSIG - ).PushSig(keys.key2, SIGHASH_ALL).EditPush(70, "01", "0101").ScriptError(SCRIPT_ERR_SIG_DER)); - - good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG, - "P2PK with high S but no LOW_S", 0 - ).PushSig(keys.key2, SIGHASH_ALL, 32, 33)); - bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG, - "P2PK with high S", SCRIPT_VERIFY_LOW_S - ).PushSig(keys.key2, SIGHASH_ALL, 32, 33).ScriptError(SCRIPT_ERR_SIG_HIGH_S)); - - good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG, - "P2PK with hybrid pubkey but no STRICTENC", 0 - ).PushSig(keys.key0, SIGHASH_ALL)); - bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG, - "P2PK with hybrid pubkey", SCRIPT_VERIFY_STRICTENC - ).PushSig(keys.key0, SIGHASH_ALL).ScriptError(SCRIPT_ERR_PUBKEYTYPE)); - bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT, - "P2PK NOT with hybrid pubkey but no STRICTENC", 0 - ).PushSig(keys.key0, SIGHASH_ALL).ScriptError(SCRIPT_ERR_EVAL_FALSE)); - bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT, - "P2PK NOT with hybrid pubkey", SCRIPT_VERIFY_STRICTENC - ).PushSig(keys.key0, SIGHASH_ALL).ScriptError(SCRIPT_ERR_PUBKEYTYPE)); - good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT, - "P2PK NOT with invalid hybrid pubkey but no STRICTENC", 0 - ).PushSig(keys.key0, SIGHASH_ALL).DamagePush(10)); - bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT, - "P2PK NOT with invalid hybrid pubkey", SCRIPT_VERIFY_STRICTENC - ).PushSig(keys.key0, SIGHASH_ALL).DamagePush(10).ScriptError(SCRIPT_ERR_PUBKEYTYPE)); - good.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey0H) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG, - "1-of-2 with the second 1 hybrid pubkey and no STRICTENC", 0 - ).Num(0).PushSig(keys.key1, SIGHASH_ALL)); - good.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey0H) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG, - "1-of-2 with the second 1 hybrid pubkey", SCRIPT_VERIFY_STRICTENC - ).Num(0).PushSig(keys.key1, SIGHASH_ALL)); - bad.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0H) << OP_2 << OP_CHECKMULTISIG, - "1-of-2 with the first 1 hybrid pubkey", SCRIPT_VERIFY_STRICTENC - ).Num(0).PushSig(keys.key1, SIGHASH_ALL).ScriptError(SCRIPT_ERR_PUBKEYTYPE)); - - good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG, - "P2PK with undefined hashtype but no STRICTENC", 0 - ).PushSig(keys.key1, 5)); - bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG, - "P2PK with undefined hashtype", SCRIPT_VERIFY_STRICTENC - ).PushSig(keys.key1, 5).ScriptError(SCRIPT_ERR_SIG_HASHTYPE)); - good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG << OP_NOT, - "P2PK NOT with invalid sig and undefined hashtype but no STRICTENC", 0 - ).PushSig(keys.key1, 5).DamagePush(10)); - bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG << OP_NOT, - "P2PK NOT with invalid sig and undefined hashtype", SCRIPT_VERIFY_STRICTENC - ).PushSig(keys.key1, 5).DamagePush(10).ScriptError(SCRIPT_ERR_SIG_HASHTYPE)); - - good.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG, - "3-of-3 with nonzero dummy but no NULLDUMMY", 0 - ).Num(1).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2)); - bad.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG, - "3-of-3 with nonzero dummy", SCRIPT_VERIFY_NULLDUMMY - ).Num(1).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2).ScriptError(SCRIPT_ERR_SIG_NULLDUMMY)); - good.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG << OP_NOT, - "3-of-3 NOT with invalid sig and nonzero dummy but no NULLDUMMY", 0 - ).Num(1).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2).DamagePush(10)); - bad.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG << OP_NOT, - "3-of-3 NOT with invalid sig with nonzero dummy", SCRIPT_VERIFY_NULLDUMMY - ).Num(1).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2).DamagePush(10).ScriptError(SCRIPT_ERR_SIG_NULLDUMMY)); - - good.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG, - "2-of-2 with two identical keys and sigs pushed using OP_DUP but no SIGPUSHONLY", 0 - ).Num(0).PushSig(keys.key1).Add(CScript() << OP_DUP)); - bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG, - "2-of-2 with two identical keys and sigs pushed using OP_DUP", SCRIPT_VERIFY_SIGPUSHONLY - ).Num(0).PushSig(keys.key1).Add(CScript() << OP_DUP).ScriptError(SCRIPT_ERR_SIG_PUSHONLY)); - good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG, - "P2SH(P2PK) with non-push scriptSig but no P2SH or SIGPUSHONLY", 0, true - ).PushSig(keys.key2).Add(CScript() << OP_NOP8).PushRedeem()); - good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG, - "P2PK with non-push scriptSig but with P2SH validation", 0 - ).PushSig(keys.key2).Add(CScript() << OP_NOP8)); - bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG, - "P2SH(P2PK) with non-push scriptSig but no SIGPUSHONLY", SCRIPT_VERIFY_P2SH, true - ).PushSig(keys.key2).Add(CScript() << OP_NOP8).PushRedeem().ScriptError(SCRIPT_ERR_SIG_PUSHONLY)); - bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG, - "P2SH(P2PK) with non-push scriptSig but not P2SH", SCRIPT_VERIFY_SIGPUSHONLY, true - ).PushSig(keys.key2).Add(CScript() << OP_NOP8).PushRedeem().ScriptError(SCRIPT_ERR_SIG_PUSHONLY)); - good.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG, - "2-of-2 with two identical keys and sigs pushed", SCRIPT_VERIFY_SIGPUSHONLY - ).Num(0).PushSig(keys.key1).PushSig(keys.key1)); - good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, - "P2PK with unnecessary input but no CLEANSTACK", SCRIPT_VERIFY_P2SH - ).Num(11).PushSig(keys.key0)); - bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, - "P2PK with unnecessary input", SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_P2SH - ).Num(11).PushSig(keys.key0).ScriptError(SCRIPT_ERR_CLEANSTACK)); - good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, - "P2SH with unnecessary input but no CLEANSTACK", SCRIPT_VERIFY_P2SH, true - ).Num(11).PushSig(keys.key0).PushRedeem()); - bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, - "P2SH with unnecessary input", SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_P2SH, true - ).Num(11).PushSig(keys.key0).PushRedeem().ScriptError(SCRIPT_ERR_CLEANSTACK)); - good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, - "P2SH with CLEANSTACK", SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_P2SH, true - ).PushSig(keys.key0).PushRedeem()); - - - std::set tests_good; - std::set tests_bad; + std::vector tests; + + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, + "P2PK", 0 + ).PushSig(keys.key0)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, + "P2PK, bad sig", 0 + ).PushSig(keys.key0).DamagePush(10).ScriptError(SCRIPT_ERR_EVAL_FALSE)); + + tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << ToByteVector(keys.pubkey1C.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG, + "P2PKH", 0 + ).PushSig(keys.key1).Push(keys.pubkey1C)); + tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << ToByteVector(keys.pubkey2C.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG, + "P2PKH, bad pubkey", 0 + ).PushSig(keys.key2).Push(keys.pubkey2C).DamagePush(5).ScriptError(SCRIPT_ERR_EQUALVERIFY)); + + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG, + "P2PK anyonecanpay", 0 + ).PushSig(keys.key1, SIGHASH_ALL | SIGHASH_ANYONECANPAY)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG, + "P2PK anyonecanpay marked with normal hashtype", 0 + ).PushSig(keys.key1, SIGHASH_ALL | SIGHASH_ANYONECANPAY).EditPush(70, "81", "01").ScriptError(SCRIPT_ERR_EVAL_FALSE)); + + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG, + "P2SH(P2PK)", SCRIPT_VERIFY_P2SH, true + ).PushSig(keys.key0).PushRedeem()); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG, + "P2SH(P2PK), bad redeemscript", SCRIPT_VERIFY_P2SH, true + ).PushSig(keys.key0).PushRedeem().DamagePush(10).ScriptError(SCRIPT_ERR_EVAL_FALSE)); + + tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << ToByteVector(keys.pubkey1.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG, + "P2SH(P2PKH), bad sig but no VERIFY_P2SH", 0, true + ).PushSig(keys.key0).DamagePush(10).PushRedeem()); + tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << ToByteVector(keys.pubkey1.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG, + "P2SH(P2PKH), bad sig", SCRIPT_VERIFY_P2SH, true + ).PushSig(keys.key0).DamagePush(10).PushRedeem().ScriptError(SCRIPT_ERR_EQUALVERIFY)); + + tests.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG, + "3-of-3", 0 + ).Num(0).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2)); + tests.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG, + "3-of-3, 2 sigs", 0 + ).Num(0).PushSig(keys.key0).PushSig(keys.key1).Num(0).ScriptError(SCRIPT_ERR_EVAL_FALSE)); + + tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG, + "P2SH(2-of-3)", SCRIPT_VERIFY_P2SH, true + ).Num(0).PushSig(keys.key1).PushSig(keys.key2).PushRedeem()); + tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG, + "P2SH(2-of-3), 1 sig", SCRIPT_VERIFY_P2SH, true + ).Num(0).PushSig(keys.key1).Num(0).PushRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE)); + + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG, + "P2PK with too much R padding but no DERSIG", 0 + ).PushSig(keys.key1, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000")); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG, + "P2PK with too much R padding", SCRIPT_VERIFY_DERSIG + ).PushSig(keys.key1, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000").ScriptError(SCRIPT_ERR_SIG_DER)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG, + "P2PK with too much S padding but no DERSIG", 0 + ).PushSig(keys.key1, SIGHASH_ALL).EditPush(1, "44", "45").EditPush(37, "20", "2100")); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG, + "P2PK with too much S padding", SCRIPT_VERIFY_DERSIG + ).PushSig(keys.key1, SIGHASH_ALL).EditPush(1, "44", "45").EditPush(37, "20", "2100").ScriptError(SCRIPT_ERR_SIG_DER)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG, + "P2PK with too little R padding but no DERSIG", 0 + ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220")); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG, + "P2PK with too little R padding", SCRIPT_VERIFY_DERSIG + ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").ScriptError(SCRIPT_ERR_SIG_DER)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG << OP_NOT, + "P2PK NOT with bad sig with too much R padding but no DERSIG", 0 + ).PushSig(keys.key2, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000").DamagePush(10)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG << OP_NOT, + "P2PK NOT with bad sig with too much R padding", SCRIPT_VERIFY_DERSIG + ).PushSig(keys.key2, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000").DamagePush(10).ScriptError(SCRIPT_ERR_SIG_DER)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG << OP_NOT, + "P2PK NOT with too much R padding but no DERSIG", 0 + ).PushSig(keys.key2, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000").ScriptError(SCRIPT_ERR_EVAL_FALSE)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG << OP_NOT, + "P2PK NOT with too much R padding", SCRIPT_VERIFY_DERSIG + ).PushSig(keys.key2, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000").ScriptError(SCRIPT_ERR_SIG_DER)); + + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG, + "BIP66 example 1, without DERSIG", 0 + ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220")); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG, + "BIP66 example 1, with DERSIG", SCRIPT_VERIFY_DERSIG + ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").ScriptError(SCRIPT_ERR_SIG_DER)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT, + "BIP66 example 2, without DERSIG", 0 + ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").ScriptError(SCRIPT_ERR_EVAL_FALSE)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT, + "BIP66 example 2, with DERSIG", SCRIPT_VERIFY_DERSIG + ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").ScriptError(SCRIPT_ERR_SIG_DER)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG, + "BIP66 example 3, without DERSIG", 0 + ).Num(0).ScriptError(SCRIPT_ERR_EVAL_FALSE)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG, + "BIP66 example 3, with DERSIG", SCRIPT_VERIFY_DERSIG + ).Num(0).ScriptError(SCRIPT_ERR_EVAL_FALSE)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT, + "BIP66 example 4, without DERSIG", 0 + ).Num(0)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT, + "BIP66 example 4, with DERSIG", SCRIPT_VERIFY_DERSIG + ).Num(0)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG, + "BIP66 example 5, without DERSIG", 0 + ).Num(1).ScriptError(SCRIPT_ERR_EVAL_FALSE)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG, + "BIP66 example 5, with DERSIG", SCRIPT_VERIFY_DERSIG + ).Num(1).ScriptError(SCRIPT_ERR_SIG_DER)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT, + "BIP66 example 6, without DERSIG", 0 + ).Num(1)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT, + "BIP66 example 6, with DERSIG", SCRIPT_VERIFY_DERSIG + ).Num(1).ScriptError(SCRIPT_ERR_SIG_DER)); + tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG, + "BIP66 example 7, without DERSIG", 0 + ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").PushSig(keys.key2)); + tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG, + "BIP66 example 7, with DERSIG", SCRIPT_VERIFY_DERSIG + ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").PushSig(keys.key2).ScriptError(SCRIPT_ERR_SIG_DER)); + tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT, + "BIP66 example 8, without DERSIG", 0 + ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").PushSig(keys.key2).ScriptError(SCRIPT_ERR_EVAL_FALSE)); + tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT, + "BIP66 example 8, with DERSIG", SCRIPT_VERIFY_DERSIG + ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").PushSig(keys.key2).ScriptError(SCRIPT_ERR_SIG_DER)); + tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG, + "BIP66 example 9, without DERSIG", 0 + ).Num(0).Num(0).PushSig(keys.key2, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").ScriptError(SCRIPT_ERR_EVAL_FALSE)); + tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG, + "BIP66 example 9, with DERSIG", SCRIPT_VERIFY_DERSIG + ).Num(0).Num(0).PushSig(keys.key2, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").ScriptError(SCRIPT_ERR_SIG_DER)); + tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT, + "BIP66 example 10, without DERSIG", 0 + ).Num(0).Num(0).PushSig(keys.key2, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220")); + tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT, + "BIP66 example 10, with DERSIG", SCRIPT_VERIFY_DERSIG + ).Num(0).Num(0).PushSig(keys.key2, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").ScriptError(SCRIPT_ERR_SIG_DER)); + tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG, + "BIP66 example 11, without DERSIG", 0 + ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").Num(0).ScriptError(SCRIPT_ERR_EVAL_FALSE)); + tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG, + "BIP66 example 11, with DERSIG", SCRIPT_VERIFY_DERSIG + ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").Num(0).ScriptError(SCRIPT_ERR_EVAL_FALSE)); + tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT, + "BIP66 example 12, without DERSIG", 0 + ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").Num(0)); + tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT, + "BIP66 example 12, with DERSIG", SCRIPT_VERIFY_DERSIG + ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").Num(0)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG, + "P2PK with multi-byte hashtype, without DERSIG", 0 + ).PushSig(keys.key2, SIGHASH_ALL).EditPush(70, "01", "0101")); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG, + "P2PK with multi-byte hashtype, with DERSIG", SCRIPT_VERIFY_DERSIG + ).PushSig(keys.key2, SIGHASH_ALL).EditPush(70, "01", "0101").ScriptError(SCRIPT_ERR_SIG_DER)); + + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG, + "P2PK with high S but no LOW_S", 0 + ).PushSig(keys.key2, SIGHASH_ALL, 32, 33)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG, + "P2PK with high S", SCRIPT_VERIFY_LOW_S + ).PushSig(keys.key2, SIGHASH_ALL, 32, 33).ScriptError(SCRIPT_ERR_SIG_HIGH_S)); + + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG, + "P2PK with hybrid pubkey but no STRICTENC", 0 + ).PushSig(keys.key0, SIGHASH_ALL)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG, + "P2PK with hybrid pubkey", SCRIPT_VERIFY_STRICTENC + ).PushSig(keys.key0, SIGHASH_ALL).ScriptError(SCRIPT_ERR_PUBKEYTYPE)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT, + "P2PK NOT with hybrid pubkey but no STRICTENC", 0 + ).PushSig(keys.key0, SIGHASH_ALL).ScriptError(SCRIPT_ERR_EVAL_FALSE)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT, + "P2PK NOT with hybrid pubkey", SCRIPT_VERIFY_STRICTENC + ).PushSig(keys.key0, SIGHASH_ALL).ScriptError(SCRIPT_ERR_PUBKEYTYPE)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT, + "P2PK NOT with invalid hybrid pubkey but no STRICTENC", 0 + ).PushSig(keys.key0, SIGHASH_ALL).DamagePush(10)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT, + "P2PK NOT with invalid hybrid pubkey", SCRIPT_VERIFY_STRICTENC + ).PushSig(keys.key0, SIGHASH_ALL).DamagePush(10).ScriptError(SCRIPT_ERR_PUBKEYTYPE)); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey0H) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG, + "1-of-2 with the second 1 hybrid pubkey and no STRICTENC", 0 + ).Num(0).PushSig(keys.key1, SIGHASH_ALL)); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey0H) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG, + "1-of-2 with the second 1 hybrid pubkey", SCRIPT_VERIFY_STRICTENC + ).Num(0).PushSig(keys.key1, SIGHASH_ALL)); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0H) << OP_2 << OP_CHECKMULTISIG, + "1-of-2 with the first 1 hybrid pubkey", SCRIPT_VERIFY_STRICTENC + ).Num(0).PushSig(keys.key1, SIGHASH_ALL).ScriptError(SCRIPT_ERR_PUBKEYTYPE)); + + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG, + "P2PK with undefined hashtype but no STRICTENC", 0 + ).PushSig(keys.key1, 5)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG, + "P2PK with undefined hashtype", SCRIPT_VERIFY_STRICTENC + ).PushSig(keys.key1, 5).ScriptError(SCRIPT_ERR_SIG_HASHTYPE)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG << OP_NOT, + "P2PK NOT with invalid sig and undefined hashtype but no STRICTENC", 0 + ).PushSig(keys.key1, 5).DamagePush(10)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG << OP_NOT, + "P2PK NOT with invalid sig and undefined hashtype", SCRIPT_VERIFY_STRICTENC + ).PushSig(keys.key1, 5).DamagePush(10).ScriptError(SCRIPT_ERR_SIG_HASHTYPE)); + + tests.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG, + "3-of-3 with nonzero dummy but no NULLDUMMY", 0 + ).Num(1).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2)); + tests.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG, + "3-of-3 with nonzero dummy", SCRIPT_VERIFY_NULLDUMMY + ).Num(1).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2).ScriptError(SCRIPT_ERR_SIG_NULLDUMMY)); + tests.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG << OP_NOT, + "3-of-3 NOT with invalid sig and nonzero dummy but no NULLDUMMY", 0 + ).Num(1).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2).DamagePush(10)); + tests.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG << OP_NOT, + "3-of-3 NOT with invalid sig with nonzero dummy", SCRIPT_VERIFY_NULLDUMMY + ).Num(1).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2).DamagePush(10).ScriptError(SCRIPT_ERR_SIG_NULLDUMMY)); + + tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG, + "2-of-2 with two identical keys and sigs pushed using OP_DUP but no SIGPUSHONLY", 0 + ).Num(0).PushSig(keys.key1).Add(CScript() << OP_DUP)); + tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG, + "2-of-2 with two identical keys and sigs pushed using OP_DUP", SCRIPT_VERIFY_SIGPUSHONLY + ).Num(0).PushSig(keys.key1).Add(CScript() << OP_DUP).ScriptError(SCRIPT_ERR_SIG_PUSHONLY)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG, + "P2SH(P2PK) with non-push scriptSig but no P2SH or SIGPUSHONLY", 0, true + ).PushSig(keys.key2).Add(CScript() << OP_NOP8).PushRedeem()); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG, + "P2PK with non-push scriptSig but with P2SH validation", 0 + ).PushSig(keys.key2).Add(CScript() << OP_NOP8)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG, + "P2SH(P2PK) with non-push scriptSig but no SIGPUSHONLY", SCRIPT_VERIFY_P2SH, true + ).PushSig(keys.key2).Add(CScript() << OP_NOP8).PushRedeem().ScriptError(SCRIPT_ERR_SIG_PUSHONLY)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG, + "P2SH(P2PK) with non-push scriptSig but not P2SH", SCRIPT_VERIFY_SIGPUSHONLY, true + ).PushSig(keys.key2).Add(CScript() << OP_NOP8).PushRedeem().ScriptError(SCRIPT_ERR_SIG_PUSHONLY)); + tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG, + "2-of-2 with two identical keys and sigs pushed", SCRIPT_VERIFY_SIGPUSHONLY + ).Num(0).PushSig(keys.key1).PushSig(keys.key1)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, + "P2PK with unnecessary input but no CLEANSTACK", SCRIPT_VERIFY_P2SH + ).Num(11).PushSig(keys.key0)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, + "P2PK with unnecessary input", SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_P2SH + ).Num(11).PushSig(keys.key0).ScriptError(SCRIPT_ERR_CLEANSTACK)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, + "P2SH with unnecessary input but no CLEANSTACK", SCRIPT_VERIFY_P2SH, true + ).Num(11).PushSig(keys.key0).PushRedeem()); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, + "P2SH with unnecessary input", SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_P2SH, true + ).Num(11).PushSig(keys.key0).PushRedeem().ScriptError(SCRIPT_ERR_CLEANSTACK)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, + "P2SH with CLEANSTACK", SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_P2SH, true + ).PushSig(keys.key0).PushRedeem()); + + + std::set tests_set; { - UniValue json_good = read_json(std::string(json_tests::script_valid, json_tests::script_valid + sizeof(json_tests::script_valid))); - UniValue json_bad = read_json(std::string(json_tests::script_invalid, json_tests::script_invalid + sizeof(json_tests::script_invalid))); + UniValue json_tests = read_json(std::string(json_tests::script_tests, json_tests::script_tests + sizeof(json_tests::script_tests))); - for (unsigned int idx = 0; idx < json_good.size(); idx++) { - const UniValue& tv = json_good[idx]; - tests_good.insert(JSONPrettyPrint(tv.get_array())); - } - for (unsigned int idx = 0; idx < json_bad.size(); idx++) { - const UniValue& tv = json_bad[idx]; - tests_bad.insert(JSONPrettyPrint(tv.get_array())); + for (unsigned int idx = 0; idx < json_tests.size(); idx++) { + const UniValue& tv = json_tests[idx]; + tests_set.insert(JSONPrettyPrint(tv.get_array())); } } - std::string strGood; - std::string strBad; + std::string strGen; - BOOST_FOREACH(TestBuilder& test, good) { + BOOST_FOREACH(TestBuilder& test, tests) { test.Test(); std::string str = JSONPrettyPrint(test.GetJSON()); #ifndef UPDATE_JSON_TESTS - if (tests_good.count(str) == 0) { + if (tests_set.count(str) == 0) { BOOST_CHECK_MESSAGE(false, "Missing auto script_valid test: " + test.GetComment()); } #endif - strGood += str + ",\n"; - } - BOOST_FOREACH(TestBuilder& test, bad) { - test.Test(); - std::string str = JSONPrettyPrint(test.GetJSON()); -#ifndef UPDATE_JSON_TESTS - if (tests_bad.count(str) == 0) { - BOOST_CHECK_MESSAGE(false, "Missing auto script_invalid test: " + test.GetComment()); - } -#endif - strBad += str + ",\n"; + strGen += str + ",\n"; } #ifdef UPDATE_JSON_TESTS - FILE* valid = fopen("script_valid.json.gen", "w"); - fputs(strGood.c_str(), valid); - fclose(valid); - FILE* invalid = fopen("script_invalid.json.gen", "w"); - fputs(strBad.c_str(), invalid); - fclose(invalid); + FILE* file = fopen("script_tests.json.gen", "w"); + fputs(strGen.c_str(), file); + fclose(file); #endif } -BOOST_AUTO_TEST_CASE(script_valid) +BOOST_AUTO_TEST_CASE(script_json_test) { - // Read tests from test/data/script_valid.json + // Read tests from test/data/script_tests.json // Format is an array of arrays // Inner arrays are [ "scriptSig", "scriptPubKey", "flags", "expected_scripterror" ] // ... where scriptSig and scriptPubKey are stringified // scripts. - UniValue tests = read_json(std::string(json_tests::script_valid, json_tests::script_valid + sizeof(json_tests::script_valid))); - - for (unsigned int idx = 0; idx < tests.size(); idx++) { - UniValue test = tests[idx]; - string strTest = test.write(); - if (test.size() < 3) // Allow size > 3; extra stuff ignored (useful for comments) - { - if (test.size() != 1) { - BOOST_ERROR("Bad test: " << strTest); - } - continue; - } - string scriptSigString = test[0].get_str(); - CScript scriptSig = ParseScript(scriptSigString); - string scriptPubKeyString = test[1].get_str(); - CScript scriptPubKey = ParseScript(scriptPubKeyString); - unsigned int scriptflags = ParseScriptFlags(test[2].get_str()); - BOOST_CHECK_EQUAL(test[3].get_str(), "OK"); - - DoTest(scriptPubKey, scriptSig, scriptflags, strTest, SCRIPT_ERR_OK); - } -} + UniValue tests = read_json(std::string(json_tests::script_tests, json_tests::script_tests + sizeof(json_tests::script_tests))); -BOOST_AUTO_TEST_CASE(script_invalid) -{ - // Scripts that should evaluate as invalid - UniValue tests = read_json(std::string(json_tests::script_invalid, json_tests::script_invalid + sizeof(json_tests::script_invalid))); for (unsigned int idx = 0; idx < tests.size(); idx++) { UniValue test = tests[idx]; string strTest = test.write(); - if (test.size() < 4) // Allow size > 2; extra stuff ignored (useful for comments) + if (test.size() < 4) // Allow size > 3; extra stuff ignored (useful for comments) { if (test.size() != 1) { BOOST_ERROR("Bad test: " << strTest); From f20d42ed2b1b8de9c41525f96c40b172ab82ec99 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sun, 3 Apr 2016 12:08:14 +0200 Subject: [PATCH 0102/1802] UpdateTip: log only one line at most per block Avoid logging two or more lines per block in UpdateTip by adding the warning into the UpdateTip log message. --- src/main.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 2c0b3bfee7aa6..1044c3556b8a3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -40,6 +40,7 @@ #include #include +#include #include #include #include @@ -2555,16 +2556,10 @@ void static UpdateTip(CBlockIndex *pindexNew) { nTimeBestReceived = GetTime(); mempool.AddTransactionsUpdated(1); - LogPrintf("%s: new best=%s height=%d version=0x%08x log2_work=%.8g tx=%lu date='%s' progress=%f cache=%.1fMiB(%utx)\n", __func__, - chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), chainActive.Tip()->nVersion, - log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)chainActive.Tip()->nChainTx, - DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()), - Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.Tip()), pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize()); - cvBlockChange.notify_all(); - // Check the version of the last 100 blocks to see if we need to upgrade: static bool fWarned = false; + std::vector warningMessages; if (!IsInitialBlockDownload()) { int nUpgraded = 0; @@ -2580,10 +2575,11 @@ void static UpdateTip(CBlockIndex *pindexNew) { fWarned = true; } } else { - LogPrintf("%s: unknown new rules are about to activate (versionbit %i)\n", __func__, bit); + warningMessages.push_back(strprintf("unknown new rules are about to activate (versionbit %i)", bit)); } } } + // Check the version of the last 100 blocks to see if we need to upgrade: for (int i = 0; i < 100 && pindex != NULL; i++) { int32_t nExpectedVersion = ComputeBlockVersion(pindex->pprev, chainParams.GetConsensus()); @@ -2592,7 +2588,7 @@ void static UpdateTip(CBlockIndex *pindexNew) { pindex = pindex->pprev; } if (nUpgraded > 0) - LogPrintf("%s: %d of last 100 blocks have unexpected version\n", __func__, nUpgraded); + warningMessages.push_back(strprintf("%d of last 100 blocks have unexpected version", nUpgraded)); if (nUpgraded > 100/2) { // strMiscWarning is read by GetWarnings(), called by Qt and the JSON-RPC code to warn the user: @@ -2603,6 +2599,15 @@ void static UpdateTip(CBlockIndex *pindexNew) { } } } + LogPrintf("%s: new best=%s height=%d version=0x%08x log2_work=%.8g tx=%lu date='%s' progress=%f cache=%.1fMiB(%utx)", __func__, + chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), chainActive.Tip()->nVersion, + log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)chainActive.Tip()->nChainTx, + DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()), + Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.Tip()), pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize()); + if (!warningMessages.empty()) + LogPrintf(" warning='%s'", boost::algorithm::join(warningMessages, ", ")); + LogPrintf("\n"); + } /** Disconnect chainActive's tip. You probably want to call mempool.removeForReorg and manually re-limit mempool size after this, with cs_main held. */ From eda3d9248971a1c3df6e6c4b23ba89be30508b51 Mon Sep 17 00:00:00 2001 From: mruddy Date: Tue, 5 Apr 2016 22:26:38 +0000 Subject: [PATCH 0103/1802] Net: Add IPv6 Link-Local Address Support --- src/netbase.cpp | 10 +++++++--- src/netbase.h | 3 ++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/netbase.cpp b/src/netbase.cpp index 7f79dd02c6052..281c6bcb7fe79 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -170,7 +170,8 @@ bool static LookupIntern(const char *pszName, std::vector& vIP, unsign if (aiTrav->ai_family == AF_INET6) { assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in6)); - vIP.push_back(CNetAddr(((struct sockaddr_in6*)(aiTrav->ai_addr))->sin6_addr)); + struct sockaddr_in6* s6 = (struct sockaddr_in6*) aiTrav->ai_addr; + vIP.push_back(CNetAddr(s6->sin6_addr, s6->sin6_scope_id)); } aiTrav = aiTrav->ai_next; @@ -629,6 +630,7 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest void CNetAddr::Init() { memset(ip, 0, sizeof(ip)); + scopeId = 0; } void CNetAddr::SetIP(const CNetAddr& ipIn) @@ -678,9 +680,10 @@ CNetAddr::CNetAddr(const struct in_addr& ipv4Addr) SetRaw(NET_IPV4, (const uint8_t*)&ipv4Addr); } -CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr) +CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr, const uint32_t scope) { SetRaw(NET_IPV6, (const uint8_t*)&ipv6Addr); + scopeId = scope; } CNetAddr::CNetAddr(const char *pszIp, bool fAllowLookup) @@ -1099,7 +1102,7 @@ CService::CService(const struct sockaddr_in& addr) : CNetAddr(addr.sin_addr), po assert(addr.sin_family == AF_INET); } -CService::CService(const struct sockaddr_in6 &addr) : CNetAddr(addr.sin6_addr), port(ntohs(addr.sin6_port)) +CService::CService(const struct sockaddr_in6 &addr) : CNetAddr(addr.sin6_addr, addr.sin6_scope_id), port(ntohs(addr.sin6_port)) { assert(addr.sin6_family == AF_INET6); } @@ -1192,6 +1195,7 @@ bool CService::GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const memset(paddrin6, 0, *addrlen); if (!GetIn6Addr(&paddrin6->sin6_addr)) return false; + paddrin6->sin6_scope_id = scopeId; paddrin6->sin6_family = AF_INET6; paddrin6->sin6_port = htons(port); return true; diff --git a/src/netbase.h b/src/netbase.h index 1db66ac27f2da..db736154fa684 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -44,6 +44,7 @@ class CNetAddr { protected: unsigned char ip[16]; // in network byte order + uint32_t scopeId; // for scoped/link-local ipv6 addresses public: CNetAddr(); @@ -89,7 +90,7 @@ class CNetAddr std::vector GetGroup() const; int GetReachabilityFrom(const CNetAddr *paddrPartner = NULL) const; - CNetAddr(const struct in6_addr& pipv6Addr); + CNetAddr(const struct in6_addr& pipv6Addr, const uint32_t scope = 0); bool GetIn6Addr(struct in6_addr* pipv6Addr) const; friend bool operator==(const CNetAddr& a, const CNetAddr& b); From 07398e8e9d2ef807e63abd0978a6e98549bdf271 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 6 Apr 2016 10:27:51 +0200 Subject: [PATCH 0104/1802] init: allow shutdown during 'Activating best chain...' Two-line patch to make it possible to shut down bitcoind cleanly during the initial ActivateBestChain. Fixes #6459 (among other complaints). To reproduce: - shutdown bitcoind - copy chainstate - start bitcoind - let the chain sync a bit - shutdown bitcoind - copy back old chainstate - start bitcoind - bitcoind will catch up with all blocks during Init() (the `boost::this_thread::interruption_point` / `ShutdownRequested()` dance is ugly, this should be refactored all over bitcoind at some point when moving from boost::threads to c++11 threads, but it works...) --- src/main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index b68c6affae7f9..c1137c9b1f369 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2877,6 +2877,8 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, CBlockIndex *pindexMostWork = NULL; do { boost::this_thread::interruption_point(); + if (ShutdownRequested()) + break; CBlockIndex *pindexNewTip = NULL; const CBlockIndex *pindexFork; From 4f7c959af1672f9f51122867dca48ac4fa454d75 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 5 Apr 2016 14:20:49 +0200 Subject: [PATCH 0105/1802] Refactor IsRBFOptIn, avoid exception --- src/policy/rbf.cpp | 15 ++++++++------- src/policy/rbf.h | 8 +++++++- src/wallet/rpcwallet.cpp | 12 ++++-------- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/policy/rbf.cpp b/src/policy/rbf.cpp index 98b1a1ba4c735..133cff611d34b 100644 --- a/src/policy/rbf.cpp +++ b/src/policy/rbf.cpp @@ -14,33 +14,34 @@ bool SignalsOptInRBF(const CTransaction &tx) return false; } -bool IsRBFOptIn(const CTxMemPoolEntry &entry, CTxMemPool &pool) +RBFTransactionState IsRBFOptIn(const CTransaction &tx, CTxMemPool &pool) { AssertLockHeld(pool.cs); CTxMemPool::setEntries setAncestors; // First check the transaction itself. - if (SignalsOptInRBF(entry.GetTx())) { - return true; + if (SignalsOptInRBF(tx)) { + return RBF_TRANSACTIONSTATE_REPLACEABLE_BIP125; } // If this transaction is not in our mempool, then we can't be sure // we will know about all its inputs. - if (!pool.exists(entry.GetTx().GetHash())) { - throw std::runtime_error("Cannot determine RBF opt-in signal for non-mempool transaction\n"); + if (!pool.exists(tx.GetHash())) { + return RBF_TRANSACTIONSTATE_UNKNOWN; } // If all the inputs have nSequence >= maxint-1, it still might be // signaled for RBF if any unconfirmed parents have signaled. uint64_t noLimit = std::numeric_limits::max(); std::string dummy; + CTxMemPoolEntry entry = *pool.mapTx.find(tx.GetHash()); pool.CalculateMemPoolAncestors(entry, setAncestors, noLimit, noLimit, noLimit, noLimit, dummy, false); BOOST_FOREACH(CTxMemPool::txiter it, setAncestors) { if (SignalsOptInRBF(it->GetTx())) { - return true; + return RBF_TRANSACTIONSTATE_REPLACEABLE_BIP125; } } - return false; + return RBF_TRANSACTIONSTATE_FINAL; } diff --git a/src/policy/rbf.h b/src/policy/rbf.h index 925ce0d9bd14a..5a711dba07370 100644 --- a/src/policy/rbf.h +++ b/src/policy/rbf.h @@ -7,6 +7,12 @@ #include "txmempool.h" +enum RBFTransactionState { + RBF_TRANSACTIONSTATE_UNKNOWN, + RBF_TRANSACTIONSTATE_REPLACEABLE_BIP125, + RBF_TRANSACTIONSTATE_FINAL +}; + // Check whether the sequence numbers on this transaction are signaling // opt-in to replace-by-fee, according to BIP 125 bool SignalsOptInRBF(const CTransaction &tx); @@ -15,6 +21,6 @@ bool SignalsOptInRBF(const CTransaction &tx); // according to BIP 125 // This involves checking sequence numbers of the transaction, as well // as the sequence numbers of all in-mempool ancestors. -bool IsRBFOptIn(const CTxMemPoolEntry &entry, CTxMemPool &pool); +RBFTransactionState IsRBFOptIn(const CTransaction &tx, CTxMemPool &pool); #endif // BITCOIN_POLICY_RBF_H diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 61c9846e114b3..5511e9d3aba41 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -82,15 +82,11 @@ void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry) std::string rbfStatus = "no"; if (confirms <= 0) { LOCK(mempool.cs); - if (!mempool.exists(hash)) { - if (SignalsOptInRBF(wtx)) { - rbfStatus = "yes"; - } else { - rbfStatus = "unknown"; - } - } else if (IsRBFOptIn(*mempool.mapTx.find(hash), mempool)) { + RBFTransactionState rbfState = IsRBFOptIn(wtx, mempool); + if (rbfState == RBF_TRANSACTIONSTATE_UNKNOWN) + rbfStatus = "unknown"; + else if (rbfState == RBF_TRANSACTIONSTATE_REPLACEABLE_BIP125) rbfStatus = "yes"; - } } entry.push_back(Pair("bip125-replaceable", rbfStatus)); From 9f7336b4575b15193151dbf08b09562529a24363 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 5 Apr 2016 10:45:11 +0200 Subject: [PATCH 0106/1802] [Wallet] slightly refactor GetOldestKeyPoolTime() --- src/wallet/wallet.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index e8c946671044c..15b9af852b6f3 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2611,12 +2611,19 @@ bool CWallet::GetKeyFromPool(CPubKey& result) int64_t CWallet::GetOldestKeyPoolTime() { - int64_t nIndex = 0; - CKeyPool keypool; - ReserveKeyFromKeyPool(nIndex, keypool); - if (nIndex == -1) + LOCK(cs_wallet); + + // if the keypool is empty, return + if (setKeyPool.empty()) return GetTime(); - ReturnKey(nIndex); + + // load oldest key from keypool, get time and return + CKeyPool keypool; + CWalletDB walletdb(strWalletFile); + int64_t nIndex = *(setKeyPool.begin()); + if (!walletdb.ReadPool(nIndex, keypool)) + throw runtime_error("GetOldestKeyPoolTime(): read oldest key in keypool failed"); + assert(keypool.vchPubKey.IsValid()); return keypool.nTime; } From bf477bcc794360c145156c9e8f155e0215f70dd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Tim=C3=B3n?= Date: Wed, 6 Apr 2016 16:00:25 +0200 Subject: [PATCH 0107/1802] Trivial: Globals: Explicitly pass const CChainParams& to ProcessMessage() --- src/main.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index b68c6affae7f9..4e94ab780999d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4475,9 +4475,8 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam } } -bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived) +bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams) { - const CChainParams& chainparams = Params(); RandAddSeedPerfmon(); LogPrint("net", "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->id); if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0) @@ -5487,7 +5486,7 @@ bool ProcessMessages(CNode* pfrom) bool fRet = false; try { - fRet = ProcessMessage(pfrom, strCommand, vRecv, msg.nTime); + fRet = ProcessMessage(pfrom, strCommand, vRecv, msg.nTime, chainparams); boost::this_thread::interruption_point(); } catch (const std::ios_base::failure& e) From 2d1d6581eca4508838cd339cc19c72efc42d6ea0 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 3 Apr 2016 15:24:09 +0200 Subject: [PATCH 0108/1802] Track block download times per individual block Currently, we're keeping a timeout for each requested block, starting from when it is requested, with a correction factor for the number of blocks in the queue. That's unnecessarily complicated and inaccurate. As peers process block requests in order, we can make the timeout for each block start counting only when all previous ones have been received, and have a correction based on the number of peers, rather than the total number of blocks. --- src/main.cpp | 60 +++++++++++++++++++++++++--------------------------- src/main.h | 4 ++++ 2 files changed, 33 insertions(+), 31 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index b68c6affae7f9..de74593bb1858 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -195,15 +195,10 @@ namespace { struct QueuedBlock { uint256 hash; CBlockIndex* pindex; //!< Optional. - int64_t nTime; //!< Time of "getdata" request in microseconds. bool fValidatedHeaders; //!< Whether this block has validated headers at the time of request. - int64_t nTimeDisconnect; //!< The timeout for this block request (for disconnecting a slow peer) }; map::iterator> > mapBlocksInFlight; - /** Number of blocks in flight with validated headers. */ - int nQueuedValidatedHeaders = 0; - /** Number of preferable block download peers. */ int nPreferredDownload = 0; @@ -212,6 +207,9 @@ namespace { /** Dirty block file entries. */ set setDirtyFileInfo; + + /** Number of peers from which we're downloading blocks. */ + int nPeersWithValidatedDownloads = 0; } // anon namespace ////////////////////////////////////////////////////////////////////////////// @@ -259,6 +257,8 @@ struct CNodeState { //! Since when we're stalling block download progress (in microseconds), or 0. int64_t nStallingSince; list vBlocksInFlight; + //! When the first entry in vBlocksInFlight started downloading. Don't care when vBlocksInFlight is empty. + int64_t nDownloadingSince; int nBlocksInFlight; int nBlocksInFlightValidHeaders; //! Whether we consider this a preferred download peer. @@ -276,6 +276,7 @@ struct CNodeState { pindexBestHeaderSent = NULL; fSyncStarted = false; nStallingSince = 0; + nDownloadingSince = 0; nBlocksInFlight = 0; nBlocksInFlightValidHeaders = 0; fPreferredDownload = false; @@ -310,12 +311,6 @@ void UpdatePreferredDownload(CNode* node, CNodeState* state) nPreferredDownload += state->fPreferredDownload; } -// Returns time at which to timeout block request (nTime in microseconds) -int64_t GetBlockTimeout(int64_t nTime, int nValidatedQueuedBefore, const Consensus::Params &consensusParams) -{ - return nTime + 500000 * consensusParams.nPowTargetSpacing * (4 + nValidatedQueuedBefore); -} - void InitializeNode(NodeId nodeid, const CNode *pnode) { LOCK(cs_main); CNodeState &state = mapNodeState.insert(std::make_pair(nodeid, CNodeState())).first->second; @@ -335,11 +330,12 @@ void FinalizeNode(NodeId nodeid) { } BOOST_FOREACH(const QueuedBlock& entry, state->vBlocksInFlight) { - nQueuedValidatedHeaders -= entry.fValidatedHeaders; mapBlocksInFlight.erase(entry.hash); } EraseOrphansFor(nodeid); nPreferredDownload -= state->fPreferredDownload; + nPeersWithValidatedDownloads -= (state->nBlocksInFlightValidHeaders != 0); + assert(nPeersWithValidatedDownloads >= 0); mapNodeState.erase(nodeid); } @@ -350,8 +346,15 @@ bool MarkBlockAsReceived(const uint256& hash) { map::iterator> >::iterator itInFlight = mapBlocksInFlight.find(hash); if (itInFlight != mapBlocksInFlight.end()) { CNodeState *state = State(itInFlight->second.first); - nQueuedValidatedHeaders -= itInFlight->second.second->fValidatedHeaders; state->nBlocksInFlightValidHeaders -= itInFlight->second.second->fValidatedHeaders; + if (state->nBlocksInFlightValidHeaders == 0 && itInFlight->second.second->fValidatedHeaders) { + // Last validated block on the queue was received. + nPeersWithValidatedDownloads--; + } + if (state->vBlocksInFlight.begin() == itInFlight->second.second) { + // First block on the queue was received, update the start download time for the next one + state->nDownloadingSince = std::max(state->nDownloadingSince, GetTimeMicros()); + } state->vBlocksInFlight.erase(itInFlight->second.second); state->nBlocksInFlight--; state->nStallingSince = 0; @@ -369,12 +372,17 @@ void MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, const Consensus::Pa // Make sure it's not listed somewhere already. MarkBlockAsReceived(hash); - int64_t nNow = GetTimeMicros(); - QueuedBlock newentry = {hash, pindex, nNow, pindex != NULL, GetBlockTimeout(nNow, nQueuedValidatedHeaders, consensusParams)}; - nQueuedValidatedHeaders += newentry.fValidatedHeaders; + QueuedBlock newentry = {hash, pindex, pindex != NULL}; list::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(), newentry); state->nBlocksInFlight++; state->nBlocksInFlightValidHeaders += newentry.fValidatedHeaders; + if (state->nBlocksInFlight == 1) { + // We're starting a block download (batch) from this peer. + state->nDownloadingSince = GetTimeMicros(); + } + if (state->nBlocksInFlightValidHeaders == 1 && pindex != NULL) { + nPeersWithValidatedDownloads++; + } mapBlocksInFlight[hash] = std::make_pair(nodeid, it); } @@ -3894,7 +3902,6 @@ void UnloadBlockIndex() nBlockSequenceId = 1; mapBlockSource.clear(); mapBlocksInFlight.clear(); - nQueuedValidatedHeaders = 0; nPreferredDownload = 0; setDirtyBlockIndex.clear(); setDirtyFileInfo.clear(); @@ -5811,24 +5818,15 @@ bool SendMessages(CNode* pto) LogPrintf("Peer=%d is stalling block download, disconnecting\n", pto->id); pto->fDisconnect = true; } - // In case there is a block that has been in flight from this peer for (2 + 0.5 * N) times the block interval - // (with N the number of validated blocks that were in flight at the time it was requested), disconnect due to - // timeout. We compensate for in-flight blocks to prevent killing off peers due to our own downstream link + // In case there is a block that has been in flight from this peer for 2 + 0.5 * N times the block interval + // (with N the number of peers from which we're downloading validated blocks), disconnect due to timeout. + // We compensate for other peers to prevent killing off peers due to our own downstream link // being saturated. We only count validated in-flight blocks so peers can't advertise non-existing block hashes // to unreasonably increase our timeout. - // We also compare the block download timeout originally calculated against the time at which we'd disconnect - // if we assumed the block were being requested now (ignoring blocks we've requested from this peer, since we're - // only looking at this peer's oldest request). This way a large queue in the past doesn't result in a - // permanently large window for this block to be delivered (ie if the number of blocks in flight is decreasing - // more quickly than once every 5 minutes, then we'll shorten the download window for this block). if (!pto->fDisconnect && state.vBlocksInFlight.size() > 0) { QueuedBlock &queuedBlock = state.vBlocksInFlight.front(); - int64_t nTimeoutIfRequestedNow = GetBlockTimeout(nNow, nQueuedValidatedHeaders - state.nBlocksInFlightValidHeaders, consensusParams); - if (queuedBlock.nTimeDisconnect > nTimeoutIfRequestedNow) { - LogPrint("net", "Reducing block download timeout for peer=%d block=%s, orig=%d new=%d\n", pto->id, queuedBlock.hash.ToString(), queuedBlock.nTimeDisconnect, nTimeoutIfRequestedNow); - queuedBlock.nTimeDisconnect = nTimeoutIfRequestedNow; - } - if (queuedBlock.nTimeDisconnect < nNow) { + int nOtherPeersWithValidatedDownloads = nPeersWithValidatedDownloads - (state.nBlocksInFlightValidHeaders > 0); + if (nNow > state.nDownloadingSince + consensusParams.nPowTargetSpacing * (BLOCK_DOWNLOAD_TIMEOUT_BASE + BLOCK_DOWNLOAD_TIMEOUT_PER_PEER * nOtherPeersWithValidatedDownloads)) { LogPrintf("Timeout downloading block %s from peer=%d, disconnecting\n", queuedBlock.hash.ToString(), pto->id); pto->fDisconnect = true; } diff --git a/src/main.h b/src/main.h index 3ea9dc500ca64..68fcf8e7c986e 100644 --- a/src/main.h +++ b/src/main.h @@ -106,6 +106,10 @@ static const unsigned int AVG_INVENTORY_BROADCAST_INTERVAL = 5; static const unsigned int AVG_FEEFILTER_BROADCAST_INTERVAL = 10 * 60; /** Maximum feefilter broadcast delay after significant change. */ static const unsigned int MAX_FEEFILTER_CHANGE_DELAY = 5 * 60; +/** Block download timeout base, expressed in millionths of the block interval (i.e. 20 min) */ +static const int64_t BLOCK_DOWNLOAD_TIMEOUT_BASE = 2000000; +/** Additional block download timeout per parallel downloading peer (i.e. 5 min) */ +static const int64_t BLOCK_DOWNLOAD_TIMEOUT_PER_PEER = 500000; static const unsigned int DEFAULT_LIMITFREERELAY = 15; static const bool DEFAULT_RELAYPRIORITY = true; From 0e24bbf679c95784ed5514a6a1f2fbf99dd97725 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 4 Apr 2016 13:35:26 +0200 Subject: [PATCH 0109/1802] Self check after the last peer is removed --- src/main.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index de74593bb1858..87c727b28feef 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -338,6 +338,13 @@ void FinalizeNode(NodeId nodeid) { assert(nPeersWithValidatedDownloads >= 0); mapNodeState.erase(nodeid); + + if (mapNodeState.empty()) { + // Do a consistency check after the last peer is removed. + assert(mapBlocksInFlight.empty()); + assert(nPreferredDownload == 0); + assert(nPeersWithValidatedDownloads == 0); + } } // Requires cs_main. From 62b9a557fca2aa55803c336ffcceccc50ccf0c3e Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 7 Apr 2016 13:18:11 +0200 Subject: [PATCH 0110/1802] Reduce block timeout to 10 minutes Now that #7804 fixed the timeout handling, reduce the block timeout from 20 minutes to 10 minutes. 20 minutes is overkill. --- src/main.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.h b/src/main.h index 68fcf8e7c986e..0962f44e9439e 100644 --- a/src/main.h +++ b/src/main.h @@ -106,8 +106,8 @@ static const unsigned int AVG_INVENTORY_BROADCAST_INTERVAL = 5; static const unsigned int AVG_FEEFILTER_BROADCAST_INTERVAL = 10 * 60; /** Maximum feefilter broadcast delay after significant change. */ static const unsigned int MAX_FEEFILTER_CHANGE_DELAY = 5 * 60; -/** Block download timeout base, expressed in millionths of the block interval (i.e. 20 min) */ -static const int64_t BLOCK_DOWNLOAD_TIMEOUT_BASE = 2000000; +/** Block download timeout base, expressed in millionths of the block interval (i.e. 10 min) */ +static const int64_t BLOCK_DOWNLOAD_TIMEOUT_BASE = 1000000; /** Additional block download timeout per parallel downloading peer (i.e. 5 min) */ static const int64_t BLOCK_DOWNLOAD_TIMEOUT_PER_PEER = 500000; From 5078ca45438e8f8d8e7cd937659887fb8ec70038 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 7 Apr 2016 15:21:01 +0200 Subject: [PATCH 0111/1802] tests: Check Content-Type header returned from RPC server Check the Content-Type header that is returned from the RPC server. Only if it is `application/json` the data is supposed to be parsed as JSON. This gives better reporting if the HTTP server happens to return an error that is not JSON-formatted, which is the case if it happens at a lower level before JSON-RPC kicks in. Before: `Unexpected exception caught during testing: No JSON object could be decoded` After: `JSONRPC error: non-JSON HTTP response with '403 Forbidden' from server` --- qa/rpc-tests/test_framework/authproxy.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/qa/rpc-tests/test_framework/authproxy.py b/qa/rpc-tests/test_framework/authproxy.py index 1eb2772592265..e5f7ab3656167 100644 --- a/qa/rpc-tests/test_framework/authproxy.py +++ b/qa/rpc-tests/test_framework/authproxy.py @@ -154,6 +154,11 @@ def _get_response(self): raise JSONRPCException({ 'code': -342, 'message': 'missing HTTP response from server'}) + content_type = http_response.getheader('Content-Type') + if content_type != 'application/json': + raise JSONRPCException({ + 'code': -342, 'message': 'non-JSON HTTP response with \'%i %s\' from server' % (http_response.status, http_response.reason)}) + responsedata = http_response.read().decode('utf8') response = json.loads(responsedata, parse_float=decimal.Decimal) if "error" in response and response["error"] is None: From 617deeb06e99d4b5fb76235b6009ec72accb4970 Mon Sep 17 00:00:00 2001 From: instagibbs Date: Mon, 4 Apr 2016 11:17:23 -0400 Subject: [PATCH 0112/1802] Gave miner test values constants for less error-prone values. --- src/test/miner_tests.cpp | 53 ++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index ab6485081ceed..492bed1450856 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -124,6 +124,11 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); delete pblocktemplate; + const CAmount BLOCKSUBSIDY = 50*COIN; + const CAmount LOWFEE = CENT; + const CAmount HIGHFEE = COIN; + const CAmount HIGHERFEE = 4*COIN; + // block sigops > limit: 1000 CHECKMULTISIG + 1 tx.vin.resize(1); // NOTE: OP_NOP is used to force 20 SigOps for the CHECKMULTISIG @@ -131,28 +136,28 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vin[0].prevout.hash = txFirst[0]->GetHash(); tx.vin[0].prevout.n = 0; tx.vout.resize(1); - tx.vout[0].nValue = 5000000000LL; + tx.vout[0].nValue = BLOCKSUBSIDY; for (unsigned int i = 0; i < 1001; ++i) { - tx.vout[0].nValue -= 1000000; + tx.vout[0].nValue -= LOWFEE; hash = tx.GetHash(); bool spendsCoinbase = (i == 0) ? true : false; // only first tx spends coinbase // If we don't set the # of sig ops in the CTxMemPoolEntry, template creation fails - mempool.addUnchecked(hash, entry.Fee(1000000).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx)); + mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx)); tx.vin[0].prevout.hash = hash; } BOOST_CHECK_THROW(CreateNewBlock(chainparams, scriptPubKey), std::runtime_error); mempool.clear(); tx.vin[0].prevout.hash = txFirst[0]->GetHash(); - tx.vout[0].nValue = 5000000000LL; + tx.vout[0].nValue = BLOCKSUBSIDY; for (unsigned int i = 0; i < 1001; ++i) { - tx.vout[0].nValue -= 1000000; + tx.vout[0].nValue -= LOWFEE; hash = tx.GetHash(); bool spendsCoinbase = (i == 0) ? true : false; // only first tx spends coinbase // If we do set the # of sig ops in the CTxMemPoolEntry, template creation passes - mempool.addUnchecked(hash, entry.Fee(1000000).Time(GetTime()).SpendsCoinbase(spendsCoinbase).SigOps(20).FromTx(tx)); + mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).SigOps(20).FromTx(tx)); tx.vin[0].prevout.hash = hash; } BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); @@ -167,13 +172,13 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vin[0].scriptSig << vchData << OP_DROP; tx.vin[0].scriptSig << OP_1; tx.vin[0].prevout.hash = txFirst[0]->GetHash(); - tx.vout[0].nValue = 5000000000LL; + tx.vout[0].nValue = BLOCKSUBSIDY; for (unsigned int i = 0; i < 128; ++i) { - tx.vout[0].nValue -= 10000000; + tx.vout[0].nValue -= 10*LOWFEE; hash = tx.GetHash(); bool spendsCoinbase = (i == 0) ? true : false; // only first tx spends coinbase - mempool.addUnchecked(hash, entry.Fee(1000000).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx)); + mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx)); tx.vin[0].prevout.hash = hash; } BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); @@ -182,24 +187,24 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) // orphan in mempool, template creation fails hash = tx.GetHash(); - mempool.addUnchecked(hash, entry.Fee(1000000).Time(GetTime()).FromTx(tx)); + mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).FromTx(tx)); BOOST_CHECK_THROW(CreateNewBlock(chainparams, scriptPubKey), std::runtime_error); mempool.clear(); // child with higher priority than parent tx.vin[0].scriptSig = CScript() << OP_1; tx.vin[0].prevout.hash = txFirst[1]->GetHash(); - tx.vout[0].nValue = 4900000000LL; + tx.vout[0].nValue = BLOCKSUBSIDY-HIGHFEE; hash = tx.GetHash(); - mempool.addUnchecked(hash, entry.Fee(100000000LL).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); + mempool.addUnchecked(hash, entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); tx.vin[0].prevout.hash = hash; tx.vin.resize(2); tx.vin[1].scriptSig = CScript() << OP_1; tx.vin[1].prevout.hash = txFirst[0]->GetHash(); tx.vin[1].prevout.n = 0; - tx.vout[0].nValue = 5900000000LL; + tx.vout[0].nValue = tx.vout[0].nValue+BLOCKSUBSIDY-HIGHERFEE; //First txn output + fresh coinbase - new txn fee hash = tx.GetHash(); - mempool.addUnchecked(hash, entry.Fee(400000000LL).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); + mempool.addUnchecked(hash, entry.Fee(HIGHERFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); delete pblocktemplate; mempool.clear(); @@ -211,7 +216,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].nValue = 0; hash = tx.GetHash(); // give it a fee so it'll get mined - mempool.addUnchecked(hash, entry.Fee(100000).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); + mempool.addUnchecked(hash, entry.Fee(LOWFEE/10).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); BOOST_CHECK_THROW(CreateNewBlock(chainparams, scriptPubKey), std::runtime_error); mempool.clear(); @@ -219,29 +224,29 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vin[0].prevout.hash = txFirst[0]->GetHash(); tx.vin[0].prevout.n = 0; tx.vin[0].scriptSig = CScript() << OP_1; - tx.vout[0].nValue = 4900000000LL; + tx.vout[0].nValue = BLOCKSUBSIDY-LOWFEE; script = CScript() << OP_0; tx.vout[0].scriptPubKey = GetScriptForDestination(CScriptID(script)); hash = tx.GetHash(); - mempool.addUnchecked(hash, entry.Fee(10000000L).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); + mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); tx.vin[0].prevout.hash = hash; tx.vin[0].scriptSig = CScript() << std::vector(script.begin(), script.end()); - tx.vout[0].nValue -= 1000000; + tx.vout[0].nValue -= LOWFEE; hash = tx.GetHash(); - mempool.addUnchecked(hash, entry.Fee(1000000).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); + mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); BOOST_CHECK_THROW(CreateNewBlock(chainparams, scriptPubKey), std::runtime_error); mempool.clear(); // double spend txn pair in mempool, template creation fails tx.vin[0].prevout.hash = txFirst[0]->GetHash(); tx.vin[0].scriptSig = CScript() << OP_1; - tx.vout[0].nValue = 4900000000LL; + tx.vout[0].nValue = BLOCKSUBSIDY-HIGHFEE; tx.vout[0].scriptPubKey = CScript() << OP_1; hash = tx.GetHash(); - mempool.addUnchecked(hash, entry.Fee(100000000L).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); + mempool.addUnchecked(hash, entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); tx.vout[0].scriptPubKey = CScript() << OP_2; hash = tx.GetHash(); - mempool.addUnchecked(hash, entry.Fee(100000000L).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); + mempool.addUnchecked(hash, entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); BOOST_CHECK_THROW(CreateNewBlock(chainparams, scriptPubKey), std::runtime_error); mempool.clear(); @@ -298,11 +303,11 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vin[0].nSequence = chainActive.Tip()->nHeight + 1; // txFirst[0] is the 2nd block prevheights[0] = baseheight + 1; tx.vout.resize(1); - tx.vout[0].nValue = 4900000000LL; + tx.vout[0].nValue = BLOCKSUBSIDY-HIGHFEE; tx.vout[0].scriptPubKey = CScript() << OP_1; tx.nLockTime = 0; hash = tx.GetHash(); - mempool.addUnchecked(hash, entry.Fee(100000000L).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); + mempool.addUnchecked(hash, entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); BOOST_CHECK(CheckFinalTx(tx, flags)); // Locktime passes BOOST_CHECK(!TestSequenceLocks(tx, flags)); // Sequence locks fail BOOST_CHECK(SequenceLocks(tx, flags, &prevheights, CreateBlockIndex(chainActive.Tip()->nHeight + 2))); // Sequence locks pass on 2nd block From f8536a62c318aeb1049479568aa8c4b6b03e87a6 Mon Sep 17 00:00:00 2001 From: instagibbs Date: Wed, 6 Apr 2016 08:29:19 -0400 Subject: [PATCH 0113/1802] Corrected values --- src/test/miner_tests.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 492bed1450856..469862518c58c 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -175,7 +175,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].nValue = BLOCKSUBSIDY; for (unsigned int i = 0; i < 128; ++i) { - tx.vout[0].nValue -= 10*LOWFEE; + tx.vout[0].nValue -= LOWFEE; hash = tx.GetHash(); bool spendsCoinbase = (i == 0) ? true : false; // only first tx spends coinbase mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx)); @@ -216,7 +216,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].nValue = 0; hash = tx.GetHash(); // give it a fee so it'll get mined - mempool.addUnchecked(hash, entry.Fee(LOWFEE/10).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); + mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); BOOST_CHECK_THROW(CreateNewBlock(chainparams, scriptPubKey), std::runtime_error); mempool.clear(); From e4ba9f6b0402cf7a2ad0d74f617c434a26c6e124 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Thu, 7 Apr 2016 14:33:08 -0400 Subject: [PATCH 0114/1802] Version 2 transactions remain non-standard until CSV activates Before activation, such transactions might not be mined, so don't allow into the mempool. --- src/main.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index a9f104c88bee6..f5c7e11d6e8a3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1025,6 +1025,14 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C if (fRequireStandard && !IsStandardTx(tx, reason)) return state.DoS(0, false, REJECT_NONSTANDARD, reason); + // Don't relay version 2 transactions until CSV is active, and we can be + // sure that such transactions will be mined (unless we're on + // -testnet/-regtest). + const CChainParams& chainparams = Params(); + if (fRequireStandard && tx.nVersion >= 2 && VersionBitsTipState(chainparams.GetConsensus(), Consensus::DEPLOYMENT_CSV) != THRESHOLD_ACTIVE) { + return state.DoS(0, false, REJECT_NONSTANDARD, "premature-version2-tx"); + } + // Only accept nLockTime-using transactions that can be mined in the next // block; we don't want our mempool filled up with transactions that can't // be mined yet. From 5cb1d8a2071d05beb9907a423178895fd8a5c359 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Thu, 7 Apr 2016 14:54:50 -0400 Subject: [PATCH 0115/1802] Tests: move get_bip9_status to util.py --- qa/rpc-tests/bip68-112-113-p2p.py | 19 ++++++------------- qa/rpc-tests/test_framework/util.py | 7 +++++++ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/qa/rpc-tests/bip68-112-113-p2p.py b/qa/rpc-tests/bip68-112-113-p2p.py index f391cb0b7aab4..35c831cb8b71d 100755 --- a/qa/rpc-tests/bip68-112-113-p2p.py +++ b/qa/rpc-tests/bip68-112-113-p2p.py @@ -149,13 +149,6 @@ def create_test_block(self, txs, version = 536870912): block.solve() return block - def get_bip9_status(self, key): - info = self.nodes[0].getblockchaininfo() - for row in info['bip9_softforks']: - if row['id'] == key: - return row - raise IndexError ('key:"%s" not found' % key) - def create_bip68txs(self, bip68inputs, txversion, locktime_delta = 0): txs = [] assert(len(bip68inputs) >= 16) @@ -223,11 +216,11 @@ def get_tests(self): self.tip = int ("0x" + self.nodes[0].getbestblockhash() + "L", 0) self.nodeaddress = self.nodes[0].getnewaddress() - assert_equal(self.get_bip9_status('csv')['status'], 'defined') + assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'defined') test_blocks = self.generate_blocks(61, 4) yield TestInstance(test_blocks, sync_every_block=False) # 1 # Advanced from DEFINED to STARTED, height = 143 - assert_equal(self.get_bip9_status('csv')['status'], 'started') + assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'started') # Fail to achieve LOCKED_IN 100 out of 144 signal bit 0 # using a variety of bits to simulate multiple parallel softforks @@ -237,7 +230,7 @@ def get_tests(self): test_blocks = self.generate_blocks(24, 536936448, test_blocks) # 0x20010000 (signalling not) yield TestInstance(test_blocks, sync_every_block=False) # 2 # Failed to advance past STARTED, height = 287 - assert_equal(self.get_bip9_status('csv')['status'], 'started') + assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'started') # 108 out of 144 signal bit 0 to achieve lock-in # using a variety of bits to simulate multiple parallel softforks @@ -247,7 +240,7 @@ def get_tests(self): test_blocks = self.generate_blocks(10, 536936448, test_blocks) # 0x20010000 (signalling not) yield TestInstance(test_blocks, sync_every_block=False) # 3 # Advanced from STARTED to LOCKED_IN, height = 431 - assert_equal(self.get_bip9_status('csv')['status'], 'locked_in') + assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'locked_in') # 140 more version 4 blocks test_blocks = self.generate_blocks(140, 4) @@ -291,7 +284,7 @@ def get_tests(self): test_blocks = self.generate_blocks(2, 4) yield TestInstance(test_blocks, sync_every_block=False) # 5 # Not yet advanced to ACTIVE, height = 574 (will activate for block 576, not 575) - assert_equal(self.get_bip9_status('csv')['status'], 'locked_in') + assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'locked_in') # Test both version 1 and version 2 transactions for all tests # BIP113 test transaction will be modified before each use to put in appropriate block time @@ -368,7 +361,7 @@ def get_tests(self): # 1 more version 4 block to get us to height 575 so the fork should now be active for the next block test_blocks = self.generate_blocks(1, 4) yield TestInstance(test_blocks, sync_every_block=False) # 8 - assert_equal(self.get_bip9_status('csv')['status'], 'active') + assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'active') ################################# diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index f069c32a607ba..d9fe0f75f2608 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -545,3 +545,10 @@ def create_lots_of_big_transactions(node, txouts, utxos, fee): txid = node.sendrawtransaction(signresult["hex"], True) txids.append(txid) return txids + +def get_bip9_status(node, key): + info = node.getblockchaininfo() + for row in info['bip9_softforks']: + if row['id'] == key: + return row + raise IndexError ('key:"%s" not found' % key) From da5fdbb3a2778523cce70d635c1aa2b31a693bc6 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Thu, 7 Apr 2016 14:59:50 -0400 Subject: [PATCH 0116/1802] Test relay of version 2 transactions --- qa/rpc-tests/bip68-sequence.py | 46 +++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/qa/rpc-tests/bip68-sequence.py b/qa/rpc-tests/bip68-sequence.py index 377a35b6872c7..33e05dfc51a09 100755 --- a/qa/rpc-tests/bip68-sequence.py +++ b/qa/rpc-tests/bip68-sequence.py @@ -4,7 +4,7 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. # -# Test BIP68 implementation (mempool only) +# Test BIP68 implementation # from test_framework.test_framework import BitcoinTestFramework @@ -26,8 +26,10 @@ class BIP68Test(BitcoinTestFramework): def setup_network(self): self.nodes = [] self.nodes.append(start_node(0, self.options.tmpdir, ["-debug", "-blockprioritysize=0"])) + self.nodes.append(start_node(1, self.options.tmpdir, ["-debug", "-blockprioritysize=0", "-acceptnonstdtxn=0"])) self.is_network_split = False self.relayfee = self.nodes[0].getnetworkinfo()["relayfee"] + connect_nodes(self.nodes[0], 1) def run_test(self): # Generate some coins @@ -42,10 +44,18 @@ def run_test(self): print "Running test sequence-lock-unconfirmed-inputs" self.test_sequence_lock_unconfirmed_inputs() - # This test needs to change when BIP68 becomes consensus - print "Running test BIP68 not consensus" + print "Running test BIP68 not consensus before versionbits activation" self.test_bip68_not_consensus() + print "Verifying nVersion=2 transactions aren't standard" + self.test_version2_relay(before_activation=True) + + print "Activating BIP68 (and 112/113)" + self.activateCSV() + + print "Verifying nVersion=2 transactions are now standard" + self.test_version2_relay(before_activation=False) + print "Passed\n" # Test that BIP68 is not in effect if tx version is 1, or if @@ -333,8 +343,12 @@ def test_nonzero_locks(orig_tx, node, relayfee, use_height_lock): self.nodes[0].invalidateblock(self.nodes[0].getblockhash(cur_height+1)) self.nodes[0].generate(10) - # Make sure that BIP68 isn't being used to validate blocks. + # Make sure that BIP68 isn't being used to validate blocks, prior to + # versionbits activation. If more blocks are mined prior to this test + # being run, then it's possible the test has activated the soft fork, and + # this test should be moved to run earlier, or deleted. def test_bip68_not_consensus(self): + assert(get_bip9_status(self.nodes[0], 'csv')['status'] != 'active') txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 2) tx1 = FromHex(CTransaction(), self.nodes[0].getrawtransaction(txid)) @@ -381,6 +395,30 @@ def test_bip68_not_consensus(self): self.nodes[0].submitblock(ToHex(block)) assert_equal(self.nodes[0].getbestblockhash(), block.hash) + def activateCSV(self): + # activation should happen at block height 432 (3 periods) + min_activation_height = 432 + height = self.nodes[0].getblockcount() + assert(height < 432) + self.nodes[0].generate(432-height) + assert(get_bip9_status(self.nodes[0], 'csv')['status'] == 'active') + sync_blocks(self.nodes) + + # Use self.nodes[1] to test standardness relay policy + def test_version2_relay(self, before_activation): + inputs = [ ] + outputs = { self.nodes[1].getnewaddress() : 1.0 } + rawtx = self.nodes[1].createrawtransaction(inputs, outputs) + rawtxfund = self.nodes[1].fundrawtransaction(rawtx)['hex'] + tx = FromHex(CTransaction(), rawtxfund) + tx.nVersion = 2 + tx_signed = self.nodes[1].signrawtransaction(ToHex(tx))["hex"] + try: + tx_id = self.nodes[1].sendrawtransaction(tx_signed) + assert(before_activation == False) + except: + assert(before_activation) + if __name__ == '__main__': BIP68Test().main() From 11114a69c86e9abf4dd7e88ac268f5d078f40913 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 3 Apr 2016 13:18:31 +0200 Subject: [PATCH 0117/1802] [amount] test negative fee rates and full constructor --- src/test/amount_tests.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/test/amount_tests.cpp b/src/test/amount_tests.cpp index 59dab20633ced..c65646474d514 100644 --- a/src/test/amount_tests.cpp +++ b/src/test/amount_tests.cpp @@ -27,6 +27,15 @@ BOOST_AUTO_TEST_CASE(GetFeeTest) BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), 1e3); BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), 9e3); + feeRate = CFeeRate(-1000); + // Must always just return -1 * arg + BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0); + BOOST_CHECK_EQUAL(feeRate.GetFee(1), -1); + BOOST_CHECK_EQUAL(feeRate.GetFee(121), -121); + BOOST_CHECK_EQUAL(feeRate.GetFee(999), -999); + BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), -1e3); + BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), -9e3); + feeRate = CFeeRate(123); // Truncates the result, if not integer BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0); @@ -37,6 +46,26 @@ BOOST_AUTO_TEST_CASE(GetFeeTest) BOOST_CHECK_EQUAL(feeRate.GetFee(999), 122); BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), 123); BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), 1107); + + feeRate = CFeeRate(-123); + // Truncates the result, if not integer + BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0); + BOOST_CHECK_EQUAL(feeRate.GetFee(8), -1); // Special case: returns -1 instead of 0 + BOOST_CHECK_EQUAL(feeRate.GetFee(9), -1); + + // Check full constructor + // default value + BOOST_CHECK(CFeeRate(CAmount(-1), 1000) == CFeeRate(-1)); + BOOST_CHECK(CFeeRate(CAmount(0), 1000) == CFeeRate(0)); + BOOST_CHECK(CFeeRate(CAmount(1), 1000) == CFeeRate(1)); + // lost precision (can only resolve satoshis per kB) + BOOST_CHECK(CFeeRate(CAmount(1), 1001) == CFeeRate(0)); + BOOST_CHECK(CFeeRate(CAmount(2), 1001) == CFeeRate(1)); + // some more integer checks + BOOST_CHECK(CFeeRate(CAmount(26), 789) == CFeeRate(32)); + BOOST_CHECK(CFeeRate(CAmount(27), 789) == CFeeRate(34)); + // Maximum size in bytes, should not crash + CFeeRate(MAX_MONEY, (std::numeric_limits::max() >> 1) - 1).GetFeePerK(); } BOOST_AUTO_TEST_SUITE_END() From fa2da2cb607ba359231fccc9635abe7c8616de56 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 3 Apr 2016 13:44:01 +0200 Subject: [PATCH 0118/1802] [amount] Add support for negative fee rates Currently negative fee rates are not supported on archs of 64-bit or more --- src/amount.cpp | 20 +++++++++++++++----- src/amount.h | 11 +++++++---- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/amount.cpp b/src/amount.cpp index 68806ff062bd9..7b8618de332a6 100644 --- a/src/amount.cpp +++ b/src/amount.cpp @@ -9,20 +9,30 @@ const std::string CURRENCY_UNIT = "BTC"; -CFeeRate::CFeeRate(const CAmount& nFeePaid, size_t nSize) +CFeeRate::CFeeRate(const CAmount& nFeePaid, size_t nBytes_) { + assert(nBytes_ <= uint64_t(std::numeric_limits::max())); + int64_t nSize = int64_t(nBytes_); + if (nSize > 0) - nSatoshisPerK = nFeePaid*1000/nSize; + nSatoshisPerK = nFeePaid * 1000 / nSize; else nSatoshisPerK = 0; } -CAmount CFeeRate::GetFee(size_t nSize) const +CAmount CFeeRate::GetFee(size_t nBytes_) const { + assert(nBytes_ <= uint64_t(std::numeric_limits::max())); + int64_t nSize = int64_t(nBytes_); + CAmount nFee = nSatoshisPerK * nSize / 1000; - if (nFee == 0 && nSize != 0 && nSatoshisPerK > 0) - nFee = CAmount(1); + if (nFee == 0 && nSize != 0) { + if (nSatoshisPerK > 0) + nFee = CAmount(1); + if (nSatoshisPerK < 0) + nFee = CAmount(-1); + } return nFee; } diff --git a/src/amount.h b/src/amount.h index 9aba6525c7f2b..5e52f37f2369d 100644 --- a/src/amount.h +++ b/src/amount.h @@ -11,6 +11,7 @@ #include #include +/** Amount in satoshis (Can be negative) */ typedef int64_t CAmount; static const CAmount COIN = 100000000; @@ -30,22 +31,24 @@ extern const std::string CURRENCY_UNIT; static const CAmount MAX_MONEY = 21000000 * COIN; inline bool MoneyRange(const CAmount& nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); } -/** Type-safe wrapper class for fee rates - * (how much to pay based on transaction size) +/** + * Fee rate in satoshis per kilobyte: CAmount / kB */ class CFeeRate { private: CAmount nSatoshisPerK; // unit is satoshis-per-1,000-bytes public: + /** Fee rate of 0 satoshis per kB */ CFeeRate() : nSatoshisPerK(0) { } explicit CFeeRate(const CAmount& _nSatoshisPerK): nSatoshisPerK(_nSatoshisPerK) { } - CFeeRate(const CAmount& nFeePaid, size_t nSize); + /** Constructor for a fee rate in satoshis per kB. The size in bytes must not exceed (2^63 - 1)*/ + CFeeRate(const CAmount& nFeePaid, size_t nBytes); CFeeRate(const CFeeRate& other) { nSatoshisPerK = other.nSatoshisPerK; } /** * Return the fee in satoshis for the given size in bytes. */ - CAmount GetFee(size_t size) const; + CAmount GetFee(size_t nBytes) const; /** * Return the fee in satoshis for a size of 1000 bytes */ From 03c77fdc143fb8d533011f23164daac560e381b2 Mon Sep 17 00:00:00 2001 From: Matthew English Date: Fri, 1 Apr 2016 23:44:26 +0200 Subject: [PATCH 0119/1802] Doc: Update isStandardTx comment --- src/policy/policy.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index e3ed7be0008ee..d1a15451dc1f6 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -73,12 +73,12 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason) BOOST_FOREACH(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 + // 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) + // considered standard. if (txin.scriptSig.size() > 1650) { reason = "scriptsig-size"; return false; From 4521f005a1e61969f21b91a7e8eef5a5cdfdd191 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sat, 9 Apr 2016 06:52:43 +0200 Subject: [PATCH 0120/1802] tests: add varints_bitpatterns test The current tests for varint only check that serialization-deserialization is a roundtrip. That is a useful test, but it is also good to check for some exact bit patterns, to prevent a code change that changes the serialization format from going undetected. As the varint functions are templated, also check with different types. --- src/test/serialize_tests.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp index c0fd99aca2e67..bec2c7459d8c9 100644 --- a/src/test/serialize_tests.cpp +++ b/src/test/serialize_tests.cpp @@ -160,6 +160,27 @@ BOOST_AUTO_TEST_CASE(varints) } } +BOOST_AUTO_TEST_CASE(varints_bitpatterns) +{ + CDataStream ss(SER_DISK, 0); + ss << VARINT(0); BOOST_CHECK_EQUAL(HexStr(ss), "00"); ss.clear(); + ss << VARINT(0x7f); BOOST_CHECK_EQUAL(HexStr(ss), "7f"); ss.clear(); + ss << VARINT((int8_t)0x7f); BOOST_CHECK_EQUAL(HexStr(ss), "7f"); ss.clear(); + ss << VARINT(0x80); BOOST_CHECK_EQUAL(HexStr(ss), "8000"); ss.clear(); + ss << VARINT((uint8_t)0x80); BOOST_CHECK_EQUAL(HexStr(ss), "8000"); ss.clear(); + ss << VARINT(0x1234); BOOST_CHECK_EQUAL(HexStr(ss), "a334"); ss.clear(); + ss << VARINT((int16_t)0x1234); BOOST_CHECK_EQUAL(HexStr(ss), "a334"); ss.clear(); + ss << VARINT(0xffff); BOOST_CHECK_EQUAL(HexStr(ss), "82fe7f"); ss.clear(); + ss << VARINT((uint16_t)0xffff); BOOST_CHECK_EQUAL(HexStr(ss), "82fe7f"); ss.clear(); + ss << VARINT(0x123456); BOOST_CHECK_EQUAL(HexStr(ss), "c7e756"); ss.clear(); + ss << VARINT((int32_t)0x123456); BOOST_CHECK_EQUAL(HexStr(ss), "c7e756"); ss.clear(); + ss << VARINT(0x80123456U); BOOST_CHECK_EQUAL(HexStr(ss), "86ffc7e756"); ss.clear(); + ss << VARINT((uint32_t)0x80123456U); BOOST_CHECK_EQUAL(HexStr(ss), "86ffc7e756"); ss.clear(); + ss << VARINT(0xffffffff); BOOST_CHECK_EQUAL(HexStr(ss), "8efefefe7f"); ss.clear(); + ss << VARINT(0x7fffffffffffffffLL); BOOST_CHECK_EQUAL(HexStr(ss), "fefefefefefefefe7f"); ss.clear(); + ss << VARINT(0xffffffffffffffffULL); BOOST_CHECK_EQUAL(HexStr(ss), "80fefefefefefefefe7f"); ss.clear(); +} + BOOST_AUTO_TEST_CASE(compactsize) { CDataStream ss(SER_DISK, 0); From 62a64860580253d9c733f3b8826908bba40eab1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Fri, 8 Apr 2016 18:52:59 +0200 Subject: [PATCH 0121/1802] RPC: do not print ping info in getpeerinfo when no ping received yet, fix help --- src/rpc/net.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 017cd6ca32187..ce14d034ce1fd 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -97,9 +97,9 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp) " \"bytesrecv\": n, (numeric) The total bytes received\n" " \"conntime\": ttt, (numeric) The connection time in seconds since epoch (Jan 1 1970 GMT)\n" " \"timeoffset\": ttt, (numeric) The time offset in seconds\n" - " \"pingtime\": n, (numeric) ping time\n" - " \"minping\": n, (numeric) minimum observed ping time\n" - " \"pingwait\": n, (numeric) ping wait\n" + " \"pingtime\": n, (numeric) ping time (if available)\n" + " \"minping\": n, (numeric) minimum observed ping time (if any at all)\n" + " \"pingwait\": n, (numeric) ping wait (if non-zero)\n" " \"version\": v, (numeric) The peer version, such as 7001\n" " \"subver\": \"/Satoshi:0.8.5/\", (string) The string version\n" " \"inbound\": true|false, (boolean) Inbound (true) or Outbound (false)\n" @@ -150,8 +150,10 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp) obj.push_back(Pair("bytesrecv", stats.nRecvBytes)); obj.push_back(Pair("conntime", stats.nTimeConnected)); obj.push_back(Pair("timeoffset", stats.nTimeOffset)); - obj.push_back(Pair("pingtime", stats.dPingTime)); - obj.push_back(Pair("minping", stats.dPingMin)); + if (stats.dPingTime > 0.0) + obj.push_back(Pair("pingtime", stats.dPingTime)); + if (stats.dPingMin < std::numeric_limits::max()/1e6) + obj.push_back(Pair("minping", stats.dPingMin)); if (stats.dPingWait > 0.0) obj.push_back(Pair("pingwait", stats.dPingWait)); obj.push_back(Pair("version", stats.nVersion)); From fe53a2af6f8dccd53116ae35f28ec3860cc72f19 Mon Sep 17 00:00:00 2001 From: mruddy Date: Fri, 8 Apr 2016 20:15:41 -0400 Subject: [PATCH 0122/1802] doc: add arch linux setup and build example [skip ci] --- doc/build-unix.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/doc/build-unix.md b/doc/build-unix.md index c1e92d8d15f65..dc754fc7339c9 100644 --- a/doc/build-unix.md +++ b/doc/build-unix.md @@ -250,6 +250,24 @@ A list of additional configure flags can be displayed with: ./configure --help +Setup and Build Example: Arch Linux +----------------------------------- +This example lists the steps necessary to setup and build a command line only, non-wallet distribution of the latest changes on Arch Linux: + + pacman -S git base-devel boost libevent python + git clone https://github.com/bitcoin/bitcoin.git + cd bitcoin/ + ./autogen.sh + ./configure --disable-wallet --without-gui --without-miniupnpc + make check + +Note: +Enabling wallet support requires either compiling against a Berkeley DB newer than 4.8 (package `db`) using `--with-incompatible-bdb`, +or building and depending on a local version of Berkeley DB 4.8. The readily available Arch Linux packages are currently built using +`--with-incompatible-bdb` according to the [PKGBUILD](https://projects.archlinux.org/svntogit/community.git/tree/bitcoin/trunk/PKGBUILD). +As mentioned above, when maintaining portability of the wallet between the standard Bitcoin Core distributions and independently built +node software is desired, Berkeley DB 4.8 must be used. + ARM Cross-compilation ------------------- @@ -270,4 +288,4 @@ To build executables for ARM: make -For further documentation on the depends system see [README.md](../depends/README.md) in the depends directory. \ No newline at end of file +For further documentation on the depends system see [README.md](../depends/README.md) in the depends directory. From facf5a494708df755a15d63d339412201512e13f Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sat, 9 Apr 2016 15:28:17 +0200 Subject: [PATCH 0123/1802] [amount] tests: Fix off-by-one mistake --- src/test/amount_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/amount_tests.cpp b/src/test/amount_tests.cpp index c65646474d514..fd6f88b36627d 100644 --- a/src/test/amount_tests.cpp +++ b/src/test/amount_tests.cpp @@ -65,7 +65,7 @@ BOOST_AUTO_TEST_CASE(GetFeeTest) BOOST_CHECK(CFeeRate(CAmount(26), 789) == CFeeRate(32)); BOOST_CHECK(CFeeRate(CAmount(27), 789) == CFeeRate(34)); // Maximum size in bytes, should not crash - CFeeRate(MAX_MONEY, (std::numeric_limits::max() >> 1) - 1).GetFeePerK(); + CFeeRate(MAX_MONEY, std::numeric_limits::max() >> 1).GetFeePerK(); } BOOST_AUTO_TEST_SUITE_END() From fa05e22e919b7e2e816606f0c0d3dea1bd325bfd Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sat, 9 Apr 2016 21:14:18 +0200 Subject: [PATCH 0124/1802] [qa] pull-tester: Don't mute zmq ImportError --- qa/pull-tester/rpc-tests.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index 6d3bda10ee6d8..17c0b3adf2e7f 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -45,10 +45,10 @@ if ENABLE_ZMQ: try: import zmq - except ImportError: - print("WARNING: \"import zmq\" failed. Setting ENABLE_ZMQ=0. " \ - "To run zmq tests, see dependency info in /qa/README.md.") - ENABLE_ZMQ=0 + except ImportError as e: + print("WARNING: \"import zmq\" failed. Set ENABLE_ZMQ=0 or " \ + "to run zmq tests, see dependency info in /qa/README.md.") + raise e ENABLE_COVERAGE=0 From faa4f22342b682a5ead1bbb8587facd761b4ac2d Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sat, 9 Apr 2016 22:17:52 +0200 Subject: [PATCH 0125/1802] [qa] pull-tester: Exit early when no tests are run --- qa/pull-tester/rpc-tests.py | 124 ++++++++++++++++++------------------ 1 file changed, 61 insertions(+), 63 deletions(-) diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index 17c0b3adf2e7f..e159082a009e5 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -40,15 +40,6 @@ ENABLE_UTILS=0 if 'ENABLE_ZMQ' not in vars(): ENABLE_ZMQ=0 - -# python-zmq may not be installed. Handle this gracefully and with some helpful info -if ENABLE_ZMQ: - try: - import zmq - except ImportError as e: - print("WARNING: \"import zmq\" failed. Set ENABLE_ZMQ=0 or " \ - "to run zmq tests, see dependency info in /qa/README.md.") - raise e ENABLE_COVERAGE=0 @@ -76,11 +67,24 @@ if "BITCOINCLI" not in os.environ: os.environ["BITCOINCLI"] = buildDir + '/src/bitcoin-cli' + EXEEXT -#Disable Windows tests by default if EXEEXT == ".exe" and "-win" not in opts: - print "Win tests currently disabled. Use -win option to enable" + # https://github.com/bitcoin/bitcoin/commit/d52802551752140cf41f0d9a225a43e84404d3e9 + print "Win tests currently disabled by default. Use -win option to enable" + sys.exit(0) + +if not (ENABLE_WALLET == 1 and ENABLE_UTILS == 1 and ENABLE_BITCOIND == 1): + print "No rpc tests to run. Wallet, utils, and bitcoind must all be enabled" sys.exit(0) +# python-zmq may not be installed. Handle this gracefully and with some helpful info +if ENABLE_ZMQ: + try: + import zmq + except ImportError as e: + print("WARNING: \"import zmq\" failed. Set ENABLE_ZMQ=0 or " \ + "to run zmq tests, see dependency info in /qa/README.md.") + raise e + #Tests testScripts = [ 'bip68-112-113-p2p.py', @@ -119,6 +123,9 @@ 'p2p-versionbits-warning.py', 'importprunedfunds.py', ] +if ENABLE_ZMQ: + testScripts.append('zmq_test.py') + testScriptsExt = [ 'bip9-softforks.py', 'bip65-cltv.py', @@ -143,11 +150,6 @@ 'pruning.py', # leave pruning last as it takes a REALLY long time ] -#Enable ZMQ tests -if ENABLE_ZMQ == 1: - testScripts.append('zmq_test.py') - - def runtests(): coverage = None @@ -155,53 +157,49 @@ def runtests(): coverage = RPCCoverage() print("Initializing coverage directory at %s\n" % coverage.dir) - if(ENABLE_WALLET == 1 and ENABLE_UTILS == 1 and ENABLE_BITCOIND == 1): - rpcTestDir = buildDir + '/qa/rpc-tests/' - run_extended = '-extended' in opts - cov_flag = coverage.flag if coverage else '' - flags = " --srcdir %s/src %s %s" % (buildDir, cov_flag, passOn) - - #Run Tests - for i in range(len(testScripts)): - if (len(opts) == 0 - or (len(opts) == 1 and "-win" in opts ) - or run_extended - or testScripts[i] in opts - or re.sub(".py$", "", testScripts[i]) in opts ): - - print("Running testscript %s%s%s ..." % (bold[1], testScripts[i], bold[0])) - time0 = time.time() - subprocess.check_call( - rpcTestDir + testScripts[i] + flags, shell=True) - print("Duration: %s s\n" % (int(time.time() - time0))) - - # exit if help is called so we print just one set of - # instructions - p = re.compile(" -h| --help") - if p.match(passOn): - sys.exit(0) - - # Run Extended Tests - for i in range(len(testScriptsExt)): - if (run_extended or testScriptsExt[i] in opts - or re.sub(".py$", "", testScriptsExt[i]) in opts): - - print( - "Running 2nd level testscript " - + "%s%s%s ..." % (bold[1], testScriptsExt[i], bold[0])) - time0 = time.time() - subprocess.check_call( - rpcTestDir + testScriptsExt[i] + flags, shell=True) - print("Duration: %s s\n" % (int(time.time() - time0))) - - if coverage: - coverage.report_rpc_coverage() - - print("Cleaning up coverage data") - coverage.cleanup() - - else: - print "No rpc tests to run. Wallet, utils, and bitcoind must all be enabled" + rpcTestDir = buildDir + '/qa/rpc-tests/' + run_extended = '-extended' in opts + cov_flag = coverage.flag if coverage else '' + flags = " --srcdir %s/src %s %s" % (buildDir, cov_flag, passOn) + + #Run Tests + for i in range(len(testScripts)): + if (len(opts) == 0 + or (len(opts) == 1 and "-win" in opts ) + or run_extended + or testScripts[i] in opts + or re.sub(".py$", "", testScripts[i]) in opts ): + + print("Running testscript %s%s%s ..." % (bold[1], testScripts[i], bold[0])) + time0 = time.time() + subprocess.check_call( + rpcTestDir + testScripts[i] + flags, shell=True) + print("Duration: %s s\n" % (int(time.time() - time0))) + + # exit if help is called so we print just one set of + # instructions + p = re.compile(" -h| --help") + if p.match(passOn): + sys.exit(0) + + # Run Extended Tests + for i in range(len(testScriptsExt)): + if (run_extended or testScriptsExt[i] in opts + or re.sub(".py$", "", testScriptsExt[i]) in opts): + + print( + "Running 2nd level testscript " + + "%s%s%s ..." % (bold[1], testScriptsExt[i], bold[0])) + time0 = time.time() + subprocess.check_call( + rpcTestDir + testScriptsExt[i] + flags, shell=True) + print("Duration: %s s\n" % (int(time.time() - time0))) + + if coverage: + coverage.report_rpc_coverage() + + print("Cleaning up coverage data") + coverage.cleanup() class RPCCoverage(object): From 5eeb913d6cff9cfe9a6769d7efe4a7b9f23de0f4 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 8 Apr 2016 22:14:19 +0200 Subject: [PATCH 0126/1802] Clean up lockorder data of destroyed mutexes The lockorder potential deadlock detection works by remembering for each lock A that is acquired while holding another B the pair (A,B), and triggering a warning when (B,A) already exists in the table. A and B in the above text are represented by pointers to the CCriticalSection object that is acquired. This does mean however that we need to clean up the table entries that refer to any critical section which is destroyed, as it memory address can potentially be used for another unrelated lock in the future. Implement this clean up by remembering not only the pairs in forward direction, but also backward direction. This allows for fast iteration over all pairs that use a deleted CCriticalSection in either the first or the second position. --- src/sync.cpp | 55 +++++++++++++++++++++++++++++++++++++++++----------- src/sync.h | 33 +++++++++++++++++++------------ 2 files changed, 65 insertions(+), 23 deletions(-) diff --git a/src/sync.cpp b/src/sync.cpp index 8df8ae43f4357..641ed2c8ca036 100644 --- a/src/sync.cpp +++ b/src/sync.cpp @@ -56,11 +56,24 @@ struct CLockLocation { }; typedef std::vector > LockStack; +typedef std::map, LockStack> LockOrders; +typedef std::set > InvLockOrders; -static boost::mutex dd_mutex; -static std::map, LockStack> lockorders; -static boost::thread_specific_ptr lockstack; +struct LockData { + // Very ugly hack: as the global constructs and destructors run single + // threaded, we use this boolean to know whether LockData still exists, + // as DeleteLock can get called by global CCriticalSection destructors + // after LockData disappears. + bool available; + LockData() : available(true) {} + ~LockData() { available = false; } + LockOrders lockorders; + InvLockOrders invlockorders; + boost::mutex dd_mutex; +} static lockdata; + +boost::thread_specific_ptr lockstack; static void potential_deadlock_detected(const std::pair& mismatch, const LockStack& s1, const LockStack& s2) { @@ -117,7 +130,7 @@ static void push_lock(void* c, const CLockLocation& locklocation, bool fTry) if (lockstack.get() == NULL) lockstack.reset(new LockStack); - dd_mutex.lock(); + boost::unique_lock lock(lockdata.dd_mutex); (*lockstack).push_back(std::make_pair(c, locklocation)); @@ -127,23 +140,21 @@ static void push_lock(void* c, const CLockLocation& locklocation, bool fTry) break; std::pair p1 = std::make_pair(i.first, c); - if (lockorders.count(p1)) + if (lockdata.lockorders.count(p1)) continue; - lockorders[p1] = (*lockstack); + lockdata.lockorders[p1] = (*lockstack); std::pair p2 = std::make_pair(c, i.first); - if (lockorders.count(p2)) - potential_deadlock_detected(p1, lockorders[p2], lockorders[p1]); + lockdata.invlockorders.insert(p2); + if (lockdata.lockorders.count(p2)) + potential_deadlock_detected(p1, lockdata.lockorders[p2], lockdata.lockorders[p1]); } } - dd_mutex.unlock(); } static void pop_lock() { - dd_mutex.lock(); (*lockstack).pop_back(); - dd_mutex.unlock(); } void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry) @@ -173,4 +184,26 @@ void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, abort(); } +void DeleteLock(void* cs) +{ + if (!lockdata.available) { + // We're already shutting down. + return; + } + boost::unique_lock lock(lockdata.dd_mutex); + std::pair item = std::make_pair(cs, (void*)0); + LockOrders::iterator it = lockdata.lockorders.lower_bound(item); + while (it != lockdata.lockorders.end() && it->first.first == cs) { + std::pair invitem = std::make_pair(it->first.second, it->first.first); + lockdata.invlockorders.erase(invitem); + lockdata.lockorders.erase(it++); + } + InvLockOrders::iterator invit = lockdata.invlockorders.lower_bound(item); + while (invit != lockdata.invlockorders.end() && invit->first == cs) { + std::pair invinvitem = std::make_pair(invit->second, invit->first); + lockdata.lockorders.erase(invinvitem); + lockdata.invlockorders.erase(invit++); + } +} + #endif /* DEBUG_LOCKORDER */ diff --git a/src/sync.h b/src/sync.h index 34dd8c228eb76..0c58fb6b4e94c 100644 --- a/src/sync.h +++ b/src/sync.h @@ -71,30 +71,39 @@ class LOCKABLE AnnotatedMixin : public PARENT } }; -/** - * Wrapped boost mutex: supports recursive locking, but no waiting - * TODO: We should move away from using the recursive lock by default. - */ -typedef AnnotatedMixin CCriticalSection; - -/** Wrapped boost mutex: supports waiting but not recursive locking */ -typedef AnnotatedMixin CWaitableCriticalSection; - -/** Just a typedef for boost::condition_variable, can be wrapped later if desired */ -typedef boost::condition_variable CConditionVariable; - #ifdef DEBUG_LOCKORDER void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false); void LeaveCritical(); std::string LocksHeld(); void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs); +void DeleteLock(void* cs); #else void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {} void static inline LeaveCritical() {} void static inline AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs) {} +void static inline DeleteLock(void* cs) {} #endif #define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs) +/** + * Wrapped boost mutex: supports recursive locking, but no waiting + * TODO: We should move away from using the recursive lock by default. + */ +class CCriticalSection : public AnnotatedMixin +{ +public: + ~CCriticalSection() { + DeleteLock((void*)this); + } +}; + +typedef CCriticalSection CDynamicCriticalSection; +/** Wrapped boost mutex: supports waiting but not recursive locking */ +typedef AnnotatedMixin CWaitableCriticalSection; + +/** Just a typedef for boost::condition_variable, can be wrapped later if desired */ +typedef boost::condition_variable CConditionVariable; + #ifdef DEBUG_LOCKCONTENTION void PrintLockContention(const char* pszName, const char* pszFile, int nLine); #endif From faa41ee204124da19dcf1e5b8a3aef1e216bf5e6 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 10 Apr 2016 16:54:28 +0200 Subject: [PATCH 0127/1802] [qa] py2: Unfiddle strings into bytes explicitly --- qa/rpc-tests/bip65-cltv-p2p.py | 3 +- qa/rpc-tests/bip68-112-113-p2p.py | 5 +- qa/rpc-tests/bip9-softforks.py | 9 +- qa/rpc-tests/bipdersig-p2p.py | 5 +- qa/rpc-tests/decodescript.py | 22 ++- qa/rpc-tests/fundrawtransaction.py | 3 - qa/rpc-tests/getblocktemplate_proposals.py | 2 +- qa/rpc-tests/httpbasics.py | 11 +- qa/rpc-tests/invalidblockrequest.py | 10 +- qa/rpc-tests/invalidtxrequest.py | 6 +- qa/rpc-tests/listtransactions.py | 7 +- qa/rpc-tests/multi_rpc.py | 13 +- qa/rpc-tests/p2p-feefilter.py | 2 +- qa/rpc-tests/p2p-fullblocktest.py | 32 ++-- qa/rpc-tests/proxy_test.py | 8 +- qa/rpc-tests/pruning.py | 2 +- qa/rpc-tests/rawtransactions.py | 2 - qa/rpc-tests/replace-by-fee.py | 10 +- qa/rpc-tests/rest.py | 15 +- qa/rpc-tests/test_framework/blocktools.py | 2 +- qa/rpc-tests/test_framework/comptool.py | 6 +- qa/rpc-tests/test_framework/mininode.py | 186 ++++++++++----------- qa/rpc-tests/test_framework/netutil.py | 11 +- qa/rpc-tests/test_framework/script.py | 4 +- qa/rpc-tests/test_framework/socks5.py | 2 +- qa/rpc-tests/test_framework/util.py | 15 +- qa/rpc-tests/zmq_test.py | 22 +-- src/test/bctest.py | 3 +- 28 files changed, 205 insertions(+), 213 deletions(-) diff --git a/qa/rpc-tests/bip65-cltv-p2p.py b/qa/rpc-tests/bip65-cltv-p2p.py index 54559c3541f2e..99d74344aef95 100755 --- a/qa/rpc-tests/bip65-cltv-p2p.py +++ b/qa/rpc-tests/bip65-cltv-p2p.py @@ -10,7 +10,6 @@ from test_framework.blocktools import create_coinbase, create_block from test_framework.comptool import TestInstance, TestManager from test_framework.script import CScript, OP_1NEGATE, OP_CHECKLOCKTIMEVERIFY, OP_DROP -from binascii import unhexlify from io import BytesIO import time @@ -60,7 +59,7 @@ def create_transaction(self, node, coinbase, to_address, amount): rawtx = node.createrawtransaction(inputs, outputs) signresult = node.signrawtransaction(rawtx) tx = CTransaction() - f = BytesIO(unhexlify(signresult['hex'])) + f = BytesIO(hex_str_to_bytes(signresult['hex'])) tx.deserialize(f) return tx diff --git a/qa/rpc-tests/bip68-112-113-p2p.py b/qa/rpc-tests/bip68-112-113-p2p.py index 35c831cb8b71d..3bcfdabe269a1 100755 --- a/qa/rpc-tests/bip68-112-113-p2p.py +++ b/qa/rpc-tests/bip68-112-113-p2p.py @@ -10,7 +10,6 @@ from test_framework.blocktools import create_coinbase, create_block from test_framework.comptool import TestInstance, TestManager from test_framework.script import * -from binascii import unhexlify from io import BytesIO import time @@ -119,7 +118,7 @@ def create_transaction(self, node, txid, to_address, amount): outputs = { to_address : amount } rawtx = node.createrawtransaction(inputs, outputs) tx = CTransaction() - f = BytesIO(unhexlify(rawtx)) + f = BytesIO(hex_str_to_bytes(rawtx)) tx.deserialize(f) return tx @@ -127,7 +126,7 @@ def sign_transaction(self, node, unsignedtx): rawtx = ToHex(unsignedtx) signresult = node.signrawtransaction(rawtx) tx = CTransaction() - f = BytesIO(unhexlify(signresult['hex'])) + f = BytesIO(hex_str_to_bytes(signresult['hex'])) tx.deserialize(f) return tx diff --git a/qa/rpc-tests/bip9-softforks.py b/qa/rpc-tests/bip9-softforks.py index 98975e719335c..d131eed92dc14 100755 --- a/qa/rpc-tests/bip9-softforks.py +++ b/qa/rpc-tests/bip9-softforks.py @@ -10,7 +10,6 @@ from test_framework.blocktools import create_coinbase, create_block from test_framework.comptool import TestInstance, TestManager from test_framework.script import CScript, OP_1NEGATE, OP_NOP3, OP_DROP -from binascii import hexlify, unhexlify from io import BytesIO import time import itertools @@ -30,7 +29,6 @@ ''' - class BIP9SoftForksTest(ComparisonTestFramework): def __init__(self): @@ -53,15 +51,15 @@ def create_transaction(self, node, coinbase, to_address, amount): outputs = { to_address : amount } rawtx = node.createrawtransaction(inputs, outputs) tx = CTransaction() - f = BytesIO(unhexlify(rawtx)) + f = BytesIO(hex_str_to_bytes(rawtx)) tx.deserialize(f) tx.nVersion = 2 return tx def sign_transaction(self, node, tx): - signresult = node.signrawtransaction(hexlify(tx.serialize())) + signresult = node.signrawtransaction(bytes_to_hex_str(tx.serialize())) tx = CTransaction() - f = BytesIO(unhexlify(signresult['hex'])) + f = BytesIO(hex_str_to_bytes(signresult['hex'])) tx.deserialize(f) return tx @@ -184,7 +182,6 @@ def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignatu NetworkThread().start() # Start up network handling in another thread - def get_tests(self): for test in itertools.chain( self.test_BIP('csv', 536870913, self.sequence_lock_invalidate, self.donothing), diff --git a/qa/rpc-tests/bipdersig-p2p.py b/qa/rpc-tests/bipdersig-p2p.py index 95be385d93fb0..bba86a50c4c56 100755 --- a/qa/rpc-tests/bipdersig-p2p.py +++ b/qa/rpc-tests/bipdersig-p2p.py @@ -10,7 +10,6 @@ from test_framework.blocktools import create_coinbase, create_block from test_framework.comptool import TestInstance, TestManager from test_framework.script import CScript -from binascii import unhexlify from io import BytesIO import time @@ -25,7 +24,7 @@ def unDERify(tx): newscript = [] for i in scriptSig: if (len(newscript) == 0): - newscript.append(i[0:-1] + '\0' + i[-1]) + newscript.append(i[0:-1] + b'\0' + i[-1:]) else: newscript.append(i) tx.vin[0].scriptSig = CScript(newscript) @@ -68,7 +67,7 @@ def create_transaction(self, node, coinbase, to_address, amount): rawtx = node.createrawtransaction(inputs, outputs) signresult = node.signrawtransaction(rawtx) tx = CTransaction() - f = BytesIO(unhexlify(signresult['hex'])) + f = BytesIO(hex_str_to_bytes(signresult['hex'])) tx.deserialize(f) return tx diff --git a/qa/rpc-tests/decodescript.py b/qa/rpc-tests/decodescript.py index 2dfafac2fc180..578844f2c5bb0 100755 --- a/qa/rpc-tests/decodescript.py +++ b/qa/rpc-tests/decodescript.py @@ -6,7 +6,6 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * from test_framework.mininode import * -from binascii import hexlify, unhexlify from io import BytesIO class DecodeScriptTest(BitcoinTestFramework): @@ -131,7 +130,7 @@ def decoderawtransaction_asm_sighashtype(self): assert_equal('OP_DUP OP_HASH160 dc863734a218bfe83ef770ee9d41a27f824a6e56 OP_EQUALVERIFY OP_CHECKSIG', rpc_result['vout'][0]['scriptPubKey']['asm']) assert_equal('OP_HASH160 2a5edea39971049a540474c6a99edf0aa4074c58 OP_EQUAL', rpc_result['vout'][1]['scriptPubKey']['asm']) txSave = CTransaction() - txSave.deserialize(BytesIO(unhexlify(tx))) + txSave.deserialize(BytesIO(hex_str_to_bytes(tx))) # make sure that a specifically crafted op_return value will not pass all the IsDERSignature checks and then get decoded as a sighash type tx = '01000000015ded05872fdbda629c7d3d02b194763ce3b9b1535ea884e3c8e765d42e316724020000006b48304502204c10d4064885c42638cbff3585915b322de33762598321145ba033fc796971e2022100bb153ad3baa8b757e30a2175bd32852d2e1cb9080f84d7e32fcdfd667934ef1b012103163c0ff73511ea1743fb5b98384a2ff09dd06949488028fd819f4d83f56264efffffffff0200000000000000000b6a0930060201000201000180380100000000001976a9141cabd296e753837c086da7a45a6c2fe0d49d7b7b88ac00000000' @@ -147,7 +146,7 @@ def decoderawtransaction_asm_sighashtype(self): # some more full transaction tests of varying specific scriptSigs. used instead of # tests in decodescript_script_sig because the decodescript RPC is specifically # for working on scriptPubKeys (argh!). - push_signature = hexlify(txSave.vin[0].scriptSig)[2:(0x48*2+4)] + push_signature = bytes_to_hex_str(txSave.vin[0].scriptSig)[2:(0x48*2+4)] signature = push_signature[2:] der_signature = signature[:-2] signature_sighash_decoded = der_signature + '[ALL]' @@ -156,25 +155,24 @@ def decoderawtransaction_asm_sighashtype(self): signature_2_sighash_decoded = der_signature + '[NONE|ANYONECANPAY]' # 1) P2PK scriptSig - txSave.vin[0].scriptSig = unhexlify(push_signature) - rpc_result = self.nodes[0].decoderawtransaction(hexlify(txSave.serialize())) + txSave.vin[0].scriptSig = hex_str_to_bytes(push_signature) + rpc_result = self.nodes[0].decoderawtransaction(bytes_to_hex_str(txSave.serialize())) assert_equal(signature_sighash_decoded, rpc_result['vin'][0]['scriptSig']['asm']) # make sure that the sighash decodes come out correctly for a more complex / lesser used case. - txSave.vin[0].scriptSig = unhexlify(push_signature_2) - rpc_result = self.nodes[0].decoderawtransaction(hexlify(txSave.serialize())) + txSave.vin[0].scriptSig = hex_str_to_bytes(push_signature_2) + rpc_result = self.nodes[0].decoderawtransaction(bytes_to_hex_str(txSave.serialize())) assert_equal(signature_2_sighash_decoded, rpc_result['vin'][0]['scriptSig']['asm']) # 2) multisig scriptSig - txSave.vin[0].scriptSig = unhexlify('00' + push_signature + push_signature_2) - rpc_result = self.nodes[0].decoderawtransaction(hexlify(txSave.serialize())) + txSave.vin[0].scriptSig = hex_str_to_bytes('00' + push_signature + push_signature_2) + rpc_result = self.nodes[0].decoderawtransaction(bytes_to_hex_str(txSave.serialize())) assert_equal('0 ' + signature_sighash_decoded + ' ' + signature_2_sighash_decoded, rpc_result['vin'][0]['scriptSig']['asm']) # 3) test a scriptSig that contains more than push operations. # in fact, it contains an OP_RETURN with data specially crafted to cause improper decode if the code does not catch it. - txSave.vin[0].scriptSig = unhexlify('6a143011020701010101010101020601010101010101') - rpc_result = self.nodes[0].decoderawtransaction(hexlify(txSave.serialize())) - print(hexlify('636174')) + txSave.vin[0].scriptSig = hex_str_to_bytes('6a143011020701010101010101020601010101010101') + rpc_result = self.nodes[0].decoderawtransaction(bytes_to_hex_str(txSave.serialize())) assert_equal('OP_RETURN 3011020701010101010101020601010101010101', rpc_result['vin'][0]['scriptSig']['asm']) def run_test(self): diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py index 82c9e48a49735..4492ea398f4ba 100755 --- a/qa/rpc-tests/fundrawtransaction.py +++ b/qa/rpc-tests/fundrawtransaction.py @@ -148,7 +148,6 @@ def run_test(self): assert_equal(fee + totalOut, utx['amount']) #compare vin total and totalout+fee - ##################################################################### # test a fundrawtransaction with which will not get a change output # ##################################################################### @@ -178,7 +177,6 @@ def run_test(self): assert_equal(fee + totalOut, utx['amount']) #compare vin total and totalout+fee - ######################################################################### # test a fundrawtransaction with a VIN smaller than the required amount # ######################################################################### @@ -484,7 +482,6 @@ def run_test(self): assert_equal(oldBalance+Decimal('51.10000000'), self.nodes[0].getbalance()) - ############################################### # multiple (~19) inputs tx test | Compare fee # ############################################### diff --git a/qa/rpc-tests/getblocktemplate_proposals.py b/qa/rpc-tests/getblocktemplate_proposals.py index d2cb4ab8d69b9..07bfe69c6d869 100755 --- a/qa/rpc-tests/getblocktemplate_proposals.py +++ b/qa/rpc-tests/getblocktemplate_proposals.py @@ -130,7 +130,7 @@ def run_test(self): # Test 5: Add an invalid tx to the end (non-duplicate) txlist.append(bytearray(txlist[0])) - txlist[-1][4+1] = b'\xff' + txlist[-1][4+1] = 0xff assert_template(node, tmpl, txlist, 'bad-txns-inputs-missingorspent') txlist.pop() diff --git a/qa/rpc-tests/httpbasics.py b/qa/rpc-tests/httpbasics.py index eff4c6e808bbd..cf37976a4ed85 100755 --- a/qa/rpc-tests/httpbasics.py +++ b/qa/rpc-tests/httpbasics.py @@ -9,7 +9,6 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * -import base64 try: import http.client as httplib @@ -31,7 +30,7 @@ def run_test(self): ################################################# url = urlparse.urlparse(self.nodes[0].url) authpair = url.username + ':' + url.password - headers = {"Authorization": "Basic " + base64.b64encode(authpair)} + headers = {"Authorization": "Basic " + str_to_b64str(authpair)} conn = httplib.HTTPConnection(url.hostname, url.port) conn.connect() @@ -48,7 +47,7 @@ def run_test(self): conn.close() #same should be if we add keep-alive because this should be the std. behaviour - headers = {"Authorization": "Basic " + base64.b64encode(authpair), "Connection": "keep-alive"} + headers = {"Authorization": "Basic " + str_to_b64str(authpair), "Connection": "keep-alive"} conn = httplib.HTTPConnection(url.hostname, url.port) conn.connect() @@ -65,7 +64,7 @@ def run_test(self): conn.close() #now do the same with "Connection: close" - headers = {"Authorization": "Basic " + base64.b64encode(authpair), "Connection":"close"} + headers = {"Authorization": "Basic " + str_to_b64str(authpair), "Connection":"close"} conn = httplib.HTTPConnection(url.hostname, url.port) conn.connect() @@ -77,7 +76,7 @@ def run_test(self): #node1 (2nd node) is running with disabled keep-alive option urlNode1 = urlparse.urlparse(self.nodes[1].url) authpair = urlNode1.username + ':' + urlNode1.password - headers = {"Authorization": "Basic " + base64.b64encode(authpair)} + headers = {"Authorization": "Basic " + str_to_b64str(authpair)} conn = httplib.HTTPConnection(urlNode1.hostname, urlNode1.port) conn.connect() @@ -88,7 +87,7 @@ def run_test(self): #node2 (third node) is running with standard keep-alive parameters which means keep-alive is on urlNode2 = urlparse.urlparse(self.nodes[2].url) authpair = urlNode2.username + ':' + urlNode2.password - headers = {"Authorization": "Basic " + base64.b64encode(authpair)} + headers = {"Authorization": "Basic " + str_to_b64str(authpair)} conn = httplib.HTTPConnection(urlNode2.hostname, urlNode2.port) conn.connect() diff --git a/qa/rpc-tests/invalidblockrequest.py b/qa/rpc-tests/invalidblockrequest.py index daad312d36390..de6be8d5b5b5d 100755 --- a/qa/rpc-tests/invalidblockrequest.py +++ b/qa/rpc-tests/invalidblockrequest.py @@ -77,9 +77,9 @@ def get_tests(self): block2 = create_block(self.tip, create_coinbase(height), self.block_time) self.block_time += 1 - # chr(81) is OP_TRUE - tx1 = create_transaction(self.block1.vtx[0], 0, chr(81), 50 * COIN) - tx2 = create_transaction(tx1, 0, chr(81), 50 * COIN) + # b'0x51' is OP_TRUE + tx1 = create_transaction(self.block1.vtx[0], 0, b'\x51', 50 * COIN) + tx2 = create_transaction(tx1, 0, b'\x51', 50 * COIN) block2.vtx.extend([tx1, tx2]) block2.hashMerkleRoot = block2.calc_merkle_root() @@ -95,7 +95,7 @@ def get_tests(self): assert(block2_orig.vtx != block2.vtx) self.tip = block2.sha256 - yield TestInstance([[block2, RejectResult(16,'bad-txns-duplicate')], [block2_orig, True]]) + yield TestInstance([[block2, RejectResult(16, b'bad-txns-duplicate')], [block2_orig, True]]) height += 1 ''' @@ -110,7 +110,7 @@ def get_tests(self): block3.rehash() block3.solve() - yield TestInstance([[block3, RejectResult(16,'bad-cb-amount')]]) + yield TestInstance([[block3, RejectResult(16, b'bad-cb-amount')]]) if __name__ == '__main__': diff --git a/qa/rpc-tests/invalidtxrequest.py b/qa/rpc-tests/invalidtxrequest.py index 8fe471ccd318b..7b8199bab0cc4 100755 --- a/qa/rpc-tests/invalidtxrequest.py +++ b/qa/rpc-tests/invalidtxrequest.py @@ -61,10 +61,10 @@ def get_tests(self): height += 1 yield test - # chr(100) is OP_NOTIF + # b'\x64' is OP_NOTIF # Transaction will be rejected with code 16 (REJECT_INVALID) - tx1 = create_transaction(self.block1.vtx[0], 0, chr(100), 50 * COIN - 12000) - yield TestInstance([[tx1, RejectResult(16, 'mandatory-script-verify-flag-failed')]]) + tx1 = create_transaction(self.block1.vtx[0], 0, b'\x64', 50 * COIN - 12000) + yield TestInstance([[tx1, RejectResult(16, b'mandatory-script-verify-flag-failed')]]) # TODO: test further transactions... diff --git a/qa/rpc-tests/listtransactions.py b/qa/rpc-tests/listtransactions.py index 8fe72d95d1d0d..0783a1f3d3717 100755 --- a/qa/rpc-tests/listtransactions.py +++ b/qa/rpc-tests/listtransactions.py @@ -9,11 +9,10 @@ from test_framework.util import * from test_framework.mininode import CTransaction, COIN from io import BytesIO -import binascii def txFromHex(hexstring): tx = CTransaction() - f = BytesIO(binascii.unhexlify(hexstring)) + f = BytesIO(hex_str_to_bytes(hexstring)) tx.deserialize(f) return tx @@ -167,7 +166,7 @@ def get_unconfirmed_utxo_entry(node, txid_to_match): tx3 = self.nodes[0].createrawtransaction(inputs, outputs) tx3_modified = txFromHex(tx3) tx3_modified.vin[0].nSequence = 0 - tx3 = binascii.hexlify(tx3_modified.serialize()).decode('utf-8') + tx3 = bytes_to_hex_str(tx3_modified.serialize()) tx3_signed = self.nodes[0].signrawtransaction(tx3)['hex'] txid_3 = self.nodes[0].sendrawtransaction(tx3_signed) @@ -193,7 +192,7 @@ def get_unconfirmed_utxo_entry(node, txid_to_match): # Replace tx3, and check that tx4 becomes unknown tx3_b = tx3_modified tx3_b.vout[0].nValue -= int(Decimal("0.004") * COIN) # bump the fee - tx3_b = binascii.hexlify(tx3_b.serialize()).decode('utf-8') + tx3_b = bytes_to_hex_str(tx3_b.serialize()) tx3_b_signed = self.nodes[0].signrawtransaction(tx3_b)['hex'] txid_3b = self.nodes[0].sendrawtransaction(tx3_b_signed, True) assert(is_opt_in(self.nodes[0], txid_3b)) diff --git a/qa/rpc-tests/multi_rpc.py b/qa/rpc-tests/multi_rpc.py index 2452b77319805..afb18cf3da20d 100755 --- a/qa/rpc-tests/multi_rpc.py +++ b/qa/rpc-tests/multi_rpc.py @@ -53,7 +53,7 @@ def run_test(self): password2 = "8/F3uMDw4KSEbw96U3CA1C4X05dkHDN2BPFjTgZW4KI=" authpairnew = "rt:"+password - headers = {"Authorization": "Basic " + base64.b64encode(authpair)} + headers = {"Authorization": "Basic " + str_to_b64str(authpair)} conn = httplib.HTTPConnection(url.hostname, url.port) conn.connect() @@ -63,7 +63,7 @@ def run_test(self): conn.close() #Use new authpair to confirm both work - headers = {"Authorization": "Basic " + base64.b64encode(authpairnew)} + headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)} conn = httplib.HTTPConnection(url.hostname, url.port) conn.connect() @@ -74,7 +74,7 @@ def run_test(self): #Wrong login name with rt's password authpairnew = "rtwrong:"+password - headers = {"Authorization": "Basic " + base64.b64encode(authpairnew)} + headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)} conn = httplib.HTTPConnection(url.hostname, url.port) conn.connect() @@ -85,7 +85,7 @@ def run_test(self): #Wrong password for rt authpairnew = "rt:"+password+"wrong" - headers = {"Authorization": "Basic " + base64.b64encode(authpairnew)} + headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)} conn = httplib.HTTPConnection(url.hostname, url.port) conn.connect() @@ -96,7 +96,7 @@ def run_test(self): #Correct for rt2 authpairnew = "rt2:"+password2 - headers = {"Authorization": "Basic " + base64.b64encode(authpairnew)} + headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)} conn = httplib.HTTPConnection(url.hostname, url.port) conn.connect() @@ -107,7 +107,7 @@ def run_test(self): #Wrong password for rt2 authpairnew = "rt2:"+password2+"wrong" - headers = {"Authorization": "Basic " + base64.b64encode(authpairnew)} + headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)} conn = httplib.HTTPConnection(url.hostname, url.port) conn.connect() @@ -117,6 +117,5 @@ def run_test(self): conn.close() - if __name__ == '__main__': HTTPBasicsTest ().main () diff --git a/qa/rpc-tests/p2p-feefilter.py b/qa/rpc-tests/p2p-feefilter.py index f85c18dcd5140..281b6ca37a0ce 100755 --- a/qa/rpc-tests/p2p-feefilter.py +++ b/qa/rpc-tests/p2p-feefilter.py @@ -14,7 +14,7 @@ ''' def hashToHex(hash): - return format(hash, '064x').decode('utf-8') + return format(hash, '064x') # Wait up to 60 secs to see if the testnode has received all the expected invs def allInvsMatch(invsExpected, testnode): diff --git a/qa/rpc-tests/p2p-fullblocktest.py b/qa/rpc-tests/p2p-fullblocktest.py index 131350c98ddf0..ae82d9dca9266 100755 --- a/qa/rpc-tests/p2p-fullblocktest.py +++ b/qa/rpc-tests/p2p-fullblocktest.py @@ -33,7 +33,7 @@ def __init__(self): self.num_nodes = 1 self.block_heights = {} self.coinbase_key = CECKey() - self.coinbase_key.set_secretbytes(bytes("horsebattery")) + self.coinbase_key.set_secretbytes(b"horsebattery") self.coinbase_pubkey = self.coinbase_key.get_pubkey() self.block_time = int(time.time())+1 self.tip = None @@ -70,7 +70,7 @@ def next_block(self, number, spend=None, additional_coinbase_value=0, script=Non block = create_block(base_block_hash, coinbase, self.block_time) if (spend != None): tx = CTransaction() - tx.vin.append(CTxIn(COutPoint(spend.tx.sha256, spend.n), "", 0xffffffff)) # no signature yet + tx.vin.append(CTxIn(COutPoint(spend.tx.sha256, spend.n), b"", 0xffffffff)) # no signature yet # This copies the java comparison tool testing behavior: the first # txout has a garbage scriptPubKey, "to make sure we're not # pre-verifying too much" (?) @@ -80,7 +80,7 @@ def next_block(self, number, spend=None, additional_coinbase_value=0, script=Non else: tx.vout.append(CTxOut(1, script)) # Now sign it if necessary - scriptSig = "" + scriptSig = b"" scriptPubKey = bytearray(spend.tx.vout[spend.n].scriptPubKey) if (scriptPubKey[0] == OP_TRUE): # looks like an anyone-can-spend scriptSig = CScript([OP_TRUE]) @@ -225,7 +225,7 @@ def update_block(block_number, new_transactions): # \-> b3 (1) -> b4 (2) tip(6) block(9, spend=out4, additional_coinbase_value=1) - yield rejected(RejectResult(16, 'bad-cb-amount')) + yield rejected(RejectResult(16, b'bad-cb-amount')) # Create a fork that ends in a block with too much fee (the one that causes the reorg) @@ -237,7 +237,7 @@ def update_block(block_number, new_transactions): yield rejected() block(11, spend=out4, additional_coinbase_value=1) - yield rejected(RejectResult(16, 'bad-cb-amount')) + yield rejected(RejectResult(16, b'bad-cb-amount')) # Try again, but with a valid fork first @@ -279,7 +279,7 @@ def update_block(block_number, new_transactions): out6 = get_spendable_output() too_many_checksigs = CScript([OP_CHECKSIG] * (1000000 // 50)) block(16, spend=out6, script=too_many_checksigs) - yield rejected(RejectResult(16, 'bad-blk-sigops')) + yield rejected(RejectResult(16, b'bad-blk-sigops')) # Attempt to spend a transaction created on a different fork @@ -288,7 +288,7 @@ def update_block(block_number, new_transactions): # \-> b3 (1) -> b4 (2) tip(15) block(17, spend=txout_b3) - yield rejected(RejectResult(16, 'bad-txns-inputs-missingorspent')) + yield rejected(RejectResult(16, b'bad-txns-inputs-missingorspent')) # Attempt to spend a transaction created on a different fork (on a fork this time) # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3) @@ -309,7 +309,7 @@ def update_block(block_number, new_transactions): tip(15) out7 = get_spendable_output() block(20, spend=out7) - yield rejected(RejectResult(16, 'bad-txns-premature-spend-of-coinbase')) + yield rejected(RejectResult(16, b'bad-txns-premature-spend-of-coinbase')) # Attempt to spend a coinbase at depth too low (on a fork this time) # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3) @@ -333,7 +333,7 @@ def update_block(block_number, new_transactions): old_hash = b23.sha256 tx = CTransaction() script_length = MAX_BLOCK_SIZE - len(b23.serialize()) - 69 - script_output = CScript([chr(0)*script_length]) + script_output = CScript([b'\x00' * script_length]) tx.vout.append(CTxOut(0, script_output)) tx.vin.append(CTxIn(COutPoint(b23.vtx[1].sha256, 1))) b23 = update_block(23, [tx]) @@ -345,11 +345,11 @@ def update_block(block_number, new_transactions): tip(15) b24 = block(24, spend=out6) script_length = MAX_BLOCK_SIZE - len(b24.serialize()) - 69 - script_output = CScript([chr(0)*(script_length+1)]) + script_output = CScript([b'\x00' * (script_length+1)]) tx.vout = [CTxOut(0, script_output)] b24 = update_block(24, [tx]) assert_equal(len(b24.serialize()), MAX_BLOCK_SIZE+1) - yield rejected(RejectResult(16, 'bad-blk-length')) + yield rejected(RejectResult(16, b'bad-blk-length')) b25 = block(25, spend=out7) yield rejected() @@ -361,12 +361,12 @@ def update_block(block_number, new_transactions): # \-> b3 (1) -> b4 (2) tip(15) b26 = block(26, spend=out6) - b26.vtx[0].vin[0].scriptSig = chr(0) + b26.vtx[0].vin[0].scriptSig = b'\x00' b26.vtx[0].rehash() # update_block causes the merkle root to get updated, even with no new # transactions, and updates the required state. b26 = update_block(26, []) - yield rejected(RejectResult(16, 'bad-cb-length')) + yield rejected(RejectResult(16, b'bad-cb-length')) # Extend the b26 chain to make sure bitcoind isn't accepting b26 b27 = block(27, spend=out7) @@ -375,10 +375,10 @@ def update_block(block_number, new_transactions): # Now try a too-large-coinbase script tip(15) b28 = block(28, spend=out6) - b28.vtx[0].vin[0].scriptSig = chr(0)*101 + b28.vtx[0].vin[0].scriptSig = b'\x00' * 101 b28.vtx[0].rehash() b28 = update_block(28, []) - yield rejected(RejectResult(16, 'bad-cb-length')) + yield rejected(RejectResult(16, b'bad-cb-length')) # Extend the b28 chain to make sure bitcoind isn't accepted b28 b29 = block(29, spend=out7) @@ -390,7 +390,7 @@ def update_block(block_number, new_transactions): # b30 has a max-sized coinbase scriptSig. tip(23) b30 = block(30) - b30.vtx[0].vin[0].scriptSig = chr(0)*100 + b30.vtx[0].vin[0].scriptSig = b'\x00' * 100 b30.vtx[0].rehash() b30 = update_block(30, []) yield accepted() diff --git a/qa/rpc-tests/proxy_test.py b/qa/rpc-tests/proxy_test.py index b3c65573ea332..91c871ddc9003 100755 --- a/qa/rpc-tests/proxy_test.py +++ b/qa/rpc-tests/proxy_test.py @@ -86,7 +86,7 @@ def node_test(self, node, proxies, auth, test_onion=True): assert(isinstance(cmd, Socks5Command)) # Note: bitcoind's SOCKS5 implementation only sends atyp DOMAINNAME, even if connecting directly to IPv4/IPv6 assert_equal(cmd.atyp, AddressType.DOMAINNAME) - assert_equal(cmd.addr, "15.61.23.23") + assert_equal(cmd.addr, b"15.61.23.23") assert_equal(cmd.port, 1234) if not auth: assert_equal(cmd.username, None) @@ -100,7 +100,7 @@ def node_test(self, node, proxies, auth, test_onion=True): assert(isinstance(cmd, Socks5Command)) # Note: bitcoind's SOCKS5 implementation only sends atyp DOMAINNAME, even if connecting directly to IPv4/IPv6 assert_equal(cmd.atyp, AddressType.DOMAINNAME) - assert_equal(cmd.addr, "1233:3432:2434:2343:3234:2345:6546:4534") + assert_equal(cmd.addr, b"1233:3432:2434:2343:3234:2345:6546:4534") assert_equal(cmd.port, 5443) if not auth: assert_equal(cmd.username, None) @@ -113,7 +113,7 @@ def node_test(self, node, proxies, auth, test_onion=True): cmd = proxies[2].queue.get() assert(isinstance(cmd, Socks5Command)) assert_equal(cmd.atyp, AddressType.DOMAINNAME) - assert_equal(cmd.addr, "bitcoinostk4e4re.onion") + assert_equal(cmd.addr, b"bitcoinostk4e4re.onion") assert_equal(cmd.port, 8333) if not auth: assert_equal(cmd.username, None) @@ -125,7 +125,7 @@ def node_test(self, node, proxies, auth, test_onion=True): cmd = proxies[3].queue.get() assert(isinstance(cmd, Socks5Command)) assert_equal(cmd.atyp, AddressType.DOMAINNAME) - assert_equal(cmd.addr, "node.noumenon") + assert_equal(cmd.addr, b"node.noumenon") assert_equal(cmd.port, 8333) if not auth: assert_equal(cmd.username, None) diff --git a/qa/rpc-tests/pruning.py b/qa/rpc-tests/pruning.py index dd2adea950f23..eccd157e5c085 100755 --- a/qa/rpc-tests/pruning.py +++ b/qa/rpc-tests/pruning.py @@ -311,7 +311,7 @@ def run_test(self): # \ \ # ++...++(1044) .. # - # N0 ********************(1032) @@...@@@(1552) + # N0 ********************(1032) @@...@@@(1552) # \ # *...**(1320) diff --git a/qa/rpc-tests/rawtransactions.py b/qa/rpc-tests/rawtransactions.py index 762a6d6a30c21..e38ef6c8b1071 100755 --- a/qa/rpc-tests/rawtransactions.py +++ b/qa/rpc-tests/rawtransactions.py @@ -88,8 +88,6 @@ def run_test(self): assert_equal(self.nodes[2].getbalance(), bal+Decimal('1.20000000')) #node2 has both keys of the 2of2 ms addr., tx should affect the balance - - # 2of3 test from different nodes bal = self.nodes[2].getbalance() addr1 = self.nodes[1].getnewaddress() diff --git a/qa/rpc-tests/replace-by-fee.py b/qa/rpc-tests/replace-by-fee.py index b951900c4dbd9..4c8ef6de26eb2 100755 --- a/qa/rpc-tests/replace-by-fee.py +++ b/qa/rpc-tests/replace-by-fee.py @@ -11,15 +11,11 @@ from test_framework.util import * from test_framework.script import * from test_framework.mininode import * -import binascii MAX_REPLACEMENT_LIMIT = 100 -def satoshi_round(amount): - return Decimal(amount).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN) - def txToHex(tx): - return binascii.hexlify(tx.serialize()).decode('utf-8') + return bytes_to_hex_str(tx.serialize()) def make_utxo(node, amount, confirmed=True, scriptPubKey=CScript([1])): """Create a txout with a given amount and scriptPubKey @@ -53,9 +49,7 @@ def make_utxo(node, amount, confirmed=True, scriptPubKey=CScript([1])): tx2.vout = [CTxOut(amount, scriptPubKey)] tx2.rehash() - binascii.hexlify(tx2.serialize()).decode('utf-8') - - signed_tx = node.signrawtransaction(binascii.hexlify(tx2.serialize()).decode('utf-8')) + signed_tx = node.signrawtransaction(txToHex(tx2)) txid = node.sendrawtransaction(signed_tx['hex'], True) diff --git a/qa/rpc-tests/rest.py b/qa/rpc-tests/rest.py index 3c8a405bdd044..359f9239fb370 100755 --- a/qa/rpc-tests/rest.py +++ b/qa/rpc-tests/rest.py @@ -39,7 +39,7 @@ def http_get_call(host, port, path, response_object = 0): if response_object: return conn.getresponse() - return conn.getresponse().read() + return conn.getresponse().read().decode('utf-8') #allows simple http post calls with a request body def http_post_call(host, port, path, requestdata = '', response_object = 0): @@ -141,9 +141,9 @@ def run_test(self): bb_hash = self.nodes[0].getbestblockhash() binaryRequest = b'\x01\x02' - binaryRequest += binascii.unhexlify(txid) + binaryRequest += hex_str_to_bytes(txid) binaryRequest += pack("i", n) - binaryRequest += binascii.unhexlify(vintx) + binaryRequest += hex_str_to_bytes(vintx) binaryRequest += pack("i", 0) bin_response = http_post_call(url.hostname, url.port, '/rest/getutxos'+self.FORMAT_SEPARATOR+'bin', binaryRequest) @@ -234,7 +234,7 @@ def run_test(self): assert_equal(response_hex.status, 200) assert_greater_than(int(response_hex.getheader('content-length')), 160) response_hex_str = response_hex.read() - assert_equal(encode(response_str, "hex")[0:160], response_hex_str[0:160]) + assert_equal(encode(response_str, "hex_codec")[0:160], response_hex_str[0:160]) # compare with hex block header response_header_hex = http_get_call(url.hostname, url.port, '/rest/headers/1/'+bb_hash+self.FORMAT_SEPARATOR+"hex", True) @@ -242,7 +242,7 @@ def run_test(self): assert_greater_than(int(response_header_hex.getheader('content-length')), 160) response_header_hex_str = response_header_hex.read() assert_equal(response_hex_str[0:160], response_header_hex_str[0:160]) - assert_equal(encode(response_header_str, "hex")[0:160], response_header_hex_str[0:160]) + assert_equal(encode(response_header_str, "hex_codec")[0:160], response_header_hex_str[0:160]) # check json format block_json_string = http_get_call(url.hostname, url.port, '/rest/block/'+bb_hash+self.FORMAT_SEPARATOR+'json') @@ -252,7 +252,7 @@ def run_test(self): # compare with json block header response_header_json = http_get_call(url.hostname, url.port, '/rest/headers/1/'+bb_hash+self.FORMAT_SEPARATOR+"json", True) assert_equal(response_header_json.status, 200) - response_header_json_str = response_header_json.read() + response_header_json_str = response_header_json.read().decode('utf-8') json_obj = json.loads(response_header_json_str, parse_float=Decimal) assert_equal(len(json_obj), 1) #ensure that there is one header in the json response assert_equal(json_obj[0]['hash'], bb_hash) #request/response hash should be the same @@ -276,7 +276,7 @@ def run_test(self): self.sync_all() response_header_json = http_get_call(url.hostname, url.port, '/rest/headers/5/'+bb_hash+self.FORMAT_SEPARATOR+"json", True) assert_equal(response_header_json.status, 200) - response_header_json_str = response_header_json.read() + response_header_json_str = response_header_json.read().decode('utf-8') json_obj = json.loads(response_header_json_str) assert_equal(len(json_obj), 5) #now we should have 5 header objects @@ -292,7 +292,6 @@ def run_test(self): assert_greater_than(int(response.getheader('content-length')), 10) - # check block tx details # let's make 3 tx and mine them on node 1 txs = [] diff --git a/qa/rpc-tests/test_framework/blocktools.py b/qa/rpc-tests/test_framework/blocktools.py index afa0f5f9ba5ec..384f40e62dfca 100644 --- a/qa/rpc-tests/test_framework/blocktools.py +++ b/qa/rpc-tests/test_framework/blocktools.py @@ -62,6 +62,6 @@ def create_transaction(prevtx, n, sig, value): tx = CTransaction() assert(n < len(prevtx.vout)) tx.vin.append(CTxIn(COutPoint(prevtx.sha256, n), sig, 0xffffffff)) - tx.vout.append(CTxOut(value, "")) + tx.vout.append(CTxOut(value, b"")) tx.calc_sha256() return tx diff --git a/qa/rpc-tests/test_framework/comptool.py b/qa/rpc-tests/test_framework/comptool.py index 6279070fbc1bb..17626cf8dada4 100755 --- a/qa/rpc-tests/test_framework/comptool.py +++ b/qa/rpc-tests/test_framework/comptool.py @@ -31,7 +31,7 @@ class RejectResult(object): ''' Outcome that expects rejection of a transaction or block. ''' - def __init__(self, code, reason=''): + def __init__(self, code, reason=b''): self.code = code self.reason = reason def match(self, other): @@ -97,9 +97,9 @@ def on_pong(self, conn, message): raise AssertionError("Got pong for unknown ping [%s]" % repr(message)) def on_reject(self, conn, message): - if message.message == 'tx': + if message.message == b'tx': self.tx_reject_map[message.data] = RejectResult(message.code, message.reason) - if message.message == 'block': + if message.message == b'block': self.block_reject_map[message.data] = RejectResult(message.code, message.reason) def send_inv(self, obj): diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index 53f5e8805aa77..5ee5b132757d4 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -20,10 +20,10 @@ import struct import socket import asyncore -import binascii import time import sys import random +from binascii import hexlify, unhexlify from io import BytesIO from codecs import encode import hashlib @@ -34,7 +34,7 @@ BIP0031_VERSION = 60000 MY_VERSION = 60001 # past bip-31 for ping/pong -MY_SUBVERSION = "/python-mininode-tester:0.0.1/" +MY_SUBVERSION = b"/python-mininode-tester:0.0.2/" MAX_INV_SZ = 50000 MAX_BLOCK_SIZE = 1000000 @@ -131,7 +131,7 @@ def deser_vector(f, c): def ser_vector(l): - r = "" + r = b"" if len(l) < 253: r = struct.pack("B", len(l)) elif len(l) < 0x10000: @@ -161,7 +161,7 @@ def deser_uint256_vector(f): def ser_uint256_vector(l): - r = "" + r = b"" if len(l) < 253: r = struct.pack("B", len(l)) elif len(l) < 0x10000: @@ -221,7 +221,7 @@ def deser_int_vector(f): def ser_int_vector(l): - r = "" + r = b"" if len(l) < 253: r = struct.pack("B", len(l)) elif len(l) < 0x10000: @@ -236,19 +236,19 @@ def ser_int_vector(l): # Deserialize from a hex string representation (eg from RPC) def FromHex(obj, hex_string): - obj.deserialize(BytesIO(binascii.unhexlify(hex_string))) + obj.deserialize(BytesIO(unhexlify(hex_string.encode('ascii')))) return obj # Convert a binary-serializable object to hex (eg for submission via RPC) def ToHex(obj): - return binascii.hexlify(obj.serialize()).decode('utf-8') + return hexlify(obj.serialize()).decode('ascii') # Objects that map to bitcoind objects, which can be serialized/deserialized class CAddress(object): def __init__(self): self.nServices = 1 - self.pchReserved = "\x00" * 10 + "\xff" * 2 + self.pchReserved = b"\x00" * 10 + b"\xff" * 2 self.ip = "0.0.0.0" self.port = 0 @@ -259,7 +259,7 @@ def deserialize(self, f): self.port = struct.unpack(">H", f.read(2))[0] def serialize(self): - r = "" + r = b"" r += struct.pack(" class msg_headers(object): - command = "headers" + command = b"headers" def __init__(self): self.headers = [] @@ -982,10 +982,10 @@ def __repr__(self): class msg_reject(object): - command = "reject" + command = b"reject" def __init__(self): - self.message = "" + self.message = b"" self.code = 0 self.reason = "" self.data = 0L @@ -1025,7 +1025,7 @@ def wait_until(predicate, attempts=float('inf'), timeout=float('inf')): return False class msg_feefilter(object): - command = "feefilter" + command = b"feefilter" def __init__(self, feerate=0L): self.feerate = feerate @@ -1034,7 +1034,7 @@ def deserialize(self, f): self.feerate = struct.unpack("= 209: th = sha256(data) @@ -1313,11 +1313,11 @@ def send_message(self, message, pushbuf=False): self.last_sent = time.time() def got_message(self, message): - if message.command == "version": + if message.command == b"version": if message.nVersion <= BIP0031_VERSION: - self.messagemap['ping'] = msg_ping_prebip31 + self.messagemap[b'ping'] = msg_ping_prebip31 if self.last_sent + 30 * 60 < time.time(): - self.send_message(self.messagemap['ping']()) + self.send_message(self.messagemap[b'ping']()) self.show_debug_msg("Recv %s" % repr(message)) self.cb.deliver(self, message) diff --git a/qa/rpc-tests/test_framework/netutil.py b/qa/rpc-tests/test_framework/netutil.py index bbc58a14ec346..52a7ab74890f1 100644 --- a/qa/rpc-tests/test_framework/netutil.py +++ b/qa/rpc-tests/test_framework/netutil.py @@ -4,13 +4,14 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. # Linux network utilities + import sys import socket import fcntl import struct import array import os -import binascii +from binascii import unhexlify, hexlify # Roughly based on http://voorloopnul.com/blog/a-python-netstat-in-less-than-100-lines-of-code/ by Ricardo Pascal STATE_ESTABLISHED = '01' @@ -43,7 +44,7 @@ def _remove_empty(array): def _convert_ip_port(array): host,port = array.split(':') # convert host from mangled-per-four-bytes form as used by kernel - host = binascii.unhexlify(host) + host = unhexlify(host) host_out = '' for x in range(0, len(host) // 4): (val,) = struct.unpack('=I', host[x*4:(x+1)*4]) @@ -94,7 +95,7 @@ def all_interfaces(): max_possible = 8 # initial value while True: bytes = max_possible * struct_size - names = array.array('B', '\0' * bytes) + names = array.array('B', b'\0' * bytes) outbytes = struct.unpack('iL', fcntl.ioctl( s.fileno(), 0x8912, # SIOCGIFCONF @@ -105,7 +106,7 @@ def all_interfaces(): else: break namestr = names.tostring() - return [(namestr[i:i+16].split('\0', 1)[0], + return [(namestr[i:i+16].split(b'\0', 1)[0], socket.inet_ntoa(namestr[i+20:i+24])) for i in range(0, outbytes, struct_size)] @@ -136,7 +137,7 @@ def addr_to_hex(addr): addr = sub[0] + ([0] * nullbytes) + sub[1] else: raise ValueError('Could not parse address %s' % addr) - return binascii.hexlify(bytearray(addr)) + return hexlify(bytearray(addr)).decode('ascii') def test_ipv6_local(): ''' diff --git a/qa/rpc-tests/test_framework/script.py b/qa/rpc-tests/test_framework/script.py index bf5e25fb27653..5fb5758f81fa3 100644 --- a/qa/rpc-tests/test_framework/script.py +++ b/qa/rpc-tests/test_framework/script.py @@ -629,7 +629,7 @@ def encode(obj): neg = obj.value < 0 absvalue = -obj.value if neg else obj.value while (absvalue): - r.append(chr(absvalue & 0xff)) + r.append(absvalue & 0xff) absvalue >>= 8 if r[-1] & 0x80: r.append(0x80 if neg else 0) @@ -777,7 +777,7 @@ def __repr__(self): # need to change def _repr(o): if isinstance(o, bytes): - return "x('%s')" % hexlify(o).decode('utf8') + return b"x('%s')" % hexlify(o).decode('ascii') else: return repr(o) diff --git a/qa/rpc-tests/test_framework/socks5.py b/qa/rpc-tests/test_framework/socks5.py index 12327a6c5f4a9..f725d97701747 100644 --- a/qa/rpc-tests/test_framework/socks5.py +++ b/qa/rpc-tests/test_framework/socks5.py @@ -102,7 +102,7 @@ def handle(self): addr = recvall(self.conn, 4) elif atyp == AddressType.DOMAINNAME: n = recvall(self.conn, 1)[0] - addr = str(recvall(self.conn, n)) + addr = recvall(self.conn, n) elif atyp == AddressType.IPV6: addr = recvall(self.conn, 16) else: diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index d9fe0f75f2608..42541b4162e96 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -1,6 +1,8 @@ # Copyright (c) 2014-2015 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. + + # # Helpful routines for regression testing # @@ -9,6 +11,8 @@ import os import sys +from binascii import hexlify, unhexlify +from base64 import b64encode from decimal import Decimal, ROUND_DOWN import json import random @@ -91,6 +95,15 @@ def check_json_precision(): def count_bytes(hex_string): return len(bytearray.fromhex(hex_string)) +def bytes_to_hex_str(byte_str): + return hexlify(byte_str).decode('ascii') + +def hex_str_to_bytes(hex_str): + return unhexlify(hex_str.encode('ascii')) + +def str_to_b64str(string): + return b64encode(string.encode('utf-8')).decode('ascii') + def sync_blocks(rpc_connections, wait=1): """ Wait until everybody has the same block count @@ -466,7 +479,7 @@ def assert_is_hash_string(string, length=64): "String %r contains invalid characters for a hash." % string) def satoshi_round(amount): - return Decimal(amount).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN) + return Decimal(amount).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN) # Helper to create at least "count" utxos # Pass in a fee that is sufficient for relay and mining new transactions. diff --git a/qa/rpc-tests/zmq_test.py b/qa/rpc-tests/zmq_test.py index 88532541ab6a5..3a8d62ef2eddc 100755 --- a/qa/rpc-tests/zmq_test.py +++ b/qa/rpc-tests/zmq_test.py @@ -28,8 +28,8 @@ class ZMQTest (BitcoinTestFramework): def setup_nodes(self): self.zmqContext = zmq.Context() self.zmqSubSocket = self.zmqContext.socket(zmq.SUB) - self.zmqSubSocket.setsockopt(zmq.SUBSCRIBE, "hashblock") - self.zmqSubSocket.setsockopt(zmq.SUBSCRIBE, "hashtx") + self.zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"hashblock") + self.zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"hashtx") self.zmqSubSocket.connect("tcp://127.0.0.1:%i" % self.port) return start_nodes(4, self.options.tmpdir, extra_args=[ ['-zmqpubhashtx=tcp://127.0.0.1:'+str(self.port), '-zmqpubhashblock=tcp://127.0.0.1:'+str(self.port)], @@ -46,13 +46,13 @@ def run_test(self): print "listen..." msg = self.zmqSubSocket.recv_multipart() - topic = str(msg[0]) + topic = msg[0] body = msg[1] msg = self.zmqSubSocket.recv_multipart() - topic = str(msg[0]) + topic = msg[0] body = msg[1] - blkhash = binascii.hexlify(body) + blkhash = bytes_to_hex_str(body) assert_equal(genhashes[0], blkhash) #blockhash from generate must be equal to the hash received over zmq @@ -63,10 +63,10 @@ def run_test(self): zmqHashes = [] for x in range(0,n*2): msg = self.zmqSubSocket.recv_multipart() - topic = str(msg[0]) + topic = msg[0] body = msg[1] - if topic == "hashblock": - zmqHashes.append(binascii.hexlify(body)) + if topic == b"hashblock": + zmqHashes.append(bytes_to_hex_str(body)) for x in range(0,n): assert_equal(genhashes[x], zmqHashes[x]) #blockhash from generate must be equal to the hash received over zmq @@ -77,11 +77,11 @@ def run_test(self): # now we should receive a zmq msg because the tx was broadcast msg = self.zmqSubSocket.recv_multipart() - topic = str(msg[0]) + topic = msg[0] body = msg[1] hashZMQ = "" - if topic == "hashtx": - hashZMQ = binascii.hexlify(body) + if topic == b"hashtx": + hashZMQ = bytes_to_hex_str(body) assert_equal(hashRPC, hashZMQ) #blockhash from generate must be equal to the hash received over zmq diff --git a/src/test/bctest.py b/src/test/bctest.py index 8105b87ffa34c..fc59152ba12f1 100644 --- a/src/test/bctest.py +++ b/src/test/bctest.py @@ -2,6 +2,7 @@ # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. from __future__ import division,print_function,unicode_literals +from io import open import subprocess import os import json @@ -16,7 +17,7 @@ def bctest(testDir, testObj, exeext): inputData = None if "input" in testObj: filename = testDir + "/" + testObj['input'] - inputData = open(filename).read() + inputData = open(filename, 'rb').read() stdinCfg = subprocess.PIPE outputFn = None From fa6399d918fdaa8844c4c767b2012e0b2ca60ee9 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 10 Apr 2016 20:49:07 +0200 Subject: [PATCH 0128/1802] [doc] gitian: Replace precise with trusty --- doc/gitian-building.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/gitian-building.md b/doc/gitian-building.md index 69d79b3c68ab7..e1f46cd82f289 100644 --- a/doc/gitian-building.md +++ b/doc/gitian-building.md @@ -363,7 +363,7 @@ Output from `gbuild` will look something like Resolving deltas: 100% (41590/41590), done. From https://github.com/bitcoin/bitcoin ... (new tags, new branch etc) - --- Building for precise amd64 --- + --- Building for trusty amd64 --- Stopping target if it is up Making a new image copy stdin: is not a tty @@ -412,14 +412,14 @@ So, if you use LXC: export PATH="$PATH":/path/to/gitian-builder/libexec export USE_LXC=1 cd /path/to/gitian-builder -./libexec/make-clean-vm --suite precise --arch amd64 +./libexec/make-clean-vm --suite trusty --arch amd64 -LXC_ARCH=amd64 LXC_SUITE=precise on-target -u root apt-get update -LXC_ARCH=amd64 LXC_SUITE=precise on-target -u root \ +LXC_ARCH=amd64 LXC_SUITE=trusty on-target -u root apt-get update +LXC_ARCH=amd64 LXC_SUITE=trusty on-target -u root \ -e DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends -y install \ $( sed -ne '/^packages:/,/[^-] .*/ {/^- .*/{s/"//g;s/- //;p}}' ../bitcoin/contrib/gitian-descriptors/*|sort|uniq ) -LXC_ARCH=amd64 LXC_SUITE=precise on-target -u root apt-get -q -y purge grub -LXC_ARCH=amd64 LXC_SUITE=precise on-target -u root -e DEBIAN_FRONTEND=noninteractive apt-get -y dist-upgrade +LXC_ARCH=amd64 LXC_SUITE=trusty on-target -u root apt-get -q -y purge grub +LXC_ARCH=amd64 LXC_SUITE=trusty on-target -u root -e DEBIAN_FRONTEND=noninteractive apt-get -y dist-upgrade ``` And then set offline mode for apt-cacher-ng: From fa42a675c08ba738a47bf37056ef090441ec5a83 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Tue, 5 Apr 2016 13:29:04 +0200 Subject: [PATCH 0129/1802] [gitian] hardcode datetime for depends --- contrib/gitian-descriptors/gitian-linux.yml | 19 ++++++++++++---- contrib/gitian-descriptors/gitian-osx.yml | 19 ++++++++++++---- contrib/gitian-descriptors/gitian-win.yml | 25 ++++++++++++++++----- 3 files changed, 49 insertions(+), 14 deletions(-) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index 8b2ab4ebfd25b..045643e297f17 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -41,29 +41,36 @@ script: | mkdir -p ${BASE_CACHE} ${SOURCES_PATH} fi - # Create global faketime wrappers + function create_global_faketime_wrappers { for prog in ${FAKETIME_PROGS}; do echo '#!/bin/bash' > ${WRAP_DIR}/${prog} echo "REAL=\`which -a ${prog} | grep -v ${WRAP_DIR}/${prog} | head -1\`" >> ${WRAP_DIR}/${prog} echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${prog} - echo "export FAKETIME=\"${REFERENCE_DATETIME}\"" >> ${WRAP_DIR}/${prog} + echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${prog} echo "\$REAL \$@" >> $WRAP_DIR/${prog} chmod +x ${WRAP_DIR}/${prog} done + } - # Create per-host faketime wrappers + function create_per-host_faketime_wrappers { for i in $HOSTS; do for prog in ${FAKETIME_HOST_PROGS}; do echo '#!/bin/bash' > ${WRAP_DIR}/${i}-${prog} echo "REAL=\`which -a ${i}-${prog} | grep -v ${WRAP_DIR}/${i}-${prog} | head -1\`" >> ${WRAP_DIR}/${i}-${prog} echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${i}-${prog} - echo "export FAKETIME=\"${REFERENCE_DATETIME}\"" >> ${WRAP_DIR}/${i}-${prog} + echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${i}-${prog} echo "\$REAL \$@" >> $WRAP_DIR/${i}-${prog} chmod +x ${WRAP_DIR}/${i}-${prog} done done + } + export PATH=${WRAP_DIR}:${PATH} + # Faketime for depends so intermediate results are comparable + create_global_faketime_wrappers "2000-01-01 12:00:00" + create_per-host_faketime_wrappers "2000-01-01 12:00:00" + cd bitcoin BASEPREFIX=`pwd`/depends # Build dependencies for each host @@ -71,6 +78,10 @@ script: | make ${MAKEOPTS} -C ${BASEPREFIX} HOST="${i}" done + # Faketime for binaries + create_global_faketime_wrappers "${REFERENCE_DATETIME}" + create_per-host_faketime_wrappers "${REFERENCE_DATETIME}" + # Create the release tarball using (arbitrarily) the first host ./autogen.sh ./configure --prefix=${BASEPREFIX}/`echo "${HOSTS}" | awk '{print $1;}'` diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml index 74fc2e93ad3d8..dbd0cedafeb41 100644 --- a/contrib/gitian-descriptors/gitian-osx.yml +++ b/contrib/gitian-descriptors/gitian-osx.yml @@ -53,29 +53,36 @@ script: | export ZERO_AR_DATE=1 - # Create global faketime wrappers + function create_global_faketime_wrappers { for prog in ${FAKETIME_PROGS}; do echo '#!/bin/bash' > ${WRAP_DIR}/${prog} echo "REAL=\`which -a ${prog} | grep -v ${WRAP_DIR}/${prog} | head -1\`" >> ${WRAP_DIR}/${prog} echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${prog} - echo "export FAKETIME=\"${REFERENCE_DATETIME}\"" >> ${WRAP_DIR}/${prog} + echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${prog} echo "\$REAL \$@" >> $WRAP_DIR/${prog} chmod +x ${WRAP_DIR}/${prog} done + } - # Create per-host faketime wrappers + function create_per-host_faketime_wrappers { for i in $HOSTS; do for prog in ${FAKETIME_HOST_PROGS}; do echo '#!/bin/bash' > ${WRAP_DIR}/${i}-${prog} echo "REAL=\`which -a ${i}-${prog} | grep -v ${WRAP_DIR}/${i}-${prog} | head -1\`" >> ${WRAP_DIR}/${i}-${prog} echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${i}-${prog} - echo "export FAKETIME=\"${REFERENCE_DATETIME}\"" >> ${WRAP_DIR}/${i}-${prog} + echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${i}-${prog} echo "\$REAL \$@" >> $WRAP_DIR/${i}-${prog} chmod +x ${WRAP_DIR}/${i}-${prog} done done + } + export PATH=${WRAP_DIR}:${PATH} + # Faketime for depends so intermediate results are comparable + create_global_faketime_wrappers "2000-01-01 12:00:00" + create_per-host_faketime_wrappers "2000-01-01 12:00:00" + cd bitcoin BASEPREFIX=`pwd`/depends @@ -87,6 +94,10 @@ script: | make ${MAKEOPTS} -C ${BASEPREFIX} HOST="${i}" done + # Faketime for binaries + create_global_faketime_wrappers "${REFERENCE_DATETIME}" + create_per-host_faketime_wrappers "${REFERENCE_DATETIME}" + # Create the release tarball using (arbitrarily) the first host ./autogen.sh ./configure --prefix=${BASEPREFIX}/`echo "${HOSTS}" | awk '{print $1;}'` diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml index 719ca9c232bfe..2c035db17b8b8 100644 --- a/contrib/gitian-descriptors/gitian-win.yml +++ b/contrib/gitian-descriptors/gitian-win.yml @@ -44,29 +44,31 @@ script: | mkdir -p ${BASE_CACHE} ${SOURCES_PATH} fi - # Create global faketime wrappers + function create_global_faketime_wrappers { for prog in ${FAKETIME_PROGS}; do echo '#!/bin/bash' > ${WRAP_DIR}/${prog} echo "REAL=\`which -a ${prog} | grep -v ${WRAP_DIR}/${prog} | head -1\`" >> ${WRAP_DIR}/${prog} echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${prog} - echo "export FAKETIME=\"${REFERENCE_DATETIME}\"" >> ${WRAP_DIR}/${prog} + echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${prog} echo "\$REAL \$@" >> $WRAP_DIR/${prog} chmod +x ${WRAP_DIR}/${prog} done + } - # Create per-host faketime wrappers + function create_per-host_faketime_wrappers { for i in $HOSTS; do for prog in ${FAKETIME_HOST_PROGS}; do echo '#!/bin/bash' > ${WRAP_DIR}/${i}-${prog} echo "REAL=\`which -a ${i}-${prog} | grep -v ${WRAP_DIR}/${i}-${prog} | head -1\`" >> ${WRAP_DIR}/${i}-${prog} echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${i}-${prog} - echo "export FAKETIME=\"${REFERENCE_DATETIME}\"" >> ${WRAP_DIR}/${i}-${prog} + echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${i}-${prog} echo "\$REAL \$@" >> $WRAP_DIR/${i}-${prog} chmod +x ${WRAP_DIR}/${i}-${prog} done done + } - # Create per-host linker wrapper + function create_per-host_linker_wrapper { # This is only needed for trusty, as the mingw linker leaks a few bytes of # heap, causing non-determinism. See discussion in https://github.com/bitcoin/bitcoin/pull/6900 for i in $HOSTS; do @@ -82,15 +84,21 @@ script: | echo '#!/bin/bash' > ${WRAP_DIR}/${i}-${prog} echo "REAL=\`which -a ${i}-${prog} | grep -v ${WRAP_DIR}/${i}-${prog} | head -1\`" >> ${WRAP_DIR}/${i}-${prog} echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${i}-${prog} - echo "export FAKETIME=\"${REFERENCE_DATETIME}\"" >> ${WRAP_DIR}/${i}-${prog} + echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${i}-${prog} echo "export COMPILER_PATH=${WRAP_DIR}/${i}" >> ${WRAP_DIR}/${i}-${prog} echo "\$REAL \$@" >> $WRAP_DIR/${i}-${prog} chmod +x ${WRAP_DIR}/${i}-${prog} done done + } export PATH=${WRAP_DIR}:${PATH} + # Faketime for depends so intermediate results are comparable + create_global_faketime_wrappers "2000-01-01 12:00:00" + create_per-host_faketime_wrappers "2000-01-01 12:00:00" + create_per-host_linker_wrapper "2000-01-01 12:00:00" + cd bitcoin BASEPREFIX=`pwd`/depends # Build dependencies for each host @@ -98,6 +106,11 @@ script: | make ${MAKEOPTS} -C ${BASEPREFIX} HOST="${i}" done + # Faketime for binaries + create_global_faketime_wrappers "${REFERENCE_DATETIME}" + create_per-host_faketime_wrappers "${REFERENCE_DATETIME}" + create_per-host_linker_wrapper "${REFERENCE_DATETIME}" + # Create the release tarball using (arbitrarily) the first host ./autogen.sh ./configure --prefix=${BASEPREFIX}/`echo "${HOSTS}" | awk '{print $1;}'` From 66b07247a7a9e48e082502338176cc06edf61474 Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Mon, 11 Apr 2016 01:09:34 +0000 Subject: [PATCH 0130/1802] Only send one GetAddr response per connection. This conserves resources from abusive peers that just send getaddr in a loop. Also makes correlating addr messages against INVs less effective. --- src/main.cpp | 8 ++++++++ src/net.cpp | 1 + src/net.h | 1 + 3 files changed, 10 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index f5c7e11d6e8a3..df494b226dcf0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5214,6 +5214,14 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, return true; } + // Only send one GetAddr response per connection to reduce resource waste + // and discourage addr stamping of INV announcements. + if (pfrom->fSentAddr) { + LogPrint("net", "Ignoring repeated \"getaddr\". peer=%d\n", pfrom->id); + return true; + } + pfrom->fSentAddr = true; + pfrom->vAddrToSend.clear(); vector vAddr = addrman.GetAddr(); BOOST_FOREACH(const CAddress &addr, vAddr) diff --git a/src/net.cpp b/src/net.cpp index e8cc753a486d0..77310fb162afa 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2384,6 +2384,7 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa nNextAddrSend = 0; nNextInvSend = 0; fRelayTxes = false; + fSentAddr = false; pfilter = new CBloomFilter(); nPingNonceSent = 0; nPingUsecStart = 0; diff --git a/src/net.h b/src/net.h index ab9eb68d8577a..230fd5bf403e7 100644 --- a/src/net.h +++ b/src/net.h @@ -358,6 +358,7 @@ class CNode // b) the peer may tell us in its version message that we should not relay tx invs // unless it loads a bloom filter. bool fRelayTxes; + bool fSentAddr; CSemaphoreGrant grantOutbound; CCriticalSection cs_filter; CBloomFilter* pfilter; From 0dbf6e4b409648a27324bf230d7feec973984da4 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 1 Apr 2016 12:19:28 -0400 Subject: [PATCH 0131/1802] build: define base filenames for use elsewhere in the buildsystem Unfortunately, the target namees defined at the Makefile.am level can't be used for *.in substitution. So these new defines will have to stay synced up with those targets. Using the new variables for the deploy targets in the main Makefile.am will ensure that they stay in sync, otherwise build tests will fail. --- Makefile.am | 6 +++--- configure.ac | 9 +++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index 0929a59ed2de6..5783c1fdd8f55 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,9 +10,9 @@ pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libbitcoinconsensus.pc endif -BITCOIND_BIN=$(top_builddir)/src/bitcoind$(EXEEXT) -BITCOIN_QT_BIN=$(top_builddir)/src/qt/bitcoin-qt$(EXEEXT) -BITCOIN_CLI_BIN=$(top_builddir)/src/bitcoin-cli$(EXEEXT) +BITCOIND_BIN=$(top_builddir)/src/$(BITCOIN_DAEMON_NAME)$(EXEEXT) +BITCOIN_QT_BIN=$(top_builddir)/src/qt/$(BITCOIN_GUI_NAME)$(EXEEXT) +BITCOIN_CLI_BIN=$(top_builddir)/src/$(BITCOIN_CLI_NAME)$(EXEEXT) BITCOIN_WIN_INSTALLER=$(PACKAGE)-$(PACKAGE_VERSION)-win$(WINDOWS_BITS)-setup$(EXEEXT) empty := diff --git a/configure.ac b/configure.ac index ec5656814f074..6e463dfc5540d 100644 --- a/configure.ac +++ b/configure.ac @@ -14,6 +14,11 @@ AC_CONFIG_HEADERS([src/config/bitcoin-config.h]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_MACRO_DIR([build-aux/m4]) +BITCOIN_DAEMON_NAME=bitcoind +BITCOIN_GUI_NAME=bitcoin-qt +BITCOIN_CLI_NAME=bitcoin-cli +BITCOIN_TX_NAME=bitcoin-tx + AC_CANONICAL_HOST AH_TOP([#ifndef BITCOIN_CONFIG_H]) @@ -1019,6 +1024,10 @@ AC_SUBST(COPYRIGHT_YEAR, _COPYRIGHT_YEAR) AC_SUBST(COPYRIGHT_HOLDERS, "_COPYRIGHT_HOLDERS") AC_SUBST(COPYRIGHT_HOLDERS_SUBSTITUTION, "_COPYRIGHT_HOLDERS_SUBSTITUTION") AC_SUBST(COPYRIGHT_HOLDERS_FINAL, "_COPYRIGHT_HOLDERS_FINAL") +AC_SUBST(BITCOIN_DAEMON_NAME) +AC_SUBST(BITCOIN_GUI_NAME) +AC_SUBST(BITCOIN_CLI_NAME) +AC_SUBST(BITCOIN_TX_NAME) AC_SUBST(RELDFLAGS) AC_SUBST(HARDENED_CXXFLAGS) From 26880c34cd3e0837724487f6b14cc3cdd7bc8a4f Mon Sep 17 00:00:00 2001 From: JeremyRand Date: Fri, 26 Feb 2016 00:04:48 +0000 Subject: [PATCH 0132/1802] build: Use PACKAGE_TARNAME and new bin names in NSIS script. Replaces the hardcoded string "bitcoin" with the autoconf variable PACKAGE_TARNAME; fixes #7265. Places where I chose not to replace: 1. bitcoin.ico wasn't replaced because it doesn't seem to be relevant to the build system and its filename never affects the end user. 2. InstallDir wasn't replaced because the current text has an uppercase B, and I'm not sure of a good way to capitalize the result of PACKAGE_TARNAME. 3. A comment in the Main Installer section wasn't replaced because comments don't ever face the end user. 4. The registry value "URL:Bitcoin" wasn't replaced for the same reason as InstallDir. 5. Startup shortcut wasn't replaced for the same reason as InstallDir. All other appearances of "bitcoin" were replaced with PACKAGE_TARNAME, except for the bin names, which were instead replaced with the new bin name autoconf variables. --- share/setup.nsi.in | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/share/setup.nsi.in b/share/setup.nsi.in index e553a5ae88275..ebffb3b8590c4 100644 --- a/share/setup.nsi.in +++ b/share/setup.nsi.in @@ -20,7 +20,7 @@ SetCompressor /SOLID lzma !define MUI_STARTMENUPAGE_REGISTRY_KEY ${REGKEY} !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME StartMenuGroup !define MUI_STARTMENUPAGE_DEFAULTFOLDER "@PACKAGE_NAME@" -!define MUI_FINISHPAGE_RUN $INSTDIR\bitcoin-qt.exe +!define MUI_FINISHPAGE_RUN $INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@ !define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico" !define MUI_UNWELCOMEFINISHPAGE_BITMAP "@abs_top_srcdir@/share/pixmaps/nsis-wizard.bmp" !define MUI_UNFINISHPAGE_NOAUTOCLOSE @@ -48,7 +48,7 @@ Var StartMenuGroup !insertmacro MUI_LANGUAGE English # Installer attributes -OutFile @abs_top_srcdir@/bitcoin-${VERSION}-win@WINDOWS_BITS@-setup.exe +OutFile @abs_top_srcdir@/@PACKAGE_TARNAME@-${VERSION}-win@WINDOWS_BITS@-setup.exe !if "@WINDOWS_BITS@" == "64" InstallDir $PROGRAMFILES64\Bitcoin !else @@ -73,19 +73,19 @@ ShowUninstDetails show Section -Main SEC0000 SetOutPath $INSTDIR SetOverwrite on - File @abs_top_srcdir@/release/bitcoin-qt.exe + File @abs_top_srcdir@/release/@BITCOIN_GUI_NAME@@EXEEXT@ File /oname=COPYING.txt @abs_top_srcdir@/COPYING File /oname=readme.txt @abs_top_srcdir@/doc/README_windows.txt SetOutPath $INSTDIR\daemon - File @abs_top_srcdir@/release/bitcoind.exe - File @abs_top_srcdir@/release/bitcoin-cli.exe + File @abs_top_srcdir@/release/@BITCOIN_DAEMON_NAME@@EXEEXT@ + File @abs_top_srcdir@/release/@BITCOIN_CLI_NAME@@EXEEXT@ SetOutPath $INSTDIR\doc File /r @abs_top_srcdir@/doc\*.* SetOutPath $INSTDIR WriteRegStr HKCU "${REGKEY}\Components" Main 1 # Remove old wxwidgets-based-bitcoin executable and locales: - Delete /REBOOTOK $INSTDIR\bitcoin.exe + Delete /REBOOTOK $INSTDIR\@PACKAGE_TARNAME@.exe RMDir /r /REBOOTOK $INSTDIR\locale SectionEnd @@ -95,7 +95,7 @@ Section -post SEC0001 WriteUninstaller $INSTDIR\uninstall.exe !insertmacro MUI_STARTMENU_WRITE_BEGIN Application CreateDirectory $SMPROGRAMS\$StartMenuGroup - CreateShortcut "$SMPROGRAMS\$StartMenuGroup\$(^Name).lnk" $INSTDIR\bitcoin-qt.exe + CreateShortcut "$SMPROGRAMS\$StartMenuGroup\$(^Name).lnk" $INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@ CreateShortcut "$SMPROGRAMS\$StartMenuGroup\Uninstall $(^Name).lnk" $INSTDIR\uninstall.exe !insertmacro MUI_STARTMENU_WRITE_END WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayName "$(^Name)" @@ -106,10 +106,10 @@ Section -post SEC0001 WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" UninstallString $INSTDIR\uninstall.exe WriteRegDWORD HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" NoModify 1 WriteRegDWORD HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" NoRepair 1 - WriteRegStr HKCR "bitcoin" "URL Protocol" "" - WriteRegStr HKCR "bitcoin" "" "URL:Bitcoin" - WriteRegStr HKCR "bitcoin\DefaultIcon" "" $INSTDIR\bitcoin-qt.exe - WriteRegStr HKCR "bitcoin\shell\open\command" "" '"$INSTDIR\bitcoin-qt.exe" "%1"' + WriteRegStr HKCR "@PACKAGE_TARNAME@" "URL Protocol" "" + WriteRegStr HKCR "@PACKAGE_TARNAME@" "" "URL:Bitcoin" + WriteRegStr HKCR "@PACKAGE_TARNAME@\DefaultIcon" "" $INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@ + WriteRegStr HKCR "@PACKAGE_TARNAME@\shell\open\command" "" '"$INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@" "%1"' SectionEnd # Macro for selecting uninstaller sections @@ -127,7 +127,7 @@ done${UNSECTION_ID}: # Uninstaller sections Section /o -un.Main UNSEC0000 - Delete /REBOOTOK $INSTDIR\bitcoin-qt.exe + Delete /REBOOTOK $INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@ Delete /REBOOTOK $INSTDIR\COPYING.txt Delete /REBOOTOK $INSTDIR\readme.txt RMDir /r /REBOOTOK $INSTDIR\daemon @@ -147,7 +147,7 @@ Section -un.post UNSEC0001 DeleteRegValue HKCU "${REGKEY}" Path DeleteRegKey /IfEmpty HKCU "${REGKEY}\Components" DeleteRegKey /IfEmpty HKCU "${REGKEY}" - DeleteRegKey HKCR "bitcoin" + DeleteRegKey HKCR "@PACKAGE_TARNAME@" RmDir /REBOOTOK $SMPROGRAMS\$StartMenuGroup RmDir /REBOOTOK $INSTDIR Push $R0 From 0528e30a4551d1437e049103624fd461229aced1 Mon Sep 17 00:00:00 2001 From: JeremyRand Date: Sat, 19 Mar 2016 11:19:06 +0000 Subject: [PATCH 0133/1802] Remove wxwidgets references from NSIS script. The NSIS script tried to delete wxwidgets-based executables/locales. These files are ancient, and presumably no users have them anymore, so we can simplify the NSIS script by removing those lines. --- share/setup.nsi.in | 4 ---- 1 file changed, 4 deletions(-) diff --git a/share/setup.nsi.in b/share/setup.nsi.in index ebffb3b8590c4..c062f96a3059c 100644 --- a/share/setup.nsi.in +++ b/share/setup.nsi.in @@ -83,10 +83,6 @@ Section -Main SEC0000 File /r @abs_top_srcdir@/doc\*.* SetOutPath $INSTDIR WriteRegStr HKCU "${REGKEY}\Components" Main 1 - - # Remove old wxwidgets-based-bitcoin executable and locales: - Delete /REBOOTOK $INSTDIR\@PACKAGE_TARNAME@.exe - RMDir /r /REBOOTOK $INSTDIR\locale SectionEnd Section -post SEC0001 From 4a1d5c19ee86b924705e66a8bc31567a35f9e53d Mon Sep 17 00:00:00 2001 From: fanquake Date: Fri, 8 Apr 2016 16:00:40 +0800 Subject: [PATCH 0134/1802] [Doc] Update gitian build guide to debian 8.4.0 --- doc/gitian-building.md | 20 +++++++++++------- .../all_files_in_one_partition.png | Bin 0 -> 3350 bytes .../create_vm_file_location_size.png | Bin 71743 -> 111942 bytes doc/gitian-building/select_startup_disk.png | Bin 130324 -> 72785 bytes 4 files changed, 12 insertions(+), 8 deletions(-) create mode 100644 doc/gitian-building/all_files_in_one_partition.png diff --git a/doc/gitian-building.md b/doc/gitian-building.md index 69d79b3c68ab7..151b9d8f9acda 100644 --- a/doc/gitian-building.md +++ b/doc/gitian-building.md @@ -47,7 +47,7 @@ You can also install Gitian on actual hardware instead of using virtualization. Create a new VirtualBox VM --------------------------- -In the VirtualBox GUI click "Create" and choose the following parameters in the wizard: +In the VirtualBox GUI click "New" and choose the following parameters in the wizard: ![](gitian-building/create_new_vm.png) @@ -74,13 +74,6 @@ In the VirtualBox GUI click "Create" and choose the following parameters in the - File location and size: at least 40GB; as low as 20GB *may* be possible, but better to err on the safe side - Click `Create` -Get the [Debian 8.x net installer](http://cdimage.debian.org/debian-cd/8.3.0/amd64/iso-cd/debian-8.3.0-amd64-netinst.iso) (a more recent minor version should also work, see also [Debian Network installation](https://www.debian.org/CD/netinst/)). -This DVD image can be validated using a SHA256 hashing tool, for example on -Unixy OSes by entering the following in a terminal: - - echo "dd25bcdde3c6ea5703cc0f313cde621b13d42ff7d252e2538a11663c93bf8654 debian-8.3.0-amd64-netinst.iso" | sha256sum -c - # (must return OK) - After creating the VM, we need to configure it. - Click the `Settings` button, then go to the `Network` tab. Adapter 1 should be attached to `NAT`. @@ -102,6 +95,13 @@ After creating the VM, we need to configure it. - Click `Ok` twice to save. +Get the [Debian 8.x net installer](http://cdimage.debian.org/debian-cd/8.4.0/amd64/iso-cd/debian-8.4.0-amd64-netinst.iso) (a more recent minor version should also work, see also [Debian Network installation](https://www.debian.org/CD/netinst/)). +This DVD image can be validated using a SHA256 hashing tool, for example on +Unixy OSes by entering the following in a terminal: + + echo "7a6b418e6a4ee3ca75dda04d79ed96c9e2c33bb0c703ca7e40c6374ab4590748 debian-8.4.0-amd64-netinst.iso" | sha256sum -c + # (must return OK) + Then start the VM. On the first launch you will be asked for a CD or DVD image. Choose the downloaded iso. ![](gitian-building/select_startup_disk.png) @@ -160,6 +160,10 @@ To select a different button, press `Tab`. ![](gitian-building/debian_install_12_choose_disk.png) + - Partition Disks -> *All files in one partition* + +![](gitian-building/all_files_in_one_partition.png) + - Finish partitioning and write changes to disk -> *Yes* (`Tab`, `Enter` to select the `Yes` button) ![](gitian-building/debian_install_14_finish.png) diff --git a/doc/gitian-building/all_files_in_one_partition.png b/doc/gitian-building/all_files_in_one_partition.png new file mode 100644 index 0000000000000000000000000000000000000000..8cbb0d8adc1deda1c7c4023611b65521e054ff69 GIT binary patch literal 3350 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∾;f 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

5}ss6hBz2 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

Yv36);|zQ7@X|zmOcox3QHk-s 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 literal 130324 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%0Ak59s=zJ0NHtF`o_dye&c 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 TE= Date: Mon, 11 Apr 2016 17:31:25 +0800 Subject: [PATCH 0135/1802] Add jl2012 public key for gitian build --- contrib/gitian-downloader/jl2012-key.pgp | 105 +++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 contrib/gitian-downloader/jl2012-key.pgp diff --git a/contrib/gitian-downloader/jl2012-key.pgp b/contrib/gitian-downloader/jl2012-key.pgp new file mode 100644 index 0000000000000..b8aad7fd88b42 --- /dev/null +++ b/contrib/gitian-downloader/jl2012-key.pgp @@ -0,0 +1,105 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Comment: GPGTools - https://gpgtools.org + +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 +=1irw +-----END PGP PUBLIC KEY BLOCK----- From 7e91f632c70ff1848a152f24ee67a06796803943 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Mon, 11 Apr 2016 12:52:29 -0400 Subject: [PATCH 0136/1802] Use txid as key in mapAlreadyAskedFor Previously we used the CInv that would be sent to the peer announcing the transaction as the key, but using the txid instead allows us to decouple the p2p layer from the application logic (which relies on this map to avoid duplicate tx requests). --- src/main.cpp | 2 +- src/net.cpp | 6 +++--- src/net.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index f5c7e11d6e8a3..5c1af9ecccfc8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4956,7 +4956,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, CValidationState state; pfrom->setAskFor.erase(inv.hash); - mapAlreadyAskedFor.erase(inv); + mapAlreadyAskedFor.erase(inv.hash); CFeeRate txFeeRate = CFeeRate(0); if (!AlreadyHave(inv) && AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs, &txFeeRate)) { diff --git a/src/net.cpp b/src/net.cpp index e8cc753a486d0..3bf8c165dc911 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -93,7 +93,7 @@ CCriticalSection cs_vNodes; map mapRelay; deque > vRelayExpiration; CCriticalSection cs_mapRelay; -limitedmap mapAlreadyAskedFor(MAX_INV_SZ); +limitedmap mapAlreadyAskedFor(MAX_INV_SZ); static deque vOneShots; CCriticalSection cs_vOneShots; @@ -2436,7 +2436,7 @@ void CNode::AskFor(const CInv& inv) // We're using mapAskFor as a priority queue, // the key is the earliest time the request can be sent int64_t nRequestTime; - limitedmap::const_iterator it = mapAlreadyAskedFor.find(inv); + limitedmap::const_iterator it = mapAlreadyAskedFor.find(inv.hash); if (it != mapAlreadyAskedFor.end()) nRequestTime = it->second; else @@ -2455,7 +2455,7 @@ void CNode::AskFor(const CInv& inv) if (it != mapAlreadyAskedFor.end()) mapAlreadyAskedFor.update(it, nRequestTime); else - mapAlreadyAskedFor.insert(std::make_pair(inv, nRequestTime)); + mapAlreadyAskedFor.insert(std::make_pair(inv.hash, nRequestTime)); mapAskFor.insert(std::make_pair(nRequestTime, inv)); } diff --git a/src/net.h b/src/net.h index ab9eb68d8577a..1892c963fcee2 100644 --- a/src/net.h +++ b/src/net.h @@ -164,7 +164,7 @@ extern CCriticalSection cs_vNodes; extern std::map mapRelay; extern std::deque > vRelayExpiration; extern CCriticalSection cs_mapRelay; -extern limitedmap mapAlreadyAskedFor; +extern limitedmap mapAlreadyAskedFor; extern std::vector vAddedNodes; extern CCriticalSection cs_vAddedNodes; From 41dbc4849e0bf14eef98962b0f0bddcde0bb3014 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Sat, 9 Apr 2016 14:30:07 +0100 Subject: [PATCH 0137/1802] Removed call to `TryCreateDirectory` from `GetDefaultDataDir` in `src/util.cpp`. See https://github.com/bitcoin/bitcoin/issues/7845#issuecomment-207684728. Also refactored `GetDefaultDataDir` function to return path for Mac in one expression. --- src/util.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/util.cpp b/src/util.cpp index 59f58f2c5534f..00b75fbdbe38e 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -471,9 +471,7 @@ boost::filesystem::path GetDefaultDataDir() pathRet = fs::path(pszHome); #ifdef MAC_OSX // Mac - pathRet /= "Library/Application Support"; - TryCreateDirectory(pathRet); - return pathRet / "Bitcoin"; + return pathRet / "Library/Application Support/Bitcoin"; #else // Unix return pathRet / ".bitcoin"; From 85c807c9ead3215021503348e75851900dfa08db Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 12 Apr 2016 15:44:18 +0930 Subject: [PATCH 0138/1802] getblockchaininfo: make bip9_softforks an object, not an array. We can't change "softforks", but it seems far more logical to use tags in an object rather than using an "id" field in an array. For example, to get the csv status before, you need to iterate the array to find the entry with 'id' field equal to "csv": jq '.bip9_softforks | map(select(.id == "csv"))[] | .status' Now: jq '.bip9_softforks.csv.status' There is no issue with fork names being incompatible with JSON tags, since we're selecting them ourselves. Signed-off-by: Rusty Russell --- qa/rpc-tests/bip9-softforks.py | 6 +----- qa/rpc-tests/test_framework/util.py | 5 +---- src/rpc/blockchain.cpp | 14 ++++++-------- 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/qa/rpc-tests/bip9-softforks.py b/qa/rpc-tests/bip9-softforks.py index 98975e719335c..e63343d35232e 100755 --- a/qa/rpc-tests/bip9-softforks.py +++ b/qa/rpc-tests/bip9-softforks.py @@ -79,11 +79,7 @@ def generate_blocks(self, number, version, test_blocks = []): def get_bip9_status(self, key): info = self.nodes[0].getblockchaininfo() - for row in info['bip9_softforks']: - if row['id'] == key: - return row - raise IndexError ('key:"%s" not found' % key) - + return info['bip9_softforks'][key] def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignature): # generate some coins for later diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index d9fe0f75f2608..acb7f8a6b49df 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -548,7 +548,4 @@ def create_lots_of_big_transactions(node, txouts, utxos, fee): def get_bip9_status(node, key): info = node.getblockchaininfo() - for row in info['bip9_softforks']: - if row['id'] == key: - return row - raise IndexError ('key:"%s" not found' % key) + return info['bip9_softforks'][key] diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 34637b9f7e398..7a01a10b7d629 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -608,10 +608,9 @@ static UniValue SoftForkDesc(const std::string &name, int version, CBlockIndex* return rv; } -static UniValue BIP9SoftForkDesc(const std::string& name, const Consensus::Params& consensusParams, Consensus::DeploymentPos id) +static UniValue BIP9SoftForkDesc(const Consensus::Params& consensusParams, Consensus::DeploymentPos id) { UniValue rv(UniValue::VOBJ); - rv.push_back(Pair("id", name)); const ThresholdState thresholdState = VersionBitsTipState(consensusParams, id); switch (thresholdState) { case THRESHOLD_DEFINED: rv.push_back(Pair("status", "defined")); break; @@ -660,15 +659,14 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) " \"reject\": { ... } (object) progress toward rejecting pre-softfork blocks (same fields as \"enforce\")\n" " }, ...\n" " ],\n" - " \"bip9_softforks\": [ (array) status of BIP9 softforks in progress\n" - " {\n" - " \"id\": \"xxxx\", (string) name of the softfork\n" + " \"bip9_softforks\": { (object) status of BIP9 softforks in progress\n" + " \"xxxx\" : { (string) name of the softfork\n" " \"status\": \"xxxx\", (string) one of \"defined\", \"started\", \"lockedin\", \"active\", \"failed\"\n" " \"bit\": xx, (numeric) the bit, 0-28, in the block version field used to signal this soft fork\n" " \"startTime\": xx, (numeric) the minimum median time past of a block at which the bit gains its meaning\n" " \"timeout\": xx (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in\n" " }\n" - " ]\n" + " }\n" "}\n" "\nExamples:\n" + HelpExampleCli("getblockchaininfo", "") @@ -691,11 +689,11 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) const Consensus::Params& consensusParams = Params().GetConsensus(); CBlockIndex* tip = chainActive.Tip(); UniValue softforks(UniValue::VARR); - UniValue bip9_softforks(UniValue::VARR); + UniValue bip9_softforks(UniValue::VOBJ); softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams)); softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams)); softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams)); - bip9_softforks.push_back(BIP9SoftForkDesc("csv", consensusParams, Consensus::DEPLOYMENT_CSV)); + bip9_softforks.push_back(Pair("csv", BIP9SoftForkDesc(consensusParams, Consensus::DEPLOYMENT_CSV))); obj.push_back(Pair("softforks", softforks)); obj.push_back(Pair("bip9_softforks", bip9_softforks)); From d12760b16ac30734b5e3b047df8aaf6564e927db Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 13 Apr 2016 16:54:07 +0930 Subject: [PATCH 0139/1802] rpc-tests: handle KeyError nicely in test_framework.py btcdrak wrote this for me. Signed-off-by: Rusty Russell --- qa/rpc-tests/test_framework/test_framework.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/qa/rpc-tests/test_framework/test_framework.py b/qa/rpc-tests/test_framework/test_framework.py index 19ee4726093de..3b08cd1384d4e 100755 --- a/qa/rpc-tests/test_framework/test_framework.py +++ b/qa/rpc-tests/test_framework/test_framework.py @@ -142,6 +142,9 @@ def main(self): except AssertionError as e: print("Assertion failed: "+ str(e)) traceback.print_tb(sys.exc_info()[2]) + except KeyError as e: + print("key not found: "+ str(e)) + traceback.print_tb(sys.exc_info()[2]) except Exception as e: print("Unexpected exception caught during testing: "+str(e)) traceback.print_tb(sys.exc_info()[2]) From c6cb6f7d4c4bbfe96256c66b3aef4e7e3ff6285f Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Wed, 13 Apr 2016 16:02:46 -0400 Subject: [PATCH 0140/1802] Avoid unnecessary database access for unknown transactions --- src/main.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 9b164c799915c..f5baf355956fe 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4344,10 +4344,12 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main) recentRejects->reset(); } + // Use pcoinsTip->HaveCoinsInCache as a quick approximation to exclude + // requesting or processing some txs which have already been included in a block return recentRejects->contains(inv.hash) || mempool.exists(inv.hash) || mapOrphanTransactions.count(inv.hash) || - pcoinsTip->HaveCoins(inv.hash); + pcoinsTip->HaveCoinsInCache(inv.hash); } case MSG_BLOCK: return mapBlockIndex.count(inv.hash); From 38c310299cfef419d42744362b90c1700b598953 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 14 Apr 2016 16:04:50 +0200 Subject: [PATCH 0141/1802] Change mapRelay to store CTransactions --- src/main.cpp | 7 ++----- src/net.cpp | 17 ++++------------- src/net.h | 5 ++--- 3 files changed, 8 insertions(+), 21 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index fff1cc346e014..f84fb8dd56550 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4456,7 +4456,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam bool pushed = false; { LOCK(cs_mapRelay); - map::iterator mi = mapRelay.find(inv); + map::iterator mi = mapRelay.find(inv.hash); if (mi != mapRelay.end()) { pfrom->PushMessage(inv.GetCommand(), (*mi).second); pushed = true; @@ -4465,10 +4465,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam if (!pushed && inv.type == MSG_TX) { CTransaction tx; if (mempool.lookup(inv.hash, tx)) { - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss.reserve(1000); - ss << tx; - pfrom->PushMessage(NetMsgType::TX, ss); + pfrom->PushMessage(NetMsgType::TX, tx); pushed = true; } } diff --git a/src/net.cpp b/src/net.cpp index 3bf8c165dc911..e64cb4ef90207 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -90,8 +90,8 @@ std::string strSubVersion; vector vNodes; CCriticalSection cs_vNodes; -map mapRelay; -deque > vRelayExpiration; +map mapRelay; +deque > vRelayExpiration; CCriticalSection cs_mapRelay; limitedmap mapAlreadyAskedFor(MAX_INV_SZ); @@ -2054,14 +2054,6 @@ instance_of_cnetcleanup; void RelayTransaction(const CTransaction& tx, CFeeRate feerate) -{ - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss.reserve(10000); - ss << tx; - RelayTransaction(tx, feerate, ss); -} - -void RelayTransaction(const CTransaction& tx, CFeeRate feerate, const CDataStream& ss) { CInv inv(MSG_TX, tx.GetHash()); { @@ -2073,9 +2065,8 @@ void RelayTransaction(const CTransaction& tx, CFeeRate feerate, const CDataStrea vRelayExpiration.pop_front(); } - // Save original serialized message so newer versions are preserved - mapRelay.insert(std::make_pair(inv, ss)); - vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv)); + mapRelay.insert(std::make_pair(inv.hash, tx)); + vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv.hash)); } LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) diff --git a/src/net.h b/src/net.h index 1892c963fcee2..7f905002a6254 100644 --- a/src/net.h +++ b/src/net.h @@ -161,8 +161,8 @@ extern int nMaxConnections; extern std::vector vNodes; extern CCriticalSection cs_vNodes; -extern std::map mapRelay; -extern std::deque > vRelayExpiration; +extern std::map mapRelay; +extern std::deque > vRelayExpiration; extern CCriticalSection cs_mapRelay; extern limitedmap mapAlreadyAskedFor; @@ -773,7 +773,6 @@ class CNode class CTransaction; void RelayTransaction(const CTransaction& tx, CFeeRate feerate); -void RelayTransaction(const CTransaction& tx, CFeeRate feerate, const CDataStream& ss); /** Access to the (IP) address database (peers.dat) */ class CAddrDB From fa7abe0a00464e6aa88d55c63dba40878bbe5b79 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 14 Apr 2016 19:39:49 +0200 Subject: [PATCH 0142/1802] [test] bctest.py: Revert faa41ee --- src/test/bctest.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/test/bctest.py b/src/test/bctest.py index fc59152ba12f1..8105b87ffa34c 100644 --- a/src/test/bctest.py +++ b/src/test/bctest.py @@ -2,7 +2,6 @@ # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. from __future__ import division,print_function,unicode_literals -from io import open import subprocess import os import json @@ -17,7 +16,7 @@ def bctest(testDir, testObj, exeext): inputData = None if "input" in testObj: filename = testDir + "/" + testObj['input'] - inputData = open(filename, 'rb').read() + inputData = open(filename).read() stdinCfg = subprocess.PIPE outputFn = None From 90604f16af63ec066d6561337f476ccd8acec326 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Mon, 1 Jun 2015 16:35:19 +0200 Subject: [PATCH 0143/1802] add bip32 pubkey serialization CExtPubKey should be serializable like CPubKey --- src/base58.h | 4 ++-- src/key.cpp | 6 +++--- src/key.h | 21 +++++++++++++++++++-- src/pubkey.cpp | 6 +++--- src/pubkey.h | 30 ++++++++++++++++++++++++++++-- src/test/bip32_tests.cpp | 16 ++++++++++++++++ 6 files changed, 71 insertions(+), 12 deletions(-) diff --git a/src/base58.h b/src/base58.h index a3980118aae34..cccebc9e0e753 100644 --- a/src/base58.h +++ b/src/base58.h @@ -164,7 +164,7 @@ template class CBitcoinExtK CBitcoinExtKeyBase() {} }; -typedef CBitcoinExtKeyBase CBitcoinExtKey; -typedef CBitcoinExtKeyBase CBitcoinExtPubKey; +typedef CBitcoinExtKeyBase CBitcoinExtKey; +typedef CBitcoinExtKeyBase CBitcoinExtPubKey; #endif // BITCOIN_BASE58_H diff --git a/src/key.cpp b/src/key.cpp index 28ba5144e4314..6a3d9aa140906 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -275,7 +275,7 @@ CExtPubKey CExtKey::Neuter() const { return ret; } -void CExtKey::Encode(unsigned char code[74]) const { +void CExtKey::Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const { code[0] = nDepth; memcpy(code+1, vchFingerprint, 4); code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF; @@ -286,12 +286,12 @@ void CExtKey::Encode(unsigned char code[74]) const { memcpy(code+42, key.begin(), 32); } -void CExtKey::Decode(const unsigned char code[74]) { +void CExtKey::Decode(const unsigned char code[BIP32_EXTKEY_SIZE]) { nDepth = code[0]; memcpy(vchFingerprint, code+1, 4); nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8]; memcpy(chaincode.begin(), code+9, 32); - key.Set(code+42, code+74, true); + key.Set(code+42, code+BIP32_EXTKEY_SIZE, true); } bool ECC_InitSanityCheck() { diff --git a/src/key.h b/src/key.h index 6c820d49cd5fc..b4f48d59f5b08 100644 --- a/src/key.h +++ b/src/key.h @@ -164,11 +164,28 @@ struct CExtKey { a.chaincode == b.chaincode && a.key == b.key; } - void Encode(unsigned char code[74]) const; - void Decode(const unsigned char code[74]); + void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const; + void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]); bool Derive(CExtKey& out, unsigned int nChild) const; CExtPubKey Neuter() const; void SetMaster(const unsigned char* seed, unsigned int nSeedLen); + template + void Serialize(Stream& s, int nType, int nVersion) const + { + unsigned int len = BIP32_EXTKEY_SIZE; + ::WriteCompactSize(s, len); + unsigned char code[BIP32_EXTKEY_SIZE]; + Encode(code); + s.write((const char *)&code[0], len); + } + template + void Unserialize(Stream& s, int nType, int nVersion) + { + unsigned int len = ::ReadCompactSize(s); + unsigned char code[BIP32_EXTKEY_SIZE]; + s.read((char *)&code[0], len); + Decode(code); + } }; /** Initialize the elliptic curve support. May not be called twice without calling ECC_Stop first. */ diff --git a/src/pubkey.cpp b/src/pubkey.cpp index db06a8928567f..be4ee27cd48d5 100644 --- a/src/pubkey.cpp +++ b/src/pubkey.cpp @@ -246,7 +246,7 @@ bool CPubKey::Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChi return true; } -void CExtPubKey::Encode(unsigned char code[74]) const { +void CExtPubKey::Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const { code[0] = nDepth; memcpy(code+1, vchFingerprint, 4); code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF; @@ -256,12 +256,12 @@ void CExtPubKey::Encode(unsigned char code[74]) const { memcpy(code+41, pubkey.begin(), 33); } -void CExtPubKey::Decode(const unsigned char code[74]) { +void CExtPubKey::Decode(const unsigned char code[BIP32_EXTKEY_SIZE]) { nDepth = code[0]; memcpy(vchFingerprint, code+1, 4); nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8]; memcpy(chaincode.begin(), code+9, 32); - pubkey.Set(code+41, code+74); + pubkey.Set(code+41, code+BIP32_EXTKEY_SIZE); } bool CExtPubKey::Derive(CExtPubKey &out, unsigned int nChild) const { diff --git a/src/pubkey.h b/src/pubkey.h index e1a17b658261b..db5444ea9d745 100644 --- a/src/pubkey.h +++ b/src/pubkey.h @@ -23,6 +23,8 @@ * script supports up to 75 for single byte push */ +const unsigned int BIP32_EXTKEY_SIZE = 74; + /** A reference to a CKey: the Hash160 of its serialized public key */ class CKeyID : public uint160 { @@ -205,9 +207,33 @@ struct CExtPubKey { a.chaincode == b.chaincode && a.pubkey == b.pubkey; } - void Encode(unsigned char code[74]) const; - void Decode(const unsigned char code[74]); + void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const; + void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]); bool Derive(CExtPubKey& out, unsigned int nChild) const; + + unsigned int GetSerializeSize(int nType, int nVersion) const + { + return BIP32_EXTKEY_SIZE+1; //add one byte for the size (compact int) + } + template + void Serialize(Stream& s, int nType, int nVersion) const + { + unsigned int len = BIP32_EXTKEY_SIZE; + ::WriteCompactSize(s, len); + unsigned char code[BIP32_EXTKEY_SIZE]; + Encode(code); + s.write((const char *)&code[0], len); + } + template + void Unserialize(Stream& s, int nType, int nVersion) + { + unsigned int len = ::ReadCompactSize(s); + unsigned char code[BIP32_EXTKEY_SIZE]; + if (len != BIP32_EXTKEY_SIZE) + throw std::runtime_error("Invalid extended key size\n"); + s.read((char *)&code[0], len); + Decode(code); + } }; /** Users of this module must hold an ECCVerifyHandle. The constructor and diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp index ce29e692db2bd..7f1c2a32dd121 100644 --- a/src/test/bip32_tests.cpp +++ b/src/test/bip32_tests.cpp @@ -117,6 +117,22 @@ void RunTest(const TestVector &test) { } key = keyNew; pubkey = pubkeyNew; + + CDataStream ssPub(SER_DISK, CLIENT_VERSION); + ssPub << pubkeyNew; + BOOST_CHECK(ssPub.size() == 75); + + CDataStream ssPriv(SER_DISK, CLIENT_VERSION); + ssPriv << keyNew; + BOOST_CHECK(ssPriv.size() == 75); + + CExtPubKey pubCheck; + CExtKey privCheck; + ssPub >> pubCheck; + ssPriv >> privCheck; + + BOOST_CHECK(pubCheck == pubkeyNew); + BOOST_CHECK(privCheck == keyNew); } } From fa939366910ee11e9c307d0d57eb21cdec8a362b Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 13 Apr 2016 12:10:04 +0200 Subject: [PATCH 0144/1802] [gitian] Add marcofalke-key.pgp --- contrib/gitian-downloader/marcofalke-key.pgp | 69 ++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 contrib/gitian-downloader/marcofalke-key.pgp diff --git a/contrib/gitian-downloader/marcofalke-key.pgp b/contrib/gitian-downloader/marcofalke-key.pgp new file mode 100644 index 0000000000000..ee626500a4824 --- /dev/null +++ b/contrib/gitian-downloader/marcofalke-key.pgp @@ -0,0 +1,69 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1 + +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 +=GC3s +-----END PGP PUBLIC KEY BLOCK----- From faf4c837fba119437ddbb36d6a799dc5fd79db37 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 13 Apr 2016 12:34:32 +0200 Subject: [PATCH 0145/1802] [gitian] Move keys to contrib/gitian-keys --- contrib/README.md | 6 +++--- .../achow101-key.pgp | 0 .../aschildbach-key.pgp | Bin .../bluematt-key.pgp | Bin .../btcdrak-key.pgp | 0 .../cdecker-key.pgp | Bin .../centaur1-key.pgp | 0 .../cfields-key.pgp | 0 .../devrandom-key.pgp | Bin .../{gitian-downloader => gitian-keys}/erkmos.pgp | Bin .../fanquake-key.pgp | 0 .../gavinandresen-key.pgp | Bin .../jl2012-key.pgp | 0 .../jonasschnelli-key.pgp | 0 .../laanwj-key.pgp | 0 .../luke-jr-key.pgp | Bin .../marcofalke-key.pgp | 0 .../michagogo-key.pgp | 0 .../petertodd-key.pgp | 0 .../{gitian-downloader => gitian-keys}/prab-key.pgp | 0 .../{gitian-downloader => gitian-keys}/sipa-key.pgp | Bin .../tcatm-key.pgp | Bin .../wtogami-key.pgp | 0 doc/release-process.md | 2 +- 24 files changed, 4 insertions(+), 4 deletions(-) rename contrib/{gitian-downloader => gitian-keys}/achow101-key.pgp (100%) rename contrib/{gitian-downloader => gitian-keys}/aschildbach-key.pgp (100%) rename contrib/{gitian-downloader => gitian-keys}/bluematt-key.pgp (100%) rename contrib/{gitian-downloader => gitian-keys}/btcdrak-key.pgp (100%) rename contrib/{gitian-downloader => gitian-keys}/cdecker-key.pgp (100%) rename contrib/{gitian-downloader => gitian-keys}/centaur1-key.pgp (100%) rename contrib/{gitian-downloader => gitian-keys}/cfields-key.pgp (100%) rename contrib/{gitian-downloader => gitian-keys}/devrandom-key.pgp (100%) rename contrib/{gitian-downloader => gitian-keys}/erkmos.pgp (100%) rename contrib/{gitian-downloader => gitian-keys}/fanquake-key.pgp (100%) rename contrib/{gitian-downloader => gitian-keys}/gavinandresen-key.pgp (100%) rename contrib/{gitian-downloader => gitian-keys}/jl2012-key.pgp (100%) rename contrib/{gitian-downloader => gitian-keys}/jonasschnelli-key.pgp (100%) rename contrib/{gitian-downloader => gitian-keys}/laanwj-key.pgp (100%) rename contrib/{gitian-downloader => gitian-keys}/luke-jr-key.pgp (100%) rename contrib/{gitian-downloader => gitian-keys}/marcofalke-key.pgp (100%) rename contrib/{gitian-downloader => gitian-keys}/michagogo-key.pgp (100%) rename contrib/{gitian-downloader => gitian-keys}/petertodd-key.pgp (100%) rename contrib/{gitian-downloader => gitian-keys}/prab-key.pgp (100%) rename contrib/{gitian-downloader => gitian-keys}/sipa-key.pgp (100%) rename contrib/{gitian-downloader => gitian-keys}/tcatm-key.pgp (100%) rename contrib/{gitian-downloader => gitian-keys}/wtogami-key.pgp (100%) diff --git a/contrib/README.md b/contrib/README.md index 9461539166ff9..32b3a170ac7ec 100644 --- a/contrib/README.md +++ b/contrib/README.md @@ -34,10 +34,10 @@ Contains files used to package bitcoind/bitcoin-qt for Debian-based Linux systems. If you compile bitcoind/bitcoin-qt yourself, there are some useful files here. ### [Gitian-descriptors](/contrib/gitian-descriptors) ### -Gavin's notes on getting gitian builds up and running using KVM. +Notes on getting Gitian builds up and running using KVM. -### [Gitian-downloader](/contrib/gitian-downloader) -Various PGP files of core developers. +### [Gitian-keys](/contrib/gitian-keys) +PGP keys used for signing Bitcoin Core [Gitian release](/doc/release-process.md) results. ### [MacDeploy](/contrib/macdeploy) ### Scripts and notes for Mac builds. diff --git a/contrib/gitian-downloader/achow101-key.pgp b/contrib/gitian-keys/achow101-key.pgp similarity index 100% rename from contrib/gitian-downloader/achow101-key.pgp rename to contrib/gitian-keys/achow101-key.pgp diff --git a/contrib/gitian-downloader/aschildbach-key.pgp b/contrib/gitian-keys/aschildbach-key.pgp similarity index 100% rename from contrib/gitian-downloader/aschildbach-key.pgp rename to contrib/gitian-keys/aschildbach-key.pgp diff --git a/contrib/gitian-downloader/bluematt-key.pgp b/contrib/gitian-keys/bluematt-key.pgp similarity index 100% rename from contrib/gitian-downloader/bluematt-key.pgp rename to contrib/gitian-keys/bluematt-key.pgp diff --git a/contrib/gitian-downloader/btcdrak-key.pgp b/contrib/gitian-keys/btcdrak-key.pgp similarity index 100% rename from contrib/gitian-downloader/btcdrak-key.pgp rename to contrib/gitian-keys/btcdrak-key.pgp diff --git a/contrib/gitian-downloader/cdecker-key.pgp b/contrib/gitian-keys/cdecker-key.pgp similarity index 100% rename from contrib/gitian-downloader/cdecker-key.pgp rename to contrib/gitian-keys/cdecker-key.pgp diff --git a/contrib/gitian-downloader/centaur1-key.pgp b/contrib/gitian-keys/centaur1-key.pgp similarity index 100% rename from contrib/gitian-downloader/centaur1-key.pgp rename to contrib/gitian-keys/centaur1-key.pgp diff --git a/contrib/gitian-downloader/cfields-key.pgp b/contrib/gitian-keys/cfields-key.pgp similarity index 100% rename from contrib/gitian-downloader/cfields-key.pgp rename to contrib/gitian-keys/cfields-key.pgp diff --git a/contrib/gitian-downloader/devrandom-key.pgp b/contrib/gitian-keys/devrandom-key.pgp similarity index 100% rename from contrib/gitian-downloader/devrandom-key.pgp rename to contrib/gitian-keys/devrandom-key.pgp diff --git a/contrib/gitian-downloader/erkmos.pgp b/contrib/gitian-keys/erkmos.pgp similarity index 100% rename from contrib/gitian-downloader/erkmos.pgp rename to contrib/gitian-keys/erkmos.pgp diff --git a/contrib/gitian-downloader/fanquake-key.pgp b/contrib/gitian-keys/fanquake-key.pgp similarity index 100% rename from contrib/gitian-downloader/fanquake-key.pgp rename to contrib/gitian-keys/fanquake-key.pgp diff --git a/contrib/gitian-downloader/gavinandresen-key.pgp b/contrib/gitian-keys/gavinandresen-key.pgp similarity index 100% rename from contrib/gitian-downloader/gavinandresen-key.pgp rename to contrib/gitian-keys/gavinandresen-key.pgp diff --git a/contrib/gitian-downloader/jl2012-key.pgp b/contrib/gitian-keys/jl2012-key.pgp similarity index 100% rename from contrib/gitian-downloader/jl2012-key.pgp rename to contrib/gitian-keys/jl2012-key.pgp diff --git a/contrib/gitian-downloader/jonasschnelli-key.pgp b/contrib/gitian-keys/jonasschnelli-key.pgp similarity index 100% rename from contrib/gitian-downloader/jonasschnelli-key.pgp rename to contrib/gitian-keys/jonasschnelli-key.pgp diff --git a/contrib/gitian-downloader/laanwj-key.pgp b/contrib/gitian-keys/laanwj-key.pgp similarity index 100% rename from contrib/gitian-downloader/laanwj-key.pgp rename to contrib/gitian-keys/laanwj-key.pgp diff --git a/contrib/gitian-downloader/luke-jr-key.pgp b/contrib/gitian-keys/luke-jr-key.pgp similarity index 100% rename from contrib/gitian-downloader/luke-jr-key.pgp rename to contrib/gitian-keys/luke-jr-key.pgp diff --git a/contrib/gitian-downloader/marcofalke-key.pgp b/contrib/gitian-keys/marcofalke-key.pgp similarity index 100% rename from contrib/gitian-downloader/marcofalke-key.pgp rename to contrib/gitian-keys/marcofalke-key.pgp diff --git a/contrib/gitian-downloader/michagogo-key.pgp b/contrib/gitian-keys/michagogo-key.pgp similarity index 100% rename from contrib/gitian-downloader/michagogo-key.pgp rename to contrib/gitian-keys/michagogo-key.pgp diff --git a/contrib/gitian-downloader/petertodd-key.pgp b/contrib/gitian-keys/petertodd-key.pgp similarity index 100% rename from contrib/gitian-downloader/petertodd-key.pgp rename to contrib/gitian-keys/petertodd-key.pgp diff --git a/contrib/gitian-downloader/prab-key.pgp b/contrib/gitian-keys/prab-key.pgp similarity index 100% rename from contrib/gitian-downloader/prab-key.pgp rename to contrib/gitian-keys/prab-key.pgp diff --git a/contrib/gitian-downloader/sipa-key.pgp b/contrib/gitian-keys/sipa-key.pgp similarity index 100% rename from contrib/gitian-downloader/sipa-key.pgp rename to contrib/gitian-keys/sipa-key.pgp diff --git a/contrib/gitian-downloader/tcatm-key.pgp b/contrib/gitian-keys/tcatm-key.pgp similarity index 100% rename from contrib/gitian-downloader/tcatm-key.pgp rename to contrib/gitian-keys/tcatm-key.pgp diff --git a/contrib/gitian-downloader/wtogami-key.pgp b/contrib/gitian-keys/wtogami-key.pgp similarity index 100% rename from contrib/gitian-downloader/wtogami-key.pgp rename to contrib/gitian-keys/wtogami-key.pgp diff --git a/doc/release-process.md b/doc/release-process.md index 2c83896c22216..5a6ac8482b674 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -115,7 +115,7 @@ The gbuild invocations below DO NOT DO THIS by default. Add other gitian builders keys to your gpg keyring - gpg --import ../bitcoin/contrib/gitian-downloader/*.pgp + gpg --import ../bitcoin/contrib/gitian-keys/*.pgp Verify the signatures From de821d56e1f458fbe580520c77ac066107f4d77c Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 29 Mar 2016 11:34:25 +0200 Subject: [PATCH 0146/1802] [ZMQ] refactor message string --- src/zmq/zmqpublishnotifier.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/zmq/zmqpublishnotifier.cpp b/src/zmq/zmqpublishnotifier.cpp index f5839620ff227..a9ce9c48c4b55 100644 --- a/src/zmq/zmqpublishnotifier.cpp +++ b/src/zmq/zmqpublishnotifier.cpp @@ -9,6 +9,11 @@ static std::multimap mapPublishNotifiers; +static const char *MSG_HASHBLOCK = "hashblock"; +static const char *MSG_HASHTX = "hashtx"; +static const char *MSG_RAWBLOCK = "rawblock"; +static const char *MSG_RAWTX = "rawtx"; + // Internal function to send multipart message static int zmq_send_multipart(void *sock, const void* data, size_t size, ...) { @@ -125,7 +130,7 @@ bool CZMQPublishHashBlockNotifier::NotifyBlock(const CBlockIndex *pindex) char data[32]; for (unsigned int i = 0; i < 32; i++) data[31 - i] = hash.begin()[i]; - int rc = zmq_send_multipart(psocket, "hashblock", 9, data, 32, 0); + int rc = zmq_send_multipart(psocket, MSG_HASHBLOCK, 9, data, 32, 0); return rc == 0; } @@ -136,7 +141,7 @@ bool CZMQPublishHashTransactionNotifier::NotifyTransaction(const CTransaction &t char data[32]; for (unsigned int i = 0; i < 32; i++) data[31 - i] = hash.begin()[i]; - int rc = zmq_send_multipart(psocket, "hashtx", 6, data, 32, 0); + int rc = zmq_send_multipart(psocket, MSG_HASHTX, 6, data, 32, 0); return rc == 0; } @@ -158,7 +163,7 @@ bool CZMQPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex) ss << block; } - int rc = zmq_send_multipart(psocket, "rawblock", 8, &(*ss.begin()), ss.size(), 0); + int rc = zmq_send_multipart(psocket, MSG_RAWBLOCK, 8, &(*ss.begin()), ss.size(), 0); return rc == 0; } @@ -168,6 +173,6 @@ bool CZMQPublishRawTransactionNotifier::NotifyTransaction(const CTransaction &tr LogPrint("zmq", "zmq: Publish rawtx %s\n", hash.GetHex()); CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss << transaction; - int rc = zmq_send_multipart(psocket, "rawtx", 5, &(*ss.begin()), ss.size(), 0); + int rc = zmq_send_multipart(psocket, MSG_RAWTX, 5, &(*ss.begin()), ss.size(), 0); return rc == 0; } From 41e835dd50d358c127bab17a1f2872471dbdfe9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Wed, 30 Mar 2016 00:59:29 +0100 Subject: [PATCH 0147/1802] Add strict flag to RPCTypeCheckObj Strict flag forces type check on all object keys. --- src/rpc/server.cpp | 15 ++++++++++++++- src/rpc/server.h | 2 +- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 8326fe14d2150..d06a9142b6819 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -89,7 +89,8 @@ void RPCTypeCheck(const UniValue& params, void RPCTypeCheckObj(const UniValue& o, const map& typesExpected, - bool fAllowNull) + bool fAllowNull, + bool fStrict) { BOOST_FOREACH(const PAIRTYPE(string, UniValue::VType)& t, typesExpected) { @@ -104,6 +105,18 @@ void RPCTypeCheckObj(const UniValue& o, throw JSONRPCError(RPC_TYPE_ERROR, err); } } + + if (fStrict) + { + BOOST_FOREACH(const string& k, o.getKeys()) + { + if (typesExpected.count(k) == 0) + { + string err = strprintf("Unexpected key %s", k); + throw JSONRPCError(RPC_TYPE_ERROR, err); + } + } + } } CAmount AmountFromValue(const UniValue& value) diff --git a/src/rpc/server.h b/src/rpc/server.h index a7ed710ce60ad..b4713366172ae 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -70,7 +70,7 @@ void RPCTypeCheck(const UniValue& params, Use like: RPCTypeCheckObj(object, boost::assign::map_list_of("name", str_type)("value", int_type)); */ void RPCTypeCheckObj(const UniValue& o, - const std::map& typesExpected, bool fAllowNull=false); + const std::map& typesExpected, bool fAllowNull=false, bool fStrict=false); /** Opaque base class for timers returned by NewTimerFunc. * This provides no methods at the moment, but makes sure that delete From af4fe7fd126eff2dd1942276ea91c8ab9dd717c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Wed, 30 Mar 2016 02:04:22 +0100 Subject: [PATCH 0148/1802] Add change options to fundrawtransaction --- qa/rpc-tests/fundrawtransaction.py | 80 +++++++++++++++++++++++++++++- src/wallet/rpcwallet.cpp | 58 ++++++++++++++++++---- src/wallet/wallet.cpp | 34 +++++++++---- src/wallet/wallet.h | 5 +- 4 files changed, 153 insertions(+), 24 deletions(-) diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py index 4492ea398f4ba..496c7fe8b0ed0 100755 --- a/qa/rpc-tests/fundrawtransaction.py +++ b/qa/rpc-tests/fundrawtransaction.py @@ -177,6 +177,83 @@ def run_test(self): assert_equal(fee + totalOut, utx['amount']) #compare vin total and totalout+fee + #################################################### + # test a fundrawtransaction with an invalid option # + #################################################### + utx = False + listunspent = self.nodes[2].listunspent() + for aUtx in listunspent: + if aUtx['amount'] == 5.0: + utx = aUtx + break + + assert_equal(utx!=False, True) + + inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ] + outputs = { self.nodes[0].getnewaddress() : Decimal(4.0) } + rawtx = self.nodes[2].createrawtransaction(inputs, outputs) + dec_tx = self.nodes[2].decoderawtransaction(rawtx) + assert_equal(utx['txid'], dec_tx['vin'][0]['txid']) + + try: + self.nodes[2].fundrawtransaction(rawtx, {'foo': 'bar'}) + raise AssertionError("Accepted invalid option foo") + except JSONRPCException,e: + assert("Unexpected key foo" in e.error['message']) + + + ############################################################ + # test a fundrawtransaction with an invalid change address # + ############################################################ + utx = False + listunspent = self.nodes[2].listunspent() + for aUtx in listunspent: + if aUtx['amount'] == 5.0: + utx = aUtx + break + + assert_equal(utx!=False, True) + + inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ] + outputs = { self.nodes[0].getnewaddress() : Decimal(4.0) } + rawtx = self.nodes[2].createrawtransaction(inputs, outputs) + dec_tx = self.nodes[2].decoderawtransaction(rawtx) + assert_equal(utx['txid'], dec_tx['vin'][0]['txid']) + + try: + self.nodes[2].fundrawtransaction(rawtx, {'changeAddress': 'foobar'}) + raise AssertionError("Accepted invalid bitcoin address") + except JSONRPCException,e: + assert("changeAddress must be a valid bitcoin address" in e.error['message']) + + + + ############################################################ + # test a fundrawtransaction with a provided change address # + ############################################################ + utx = False + listunspent = self.nodes[2].listunspent() + for aUtx in listunspent: + if aUtx['amount'] == 5.0: + utx = aUtx + break + + assert_equal(utx!=False, True) + + inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ] + outputs = { self.nodes[0].getnewaddress() : Decimal(4.0) } + rawtx = self.nodes[2].createrawtransaction(inputs, outputs) + dec_tx = self.nodes[2].decoderawtransaction(rawtx) + assert_equal(utx['txid'], dec_tx['vin'][0]['txid']) + + change = self.nodes[2].getnewaddress() + rawtxfund = self.nodes[2].fundrawtransaction(rawtx, {'changeAddress': change, 'changePosition': 0}) + dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) + out = dec_tx['vout'][0]; + assert_equal(change, out['scriptPubKey']['addresses'][0]) + + + ######################################################################### # test a fundrawtransaction with a VIN smaller than the required amount # ######################################################################### @@ -568,7 +645,7 @@ def run_test(self): outputs = {self.nodes[2].getnewaddress() : watchonly_amount / 2} rawtx = self.nodes[3].createrawtransaction(inputs, outputs) - result = self.nodes[3].fundrawtransaction(rawtx, True) + result = self.nodes[3].fundrawtransaction(rawtx, {'includeWatching': True }) res_dec = self.nodes[0].decoderawtransaction(result["hex"]) assert_equal(len(res_dec["vin"]), 1) assert_equal(res_dec["vin"][0]["txid"], watchonly_txid) @@ -584,6 +661,7 @@ def run_test(self): outputs = {self.nodes[2].getnewaddress() : watchonly_amount} rawtx = self.nodes[3].createrawtransaction(inputs, outputs) + # Backward compatibility test (2nd param is includeWatching) result = self.nodes[3].fundrawtransaction(rawtx, True) res_dec = self.nodes[0].decoderawtransaction(result["hex"]) assert_equal(len(res_dec["vin"]), 2) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 5511e9d3aba41..5cd57fc385114 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2437,7 +2437,7 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( - "fundrawtransaction \"hexstring\" includeWatching\n" + "fundrawtransaction \"hexstring\" ( options )\n" "\nAdd inputs to a transaction until it has enough in value to meet its out value.\n" "This will not modify existing inputs, and will add one change output to the outputs.\n" "Note that inputs which were signed may need to be resigned after completion since in/outputs have been added.\n" @@ -2447,8 +2447,14 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) "in the wallet using importaddress or addmultisigaddress (to calculate fees).\n" "Only pay-to-pubkey, multisig, and P2SH versions thereof are currently supported for watch-only\n" "\nArguments:\n" - "1. \"hexstring\" (string, required) The hex string of the raw transaction\n" - "2. includeWatching (boolean, optional, default false) Also select inputs which are watch only\n" + "1. \"hexstring\" (string, required) The hex string of the raw transaction\n" + "2. options (object, optional)\n" + " {\n" + " \"changeAddress\" (string, optional, default pool address) The bitcoin address to receive the change\n" + " \"changePosition\" (numeric, optional, default random) The index of the change output\n" + " \"includeWatching\" (boolean, optional, default false) Also select inputs which are watch only\n" + " }\n" + " for backward compatibility: passing in a true instzead of an object will result in {\"includeWatching\":true}\n" "\nResult:\n" "{\n" " \"hex\": \"value\", (string) The resulting raw transaction (hex-encoded string)\n" @@ -2467,7 +2473,40 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) + HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"") ); - RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VBOOL)); + RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)); + + CTxDestination changeAddress = CNoDestination(); + int changePosition = -1; + bool includeWatching = false; + + if (params.size() > 1) { + if (params[1].type() == UniValue::VBOOL) { + // backward compatibility bool only fallback + includeWatching = params[1].get_bool(); + } + else { + RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VOBJ)); + + UniValue options = params[1]; + + RPCTypeCheckObj(options, boost::assign::map_list_of("changeAddress", UniValue::VSTR)("changePosition", UniValue::VNUM)("includeWatching", UniValue::VBOOL), true, true); + + if (options.exists("changeAddress")) { + CBitcoinAddress address(options["changeAddress"].get_str()); + + if (!address.IsValid()) + throw JSONRPCError(RPC_INVALID_PARAMETER, "changeAddress must be a valid bitcoin address"); + + changeAddress = address.Get(); + } + + if (options.exists("changePosition")) + changePosition = options["changePosition"].get_int(); + + if (options.exists("includeWatching")) + includeWatching = options["includeWatching"].get_bool(); + } + } // parse hex string from parameter CTransaction origTx; @@ -2477,20 +2516,19 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) if (origTx.vout.size() == 0) throw JSONRPCError(RPC_INVALID_PARAMETER, "TX must have at least one output"); - bool includeWatching = false; - if (params.size() > 1) - includeWatching = params[1].get_bool(); + if (changePosition != -1 && (changePosition < 0 || changePosition > origTx.vout.size())) + throw JSONRPCError(RPC_INVALID_PARAMETER, "changePosition out of bounds"); CMutableTransaction tx(origTx); CAmount nFee; string strFailReason; - int nChangePos = -1; - if(!pwalletMain->FundTransaction(tx, nFee, nChangePos, strFailReason, includeWatching)) + + if(!pwalletMain->FundTransaction(tx, nFee, changePosition, strFailReason, includeWatching, changeAddress)) throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason); UniValue result(UniValue::VOBJ); result.push_back(Pair("hex", EncodeHexTx(tx))); - result.push_back(Pair("changepos", nChangePos)); + result.push_back(Pair("changepos", changePosition)); result.push_back(Pair("fee", ValueFromAmount(nFee))); return result; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index e8c946671044c..ee92552168b43 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1932,7 +1932,7 @@ bool CWallet::SelectCoins(const vector& vAvailableCoins, const CAmount& return res; } -bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount &nFeeRet, int& nChangePosRet, std::string& strFailReason, bool includeWatching) +bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, const CTxDestination& destChange) { vector vecSend; @@ -1944,6 +1944,7 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount &nFeeRet, int& nC } CCoinControl coinControl; + coinControl.destChange = destChange; coinControl.fAllowOtherInputs = true; coinControl.fAllowWatchOnly = includeWatching; BOOST_FOREACH(const CTxIn& txin, tx.vin) @@ -1951,11 +1952,11 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount &nFeeRet, int& nC CReserveKey reservekey(this); CWalletTx wtx; - if (!CreateTransaction(vecSend, wtx, reservekey, nFeeRet, nChangePosRet, strFailReason, &coinControl, false)) + if (!CreateTransaction(vecSend, wtx, reservekey, nFeeRet, nChangePosInOut, strFailReason, &coinControl, false)) return false; - if (nChangePosRet != -1) - tx.vout.insert(tx.vout.begin() + nChangePosRet, wtx.vout[nChangePosRet]); + if (nChangePosInOut != -1) + tx.vout.insert(tx.vout.begin() + nChangePosInOut, wtx.vout[nChangePosInOut]); // Add new txins (keeping original txin scriptSig/order) BOOST_FOREACH(const CTxIn& txin, wtx.vin) @@ -1968,9 +1969,10 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount &nFeeRet, int& nC } bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, - int& nChangePosRet, std::string& strFailReason, const CCoinControl* coinControl, bool sign) + int& nChangePosInOut, std::string& strFailReason, const CCoinControl* coinControl, bool sign) { CAmount nValue = 0; + int nChangePosRequest = nChangePosInOut; unsigned int nSubtractFeeFromAmount = 0; BOOST_FOREACH (const CRecipient& recipient, vecSend) { @@ -2036,10 +2038,10 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt // Start with no fee and loop until there is enough fee while (true) { + nChangePosInOut = nChangePosRequest; txNew.vin.clear(); txNew.vout.clear(); wtxNew.fFromMe = true; - nChangePosRet = -1; bool fFirst = true; CAmount nValueToSelect = nValue; @@ -2159,14 +2161,24 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt // add the dust to the fee. if (newTxOut.IsDust(::minRelayTxFee)) { + nChangePosInOut = -1; nFeeRet += nChange; reservekey.ReturnKey(); } else { - // Insert change txn at random position: - nChangePosRet = GetRandInt(txNew.vout.size()+1); - vector::iterator position = txNew.vout.begin()+nChangePosRet; + if (nChangePosInOut == -1) + { + // Insert change txn at random position: + nChangePosInOut = GetRandInt(txNew.vout.size()+1); + } + else if (nChangePosInOut > txNew.vout.size()) + { + strFailReason = _("Change index out of range"); + return false; + } + + vector::iterator position = txNew.vout.begin()+nChangePosInOut; txNew.vout.insert(position, newTxOut); } } @@ -2842,13 +2854,13 @@ void CWallet::GetScriptForMining(boost::shared_ptr &script) script->reserveScript = CScript() << ToByteVector(pubkey) << OP_CHECKSIG; } -void CWallet::LockCoin(COutPoint& output) +void CWallet::LockCoin(const COutPoint& output) { AssertLockHeld(cs_wallet); // setLockedCoins setLockedCoins.insert(output); } -void CWallet::UnlockCoin(COutPoint& output) +void CWallet::UnlockCoin(const COutPoint& output) { AssertLockHeld(cs_wallet); // setLockedCoins setLockedCoins.erase(output); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 96d5d4e1e015b..b0781e917b917 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -739,13 +739,14 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface * Insert additional inputs into the transaction by * calling CreateTransaction(); */ - bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosRet, std::string& strFailReason, bool includeWatching); + bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, const CTxDestination& destChange = CNoDestination()); /** * Create a new transaction paying the recipients with a set of coins * selected by SelectCoins(); Also create the change output, when needed + * @note passing nChangePosInOut as -1 will result in setting a random position */ - bool CreateTransaction(const std::vector& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosRet, + bool CreateTransaction(const std::vector& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, const CCoinControl *coinControl = NULL, bool sign = true); bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey); From f2d0944eb372838e05c666ce9b3df119d7da5594 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Wed, 6 Apr 2016 15:56:14 +0100 Subject: [PATCH 0149/1802] Add lockUnspents option to fundrawtransaction --- src/wallet/rpcwallet.cpp | 9 +++++++-- src/wallet/wallet.cpp | 10 +++++++++- src/wallet/wallet.h | 6 +++--- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 5cd57fc385114..3078cebd486c3 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2453,6 +2453,7 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) " \"changeAddress\" (string, optional, default pool address) The bitcoin address to receive the change\n" " \"changePosition\" (numeric, optional, default random) The index of the change output\n" " \"includeWatching\" (boolean, optional, default false) Also select inputs which are watch only\n" + " \"lockUnspents\" (boolean, optional, default false) Lock selected unspent outputs\n" " }\n" " for backward compatibility: passing in a true instzead of an object will result in {\"includeWatching\":true}\n" "\nResult:\n" @@ -2478,6 +2479,7 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) CTxDestination changeAddress = CNoDestination(); int changePosition = -1; bool includeWatching = false; + bool lockUnspents = false; if (params.size() > 1) { if (params[1].type() == UniValue::VBOOL) { @@ -2489,7 +2491,7 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) UniValue options = params[1]; - RPCTypeCheckObj(options, boost::assign::map_list_of("changeAddress", UniValue::VSTR)("changePosition", UniValue::VNUM)("includeWatching", UniValue::VBOOL), true, true); + RPCTypeCheckObj(options, boost::assign::map_list_of("changeAddress", UniValue::VSTR)("changePosition", UniValue::VNUM)("includeWatching", UniValue::VBOOL)("lockUnspents", UniValue::VBOOL), true, true); if (options.exists("changeAddress")) { CBitcoinAddress address(options["changeAddress"].get_str()); @@ -2505,6 +2507,9 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) if (options.exists("includeWatching")) includeWatching = options["includeWatching"].get_bool(); + + if (options.exists("lockUnspents")) + lockUnspents = options["lockUnspents"].get_bool(); } } @@ -2523,7 +2528,7 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) CAmount nFee; string strFailReason; - if(!pwalletMain->FundTransaction(tx, nFee, changePosition, strFailReason, includeWatching, changeAddress)) + if(!pwalletMain->FundTransaction(tx, nFee, changePosition, strFailReason, includeWatching, lockUnspents, changeAddress)) throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason); UniValue result(UniValue::VOBJ); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index ee92552168b43..8161c659ab369 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1932,7 +1932,7 @@ bool CWallet::SelectCoins(const vector& vAvailableCoins, const CAmount& return res; } -bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, const CTxDestination& destChange) +bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, bool lockUnspents, const CTxDestination& destChange) { vector vecSend; @@ -1962,7 +1962,15 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC BOOST_FOREACH(const CTxIn& txin, wtx.vin) { if (!coinControl.IsSelected(txin.prevout)) + { tx.vin.push_back(txin); + + if (lockUnspents) + { + LOCK2(cs_main, cs_wallet); + LockCoin(txin.prevout); + } + } } return true; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index b0781e917b917..aab4b217caa87 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -667,8 +667,8 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface bool IsSpent(const uint256& hash, unsigned int n) const; bool IsLockedCoin(uint256 hash, unsigned int n) const; - void LockCoin(COutPoint& output); - void UnlockCoin(COutPoint& output); + void LockCoin(const COutPoint& output); + void UnlockCoin(const COutPoint& output); void UnlockAllCoins(); void ListLockedCoins(std::vector& vOutpts); @@ -739,7 +739,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface * Insert additional inputs into the transaction by * calling CreateTransaction(); */ - bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, const CTxDestination& destChange = CNoDestination()); + bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, bool lockUnspents, const CTxDestination& destChange = CNoDestination()); /** * Create a new transaction paying the recipients with a set of coins From 509cb006d514cece5ab7680094f033c8dc8a2318 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 28 Mar 2016 18:18:30 +0200 Subject: [PATCH 0150/1802] txdb: Add Cursor() method to CCoinsView to iterate over UTXO set Add a method Cursor() to CCoinsView that returns a cursor which can be used to iterate over the whole UTXO set. - rpc: Change gettxoutsetinfo to use new Cursor method - txdb: Remove GetStats method - Now that GetStats is implemented in terms of Cursor, remove it. --- src/coins.cpp | 8 +++-- src/coins.h | 33 ++++++++++------- src/rpc/blockchain.cpp | 58 +++++++++++++++++++++++++++++- src/test/coins_tests.cpp | 2 -- src/txdb.cpp | 78 ++++++++++++++++++++-------------------- src/txdb.h | 26 +++++++++++++- 6 files changed, 148 insertions(+), 57 deletions(-) diff --git a/src/coins.cpp b/src/coins.cpp index 877fb8b26c4f6..1c329740b45f6 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -45,7 +45,7 @@ bool CCoinsView::GetCoins(const uint256 &txid, CCoins &coins) const { return fal bool CCoinsView::HaveCoins(const uint256 &txid) const { return false; } uint256 CCoinsView::GetBestBlock() const { return uint256(); } bool CCoinsView::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return false; } -bool CCoinsView::GetStats(CCoinsStats &stats) const { return false; } +CCoinsViewCursor *CCoinsView::Cursor() const { return 0; } CCoinsViewBacked::CCoinsViewBacked(CCoinsView *viewIn) : base(viewIn) { } @@ -54,7 +54,7 @@ bool CCoinsViewBacked::HaveCoins(const uint256 &txid) const { return base->HaveC uint256 CCoinsViewBacked::GetBestBlock() const { return base->GetBestBlock(); } void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; } bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return base->BatchWrite(mapCoins, hashBlock); } -bool CCoinsViewBacked::GetStats(CCoinsStats &stats) const { return base->GetStats(stats); } +CCoinsViewCursor *CCoinsViewBacked::Cursor() const { return base->Cursor(); } CCoinsKeyHasher::CCoinsKeyHasher() : salt(GetRandHash()) {} @@ -300,3 +300,7 @@ CCoinsModifier::~CCoinsModifier() cache.cachedCoinsUsage += it->second.coins.DynamicMemoryUsage(); } } + +CCoinsViewCursor::~CCoinsViewCursor() +{ +} diff --git a/src/coins.h b/src/coins.h index d297cae1aa3c5..d72f8854731eb 100644 --- a/src/coins.h +++ b/src/coins.h @@ -297,19 +297,26 @@ struct CCoinsCacheEntry typedef boost::unordered_map CCoinsMap; -struct CCoinsStats +/** Cursor for iterating over CoinsView state */ +class CCoinsViewCursor { - int nHeight; - uint256 hashBlock; - uint64_t nTransactions; - uint64_t nTransactionOutputs; - uint64_t nSerializedSize; - uint256 hashSerialized; - CAmount nTotalAmount; +public: + CCoinsViewCursor(const uint256 &hashBlockIn): hashBlock(hashBlockIn) {} + virtual ~CCoinsViewCursor(); - CCoinsStats() : nHeight(0), nTransactions(0), nTransactionOutputs(0), nSerializedSize(0), nTotalAmount(0) {} -}; + virtual bool GetKey(uint256 &key) const = 0; + virtual bool GetValue(CCoins &coins) const = 0; + /* Don't care about GetKeySize here */ + virtual unsigned int GetValueSize() const = 0; + virtual bool Valid() const = 0; + virtual void Next() = 0; + + //! Get best block at the time this cursor was created + const uint256 &GetBestBlock() const { return hashBlock; } +private: + uint256 hashBlock; +}; /** Abstract view on the open txout dataset. */ class CCoinsView @@ -329,8 +336,8 @@ class CCoinsView //! The passed mapCoins can be modified. virtual bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock); - //! Calculate statistics about the unspent transaction output set - virtual bool GetStats(CCoinsStats &stats) const; + //! Get a cursor to iterate over the whole state + virtual CCoinsViewCursor *Cursor() const; //! As we use CCoinsViews polymorphically, have a virtual destructor virtual ~CCoinsView() {} @@ -350,7 +357,7 @@ class CCoinsViewBacked : public CCoinsView uint256 GetBestBlock() const; void SetBackend(CCoinsView &viewIn); bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock); - bool GetStats(CCoinsStats &stats) const; + CCoinsViewCursor *Cursor() const; }; diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 34637b9f7e398..8dbfbd5ff8d8b 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -18,11 +18,14 @@ #include "txmempool.h" #include "util.h" #include "utilstrencodings.h" +#include "hash.h" #include #include +#include // boost::thread::interrupt + using namespace std; extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); @@ -432,6 +435,59 @@ UniValue getblock(const UniValue& params, bool fHelp) return blockToJSON(block, pblockindex); } +struct CCoinsStats +{ + int nHeight; + uint256 hashBlock; + uint64_t nTransactions; + uint64_t nTransactionOutputs; + uint64_t nSerializedSize; + uint256 hashSerialized; + CAmount nTotalAmount; + + CCoinsStats() : nHeight(0), nTransactions(0), nTransactionOutputs(0), nSerializedSize(0), nTotalAmount(0) {} +}; + +//! Calculate statistics about the unspent transaction output set +static bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats) +{ + boost::scoped_ptr pcursor(view->Cursor()); + + CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); + stats.hashBlock = pcursor->GetBestBlock(); + { + LOCK(cs_main); + stats.nHeight = mapBlockIndex.find(stats.hashBlock)->second->nHeight; + } + ss << stats.hashBlock; + CAmount nTotalAmount = 0; + while (pcursor->Valid()) { + boost::this_thread::interruption_point(); + uint256 key; + CCoins coins; + if (pcursor->GetKey(key) && pcursor->GetValue(coins)) { + stats.nTransactions++; + for (unsigned int i=0; iGetValueSize(); + ss << VARINT(0); + } else { + return error("%s: unable to read value", __func__); + } + pcursor->Next(); + } + stats.hashSerialized = ss.GetHash(); + stats.nTotalAmount = nTotalAmount; + return true; +} + UniValue gettxoutsetinfo(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 0) @@ -458,7 +514,7 @@ UniValue gettxoutsetinfo(const UniValue& params, bool fHelp) CCoinsStats stats; FlushStateToDisk(); - if (pcoinsTip->GetStats(stats)) { + if (GetUTXOStats(pcoinsTip, stats)) { ret.push_back(Pair("height", (int64_t)stats.nHeight)); ret.push_back(Pair("bestblock", stats.hashBlock.GetHex())); ret.push_back(Pair("transactions", (int64_t)stats.nTransactions)); diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 3fe536f91aec8..48e3c8ed8e07f 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -61,8 +61,6 @@ class CCoinsViewTest : public CCoinsView hashBestBlock_ = hashBlock; return true; } - - bool GetStats(CCoinsStats& stats) const { return false; } }; class CCoinsViewCacheTest : public CCoinsViewCache diff --git a/src/txdb.cpp b/src/txdb.cpp index f99e11f26e3f4..be86cceeb36a7 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -94,50 +94,52 @@ bool CBlockTreeDB::ReadLastBlockFile(int &nFile) { return Read(DB_LAST_BLOCK, nFile); } -bool CCoinsViewDB::GetStats(CCoinsStats &stats) const { +CCoinsViewCursor *CCoinsViewDB::Cursor() const +{ + CCoinsViewDBCursor *i = new CCoinsViewDBCursor(const_cast(&db)->NewIterator(), GetBestBlock()); /* It seems that there are no "const iterators" for LevelDB. Since we only need read operations on it, use a const-cast to get around that restriction. */ - boost::scoped_ptr pcursor(const_cast(&db)->NewIterator()); - pcursor->Seek(DB_COINS); + i->pcursor->Seek(DB_COINS); + // Cache key of first record + i->pcursor->GetKey(i->keyTmp); + return i; +} - CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); - stats.hashBlock = GetBestBlock(); - ss << stats.hashBlock; - CAmount nTotalAmount = 0; - while (pcursor->Valid()) { - boost::this_thread::interruption_point(); - std::pair key; - CCoins coins; - if (pcursor->GetKey(key) && key.first == DB_COINS) { - if (pcursor->GetValue(coins)) { - stats.nTransactions++; - for (unsigned int i=0; iGetValueSize(); - ss << VARINT(0); - } else { - return error("CCoinsViewDB::GetStats() : unable to read value"); - } - } else { - break; - } - pcursor->Next(); +bool CCoinsViewDBCursor::GetKey(uint256 &key) const +{ + // Return cached key + if (keyTmp.first == DB_COINS) { + key = keyTmp.second; + return true; } - { - LOCK(cs_main); - stats.nHeight = mapBlockIndex.find(stats.hashBlock)->second->nHeight; + return false; +} + +bool CCoinsViewDBCursor::GetValue(CCoins &coins) const +{ + return pcursor->GetValue(coins); +} + +unsigned int CCoinsViewDBCursor::GetValueSize() const +{ + return pcursor->GetValueSize(); +} + +bool CCoinsViewDBCursor::Valid() const +{ + return keyTmp.first == DB_COINS; +} + +void CCoinsViewDBCursor::Next() +{ + pcursor->Next(); + if (pcursor->Valid()) { + bool ok = pcursor->GetKey(keyTmp); + assert(ok); // If GetKey fails here something must be wrong with underlying database, we cannot handle that here + } else { + keyTmp.first = 0; // Invalidate cached key after last record so that Valid() and GetKey() return false } - stats.hashSerialized = ss.GetHash(); - stats.nTotalAmount = nTotalAmount; - return true; } bool CBlockTreeDB::WriteBatchSync(const std::vector >& fileInfo, int nLastFile, const std::vector& blockinfo) { diff --git a/src/txdb.h b/src/txdb.h index 22e0c5704cb26..749802f0e5fd0 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -26,6 +26,8 @@ static const int64_t nMaxDbCache = sizeof(void*) > 4 ? 16384 : 1024; //! min. -dbcache in (MiB) static const int64_t nMinDbCache = 4; +class CCoinsViewDBCursor; + /** CCoinsView backed by the coin database (chainstate/) */ class CCoinsViewDB : public CCoinsView { @@ -38,7 +40,29 @@ class CCoinsViewDB : public CCoinsView bool HaveCoins(const uint256 &txid) const; uint256 GetBestBlock() const; bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock); - bool GetStats(CCoinsStats &stats) const; + CCoinsViewCursor *Cursor() const; +}; + +/** Specialization of CCoinsViewCursor to iterate over a CCoinsViewDB */ +class CCoinsViewDBCursor: public CCoinsViewCursor +{ +public: + ~CCoinsViewDBCursor() {} + + bool GetKey(uint256 &key) const; + bool GetValue(CCoins &coins) const; + unsigned int GetValueSize() const; + + bool Valid() const; + void Next(); + +private: + CCoinsViewDBCursor(CDBIterator* pcursorIn, const uint256 &hashBlockIn): + CCoinsViewCursor(hashBlockIn), pcursor(pcursorIn) {} + boost::scoped_ptr pcursor; + std::pair keyTmp; + + friend class CCoinsViewDB; }; /** Access to the block database (blocks/index/) */ From 9ad1a518574b9afed3e66a1e1658ead1d3d7ce54 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sat, 9 Apr 2016 07:39:35 +0200 Subject: [PATCH 0151/1802] crypto: bytes counts are 64 bit Byte counts for SHA256, SHA512, SHA1 and RIPEMD160 must be 64 bits. `size_t` has a different size per platform, causing divergent results when hashing more than 4GB of data. --- src/crypto/ripemd160.h | 2 +- src/crypto/sha1.h | 2 +- src/crypto/sha256.h | 2 +- src/crypto/sha512.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/crypto/ripemd160.h b/src/crypto/ripemd160.h index 687204fdae8b6..bd41f02508404 100644 --- a/src/crypto/ripemd160.h +++ b/src/crypto/ripemd160.h @@ -14,7 +14,7 @@ class CRIPEMD160 private: uint32_t s[5]; unsigned char buf[64]; - size_t bytes; + uint64_t bytes; public: static const size_t OUTPUT_SIZE = 20; diff --git a/src/crypto/sha1.h b/src/crypto/sha1.h index 7b2a21bc6c6f6..8fb20810be66a 100644 --- a/src/crypto/sha1.h +++ b/src/crypto/sha1.h @@ -14,7 +14,7 @@ class CSHA1 private: uint32_t s[5]; unsigned char buf[64]; - size_t bytes; + uint64_t bytes; public: static const size_t OUTPUT_SIZE = 20; diff --git a/src/crypto/sha256.h b/src/crypto/sha256.h index 85cf33739aec8..5b15b6a233b16 100644 --- a/src/crypto/sha256.h +++ b/src/crypto/sha256.h @@ -14,7 +14,7 @@ class CSHA256 private: uint32_t s[8]; unsigned char buf[64]; - size_t bytes; + uint64_t bytes; public: static const size_t OUTPUT_SIZE = 32; diff --git a/src/crypto/sha512.h b/src/crypto/sha512.h index f1f17caf90ce4..614681fae2f11 100644 --- a/src/crypto/sha512.h +++ b/src/crypto/sha512.h @@ -14,7 +14,7 @@ class CSHA512 private: uint64_t s[8]; unsigned char buf[128]; - size_t bytes; + uint64_t bytes; public: static const size_t OUTPUT_SIZE = 64; From 99e70751f23aa59ac297f6746dd8f09a140d48ae Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 5 Apr 2016 15:14:48 +0200 Subject: [PATCH 0152/1802] =?UTF-8?q?Break=20circular=20dependency=20main?= =?UTF-8?q?=20=E2=86=94=20txdb?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Break the circular dependency between main and txdb by: - Moving `CBlockFileInfo` from `main.h` to `chain.h`. I think this makes sense, as the other block-file stuff is there too. - Moving `CDiskTxPos` from `main.h` to `txdb.h`. This type seems specific to txdb. - Pass a functor `insertBlockIndex` to `LoadBlockIndexGuts`. This leaves it up to the caller how to insert block indices. --- src/chain.h | 54 +++++++++++++++++++++++++++++++++++ src/main.cpp | 2 +- src/main.h | 79 ---------------------------------------------------- src/txdb.cpp | 8 ++---- src/txdb.h | 33 +++++++++++++++++++--- 5 files changed, 87 insertions(+), 89 deletions(-) diff --git a/src/chain.h b/src/chain.h index 5b9605a80bdb3..e9da407e9917e 100644 --- a/src/chain.h +++ b/src/chain.h @@ -14,6 +14,60 @@ #include +class CBlockFileInfo +{ +public: + unsigned int nBlocks; //!< number of blocks stored in file + unsigned int nSize; //!< number of used bytes of block file + unsigned int nUndoSize; //!< number of used bytes in the undo file + unsigned int nHeightFirst; //!< lowest height of block in file + unsigned int nHeightLast; //!< highest height of block in file + uint64_t nTimeFirst; //!< earliest time of block in file + uint64_t nTimeLast; //!< latest time of block in file + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + READWRITE(VARINT(nBlocks)); + READWRITE(VARINT(nSize)); + READWRITE(VARINT(nUndoSize)); + READWRITE(VARINT(nHeightFirst)); + READWRITE(VARINT(nHeightLast)); + READWRITE(VARINT(nTimeFirst)); + READWRITE(VARINT(nTimeLast)); + } + + void SetNull() { + nBlocks = 0; + nSize = 0; + nUndoSize = 0; + nHeightFirst = 0; + nHeightLast = 0; + nTimeFirst = 0; + nTimeLast = 0; + } + + CBlockFileInfo() { + SetNull(); + } + + std::string ToString() const; + + /** update statistics (does not update nSize) */ + void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn) { + if (nBlocks==0 || nHeightFirst > nHeightIn) + nHeightFirst = nHeightIn; + if (nBlocks==0 || nTimeFirst > nTimeIn) + nTimeFirst = nTimeIn; + nBlocks++; + if (nHeightIn > nHeightLast) + nHeightLast = nHeightIn; + if (nTimeIn > nTimeLast) + nTimeLast = nTimeIn; + } +}; + struct CDiskBlockPos { int nFile; diff --git a/src/main.cpp b/src/main.cpp index a94d52f8954e8..2db726cb45dba 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3706,7 +3706,7 @@ CBlockIndex * InsertBlockIndex(uint256 hash) bool static LoadBlockIndexDB() { const CChainParams& chainparams = Params(); - if (!pblocktree->LoadBlockIndexGuts()) + if (!pblocktree->LoadBlockIndexGuts(InsertBlockIndex)) return false; boost::this_thread::interruption_point(); diff --git a/src/main.h b/src/main.h index 0962f44e9439e..cd2009e28614c 100644 --- a/src/main.h +++ b/src/main.h @@ -307,30 +307,6 @@ struct CNodeStateStats { std::vector vHeightInFlight; }; -struct CDiskTxPos : public CDiskBlockPos -{ - unsigned int nTxOffset; // after header - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(*(CDiskBlockPos*)this); - READWRITE(VARINT(nTxOffset)); - } - - CDiskTxPos(const CDiskBlockPos &blockIn, unsigned int nTxOffsetIn) : CDiskBlockPos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn) { - } - - CDiskTxPos() { - SetNull(); - } - - void SetNull() { - CDiskBlockPos::SetNull(); - nTxOffset = 0; - } -}; /** @@ -469,61 +445,6 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI /** Check a block is completely valid from start to finish (only works on top of our current best block, with cs_main held) */ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, const CBlock& block, CBlockIndex* pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true); - -class CBlockFileInfo -{ -public: - unsigned int nBlocks; //!< number of blocks stored in file - unsigned int nSize; //!< number of used bytes of block file - unsigned int nUndoSize; //!< number of used bytes in the undo file - unsigned int nHeightFirst; //!< lowest height of block in file - unsigned int nHeightLast; //!< highest height of block in file - uint64_t nTimeFirst; //!< earliest time of block in file - uint64_t nTimeLast; //!< latest time of block in file - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(VARINT(nBlocks)); - READWRITE(VARINT(nSize)); - READWRITE(VARINT(nUndoSize)); - READWRITE(VARINT(nHeightFirst)); - READWRITE(VARINT(nHeightLast)); - READWRITE(VARINT(nTimeFirst)); - READWRITE(VARINT(nTimeLast)); - } - - void SetNull() { - nBlocks = 0; - nSize = 0; - nUndoSize = 0; - nHeightFirst = 0; - nHeightLast = 0; - nTimeFirst = 0; - nTimeLast = 0; - } - - CBlockFileInfo() { - SetNull(); - } - - std::string ToString() const; - - /** update statistics (does not update nSize) */ - void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn) { - if (nBlocks==0 || nHeightFirst > nHeightIn) - nHeightFirst = nHeightIn; - if (nBlocks==0 || nTimeFirst > nTimeIn) - nTimeFirst = nTimeIn; - nBlocks++; - if (nHeightIn > nHeightLast) - nHeightLast = nHeightIn; - if (nTimeIn > nTimeLast) - nTimeLast = nTimeIn; - } -}; - /** RAII wrapper for VerifyDB: Verify consistency of the block and coin databases */ class CVerifyDB { public: diff --git a/src/txdb.cpp b/src/txdb.cpp index be86cceeb36a7..caa6bde38d607 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -5,10 +5,8 @@ #include "txdb.h" -#include "chain.h" #include "chainparams.h" #include "hash.h" -#include "main.h" #include "pow.h" #include "uint256.h" @@ -177,7 +175,7 @@ bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) { return true; } -bool CBlockTreeDB::LoadBlockIndexGuts() +bool CBlockTreeDB::LoadBlockIndexGuts(boost::function insertBlockIndex) { boost::scoped_ptr pcursor(NewIterator()); @@ -191,8 +189,8 @@ bool CBlockTreeDB::LoadBlockIndexGuts() CDiskBlockIndex diskindex; if (pcursor->GetValue(diskindex)) { // Construct block index object - CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash()); - pindexNew->pprev = InsertBlockIndex(diskindex.hashPrev); + CBlockIndex* pindexNew = insertBlockIndex(diskindex.GetBlockHash()); + pindexNew->pprev = insertBlockIndex(diskindex.hashPrev); pindexNew->nHeight = diskindex.nHeight; pindexNew->nFile = diskindex.nFile; pindexNew->nDataPos = diskindex.nDataPos; diff --git a/src/txdb.h b/src/txdb.h index 749802f0e5fd0..ce3c39d7fec11 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -8,15 +8,17 @@ #include "coins.h" #include "dbwrapper.h" +#include "chain.h" #include #include #include #include -class CBlockFileInfo; +#include + class CBlockIndex; -struct CDiskTxPos; +class CCoinsViewDBCursor; class uint256; //! -dbcache default (MiB) @@ -26,7 +28,30 @@ static const int64_t nMaxDbCache = sizeof(void*) > 4 ? 16384 : 1024; //! min. -dbcache in (MiB) static const int64_t nMinDbCache = 4; -class CCoinsViewDBCursor; +struct CDiskTxPos : public CDiskBlockPos +{ + unsigned int nTxOffset; // after header + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + READWRITE(*(CDiskBlockPos*)this); + READWRITE(VARINT(nTxOffset)); + } + + CDiskTxPos(const CDiskBlockPos &blockIn, unsigned int nTxOffsetIn) : CDiskBlockPos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn) { + } + + CDiskTxPos() { + SetNull(); + } + + void SetNull() { + CDiskBlockPos::SetNull(); + nTxOffset = 0; + } +}; /** CCoinsView backed by the coin database (chainstate/) */ class CCoinsViewDB : public CCoinsView @@ -83,7 +108,7 @@ class CBlockTreeDB : public CDBWrapper bool WriteTxIndex(const std::vector > &list); bool WriteFlag(const std::string &name, bool fValue); bool ReadFlag(const std::string &name, bool &fValue); - bool LoadBlockIndexGuts(); + bool LoadBlockIndexGuts(boost::function insertBlockIndex); }; #endif // BITCOIN_TXDB_H From 76212bbc6a13298d7154ac16c0b989aca5471de8 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sat, 9 Apr 2016 07:59:49 +0200 Subject: [PATCH 0153/1802] rpc: make sure `gettxoutsetinfo` hash has txids The key (transaction id for the following outputs) should be serialized to the HashWriter. This is a problem as it means different transactions in the same position with the same outputs will potentially result in the same hash. Fixes primary concern of #7758. --- src/rpc/blockchain.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index b85b2f6b57e19..88f6278b2a42a 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -467,6 +467,7 @@ static bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats) CCoins coins; if (pcursor->GetKey(key) && pcursor->GetValue(coins)) { stats.nTransactions++; + ss << key; for (unsigned int i=0; i Date: Fri, 15 Apr 2016 17:54:45 +0200 Subject: [PATCH 0154/1802] doc: update release-notes for `gettxoutsetinfo` change --- doc/release-notes.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/release-notes.md b/doc/release-notes.md index 806d174ebf7fc..8360cc4816c36 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -21,6 +21,13 @@ It is recommended to use this for sensitive information such as wallet passphrases, as command-line arguments can usually be read from the process table by any user on the system. +RPC low-level changes +---------------------- + +- `gettxoutsetinfo` UTXO hash (`hash_serialized`) has changed. There was a divergence between + 32-bit and 64-bit platforms, and the txids were missing in the hashed data. This has been + fixed, but this means that the output will be different than from previous versions. + 0.13.0 Change log ================= From 1e2c29f2632c378843c5a3c9ad401a7bcacc4de0 Mon Sep 17 00:00:00 2001 From: Kaz Wesley Date: Wed, 13 Apr 2016 10:09:16 -0700 Subject: [PATCH 0155/1802] prevector: destroy elements only via erase() Fixes a bug in which pop_back did not call the deleted item's destructor. Using the most general erase() implementation to implement all the others prevents similar bugs because the coupling between deallocation and destructor invocation only needs to be maintained in one place. Also reduces duplication of complex memmove logic. --- src/prevector.h | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/prevector.h b/src/prevector.h index 1da459bcfe1f3..16b2f8dca7fb6 100644 --- a/src/prevector.h +++ b/src/prevector.h @@ -298,9 +298,8 @@ class prevector { } void resize(size_type new_size) { - while (size() > new_size) { - item_ptr(size() - 1)->~T(); - _size--; + if (size() > new_size) { + erase(item_ptr(new_size), end()); } if (new_size > capacity()) { change_capacity(new_size); @@ -368,10 +367,7 @@ class prevector { } iterator erase(iterator pos) { - (*pos).~T(); - memmove(&(*pos), &(*pos) + 1, ((char*)&(*end())) - ((char*)(1 + &(*pos)))); - _size--; - return pos; + return erase(pos, pos + 1); } iterator erase(iterator first, iterator last) { @@ -396,7 +392,7 @@ class prevector { } void pop_back() { - _size--; + erase(end() - 1, end()); } T& front() { From 4ed41a2b611dfd328fe6f72312d6c596650f03f8 Mon Sep 17 00:00:00 2001 From: Kaz Wesley Date: Sat, 16 Apr 2016 06:49:38 -0700 Subject: [PATCH 0156/1802] test prevector::swap - add a swap operation to prevector tests (fails due to broken prevector::swap) - fix 2 prevector test operation conditions that were impossible --- src/test/prevector_tests.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp index 01a45b540d512..b39b90353053c 100644 --- a/src/test/prevector_tests.cpp +++ b/src/test/prevector_tests.cpp @@ -19,9 +19,11 @@ template class prevector_tester { typedef std::vector realtype; realtype real_vector; + realtype real_vector_alt; typedef prevector pretype; pretype pre_vector; + pretype pre_vector_alt; typedef typename pretype::size_type Size; @@ -149,6 +151,12 @@ class prevector_tester { pre_vector.shrink_to_fit(); test(); } + + void swap() { + real_vector.swap(real_vector_alt); + pre_vector.swap(pre_vector_alt); + test(); + } }; BOOST_AUTO_TEST_CASE(PrevectorTestInt) @@ -204,12 +212,15 @@ BOOST_AUTO_TEST_CASE(PrevectorTestInt) if (test.size() > 0) { test.update(insecure_rand() % test.size(), insecure_rand()); } - if (((r >> 11) & 1024) == 11) { + if (((r >> 11) % 1024) == 11) { test.clear(); } - if (((r >> 21) & 512) == 12) { + if (((r >> 21) % 512) == 12) { test.assign(insecure_rand() % 32, insecure_rand()); } + if (((r >> 15) % 64) == 3) { + test.swap(); + } } } } From a7af72a697a8decab364792230153f114be3919c Mon Sep 17 00:00:00 2001 From: Kaz Wesley Date: Thu, 14 Apr 2016 09:26:32 -0700 Subject: [PATCH 0157/1802] prevector::swap: fix (unreached) data corruption swap was using an incorrect condition to determine when to apply an optimization (not swapping the full direct[] when swapping two indirect prevectors). Rather than correct the optimization I'm removing it for simplicity. Removing this optimization minutely improves performance in the typical (currently only) usage of member swap(), which is swapping with a freshly value-initialized object. --- src/prevector.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/prevector.h b/src/prevector.h index 16b2f8dca7fb6..a0e1e140b4013 100644 --- a/src/prevector.h +++ b/src/prevector.h @@ -412,12 +412,7 @@ class prevector { } void swap(prevector& other) { - if (_size & other._size & 1) { - std::swap(_union.capacity, other._union.capacity); - std::swap(_union.indirect, other._union.indirect); - } else { - std::swap(_union, other._union); - } + std::swap(_union, other._union); std::swap(_size, other._size); } From fc95f6ecb6ee09c4a5832247f2c8759cb88c2fa1 Mon Sep 17 00:00:00 2001 From: Chris Moore Date: Sat, 16 Apr 2016 13:35:42 -0700 Subject: [PATCH 0158/1802] fix typo in help text 'in which the transaction is included in' --- src/rpc/rawtransaction.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index de8cd68f66267..4e1b1576a4886 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -211,7 +211,7 @@ UniValue gettxoutproof(const UniValue& params, bool fHelp) "\nNOTE: By default this function only works sometimes. This is when there is an\n" "unspent output in the utxo for this transaction. To make it always work,\n" "you need to maintain a transaction index, using the -txindex command line option or\n" - "specify the block in which the transaction is included in manually (by blockhash).\n" + "specify the block in which the transaction is included manually (by blockhash).\n" "\nReturn the raw transaction data.\n" "\nArguments:\n" "1. \"txids\" (string) A json array of txids to filter\n" From dc0693f6379cc63fcea4cb979526b1ba8e0461f3 Mon Sep 17 00:00:00 2001 From: Chris Moore Date: Sat, 16 Apr 2016 13:42:28 -0700 Subject: [PATCH 0159/1802] add missing newline Without the newline I see "bein" where the two lines are concatenated: Note that all inputs selected must be of standard form and P2SH scripts must *bein* the wallet using importaddress or addmultisigaddress (to calculate fees). --- src/wallet/rpcwallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 3078cebd486c3..096206f5de8e3 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2443,7 +2443,7 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) "Note that inputs which were signed may need to be resigned after completion since in/outputs have been added.\n" "The inputs added will not be signed, use signrawtransaction for that.\n" "Note that all existing inputs must have their previous output transaction be in the wallet.\n" - "Note that all inputs selected must be of standard form and P2SH scripts must be" + "Note that all inputs selected must be of standard form and P2SH scripts must be\n" "in the wallet using importaddress or addmultisigaddress (to calculate fees).\n" "Only pay-to-pubkey, multisig, and P2SH versions thereof are currently supported for watch-only\n" "\nArguments:\n" From 3107c475a70042c1aad8b3bbb7d63234b1bbed8d Mon Sep 17 00:00:00 2001 From: Chris Moore Date: Sun, 17 Apr 2016 00:01:49 -0700 Subject: [PATCH 0160/1802] fix spelling mistake --- src/wallet/rpcwallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 3078cebd486c3..21192a58b81f8 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2455,7 +2455,7 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) " \"includeWatching\" (boolean, optional, default false) Also select inputs which are watch only\n" " \"lockUnspents\" (boolean, optional, default false) Lock selected unspent outputs\n" " }\n" - " for backward compatibility: passing in a true instzead of an object will result in {\"includeWatching\":true}\n" + " for backward compatibility: passing in a true instead of an object will result in {\"includeWatching\":true}\n" "\nResult:\n" "{\n" " \"hex\": \"value\", (string) The resulting raw transaction (hex-encoded string)\n" From e9fc71e5fa6f0d7991bac616b9fed6a80e77a8d7 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 12 Apr 2016 20:23:16 -0400 Subject: [PATCH 0161/1802] net: require lookup functions to specify all arguments To make it clear where DNS resolves are happening --- src/net.cpp | 4 ++-- src/netbase.h | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index f294e4c667836..6ab6ef819d077 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1443,7 +1443,7 @@ void ThreadDNSAddressSeed() } else { vector vIPs; vector vAdd; - if (LookupHost(seed.host.c_str(), vIPs)) + if (LookupHost(seed.host.c_str(), vIPs, 0, true)) { BOOST_FOREACH(const CNetAddr& ip, vIPs) { @@ -1884,7 +1884,7 @@ void static Discover(boost::thread_group& threadGroup) if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR) { vector vaddr; - if (LookupHost(pszHostName, vaddr)) + if (LookupHost(pszHostName, vaddr, 0, true)) { BOOST_FOREACH (const CNetAddr &addr, vaddr) { diff --git a/src/netbase.h b/src/netbase.h index db736154fa684..4529f9822914c 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -206,9 +206,9 @@ bool GetProxy(enum Network net, proxyType &proxyInfoOut); bool IsProxy(const CNetAddr &addr); bool SetNameProxy(const proxyType &addrProxy); bool HaveNameProxy(); -bool LookupHost(const char *pszName, std::vector& vIP, unsigned int nMaxSolutions = 0, bool fAllowLookup = true); -bool Lookup(const char *pszName, CService& addr, int portDefault = 0, bool fAllowLookup = true); -bool Lookup(const char *pszName, std::vector& vAddr, int portDefault = 0, bool fAllowLookup = true, unsigned int nMaxSolutions = 0); +bool LookupHost(const char *pszName, std::vector& vIP, unsigned int nMaxSolutions, bool fAllowLookup); +bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLookup); +bool Lookup(const char *pszName, std::vector& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions); bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0); bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed = 0); bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout, bool *outProxyConnectionFailed = 0); From a3310b4d485b1510c240f1db882530590b6fd7c9 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 18 Apr 2016 12:05:32 +0200 Subject: [PATCH 0162/1802] txdb: Fix assert crash in new UTXO set cursor Remove the mistaken assumption that GetKey returning false signifies an internal database issue. It will return false when the key cannot be deserialized into the (char,uint256) stanza, which indicates that the cursor has reached a different kind of key. Fixes bug #7890 introduced in #7756. --- src/txdb.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/txdb.cpp b/src/txdb.cpp index be86cceeb36a7..19ca1786549ee 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -134,12 +134,8 @@ bool CCoinsViewDBCursor::Valid() const void CCoinsViewDBCursor::Next() { pcursor->Next(); - if (pcursor->Valid()) { - bool ok = pcursor->GetKey(keyTmp); - assert(ok); // If GetKey fails here something must be wrong with underlying database, we cannot handle that here - } else { + if (!pcursor->Valid() || !pcursor->GetKey(keyTmp)) keyTmp.first = 0; // Invalidate cached key after last record so that Valid() and GetKey() return false - } } bool CBlockTreeDB::WriteBatchSync(const std::vector >& fileInfo, int nLastFile, const std::vector& blockinfo) { From de39c95c2468cc643a5d5bed9e5dd8cea6a40747 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 18 Apr 2016 14:03:53 +0200 Subject: [PATCH 0163/1802] test: move accounting_tests and rpc_wallet_tests to wallet/test Move the two other wallet tests to where they belong. --- src/Makefile.test.include | 4 ++-- src/{ => wallet}/test/accounting_tests.cpp | 0 src/{ => wallet}/test/rpc_wallet_tests.cpp | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename src/{ => wallet}/test/accounting_tests.cpp (100%) rename src/{ => wallet}/test/rpc_wallet_tests.cpp (100%) diff --git a/src/Makefile.test.include b/src/Makefile.test.include index f025b18c7e690..989718554930f 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -90,9 +90,9 @@ BITCOIN_TESTS =\ if ENABLE_WALLET BITCOIN_TESTS += \ - test/accounting_tests.cpp \ + wallet/test/accounting_tests.cpp \ wallet/test/wallet_tests.cpp \ - test/rpc_wallet_tests.cpp + wallet/test/rpc_wallet_tests.cpp endif test_test_bitcoin_SOURCES = $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES) diff --git a/src/test/accounting_tests.cpp b/src/wallet/test/accounting_tests.cpp similarity index 100% rename from src/test/accounting_tests.cpp rename to src/wallet/test/accounting_tests.cpp diff --git a/src/test/rpc_wallet_tests.cpp b/src/wallet/test/rpc_wallet_tests.cpp similarity index 100% rename from src/test/rpc_wallet_tests.cpp rename to src/wallet/test/rpc_wallet_tests.cpp From fae1f4ebfe6be4426685b22166f5367c92ba0833 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Fri, 15 Apr 2016 11:25:19 +0200 Subject: [PATCH 0164/1802] [qa] rpc-tests: Fix link in comment and label error msg --- qa/pull-tester/rpc-tests.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index e159082a009e5..c0637209e3c1d 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -69,6 +69,7 @@ if EXEEXT == ".exe" and "-win" not in opts: # https://github.com/bitcoin/bitcoin/commit/d52802551752140cf41f0d9a225a43e84404d3e9 + # https://github.com/bitcoin/bitcoin/pull/5677#issuecomment-136646964 print "Win tests currently disabled by default. Use -win option to enable" sys.exit(0) @@ -81,7 +82,7 @@ try: import zmq except ImportError as e: - print("WARNING: \"import zmq\" failed. Set ENABLE_ZMQ=0 or " \ + print("ERROR: \"import zmq\" failed. Set ENABLE_ZMQ=0 or " \ "to run zmq tests, see dependency info in /qa/README.md.") raise e From f4eae2d910d9edb3750efec4facbeab161cce593 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 18 Apr 2016 14:54:57 +0200 Subject: [PATCH 0165/1802] test: Create test fixture for wallet Removes all the `#ifdef ENABLE_WALLET` from `test_bitcoin` by making the wallet tests use their own fixture. --- src/Makefile.test.include | 2 ++ src/test/test_bitcoin.cpp | 23 -------------------- src/test/test_bitcoin.h | 3 +-- src/wallet/test/accounting_tests.cpp | 4 ++-- src/wallet/test/rpc_wallet_tests.cpp | 4 ++-- src/wallet/test/wallet_test_fixture.cpp | 28 +++++++++++++++++++++++++ src/wallet/test/wallet_test_fixture.h | 18 ++++++++++++++++ src/wallet/test/wallet_tests.cpp | 4 ++-- 8 files changed, 55 insertions(+), 31 deletions(-) create mode 100644 src/wallet/test/wallet_test_fixture.cpp create mode 100644 src/wallet/test/wallet_test_fixture.h diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 989718554930f..08e2f6af4db73 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -90,6 +90,8 @@ BITCOIN_TESTS =\ if ENABLE_WALLET BITCOIN_TESTS += \ + wallet/test/wallet_test_fixture.cpp \ + wallet/test/wallet_test_fixture.h \ wallet/test/accounting_tests.cpp \ wallet/test/wallet_tests.cpp \ wallet/test/rpc_wallet_tests.cpp diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index 97b99962527e6..eb8ac01e8d32e 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -19,10 +19,6 @@ #include "ui_interface.h" #include "rpc/server.h" #include "rpc/register.h" -#ifdef ENABLE_WALLET -#include "wallet/db.h" -#include "wallet/wallet.h" -#endif #include "test/testutil.h" @@ -57,10 +53,6 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha // Ideally we'd move all the RPC tests to the functional testing framework // instead of unit tests, but for now we need these here. RegisterAllCoreRPCCommands(tableRPC); -#ifdef ENABLE_WALLET - bitdb.MakeMock(); - RegisterWalletRPCCommands(tableRPC); -#endif ClearDatadirCache(); pathTemp = GetTempPath() / strprintf("test_bitcoin_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000))); boost::filesystem::create_directories(pathTemp); @@ -69,12 +61,6 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha pcoinsdbview = new CCoinsViewDB(1 << 23, true); pcoinsTip = new CCoinsViewCache(pcoinsdbview); InitBlockIndex(chainparams); -#ifdef ENABLE_WALLET - bool fFirstRun; - pwalletMain = new CWallet("wallet.dat"); - pwalletMain->LoadWallet(fFirstRun); - RegisterValidationInterface(pwalletMain); -#endif nScriptCheckThreads = 3; for (int i=0; i < nScriptCheckThreads-1; i++) threadGroup.create_thread(&ThreadScriptCheck); @@ -86,19 +72,10 @@ TestingSetup::~TestingSetup() UnregisterNodeSignals(GetNodeSignals()); threadGroup.interrupt_all(); threadGroup.join_all(); -#ifdef ENABLE_WALLET - UnregisterValidationInterface(pwalletMain); - delete pwalletMain; - pwalletMain = NULL; -#endif UnloadBlockIndex(); delete pcoinsTip; delete pcoinsdbview; delete pblocktree; -#ifdef ENABLE_WALLET - bitdb.Flush(true); - bitdb.Reset(); -#endif boost::filesystem::remove_all(pathTemp); } diff --git a/src/test/test_bitcoin.h b/src/test/test_bitcoin.h index 769ae5a13252b..57f66f6c6d0dc 100644 --- a/src/test/test_bitcoin.h +++ b/src/test/test_bitcoin.h @@ -25,8 +25,7 @@ struct BasicTestingSetup { }; /** Testing setup that configures a complete environment. - * Included are data directory, coins database, script check threads - * and wallet (if enabled) setup. + * Included are data directory, coins database, script check threads setup. */ struct TestingSetup: public BasicTestingSetup { CCoinsViewDB *pcoinsdbview; diff --git a/src/wallet/test/accounting_tests.cpp b/src/wallet/test/accounting_tests.cpp index dad191c68435e..d075b2b641a1b 100644 --- a/src/wallet/test/accounting_tests.cpp +++ b/src/wallet/test/accounting_tests.cpp @@ -5,7 +5,7 @@ #include "wallet/wallet.h" #include "wallet/walletdb.h" -#include "test/test_bitcoin.h" +#include "wallet/test/wallet_test_fixture.h" #include @@ -14,7 +14,7 @@ extern CWallet* pwalletMain; -BOOST_FIXTURE_TEST_SUITE(accounting_tests, TestingSetup) +BOOST_FIXTURE_TEST_SUITE(accounting_tests, WalletTestingSetup) static void GetResults(CWalletDB& walletdb, std::map& results) diff --git a/src/wallet/test/rpc_wallet_tests.cpp b/src/wallet/test/rpc_wallet_tests.cpp index 3443be2093015..4e7d177f51855 100644 --- a/src/wallet/test/rpc_wallet_tests.cpp +++ b/src/wallet/test/rpc_wallet_tests.cpp @@ -9,7 +9,7 @@ #include "main.h" #include "wallet/wallet.h" -#include "test/test_bitcoin.h" +#include "wallet/test/wallet_test_fixture.h" #include #include @@ -23,7 +23,7 @@ extern UniValue CallRPC(string args); extern CWallet* pwalletMain; -BOOST_FIXTURE_TEST_SUITE(rpc_wallet_tests, TestingSetup) +BOOST_FIXTURE_TEST_SUITE(rpc_wallet_tests, WalletTestingSetup) BOOST_AUTO_TEST_CASE(rpc_addmultisig) { diff --git a/src/wallet/test/wallet_test_fixture.cpp b/src/wallet/test/wallet_test_fixture.cpp new file mode 100644 index 0000000000000..8370300963213 --- /dev/null +++ b/src/wallet/test/wallet_test_fixture.cpp @@ -0,0 +1,28 @@ +#include "wallet/test/wallet_test_fixture.h" + +#include "rpc/server.h" +#include "wallet/db.h" +#include "wallet/wallet.h" + +WalletTestingSetup::WalletTestingSetup(const std::string& chainName): + TestingSetup(chainName) +{ + bitdb.MakeMock(); + + bool fFirstRun; + pwalletMain = new CWallet("wallet.dat"); + pwalletMain->LoadWallet(fFirstRun); + RegisterValidationInterface(pwalletMain); + + RegisterWalletRPCCommands(tableRPC); +} + +WalletTestingSetup::~WalletTestingSetup() +{ + UnregisterValidationInterface(pwalletMain); + delete pwalletMain; + pwalletMain = NULL; + + bitdb.Flush(true); + bitdb.Reset(); +} diff --git a/src/wallet/test/wallet_test_fixture.h b/src/wallet/test/wallet_test_fixture.h new file mode 100644 index 0000000000000..97a6d98397acc --- /dev/null +++ b/src/wallet/test/wallet_test_fixture.h @@ -0,0 +1,18 @@ +// Copyright (c) 2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_WALLET_TEST_FIXTURE_H +#define BITCOIN_WALLET_TEST_FIXTURE_H + +#include "test/test_bitcoin.h" + +/** Testing setup and teardown for wallet. + */ +struct WalletTestingSetup: public TestingSetup { + WalletTestingSetup(const std::string& chainName = CBaseChainParams::MAIN); + ~WalletTestingSetup(); +}; + +#endif + diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index e84d5880261c4..b759a6b2e8b75 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -9,7 +9,7 @@ #include #include -#include "test/test_bitcoin.h" +#include "wallet/test/wallet_test_fixture.h" #include #include @@ -25,7 +25,7 @@ using namespace std; typedef set > CoinSet; -BOOST_FIXTURE_TEST_SUITE(wallet_tests, TestingSetup) +BOOST_FIXTURE_TEST_SUITE(wallet_tests, WalletTestingSetup) static CWallet wallet; static vector vCoins; From a25a4f5b04c3e045557e9e7e807b2af74ad75128 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 18 Apr 2016 15:12:46 +0200 Subject: [PATCH 0166/1802] =?UTF-8?q?wallet=5Fismine.h=20=E2=86=92=20scrip?= =?UTF-8?q?t/ismine.h?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removes conditional dependency of `src/test` on wallet. Makes multisig and P2SH tests complete without wallet built-in. --- src/Makefile.am | 4 ++-- src/{wallet/wallet_ismine.cpp => script/ismine.cpp} | 2 +- src/{wallet/wallet_ismine.h => script/ismine.h} | 6 +++--- src/test/multisig_tests.cpp | 12 +----------- src/test/script_P2SH_tests.cpp | 9 +-------- src/wallet/wallet.h | 2 +- 6 files changed, 9 insertions(+), 26 deletions(-) rename src/{wallet/wallet_ismine.cpp => script/ismine.cpp} (99%) rename src/{wallet/wallet_ismine.h => script/ismine.h} (90%) diff --git a/src/Makefile.am b/src/Makefile.am index d91e959cffe79..24744835f50d6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -135,6 +135,7 @@ BITCOIN_CORE_H = \ script/sigcache.h \ script/sign.h \ script/standard.h \ + script/ismine.h \ streams.h \ support/allocators/secure.h \ support/allocators/zeroafterfree.h \ @@ -157,7 +158,6 @@ BITCOIN_CORE_H = \ wallet/db.h \ wallet/rpcwallet.h \ wallet/wallet.h \ - wallet/wallet_ismine.h \ wallet/walletdb.h \ zmq/zmqabstractnotifier.h \ zmq/zmqconfig.h\ @@ -199,6 +199,7 @@ libbitcoin_server_a_SOURCES = \ rpc/rawtransaction.cpp \ rpc/server.cpp \ script/sigcache.cpp \ + script/ismine.cpp \ timedata.cpp \ torcontrol.cpp \ txdb.cpp \ @@ -229,7 +230,6 @@ libbitcoin_wallet_a_SOURCES = \ wallet/rpcdump.cpp \ wallet/rpcwallet.cpp \ wallet/wallet.cpp \ - wallet/wallet_ismine.cpp \ wallet/walletdb.cpp \ policy/rbf.cpp \ $(BITCOIN_CORE_H) diff --git a/src/wallet/wallet_ismine.cpp b/src/script/ismine.cpp similarity index 99% rename from src/wallet/wallet_ismine.cpp rename to src/script/ismine.cpp index ebda5cc53df76..535c56b57a06a 100644 --- a/src/wallet/wallet_ismine.cpp +++ b/src/script/ismine.cpp @@ -3,7 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "wallet_ismine.h" +#include "ismine.h" #include "key.h" #include "keystore.h" diff --git a/src/wallet/wallet_ismine.h b/src/script/ismine.h similarity index 90% rename from src/wallet/wallet_ismine.h rename to src/script/ismine.h index 51afd1b1402cb..4b7db8802ba54 100644 --- a/src/wallet/wallet_ismine.h +++ b/src/script/ismine.h @@ -3,8 +3,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_WALLET_WALLET_ISMINE_H -#define BITCOIN_WALLET_WALLET_ISMINE_H +#ifndef BITCOIN_SCRIPT_ISMINE_H +#define BITCOIN_SCRIPT_ISMINE_H #include "script/standard.h" @@ -31,4 +31,4 @@ typedef uint8_t isminefilter; isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey); isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest); -#endif // BITCOIN_WALLET_WALLET_ISMINE_H +#endif // BITCOIN_SCRIPT_ISMINE_H diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp index edf1650ca54d5..d48a68ba547c5 100644 --- a/src/test/multisig_tests.cpp +++ b/src/test/multisig_tests.cpp @@ -9,12 +9,10 @@ #include "script/script_error.h" #include "script/interpreter.h" #include "script/sign.h" +#include "script/ismine.h" #include "uint256.h" #include "test/test_bitcoin.h" -#ifdef ENABLE_WALLET -#include "wallet/wallet_ismine.h" -#endif #include #include @@ -210,10 +208,8 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1) CTxDestination addr; BOOST_CHECK(ExtractDestination(s, addr)); BOOST_CHECK(addr == keyaddr[0]); -#ifdef ENABLE_WALLET BOOST_CHECK(IsMine(keystore, s)); BOOST_CHECK(!IsMine(emptykeystore, s)); -#endif } { vector solutions; @@ -225,10 +221,8 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1) CTxDestination addr; BOOST_CHECK(ExtractDestination(s, addr)); BOOST_CHECK(addr == keyaddr[0]); -#ifdef ENABLE_WALLET BOOST_CHECK(IsMine(keystore, s)); BOOST_CHECK(!IsMine(emptykeystore, s)); -#endif } { vector solutions; @@ -239,11 +233,9 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1) BOOST_CHECK_EQUAL(solutions.size(), 4U); CTxDestination addr; BOOST_CHECK(!ExtractDestination(s, addr)); -#ifdef ENABLE_WALLET BOOST_CHECK(IsMine(keystore, s)); BOOST_CHECK(!IsMine(emptykeystore, s)); BOOST_CHECK(!IsMine(partialkeystore, s)); -#endif } { vector solutions; @@ -258,11 +250,9 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1) BOOST_CHECK(addrs[0] == keyaddr[0]); BOOST_CHECK(addrs[1] == keyaddr[1]); BOOST_CHECK(nRequired == 1); -#ifdef ENABLE_WALLET BOOST_CHECK(IsMine(keystore, s)); BOOST_CHECK(!IsMine(emptykeystore, s)); BOOST_CHECK(!IsMine(partialkeystore, s)); -#endif } { vector solutions; diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp index 28b85e8d290a7..d10284fe940e5 100644 --- a/src/test/script_P2SH_tests.cpp +++ b/src/test/script_P2SH_tests.cpp @@ -9,12 +9,9 @@ #include "script/script.h" #include "script/script_error.h" #include "script/sign.h" +#include "script/ismine.h" #include "test/test_bitcoin.h" -#ifdef ENABLE_WALLET -#include "wallet/wallet_ismine.h" -#endif - #include #include @@ -101,9 +98,7 @@ BOOST_AUTO_TEST_CASE(sign) txTo[i].vin[0].prevout.n = i; txTo[i].vin[0].prevout.hash = txFrom.GetHash(); txTo[i].vout[0].nValue = 1; -#ifdef ENABLE_WALLET BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i)); -#endif } for (int i = 0; i < 8; i++) { @@ -198,9 +193,7 @@ BOOST_AUTO_TEST_CASE(set) txTo[i].vin[0].prevout.hash = txFrom.GetHash(); txTo[i].vout[0].nValue = 1*CENT; txTo[i].vout[0].scriptPubKey = inner[i]; -#ifdef ENABLE_WALLET BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i)); -#endif } for (int i = 0; i < 4; i++) { diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index aab4b217caa87..fa8740eb7fe38 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -12,8 +12,8 @@ #include "ui_interface.h" #include "utilstrencodings.h" #include "validationinterface.h" +#include "script/ismine.h" #include "wallet/crypter.h" -#include "wallet/wallet_ismine.h" #include "wallet/walletdb.h" #include "wallet/rpcwallet.h" From b30fb42e499beee5899b7e0e6c7581101b14ee83 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 18 Apr 2016 15:15:57 +0200 Subject: [PATCH 0167/1802] test: Rename wallet.dat to wallet_test.dat Indicate that the file name is not hardcoded, and a little bit of safety so that it never nukes the main wallet. Suggestion by Marco Falke. --- src/wallet/test/wallet_test_fixture.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/test/wallet_test_fixture.cpp b/src/wallet/test/wallet_test_fixture.cpp index 8370300963213..9036ee26d83e0 100644 --- a/src/wallet/test/wallet_test_fixture.cpp +++ b/src/wallet/test/wallet_test_fixture.cpp @@ -10,7 +10,7 @@ WalletTestingSetup::WalletTestingSetup(const std::string& chainName): bitdb.MakeMock(); bool fFirstRun; - pwalletMain = new CWallet("wallet.dat"); + pwalletMain = new CWallet("wallet_test.dat"); pwalletMain->LoadWallet(fFirstRun); RegisterValidationInterface(pwalletMain); From 87049e832d97d4f2808c0b479b21fc7b16c86934 Mon Sep 17 00:00:00 2001 From: mrbandrews Date: Mon, 18 Apr 2016 12:10:47 -0400 Subject: [PATCH 0168/1802] Speed up getchaintips. --- src/rpc/blockchain.cpp | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 34637b9f7e398..3db827d9ae372 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -760,17 +760,30 @@ UniValue getchaintips(const UniValue& params, bool fHelp) LOCK(cs_main); - /* Build up a list of chain tips. We start with the list of all - known blocks, and successively remove blocks that appear as pprev - of another block. */ + /* + * Idea: the set of chain tips is chainActive.tip, plus orphan blocks which do not have another orphan building off of them. + * Algorithm: + * - Make one pass through mapBlockIndex, picking out the orphan blocks, and also storing a set of the orphan block's pprev pointers. + * - Iterate through the orphan blocks. If the block isn't pointed to by another orphan, it is a chain tip. + * - add chainActive.Tip() + */ std::set setTips; - BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex) - setTips.insert(item.second); + std::set setOrphans; + std::set setPrevs; + BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex) { - const CBlockIndex* pprev = item.second->pprev; - if (pprev) - setTips.erase(pprev); + if (!chainActive.Contains(item.second)) { + setOrphans.insert(item.second); + setPrevs.insert(item.second->pprev); + } + } + + for (std::set::iterator it = setOrphans.begin(); it != setOrphans.end(); ++it) + { + if (setPrevs.erase(*it) == 0) { + setTips.insert(*it); + } } // Always report the currently active tip. From fa942c755ab513829dcab27487ba1e7ab5a806ee Mon Sep 17 00:00:00 2001 From: Joao Fonseca Date: Tue, 19 Apr 2016 12:22:11 +0100 Subject: [PATCH 0169/1802] Move method to check matches within arrays on util.py --- qa/rpc-tests/getblocktemplate_longpoll.py | 22 ------- qa/rpc-tests/getblocktemplate_proposals.py | 22 ------- qa/rpc-tests/keypool.py | 22 ------- qa/rpc-tests/listtransactions.py | 71 ++++++++-------------- qa/rpc-tests/receivedby.py | 40 +++--------- qa/rpc-tests/test_framework/util.py | 29 +++++++++ 6 files changed, 61 insertions(+), 145 deletions(-) diff --git a/qa/rpc-tests/getblocktemplate_longpoll.py b/qa/rpc-tests/getblocktemplate_longpoll.py index 3e85957ae2323..e2a839f718924 100755 --- a/qa/rpc-tests/getblocktemplate_longpoll.py +++ b/qa/rpc-tests/getblocktemplate_longpoll.py @@ -6,28 +6,6 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * - -def check_array_result(object_array, to_match, expected): - """ - Pass in array of JSON objects, a dictionary with key/value pairs - to match against, and another dictionary with expected key/value - pairs. - """ - num_matched = 0 - for item in object_array: - all_match = True - for key,value in to_match.items(): - if item[key] != value: - all_match = False - if not all_match: - continue - for key,value in expected.items(): - if item[key] != value: - raise AssertionError("%s : expected %s=%s"%(str(item), str(key), str(value))) - num_matched = num_matched+1 - if num_matched == 0: - raise AssertionError("No objects matched %s"%(str(to_match))) - import threading class LongpollThread(threading.Thread): diff --git a/qa/rpc-tests/getblocktemplate_proposals.py b/qa/rpc-tests/getblocktemplate_proposals.py index 07bfe69c6d869..be119031baf0b 100755 --- a/qa/rpc-tests/getblocktemplate_proposals.py +++ b/qa/rpc-tests/getblocktemplate_proposals.py @@ -10,28 +10,6 @@ from hashlib import sha256 from struct import pack - -def check_array_result(object_array, to_match, expected): - """ - Pass in array of JSON objects, a dictionary with key/value pairs - to match against, and another dictionary with expected key/value - pairs. - """ - num_matched = 0 - for item in object_array: - all_match = True - for key,value in to_match.items(): - if item[key] != value: - all_match = False - if not all_match: - continue - for key,value in expected.items(): - if item[key] != value: - raise AssertionError("%s : expected %s=%s"%(str(item), str(key), str(value))) - num_matched = num_matched+1 - if num_matched == 0: - raise AssertionError("No objects matched %s"%(str(to_match))) - def b2x(b): return b2a_hex(b).decode('ascii') diff --git a/qa/rpc-tests/keypool.py b/qa/rpc-tests/keypool.py index 5253d49c308f7..b86c085e0009e 100755 --- a/qa/rpc-tests/keypool.py +++ b/qa/rpc-tests/keypool.py @@ -10,28 +10,6 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * - -def check_array_result(object_array, to_match, expected): - """ - Pass in array of JSON objects, a dictionary with key/value pairs - to match against, and another dictionary with expected key/value - pairs. - """ - num_matched = 0 - for item in object_array: - all_match = True - for key,value in to_match.items(): - if item[key] != value: - all_match = False - if not all_match: - continue - for key,value in expected.items(): - if item[key] != value: - raise AssertionError("%s : expected %s=%s"%(str(item), str(key), str(value))) - num_matched = num_matched+1 - if num_matched == 0: - raise AssertionError("No objects matched %s"%(str(to_match))) - class KeyPoolTest(BitcoinTestFramework): def run_test(self): diff --git a/qa/rpc-tests/listtransactions.py b/qa/rpc-tests/listtransactions.py index 0783a1f3d3717..4e5809f4a77d8 100755 --- a/qa/rpc-tests/listtransactions.py +++ b/qa/rpc-tests/listtransactions.py @@ -16,27 +16,6 @@ def txFromHex(hexstring): tx.deserialize(f) return tx -def check_array_result(object_array, to_match, expected): - """ - Pass in array of JSON objects, a dictionary with key/value pairs - to match against, and another dictionary with expected key/value - pairs. - """ - num_matched = 0 - for item in object_array: - all_match = True - for key,value in to_match.items(): - if item[key] != value: - all_match = False - if not all_match: - continue - for key,value in expected.items(): - if item[key] != value: - raise AssertionError("%s : expected %s=%s"%(str(item), str(key), str(value))) - num_matched = num_matched+1 - if num_matched == 0: - raise AssertionError("No objects matched %s"%(str(to_match))) - class ListTransactionsTest(BitcoinTestFramework): def setup_nodes(self): @@ -48,28 +27,28 @@ def run_test(self): # Simple send, 0 to 1: txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1) self.sync_all() - check_array_result(self.nodes[0].listtransactions(), + assert_array_result(self.nodes[0].listtransactions(), {"txid":txid}, {"category":"send","account":"","amount":Decimal("-0.1"),"confirmations":0}) - check_array_result(self.nodes[1].listtransactions(), + assert_array_result(self.nodes[1].listtransactions(), {"txid":txid}, {"category":"receive","account":"","amount":Decimal("0.1"),"confirmations":0}) # mine a block, confirmations should change: self.nodes[0].generate(1) self.sync_all() - check_array_result(self.nodes[0].listtransactions(), + assert_array_result(self.nodes[0].listtransactions(), {"txid":txid}, {"category":"send","account":"","amount":Decimal("-0.1"),"confirmations":1}) - check_array_result(self.nodes[1].listtransactions(), + assert_array_result(self.nodes[1].listtransactions(), {"txid":txid}, {"category":"receive","account":"","amount":Decimal("0.1"),"confirmations":1}) # send-to-self: txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 0.2) - check_array_result(self.nodes[0].listtransactions(), + assert_array_result(self.nodes[0].listtransactions(), {"txid":txid, "category":"send"}, {"amount":Decimal("-0.2")}) - check_array_result(self.nodes[0].listtransactions(), + assert_array_result(self.nodes[0].listtransactions(), {"txid":txid, "category":"receive"}, {"amount":Decimal("0.2")}) @@ -80,28 +59,28 @@ def run_test(self): self.nodes[1].getaccountaddress("toself") : 0.44 } txid = self.nodes[1].sendmany("", send_to) self.sync_all() - check_array_result(self.nodes[1].listtransactions(), + assert_array_result(self.nodes[1].listtransactions(), {"category":"send","amount":Decimal("-0.11")}, {"txid":txid} ) - check_array_result(self.nodes[0].listtransactions(), + assert_array_result(self.nodes[0].listtransactions(), {"category":"receive","amount":Decimal("0.11")}, {"txid":txid} ) - check_array_result(self.nodes[1].listtransactions(), + assert_array_result(self.nodes[1].listtransactions(), {"category":"send","amount":Decimal("-0.22")}, {"txid":txid} ) - check_array_result(self.nodes[1].listtransactions(), + assert_array_result(self.nodes[1].listtransactions(), {"category":"receive","amount":Decimal("0.22")}, {"txid":txid} ) - check_array_result(self.nodes[1].listtransactions(), + assert_array_result(self.nodes[1].listtransactions(), {"category":"send","amount":Decimal("-0.33")}, {"txid":txid} ) - check_array_result(self.nodes[0].listtransactions(), + assert_array_result(self.nodes[0].listtransactions(), {"category":"receive","amount":Decimal("0.33")}, {"txid":txid, "account" : "from1"} ) - check_array_result(self.nodes[1].listtransactions(), + assert_array_result(self.nodes[1].listtransactions(), {"category":"send","amount":Decimal("-0.44")}, {"txid":txid, "account" : ""} ) - check_array_result(self.nodes[1].listtransactions(), + assert_array_result(self.nodes[1].listtransactions(), {"category":"receive","amount":Decimal("0.44")}, {"txid":txid, "account" : "toself"} ) @@ -111,7 +90,7 @@ def run_test(self): self.nodes[1].generate(1) self.sync_all() assert(len(self.nodes[0].listtransactions("watchonly", 100, 0, False)) == 0) - check_array_result(self.nodes[0].listtransactions("watchonly", 100, 0, True), + assert_array_result(self.nodes[0].listtransactions("watchonly", 100, 0, True), {"category":"receive","amount":Decimal("0.1")}, {"txid":txid, "account" : "watchonly"} ) @@ -139,9 +118,9 @@ def get_unconfirmed_utxo_entry(node, txid_to_match): # 1. Chain a few transactions that don't opt-in. txid_1 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1) assert(not is_opt_in(self.nodes[0], txid_1)) - check_array_result(self.nodes[0].listtransactions(), {"txid": txid_1}, {"bip125-replaceable":"no"}) + assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_1}, {"bip125-replaceable":"no"}) sync_mempools(self.nodes) - check_array_result(self.nodes[1].listtransactions(), {"txid": txid_1}, {"bip125-replaceable":"no"}) + assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_1}, {"bip125-replaceable":"no"}) # Tx2 will build off txid_1, still not opting in to RBF. utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[1], txid_1) @@ -155,9 +134,9 @@ def get_unconfirmed_utxo_entry(node, txid_to_match): # ...and check the result assert(not is_opt_in(self.nodes[1], txid_2)) - check_array_result(self.nodes[1].listtransactions(), {"txid": txid_2}, {"bip125-replaceable":"no"}) + assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_2}, {"bip125-replaceable":"no"}) sync_mempools(self.nodes) - check_array_result(self.nodes[0].listtransactions(), {"txid": txid_2}, {"bip125-replaceable":"no"}) + assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_2}, {"bip125-replaceable":"no"}) # Tx3 will opt-in to RBF utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[0], txid_2) @@ -171,9 +150,9 @@ def get_unconfirmed_utxo_entry(node, txid_to_match): txid_3 = self.nodes[0].sendrawtransaction(tx3_signed) assert(is_opt_in(self.nodes[0], txid_3)) - check_array_result(self.nodes[0].listtransactions(), {"txid": txid_3}, {"bip125-replaceable":"yes"}) + assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_3}, {"bip125-replaceable":"yes"}) sync_mempools(self.nodes) - check_array_result(self.nodes[1].listtransactions(), {"txid": txid_3}, {"bip125-replaceable":"yes"}) + assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_3}, {"bip125-replaceable":"yes"}) # Tx4 will chain off tx3. Doesn't signal itself, but depends on one # that does. @@ -185,9 +164,9 @@ def get_unconfirmed_utxo_entry(node, txid_to_match): txid_4 = self.nodes[1].sendrawtransaction(tx4_signed) assert(not is_opt_in(self.nodes[1], txid_4)) - check_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"yes"}) + assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"yes"}) sync_mempools(self.nodes) - check_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"yes"}) + assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"yes"}) # Replace tx3, and check that tx4 becomes unknown tx3_b = tx3_modified @@ -197,9 +176,9 @@ def get_unconfirmed_utxo_entry(node, txid_to_match): txid_3b = self.nodes[0].sendrawtransaction(tx3_b_signed, True) assert(is_opt_in(self.nodes[0], txid_3b)) - check_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"unknown"}) + assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"unknown"}) sync_mempools(self.nodes) - check_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"unknown"}) + assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"unknown"}) # Check gettransaction as well: for n in self.nodes[0:2]: diff --git a/qa/rpc-tests/receivedby.py b/qa/rpc-tests/receivedby.py index 606426b394199..7d8231f5e47cf 100755 --- a/qa/rpc-tests/receivedby.py +++ b/qa/rpc-tests/receivedby.py @@ -25,32 +25,6 @@ def get_sub_array_from_array(object_array, to_match): return item return [] -def check_array_result(object_array, to_match, expected, should_not_find = False): - """ - Pass in array of JSON objects, a dictionary with key/value pairs - to match against, and another dictionary with expected key/value - pairs. - If the should_not_find flag is true, to_match should not be found in object_array - """ - if should_not_find == True: - expected = { } - num_matched = 0 - for item in object_array: - all_match = True - for key,value in to_match.items(): - if item[key] != value: - all_match = False - if not all_match: - continue - for key,value in expected.items(): - if item[key] != value: - raise AssertionError("%s : expected %s=%s"%(str(item), str(key), str(value))) - num_matched = num_matched+1 - if num_matched == 0 and should_not_find != True: - raise AssertionError("No objects matched %s"%(str(to_match))) - if num_matched > 0 and should_not_find == True: - raise AssertionError("Objects was matched %s"%(str(to_match))) - class ReceivedByTest(BitcoinTestFramework): def setup_nodes(self): @@ -68,26 +42,26 @@ def run_test(self): self.sync_all() #Check not listed in listreceivedbyaddress because has 0 confirmations - check_array_result(self.nodes[1].listreceivedbyaddress(), + assert_array_result(self.nodes[1].listreceivedbyaddress(), {"address":addr}, { }, True) #Bury Tx under 10 block so it will be returned by listreceivedbyaddress self.nodes[1].generate(10) self.sync_all() - check_array_result(self.nodes[1].listreceivedbyaddress(), + assert_array_result(self.nodes[1].listreceivedbyaddress(), {"address":addr}, {"address":addr, "account":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]}) #With min confidence < 10 - check_array_result(self.nodes[1].listreceivedbyaddress(5), + assert_array_result(self.nodes[1].listreceivedbyaddress(5), {"address":addr}, {"address":addr, "account":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]}) #With min confidence > 10, should not find Tx - check_array_result(self.nodes[1].listreceivedbyaddress(11),{"address":addr},{ },True) + assert_array_result(self.nodes[1].listreceivedbyaddress(11),{"address":addr},{ },True) #Empty Tx addr = self.nodes[1].getnewaddress() - check_array_result(self.nodes[1].listreceivedbyaddress(0,True), + assert_array_result(self.nodes[1].listreceivedbyaddress(0,True), {"address":addr}, {"address":addr, "account":"", "amount":0, "confirmations":0, "txids":[]}) @@ -131,7 +105,7 @@ def run_test(self): self.sync_all() # listreceivedbyaccount should return received_by_account_json because of 0 confirmations - check_array_result(self.nodes[1].listreceivedbyaccount(), + assert_array_result(self.nodes[1].listreceivedbyaccount(), {"account":account}, received_by_account_json) @@ -143,7 +117,7 @@ def run_test(self): self.nodes[1].generate(10) self.sync_all() # listreceivedbyaccount should return updated account balance - check_array_result(self.nodes[1].listreceivedbyaccount(), + assert_array_result(self.nodes[1].listreceivedbyaccount(), {"account":account}, {"account":received_by_account_json["account"], "amount":(received_by_account_json["amount"] + Decimal("0.1"))}) diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index 8b720b54a1a3d..27891f7f4c383 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -478,6 +478,35 @@ def assert_is_hash_string(string, length=64): raise AssertionError( "String %r contains invalid characters for a hash." % string) +def assert_array_result(object_array, to_match, expected, should_not_find = False): + """ + Pass in array of JSON objects, a dictionary with key/value pairs + to match against, and another dictionary with expected key/value + pairs. + If the should_not_find flag is true, to_match should not be found + in object_array + """ + if should_not_find == True: + expected = { } + num_matched = 0 + for item in object_array: + all_match = True + for key,value in to_match.items(): + if item[key] != value: + all_match = False + if not all_match: + continue + elif should_not_find == True: + num_matched = num_matched+1 + for key,value in expected.items(): + if item[key] != value: + raise AssertionError("%s : expected %s=%s"%(str(item), str(key), str(value))) + num_matched = num_matched+1 + if num_matched == 0 and should_not_find != True: + raise AssertionError("No objects matched %s"%(str(to_match))) + if num_matched > 0 and should_not_find == True: + raise AssertionError("Objects were found %s"%(str(to_match))) + def satoshi_round(amount): return Decimal(amount).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN) From 5d217decc1145823a3c126658c82c60cf7dbfec8 Mon Sep 17 00:00:00 2001 From: Joao Fonseca Date: Tue, 19 Apr 2016 12:28:37 +0100 Subject: [PATCH 0170/1802] Add test to check spendable and unspendable UTXO on RPC listunspent --- qa/rpc-tests/wallet.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py index 8fdcea50b6329..555f836482d20 100755 --- a/qa/rpc-tests/wallet.py +++ b/qa/rpc-tests/wallet.py @@ -32,6 +32,12 @@ def setup_network(self, split=False): self.sync_all() def run_test (self): + + # Check that there's no UTXO on none of the nodes + assert_equal(len(self.nodes[0].listunspent()), 0) + assert_equal(len(self.nodes[1].listunspent()), 0) + assert_equal(len(self.nodes[2].listunspent()), 0) + print "Mining blocks..." self.nodes[0].generate(1) @@ -48,6 +54,11 @@ def run_test (self): assert_equal(self.nodes[1].getbalance(), 50) assert_equal(self.nodes[2].getbalance(), 0) + # Check that only first and second nodes have UTXOs + assert_equal(len(self.nodes[0].listunspent()), 1) + assert_equal(len(self.nodes[1].listunspent()), 1) + assert_equal(len(self.nodes[2].listunspent()), 0) + # Send 21 BTC from 0 to 2 using sendtoaddress call. self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11) self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10) @@ -259,6 +270,32 @@ def run_test (self): except JSONRPCException as e: assert("not an integer" in e.error['message']) + # Import address and private key to check correct behavior of spendable unspents + # 1. Send some coins to generate new UTXO + address_to_import = self.nodes[2].getnewaddress() + txid = self.nodes[0].sendtoaddress(address_to_import, 1) + self.nodes[0].generate(1) + self.sync_all() + + # 2. Import address from node2 to node1 + self.nodes[1].importaddress(address_to_import) + + # 3. Validate that the imported address is watch-only on node1 + assert(self.nodes[1].validateaddress(address_to_import)["iswatchonly"]) + + # 4. Check that the unspents after import are not spendable + assert_array_result(self.nodes[1].listunspent(), + {"address": address_to_import}, + {"spendable": False}) + + # 5. Import private key of the previously imported address on node1 + priv_key = self.nodes[2].dumpprivkey(address_to_import) + self.nodes[1].importprivkey(priv_key) + + # 6. Check that the unspents are now spendable on node1 + assert_array_result(self.nodes[1].listunspent(), + {"address": address_to_import}, + {"spendable": True}) # Mine a block from node0 to an address from node1 cbAddr = self.nodes[1].getnewaddress() From 0b25a9fb42d5df54ea35ddb2bb4837e1e29355fd Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 29 Mar 2016 14:30:02 +0200 Subject: [PATCH 0171/1802] [ZMQ] append a message sequence number to every ZMQ notification --- contrib/zmq/zmq_sub.py | 14 +++++++++----- doc/release-notes.md | 9 +++++++++ doc/zmq.md | 5 +++++ qa/rpc-tests/zmq_test.py | 13 +++++++++++++ src/zmq/zmqpublishnotifier.cpp | 29 +++++++++++++++++++++-------- src/zmq/zmqpublishnotifier.h | 12 ++++++++++++ 6 files changed, 69 insertions(+), 13 deletions(-) diff --git a/contrib/zmq/zmq_sub.py b/contrib/zmq/zmq_sub.py index decf29d42a4c1..6268123dd8e53 100755 --- a/contrib/zmq/zmq_sub.py +++ b/contrib/zmq/zmq_sub.py @@ -3,6 +3,7 @@ import array import binascii import zmq +import struct port = 28332 @@ -19,18 +20,21 @@ msg = zmqSubSocket.recv_multipart() topic = str(msg[0]) body = msg[1] - + sequence = "Unknown"; + if len(msg[-1]) == 4: + msgSequence = struct.unpack('GetBlockHash(); @@ -130,8 +147,7 @@ bool CZMQPublishHashBlockNotifier::NotifyBlock(const CBlockIndex *pindex) char data[32]; for (unsigned int i = 0; i < 32; i++) data[31 - i] = hash.begin()[i]; - int rc = zmq_send_multipart(psocket, MSG_HASHBLOCK, 9, data, 32, 0); - return rc == 0; + return SendMessage(MSG_HASHBLOCK, data, 32); } bool CZMQPublishHashTransactionNotifier::NotifyTransaction(const CTransaction &transaction) @@ -141,8 +157,7 @@ bool CZMQPublishHashTransactionNotifier::NotifyTransaction(const CTransaction &t char data[32]; for (unsigned int i = 0; i < 32; i++) data[31 - i] = hash.begin()[i]; - int rc = zmq_send_multipart(psocket, MSG_HASHTX, 6, data, 32, 0); - return rc == 0; + return SendMessage(MSG_HASHTX, data, 32); } bool CZMQPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex) @@ -163,8 +178,7 @@ bool CZMQPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex) ss << block; } - int rc = zmq_send_multipart(psocket, MSG_RAWBLOCK, 8, &(*ss.begin()), ss.size(), 0); - return rc == 0; + return SendMessage(MSG_RAWBLOCK, &(*ss.begin()), ss.size()); } bool CZMQPublishRawTransactionNotifier::NotifyTransaction(const CTransaction &transaction) @@ -173,6 +187,5 @@ bool CZMQPublishRawTransactionNotifier::NotifyTransaction(const CTransaction &tr LogPrint("zmq", "zmq: Publish rawtx %s\n", hash.GetHex()); CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss << transaction; - int rc = zmq_send_multipart(psocket, MSG_RAWTX, 5, &(*ss.begin()), ss.size(), 0); - return rc == 0; + return SendMessage(MSG_RAWTX, &(*ss.begin()), ss.size()); } diff --git a/src/zmq/zmqpublishnotifier.h b/src/zmq/zmqpublishnotifier.h index 44d5cbea67d20..22f02a3d0dbb8 100644 --- a/src/zmq/zmqpublishnotifier.h +++ b/src/zmq/zmqpublishnotifier.h @@ -11,7 +11,19 @@ class CBlockIndex; class CZMQAbstractPublishNotifier : public CZMQAbstractNotifier { +private: + uint32_t nSequence; //! upcounting per message sequence number + public: + + /* send zmq multipart message + parts: + * command + * data + * message sequence number + */ + bool SendMessage(const char *command, const void* data, size_t size); + bool Initialize(void *pcontext); void Shutdown(); }; From fa10ce6a6dd0a6f00f6528e12f1de7a7fcb08928 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Tue, 19 Apr 2016 16:10:19 +0200 Subject: [PATCH 0172/1802] Move ui_interface.cpp to libbitcoin_server_a_SOURCES It is only needed by bitcoind and bitcoin-qt --- src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index 10aa550a02bef..585463fc13988 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -203,6 +203,7 @@ libbitcoin_server_a_SOURCES = \ torcontrol.cpp \ txdb.cpp \ txmempool.cpp \ + ui_interface.cpp \ validationinterface.cpp \ versionbits.cpp \ $(BITCOIN_CORE_H) @@ -323,7 +324,6 @@ libbitcoin_util_a_SOURCES = \ rpc/protocol.cpp \ support/cleanse.cpp \ sync.cpp \ - ui_interface.cpp \ util.cpp \ utilmoneystr.cpp \ utilstrencodings.cpp \ From 764d2377727c8945d648a018492a61add4fcf042 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Tim=C3=B3n?= Date: Wed, 6 Apr 2016 16:36:32 +0200 Subject: [PATCH 0173/1802] Globals: Explicitly pass const CChainParams& to UpdateTip() --- src/main.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index a94d52f8954e8..aaf5f9ae64845 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2570,8 +2570,7 @@ void PruneAndFlush() { } /** Update chainActive and related internal data structures. */ -void static UpdateTip(CBlockIndex *pindexNew) { - const CChainParams& chainParams = Params(); +void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { chainActive.SetTip(pindexNew); // New best block @@ -2631,6 +2630,7 @@ void static UpdateTip(CBlockIndex *pindexNew) { /** Disconnect chainActive's tip. You probably want to call mempool.removeForReorg and manually re-limit mempool size after this, with cs_main held. */ bool static DisconnectTip(CValidationState& state, const Consensus::Params& consensusParams) { + const CChainParams& chainparams = Params(); // TODO replace consensusParams parameter CBlockIndex *pindexDelete = chainActive.Tip(); assert(pindexDelete); // Read block from disk. @@ -2668,7 +2668,7 @@ bool static DisconnectTip(CValidationState& state, const Consensus::Params& cons // block that were added back and cleans up the mempool state. mempool.UpdateTransactionsFromBlock(vHashUpdate); // Update chainActive and related variables. - UpdateTip(pindexDelete->pprev); + UpdateTip(pindexDelete->pprev, chainparams); // Let wallets know transactions went from 1-confirmed to // 0-confirmed or conflicted: BOOST_FOREACH(const CTransaction &tx, block.vtx) { @@ -2727,7 +2727,7 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, list txConflicted; mempool.removeForBlock(pblock->vtx, pindexNew->nHeight, txConflicted, !IsInitialBlockDownload()); // Update chainActive & related variables. - UpdateTip(pindexNew); + UpdateTip(pindexNew, chainparams); // Tell wallet about transactions that went from mempool // to conflicted: BOOST_FOREACH(const CTransaction &tx, txConflicted) { From d0a6353dec48f365c38de3c76b42f67eda737ed5 Mon Sep 17 00:00:00 2001 From: face Date: Sun, 17 Apr 2016 10:58:50 +0300 Subject: [PATCH 0174/1802] Pass CChainParams to DisconnectTip() --- src/main.cpp | 11 +++++------ src/main.h | 2 +- src/rpc/blockchain.cpp | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index aaf5f9ae64845..518393000162e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2628,14 +2628,13 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { } /** Disconnect chainActive's tip. You probably want to call mempool.removeForReorg and manually re-limit mempool size after this, with cs_main held. */ -bool static DisconnectTip(CValidationState& state, const Consensus::Params& consensusParams) +bool static DisconnectTip(CValidationState& state, const CChainParams& chainparams) { - const CChainParams& chainparams = Params(); // TODO replace consensusParams parameter CBlockIndex *pindexDelete = chainActive.Tip(); assert(pindexDelete); // Read block from disk. CBlock block; - if (!ReadBlockFromDisk(block, pindexDelete, consensusParams)) + if (!ReadBlockFromDisk(block, pindexDelete, chainparams.GetConsensus())) return AbortNode(state, "Failed to read block"); // Apply the block atomically to the chain state. int64_t nStart = GetTimeMicros(); @@ -2828,7 +2827,7 @@ static bool ActivateBestChainStep(CValidationState& state, const CChainParams& c // Disconnect active blocks which are no longer in the best chain. bool fBlocksDisconnected = false; while (chainActive.Tip() && chainActive.Tip() != pindexFork) { - if (!DisconnectTip(state, chainparams.GetConsensus())) + if (!DisconnectTip(state, chainparams)) return false; fBlocksDisconnected = true; } @@ -2973,7 +2972,7 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, return true; } -bool InvalidateBlock(CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex *pindex) +bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex) { AssertLockHeld(cs_main); @@ -2989,7 +2988,7 @@ bool InvalidateBlock(CValidationState& state, const Consensus::Params& consensus setBlockIndexCandidates.erase(pindexWalk); // ActivateBestChain considers blocks already in chainActive // unconditionally valid already, so force disconnect away from it. - if (!DisconnectTip(state, consensusParams)) { + if (!DisconnectTip(state, chainparams)) { mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS); return false; } diff --git a/src/main.h b/src/main.h index 0962f44e9439e..e4c98a96964ae 100644 --- a/src/main.h +++ b/src/main.h @@ -536,7 +536,7 @@ class CVerifyDB { CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator); /** Mark a block as invalid. */ -bool InvalidateBlock(CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex *pindex); +bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex); /** Remove invalidity status from a block and its descendants. */ bool ReconsiderBlock(CValidationState& state, CBlockIndex *pindex); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index b85b2f6b57e19..2670a85c4ffeb 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -928,7 +928,7 @@ UniValue invalidateblock(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); CBlockIndex* pblockindex = mapBlockIndex[hash]; - InvalidateBlock(state, Params().GetConsensus(), pblockindex); + InvalidateBlock(state, Params(), pblockindex); } if (state.IsValid()) { From a4625acbf8afbe3f698e8dc7936312c9d2b65d22 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 17 Feb 2016 14:35:35 -0500 Subject: [PATCH 0175/1802] leveldb: integrate leveldb into our buildsystem leveldb's buildsystem causes us a few problems: - breaks out-of-tree builds - forces flags used for some tools - limits cross builds Rather than continuing to add wrappers around it, simply integrate it into our build. --- configure.ac | 22 ++++++++-- src/Makefile.am | 22 +++------- src/Makefile.leveldb.include | 81 ++++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+), 19 deletions(-) create mode 100644 src/Makefile.leveldb.include diff --git a/configure.ac b/configure.ac index 6e463dfc5540d..03b90521045ed 100644 --- a/configure.ac +++ b/configure.ac @@ -267,7 +267,7 @@ case $host in fi CPPFLAGS="$CPPFLAGS -D_MT -DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB" - LEVELDB_TARGET_FLAGS="TARGET_OS=OS_WINDOWS_CROSSCOMPILE" + LEVELDB_TARGET_FLAGS="-DOS_WINDOWS" if test "x$CXXFLAGS_overridden" = "xno"; then CXXFLAGS="$CXXFLAGS -w" fi @@ -289,7 +289,7 @@ case $host in ;; *darwin*) TARGET_OS=darwin - LEVELDB_TARGET_FLAGS="TARGET_OS=Darwin" + LEVELDB_TARGET_FLAGS="-DOS_MACOSX" if test x$cross_compiling != xyes; then BUILD_OS=darwin AC_CHECK_PROG([PORT],port, port) @@ -354,9 +354,11 @@ case $host in OBJCXXFLAGS="$CXXFLAGS" ;; *linux*) - TARGET_OS=linux + LEVELDB_TARGET_FLAGS="-DOS_LINUX" ;; *) + OTHER_OS=`echo ${host_os} | awk '{print toupper($0)}'` + LEVELDB_TARGET_FLAGS="-DOS_${OTHER_OS}" ;; esac @@ -541,6 +543,18 @@ if test x$use_reduce_exports = xyes; then [AC_MSG_ERROR([Cannot set default symbol visibility. Use --disable-reduce-exports.])]) fi +dnl This can go away when we require c++11 +TEMP_CXXFLAGS="$CXXFLAGS" +CXXFLAGS="$CXXFLAGS -std=c++0x" +AC_MSG_CHECKING(for c++11 atomics) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #include + ]],[[]])], + [ AC_MSG_RESULT(yes); LEVELDB_ATOMIC_CPPFLAGS="-DLEVELDB_ATOMIC_PRESENT"; LEVELDB_ATOMIC_CXXFLAGS="-std=c++0x"], + [ AC_MSG_RESULT(no)] +) +CXXFLAGS="$TEMP_CXXFLAGS" + LEVELDB_CPPFLAGS= LIBLEVELDB= LIBMEMENV= @@ -1043,6 +1057,8 @@ AC_SUBST(TESTDEFS) AC_SUBST(LEVELDB_TARGET_FLAGS) AC_SUBST(MINIUPNPC_CPPFLAGS) AC_SUBST(MINIUPNPC_LIBS) +AC_SUBST(LEVELDB_ATOMIC_CPPFLAGS) +AC_SUBST(LEVELDB_ATOMIC_CXXFLAGS) AC_CONFIG_FILES([Makefile src/Makefile share/setup.nsi share/qt/Info.plist src/test/buildenv.py]) AC_CONFIG_FILES([qa/pull-tester/run-bitcoind-for-test.sh],[chmod +x qa/pull-tester/run-bitcoind-for-test.sh]) AC_CONFIG_FILES([qa/pull-tester/tests_config.py],[chmod +x qa/pull-tester/tests_config.py]) diff --git a/src/Makefile.am b/src/Makefile.am index c1912dafc53bb..3c056386fac7b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -3,6 +3,7 @@ DIST_SUBDIRS = secp256k1 univalue AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS) $(HARDENED_LDFLAGS) AM_CXXFLAGS = $(HARDENED_CXXFLAGS) AM_CPPFLAGS = $(HARDENED_CPPFLAGS) +EXTRA_LIBRARIES = if EMBEDDED_UNIVALUE LIBUNIVALUE = univalue/libunivalue.la @@ -13,21 +14,6 @@ else LIBUNIVALUE = $(UNIVALUE_LIBS) endif -if EMBEDDED_LEVELDB -LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/include -LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/helpers/memenv -LIBLEVELDB += $(builddir)/leveldb/libleveldb.a -LIBMEMENV += $(builddir)/leveldb/libmemenv.a - -# NOTE: This dependency is not strictly necessary, but without it make may try to build both in parallel, which breaks the LevelDB build system in a race -$(LIBLEVELDB): $(LIBMEMENV) - -$(LIBLEVELDB) $(LIBMEMENV): - @echo "Building LevelDB ..." && $(MAKE) -C $(@D) $(@F) CXX="$(CXX)" \ - CC="$(CC)" PLATFORM=$(TARGET_OS) AR="$(AR)" $(LEVELDB_TARGET_FLAGS) \ - OPT="$(AM_CXXFLAGS) $(PIE_FLAGS) $(CXXFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) -D__STDC_LIMIT_MACROS" -endif - BITCOIN_CONFIG_INCLUDES=-I$(builddir)/config BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) $(SSL_CFLAGS) @@ -49,7 +35,7 @@ $(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*) # Make is not made aware of per-object dependencies to avoid limiting building parallelization # But to build the less dependent modules first, we manually select their order here: -EXTRA_LIBRARIES = \ +EXTRA_LIBRARIES += \ crypto/libbitcoin_crypto.a \ libbitcoin_util.a \ libbitcoin_common.a \ @@ -482,6 +468,10 @@ endif @test -f $(PROTOC) $(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$( Date: Tue, 19 Apr 2016 13:07:16 -0700 Subject: [PATCH 0176/1802] Replace memcmp with std::equal in CScript::FindAndDelete Function is stl; std::equal just makes more sense. --- src/script/script.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/script/script.h b/src/script/script.h index d2a68a07ba149..ef3af21d6a3cc 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -574,7 +574,7 @@ class CScript : public CScriptBase opcodetype opcode; do { - while (end() - pc >= (long)b.size() && memcmp(&pc[0], &b[0], b.size()) == 0) + while (end() - pc >= (long)b.size() && std::equal(b.begin(), b.end(), pc)) { pc = erase(pc, pc + b.size()); ++nFound; From c0f660c3a39e3b6d75d9a6bf8a9824c347c321b8 Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Tue, 19 Apr 2016 13:13:46 -0700 Subject: [PATCH 0177/1802] Replace c-style cast with c++ style static_cast. --- src/script/script.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/script/script.h b/src/script/script.h index ef3af21d6a3cc..0503b39a76f54 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -574,7 +574,7 @@ class CScript : public CScriptBase opcodetype opcode; do { - while (end() - pc >= (long)b.size() && std::equal(b.begin(), b.end(), pc)) + while (static_cast(end() - pc) >= b.size() && std::equal(b.begin(), b.end(), pc)) { pc = erase(pc, pc + b.size()); ++nFound; From e2a30bc9a9f7d2969e52632f8e8942a4e72f4ba6 Mon Sep 17 00:00:00 2001 From: Gavin Andresen Date: Wed, 3 Feb 2016 16:15:18 -0500 Subject: [PATCH 0178/1802] Unit test for CScript::FindAndDelete --- src/test/script_tests.cpp | 117 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index d42187f9127c2..5e9711a4a7e26 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -1051,4 +1051,121 @@ BOOST_AUTO_TEST_CASE(script_GetScriptAsm) BOOST_CHECK_EQUAL(derSig + "83 " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "83")) << vchPubKey)); } +static CScript +ScriptFromHex(const char* hex) +{ + std::vector data = ParseHex(hex); + return CScript(data.begin(), data.end()); +} + + +BOOST_AUTO_TEST_CASE(script_FindAndDelete) +{ + // Exercise the FindAndDelete functionality + CScript s; + CScript d; + CScript expect; + + s = CScript() << OP_1 << OP_2; + d = CScript(); // delete nothing should be a no-op + expect = s; + BOOST_CHECK_EQUAL(s.FindAndDelete(d), 0); + BOOST_CHECK(s == expect); + + s = CScript() << OP_1 << OP_2 << OP_3; + d = CScript() << OP_2; + expect = CScript() << OP_1 << OP_3; + BOOST_CHECK_EQUAL(s.FindAndDelete(d), 1); + BOOST_CHECK(s == expect); + + s = CScript() << OP_3 << OP_1 << OP_3 << OP_3 << OP_4 << OP_3; + d = CScript() << OP_3; + expect = CScript() << OP_1 << OP_4; + BOOST_CHECK_EQUAL(s.FindAndDelete(d), 4); + BOOST_CHECK(s == expect); + + s = ScriptFromHex("0302ff03"); // PUSH 0x02ff03 onto stack + d = ScriptFromHex("0302ff03"); + expect = CScript(); + BOOST_CHECK_EQUAL(s.FindAndDelete(d), 1); + BOOST_CHECK(s == expect); + + s = ScriptFromHex("0302ff030302ff03"); // PUSH 0x2ff03 PUSH 0x2ff03 + d = ScriptFromHex("0302ff03"); + expect = CScript(); + BOOST_CHECK_EQUAL(s.FindAndDelete(d), 2); + BOOST_CHECK(s == expect); + + s = ScriptFromHex("0302ff030302ff03"); + d = ScriptFromHex("02"); + expect = s; // FindAndDelete matches entire opcodes + BOOST_CHECK_EQUAL(s.FindAndDelete(d), 0); + BOOST_CHECK(s == expect); + + s = ScriptFromHex("0302ff030302ff03"); + d = ScriptFromHex("ff"); + expect = s; + BOOST_CHECK_EQUAL(s.FindAndDelete(d), 0); + BOOST_CHECK(s == expect); + + // This is an odd edge case: strip of the push-three-bytes + // prefix, leaving 02ff03 which is push-two-bytes: + s = ScriptFromHex("0302ff030302ff03"); + d = ScriptFromHex("03"); + expect = CScript() << ParseHex("ff03") << ParseHex("ff03"); + BOOST_CHECK_EQUAL(s.FindAndDelete(d), 2); + BOOST_CHECK(s == expect); + + // Byte sequence that spans multiple opcodes: + s = ScriptFromHex("02feed5169"); // PUSH(0xfeed) OP_1 OP_VERIFY + d = ScriptFromHex("feed51"); + expect = s; + BOOST_CHECK_EQUAL(s.FindAndDelete(d), 0); // doesn't match 'inside' opcodes + BOOST_CHECK(s == expect); + + s = ScriptFromHex("02feed5169"); // PUSH(0xfeed) OP_1 OP_VERIFY + d = ScriptFromHex("02feed51"); + expect = ScriptFromHex("69"); + BOOST_CHECK_EQUAL(s.FindAndDelete(d), 1); + BOOST_CHECK(s == expect); + + s = ScriptFromHex("516902feed5169"); + d = ScriptFromHex("feed51"); + expect = s; + BOOST_CHECK_EQUAL(s.FindAndDelete(d), 0); + BOOST_CHECK(s == expect); + + s = ScriptFromHex("516902feed5169"); + d = ScriptFromHex("02feed51"); + expect = ScriptFromHex("516969"); + BOOST_CHECK_EQUAL(s.FindAndDelete(d), 1); + BOOST_CHECK(s == expect); + + s = CScript() << OP_0 << OP_0 << OP_1 << OP_1; + d = CScript() << OP_0 << OP_1; + expect = CScript() << OP_0 << OP_1; // FindAndDelete is single-pass + BOOST_CHECK_EQUAL(s.FindAndDelete(d), 1); + BOOST_CHECK(s == expect); + + s = CScript() << OP_0 << OP_0 << OP_1 << OP_0 << OP_1 << OP_1; + d = CScript() << OP_0 << OP_1; + expect = CScript() << OP_0 << OP_1; // FindAndDelete is single-pass + BOOST_CHECK_EQUAL(s.FindAndDelete(d), 2); + BOOST_CHECK(s == expect); + + // Another weird edge case: + // End with invalid push (not enough data)... + s = ScriptFromHex("0003feed"); + d = ScriptFromHex("03feed"); // ... can remove the invalid push + expect = ScriptFromHex("00"); + BOOST_CHECK_EQUAL(s.FindAndDelete(d), 1); + BOOST_CHECK(s == expect); + + s = ScriptFromHex("0003feed"); + d = ScriptFromHex("00"); + expect = ScriptFromHex("03feed"); + BOOST_CHECK_EQUAL(s.FindAndDelete(d), 1); + BOOST_CHECK(s == expect); +} + BOOST_AUTO_TEST_SUITE_END() From f2d3ba73860e875972738d1da1507124d0971ae5 Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Mon, 4 Apr 2016 02:36:47 +0000 Subject: [PATCH 0179/1802] Eliminate TX trickle bypass, sort TX invs for privacy and priority. Previously Bitcoin would send 1/4 of transactions out to all peers instantly. This causes high overhead because it makes >80% of INVs size 1. Doing so harms privacy, because it limits the amount of source obscurity a transaction can receive. These randomized broadcasts also disobeyed transaction dependencies and required use of the orphan pool. Because the orphan pool is so small this leads to poor propagation for dependent transactions. When the bypass wasn't in effect, transactions were sent in the order they were received. This avoided creating orphans but undermines privacy fairly significantly. This commit: Eliminates the bypass. The bypass is replaced by halving the average delay for outbound peers. Sorts candidate transactions for INV by their topological depth then by their feerate (then hash); removing the information leakage and providing priority service to higher fee transactions. Limits the amount of transactions sent in a single INV to 7tx/sec (and twice that for outbound); this limits the harm of low fee transaction floods, gives faster relay service to higher fee transactions. The 7 sounds lower than it really is because received advertisements need not be sent, and because the aggregate rate is multipled by the number of peers. --- src/main.cpp | 60 ++++++++++++++++++++++++++++------------------- src/main.h | 9 ++++--- src/txmempool.cpp | 15 ++++++++++++ src/txmempool.h | 1 + 4 files changed, 58 insertions(+), 27 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index a94d52f8954e8..4a28bbb00c422 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5560,6 +5560,29 @@ bool ProcessMessages(CNode* pfrom) return fOk; } +class CompareInvMempoolOrder +{ + CTxMemPool *mp; +public: + CompareInvMempoolOrder(CTxMemPool *mempool) + { + mp = mempool; + } + + bool operator()(const CInv &a, const CInv &b) + { + if (a.type != MSG_TX && b.type != MSG_TX) { + return false; + } else { + if (a.type != MSG_TX) { + return true; + } else if (b.type != MSG_TX) { + return false; + } + return mp->CompareDepthAndScore(a.hash, b.hash); + } + } +}; bool SendMessages(CNode* pto) { @@ -5790,42 +5813,31 @@ bool SendMessages(CNode* pto) bool fSendTrickle = pto->fWhitelisted; if (pto->nNextInvSend < nNow) { fSendTrickle = true; - pto->nNextInvSend = PoissonNextSend(nNow, AVG_INVENTORY_BROADCAST_INTERVAL); + // Use half the delay for outbound peers, as their is less privacy concern for them. + pto->nNextInvSend = PoissonNextSend(nNow, INVENTORY_BROADCAST_INTERVAL >> !pto->fInbound); } LOCK(pto->cs_inventory); - vInv.reserve(std::min(1000, pto->vInventoryToSend.size())); + if (fSendTrickle && pto->vInventoryToSend.size() > 1) { + // Topologically and fee-rate sort the inventory we send for privacy and priority reasons. + CompareInvMempoolOrder compareInvMempoolOrder(&mempool); + std::stable_sort(pto->vInventoryToSend.begin(), pto->vInventoryToSend.end(), compareInvMempoolOrder); + } + vInv.reserve(std::min(INVENTORY_BROADCAST_MAX, pto->vInventoryToSend.size())); vInvWait.reserve(pto->vInventoryToSend.size()); BOOST_FOREACH(const CInv& inv, pto->vInventoryToSend) { if (inv.type == MSG_TX && pto->filterInventoryKnown.contains(inv.hash)) continue; - - // trickle out tx inv to protect privacy - if (inv.type == MSG_TX && !fSendTrickle) - { - // 1/4 of tx invs blast to all immediately - static uint256 hashSalt; - if (hashSalt.IsNull()) - hashSalt = GetRandHash(); - uint256 hashRand = ArithToUint256(UintToArith256(inv.hash) ^ UintToArith256(hashSalt)); - hashRand = Hash(BEGIN(hashRand), END(hashRand)); - bool fTrickleWait = ((UintToArith256(hashRand) & 3) != 0); - - if (fTrickleWait) - { - vInvWait.push_back(inv); - continue; - } + // No reason to drain out at many times the network's capacity, + // especially since we have many peers and some will draw much shorter delays. + if (vInv.size() >= INVENTORY_BROADCAST_MAX || (inv.type == MSG_TX && !fSendTrickle)) { + vInvWait.push_back(inv); + continue; } pto->filterInventoryKnown.insert(inv.hash); vInv.push_back(inv); - if (vInv.size() >= 1000) - { - pto->PushMessage(NetMsgType::INV, vInv); - vInv.clear(); - } } pto->vInventoryToSend = vInvWait; } diff --git a/src/main.h b/src/main.h index 0962f44e9439e..4372c16a421c8 100644 --- a/src/main.h +++ b/src/main.h @@ -99,9 +99,12 @@ static const unsigned int MAX_REJECT_MESSAGE_LENGTH = 111; static const unsigned int AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL = 24 * 24 * 60; /** Average delay between peer address broadcasts in seconds. */ static const unsigned int AVG_ADDRESS_BROADCAST_INTERVAL = 30; -/** Average delay between trickled inventory broadcasts in seconds. - * Blocks, whitelisted receivers, and a random 25% of transactions bypass this. */ -static const unsigned int AVG_INVENTORY_BROADCAST_INTERVAL = 5; +/** Average delay between trickled inventory transmissions in seconds. + * Blocks and whitelisted receivers bypass this, outbound peers get half this delay. */ +static const unsigned int INVENTORY_BROADCAST_INTERVAL = 5; +/** Maximum number of inventory items to send per transmission. + * Limits the impact of low-fee transaction floods. */ +static const unsigned int INVENTORY_BROADCAST_MAX = 7 * INVENTORY_BROADCAST_INTERVAL; /** Average delay between feefilter broadcasts in seconds. */ static const unsigned int AVG_FEEFILTER_BROADCAST_INTERVAL = 10 * 60; /** Maximum feefilter broadcast delay after significant change. */ diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 52c7793118331..3aba578fac99e 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -752,6 +752,21 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const assert(innerUsage == cachedInnerUsage); } +bool CTxMemPool::CompareDepthAndScore(const uint256& hasha, const uint256& hashb) +{ + LOCK(cs); + indexed_transaction_set::const_iterator i = mapTx.find(hasha); + if (i == mapTx.end()) return false; + indexed_transaction_set::const_iterator j = mapTx.find(hashb); + if (j == mapTx.end()) return true; + uint64_t counta = i->GetCountWithAncestors(); + uint64_t countb = j->GetCountWithAncestors(); + if (counta == countb) { + return CompareTxMemPoolEntryByScore()(*i, *j); + } + return counta < countb; +} + void CTxMemPool::queryHashes(vector& vtxid) { vtxid.clear(); diff --git a/src/txmempool.h b/src/txmempool.h index de4ba0b371a42..e4934336c2cdc 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -511,6 +511,7 @@ class CTxMemPool std::list& conflicts, bool fCurrentEstimate = true); void clear(); void _clear(); //lock free + bool CompareDepthAndScore(const uint256& hasha, const uint256& hashb); void queryHashes(std::vector& vtxid); void pruneSpent(const uint256& hash, CCoins &coins); unsigned int GetTransactionsUpdated() const; From 220f950ab1302f8f8c0bb5b9c818f3d6569796bd Mon Sep 17 00:00:00 2001 From: Yuri Zhykin Date: Wed, 20 Apr 2016 00:03:42 +0300 Subject: [PATCH 0180/1802] Fix for incorrect locking in GetPubKey() (keystore.cpp) --- src/keystore.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/keystore.cpp b/src/keystore.cpp index cc8a5733671da..d568a7435098a 100644 --- a/src/keystore.cpp +++ b/src/keystore.cpp @@ -19,6 +19,7 @@ bool CBasicKeyStore::GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) con { CKey key; if (!GetKey(address, key)) { + LOCK(cs_KeyStore); WatchKeyMap::const_iterator it = mapWatchKeys.find(address); if (it != mapWatchKeys.end()) { vchPubKeyOut = it->second; From 807fa47a1e5c9f072d7dbf549bf17f66c47dbf46 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Tue, 19 Apr 2016 16:18:38 -0400 Subject: [PATCH 0181/1802] Tests: Fix deserialization of reject messages Assume that reject messages for blocks or transactions due to reason REJECT_MALFORMED will not include the hash of the block or tx being rejected. --- qa/rpc-tests/test_framework/mininode.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index 5ee5b132757d4..af3356411471e 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -983,6 +983,7 @@ def __repr__(self): class msg_reject(object): command = b"reject" + REJECT_MALFORMED = 1 def __init__(self): self.message = b"" @@ -994,14 +995,16 @@ def deserialize(self, f): self.message = deser_string(f) self.code = struct.unpack(" Date: Tue, 19 Apr 2016 16:16:39 +0300 Subject: [PATCH 0182/1802] Explicitly pass CChainParams to ConnectBlock --- src/main.cpp | 10 +++++----- src/main.h | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 518393000162e..1015e538d5117 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2221,9 +2221,9 @@ static int64_t nTimeIndex = 0; static int64_t nTimeCallbacks = 0; static int64_t nTimeTotal = 0; -bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool fJustCheck) +bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, + CCoinsViewCache& view, const CChainParams& chainparams, bool fJustCheck) { - const CChainParams& chainparams = Params(); AssertLockHeld(cs_main); int64_t nTimeStart = GetTimeMicros(); @@ -2703,7 +2703,7 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, LogPrint("bench", " - Load block from disk: %.2fms [%.2fs]\n", (nTime2 - nTime1) * 0.001, nTimeReadFromDisk * 0.000001); { CCoinsViewCache view(pcoinsTip); - bool rv = ConnectBlock(*pblock, state, pindexNew, view); + bool rv = ConnectBlock(*pblock, state, pindexNew, view, chainparams); GetMainSignals().BlockChecked(*pblock, state); if (!rv) { if (state.IsInvalid()) @@ -3523,7 +3523,7 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, return error("%s: Consensus::CheckBlock: %s", __func__, FormatStateMessage(state)); if (!ContextualCheckBlock(block, state, pindexPrev)) return error("%s: Consensus::ContextualCheckBlock: %s", __func__, FormatStateMessage(state)); - if (!ConnectBlock(block, state, &indexDummy, viewNew, true)) + if (!ConnectBlock(block, state, &indexDummy, viewNew, chainparams, true)) return false; assert(state.IsValid()); @@ -3891,7 +3891,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, CBlock block; if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus())) return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); - if (!ConnectBlock(block, state, pindex, coins)) + if (!ConnectBlock(block, state, pindex, coins, chainparams)) return error("VerifyDB(): *** found unconnectable block at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); } } diff --git a/src/main.h b/src/main.h index e4c98a96964ae..2c9635bcf2b8f 100644 --- a/src/main.h +++ b/src/main.h @@ -458,7 +458,8 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn /** Apply the effects of this block (with given index) on the UTXO set represented by coins. * Validity checks that depend on the UTXO set are also done; ConnectBlock() * can fail if those validity checks fail (among other reasons). */ -bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false); +bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, + const CChainParams& chainparams, bool fJustCheck = false); /** Undo the effects of this block (with given index) on the UTXO set represented by coins. * In case pfClean is provided, operation will try to be tolerant about errors, and *pfClean From a98cd1fc86eac1e5e5a09830028233dbce1dae70 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 12 Apr 2016 20:38:06 -0400 Subject: [PATCH 0183/1802] net: manually resolve dns seed sources Note: Some seeds aren't actually returning an IP for their name entries, so they're being added to addrman with a source of [::]. This commit shouldn't change that behavior, for better or worse. --- src/net.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/net.cpp b/src/net.cpp index 6ab6ef819d077..7dec8fc1cf599 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1454,7 +1454,15 @@ void ThreadDNSAddressSeed() found++; } } - addrman.Add(vAdd, CNetAddr(seed.name, true)); + // TODO: The seed name resolve may fail, yielding an IP of [::], which results in + // addrman assigning the same source to results from different seeds. + // This should switch to a hard-coded stable dummy IP for each seed name, so that the + // resolve is not required at all. + if (!vIPs.empty()) { + CService seedSource; + Lookup(seed.name.c_str(), seedSource, 0, true); + addrman.Add(vAdd, seedSource); + } } } From 367569926a9b15c05ba8d56c554880b8f5614f71 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 12 Apr 2016 20:41:39 -0400 Subject: [PATCH 0184/1802] net: resolve outside of storage structures Rather than allowing CNetAddr/CService/CSubNet to launch DNS queries, require that addresses are already resolved. This greatly simplifies async resolve logic, and makes it harder to accidentally leak DNS queries. --- src/init.cpp | 7 ++++--- src/netbase.cpp | 10 ++++++---- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 3667820a21fe6..80527b782e986 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1156,10 +1156,11 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (mapArgs.count("-externalip")) { BOOST_FOREACH(const std::string& strAddr, mapMultiArgs["-externalip"]) { - CService addrLocal(strAddr, GetListenPort(), fNameLookup); - if (!addrLocal.IsValid()) + CService addrLocal; + if (Lookup(strAddr.c_str(), addrLocal, GetListenPort(), fNameLookup) && addrLocal.IsValid()) + AddLocal(addrLocal, LOCAL_MANUAL); + else return InitError(ResolveErrMsg("externalip", strAddr)); - AddLocal(CService(strAddr, GetListenPort(), fNameLookup), LOCAL_MANUAL); } } diff --git a/src/netbase.cpp b/src/netbase.cpp index 281c6bcb7fe79..1855d0a2e833b 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -614,10 +614,12 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest proxyType nameProxy; GetNameProxy(nameProxy); - CService addrResolved(CNetAddr(strDest, fNameLookup && !HaveNameProxy()), port); - if (addrResolved.IsValid()) { - addr = addrResolved; - return ConnectSocket(addr, hSocketRet, nTimeout); + CService addrResolved; + if (Lookup(strDest.c_str(), addrResolved, port, fNameLookup && !HaveNameProxy())) { + if (addrResolved.IsValid()) { + addr = addrResolved; + return ConnectSocket(addr, hSocketRet, nTimeout); + } } addr = CService("0.0.0.0:0"); From d39f5b425d8fc1bf3b7f33d35625ffd8d7a3cd77 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 12 Apr 2016 20:48:29 -0400 Subject: [PATCH 0185/1802] net: disable resolving from storage structures CNetAddr/CService/CSubnet can no longer resolve DNS. --- src/netbase.cpp | 28 ++++++++++++++-------------- src/netbase.h | 14 +++++++------- src/torcontrol.cpp | 2 +- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/netbase.cpp b/src/netbase.cpp index 1855d0a2e833b..b44a8b16e20cc 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -688,19 +688,19 @@ CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr, const uint32_t scope) scopeId = scope; } -CNetAddr::CNetAddr(const char *pszIp, bool fAllowLookup) +CNetAddr::CNetAddr(const char *pszIp) { Init(); std::vector vIP; - if (LookupHost(pszIp, vIP, 1, fAllowLookup)) + if (LookupHost(pszIp, vIP, 1, false)) *this = vIP[0]; } -CNetAddr::CNetAddr(const std::string &strIp, bool fAllowLookup) +CNetAddr::CNetAddr(const std::string &strIp) { Init(); std::vector vIP; - if (LookupHost(strIp.c_str(), vIP, 1, fAllowLookup)) + if (LookupHost(strIp.c_str(), vIP, 1, false)) *this = vIP[0]; } @@ -1123,35 +1123,35 @@ bool CService::SetSockAddr(const struct sockaddr *paddr) } } -CService::CService(const char *pszIpPort, bool fAllowLookup) +CService::CService(const char *pszIpPort) { Init(); CService ip; - if (Lookup(pszIpPort, ip, 0, fAllowLookup)) + if (Lookup(pszIpPort, ip, 0, false)) *this = ip; } -CService::CService(const char *pszIpPort, int portDefault, bool fAllowLookup) +CService::CService(const char *pszIpPort, int portDefault) { Init(); CService ip; - if (Lookup(pszIpPort, ip, portDefault, fAllowLookup)) + if (Lookup(pszIpPort, ip, portDefault, false)) *this = ip; } -CService::CService(const std::string &strIpPort, bool fAllowLookup) +CService::CService(const std::string &strIpPort) { Init(); CService ip; - if (Lookup(strIpPort.c_str(), ip, 0, fAllowLookup)) + if (Lookup(strIpPort.c_str(), ip, 0, false)) *this = ip; } -CService::CService(const std::string &strIpPort, int portDefault, bool fAllowLookup) +CService::CService(const std::string &strIpPort, int portDefault) { Init(); CService ip; - if (Lookup(strIpPort.c_str(), ip, portDefault, fAllowLookup)) + if (Lookup(strIpPort.c_str(), ip, portDefault, false)) *this = ip; } @@ -1245,7 +1245,7 @@ CSubNet::CSubNet(): memset(netmask, 0, sizeof(netmask)); } -CSubNet::CSubNet(const std::string &strSubnet, bool fAllowLookup) +CSubNet::CSubNet(const std::string &strSubnet) { size_t slash = strSubnet.find_last_of('/'); std::vector vIP; @@ -1255,7 +1255,7 @@ CSubNet::CSubNet(const std::string &strSubnet, bool fAllowLookup) memset(netmask, 255, sizeof(netmask)); std::string strAddress = strSubnet.substr(0, slash); - if (LookupHost(strAddress.c_str(), vIP, 1, fAllowLookup)) + if (LookupHost(strAddress.c_str(), vIP, 1, false)) { network = vIP[0]; if (slash != strSubnet.npos) diff --git a/src/netbase.h b/src/netbase.h index 4529f9822914c..65187a17cfd54 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -49,8 +49,8 @@ class CNetAddr public: CNetAddr(); CNetAddr(const struct in_addr& ipv4Addr); - explicit CNetAddr(const char *pszIp, bool fAllowLookup = false); - explicit CNetAddr(const std::string &strIp, bool fAllowLookup = false); + explicit CNetAddr(const char *pszIp); + explicit CNetAddr(const std::string &strIp); void Init(); void SetIP(const CNetAddr& ip); @@ -119,7 +119,7 @@ class CSubNet public: CSubNet(); - explicit CSubNet(const std::string &strSubnet, bool fAllowLookup = false); + explicit CSubNet(const std::string &strSubnet); //constructor for single ip subnet (/32 or /128) explicit CSubNet(const CNetAddr &addr); @@ -154,10 +154,10 @@ class CService : public CNetAddr CService(const CNetAddr& ip, unsigned short port); CService(const struct in_addr& ipv4Addr, unsigned short port); CService(const struct sockaddr_in& addr); - explicit CService(const char *pszIpPort, int portDefault, bool fAllowLookup = false); - explicit CService(const char *pszIpPort, bool fAllowLookup = false); - explicit CService(const std::string& strIpPort, int portDefault, bool fAllowLookup = false); - explicit CService(const std::string& strIpPort, bool fAllowLookup = false); + explicit CService(const char *pszIpPort, int portDefault); + explicit CService(const char *pszIpPort); + explicit CService(const std::string& strIpPort, int portDefault); + explicit CService(const std::string& strIpPort); void Init(); void SetPort(unsigned short portIn); unsigned short GetPort() const; diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index 1c7bc2dbeee6b..47d834c7b4eff 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -438,7 +438,7 @@ void TorController::add_onion_cb(TorControlConnection& conn, const TorControlRep private_key = i->second; } - service = CService(service_id+".onion", GetListenPort(), false); + service = CService(service_id+".onion", GetListenPort()); LogPrintf("tor: Got service ID %s, advertising service %s\n", service_id, service.ToString()); if (WriteBinaryFile(GetPrivateKeyFile(), private_key)) { LogPrint("tor", "tor: Cached service private key to %s\n", GetPrivateKeyFile()); From 3a99fb2cb14955f5e029d315041a093e957e6c3e Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Wed, 20 Apr 2016 13:49:55 -0400 Subject: [PATCH 0186/1802] Fix headers announcements edge case Previously we would assert that if every block in vBlockHashesToAnnounce is in chainActive, then the blocks to be announced must connect. However, there are edge cases where this assumption could be violated (eg using invalidateblock / reconsiderblock), so just check for this case and revert to inv-announcement instead. --- src/main.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index a94d52f8954e8..e2fbfcf12dfa4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5718,7 +5718,21 @@ bool SendMessages(CNode* pto) fRevertToInv = true; break; } - assert(pBestIndex == NULL || pindex->pprev == pBestIndex); + if (pBestIndex != NULL && pindex->pprev != pBestIndex) { + // This means that the list of blocks to announce don't + // connect to each other. + // This shouldn't really be possible to hit during + // regular operation (because reorgs should take us to + // a chain that has some block not on the prior chain, + // which should be caught by the prior check), but one + // way this could happen is by using invalidateblock / + // reconsiderblock repeatedly on the tip, causing it to + // be added multiple times to vBlockHashesToAnnounce. + // Robustly deal with this rare situation by reverting + // to an inv. + fRevertToInv = true; + break; + } pBestIndex = pindex; if (fFoundStartingHeader) { // add this to the headers message From dc13dcd2bec2613a1cd5e0395b09b449d176146f Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 7 Apr 2016 13:57:36 +0200 Subject: [PATCH 0187/1802] Split up and optimize transaction and block inv queues --- src/main.cpp | 76 +++++++++++++++++++++++++++++++--------------------- src/net.h | 20 +++++++++----- 2 files changed, 59 insertions(+), 37 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 4a28bbb00c422..61d9301f8f0d2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5569,18 +5569,11 @@ class CompareInvMempoolOrder mp = mempool; } - bool operator()(const CInv &a, const CInv &b) + bool operator()(std::set::iterator a, std::set::iterator b) { - if (a.type != MSG_TX && b.type != MSG_TX) { - return false; - } else { - if (a.type != MSG_TX) { - return true; - } else if (b.type != MSG_TX) { - return false; - } - return mp->CompareDepthAndScore(a.hash, b.hash); - } + /* As std::make_heap produces a max-heap, we want the entries with the + * fewest ancestors/highest fee to sort later. */ + return mp->CompareDepthAndScore(*b, *a); } }; @@ -5808,38 +5801,59 @@ bool SendMessages(CNode* pto) // Message: inventory // vector vInv; - vector vInvWait; { + LOCK(pto->cs_inventory); + vInv.reserve(std::max(pto->vInventoryBlockToSend.size(), INVENTORY_BROADCAST_MAX)); + + // Add blocks + BOOST_FOREACH(const uint256& hash, pto->vInventoryBlockToSend) { + vInv.push_back(CInv(MSG_BLOCK, hash)); + if (vInv.size() == MAX_INV_SZ) { + pto->PushMessage(NetMsgType::INV, vInv); + vInv.clear(); + } + } + pto->vInventoryBlockToSend.clear(); + + // Determine transactions to relay bool fSendTrickle = pto->fWhitelisted; if (pto->nNextInvSend < nNow) { fSendTrickle = true; - // Use half the delay for outbound peers, as their is less privacy concern for them. + // Use half the delay for outbound peers, as there is less privacy concern for them. pto->nNextInvSend = PoissonNextSend(nNow, INVENTORY_BROADCAST_INTERVAL >> !pto->fInbound); } - LOCK(pto->cs_inventory); - if (fSendTrickle && pto->vInventoryToSend.size() > 1) { + if (fSendTrickle) { + // Produce a vector with all candidates for sending + vector::iterator> vInvTx; + vInvTx.reserve(pto->setInventoryTxToSend.size()); + for (std::set::iterator it = pto->setInventoryTxToSend.begin(); it != pto->setInventoryTxToSend.end(); it++) { + vInvTx.push_back(it); + } // Topologically and fee-rate sort the inventory we send for privacy and priority reasons. + // A heap is used so that not all items need sorting if only a few are being sent. CompareInvMempoolOrder compareInvMempoolOrder(&mempool); - std::stable_sort(pto->vInventoryToSend.begin(), pto->vInventoryToSend.end(), compareInvMempoolOrder); - } - vInv.reserve(std::min(INVENTORY_BROADCAST_MAX, pto->vInventoryToSend.size())); - vInvWait.reserve(pto->vInventoryToSend.size()); - BOOST_FOREACH(const CInv& inv, pto->vInventoryToSend) - { - if (inv.type == MSG_TX && pto->filterInventoryKnown.contains(inv.hash)) - continue; + std::make_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder); // No reason to drain out at many times the network's capacity, // especially since we have many peers and some will draw much shorter delays. - if (vInv.size() >= INVENTORY_BROADCAST_MAX || (inv.type == MSG_TX && !fSendTrickle)) { - vInvWait.push_back(inv); - continue; + unsigned int nRelayedTransactions = 0; + while (!vInvTx.empty() && nRelayedTransactions < INVENTORY_BROADCAST_MAX) { + // Fetch the top element from the heap + std::pop_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder); + std::set::iterator it = vInvTx.back(); + vInvTx.pop_back(); + uint256 hash = *it; + // Remove it from the to-be-sent set + pto->setInventoryTxToSend.erase(it); + // Check if not in the filter already + if (pto->filterInventoryKnown.contains(hash)) { + continue; + } + // Send + vInv.push_back(CInv(MSG_TX, hash)); + nRelayedTransactions++; + pto->filterInventoryKnown.insert(hash); } - - pto->filterInventoryKnown.insert(inv.hash); - - vInv.push_back(inv); } - pto->vInventoryToSend = vInvWait; } if (!vInv.empty()) pto->PushMessage(NetMsgType::INV, vInv); diff --git a/src/net.h b/src/net.h index bf367684f6c14..a95fa79e7e03b 100644 --- a/src/net.h +++ b/src/net.h @@ -397,7 +397,13 @@ class CNode // inventory based relay CRollingBloomFilter filterInventoryKnown; - std::vector vInventoryToSend; + // Set of transaction ids we still have to announce. + // They are sorted by the mempool before relay, so the order is not important. + std::set setInventoryTxToSend; + // List of block ids we still have announce. + // There is no final sorting before sending, as they are always sent immediately + // and in the order requested. + std::vector vInventoryBlockToSend; CCriticalSection cs_inventory; std::set setAskFor; std::multimap mapAskFor; @@ -517,11 +523,13 @@ class CNode void PushInventory(const CInv& inv) { - { - LOCK(cs_inventory); - if (inv.type == MSG_TX && filterInventoryKnown.contains(inv.hash)) - return; - vInventoryToSend.push_back(inv); + LOCK(cs_inventory); + if (inv.type == MSG_TX) { + if (!filterInventoryKnown.contains(inv.hash)) { + setInventoryTxToSend.insert(inv.hash); + } + } else if (inv.type == MSG_BLOCK) { + vInventoryBlockToSend.push_back(inv.hash); } } From ed7068302c7490e8061cb3a558a0f83a465beeea Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 8 Apr 2016 16:26:41 +0200 Subject: [PATCH 0188/1802] Handle mempool requests in send loop, subject to trickle By eliminating queued entries from the mempool response and responding only at trickle time, this makes the mempool no longer leak transaction arrival order information (as the mempool itself is also sorted)-- at least no more than relay itself leaks it. --- src/main.cpp | 74 ++++++++++++++++++++++++++++++++-------------------- src/net.cpp | 1 + src/net.h | 2 ++ 3 files changed, 49 insertions(+), 28 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 61d9301f8f0d2..282c8cdb66449 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5235,34 +5235,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, pfrom->fDisconnect = true; return true; } - LOCK2(cs_main, pfrom->cs_filter); - std::vector vtxid; - mempool.queryHashes(vtxid); - vector vInv; - BOOST_FOREACH(uint256& hash, vtxid) { - CInv inv(MSG_TX, hash); - if (pfrom->pfilter) { - CTransaction tx; - bool fInMemPool = mempool.lookup(hash, tx); - if (!fInMemPool) continue; // another thread removed since queryHashes, maybe... - if (!pfrom->pfilter->IsRelevantAndUpdate(tx)) continue; - } - if (pfrom->minFeeFilter) { - CFeeRate feeRate; - mempool.lookupFeeRate(hash, feeRate); - LOCK(pfrom->cs_feeFilter); - if (feeRate.GetFeePerK() < pfrom->minFeeFilter) - continue; - } - vInv.push_back(inv); - if (vInv.size() == MAX_INV_SZ) { - pfrom->PushMessage(NetMsgType::INV, vInv); - vInv.clear(); - } - } - if (vInv.size() > 0) - pfrom->PushMessage(NetMsgType::INV, vInv); + LOCK(pfrom->cs_inventory); + pfrom->fSendMempool = true; } @@ -5815,13 +5790,52 @@ bool SendMessages(CNode* pto) } pto->vInventoryBlockToSend.clear(); - // Determine transactions to relay + // Check whether periodic sends should happen bool fSendTrickle = pto->fWhitelisted; if (pto->nNextInvSend < nNow) { fSendTrickle = true; // Use half the delay for outbound peers, as there is less privacy concern for them. pto->nNextInvSend = PoissonNextSend(nNow, INVENTORY_BROADCAST_INTERVAL >> !pto->fInbound); } + + // Respond to BIP35 mempool requests + if (fSendTrickle && pto->fSendMempool) { + std::vector vtxid; + mempool.queryHashes(vtxid); + pto->fSendMempool = false; + CAmount filterrate = 0; + { + LOCK(pto->cs_feeFilter); + filterrate = pto->minFeeFilter; + } + + LOCK(pto->cs_filter); + + BOOST_FOREACH(const uint256& hash, vtxid) { + CInv inv(MSG_TX, hash); + pto->setInventoryTxToSend.erase(hash); + if (filterrate) { + CFeeRate feeRate; + mempool.lookupFeeRate(hash, feeRate); + if (feeRate.GetFeePerK() < filterrate) + continue; + } + if (pto->pfilter) { + CTransaction tx; + bool fInMemPool = mempool.lookup(hash, tx); + if (!fInMemPool) continue; // another thread removed since queryHashes, maybe... + if (!pto->pfilter->IsRelevantAndUpdate(tx)) continue; + } + pto->filterInventoryKnown.insert(hash); + vInv.push_back(inv); + if (vInv.size() == MAX_INV_SZ) { + pto->PushMessage(NetMsgType::INV, vInv); + vInv.clear(); + } + } + } + + // Determine transactions to relay if (fSendTrickle) { // Produce a vector with all candidates for sending vector::iterator> vInvTx; @@ -5851,6 +5865,10 @@ bool SendMessages(CNode* pto) // Send vInv.push_back(CInv(MSG_TX, hash)); nRelayedTransactions++; + if (vInv.size() == MAX_INV_SZ) { + pto->PushMessage(NetMsgType::INV, vInv); + vInv.clear(); + } pto->filterInventoryKnown.insert(hash); } } diff --git a/src/net.cpp b/src/net.cpp index f294e4c667836..6b305ebae48a8 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2370,6 +2370,7 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa hashContinue = uint256(); nStartingHeight = -1; filterInventoryKnown.reset(); + fSendMempool = false; fGetAddr = false; nNextLocalAddrSend = 0; nNextAddrSend = 0; diff --git a/src/net.h b/src/net.h index a95fa79e7e03b..26acf59e605cf 100644 --- a/src/net.h +++ b/src/net.h @@ -411,6 +411,8 @@ class CNode // Used for headers announcements - unfiltered blocks to relay // Also protected by cs_inventory std::vector vBlockHashesToAnnounce; + // Used for BIP35 mempool sending, also protected by cs_inventory + bool fSendMempool; // Ping time measurement: // The pong reply we're expecting, or 0 if no pong expected. From 4578215e7f787968c1d6478e6df75499bd36dd8d Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 10 Apr 2016 15:33:05 +0200 Subject: [PATCH 0189/1802] Return mempool queries in dependency order --- src/txmempool.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 3aba578fac99e..0d9fcc982d306 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -767,6 +767,16 @@ bool CTxMemPool::CompareDepthAndScore(const uint256& hasha, const uint256& hashb return counta < countb; } +namespace { +class DepthAndScoreComparator +{ + CTxMemPool *mp; +public: + DepthAndScoreComparator(CTxMemPool *mempool) : mp(mempool) {} + bool operator()(const uint256& a, const uint256& b) { return mp->CompareDepthAndScore(a, b); } +}; +} + void CTxMemPool::queryHashes(vector& vtxid) { vtxid.clear(); @@ -775,6 +785,8 @@ void CTxMemPool::queryHashes(vector& vtxid) vtxid.reserve(mapTx.size()); for (indexed_transaction_set::iterator mi = mapTx.begin(); mi != mapTx.end(); ++mi) vtxid.push_back(mi->GetTx().GetHash()); + + std::sort(vtxid.begin(), vtxid.end(), DepthAndScoreComparator(this)); } bool CTxMemPool::lookup(uint256 hash, CTransaction& result) const From b5599147533103efea896a1fc4ff51f2d3ad5808 Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Wed, 20 Apr 2016 07:05:23 +0000 Subject: [PATCH 0190/1802] Move bloom and feerate filtering to just prior to tx sending. This will avoid sending more pointless INVs around updates, and prevents using filter updates to timetag transactions. Also adds locking for fRelayTxes. --- src/main.cpp | 42 ++++++++++++++++++++++++++++++++++++------ src/net.cpp | 15 +-------------- src/net.h | 2 +- 3 files changed, 38 insertions(+), 21 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 282c8cdb66449..b707de2e585da 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4557,12 +4557,16 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, vRecv >> LIMITED_STRING(pfrom->strSubVer, MAX_SUBVERSION_LENGTH); pfrom->cleanSubVer = SanitizeString(pfrom->strSubVer); } - if (!vRecv.empty()) + if (!vRecv.empty()) { vRecv >> pfrom->nStartingHeight; - if (!vRecv.empty()) - vRecv >> pfrom->fRelayTxes; // set to true after we get the first filter* message - else - pfrom->fRelayTxes = true; + } + { + LOCK(pfrom->cs_filter); + if (!vRecv.empty()) + vRecv >> pfrom->fRelayTxes; // set to true after we get the first filter* message + else + pfrom->fRelayTxes = true; + } // Disconnect if we connected to ourself if (nNonce == nLocalHostNonce && nNonce > 1) @@ -5325,12 +5329,13 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, CBloomFilter filter; vRecv >> filter; + LOCK(pfrom->cs_filter); + if (!filter.IsWithinSizeConstraints()) // There is no excuse for sending a too-large filter Misbehaving(pfrom->GetId(), 100); else { - LOCK(pfrom->cs_filter); delete pfrom->pfilter; pfrom->pfilter = new CBloomFilter(filter); pfrom->pfilter->UpdateEmptyFull(); @@ -5798,6 +5803,12 @@ bool SendMessages(CNode* pto) pto->nNextInvSend = PoissonNextSend(nNow, INVENTORY_BROADCAST_INTERVAL >> !pto->fInbound); } + // Time to send but the peer has requested we not relay transactions. + if (fSendTrickle) { + LOCK(pto->cs_filter); + if (!pto->fRelayTxes) pto->setInventoryTxToSend.clear(); + } + // Respond to BIP35 mempool requests if (fSendTrickle && pto->fSendMempool) { std::vector vtxid; @@ -5843,6 +5854,11 @@ bool SendMessages(CNode* pto) for (std::set::iterator it = pto->setInventoryTxToSend.begin(); it != pto->setInventoryTxToSend.end(); it++) { vInvTx.push_back(it); } + CAmount filterrate = 0; + { + LOCK(pto->cs_feeFilter); + filterrate = pto->minFeeFilter; + } // Topologically and fee-rate sort the inventory we send for privacy and priority reasons. // A heap is used so that not all items need sorting if only a few are being sent. CompareInvMempoolOrder compareInvMempoolOrder(&mempool); @@ -5850,6 +5866,7 @@ bool SendMessages(CNode* pto) // No reason to drain out at many times the network's capacity, // especially since we have many peers and some will draw much shorter delays. unsigned int nRelayedTransactions = 0; + LOCK(pto->cs_filter); while (!vInvTx.empty() && nRelayedTransactions < INVENTORY_BROADCAST_MAX) { // Fetch the top element from the heap std::pop_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder); @@ -5862,6 +5879,19 @@ bool SendMessages(CNode* pto) if (pto->filterInventoryKnown.contains(hash)) { continue; } + // Not in the mempool anymore? don't bother sending it. + CFeeRate feeRate; + if (!mempool.lookupFeeRate(hash, feeRate)) { + continue; + } + if (filterrate && feeRate.GetFeePerK() < filterrate) { + continue; + } + if (pto->pfilter) { + CTransaction tx; + if (!mempool.lookup(hash, tx)) continue; + if (!pto->pfilter->IsRelevantAndUpdate(tx)) continue; + } // Send vInv.push_back(CInv(MSG_TX, hash)); nRelayedTransactions++; diff --git a/src/net.cpp b/src/net.cpp index 6b305ebae48a8..ccc430f5c2804 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2071,20 +2071,7 @@ void RelayTransaction(const CTransaction& tx, CFeeRate feerate) LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) { - if(!pnode->fRelayTxes) - continue; - { - LOCK(pnode->cs_feeFilter); - if (feerate.GetFeePerK() < pnode->minFeeFilter) - continue; - } - LOCK(pnode->cs_filter); - if (pnode->pfilter) - { - if (pnode->pfilter->IsRelevantAndUpdate(tx)) - pnode->PushInventory(inv); - } else - pnode->PushInventory(inv); + pnode->PushInventory(inv); } } diff --git a/src/net.h b/src/net.h index 26acf59e605cf..b6ec7bf3e2c28 100644 --- a/src/net.h +++ b/src/net.h @@ -357,7 +357,7 @@ class CNode // a) it allows us to not relay tx invs before receiving the peer's version message // b) the peer may tell us in its version message that we should not relay tx invs // unless it loads a bloom filter. - bool fRelayTxes; + bool fRelayTxes; //protected by cs_filter bool fSentAddr; CSemaphoreGrant grantOutbound; CCriticalSection cs_filter; From fa243293343eb964bfee5b91cc52b91f16232ab6 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 21 Apr 2016 15:28:53 +0200 Subject: [PATCH 0191/1802] [contrib] verify-commits: Add MarcoFalke fingerprint --- contrib/verify-commits/trusted-keys | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/verify-commits/trusted-keys b/contrib/verify-commits/trusted-keys index a0d0f82db3f43..ad1b28be0cc47 100644 --- a/contrib/verify-commits/trusted-keys +++ b/contrib/verify-commits/trusted-keys @@ -5,3 +5,4 @@ AF8BE07C7049F3A26B239D5325B3083201782B2F 81291FA67D2C379A006A053FEAB5AF94D9E9ABE7 3F1888C6DCA92A6499C4911FDBA1A67379A1A931 32EE5C4C3FA15CCADB46ABE529D4BCB6416F53EC +FE09B823E6D83A3BC7983EAA2D7F2372E50FE137 From a6666b25c7fa196d3829f0df38104e0384408412 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sat, 2 Apr 2016 16:45:26 +0200 Subject: [PATCH 0192/1802] depends: mac deploy Py3 compatibility This fixes the gitian MacOSX build, it was broken in #7723. The patch to `native_mac_alias` should probably make it upstream. --- contrib/macdeploy/macdeployqtplus | 6 +- depends/packages/native_mac_alias.mk | 5 ++ .../patches/native_mac_alias/python3.patch | 72 +++++++++++++++++++ 3 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 depends/patches/native_mac_alias/python3.patch diff --git a/contrib/macdeploy/macdeployqtplus b/contrib/macdeploy/macdeployqtplus index 685ed8e5b89c0..f8201e72c649d 100755 --- a/contrib/macdeploy/macdeployqtplus +++ b/contrib/macdeploy/macdeployqtplus @@ -210,8 +210,8 @@ def getFrameworks(binaryPath, verbose): sys.stderr.write(o_stderr) sys.stderr.flush() raise RuntimeError("otool failed with return code %d" % otool.returncode) - - otoolLines = o_stdout.split("\n") + + otoolLines = o_stdout.decode().split("\n") otoolLines.pop(0) # First line is the inspected binary if ".framework" in binaryPath or binaryPath.endswith(".dylib"): otoolLines.pop(0) # Frameworks and dylibs list themselves as a dependency. @@ -676,7 +676,7 @@ if verbose >= 2: print("+ Installing qt.conf +") f = open(os.path.join(applicationBundle.resourcesPath, "qt.conf"), "wb") -f.write(qt_conf) +f.write(qt_conf.encode()) f.close() # ------------------------------------------------ diff --git a/depends/packages/native_mac_alias.mk b/depends/packages/native_mac_alias.mk index d117c1c9a3f68..85a8a402bf92c 100644 --- a/depends/packages/native_mac_alias.mk +++ b/depends/packages/native_mac_alias.mk @@ -5,6 +5,11 @@ $(package)_download_file=v$($(package)_version).tar.bz2 $(package)_file_name=$(package)-$($(package)_version).tar.bz2 $(package)_sha256_hash=87ad827e66790028361e43fc754f68ed041a9bdb214cca03c853f079b04fb120 $(package)_install_libdir=$(build_prefix)/lib/python/dist-packages +$(package)_patches=python3.patch + +define $(package)_preprocess_cmds + patch -p1 < $($(package)_patch_dir)/python3.patch +endef define $(package)_build_cmds python setup.py build diff --git a/depends/patches/native_mac_alias/python3.patch b/depends/patches/native_mac_alias/python3.patch new file mode 100644 index 0000000000000..1a32340be5b13 --- /dev/null +++ b/depends/patches/native_mac_alias/python3.patch @@ -0,0 +1,72 @@ +diff -dur a/mac_alias/alias.py b/mac_alias/alias.py +--- a/mac_alias/alias.py 2015-10-19 12:12:48.000000000 +0200 ++++ b/mac_alias/alias.py 2016-04-03 12:13:12.037159417 +0200 +@@ -243,10 +243,10 @@ + alias = Alias() + alias.appinfo = appinfo + +- alias.volume = VolumeInfo (volname.replace('/',':'), ++ alias.volume = VolumeInfo (volname.decode().replace('/',':'), + voldate, fstype, disktype, + volattrs, volfsid) +- alias.target = TargetInfo (kind, filename.replace('/',':'), ++ alias.target = TargetInfo (kind, filename.decode().replace('/',':'), + folder_cnid, cnid, + crdate, creator_code, type_code) + alias.target.levels_from = levels_from +@@ -261,9 +261,9 @@ + b.read(1) + + if tag == TAG_CARBON_FOLDER_NAME: +- alias.target.folder_name = value.replace('/',':') ++ alias.target.folder_name = value.decode().replace('/',':') + elif tag == TAG_CNID_PATH: +- alias.target.cnid_path = struct.unpack(b'>%uI' % (length // 4), ++ alias.target.cnid_path = struct.unpack('>%uI' % (length // 4), + value) + elif tag == TAG_CARBON_PATH: + alias.target.carbon_path = value +@@ -298,9 +298,9 @@ + alias.target.creation_date \ + = mac_epoch + datetime.timedelta(seconds=seconds) + elif tag == TAG_POSIX_PATH: +- alias.target.posix_path = value ++ alias.target.posix_path = value.decode() + elif tag == TAG_POSIX_PATH_TO_MOUNTPOINT: +- alias.volume.posix_path = value ++ alias.volume.posix_path = value.decode() + elif tag == TAG_RECURSIVE_ALIAS_OF_DISK_IMAGE: + alias.volume.disk_image_alias = Alias.from_bytes(value) + elif tag == TAG_USER_HOME_LENGTH_PREFIX: +@@ -422,13 +422,13 @@ + # (so doing so is ridiculous, and nothing could rely on it). + b.write(struct.pack(b'>h28pI2shI64pII4s4shhI2s10s', + self.target.kind, +- carbon_volname, voldate, ++ carbon_volname, int(voldate), + self.volume.fs_type, + self.volume.disk_type, + self.target.folder_cnid, + carbon_filename, + self.target.cnid, +- crdate, ++ int(crdate), + self.target.creator_code, + self.target.type_code, + self.target.levels_from, +@@ -449,12 +449,12 @@ + + b.write(struct.pack(b'>hhQhhQ', + TAG_HIGH_RES_VOLUME_CREATION_DATE, +- 8, long(voldate * 65536), ++ 8, int(voldate * 65536), + TAG_HIGH_RES_CREATION_DATE, +- 8, long(crdate * 65536))) ++ 8, int(crdate * 65536))) + + if self.target.cnid_path: +- cnid_path = struct.pack(b'>%uI' % len(self.target.cnid_path), ++ cnid_path = struct.pack('>%uI' % len(self.target.cnid_path), + *self.target.cnid_path) + b.write(struct.pack(b'>hh', TAG_CNID_PATH, + len(cnid_path))) From 06fdffd222ba0a00add4abe9fab9ad2c3e220d8f Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 20 Apr 2016 16:36:52 -0400 Subject: [PATCH 0193/1802] travis: switch to Trusty --- .travis.yml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 95ef36bf028ee..0c9ac71c00b06 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,8 +7,7 @@ # IPv6 support sudo: required -dist: precise -group: legacy +dist: trusty os: linux language: cpp @@ -38,22 +37,25 @@ matrix: - compiler: ": ARM" env: HOST=arm-linux-gnueabihf PACKAGES="g++-arm-linux-gnueabihf" DEP_OPTS="NO_QT=1" CHECK_DOC=1 GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" - compiler: ": Win32" - env: HOST=i686-w64-mingw32 PPA="ppa:ubuntu-wine/ppa" PACKAGES="nsis gcc-mingw-w64-i686 g++-mingw-w64-i686 binutils-mingw-w64-i686 mingw-w64-dev wine1.7 bc" RUN_TESTS=true GOAL="deploy" BITCOIN_CONFIG="--enable-gui --enable-reduce-exports" MAKEJOBS="-j2" + env: HOST=i686-w64-mingw32 DPKG_ADD_ARCH="i386" PACKAGES="nsis g++-mingw-w64-i686 wine1.6 bc" RUN_TESTS=true GOAL="deploy" BITCOIN_CONFIG="--enable-gui --enable-reduce-exports" MAKEJOBS="-j2" - compiler: ": 32-bit + dash" - env: HOST=i686-pc-linux-gnu PACKAGES="g++-multilib bc python-zmq" PPA="ppa:chris-lea/zeromq" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++" USE_SHELL="/bin/dash" + env: HOST=i686-pc-linux-gnu PACKAGES="g++-multilib bc python-zmq" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++" USE_SHELL="/bin/dash" - compiler: ": Win64" - env: HOST=x86_64-w64-mingw32 PPA="ppa:ubuntu-wine/ppa" PACKAGES="nsis gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 binutils-mingw-w64-x86-64 mingw-w64-dev wine1.7 bc" RUN_TESTS=true GOAL="deploy" BITCOIN_CONFIG="--enable-gui --enable-reduce-exports" MAKEJOBS="-j2" + env: HOST=x86_64-w64-mingw32 DPKG_ADD_ARCH="i386" PACKAGES="nsis g++-mingw-w64-x86-64 wine1.6 bc" RUN_TESTS=true GOAL="deploy" BITCOIN_CONFIG="--enable-gui --enable-reduce-exports" MAKEJOBS="-j2" - compiler: ": bitcoind" - env: HOST=x86_64-unknown-linux-gnu PACKAGES="bc python-zmq" PPA="ppa:chris-lea/zeromq" DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports CPPFLAGS=-DDEBUG_LOCKORDER" + env: HOST=x86_64-unknown-linux-gnu PACKAGES="bc python-zmq" DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports CPPFLAGS=-DDEBUG_LOCKORDER" - compiler: ": No wallet" env: HOST=x86_64-unknown-linux-gnu DEP_OPTS="NO_WALLET=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" - compiler: ": Cross-Mac" env: HOST=x86_64-apple-darwin11 PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev" BITCOIN_CONFIG="--enable-reduce-exports" OSX_SDK=10.9 GOAL="deploy" exclude: - compiler: gcc +before_install: + - export PATH=$(echo $PATH | tr ':' "\n" | sed '/\/opt\/python/d' | tr "\n" ":" | sed "s|::|:|g") install: - - if [ -n "$PACKAGES" ]; then sudo rm -f /etc/apt/sources.list.d/travis_ci_zeromq3-source.list; fi + - if [ -n "$PACKAGES" ]; then sudo rm -f /etc/apt/sources.list.d/google-chrome.list; fi - if [ -n "$PPA" ]; then travis_retry sudo add-apt-repository "$PPA" -y; fi + - if [ -n "$DPKG_ADD_ARCH" ]; then sudo dpkg --add-architecture "$DPKG_ADD_ARCH" ; fi - if [ -n "$PACKAGES" ]; then travis_retry sudo apt-get update; fi - if [ -n "$PACKAGES" ]; then travis_retry sudo apt-get install --no-install-recommends --no-upgrade -qq $PACKAGES; fi before_script: From d1d7775587473410a107e7079616b9ecaae8dd06 Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Tue, 19 Apr 2016 13:17:38 -0700 Subject: [PATCH 0194/1802] Improve worst-case behavior of CScript::FindAndDelete Thanks to Sergio Lerner for identifying this issue and suggesting this kind of solution. --- src/script/script.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/script/script.h b/src/script/script.h index 0503b39a76f54..bdbd340bccfdb 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -570,17 +570,26 @@ class CScript : public CScriptBase int nFound = 0; if (b.empty()) return nFound; - iterator pc = begin(); + CScript result; + iterator pc = begin(), pc2 = begin(); opcodetype opcode; do { + result.insert(result.end(), pc2, pc); while (static_cast(end() - pc) >= b.size() && std::equal(b.begin(), b.end(), pc)) { - pc = erase(pc, pc + b.size()); + pc = pc + b.size(); ++nFound; } + pc2 = pc; } while (GetOp(pc, opcode)); + + if (nFound > 0) { + result.insert(result.end(), pc2, end()); + *this = result; + } + return nFound; } int Find(opcodetype op) const From 57704499be948c640c789c7fc11ed1abf8a681bd Mon Sep 17 00:00:00 2001 From: Kaz Wesley Date: Mon, 18 Apr 2016 14:56:02 -0700 Subject: [PATCH 0195/1802] CBase58Data::SetString: cleanse the full vector SetString seems to be passing the length of the wrong variable to memory_cleanse, resulting in the last byte of the temporary buffer not being securely erased. --- src/base58.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base58.cpp b/src/base58.cpp index d81c26092c305..d1d60a6f1dcf5 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -177,7 +177,7 @@ bool CBase58Data::SetString(const char* psz, unsigned int nVersionBytes) vchData.resize(vchTemp.size() - nVersionBytes); if (!vchData.empty()) memcpy(&vchData[0], &vchTemp[nVersionBytes], vchData.size()); - memory_cleanse(&vchTemp[0], vchData.size()); + memory_cleanse(&vchTemp[0], vchTemp.size()); return true; } From f59dceb44f9bcfe1447b2dcca7483ed806cab22a Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 22 Apr 2016 09:21:09 +0200 Subject: [PATCH 0196/1802] qt: Fix out-of-tree GUI builds Without this patch: - When I compile the GUI from the bitcoin directory itself, it works as expected. - When I build the GUI in an out-of-tree build, I cannot get it to select tabs. When I click, say the "Receive" tab nothing happens, the button selects but it doesn't switch the page. The rest - even the debug window - seems to work. See full discussion here: https://github.com/bitcoin/bitcoin/pull/7911#issuecomment-212413442 This turned out to be caused by a mismatch in the arguments to moc, preventing it from finding `bitcoin-config.h`. Fix this by passing `$(DEFAULT_INCLUDES)` to it, which gets set to the appropriate path by autoconf itself. --- src/Makefile.qt.include | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 8443fe697b336..3b39919441088 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -424,11 +424,11 @@ ui_%.h: %.ui $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(UIC) -o $@ $< || (echo "Error creating $@"; false) %.moc: %.cpp - $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(MOC) $(QT_INCLUDES) $(MOC_DEFS) $< | \ + $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(MOC) $(DEFAULT_INCLUDES) $(QT_INCLUDES) $(MOC_DEFS) $< | \ $(SED) -e '/^\*\*.*Created:/d' -e '/^\*\*.*by:/d' > $@ moc_%.cpp: %.h - $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(MOC) $(QT_INCLUDES) $(MOC_DEFS) $< | \ + $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(MOC) $(DEFAULT_INCLUDES) $(QT_INCLUDES) $(MOC_DEFS) $< | \ $(SED) -e '/^\*\*.*Created:/d' -e '/^\*\*.*by:/d' > $@ %.qm: %.ts From 9c0bcb617b7358006842900ad8a9b333b30f5031 Mon Sep 17 00:00:00 2001 From: instagibbs Date: Fri, 22 Apr 2016 11:20:06 -0700 Subject: [PATCH 0197/1802] push back getaddednodeinfo dead value --- src/rpc/net.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index ce14d034ce1fd..320091b9c4d4d 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -347,6 +347,7 @@ UniValue getaddednodeinfo(const UniValue& params, bool fHelp) obj.push_back(Pair("connected", false)); UniValue addresses(UniValue::VARR); obj.push_back(Pair("addresses", addresses)); + ret.push_back(obj); } } From 74f7b1273c41892058fb2ff99aab878ccd22082a Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 20 Apr 2016 09:05:12 +0200 Subject: [PATCH 0198/1802] dbwrapper: Remove throw keywords in function signatures Using throw() specifications in function signatures is not only not required in C++, it is considered deprecated for [various reasons](https://stackoverflow.com/questions/1055387/throw-keyword-in-functions-signature). It is not implemented by any of the common C++ compilers. The usage is also inconsistent with the rest of the source code. --- src/dbwrapper.cpp | 4 ++-- src/dbwrapper.h | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp index 1907e2fa78439..16f85a3e65dbd 100644 --- a/src/dbwrapper.cpp +++ b/src/dbwrapper.cpp @@ -15,7 +15,7 @@ #include #include -void HandleError(const leveldb::Status& status) throw(dbwrapper_error) +void HandleError(const leveldb::Status& status) { if (status.ok()) return; @@ -102,7 +102,7 @@ CDBWrapper::~CDBWrapper() options.env = NULL; } -bool CDBWrapper::WriteBatch(CDBBatch& batch, bool fSync) throw(dbwrapper_error) +bool CDBWrapper::WriteBatch(CDBBatch& batch, bool fSync) { leveldb::Status status = pdb->Write(fSync ? syncoptions : writeoptions, &batch.batch); HandleError(status); diff --git a/src/dbwrapper.h b/src/dbwrapper.h index 5e7313f7eb544..96fb42429f84e 100644 --- a/src/dbwrapper.h +++ b/src/dbwrapper.h @@ -23,7 +23,7 @@ class dbwrapper_error : public std::runtime_error dbwrapper_error(const std::string& msg) : std::runtime_error(msg) {} }; -void HandleError(const leveldb::Status& status) throw(dbwrapper_error); +void HandleError(const leveldb::Status& status); /** Batch of changes queued to be written to a CDBWrapper */ class CDBBatch @@ -180,7 +180,7 @@ class CDBWrapper ~CDBWrapper(); template - bool Read(const K& key, V& value) const throw(dbwrapper_error) + bool Read(const K& key, V& value) const { CDataStream ssKey(SER_DISK, CLIENT_VERSION); ssKey.reserve(ssKey.GetSerializeSize(key)); @@ -206,7 +206,7 @@ class CDBWrapper } template - bool Write(const K& key, const V& value, bool fSync = false) throw(dbwrapper_error) + bool Write(const K& key, const V& value, bool fSync = false) { CDBBatch batch(&obfuscate_key); batch.Write(key, value); @@ -214,7 +214,7 @@ class CDBWrapper } template - bool Exists(const K& key) const throw(dbwrapper_error) + bool Exists(const K& key) const { CDataStream ssKey(SER_DISK, CLIENT_VERSION); ssKey.reserve(ssKey.GetSerializeSize(key)); @@ -233,14 +233,14 @@ class CDBWrapper } template - bool Erase(const K& key, bool fSync = false) throw(dbwrapper_error) + bool Erase(const K& key, bool fSync = false) { CDBBatch batch(&obfuscate_key); batch.Erase(key); return WriteBatch(batch, fSync); } - bool WriteBatch(CDBBatch& batch, bool fSync = false) throw(dbwrapper_error); + bool WriteBatch(CDBBatch& batch, bool fSync = false); // not available for LevelDB; provide for compatibility with BDB bool Flush() @@ -248,7 +248,7 @@ class CDBWrapper return true; } - bool Sync() throw(dbwrapper_error) + bool Sync() { CDBBatch batch(&obfuscate_key); return WriteBatch(batch, true); From 878bf480a3875181712a53a1156754faa19e579b Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 20 Apr 2016 09:08:45 +0200 Subject: [PATCH 0199/1802] dbwrapper: Remove CDBWrapper::GetObfuscateKeyHex It is an unnecessary method as it is used only two times and only internally, and the whole implementation is HexStr(obfuscate_key). --- src/dbwrapper.cpp | 9 ++------- src/dbwrapper.h | 6 ------ 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp index 16f85a3e65dbd..9eae7c7c80b54 100644 --- a/src/dbwrapper.cpp +++ b/src/dbwrapper.cpp @@ -84,10 +84,10 @@ CDBWrapper::CDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, b Write(OBFUSCATE_KEY_KEY, new_key); obfuscate_key = new_key; - LogPrintf("Wrote new obfuscate key for %s: %s\n", path.string(), GetObfuscateKeyHex()); + LogPrintf("Wrote new obfuscate key for %s: %s\n", path.string(), HexStr(obfuscate_key)); } - LogPrintf("Using obfuscation key for %s: %s\n", path.string(), GetObfuscateKeyHex()); + LogPrintf("Using obfuscation key for %s: %s\n", path.string(), HexStr(obfuscate_key)); } CDBWrapper::~CDBWrapper() @@ -141,11 +141,6 @@ const std::vector& CDBWrapper::GetObfuscateKey() const return obfuscate_key; } -std::string CDBWrapper::GetObfuscateKeyHex() const -{ - return HexStr(obfuscate_key); -} - CDBIterator::~CDBIterator() { delete piter; } bool CDBIterator::Valid() { return piter->Valid(); } void CDBIterator::SeekToFirst() { piter->SeekToFirst(); } diff --git a/src/dbwrapper.h b/src/dbwrapper.h index 96fb42429f84e..153c0fd1bf8b8 100644 --- a/src/dbwrapper.h +++ b/src/dbwrapper.h @@ -268,12 +268,6 @@ class CDBWrapper * Accessor for obfuscate_key. */ const std::vector& GetObfuscateKey() const; - - /** - * Return the obfuscate_key as a hex-formatted string. - */ - std::string GetObfuscateKeyHex() const; - }; #endif // BITCOIN_DBWRAPPER_H From b69836d6ff2bd7dc9568ad4af8235662bb4f1826 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 20 Apr 2016 11:46:01 +0200 Subject: [PATCH 0200/1802] dbwrapper: Pass parent CDBWrapper into CDBBatch and CDBIterator Pass parent wrapper directly instead of obfuscation key. This makes it possible for other databases which re-use this code to use other properties from the database. Add a namespace dbwrapper_private for private functions to be used only in dbwrapper.h/cpp and dbwrapper_tests. --- src/dbwrapper.cpp | 14 +++++++---- src/dbwrapper.h | 46 ++++++++++++++++++++++-------------- src/test/dbwrapper_tests.cpp | 8 +++---- src/txdb.cpp | 6 ++--- 4 files changed, 44 insertions(+), 30 deletions(-) diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp index 9eae7c7c80b54..42f57676ab961 100644 --- a/src/dbwrapper.cpp +++ b/src/dbwrapper.cpp @@ -136,12 +136,16 @@ bool CDBWrapper::IsEmpty() return !(it->Valid()); } -const std::vector& CDBWrapper::GetObfuscateKey() const -{ - return obfuscate_key; -} - CDBIterator::~CDBIterator() { delete piter; } bool CDBIterator::Valid() { return piter->Valid(); } void CDBIterator::SeekToFirst() { piter->SeekToFirst(); } void CDBIterator::Next() { piter->Next(); } + +namespace dbwrapper_private { + +const std::vector& GetObfuscateKey(const CDBWrapper &w) +{ + return w.obfuscate_key; +} + +}; diff --git a/src/dbwrapper.h b/src/dbwrapper.h index 153c0fd1bf8b8..9eca2edf60734 100644 --- a/src/dbwrapper.h +++ b/src/dbwrapper.h @@ -25,20 +25,34 @@ class dbwrapper_error : public std::runtime_error void HandleError(const leveldb::Status& status); +class CDBWrapper; + +/** These should be considered an implementation detail of the specific database. + */ +namespace dbwrapper_private { + +/** Work around circular dependency, as well as for testing in dbwrapper_tests. + * Database obfuscation should be considered an implementation detail of the + * specific database. + */ +const std::vector& GetObfuscateKey(const CDBWrapper &w); + +}; + /** Batch of changes queued to be written to a CDBWrapper */ class CDBBatch { friend class CDBWrapper; private: + const CDBWrapper &parent; leveldb::WriteBatch batch; - const std::vector *obfuscate_key; public: /** - * @param[in] obfuscate_key If passed, XOR data with this key. + * @param[in] parent CDBWrapper that this batch is to be submitted to */ - CDBBatch(const std::vector *obfuscate_key) : obfuscate_key(obfuscate_key) { }; + CDBBatch(const CDBWrapper &parent) : parent(parent) { }; template void Write(const K& key, const V& value) @@ -51,7 +65,7 @@ class CDBBatch CDataStream ssValue(SER_DISK, CLIENT_VERSION); ssValue.reserve(ssValue.GetSerializeSize(value)); ssValue << value; - ssValue.Xor(*obfuscate_key); + ssValue.Xor(dbwrapper_private::GetObfuscateKey(parent)); leveldb::Slice slValue(&ssValue[0], ssValue.size()); batch.Put(slKey, slValue); @@ -72,17 +86,17 @@ class CDBBatch class CDBIterator { private: + const CDBWrapper &parent; leveldb::Iterator *piter; - const std::vector *obfuscate_key; public: /** + * @param[in] parent Parent CDBWrapper instance. * @param[in] piterIn The original leveldb iterator. - * @param[in] obfuscate_key If passed, XOR data with this key. */ - CDBIterator(leveldb::Iterator *piterIn, const std::vector* obfuscate_key) : - piter(piterIn), obfuscate_key(obfuscate_key) { }; + CDBIterator(const CDBWrapper &parent, leveldb::Iterator *piterIn) : + parent(parent), piter(piterIn) { }; ~CDBIterator(); bool Valid(); @@ -118,7 +132,7 @@ class CDBIterator leveldb::Slice slValue = piter->value(); try { CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION); - ssValue.Xor(*obfuscate_key); + ssValue.Xor(dbwrapper_private::GetObfuscateKey(parent)); ssValue >> value; } catch (const std::exception&) { return false; @@ -134,6 +148,7 @@ class CDBIterator class CDBWrapper { + friend const std::vector& dbwrapper_private::GetObfuscateKey(const CDBWrapper &w); private: //! custom environment this database is using (may be NULL in case of default environment) leveldb::Env* penv; @@ -208,7 +223,7 @@ class CDBWrapper template bool Write(const K& key, const V& value, bool fSync = false) { - CDBBatch batch(&obfuscate_key); + CDBBatch batch(*this); batch.Write(key, value); return WriteBatch(batch, fSync); } @@ -235,7 +250,7 @@ class CDBWrapper template bool Erase(const K& key, bool fSync = false) { - CDBBatch batch(&obfuscate_key); + CDBBatch batch(*this); batch.Erase(key); return WriteBatch(batch, fSync); } @@ -250,24 +265,19 @@ class CDBWrapper bool Sync() { - CDBBatch batch(&obfuscate_key); + CDBBatch batch(*this); return WriteBatch(batch, true); } CDBIterator *NewIterator() { - return new CDBIterator(pdb->NewIterator(iteroptions), &obfuscate_key); + return new CDBIterator(*this, pdb->NewIterator(iteroptions)); } /** * Return true if the database managed by this class contains no entries. */ bool IsEmpty(); - - /** - * Accessor for obfuscate_key. - */ - const std::vector& GetObfuscateKey() const; }; #endif // BITCOIN_DBWRAPPER_H diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp index e399315870e79..081d57831d0dd 100644 --- a/src/test/dbwrapper_tests.cpp +++ b/src/test/dbwrapper_tests.cpp @@ -39,7 +39,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper) uint256 res; // Ensure that we're doing real obfuscation when obfuscate=true - BOOST_CHECK(obfuscate != is_null_key(dbw.GetObfuscateKey())); + BOOST_CHECK(obfuscate != is_null_key(dbwrapper_private::GetObfuscateKey(dbw))); BOOST_CHECK(dbw.Write(key, in)); BOOST_CHECK(dbw.Read(key, res)); @@ -64,7 +64,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper_batch) uint256 in3 = GetRandHash(); uint256 res; - CDBBatch batch(&dbw.GetObfuscateKey()); + CDBBatch batch(dbw); batch.Write(key, in); batch.Write(key2, in2); @@ -156,7 +156,7 @@ BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate) BOOST_CHECK_EQUAL(res2.ToString(), in.ToString()); BOOST_CHECK(!odbw.IsEmpty()); // There should be existing data - BOOST_CHECK(is_null_key(odbw.GetObfuscateKey())); // The key should be an empty string + BOOST_CHECK(is_null_key(dbwrapper_private::GetObfuscateKey(odbw))); // The key should be an empty string uint256 in2 = GetRandHash(); uint256 res3; @@ -193,7 +193,7 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex) // Check that the key/val we wrote with unobfuscated wrapper doesn't exist uint256 res2; BOOST_CHECK(!odbw.Read(key, res2)); - BOOST_CHECK(!is_null_key(odbw.GetObfuscateKey())); + BOOST_CHECK(!is_null_key(dbwrapper_private::GetObfuscateKey(odbw))); uint256 in2 = GetRandHash(); uint256 res3; diff --git a/src/txdb.cpp b/src/txdb.cpp index 19ca1786549ee..5fbaeb608a74c 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -49,7 +49,7 @@ uint256 CCoinsViewDB::GetBestBlock() const { } bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { - CDBBatch batch(&db.GetObfuscateKey()); + CDBBatch batch(db); size_t count = 0; size_t changed = 0; for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) { @@ -139,7 +139,7 @@ void CCoinsViewDBCursor::Next() } bool CBlockTreeDB::WriteBatchSync(const std::vector >& fileInfo, int nLastFile, const std::vector& blockinfo) { - CDBBatch batch(&GetObfuscateKey()); + CDBBatch batch(*this); for (std::vector >::const_iterator it=fileInfo.begin(); it != fileInfo.end(); it++) { batch.Write(make_pair(DB_BLOCK_FILES, it->first), *it->second); } @@ -155,7 +155,7 @@ bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) { } bool CBlockTreeDB::WriteTxIndex(const std::vector >&vect) { - CDBBatch batch(&GetObfuscateKey()); + CDBBatch batch(*this); for (std::vector >::const_iterator it=vect.begin(); it!=vect.end(); it++) batch.Write(make_pair(DB_TXINDEX, it->first), it->second); return WriteBatch(batch); From 869cf1234a915808fda6fd663dead5580fbd046e Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 20 Apr 2016 11:48:57 +0200 Subject: [PATCH 0201/1802] dbwrapper: Move `HandleError` to `dbwrapper_private` HandleError is implementation-specific. --- src/dbwrapper.cpp | 34 +++++++++++++++++----------------- src/dbwrapper.h | 10 ++++++---- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp index 42f57676ab961..09c68fbe550c8 100644 --- a/src/dbwrapper.cpp +++ b/src/dbwrapper.cpp @@ -15,20 +15,6 @@ #include #include -void HandleError(const leveldb::Status& status) -{ - if (status.ok()) - return; - LogPrintf("%s\n", status.ToString()); - if (status.IsCorruption()) - throw dbwrapper_error("Database corrupted"); - if (status.IsIOError()) - throw dbwrapper_error("Database I/O error"); - if (status.IsNotFound()) - throw dbwrapper_error("Database entry missing"); - throw dbwrapper_error("Unknown database error"); -} - static leveldb::Options GetOptions(size_t nCacheSize) { leveldb::Options options; @@ -61,13 +47,13 @@ CDBWrapper::CDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, b if (fWipe) { LogPrintf("Wiping LevelDB in %s\n", path.string()); leveldb::Status result = leveldb::DestroyDB(path.string(), options); - HandleError(result); + dbwrapper_private::HandleError(result); } TryCreateDirectory(path); LogPrintf("Opening LevelDB in %s\n", path.string()); } leveldb::Status status = leveldb::DB::Open(options, path.string(), &pdb); - HandleError(status); + dbwrapper_private::HandleError(status); LogPrintf("Opened LevelDB successfully\n"); // The base-case obfuscation key, which is a noop. @@ -105,7 +91,7 @@ CDBWrapper::~CDBWrapper() bool CDBWrapper::WriteBatch(CDBBatch& batch, bool fSync) { leveldb::Status status = pdb->Write(fSync ? syncoptions : writeoptions, &batch.batch); - HandleError(status); + dbwrapper_private::HandleError(status); return true; } @@ -143,6 +129,20 @@ void CDBIterator::Next() { piter->Next(); } namespace dbwrapper_private { +void HandleError(const leveldb::Status& status) +{ + if (status.ok()) + return; + LogPrintf("%s\n", status.ToString()); + if (status.IsCorruption()) + throw dbwrapper_error("Database corrupted"); + if (status.IsIOError()) + throw dbwrapper_error("Database I/O error"); + if (status.IsNotFound()) + throw dbwrapper_error("Database entry missing"); + throw dbwrapper_error("Unknown database error"); +} + const std::vector& GetObfuscateKey(const CDBWrapper &w) { return w.obfuscate_key; diff --git a/src/dbwrapper.h b/src/dbwrapper.h index 9eca2edf60734..a0779d3ab9918 100644 --- a/src/dbwrapper.h +++ b/src/dbwrapper.h @@ -23,14 +23,16 @@ class dbwrapper_error : public std::runtime_error dbwrapper_error(const std::string& msg) : std::runtime_error(msg) {} }; -void HandleError(const leveldb::Status& status); - class CDBWrapper; /** These should be considered an implementation detail of the specific database. */ namespace dbwrapper_private { +/** Handle database error by throwing dbwrapper_error exception. + */ +void HandleError(const leveldb::Status& status); + /** Work around circular dependency, as well as for testing in dbwrapper_tests. * Database obfuscation should be considered an implementation detail of the * specific database. @@ -208,7 +210,7 @@ class CDBWrapper if (status.IsNotFound()) return false; LogPrintf("LevelDB read failure: %s\n", status.ToString()); - HandleError(status); + dbwrapper_private::HandleError(status); } try { CDataStream ssValue(strValue.data(), strValue.data() + strValue.size(), SER_DISK, CLIENT_VERSION); @@ -242,7 +244,7 @@ class CDBWrapper if (status.IsNotFound()) return false; LogPrintf("LevelDB read failure: %s\n", status.ToString()); - HandleError(status); + dbwrapper_private::HandleError(status); } return true; } From 5555528b47b7d33a5b963c076e6bb09ee25931b5 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sat, 23 Apr 2016 14:35:52 +0200 Subject: [PATCH 0202/1802] [qa] mininode: Unfiddle strings into bytes --- qa/rpc-tests/test_framework/mininode.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index af3356411471e..30aecfd445b0e 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -93,7 +93,7 @@ def deser_uint256(f): def ser_uint256(u): - rs = "" + rs = b"" for i in xrange(8): rs += struct.pack(">= 32 @@ -191,7 +191,7 @@ def deser_string_vector(f): def ser_string_vector(l): - r = "" + r = b"" if len(l) < 253: r = struct.pack("B", len(l)) elif len(l) < 0x10000: @@ -624,7 +624,7 @@ def deserialize(self, f): self.vchSig = deser_string(f) def serialize(self): - r = "" + r = b"" r += ser_string(self.vchMsg) r += ser_string(self.vchSig) return r @@ -988,7 +988,7 @@ class msg_reject(object): def __init__(self): self.message = b"" self.code = 0 - self.reason = "" + self.reason = b"" self.data = 0L def deserialize(self, f): From fb26bf0ea3822638b10a783f054c280fc053a2b5 Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Sat, 23 Apr 2016 22:21:52 -0700 Subject: [PATCH 0203/1802] CAddrMan::Deserialize handle corrupt serializations better. --- src/addrman.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/addrman.h b/src/addrman.h index 4f3de8d7c5e63..3085450450474 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -350,6 +350,14 @@ class CAddrMan nUBuckets ^= (1 << 30); } + if (nNew > ADDRMAN_NEW_BUCKET_COUNT * ADDRMAN_BUCKET_SIZE) { + throw std::ios_base::failure("Corrupt CAddrMan serialization, nNew exceeds limit."); + } + + if (nTried > ADDRMAN_TRIED_BUCKET_COUNT * ADDRMAN_BUCKET_SIZE) { + throw std::ios_base::failure("Corrupt CAddrMan serialization, nTried exceeds limit."); + } + // Deserialize entries from the new table. for (int n = 0; n < nNew; n++) { CAddrInfo &info = mapInfo[n]; From c907f4d56b0a27ecd002a6d7d89a38cfc6d45ee3 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 15 Apr 2016 13:21:16 +0200 Subject: [PATCH 0204/1802] doc: Update release process The actual release process quite diverged from what was written here, also clarify things a bit. --- doc/release-notes.md | 15 +++ doc/release-process.md | 294 ++++++++++++++++++++++++----------------- 2 files changed, 191 insertions(+), 118 deletions(-) diff --git a/doc/release-notes.md b/doc/release-notes.md index 806d174ebf7fc..4e318ef294059 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -1,6 +1,21 @@ (note: this is a temporary file, to be added-to by anybody, and moved to release-notes at release time) +Bitcoin Core version *version* is now available from: + + + +This is a new major version release, including new features, various bugfixes +and performance improvements, as well as updated translations. + +Please report bugs using the issue tracker at github: + + + +To receive security and update notifications, please subscribe to: + + + Notable changes =============== diff --git a/doc/release-process.md b/doc/release-process.md index 5a6ac8482b674..34dead86bc1e4 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -1,181 +1,228 @@ Release Process ==================== -* Update translations (ping wumpus, Diapolo or tcatm on IRC) see [translation_process.md](https://github.com/bitcoin/bitcoin/blob/master/doc/translation_process.md#syncing-with-transifex) +Before every release candidate: + +* Update translations (ping wumpus on IRC) see [translation_process.md](https://github.com/bitcoin/bitcoin/blob/master/doc/translation_process.md#syncing-with-transifex) + +Before every minor and major release: + * Update [bips.md](bips.md) to account for changes since the last release. -* Update hardcoded [seeds](/contrib/seeds) +* Update version in sources (see below) +* Write release notes (see below) + +Before every major release: -* * * +* Update hardcoded [seeds](/contrib/seeds/README.md), see [this pull request](https://github.com/bitcoin/bitcoin/pull/7415) for an example. + +### First time / New builders -###First time / New builders Check out the source code in the following directory hierarchy. - cd /path/to/your/toplevel/build - git clone https://github.com/bitcoin/gitian.sigs.git - git clone https://github.com/bitcoin/bitcoin-detached-sigs.git - git clone https://github.com/devrandom/gitian-builder.git - git clone https://github.com/bitcoin/bitcoin.git + cd /path/to/your/toplevel/build + git clone https://github.com/bitcoin/gitian.sigs.git + git clone https://github.com/bitcoin/bitcoin-detached-sigs.git + git clone https://github.com/devrandom/gitian-builder.git + git clone https://github.com/bitcoin/bitcoin.git + +### Bitcoin maintainers/release engineers, update version in sources + +Update the following: + +- `configure.ac`: + - `_CLIENT_VERSION_MAJOR` + - `_CLIENT_VERSION_MINOR` + - `_CLIENT_VERSION_REVISION` + - Don't forget to set `_CLIENT_VERSION_IS_RELEASE` to `true` +- `src/clientversion.h`: (this mirrors `configure.ac` - see issue #3539) + - `CLIENT_VERSION_MAJOR` + - `CLIENT_VERSION_MINOR` + - `CLIENT_VERSION_REVISION` + - Don't forget to set `CLIENT_VERSION_IS_RELEASE` to `true` +- `doc/README.md` and `doc/README_windows.txt` +- `doc/Doxyfile`: `PROJECT_NUMBER` contains the full version +- `contrib/gitian-descriptors/*.yml`: usually one'd want to do this on master after branching off the release - but be sure to at least do it before a new major release -###Bitcoin maintainers/release engineers, update (commit) version in sources +Write release notes. git shortlog helps a lot, for example: - pushd ./bitcoin - contrib/verifysfbinaries/verify.sh - configure.ac - doc/README* - doc/Doxyfile - contrib/gitian-descriptors/*.yml - src/clientversion.h (change CLIENT_VERSION_IS_RELEASE to true) + git shortlog --no-merges v(current version, e.g. 0.7.2)..v(new version, e.g. 0.8.0) - # tag version in git +(or ping @wumpus on IRC, he has specific tooling to generate the list of merged pulls +and sort them into categories based on labels) - git tag -s v(new version, e.g. 0.8.0) +Generate list of authors: - # write release notes. git shortlog helps a lot, for example: + git log --format='%aN' "$*" | sort -ui | sed -e 's/^/- /' - git shortlog --no-merges v(current version, e.g. 0.7.2)..v(new version, e.g. 0.8.0) - popd +Tag version (or release candidate) in git -* * * + git tag -s v(new version, e.g. 0.8.0) -###Setup and perform Gitian builds +### Setup and perform Gitian builds - Setup Gitian descriptors: +Setup Gitian descriptors: - pushd ./bitcoin - export SIGNER=(your Gitian key, ie bluematt, sipa, etc) - export VERSION=(new version, e.g. 0.8.0) - git fetch - git checkout v${VERSION} - popd + pushd ./bitcoin + export SIGNER=(your Gitian key, ie bluematt, sipa, etc) + export VERSION=(new version, e.g. 0.8.0) + git fetch + git checkout v${VERSION} + popd - Ensure your gitian.sigs are up-to-date if you wish to gverify your builds against other Gitian signatures. +Ensure your gitian.sigs are up-to-date if you wish to gverify your builds against other Gitian signatures. - pushd ./gitian.sigs - git pull - popd + pushd ./gitian.sigs + git pull + popd - Ensure gitian-builder is up-to-date to take advantage of new caching features (`e9741525c` or later is recommended). +Ensure gitian-builder is up-to-date to take advantage of new caching features (`e9741525c` or later is recommended). - pushd ./gitian-builder - git pull + pushd ./gitian-builder + git pull + popd -###Fetch and create inputs: (first time, or when dependency versions change) +### Fetch and create inputs: (first time, or when dependency versions change) - mkdir -p inputs - wget -P inputs https://bitcoincore.org/cfields/osslsigncode-Backports-to-1.7.1.patch - wget -P inputs http://downloads.sourceforge.net/project/osslsigncode/osslsigncode/osslsigncode-1.7.1.tar.gz + pushd ./gitian-builder + mkdir -p inputs + wget -P inputs https://bitcoincore.org/cfields/osslsigncode-Backports-to-1.7.1.patch + wget -P inputs http://downloads.sourceforge.net/project/osslsigncode/osslsigncode/osslsigncode-1.7.1.tar.gz + popd - Register and download the Apple SDK: see [OS X readme](README_osx.txt) for details. +Register and download the Apple SDK: see [OS X readme](README_osx.txt) for details. - https://developer.apple.com/devcenter/download.action?path=/Developer_Tools/xcode_6.1.1/xcode_6.1.1.dmg +https://developer.apple.com/devcenter/download.action?path=/Developer_Tools/xcode_6.1.1/xcode_6.1.1.dmg - Using a Mac, create a tarball for the 10.9 SDK and copy it to the inputs directory: +Using a Mac, create a tarball for the 10.9 SDK and copy it to the inputs directory: - tar -C /Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ -czf MacOSX10.9.sdk.tar.gz MacOSX10.9.sdk + tar -C /Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ -czf MacOSX10.9.sdk.tar.gz MacOSX10.9.sdk -###Optional: Seed the Gitian sources cache and offline git repositories +### Optional: Seed the Gitian sources cache and offline git repositories By default, Gitian will fetch source files as needed. To cache them ahead of time: - make -C ../bitcoin/depends download SOURCES_PATH=`pwd`/cache/common + pushd ./gitian-builder + make -C ../bitcoin/depends download SOURCES_PATH=`pwd`/cache/common + popd Only missing files will be fetched, so this is safe to re-run for each build. NOTE: Offline builds must use the --url flag to ensure Gitian fetches only from local URLs. For example: -``` -./bin/gbuild --url bitcoin=/path/to/bitcoin,signature=/path/to/sigs {rest of arguments} -``` + + pushd ./gitian-builder + ./bin/gbuild --url bitcoin=/path/to/bitcoin,signature=/path/to/sigs {rest of arguments} + popd + The gbuild invocations below DO NOT DO THIS by default. -###Build and sign Bitcoin Core for Linux, Windows, and OS X: +### Build and sign Bitcoin Core for Linux, Windows, and OS X: - ./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml - ./bin/gsign --signer $SIGNER --release ${VERSION}-linux --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml + pushd ./gitian-builder + ./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml + ./bin/gsign --signer $SIGNER --release ${VERSION}-linux --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml mv build/out/bitcoin-*.tar.gz build/out/src/bitcoin-*.tar.gz ../ - ./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-win.yml - ./bin/gsign --signer $SIGNER --release ${VERSION}-win-unsigned --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win.yml + ./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-win.yml + ./bin/gsign --signer $SIGNER --release ${VERSION}-win-unsigned --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win.yml mv build/out/bitcoin-*-win-unsigned.tar.gz inputs/bitcoin-win-unsigned.tar.gz mv build/out/bitcoin-*.zip build/out/bitcoin-*.exe ../ - ./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml - ./bin/gsign --signer $SIGNER --release ${VERSION}-osx-unsigned --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml + ./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml + ./bin/gsign --signer $SIGNER --release ${VERSION}-osx-unsigned --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml mv build/out/bitcoin-*-osx-unsigned.tar.gz inputs/bitcoin-osx-unsigned.tar.gz mv build/out/bitcoin-*.tar.gz build/out/bitcoin-*.dmg ../ + popd - Build output expected: +Build output expected: - 1. source tarball (bitcoin-${VERSION}.tar.gz) - 2. linux 32-bit and 64-bit dist tarballs (bitcoin-${VERSION}-linux[32|64].tar.gz) - 3. windows 32-bit and 64-bit unsigned installers and dist zips (bitcoin-${VERSION}-win[32|64]-setup-unsigned.exe, bitcoin-${VERSION}-win[32|64].zip) - 4. OS X unsigned installer and dist tarball (bitcoin-${VERSION}-osx-unsigned.dmg, bitcoin-${VERSION}-osx64.tar.gz) - 5. Gitian signatures (in gitian.sigs/${VERSION}-/(your Gitian key)/ + 1. source tarball (`bitcoin-${VERSION}.tar.gz`) + 2. linux 32-bit and 64-bit dist tarballs (`bitcoin-${VERSION}-linux[32|64].tar.gz`) + 3. windows 32-bit and 64-bit unsigned installers and dist zips (`bitcoin-${VERSION}-win[32|64]-setup-unsigned.exe`, `bitcoin-${VERSION}-win[32|64].zip`) + 4. OS X unsigned installer and dist tarball (`bitcoin-${VERSION}-osx-unsigned.dmg`, `bitcoin-${VERSION}-osx64.tar.gz`) + 5. Gitian signatures (in `gitian.sigs/${VERSION}-/(your Gitian key)/`) -###Verify other gitian builders signatures to your own. (Optional) +### Verify other gitian builders signatures to your own. (Optional) - Add other gitian builders keys to your gpg keyring +Add other gitian builders keys to your gpg keyring - gpg --import ../bitcoin/contrib/gitian-keys/*.pgp + gpg --import bitcoin/contrib/gitian-keys/*.pgp - Verify the signatures +Verify the signatures - ./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-linux ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml - ./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-win-unsigned ../bitcoin/contrib/gitian-descriptors/gitian-win.yml - ./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-osx-unsigned ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml + pushd ./gitian-builder + ./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-linux ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml + ./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-win-unsigned ../bitcoin/contrib/gitian-descriptors/gitian-win.yml + ./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-osx-unsigned ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml + popd - popd - -###Next steps: +### Next steps: Commit your signature to gitian.sigs: - pushd gitian.sigs - git add ${VERSION}-linux/${SIGNER} - git add ${VERSION}-win-unsigned/${SIGNER} - git add ${VERSION}-osx-unsigned/${SIGNER} - git commit -a - git push # Assuming you can push to the gitian.sigs tree - popd - - Wait for Windows/OS X detached signatures: - Once the Windows/OS X builds each have 3 matching signatures, they will be signed with their respective release keys. - Detached signatures will then be committed to the [bitcoin-detached-sigs](https://github.com/bitcoin/bitcoin-detached-sigs) repository, which can be combined with the unsigned apps to create signed binaries. - - Create (and optionally verify) the signed OS X binary: - - pushd ./gitian-builder - ./bin/gbuild -i --commit signature=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml - ./bin/gsign --signer $SIGNER --release ${VERSION}-osx-signed --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml - ./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-osx-signed ../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml - mv build/out/bitcoin-osx-signed.dmg ../bitcoin-${VERSION}-osx.dmg - popd - - Create (and optionally verify) the signed Windows binaries: - - pushd ./gitian-builder - ./bin/gbuild -i --commit signature=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml - ./bin/gsign --signer $SIGNER --release ${VERSION}-win-signed --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml - ./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-win-signed ../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml - mv build/out/bitcoin-*win64-setup.exe ../bitcoin-${VERSION}-win64-setup.exe - mv build/out/bitcoin-*win32-setup.exe ../bitcoin-${VERSION}-win32-setup.exe - popd + pushd gitian.sigs + git add ${VERSION}-linux/${SIGNER} + git add ${VERSION}-win-unsigned/${SIGNER} + git add ${VERSION}-osx-unsigned/${SIGNER} + git commit -a + git push # Assuming you can push to the gitian.sigs tree + popd -Commit your signature for the signed OS X/Windows binaries: +Wait for Windows/OS X detached signatures: + +- Once the Windows/OS X builds each have 3 matching signatures, they will be signed with their respective release keys. +- Detached signatures will then be committed to the [bitcoin-detached-sigs](https://github.com/bitcoin/bitcoin-detached-sigs) repository, which can be combined with the unsigned apps to create signed binaries. + +Create (and optionally verify) the signed OS X binary: - pushd gitian.sigs - git add ${VERSION}-osx-signed/${SIGNER} - git add ${VERSION}-win-signed/${SIGNER} - git commit -a - git push # Assuming you can push to the gitian.sigs tree - popd + pushd ./gitian-builder + ./bin/gbuild -i --commit signature=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml + ./bin/gsign --signer $SIGNER --release ${VERSION}-osx-signed --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml + ./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-osx-signed ../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml + mv build/out/bitcoin-osx-signed.dmg ../bitcoin-${VERSION}-osx.dmg + popd -------------------------------------------------------------------------- +Create (and optionally verify) the signed Windows binaries: + + pushd ./gitian-builder + ./bin/gbuild -i --commit signature=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml + ./bin/gsign --signer $SIGNER --release ${VERSION}-win-signed --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml + ./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-win-signed ../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml + mv build/out/bitcoin-*win64-setup.exe ../bitcoin-${VERSION}-win64-setup.exe + mv build/out/bitcoin-*win32-setup.exe ../bitcoin-${VERSION}-win32-setup.exe + popd + +Commit your signature for the signed OS X/Windows binaries: + + pushd gitian.sigs + git add ${VERSION}-osx-signed/${SIGNER} + git add ${VERSION}-win-signed/${SIGNER} + git commit -a + git push # Assuming you can push to the gitian.sigs tree + popd ### After 3 or more people have gitian-built and their results match: - Create `SHA256SUMS.asc` for the builds, and GPG-sign it: + ```bash sha256sum * > SHA256SUMS +``` + +The list of files should be: +``` +bitcoin-${VERSION}-linux32.tar.gz +bitcoin-${VERSION}-linux64.tar.gz +bitcoin-${VERSION}-osx64.tar.gz +bitcoin-${VERSION}-osx.dmg +bitcoin-${VERSION}.tar.gz +bitcoin-${VERSION}-win32-setup.exe +bitcoin-${VERSION}-win32.zip +bitcoin-${VERSION}-win64-setup.exe +bitcoin-${VERSION}-win64.zip +``` + +- GPG-sign it, delete the unsigned file: +``` gpg --digest-algo sha256 --clearsign SHA256SUMS # outputs SHA256SUMS.asc rm SHA256SUMS ``` @@ -185,6 +232,15 @@ Note: check that SHA256SUMS itself doesn't end up in SHA256SUMS, which is a spur - Upload zips and installers, as well as `SHA256SUMS.asc` from last step, to the bitcoin.org server into `/var/www/bin/bitcoin-core-${VERSION}` +- A `.torrent` will appear in the directory after a few minutes. Optionally help seed this torrent. To get the `magnet:` URI use: +```bash +transmission-show -m +``` +Insert the magnet URI into the announcement sent to mailing lists. This permits +people without access to `bitcoin.org` to download the binary distribution. +Also put it into the `optional_magnetlink:` slot in the YAML file for +bitcoin.org (see below for bitcoin.org update instructions). + - Update bitcoin.org version - First, check to see if the Bitcoin.org maintainers have prepared a @@ -202,16 +258,18 @@ Note: check that SHA256SUMS itself doesn't end up in SHA256SUMS, which is a spur - Announce the release: - - Release sticky on bitcointalk: https://bitcointalk.org/index.php?board=1.0 + - bitcoin-dev and bitcoin-core-dev mailing list + + - Bitcoin Core announcements list https://bitcoincore.org/en/list/announcements/join/ - - Bitcoin-development mailing list + - bitcoincore.org blog post - Update title of #bitcoin on Freenode IRC - - Optionally reddit /r/Bitcoin, ... but this will usually sort out itself + - Optionally twitter, reddit /r/Bitcoin, ... but this will usually sort out itself -- Notify BlueMatt so that he can start building [the PPAs](https://launchpad.net/~bitcoin/+archive/ubuntu/bitcoin) + - Notify BlueMatt so that he can start building [the PPAs](https://launchpad.net/~bitcoin/+archive/ubuntu/bitcoin) -- Add release notes for the new version to the directory `doc/release-notes` in git master + - Add release notes for the new version to the directory `doc/release-notes` in git master -- Celebrate + - Celebrate From 182bec427946d4ce951e8572130c903f0131447e Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 15 Apr 2016 13:21:51 +0200 Subject: [PATCH 0205/1802] contrib: remove hardcoded version from verify.sh Closes #7595 as by removing the hardcoded version number from `verify.sh`. --- contrib/verifysfbinaries/verify.sh | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/contrib/verifysfbinaries/verify.sh b/contrib/verifysfbinaries/verify.sh index 847c507553057..657c3bd33c2e2 100755 --- a/contrib/verifysfbinaries/verify.sh +++ b/contrib/verifysfbinaries/verify.sh @@ -23,9 +23,6 @@ BASEDIR="https://bitcoin.org/bin/" VERSIONPREFIX="bitcoin-core-" RCVERSIONSTRING="rc" -#this URL is used if a version number is not specified as an argument to the script -SIGNATUREFILE="$BASEDIR""$VERSIONPREFIX""0.10.4/""$RCSUBDIR""$SIGNATUREFILENAME" - if [ ! -d "$WORKINGDIR" ]; then mkdir "$WORKINGDIR" fi @@ -53,7 +50,8 @@ if [ -n "$1" ]; then SIGNATUREFILE="$BASEDIR$SIGNATUREFILENAME" else - BASEDIR="${SIGNATUREFILE%/*}/" + echo "Error: need to specify a version on the command line" + exit 2 fi #first we fetch the file containing the signature From f1544700703a442191ac1dfaae7f31b04ba7b12b Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Fri, 15 Apr 2016 12:18:12 +0200 Subject: [PATCH 0206/1802] [contrib] Remove reference to sf and add doc to verify.sh --- contrib/README.md | 4 ++-- contrib/{verifysfbinaries => verifybinaries}/README.md | 9 ++++++++- contrib/{verifysfbinaries => verifybinaries}/verify.sh | 0 3 files changed, 10 insertions(+), 3 deletions(-) rename contrib/{verifysfbinaries => verifybinaries}/README.md (81%) rename contrib/{verifysfbinaries => verifybinaries}/verify.sh (100%) diff --git a/contrib/README.md b/contrib/README.md index 32b3a170ac7ec..a23b197cc6122 100644 --- a/contrib/README.md +++ b/contrib/README.md @@ -51,5 +51,5 @@ Test and Verify Tools ### [TestGen](/contrib/testgen) ### Utilities to generate test vectors for the data-driven Bitcoin tests. -### [Verify SF Binaries](/contrib/verifysfbinaries) ### -This script attempts to download and verify the signature file SHA256SUMS.asc from SourceForge. +### [Verify Binaries](/contrib/verifybinaries) ### +This script attempts to download and verify the signature file SHA256SUMS.asc from bitcoin.org. diff --git a/contrib/verifysfbinaries/README.md b/contrib/verifybinaries/README.md similarity index 81% rename from contrib/verifysfbinaries/README.md rename to contrib/verifybinaries/README.md index 1db3fe52fc2c3..8970f3daa406a 100644 --- a/contrib/verifysfbinaries/README.md +++ b/contrib/verifybinaries/README.md @@ -1,6 +1,13 @@ -### Verify Binaries ### +### Verify Binaries This script attempts to download the signature file `SHA256SUMS.asc` from https://bitcoin.org. It first checks if the signature passes, and then downloads the files specified in the file, and checks if the hashes of these files match those that are specified in the signature file. The script returns 0 if everything passes the checks. It returns 1 if either the signature check or the hash check doesn't pass. If an error occurs the return value is 2. + +Usage: + +```sh +./verify.sh bitcoin-core-0.11.2 +./verify.sh bitcoin-core-0.12.0 +``` diff --git a/contrib/verifysfbinaries/verify.sh b/contrib/verifybinaries/verify.sh similarity index 100% rename from contrib/verifysfbinaries/verify.sh rename to contrib/verifybinaries/verify.sh From f8e6fb1800fbac87e76cdddc074d8f4af585f050 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 25 Apr 2016 12:31:45 +0200 Subject: [PATCH 0207/1802] Introduce constant for maximum CScript length --- src/script/interpreter.cpp | 2 +- src/script/script.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 9c47f7c6c9577..fd4a5674cfea1 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -247,7 +247,7 @@ bool EvalScript(vector >& stack, const CScript& script, un vector vfExec; vector altstack; set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR); - if (script.size() > 10000) + if (script.size() > MAX_SCRIPT_SIZE) return set_error(serror, SCRIPT_ERR_SCRIPT_SIZE); int nOpCount = 0; bool fRequireMinimal = (flags & SCRIPT_VERIFY_MINIMALDATA) != 0; diff --git a/src/script/script.h b/src/script/script.h index d2a68a07ba149..68cde03e34543 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -27,6 +27,9 @@ static const int MAX_OPS_PER_SCRIPT = 201; // Maximum number of public keys per multisig static const int MAX_PUBKEYS_PER_MULTISIG = 20; +// Maximum script length in bytes +static const int MAX_SCRIPT_SIZE = 10000; + // Threshold for nLockTime: below this value it is interpreted as block number, // otherwise as UNIX timestamp. static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC From 4f87af6fc7580912726f9bf833c21e6e1b478e1d Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 25 Apr 2016 12:32:01 +0200 Subject: [PATCH 0208/1802] Treat overly long scriptPubKeys as unspendable --- src/script/script.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/script/script.h b/src/script/script.h index 68cde03e34543..2a338d6f5ccbf 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -624,7 +624,7 @@ class CScript : public CScriptBase */ bool IsUnspendable() const { - return (size() > 0 && *begin() == OP_RETURN); + return (size() > 0 && *begin() == OP_RETURN) || (size() > MAX_SCRIPT_SIZE); } void clear() From 4bf631e5e48cd4c14c825cdaf7a1bee81e15493d Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Sun, 24 Apr 2016 21:59:46 -0700 Subject: [PATCH 0209/1802] CDataStream::ignore Throw exception instead of assert on negative nSize. Previously disk corruption would cause an assert instead of an exception. --- src/streams.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/streams.h b/src/streams.h index 0fc6135a6a793..a50fe4e859d77 100644 --- a/src/streams.h +++ b/src/streams.h @@ -240,7 +240,9 @@ class CDataStream CDataStream& ignore(int nSize) { // Ignore from the beginning of the buffer - assert(nSize >= 0); + if (nSize < 0) { + throw std::ios_base::failure("CDataStream::ignore(): nSize negative"); + } unsigned int nReadPosNext = nReadPos + nSize; if (nReadPosNext >= vch.size()) { From 5d0434d13d0145a110c0c93e59edfd7d062f8531 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 24 Apr 2016 16:21:44 +0200 Subject: [PATCH 0210/1802] Fix OOM bug: UTXO entries with invalid script length --- src/compressor.h | 10 ++++++++-- src/streams.h | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/compressor.h b/src/compressor.h index 4a72090830587..fa702f0dfa900 100644 --- a/src/compressor.h +++ b/src/compressor.h @@ -86,8 +86,14 @@ class CScriptCompressor return; } nSize -= nSpecialScripts; - script.resize(nSize); - s >> REF(CFlatData(script)); + if (nSize > MAX_SCRIPT_SIZE) { + // Overly long script, replace with a short invalid one + script << OP_RETURN; + s.ignore(nSize); + } else { + script.resize(nSize); + s >> REF(CFlatData(script)); + } } }; diff --git a/src/streams.h b/src/streams.h index a50fe4e859d77..ed14f3f412172 100644 --- a/src/streams.h +++ b/src/streams.h @@ -406,6 +406,20 @@ class CAutoFile return (*this); } + CAutoFile& ignore(size_t nSize) + { + if (!file) + throw std::ios_base::failure("CAutoFile::ignore: file handle is NULL"); + unsigned char data[4096]; + while (nSize > 0) { + size_t nNow = std::min(nSize, sizeof(data)); + if (fread(data, 1, nNow, file) != nNow) + throw std::ios_base::failure(feof(file) ? "CAutoFile::ignore: end of file" : "CAutoFile::read: fread failed"); + nSize -= nNow; + } + return (*this); + } + CAutoFile& write(const char* pch, size_t nSize) { if (!file) From 1e44169f0e0c334a86b14a22ebc8fec45cec7354 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 25 Apr 2016 14:05:36 +0200 Subject: [PATCH 0211/1802] Add tests for CCoins deserialization --- src/test/coins_tests.cpp | 71 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 48e3c8ed8e07f..129ce04e0bca1 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -4,7 +4,9 @@ #include "coins.h" #include "random.h" +#include "script/standard.h" #include "uint256.h" +#include "utilstrencodings.h" #include "test/test_bitcoin.h" #include "main.h" #include "consensus/validation.h" @@ -345,4 +347,73 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) BOOST_CHECK(spent_a_duplicate_coinbase); } +BOOST_AUTO_TEST_CASE(ccoins_serialization) +{ + // Good example + CDataStream ss1(ParseHex("0104835800816115944e077fe7c803cfa57f29b36bf87c1d358bb85e"), SER_DISK, CLIENT_VERSION); + CCoins cc1; + ss1 >> cc1; + BOOST_CHECK_EQUAL(cc1.nVersion, 1); + BOOST_CHECK_EQUAL(cc1.fCoinBase, false); + BOOST_CHECK_EQUAL(cc1.nHeight, 203998); + BOOST_CHECK_EQUAL(cc1.vout.size(), 2); + BOOST_CHECK_EQUAL(cc1.IsAvailable(0), false); + BOOST_CHECK_EQUAL(cc1.IsAvailable(1), true); + BOOST_CHECK_EQUAL(cc1.vout[1].nValue, 60000000000ULL); + BOOST_CHECK_EQUAL(HexStr(cc1.vout[1].scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("816115944e077fe7c803cfa57f29b36bf87c1d35")))))); + + // Good example + CDataStream ss2(ParseHex("0109044086ef97d5790061b01caab50f1b8e9c50a5057eb43c2d9563a4eebbd123008c988f1a4a4de2161e0f50aac7f17e7f9555caa486af3b"), SER_DISK, CLIENT_VERSION); + CCoins cc2; + ss2 >> cc2; + BOOST_CHECK_EQUAL(cc2.nVersion, 1); + BOOST_CHECK_EQUAL(cc2.fCoinBase, true); + BOOST_CHECK_EQUAL(cc2.nHeight, 120891); + BOOST_CHECK_EQUAL(cc2.vout.size(), 17); + for (int i = 0; i < 17; i++) { + BOOST_CHECK_EQUAL(cc2.IsAvailable(i), i == 4 || i == 16); + } + BOOST_CHECK_EQUAL(cc2.vout[4].nValue, 234925952); + BOOST_CHECK_EQUAL(HexStr(cc2.vout[4].scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("61b01caab50f1b8e9c50a5057eb43c2d9563a4ee")))))); + BOOST_CHECK_EQUAL(cc2.vout[16].nValue, 110397); + BOOST_CHECK_EQUAL(HexStr(cc2.vout[16].scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("8c988f1a4a4de2161e0f50aac7f17e7f9555caa4")))))); + + // Smallest possible example + CDataStream ssx(SER_DISK, CLIENT_VERSION); + BOOST_CHECK_EQUAL(HexStr(ssx.begin(), ssx.end()), ""); + + CDataStream ss3(ParseHex("0002000600"), SER_DISK, CLIENT_VERSION); + CCoins cc3; + ss3 >> cc3; + BOOST_CHECK_EQUAL(cc3.nVersion, 0); + BOOST_CHECK_EQUAL(cc3.fCoinBase, false); + BOOST_CHECK_EQUAL(cc3.nHeight, 0); + BOOST_CHECK_EQUAL(cc3.vout.size(), 1); + BOOST_CHECK_EQUAL(cc3.IsAvailable(0), true); + BOOST_CHECK_EQUAL(cc3.vout[0].nValue, 0); + BOOST_CHECK_EQUAL(cc3.vout[0].scriptPubKey.size(), 0); + + // scriptPubKey that ends beyond the end of the stream + CDataStream ss4(ParseHex("0002000800"), SER_DISK, CLIENT_VERSION); + try { + CCoins cc4; + ss4 >> cc4; + BOOST_CHECK_MESSAGE(false, "We should have thrown"); + } catch (const std::ios_base::failure& e) { + } + + // Very large scriptPubKey (3*10^9 bytes) past the end of the stream + CDataStream tmp(SER_DISK, CLIENT_VERSION); + uint64_t x = 3000000000ULL; + tmp << VARINT(x); + BOOST_CHECK_EQUAL(HexStr(tmp.begin(), tmp.end()), "8a95c0bb00"); + CDataStream ss5(ParseHex("0002008a95c0bb0000"), SER_DISK, CLIENT_VERSION); + try { + CCoins cc5; + ss5 >> cc5; + BOOST_CHECK_MESSAGE(false, "We should have thrown"); + } catch (const std::ios_base::failure& e) { + } +} + BOOST_AUTO_TEST_SUITE_END() From 17a6a217867603f349de676739f072c789c3918f Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 25 Apr 2016 16:01:28 +0200 Subject: [PATCH 0212/1802] qt: Make it possible to show details for multiple transactions A small GUI annoyance for me has always been that it's impossible to have multiple transaction detail windows open, for example to compare transactions. This patch makes the window non-modal so that it is possible to open transaction details at will. --- src/qt/transactionview.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index a352228c36fb5..eb6111e682e9f 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -478,8 +478,9 @@ void TransactionView::showDetails() QModelIndexList selection = transactionView->selectionModel()->selectedRows(); if(!selection.isEmpty()) { - TransactionDescDialog dlg(selection.at(0)); - dlg.exec(); + TransactionDescDialog *dlg = new TransactionDescDialog(selection.at(0)); + dlg->setAttribute(Qt::WA_DeleteOnClose); + dlg->show(); } } From 62a9abd12b27d94cddae2b38f94bb44fead34235 Mon Sep 17 00:00:00 2001 From: Chris Stewart Date: Mon, 25 Apr 2016 11:08:10 -0500 Subject: [PATCH 0213/1802] Fixing comment in script_test.json test case --- src/test/data/script_tests.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json index e69cc9e41371e..e75b7825ed545 100644 --- a/src/test/data/script_tests.json +++ b/src/test/data/script_tests.json @@ -1098,7 +1098,7 @@ "NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG", "P2SH,STRICTENC", "OP_COUNT", -"Fails due to 201 sig op limit"], +"Fails due to 201 script operation limit"], ["1", "NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY", From efb54ba065e41e0d36383bcabfcc01bbca7b2340 Mon Sep 17 00:00:00 2001 From: Kaz Wesley Date: Mon, 25 Apr 2016 13:13:52 -0700 Subject: [PATCH 0214/1802] lock cs_main for State/Misbehaving ProcessMessage calls State(...) and Misbehaving(...) without holding the required lock; add LOCK(cs_main) blocks. --- src/main.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index f6a89fa2e675a..a85ee46d5aa7d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4514,6 +4514,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, strCommand == NetMsgType::FILTERCLEAR)) { if (pfrom->nVersion >= NO_BLOOM_VERSION) { + LOCK(cs_main); Misbehaving(pfrom->GetId(), 100); return false; } else { @@ -4529,6 +4530,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, if (pfrom->nVersion != 0) { pfrom->PushMessage(NetMsgType::REJECT, strCommand, REJECT_DUPLICATE, string("Duplicate version message")); + LOCK(cs_main); Misbehaving(pfrom->GetId(), 1); return false; } @@ -4584,7 +4586,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, pfrom->fClient = !(pfrom->nServices & NODE_NETWORK); // Potentially mark this peer as a preferred download peer. + { + LOCK(cs_main); UpdatePreferredDownload(pfrom, State(pfrom->GetId())); + } // Change version pfrom->PushMessage(NetMsgType::VERACK); @@ -4642,6 +4647,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, else if (pfrom->nVersion == 0) { // Must have a version message before anything else + LOCK(cs_main); Misbehaving(pfrom->GetId(), 1); return false; } @@ -4677,6 +4683,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, return true; if (vAddr.size() > 1000) { + LOCK(cs_main); Misbehaving(pfrom->GetId(), 20); return error("message addr size() = %u", vAddr.size()); } @@ -4746,6 +4753,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, vRecv >> vInv; if (vInv.size() > MAX_INV_SZ) { + LOCK(cs_main); Misbehaving(pfrom->GetId(), 20); return error("message inv size() = %u", vInv.size()); } @@ -4821,6 +4829,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, vRecv >> vInv; if (vInv.size() > MAX_INV_SZ) { + LOCK(cs_main); Misbehaving(pfrom->GetId(), 20); return error("message getdata size() = %u", vInv.size()); } @@ -5074,6 +5083,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // Bypass the normal CBlock deserialization, as we don't want to risk deserializing 2000 full blocks. unsigned int nCount = ReadCompactSize(vRecv); if (nCount > MAX_HEADERS_RESULTS) { + LOCK(cs_main); Misbehaving(pfrom->GetId(), 20); return error("headers message size = %u", nCount); } @@ -5350,8 +5360,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, vRecv >> filter; if (!filter.IsWithinSizeConstraints()) + { // There is no excuse for sending a too-large filter + LOCK(cs_main); Misbehaving(pfrom->GetId(), 100); + } else { LOCK(pfrom->cs_filter); @@ -5372,13 +5385,17 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // and thus, the maximum size any matched object can have) in a filteradd message if (vData.size() > MAX_SCRIPT_ELEMENT_SIZE) { + LOCK(cs_main); Misbehaving(pfrom->GetId(), 100); } else { LOCK(pfrom->cs_filter); if (pfrom->pfilter) pfrom->pfilter->insert(vData); else + { + LOCK(cs_main); Misbehaving(pfrom->GetId(), 100); + } } } From 719de56ab2c8e5bc6ce9f67c7bf159adc242d49b Mon Sep 17 00:00:00 2001 From: Kaz Wesley Date: Mon, 25 Apr 2016 12:31:32 -0700 Subject: [PATCH 0215/1802] lock cs_main for chainActive ActivateBestChain uses chainActive after releasing the lock; reorder operations to move all access to synchronized object into existing LOCK(cs_main) block. --- src/main.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index a85ee46d5aa7d..83fc4d6bd8843 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2897,14 +2897,15 @@ static bool ActivateBestChainStep(CValidationState& state, const CChainParams& c */ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, const CBlock *pblock) { CBlockIndex *pindexMostWork = NULL; + CBlockIndex *pindexNewTip = NULL; do { boost::this_thread::interruption_point(); if (ShutdownRequested()) break; - CBlockIndex *pindexNewTip = NULL; const CBlockIndex *pindexFork; bool fInitialDownload; + int nNewHeight; { LOCK(cs_main); CBlockIndex *pindexOldTip = chainActive.Tip(); @@ -2920,6 +2921,7 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, pindexNewTip = chainActive.Tip(); pindexFork = chainActive.FindFork(pindexOldTip); fInitialDownload = IsInitialBlockDownload(); + nNewHeight = chainActive.Height(); } // When we reach this point, we switched to a new tip (stored in pindexNewTip). @@ -2948,7 +2950,7 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, { LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) { - if (chainActive.Height() > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate)) { + if (nNewHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate)) { BOOST_REVERSE_FOREACH(const uint256& hash, vHashes) { pnode->PushBlockHash(hash); } @@ -2961,7 +2963,7 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, } } } - } while(pindexMostWork != chainActive.Tip()); + } while (pindexNewTip != pindexMostWork); CheckBlockIndex(chainparams.GetConsensus()); // Write changes periodically to disk, after relay. From 9267a47d86d0673eae9e504ee566aa4e0410d923 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Mon, 25 Apr 2016 22:27:59 -0400 Subject: [PATCH 0216/1802] depends: enable pre-compiled headers for qt All trusty compilers work ok with this now, and it shaves a few minutes off of build time --- depends/packages/qt.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index 77df77b73f7f0..e5ac0c9651bc7 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -31,7 +31,7 @@ $(package)_config_opts += -no-iconv $(package)_config_opts += -no-gif $(package)_config_opts += -no-freetype $(package)_config_opts += -no-nis -$(package)_config_opts += -no-pch +$(package)_config_opts += -pch $(package)_config_opts += -no-qml-debug $(package)_config_opts += -nomake examples $(package)_config_opts += -nomake tests From cf77fcdb1fe525b63b004ef729173f04bdb48882 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Mon, 25 Apr 2016 22:29:23 -0400 Subject: [PATCH 0217/1802] travis: drop MAKEJOBS=2 for windows compilers These were only in place because of the old precice mingw toolchain --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0c9ac71c00b06..804686a34a5d4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,11 +37,11 @@ matrix: - compiler: ": ARM" env: HOST=arm-linux-gnueabihf PACKAGES="g++-arm-linux-gnueabihf" DEP_OPTS="NO_QT=1" CHECK_DOC=1 GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" - compiler: ": Win32" - env: HOST=i686-w64-mingw32 DPKG_ADD_ARCH="i386" PACKAGES="nsis g++-mingw-w64-i686 wine1.6 bc" RUN_TESTS=true GOAL="deploy" BITCOIN_CONFIG="--enable-gui --enable-reduce-exports" MAKEJOBS="-j2" + env: HOST=i686-w64-mingw32 DPKG_ADD_ARCH="i386" PACKAGES="nsis g++-mingw-w64-i686 wine1.6 bc" RUN_TESTS=true GOAL="deploy" BITCOIN_CONFIG="--enable-gui --enable-reduce-exports" - compiler: ": 32-bit + dash" env: HOST=i686-pc-linux-gnu PACKAGES="g++-multilib bc python-zmq" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++" USE_SHELL="/bin/dash" - compiler: ": Win64" - env: HOST=x86_64-w64-mingw32 DPKG_ADD_ARCH="i386" PACKAGES="nsis g++-mingw-w64-x86-64 wine1.6 bc" RUN_TESTS=true GOAL="deploy" BITCOIN_CONFIG="--enable-gui --enable-reduce-exports" MAKEJOBS="-j2" + env: HOST=x86_64-w64-mingw32 DPKG_ADD_ARCH="i386" PACKAGES="nsis g++-mingw-w64-x86-64 wine1.6 bc" RUN_TESTS=true GOAL="deploy" BITCOIN_CONFIG="--enable-gui --enable-reduce-exports" - compiler: ": bitcoind" env: HOST=x86_64-unknown-linux-gnu PACKAGES="bc python-zmq" DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports CPPFLAGS=-DDEBUG_LOCKORDER" - compiler: ": No wallet" From 174023c9b008fc02316bce972b0c1031de3feee3 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 26 Apr 2016 01:17:46 -0400 Subject: [PATCH 0218/1802] travis: Don't disable writing ccache for pull-requests This was doing more harm than good. The original intention was to speed up builds, since a PR's ccache results will be thrown away anyway. However, each PR maintains its own cache, so disabling writes means that subsequent pushes don't benefit from the fresh cache. This is significant when (for example) many headers are touched in a PR, then the PR is updated. With this change, the updated PR will take advantage of the cache generated during the PR's previous build. --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 804686a34a5d4..25e9cc1e05647 100644 --- a/.travis.yml +++ b/.travis.yml @@ -71,7 +71,6 @@ script: - OUTDIR=$BASE_OUTDIR/$TRAVIS_PULL_REQUEST/$TRAVIS_JOB_NUMBER-$HOST - BITCOIN_CONFIG_ALL="--disable-dependency-tracking --prefix=$TRAVIS_BUILD_DIR/depends/$HOST --bindir=$OUTDIR/bin --libdir=$OUTDIR/lib" - depends/$HOST/native/bin/ccache --max-size=$CCACHE_SIZE - - if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then export CCACHE_READONLY=1; fi - test -n "$USE_SHELL" && eval '"$USE_SHELL" -c "./autogen.sh"' || ./autogen.sh - ./configure --cache-file=config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false) - make distdir PACKAGE=bitcoin VERSION=$HOST From a33b7c9cb545985771d074748c0e368ca2d06702 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 26 Apr 2016 00:54:57 -0400 Subject: [PATCH 0219/1802] travis: temporarily disable qt to avoid timeouts These builds take longer than they did on precise. Disable them now to keep things working, we can re-enable them after experimentation --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 25e9cc1e05647..2f3ea4e76f859 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,11 +37,11 @@ matrix: - compiler: ": ARM" env: HOST=arm-linux-gnueabihf PACKAGES="g++-arm-linux-gnueabihf" DEP_OPTS="NO_QT=1" CHECK_DOC=1 GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" - compiler: ": Win32" - env: HOST=i686-w64-mingw32 DPKG_ADD_ARCH="i386" PACKAGES="nsis g++-mingw-w64-i686 wine1.6 bc" RUN_TESTS=true GOAL="deploy" BITCOIN_CONFIG="--enable-gui --enable-reduce-exports" + env: HOST=i686-w64-mingw32 DPKG_ADD_ARCH="i386" DEP_OPTS="NO_QT=1" PACKAGES="nsis g++-mingw-w64-i686 wine1.6 bc" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-reduce-exports" - compiler: ": 32-bit + dash" - env: HOST=i686-pc-linux-gnu PACKAGES="g++-multilib bc python-zmq" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++" USE_SHELL="/bin/dash" + env: HOST=i686-pc-linux-gnu PACKAGES="g++-multilib bc python-zmq" DEP_OPTS="NO_QT=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++" USE_SHELL="/bin/dash" - compiler: ": Win64" - env: HOST=x86_64-w64-mingw32 DPKG_ADD_ARCH="i386" PACKAGES="nsis g++-mingw-w64-x86-64 wine1.6 bc" RUN_TESTS=true GOAL="deploy" BITCOIN_CONFIG="--enable-gui --enable-reduce-exports" + env: HOST=x86_64-w64-mingw32 DPKG_ADD_ARCH="i386" DEP_OPTS="NO_QT=1" PACKAGES="nsis g++-mingw-w64-x86-64 wine1.6 bc" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-reduce-exports" - compiler: ": bitcoind" env: HOST=x86_64-unknown-linux-gnu PACKAGES="bc python-zmq" DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports CPPFLAGS=-DDEBUG_LOCKORDER" - compiler: ": No wallet" From 89c844df14046a114bebec959bd9e188bf8ba21b Mon Sep 17 00:00:00 2001 From: randy-waterhouse Date: Tue, 26 Apr 2016 19:43:14 +1200 Subject: [PATCH 0220/1802] Re-instate TARGET_OS=linux in configure.ac. Removed by 351abf9e035. --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index 03b90521045ed..100bb79e11fea 100644 --- a/configure.ac +++ b/configure.ac @@ -354,6 +354,7 @@ case $host in OBJCXXFLAGS="$CXXFLAGS" ;; *linux*) + TARGET_OS=linux LEVELDB_TARGET_FLAGS="-DOS_LINUX" ;; *) From f135e3c943a19096485b0979918f8878f7fa1c8d Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 26 Apr 2016 16:01:45 +0200 Subject: [PATCH 0221/1802] qt: Add transaction hash to details window title --- src/qt/forms/transactiondescdialog.ui | 2 +- src/qt/transactiondescdialog.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/qt/forms/transactiondescdialog.ui b/src/qt/forms/transactiondescdialog.ui index 5ae1e12856631..3a698cfd1d408 100644 --- a/src/qt/forms/transactiondescdialog.ui +++ b/src/qt/forms/transactiondescdialog.ui @@ -11,7 +11,7 @@ - Transaction details + Transaction details diff --git a/src/qt/transactiondescdialog.cpp b/src/qt/transactiondescdialog.cpp index f7b6995b239c3..65adcc4f023e3 100644 --- a/src/qt/transactiondescdialog.cpp +++ b/src/qt/transactiondescdialog.cpp @@ -14,6 +14,7 @@ TransactionDescDialog::TransactionDescDialog(const QModelIndex &idx, QWidget *pa ui(new Ui::TransactionDescDialog) { ui->setupUi(this); + setWindowTitle(tr("Details for %1").arg(idx.data(TransactionTableModel::TxIDRole).toString())); QString desc = idx.data(TransactionTableModel::LongDescriptionRole).toString(); ui->detailText->setHtml(desc); } From 67969af09f4729d041589da5f31ac40c07d2f4be Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 3 Dec 2015 14:44:57 +0100 Subject: [PATCH 0222/1802] build: Enable C++11 build, require C++11 compiler Implements #6211. --- build-aux/m4/ax_cxx_compile_stdcxx.m4 | 558 ++++++++++++++++++++++++++ configure.ac | 2 + 2 files changed, 560 insertions(+) create mode 100644 build-aux/m4/ax_cxx_compile_stdcxx.m4 diff --git a/build-aux/m4/ax_cxx_compile_stdcxx.m4 b/build-aux/m4/ax_cxx_compile_stdcxx.m4 new file mode 100644 index 0000000000000..079e17d2a629e --- /dev/null +++ b/build-aux/m4/ax_cxx_compile_stdcxx.m4 @@ -0,0 +1,558 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the specified +# version of the C++ standard. If necessary, add switches to CXXFLAGS to +# enable support. VERSION may be '11' (for the C++11 standard) or '14' +# (for the C++14 standard). +# +# The second argument, if specified, indicates whether you insist on an +# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. +# -std=c++11). If neither is specified, you get whatever works, with +# preference for an extended mode. +# +# The third argument, if specified 'mandatory' or if left unspecified, +# indicates that baseline support for the specified C++ standard is +# required and that the macro should error out if no mode with that +# support is found. If specified 'optional', then configuration proceeds +# regardless, after defining HAVE_CXX${VERSION} if and only if a +# supporting mode is found. +# +# LICENSE +# +# Copyright (c) 2008 Benjamin Kosnik +# Copyright (c) 2012 Zack Weinberg +# Copyright (c) 2013 Roy Stogner +# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov +# Copyright (c) 2015 Paul Norman +# Copyright (c) 2015 Moritz Klammler +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 1 + +dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro +dnl (serial version number 13). + +AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl + m4_if([$1], [11], [], + [$1], [14], [], + [$1], [17], [m4_fatal([support for C++17 not yet implemented in AX_CXX_COMPILE_STDCXX])], + [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$2], [], [], + [$2], [ext], [], + [$2], [noext], [], + [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], + [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], + [$3], [optional], [ax_cxx_compile_cxx$1_required=false], + [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) + AC_LANG_PUSH([C++])dnl + ac_success=no + AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, + ax_cv_cxx_compile_cxx$1, + [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [ax_cv_cxx_compile_cxx$1=yes], + [ax_cv_cxx_compile_cxx$1=no])]) + if test x$ax_cv_cxx_compile_cxx$1 = xyes; then + ac_success=yes + fi + + m4_if([$2], [noext], [], [dnl + if test x$ac_success = xno; then + for switch in -std=gnu++$1 -std=gnu++0x; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXXFLAGS="$ac_save_CXXFLAGS"]) + if eval test x\$$cachevar = xyes; then + CXXFLAGS="$CXXFLAGS $switch" + ac_success=yes + break + fi + done + fi]) + + m4_if([$2], [ext], [], [dnl + if test x$ac_success = xno; then + dnl HP's aCC needs +std=c++11 according to: + dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf + dnl Cray's crayCC needs "-h std=c++11" + for switch in -std=c++$1 -std=c++0x +std=c++$1 "-h std=c++$1"; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXXFLAGS="$ac_save_CXXFLAGS"]) + if eval test x\$$cachevar = xyes; then + CXXFLAGS="$CXXFLAGS $switch" + ac_success=yes + break + fi + done + fi]) + AC_LANG_POP([C++]) + if test x$ax_cxx_compile_cxx$1_required = xtrue; then + if test x$ac_success = xno; then + AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) + fi + else + if test x$ac_success = xno; then + HAVE_CXX$1=0 + AC_MSG_NOTICE([No compiler with C++$1 support was found]) + else + HAVE_CXX$1=1 + AC_DEFINE(HAVE_CXX$1,1, + [define if the compiler supports basic C++$1 syntax]) + fi + + AC_SUBST(HAVE_CXX$1) + fi +]) + + +dnl Test body for checking C++11 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 +) + + +dnl Test body for checking C++14 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 +) + + +dnl Tests for new features in C++11 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ + +// If the compiler admits that it is not ready for C++11, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201103L + +#error "This is not a C++11 compiler" + +#else + +namespace cxx11 +{ + + namespace test_static_assert + { + + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + } + + namespace test_final_override + { + + struct Base + { + virtual void f() {} + }; + + struct Derived : public Base + { + virtual void f() override {} + }; + + } + + namespace test_double_right_angle_brackets + { + + template < typename T > + struct check {}; + + typedef check single_type; + typedef check> double_type; + typedef check>> triple_type; + typedef check>>> quadruple_type; + + } + + namespace test_decltype + { + + int + f() + { + int a = 1; + decltype(a) b = 2; + return a + b; + } + + } + + namespace test_type_deduction + { + + template < typename T1, typename T2 > + struct is_same + { + static const bool value = false; + }; + + template < typename T > + struct is_same + { + static const bool value = true; + }; + + template < typename T1, typename T2 > + auto + add(T1 a1, T2 a2) -> decltype(a1 + a2) + { + return a1 + a2; + } + + int + test(const int c, volatile int v) + { + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == false, ""); + auto ac = c; + auto av = v; + auto sumi = ac + av + 'x'; + auto sumf = ac + av + 1.0; + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == true, ""); + return (sumf > 0.0) ? sumi : add(c, v); + } + + } + + namespace test_noexcept + { + + int f() { return 0; } + int g() noexcept { return 0; } + + static_assert(noexcept(f()) == false, ""); + static_assert(noexcept(g()) == true, ""); + + } + + namespace test_constexpr + { + + template < typename CharT > + unsigned long constexpr + strlen_c_r(const CharT *const s, const unsigned long acc) noexcept + { + return *s ? strlen_c_r(s + 1, acc + 1) : acc; + } + + template < typename CharT > + unsigned long constexpr + strlen_c(const CharT *const s) noexcept + { + return strlen_c_r(s, 0UL); + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("1") == 1UL, ""); + static_assert(strlen_c("example") == 7UL, ""); + static_assert(strlen_c("another\0example") == 7UL, ""); + + } + + namespace test_rvalue_references + { + + template < int N > + struct answer + { + static constexpr int value = N; + }; + + answer<1> f(int&) { return answer<1>(); } + answer<2> f(const int&) { return answer<2>(); } + answer<3> f(int&&) { return answer<3>(); } + + void + test() + { + int i = 0; + const int c = 0; + static_assert(decltype(f(i))::value == 1, ""); + static_assert(decltype(f(c))::value == 2, ""); + static_assert(decltype(f(0))::value == 3, ""); + } + + } + + namespace test_uniform_initialization + { + + struct test + { + static const int zero {}; + static const int one {1}; + }; + + static_assert(test::zero == 0, ""); + static_assert(test::one == 1, ""); + + } + + namespace test_lambdas + { + + void + test1() + { + auto lambda1 = [](){}; + auto lambda2 = lambda1; + lambda1(); + lambda2(); + } + + int + test2() + { + auto a = [](int i, int j){ return i + j; }(1, 2); + auto b = []() -> int { return '0'; }(); + auto c = [=](){ return a + b; }(); + auto d = [&](){ return c; }(); + auto e = [a, &b](int x) mutable { + const auto identity = [](int y){ return y; }; + for (auto i = 0; i < a; ++i) + a += b--; + return x + identity(a + b); + }(0); + return a + b + c + d + e; + } + + int + test3() + { + const auto nullary = [](){ return 0; }; + const auto unary = [](int x){ return x; }; + using nullary_t = decltype(nullary); + using unary_t = decltype(unary); + const auto higher1st = [](nullary_t f){ return f(); }; + const auto higher2nd = [unary](nullary_t f1){ + return [unary, f1](unary_t f2){ return f2(unary(f1())); }; + }; + return higher1st(nullary) + higher2nd(nullary)(unary); + } + + } + + namespace test_variadic_templates + { + + template + struct sum; + + template + struct sum + { + static constexpr auto value = N0 + sum::value; + }; + + template <> + struct sum<> + { + static constexpr auto value = 0; + }; + + static_assert(sum<>::value == 0, ""); + static_assert(sum<1>::value == 1, ""); + static_assert(sum<23>::value == 23, ""); + static_assert(sum<1, 2>::value == 3, ""); + static_assert(sum<5, 5, 11>::value == 21, ""); + static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); + + } + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function + // because of this. + namespace test_template_alias_sfinae + { + + struct foo {}; + + template + using member = typename T::member_type; + + template + void func(...) {} + + template + void func(member*) {} + + void test(); + + void test() { func(0); } + + } + +} // namespace cxx11 + +#endif // __cplusplus >= 201103L + +]]) + + +dnl Tests for new features in C++14 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ + +// If the compiler admits that it is not ready for C++14, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201402L + +#error "This is not a C++14 compiler" + +#else + +namespace cxx14 +{ + + namespace test_polymorphic_lambdas + { + + int + test() + { + const auto lambda = [](auto&&... args){ + const auto istiny = [](auto x){ + return (sizeof(x) == 1UL) ? 1 : 0; + }; + const int aretiny[] = { istiny(args)... }; + return aretiny[0]; + }; + return lambda(1, 1L, 1.0f, '1'); + } + + } + + namespace test_binary_literals + { + + constexpr auto ivii = 0b0000000000101010; + static_assert(ivii == 42, "wrong value"); + + } + + namespace test_generalized_constexpr + { + + template < typename CharT > + constexpr unsigned long + strlen_c(const CharT *const s) noexcept + { + auto length = 0UL; + for (auto p = s; *p; ++p) + ++length; + return length; + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("x") == 1UL, ""); + static_assert(strlen_c("test") == 4UL, ""); + static_assert(strlen_c("another\0test") == 7UL, ""); + + } + + namespace test_lambda_init_capture + { + + int + test() + { + auto x = 0; + const auto lambda1 = [a = x](int b){ return a + b; }; + const auto lambda2 = [a = lambda1(x)](){ return a; }; + return lambda2(); + } + + } + + namespace test_digit_seperators + { + + constexpr auto ten_million = 100'000'000; + static_assert(ten_million == 100000000, ""); + + } + + namespace test_return_type_deduction + { + + auto f(int& x) { return x; } + decltype(auto) g(int& x) { return x; } + + template < typename T1, typename T2 > + struct is_same + { + static constexpr auto value = false; + }; + + template < typename T > + struct is_same + { + static constexpr auto value = true; + }; + + int + test() + { + auto x = 0; + static_assert(is_same::value, ""); + static_assert(is_same::value, ""); + return x; + } + + } + +} // namespace cxx14 + +#endif // __cplusplus >= 201402L + +]]) diff --git a/configure.ac b/configure.ac index 100bb79e11fea..713ea59edacf9 100644 --- a/configure.ac +++ b/configure.ac @@ -55,6 +55,8 @@ case $host in lt_cv_deplibs_check_method="pass_all" ;; esac +dnl Require C++11 compiler (no GNU extensions) +AX_CXX_COMPILE_STDCXX([11], [noext], [mandatory]) dnl Libtool init checks. LT_INIT([pic-only]) From fada064f67302502f6b51d9d22927381c2707cbb Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Tue, 26 Apr 2016 18:11:42 +0200 Subject: [PATCH 0223/1802] [qa] test_framework: Properly print exceptions and assert empty dict --- qa/rpc-tests/test_framework/test_framework.py | 2 +- qa/rpc-tests/test_framework/util.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/qa/rpc-tests/test_framework/test_framework.py b/qa/rpc-tests/test_framework/test_framework.py index 3b08cd1384d4e..18ecf64b06e59 100755 --- a/qa/rpc-tests/test_framework/test_framework.py +++ b/qa/rpc-tests/test_framework/test_framework.py @@ -146,7 +146,7 @@ def main(self): print("key not found: "+ str(e)) traceback.print_tb(sys.exc_info()[2]) except Exception as e: - print("Unexpected exception caught during testing: "+str(e)) + print("Unexpected exception caught during testing: " + repr(e)) traceback.print_tb(sys.exc_info()[2]) if not self.options.noshutdown: diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index 27891f7f4c383..baa1ed6790724 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -487,7 +487,7 @@ def assert_array_result(object_array, to_match, expected, should_not_find = Fals in object_array """ if should_not_find == True: - expected = { } + assert_equal(expected, { }) num_matched = 0 for item in object_array: all_match = True From 61c01706cd1d38023facea7f25bc1d84980f8c43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Tue, 26 Apr 2016 22:22:59 +0200 Subject: [PATCH 0224/1802] Log invalid block hash to make debugging easier. --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index f6a89fa2e675a..a8f8e6fa5b104 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3371,7 +3371,7 @@ static bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state if (ppindex) *ppindex = pindex; if (pindex->nStatus & BLOCK_FAILED_MASK) - return state.Invalid(error("%s: block is marked invalid", __func__), 0, "duplicate"); + return state.Invalid(error("%s: block %s is marked invalid", __func__, hash.ToString()), 0, "duplicate"); return true; } From 63b3111f84daa421abc2889a550e86c17bf9609d Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 9 Mar 2016 16:45:58 -0500 Subject: [PATCH 0225/1802] build: quiet annoying warnings without adding new ones Disabling warnings can be tricky, because doing so can cause a different compiler to create new warnings about unsupported disable flags. Also, some warnings don't surface until they're paired with another warning (gcc). For example, adding "-Wno-foo" won't cause any trouble, but if there's a legitimate warning emitted, the "unknown option -Wno-foo" will show up as well. Work around this in 2 ways: 1. When checking to see if -Wno-foo is supported, check for "-Wfoo" instead. 2. Enable -Werror while checking 1. If "-Werror -Wfoo" compiles, "-Wno-foo" is almost guaranteed to be supported. -Werror itself is also checked. If that fails to compile by itself, it likely means that the user added a flag that adds a warning. In that case, -Werror won't be used while checking, and the build may be extra noisy. The user would need to fix the bad input flag. Also, silence 2 more additional warnings that can show up post-c++11. --- configure.ac | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index 100bb79e11fea..e73f7e0868e65 100644 --- a/configure.ac +++ b/configure.ac @@ -185,6 +185,9 @@ AC_ARG_ENABLE([debug], [enable_debug=$enableval], [enable_debug=no]) +AC_LANG_PUSH([C++]) +AX_CHECK_COMPILE_FLAG([-Werror],[CXXFLAG_WERROR="-Werror"],[CXXFLAG_WERROR=""]) + if test "x$enable_debug" = xyes; then CPPFLAGS="$CPPFLAGS -DDEBUG -DDEBUG_LOCKORDER" if test "x$GCC" = xyes; then @@ -196,11 +199,19 @@ if test "x$enable_debug" = xyes; then fi fi -## TODO: Remove these hard-coded paths and flags. They are here for the sake of -## compatibility with the legacy buildsystem. -## if test "x$CXXFLAGS_overridden" = "xno"; then - CXXFLAGS="$CXXFLAGS -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter -Wno-self-assign" + AX_CHECK_COMPILE_FLAG([-Wall],[CXXFLAGS="$CXXFLAGS -Wall"],,[[$CXXFLAG_WERROR]]) + AX_CHECK_COMPILE_FLAG([-Wextra],[CXXFLAGS="$CXXFLAGS -Wextra"],,[[$CXXFLAG_WERROR]]) + AX_CHECK_COMPILE_FLAG([-Wformat],[CXXFLAGS="$CXXFLAGS -Wformat"],,[[$CXXFLAG_WERROR]]) + AX_CHECK_COMPILE_FLAG([-Wformat-security],[CXXFLAGS="$CXXFLAGS -Wformat-security"],,[[$CXXFLAG_WERROR]]) + + ## Some compilers (gcc) ignore unknown -Wno-* options, but warn about all + ## unknown options if any other warning is produced. Test the -Wfoo case, and + ## set the -Wno-foo case if it works. + AX_CHECK_COMPILE_FLAG([-Wunused-parameter],[CXXFLAGS="$CXXFLAGS -Wno-unused-parameter"],,[[$CXXFLAG_WERROR]]) + AX_CHECK_COMPILE_FLAG([-Wself-assign],[CXXFLAGS="$CXXFLAGS -Wno-self-assign"],,[[$CXXFLAG_WERROR]]) + AX_CHECK_COMPILE_FLAG([-Wunused-local-typedef],[CXXFLAGS="$CXXFLAGS -Wno-unused-local-typedef"],,[[$CXXFLAG_WERROR]]) + AX_CHECK_COMPILE_FLAG([-Wdeprecated-register],[CXXFLAGS="$CXXFLAGS -Wno-deprecated-register"],,[[$CXXFLAG_WERROR]]) fi CPPFLAGS="$CPPFLAGS -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS" @@ -222,8 +233,6 @@ AC_ARG_WITH([daemon], [build_bitcoind=$withval], [build_bitcoind=yes]) -AC_LANG_PUSH([C++]) - use_pkgconfig=yes case $host in *mingw*) From 84c13e759dbb0de282e2c8ce43d77f4d52fda6d9 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 26 Apr 2016 14:34:40 +0200 Subject: [PATCH 0226/1802] chain: Add assertion in case of missing records in index db --- src/chain.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/chain.cpp b/src/chain.cpp index 32f6480f849da..77e924e703043 100644 --- a/src/chain.cpp +++ b/src/chain.cpp @@ -93,6 +93,7 @@ CBlockIndex* CBlockIndex::GetAncestor(int height) pindexWalk = pindexWalk->pskip; heightWalk = heightSkip; } else { + assert(pindexWalk->pprev); pindexWalk = pindexWalk->pprev; heightWalk--; } From 6030625631c62b0ffab2ac545c8351fa59dca483 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 27 Apr 2016 11:07:43 +0200 Subject: [PATCH 0227/1802] test: Add more thorough test for dbwrapper iterators I made a silly mistake in a database wrapper where keys were sorted by char instead of uint8_t. As x86 char is signed the sorting for the block index database was messed up, resulting in a segfault due to missing records. Add a test to catch: - Wrong sorting - Seeking errors - Iteration result not complete --- src/test/dbwrapper_tests.cpp | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp index 081d57831d0dd..8745d1439ca33 100644 --- a/src/test/dbwrapper_tests.cpp +++ b/src/test/dbwrapper_tests.cpp @@ -203,5 +203,39 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex) BOOST_CHECK(odbw.Read(key, res3)); BOOST_CHECK_EQUAL(res3.ToString(), in2.ToString()); } - + +BOOST_AUTO_TEST_CASE(iterator_ordering) +{ + path ph = temp_directory_path() / unique_path(); + CDBWrapper dbw(ph, (1 << 20), true, false, false); + for (int x=0x00; x<256; ++x) { + uint8_t key = x; + uint32_t value = x*x; + BOOST_CHECK(dbw.Write(key, value)); + } + + boost::scoped_ptr it(const_cast(&dbw)->NewIterator()); + for (int c=0; c<2; ++c) { + int seek_start; + if (c == 0) + seek_start = 0x00; + else + seek_start = 0x80; + it->Seek((uint8_t)seek_start); + for (int x=seek_start; x<256; ++x) { + uint8_t key; + uint32_t value; + BOOST_CHECK(it->Valid()); + if (!it->Valid()) // Avoid spurious errors about invalid iterator's key and value in case of failure + break; + BOOST_CHECK(it->GetKey(key)); + BOOST_CHECK(it->GetValue(value)); + BOOST_CHECK_EQUAL(key, x); + BOOST_CHECK_EQUAL(value, x*x); + it->Next(); + } + BOOST_CHECK(!it->Valid()); + } +} + BOOST_AUTO_TEST_SUITE_END() From f90efbfeef9cd733aa7590fdf581ff82b999c4b5 Mon Sep 17 00:00:00 2001 From: Andrew Date: Tue, 26 Apr 2016 13:17:00 -0400 Subject: [PATCH 0228/1802] Create signmessagewithprivkey rpc New rpc 'signmessagewithprivkey' which takes a private key to sign a message without using the wallet. --- src/rpc/misc.cpp | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index e8a099b4452c4..09f51857815e2 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -366,6 +366,48 @@ UniValue verifymessage(const UniValue& params, bool fHelp) return (pubkey.GetID() == keyID); } +UniValue signmessagewithprivkey(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 2) + throw runtime_error( + "signmessagewithprivkey \"privkey\" \"message\"\n" + "\nSign a message with the private key of an address\n" + "\nArguments:\n" + "1. \"privkey\" (string, required) The private key to sign the message with.\n" + "2. \"message\" (string, required) The message to create a signature of.\n" + "\nResult:\n" + "\"signature\" (string) The signature of the message encoded in base 64\n" + "\nExamples:\n" + "\nCreate the signature\n" + + HelpExampleCli("signmessagewithprivkey", "\"privkey\" \"my message\"") + + "\nVerify the signature\n" + + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") + + "\nAs json rpc\n" + + HelpExampleRpc("signmessagewithprivkey", "\"privkey\", \"my message\"") + ); + + string strPrivkey = params[0].get_str(); + string strMessage = params[1].get_str(); + + CBitcoinSecret vchSecret; + bool fGood = vchSecret.SetString(strPrivkey); + if (!fGood) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key"); + CKey key = vchSecret.GetKey(); + if (!key.IsValid()) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range"); + + CHashWriter ss(SER_GETHASH, 0); + ss << strMessageMagic; + ss << strMessage; + + vector vchSig; + if (!key.SignCompact(ss.GetHash(), vchSig)) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed"); + + return EncodeBase64(&vchSig[0], vchSig.size()); +} + UniValue setmocktime(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 1) @@ -404,6 +446,7 @@ static const CRPCCommand commands[] = { "util", "validateaddress", &validateaddress, true }, /* uses wallet if enabled */ { "util", "createmultisig", &createmultisig, true }, { "util", "verifymessage", &verifymessage, true }, + { "util", "signmessagewithprivkey", &signmessagewithprivkey, true }, /* Not shown in help */ { "hidden", "setmocktime", &setmocktime, true }, From a398549b3bfc976f1b6408f41af7dac3514e2553 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 21 Apr 2016 16:23:40 -0400 Subject: [PATCH 0229/1802] depends: use c++11 --- depends/hosts/darwin.mk | 2 +- depends/packages/bdb.mk | 1 + depends/packages/boost.mk | 2 +- depends/packages/protobuf.mk | 1 + depends/packages/qt.mk | 2 +- depends/packages/zeromq.mk | 1 + 6 files changed, 6 insertions(+), 3 deletions(-) diff --git a/depends/hosts/darwin.mk b/depends/hosts/darwin.mk index 2958dc50cc8dc..dbe6d00795e00 100644 --- a/depends/hosts/darwin.mk +++ b/depends/hosts/darwin.mk @@ -3,7 +3,7 @@ OSX_SDK_VERSION=10.9 OSX_SDK=$(SDK_PATH)/MacOSX$(OSX_SDK_VERSION).sdk LD64_VERSION=241.9 darwin_CC=clang -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION) -darwin_CXX=clang++ -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION) +darwin_CXX=clang++ -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION) -stdlib=libc++ darwin_CFLAGS=-pipe darwin_CXXFLAGS=$(darwin_CFLAGS) diff --git a/depends/packages/bdb.mk b/depends/packages/bdb.mk index e2f85ad4fcad8..200d57314ea0d 100644 --- a/depends/packages/bdb.mk +++ b/depends/packages/bdb.mk @@ -9,6 +9,7 @@ define $(package)_set_vars $(package)_config_opts=--disable-shared --enable-cxx --disable-replication $(package)_config_opts_mingw32=--enable-mingw $(package)_config_opts_linux=--with-pic +$(package)_cxxflags=-std=c++11 endef define $(package)_preprocess_cmds diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk index 215c694b6b82b..ef1307c241b66 100644 --- a/depends/packages/boost.mk +++ b/depends/packages/boost.mk @@ -20,7 +20,7 @@ $(package)_archiver_$(host_os)=$($(package)_ar) $(package)_toolset_darwin=darwin $(package)_archiver_darwin=$($(package)_libtool) $(package)_config_libraries=chrono,filesystem,program_options,system,thread,test -$(package)_cxxflags=-fvisibility=hidden +$(package)_cxxflags=-std=c++11 -fvisibility=hidden $(package)_cxxflags_linux=-fPIC endef diff --git a/depends/packages/protobuf.mk b/depends/packages/protobuf.mk index 5affad28375a9..54d3fd924519b 100644 --- a/depends/packages/protobuf.mk +++ b/depends/packages/protobuf.mk @@ -4,6 +4,7 @@ $(package)_download_path=$(native_$(package)_download_path) $(package)_file_name=$(native_$(package)_file_name) $(package)_sha256_hash=$(native_$(package)_sha256_hash) $(package)_dependencies=native_$(package) +$(package)_cxxflags=-std=c++11 define $(package)_set_vars $(package)_config_opts=--disable-shared --with-protoc=$(build_prefix)/bin/protoc diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index e5ac0c9651bc7..c1fc8e3058e9e 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -49,7 +49,7 @@ $(package)_config_opts += -no-sql-sqlite2 $(package)_config_opts += -prefix $(host_prefix) $(package)_config_opts += -hostprefix $(build_prefix) $(package)_config_opts += -bindir $(build_prefix)/bin -$(package)_config_opts += -no-c++11 +$(package)_config_opts += -c++11 $(package)_config_opts += -openssl-linked $(package)_config_opts += -v $(package)_config_opts += -static diff --git a/depends/packages/zeromq.mk b/depends/packages/zeromq.mk index 7b866e9c0f662..b3f18db056968 100644 --- a/depends/packages/zeromq.mk +++ b/depends/packages/zeromq.mk @@ -7,6 +7,7 @@ $(package)_sha256_hash=e00b2967e074990d0538361cc79084a0a92892df2c6e7585da34e4c61 define $(package)_set_vars $(package)_config_opts=--without-documentation --disable-shared $(package)_config_opts_linux=--with-pic + $(package)_cxxflags=-std=c++11 endef define $(package)_config_cmds From a946bb6b182ee169934ffb97940434f38d1ae9e8 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 22 Dec 2015 13:52:57 +0100 Subject: [PATCH 0230/1802] [RPC] createrawtransaction: add option to set the sequence number per input --- qa/rpc-tests/rawtransactions.py | 6 ++++++ src/rpc/rawtransaction.cpp | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/qa/rpc-tests/rawtransactions.py b/qa/rpc-tests/rawtransactions.py index e38ef6c8b1071..ef545273c5b33 100755 --- a/qa/rpc-tests/rawtransactions.py +++ b/qa/rpc-tests/rawtransactions.py @@ -137,5 +137,11 @@ def run_test(self): self.sync_all() assert_equal(self.nodes[0].getbalance(), bal+Decimal('50.00000000')+Decimal('2.19000000')) #block reward + tx + inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : 1000}] + outputs = { self.nodes[0].getnewaddress() : 1 } + rawtx = self.nodes[0].createrawtransaction(inputs, outputs) + decrawtx= self.nodes[0].decoderawtransaction(rawtx) + assert_equal(decrawtx['vin'][0]['sequence'], 1000) + if __name__ == '__main__': RawTransactionsTest().main() diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index de8cd68f66267..b475f9a223007 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -334,6 +334,7 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp) " {\n" " \"txid\":\"id\", (string, required) The transaction id\n" " \"vout\":n (numeric, required) The output number\n" + " \"sequence\":n (numeric, optional) The sequence number\n" " }\n" " ,...\n" " ]\n" @@ -384,6 +385,12 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive"); uint32_t nSequence = (rawTx.nLockTime ? std::numeric_limits::max() - 1 : std::numeric_limits::max()); + + // set the sequence number if passed in the parameters object + const UniValue& sequenceObj = find_value(o, "sequence"); + if (sequenceObj.isNum()) + nSequence = sequenceObj.get_int(); + CTxIn in(COutPoint(txid, nOutput), CScript(), nSequence); rawTx.vin.push_back(in); From e59336fbf9b906bf05d50a732036613216898bd1 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 3 Dec 2015 16:29:45 +0100 Subject: [PATCH 0231/1802] [bitcoin-tx] allow to set nSequence number over the in= command --- src/bitcoin-tx.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 95d7a085a0a3d..d5e2fc279bc25 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -71,7 +71,7 @@ static bool AppInitRawTx(int argc, char* argv[]) strUsage = HelpMessageGroup(_("Commands:")); strUsage += HelpMessageOpt("delin=N", _("Delete input N from TX")); strUsage += HelpMessageOpt("delout=N", _("Delete output N from TX")); - strUsage += HelpMessageOpt("in=TXID:VOUT", _("Add input to TX")); + strUsage += HelpMessageOpt("in=TXID:VOUT(:SEQUENCE_NUMBER)", _("Add input to TX")); strUsage += HelpMessageOpt("locktime=N", _("Set TX lock time to N")); strUsage += HelpMessageOpt("nversion=N", _("Set TX version to N")); strUsage += HelpMessageOpt("outaddr=VALUE:ADDRESS", _("Add address-based output to TX")); @@ -181,15 +181,15 @@ static void MutateTxLocktime(CMutableTransaction& tx, const string& cmdVal) static void MutateTxAddInput(CMutableTransaction& tx, const string& strInput) { + std::vector vStrInputParts; + boost::split(vStrInputParts, strInput, boost::is_any_of(":")); + // separate TXID:VOUT in string - size_t pos = strInput.find(':'); - if ((pos == string::npos) || - (pos == 0) || - (pos == (strInput.size() - 1))) + if (vStrInputParts.size()<2) throw runtime_error("TX input missing separator"); // extract and validate TXID - string strTxid = strInput.substr(0, pos); + string strTxid = vStrInputParts[0]; if ((strTxid.size() != 64) || !IsHex(strTxid)) throw runtime_error("invalid TX input txid"); uint256 txid(uint256S(strTxid)); @@ -198,13 +198,18 @@ static void MutateTxAddInput(CMutableTransaction& tx, const string& strInput) static const unsigned int maxVout = MAX_BLOCK_SIZE / minTxOutSz; // extract and validate vout - string strVout = strInput.substr(pos + 1, string::npos); + string strVout = vStrInputParts[1]; int vout = atoi(strVout); if ((vout < 0) || (vout > (int)maxVout)) throw runtime_error("invalid TX input vout"); + // extract the optional sequence number + uint32_t nSequenceIn=std::numeric_limits::max(); + if (vStrInputParts.size() > 2) + nSequenceIn = atoi(vStrInputParts[2]); + // append to transaction input list - CTxIn txin(txid, vout); + CTxIn txin(txid, vout, CScript(), nSequenceIn); tx.vin.push_back(txin); } From 383fc10ebb8e9ffe88c1b9e2ea706c76e5a6343e Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Wed, 27 Apr 2016 09:57:02 -0400 Subject: [PATCH 0232/1802] Only use AddInventoryKnown for transactions filterInventoryKnown is only used when relaying transactions, so stop adding block hashes to the filter. --- src/main.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index f6a89fa2e675a..90db9de14eed7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4765,7 +4765,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, const CInv &inv = vInv[nInv]; boost::this_thread::interruption_point(); - pfrom->AddInventoryKnown(inv); bool fAlreadyHave = AlreadyHave(inv); LogPrint("net", "got inv: %s %s peer=%d\n", inv.ToString(), fAlreadyHave ? "have" : "new", pfrom->id); @@ -4795,6 +4794,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } else { + pfrom->AddInventoryKnown(inv); if (fBlocksOnly) LogPrint("net", "transaction (%s) inv sent in violation of protocol peer=%d\n", inv.hash.ToString(), pfrom->id); else if (!fAlreadyHave && !fImporting && !fReindex && !IsInitialBlockDownload()) @@ -5173,10 +5173,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, CBlock block; vRecv >> block; - CInv inv(MSG_BLOCK, block.GetHash()); - LogPrint("net", "received block %s peer=%d\n", inv.hash.ToString(), pfrom->id); - - pfrom->AddInventoryKnown(inv); + LogPrint("net", "received block %s peer=%d\n", block.GetHash().ToString(), pfrom->id); CValidationState state; // Process all blocks from whitelisted peers, even if not requested, @@ -5189,7 +5186,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, if (state.IsInvalid(nDoS)) { assert (state.GetRejectCode() < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes pfrom->PushMessage(NetMsgType::REJECT, strCommand, (unsigned char)state.GetRejectCode(), - state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash); + state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), block.GetHash()); if (nDoS > 0) { LOCK(cs_main); Misbehaving(pfrom->GetId(), nDoS); @@ -5769,9 +5766,7 @@ bool SendMessages(CNode* pto) hashToAnnounce.ToString(), chainActive.Tip()->GetBlockHash().ToString()); } - // If the peer announced this block to us, don't inv it back. - // (Since block announcements may not be via inv's, we can't solely rely on - // setInventoryKnown to track this.) + // If the peer's chain has this block, don't inv it back. if (!PeerHasHeader(&state, pindex)) { pto->PushInventory(CInv(MSG_BLOCK, hashToAnnounce)); LogPrint("net", "%s: sending inv peer=%d hash=%s\n", __func__, From b02119e4634f2453260bb1b195e39bdc0a3b5691 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Wed, 27 Apr 2016 18:04:02 +0200 Subject: [PATCH 0233/1802] Remove useless argument to AlertNotify. It is always 'true', so useless. --- src/main.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index f6a89fa2e675a..418ef704b5167 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1593,7 +1593,7 @@ bool fLargeWorkForkFound = false; bool fLargeWorkInvalidChainFound = false; CBlockIndex *pindexBestForkTip = NULL, *pindexBestForkBase = NULL; -static void AlertNotify(const std::string& strMessage, bool fThread) +static void AlertNotify(const std::string& strMessage) { uiInterface.NotifyAlertChanged(); std::string strCmd = GetArg("-alertnotify", ""); @@ -1607,10 +1607,7 @@ static void AlertNotify(const std::string& strMessage, bool fThread) safeStatus = singleQuote+safeStatus+singleQuote; boost::replace_all(strCmd, "%s", safeStatus); - if (fThread) - boost::thread t(runCommand, strCmd); // thread runs free - else - runCommand(strCmd); + boost::thread t(runCommand, strCmd); // thread runs free } void CheckForkWarningConditions() @@ -1632,7 +1629,7 @@ void CheckForkWarningConditions() { std::string warning = std::string("'Warning: Large-work fork detected, forking after block ") + pindexBestForkBase->phashBlock->ToString() + std::string("'"); - AlertNotify(warning, true); + AlertNotify(warning); } if (pindexBestForkTip && pindexBestForkBase) { @@ -2163,7 +2160,7 @@ void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const if (!strWarning.empty()) { strMiscWarning = strWarning; - AlertNotify(strWarning, true); + AlertNotify(strWarning); lastAlertTime = now; } } @@ -2598,7 +2595,7 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { if (state == THRESHOLD_ACTIVE) { strMiscWarning = strprintf(_("Warning: unknown new rules activated (versionbit %i)"), bit); if (!fWarned) { - AlertNotify(strMiscWarning, true); + AlertNotify(strMiscWarning); fWarned = true; } } else { @@ -2620,7 +2617,7 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { // strMiscWarning is read by GetWarnings(), called by Qt and the JSON-RPC code to warn the user: strMiscWarning = _("Warning: Unknown block versions being mined! It's possible unknown rules are in effect"); if (!fWarned) { - AlertNotify(strMiscWarning, true); + AlertNotify(strMiscWarning); fWarned = true; } } From f4ac02ee7c6530c273503d8575a492e9b2ac1f13 Mon Sep 17 00:00:00 2001 From: Kaz Wesley Date: Wed, 27 Apr 2016 09:26:33 -0700 Subject: [PATCH 0234/1802] fix race that could fail to persist a ban DumpBanList currently does this: - with lock: take a copy of the banmap - perform I/O (write out the banmap) - with lock: mark the banmap non-dirty If a new ban is added during the I/O operation, it may never be persisted to disk. Reorder operations so that the data to be persisted cannot be older than the time at which the banmap was marked non-dirty. --- src/net.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 7dec8fc1cf599..f566af24c425a 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2634,9 +2634,10 @@ void DumpBanlist() CBanDB bandb; banmap_t banmap; + CNode::SetBannedSetDirty(false); CNode::GetBanned(banmap); - if (bandb.Write(banmap)) - CNode::SetBannedSetDirty(false); + if (!bandb.Write(banmap)) + CNode::SetBannedSetDirty(true); LogPrint("net", "Flushed %d banned node ips/subnets to banlist.dat %dms\n", banmap.size(), GetTimeMillis() - nStart); From c7aac2d557fe3d3aa5bcdd3301a9b87eb110d8ed Mon Sep 17 00:00:00 2001 From: 21E14 <21xe14@gmail.com> Date: Wed, 27 Apr 2016 22:36:45 -0400 Subject: [PATCH 0235/1802] Deprecating the remaining LogPrintf dependencies that were made obsolete in PR #7459. --- src/pow.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/pow.cpp b/src/pow.cpp index 058404f357b0b..1db3b692932fe 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -64,9 +64,7 @@ unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nF // Retarget const arith_uint256 bnPowLimit = UintToArith256(params.powLimit); arith_uint256 bnNew; - arith_uint256 bnOld; bnNew.SetCompact(pindexLast->nBits); - bnOld = bnNew; bnNew *= nActualTimespan; bnNew /= params.nPowTargetTimespan; From 2aacc72727b891aa6f42e97d16e8954fba014703 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 28 Apr 2016 10:18:06 +0200 Subject: [PATCH 0236/1802] build: update ax_cxx_compile_stdcxx to serial 4 --- build-aux/m4/ax_cxx_compile_stdcxx.m4 | 48 +++++++++++++++------------ 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/build-aux/m4/ax_cxx_compile_stdcxx.m4 b/build-aux/m4/ax_cxx_compile_stdcxx.m4 index 079e17d2a629e..2c18e49c56c0b 100644 --- a/build-aux/m4/ax_cxx_compile_stdcxx.m4 +++ b/build-aux/m4/ax_cxx_compile_stdcxx.m4 @@ -9,9 +9,9 @@ # DESCRIPTION # # Check for baseline language coverage in the compiler for the specified -# version of the C++ standard. If necessary, add switches to CXXFLAGS to -# enable support. VERSION may be '11' (for the C++11 standard) or '14' -# (for the C++14 standard). +# version of the C++ standard. If necessary, add switches to CXX and +# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard) +# or '14' (for the C++14 standard). # # The second argument, if specified, indicates whether you insist on an # extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. @@ -39,7 +39,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 1 +#serial 4 dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro dnl (serial version number 13). @@ -74,14 +74,17 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, $cachevar, - [ac_save_CXXFLAGS="$CXXFLAGS" - CXXFLAGS="$CXXFLAGS $switch" + [ac_save_CXX="$CXX" + CXX="$CXX $switch" AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], [eval $cachevar=yes], [eval $cachevar=no]) - CXXFLAGS="$ac_save_CXXFLAGS"]) + CXX="$ac_save_CXX"]) if eval test x\$$cachevar = xyes; then - CXXFLAGS="$CXXFLAGS $switch" + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi ac_success=yes break fi @@ -97,14 +100,17 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, $cachevar, - [ac_save_CXXFLAGS="$CXXFLAGS" - CXXFLAGS="$CXXFLAGS $switch" + [ac_save_CXX="$CXX" + CXX="$CXX $switch" AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], [eval $cachevar=yes], [eval $cachevar=no]) - CXXFLAGS="$ac_save_CXXFLAGS"]) + CXX="$ac_save_CXX"]) if eval test x\$$cachevar = xyes; then - CXXFLAGS="$CXXFLAGS $switch" + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi ac_success=yes break fi @@ -115,18 +121,16 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl if test x$ac_success = xno; then AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) fi + fi + if test x$ac_success = xno; then + HAVE_CXX$1=0 + AC_MSG_NOTICE([No compiler with C++$1 support was found]) else - if test x$ac_success = xno; then - HAVE_CXX$1=0 - AC_MSG_NOTICE([No compiler with C++$1 support was found]) - else - HAVE_CXX$1=1 - AC_DEFINE(HAVE_CXX$1,1, - [define if the compiler supports basic C++$1 syntax]) - fi - - AC_SUBST(HAVE_CXX$1) + HAVE_CXX$1=1 + AC_DEFINE(HAVE_CXX$1,1, + [define if the compiler supports basic C++$1 syntax]) fi + AC_SUBST(HAVE_CXX$1) ]) From 7df92242a99db68962048aad34532e6c0e7a42fa Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 28 Apr 2016 10:43:39 +0200 Subject: [PATCH 0237/1802] doc: Add note about new build/test requirements to release notes [skip ci] --- doc/release-notes.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/doc/release-notes.md b/doc/release-notes.md index 7a673cc350670..7d44b8cda934c 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -43,6 +43,19 @@ RPC low-level changes 32-bit and 64-bit platforms, and the txids were missing in the hashed data. This has been fixed, but this means that the output will be different than from previous versions. +C++11 and Python 3 +------------------- + +Various code modernizations have been done. The Bitcoin Core code base has +started using C++11. This means that a C++11-capable compiler is now needed for +building. Effectively this means GCC 4.7 or higher, or Clang 3.3 or higher. + +When cross-compiling for a target that doesn't have C++11 libraries, configure with +`./configure --enable-glibc-back-compat ... LDFLAGS=-static-libstdc++`. + +For running the functional tests in `qa/rpc-tests`, Python3.4 or higher is now +required. + 0.13.0 Change log ================= From 073225cb01d9c2629c7a423dbe6afcd07601ffb7 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 28 Apr 2016 13:35:16 +0200 Subject: [PATCH 0238/1802] chain: define enum used as bit field as uint32_t Bitwise logic combined with `<` with undefined signedness will potentially results in undefined behavior. Fix this by defining the type as a c++11 typed enum. Fixes #6017. --- src/chain.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chain.h b/src/chain.h index 5b9605a80bdb3..017d4fe45789a 100644 --- a/src/chain.h +++ b/src/chain.h @@ -54,7 +54,7 @@ struct CDiskBlockPos }; -enum BlockStatus { +enum BlockStatus: uint32_t { //! Unused. BLOCK_VALID_UNKNOWN = 0, From 07e4edb056249e017b0e5a4783e4452ce892b52d Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 28 Apr 2016 13:40:20 +0200 Subject: [PATCH 0239/1802] =?UTF-8?q?auto=5Fptr=20=E2=86=92=20unique=5Fptr?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the few occurrences of the deprecated `auto_ptr` to c++11 `unique_ptr`. Silences the deprecation warnings. Also add a missing `std::` for consistency. --- src/httpserver.cpp | 4 ++-- src/miner.cpp | 2 +- src/rpc/mining.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/httpserver.cpp b/src/httpserver.cpp index ce1accb0464e1..a98eff7c167d7 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -252,7 +252,7 @@ static std::string RequestMethodString(HTTPRequest::RequestMethod m) /** HTTP request callback */ static void http_request_cb(struct evhttp_request* req, void* arg) { - std::auto_ptr hreq(new HTTPRequest(req)); + std::unique_ptr hreq(new HTTPRequest(req)); LogPrint("http", "Received a %s request for %s from %s\n", RequestMethodString(hreq->GetRequestMethod()), hreq->GetURI(), hreq->GetPeer().ToString()); @@ -288,7 +288,7 @@ static void http_request_cb(struct evhttp_request* req, void* arg) // Dispatch to worker thread if (i != iend) { - std::auto_ptr item(new HTTPWorkItem(hreq.release(), path, i->handler)); + std::unique_ptr item(new HTTPWorkItem(hreq.release(), path, i->handler)); assert(workQueue); if (workQueue->Enqueue(item.get())) item.release(); /* if true, queue took ownership */ diff --git a/src/miner.cpp b/src/miner.cpp index ef8fd4db43d0e..eaf29a767b594 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -74,7 +74,7 @@ int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParam CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& scriptPubKeyIn) { // Create new block - auto_ptr pblocktemplate(new CBlockTemplate()); + std::unique_ptr pblocktemplate(new CBlockTemplate()); if(!pblocktemplate.get()) return NULL; CBlock *pblock = &pblocktemplate->block; // pointer for convenience diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index b63ee2288918b..9a7d9d53a07fc 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -111,7 +111,7 @@ UniValue generateBlocks(boost::shared_ptr coinbaseScript, int nG UniValue blockHashes(UniValue::VARR); while (nHeight < nHeightEnd) { - auto_ptr pblocktemplate(CreateNewBlock(Params(), coinbaseScript->reserveScript)); + std::unique_ptr pblocktemplate(CreateNewBlock(Params(), coinbaseScript->reserveScript)); if (!pblocktemplate.get()) throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block"); CBlock *pblock = &pblocktemplate->block; From aa62b68745ef43ca135fdffbd886818221e85731 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 24 Apr 2016 17:12:34 +0200 Subject: [PATCH 0240/1802] Benchmark rolling bloom filter --- src/Makefile.bench.include | 3 ++- src/bench/rollingbloom.cpp | 43 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 src/bench/rollingbloom.cpp diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include index 8e7b59b46177d..24e2b3e0c85e1 100644 --- a/src/Makefile.bench.include +++ b/src/Makefile.bench.include @@ -7,7 +7,8 @@ bench_bench_bitcoin_SOURCES = \ bench/bench_bitcoin.cpp \ bench/bench.cpp \ bench/bench.h \ - bench/Examples.cpp + bench/Examples.cpp \ + bench/rollingbloom.cpp bench_bench_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CLFAGS) $(EVENT_PTHREADS_CFLAGS) -I$(builddir)/bench/ bench_bench_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) diff --git a/src/bench/rollingbloom.cpp b/src/bench/rollingbloom.cpp new file mode 100644 index 0000000000000..73c02cf7189eb --- /dev/null +++ b/src/bench/rollingbloom.cpp @@ -0,0 +1,43 @@ +// Copyright (c) 2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include "bench.h" +#include "bloom.h" +#include "utiltime.h" + +static void RollingBloom(benchmark::State& state) +{ + CRollingBloomFilter filter(120000, 0.000001); + std::vector data(32); + uint32_t count = 0; + uint32_t nEntriesPerGeneration = (120000 + 1) / 2; + uint32_t countnow = 0; + uint64_t match = 0; + while (state.KeepRunning()) { + count++; + data[0] = count; + data[1] = count >> 8; + data[2] = count >> 16; + data[3] = count >> 24; + if (countnow == nEntriesPerGeneration) { + int64_t b = GetTimeMicros(); + filter.insert(data); + int64_t e = GetTimeMicros(); + std::cout << "RollingBloom-refresh,1," << (e-b)*0.000001 << "," << (e-b)*0.000001 << "," << (e-b)*0.000001 << "\n"; + countnow = 0; + } else { + filter.insert(data); + } + countnow++; + data[0] = count >> 24; + data[1] = count >> 16; + data[2] = count >> 8; + data[3] = count; + match += filter.contains(data); + } +} + +BENCHMARK(RollingBloom); From 1953c40aa9589a03035fd294f3ba3549374a4826 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 24 Apr 2016 18:37:29 +0200 Subject: [PATCH 0241/1802] More efficient bitsliced rolling Bloom filter This patch changes the implementation from one that stores 16 2-bit integers in one uint32_t's, to one that stores the first bit of 64 2-bit integers in one uint64_t and the second bit in another. This allows for 450x faster refreshing and 2.2x faster average speed. --- src/bloom.cpp | 40 +++++++++++++++++++++++++++------------- src/bloom.h | 13 +------------ src/test/bloom_tests.cpp | 5 ++++- 3 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/bloom.cpp b/src/bloom.cpp index 4e6f0e5d2ddaa..fd328e8e96e53 100644 --- a/src/bloom.cpp +++ b/src/bloom.cpp @@ -234,14 +234,18 @@ CRollingBloomFilter::CRollingBloomFilter(unsigned int nElements, double fpRate) */ uint32_t nFilterBits = (uint32_t)ceil(-1.0 * nHashFuncs * nMaxElements / log(1.0 - exp(logFpRate / nHashFuncs))); data.clear(); - /* We store up to 16 'bits' per data element. */ - data.resize((nFilterBits + 15) / 16); + /* For each data element we need to store 2 bits. If both bits are 0, the + * bit is treated as unset. If the bits are (01), (10), or (11), the bit is + * treated as set in generation 1, 2, or 3 respectively. + * These bits are stored in separate integers: position P corresponds to bit + * (P & 63) of the integers data[(P >> 6) * 2] and data[(P >> 6) * 2 + 1]. */ + data.resize(((nFilterBits + 63) / 64) << 1); reset(); } /* Similar to CBloomFilter::Hash */ -inline unsigned int CRollingBloomFilter::Hash(unsigned int nHashNum, const std::vector& vDataToHash) const { - return MurmurHash3(nHashNum * 0xFBA4C795 + nTweak, vDataToHash) % (data.size() * 16); +static inline uint32_t RollingBloomHash(unsigned int nHashNum, uint32_t nTweak, const std::vector& vDataToHash) { + return MurmurHash3(nHashNum * 0xFBA4C795 + nTweak, vDataToHash); } void CRollingBloomFilter::insert(const std::vector& vKey) @@ -252,18 +256,25 @@ void CRollingBloomFilter::insert(const std::vector& vKey) if (nGeneration == 4) { nGeneration = 1; } + uint64_t nGenerationMask1 = -(uint64_t)(nGeneration & 1); + uint64_t nGenerationMask2 = -(uint64_t)(nGeneration >> 1); /* Wipe old entries that used this generation number. */ - for (uint32_t p = 0; p < data.size() * 16; p++) { - if (get(p) == nGeneration) { - put(p, 0); - } + for (uint32_t p = 0; p < data.size(); p += 2) { + uint64_t p1 = data[p], p2 = data[p + 1]; + uint64_t mask = (p1 ^ nGenerationMask1) | (p2 ^ nGenerationMask2); + data[p] = p1 & mask; + data[p + 1] = p2 & mask; } } nEntriesThisGeneration++; for (int n = 0; n < nHashFuncs; n++) { - uint32_t h = Hash(n, vKey); - put(h, nGeneration); + uint32_t h = RollingBloomHash(n, nTweak, vKey); + int bit = h & 0x3F; + uint32_t pos = (h >> 6) % data.size(); + /* The lowest bit of pos is ignored, and set to zero for the first bit, and to one for the second. */ + data[pos & ~1] = (data[pos & ~1] & ~(((uint64_t)1) << bit)) | ((uint64_t)(nGeneration & 1)) << bit; + data[pos | 1] = (data[pos | 1] & ~(((uint64_t)1) << bit)) | ((uint64_t)(nGeneration >> 1)) << bit; } } @@ -276,8 +287,11 @@ void CRollingBloomFilter::insert(const uint256& hash) bool CRollingBloomFilter::contains(const std::vector& vKey) const { for (int n = 0; n < nHashFuncs; n++) { - uint32_t h = Hash(n, vKey); - if (get(h) == 0) { + uint32_t h = RollingBloomHash(n, nTweak, vKey); + int bit = h & 0x3F; + uint32_t pos = (h >> 6) % data.size(); + /* If the relevant bit is not set in either data[pos & ~1] or data[pos | 1], the filter does not contain vKey */ + if (!(((data[pos & ~1] | data[pos | 1]) >> bit) & 1)) { return false; } } @@ -295,7 +309,7 @@ void CRollingBloomFilter::reset() nTweak = GetRand(std::numeric_limits::max()); nEntriesThisGeneration = 0; nGeneration = 1; - for (std::vector::iterator it = data.begin(); it != data.end(); it++) { + for (std::vector::iterator it = data.begin(); it != data.end(); it++) { *it = 0; } } diff --git a/src/bloom.h b/src/bloom.h index b0ad8b875d04b..ad6de625d8f8a 100644 --- a/src/bloom.h +++ b/src/bloom.h @@ -135,20 +135,9 @@ class CRollingBloomFilter int nEntriesPerGeneration; int nEntriesThisGeneration; int nGeneration; - std::vector data; + std::vector data; unsigned int nTweak; int nHashFuncs; - - unsigned int Hash(unsigned int nHashNum, const std::vector& vDataToHash) const; - - inline int get(uint32_t position) const { - return (data[(position >> 4) % data.size()] >> (2 * (position & 0xF))) & 0x3; - } - - inline void put(uint32_t position, uint32_t val) { - uint32_t& cell = data[(position >> 4) % data.size()]; - cell = (cell & ~(((uint32_t)3) << (2 * (position & 0xF)))) | (val << (2 * (position & 0xF))); - } }; #endif // BITCOIN_BLOOM_H diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp index 9557000ddcc11..042fad42dae89 100644 --- a/src/test/bloom_tests.cpp +++ b/src/test/bloom_tests.cpp @@ -514,11 +514,14 @@ BOOST_AUTO_TEST_CASE(rolling_bloom) if (i >= 100) BOOST_CHECK(rb1.contains(data[i-100])); rb1.insert(data[i]); + BOOST_CHECK(rb1.contains(data[i])); } // Insert 999 more random entries: for (int i = 0; i < 999; i++) { - rb1.insert(RandomData()); + std::vector d = RandomData(); + rb1.insert(d); + BOOST_CHECK(rb1.contains(d)); } // Sanity check to make sure the filter isn't just filling up: nHits = 0; From 7db0ecb90c80bd4995bedf8c2982e9a22345ca65 Mon Sep 17 00:00:00 2001 From: Andrew Chow Date: Wed, 27 Apr 2016 12:18:20 -0700 Subject: [PATCH 0242/1802] Test for signing messages New rpc test for signing and verifying messages. --- qa/pull-tester/rpc-tests.py | 1 + qa/rpc-tests/signmessages.py | 40 ++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100755 qa/rpc-tests/signmessages.py diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index c0637209e3c1d..26142c35e9992 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -123,6 +123,7 @@ 'abandonconflict.py', 'p2p-versionbits-warning.py', 'importprunedfunds.py', + 'signmessages.py' ] if ENABLE_ZMQ: testScripts.append('zmq_test.py') diff --git a/qa/rpc-tests/signmessages.py b/qa/rpc-tests/signmessages.py new file mode 100755 index 0000000000000..ff22f35300a4b --- /dev/null +++ b/qa/rpc-tests/signmessages.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python2 +# Copyright (c) 2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * + + +class SignMessagesTest(BitcoinTestFramework): + """Tests RPC commands for signing and verifying messages.""" + + def setup_chain(self): + print('Initializing test directory ' + self.options.tmpdir) + initialize_chain_clean(self.options.tmpdir, 1) + + def setup_network(self, split=False): + self.nodes = start_nodes(1, self.options.tmpdir) + self.is_network_split = False + + def run_test(self): + message = 'This is just a test message' + + # Test the signing with a privkey + privKey = 'cUeKHd5orzT3mz8P9pxyREHfsWtVfgsfDjiZZBcjUBAaGk1BTj7N' + address = 'mpLQjfK79b7CCV4VMJWEWAj5Mpx8Up5zxB' + signature = self.nodes[0].signmessagewithprivkey(privKey, message) + + # Verify the message + assert(self.nodes[0].verifymessage(address, signature, message)) + + # Test the signing with an address with wallet + address = self.nodes[0].getnewaddress() + signature = self.nodes[0].signmessage(address, message) + + # Verify the message + assert(self.nodes[0].verifymessage(address, signature, message)) + +if __name__ == '__main__': + SignMessagesTest().main() From 3b35e4896b5b8be9ffd6dacddb081f69a5b77903 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 28 Apr 2016 22:04:07 +0200 Subject: [PATCH 0243/1802] [RPC] add feerate option to fundrawtransaction --- qa/rpc-tests/fundrawtransaction.py | 8 ++++++++ src/coincontrol.h | 3 +++ src/wallet/rpcwallet.cpp | 13 +++++++++---- src/wallet/wallet.cpp | 6 +++++- src/wallet/wallet.h | 2 +- 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py index 496c7fe8b0ed0..f76fe90ef4e79 100755 --- a/qa/rpc-tests/fundrawtransaction.py +++ b/qa/rpc-tests/fundrawtransaction.py @@ -677,6 +677,14 @@ def run_test(self): assert(signedtx["complete"]) self.nodes[0].sendrawtransaction(signedtx["hex"]) + inputs = [] + outputs = {self.nodes[2].getnewaddress() : 1} + rawtx = self.nodes[3].createrawtransaction(inputs, outputs) + result = self.nodes[3].fundrawtransaction(rawtx, ) + result2 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2000}) + result3 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 10000}) + assert_equal(result['fee']*2, result2['fee']) + assert_equal(result['fee']*10, result3['fee']) if __name__ == '__main__': RawTransactionsTest().main() diff --git a/src/coincontrol.h b/src/coincontrol.h index 12fe9ce219c27..6129397bc8f5d 100644 --- a/src/coincontrol.h +++ b/src/coincontrol.h @@ -18,6 +18,8 @@ class CCoinControl bool fAllowWatchOnly; //! Minimum absolute fee (not per kilobyte) CAmount nMinimumTotalFee; + //! Feerate to use (0 = estimate fee with payTxFee fallback) + CFeeRate nFeeRate; CCoinControl() { @@ -31,6 +33,7 @@ class CCoinControl fAllowWatchOnly = false; setSelected.clear(); nMinimumTotalFee = 0; + nFeeRate = CFeeRate(0); } bool HasSelected() const diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 623037e76648b..b14d748b3917e 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2458,6 +2458,7 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) " \"changePosition\" (numeric, optional, default random) The index of the change output\n" " \"includeWatching\" (boolean, optional, default false) Also select inputs which are watch only\n" " \"lockUnspents\" (boolean, optional, default false) Lock selected unspent outputs\n" + " \"feeRate\" (numeric, optional, default 0=estimate) Set a specific feerate (fee per KB)\n" " }\n" " for backward compatibility: passing in a true instead of an object will result in {\"includeWatching\":true}\n" "\nResult:\n" @@ -2484,6 +2485,7 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) int changePosition = -1; bool includeWatching = false; bool lockUnspents = false; + CFeeRate feeRate = CFeeRate(0); if (params.size() > 1) { if (params[1].type() == UniValue::VBOOL) { @@ -2495,7 +2497,7 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) UniValue options = params[1]; - RPCTypeCheckObj(options, boost::assign::map_list_of("changeAddress", UniValue::VSTR)("changePosition", UniValue::VNUM)("includeWatching", UniValue::VBOOL)("lockUnspents", UniValue::VBOOL), true, true); + RPCTypeCheckObj(options, boost::assign::map_list_of("changeAddress", UniValue::VSTR)("changePosition", UniValue::VNUM)("includeWatching", UniValue::VBOOL)("lockUnspents", UniValue::VBOOL)("feeRate", UniValue::VNUM), true, true); if (options.exists("changeAddress")) { CBitcoinAddress address(options["changeAddress"].get_str()); @@ -2514,6 +2516,9 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) if (options.exists("lockUnspents")) lockUnspents = options["lockUnspents"].get_bool(); + + if (options.exists("feeRate")) + feeRate = CFeeRate(options["feeRate"].get_real()); } } @@ -2529,16 +2534,16 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INVALID_PARAMETER, "changePosition out of bounds"); CMutableTransaction tx(origTx); - CAmount nFee; + CAmount nFeeOut; string strFailReason; - if(!pwalletMain->FundTransaction(tx, nFee, changePosition, strFailReason, includeWatching, lockUnspents, changeAddress)) + if(!pwalletMain->FundTransaction(tx, nFeeOut, feeRate, changePosition, strFailReason, includeWatching, lockUnspents, changeAddress)) throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason); UniValue result(UniValue::VOBJ); result.push_back(Pair("hex", EncodeHexTx(tx))); result.push_back(Pair("changepos", changePosition)); - result.push_back(Pair("fee", ValueFromAmount(nFee))); + result.push_back(Pair("fee", ValueFromAmount(nFeeOut))); return result; } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 29d7138547bd1..6b5e3ca7f5994 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1918,7 +1918,7 @@ bool CWallet::SelectCoins(const vector& vAvailableCoins, const CAmount& return res; } -bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, bool lockUnspents, const CTxDestination& destChange) +bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, const CFeeRate& specificFeeRate, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, bool lockUnspents, const CTxDestination& destChange) { vector vecSend; @@ -1933,6 +1933,8 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC coinControl.destChange = destChange; coinControl.fAllowOtherInputs = true; coinControl.fAllowWatchOnly = includeWatching; + coinControl.nFeeRate = specificFeeRate; + BOOST_FOREACH(const CTxIn& txin, tx.vin) coinControl.Select(txin.prevout); @@ -2242,6 +2244,8 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt if (coinControl && nFeeNeeded > 0 && coinControl->nMinimumTotalFee > nFeeNeeded) { nFeeNeeded = coinControl->nMinimumTotalFee; } + if (coinControl && coinControl->nFeeRate > CFeeRate(0)) + nFeeNeeded = coinControl->nFeeRate.GetFee(nBytes); // If we made it here and we aren't even able to meet the relay fee on the next pass, give up // because we must be at the maximum allowed fee. diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index c3bd343edd3e7..7b5168975ce11 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -740,7 +740,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface * Insert additional inputs into the transaction by * calling CreateTransaction(); */ - bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, bool lockUnspents, const CTxDestination& destChange = CNoDestination()); + bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, const CFeeRate& specificFeeRate, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, bool lockUnspents, const CTxDestination& destChange = CNoDestination()); /** * Create a new transaction paying the recipients with a set of coins From faf3d11ad7b10b9acfb59fe186876a3005385e4d Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Fri, 29 Apr 2016 23:17:18 +0200 Subject: [PATCH 0244/1802] [doc] Update bitcoin-core GitHub links --- contrib/devtools/README.md | 6 +++--- contrib/gitian-descriptors/gitian-osx-signer.yml | 2 +- contrib/gitian-descriptors/gitian-win-signer.yml | 2 +- doc/gitian-building.md | 6 +++--- doc/release-notes/release-notes-0.12.0.md | 2 +- doc/release-process.md | 6 +++--- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/contrib/devtools/README.md b/contrib/devtools/README.md index 1103ca86c5e82..bb8b9246b8781 100644 --- a/contrib/devtools/README.md +++ b/contrib/devtools/README.md @@ -48,9 +48,9 @@ the commit it claims to have been updated to. To use, make sure that you have fetched the upstream repository branch in which the subtree is maintained: -* for `src/secp256k1`: https://github.com/bitcoin/secp256k1.git (branch master) -* for `src/leveldb`: https://github.com/bitcoin/leveldb.git (branch bitcoin-fork) -* for `src/univalue`: https://github.com/bitcoin/univalue.git (branch master) +* for `src/secp256k1`: https://github.com/bitcoin-core/secp256k1.git (branch master) +* for `src/leveldb`: https://github.com/bitcoin-core/leveldb.git (branch bitcoin-fork) +* for `src/univalue`: https://github.com/bitcoin-core/univalue.git (branch master) Usage: `git-subtree-check.sh DIR COMMIT` diff --git a/contrib/gitian-descriptors/gitian-osx-signer.yml b/contrib/gitian-descriptors/gitian-osx-signer.yml index c4165470af132..fac61aa3debed 100644 --- a/contrib/gitian-descriptors/gitian-osx-signer.yml +++ b/contrib/gitian-descriptors/gitian-osx-signer.yml @@ -8,7 +8,7 @@ packages: - "faketime" reference_datetime: "2016-01-01 00:00:00" remotes: -- "url": "https://github.com/bitcoin/bitcoin-detached-sigs.git" +- "url": "https://github.com/bitcoin-core/bitcoin-detached-sigs.git" "dir": "signature" files: - "bitcoin-osx-unsigned.tar.gz" diff --git a/contrib/gitian-descriptors/gitian-win-signer.yml b/contrib/gitian-descriptors/gitian-win-signer.yml index 27c4f01eb4ed9..88edb96627e82 100644 --- a/contrib/gitian-descriptors/gitian-win-signer.yml +++ b/contrib/gitian-descriptors/gitian-win-signer.yml @@ -9,7 +9,7 @@ packages: - "autoconf" reference_datetime: "2016-01-01 00:00:00" remotes: -- "url": "https://github.com/bitcoin/bitcoin-detached-sigs.git" +- "url": "https://github.com/bitcoin-core/bitcoin-detached-sigs.git" "dir": "signature" files: - "osslsigncode-1.7.1.tar.gz" diff --git a/doc/gitian-building.md b/doc/gitian-building.md index 3126218518690..13f8ad316b3f5 100644 --- a/doc/gitian-building.md +++ b/doc/gitian-building.md @@ -310,7 +310,7 @@ Clone the git repositories for bitcoin and Gitian. ```bash git clone https://github.com/devrandom/gitian-builder.git git clone https://github.com/bitcoin/bitcoin -git clone https://github.com/bitcoin/gitian.sigs.git +git clone https://github.com/bitcoin-core/gitian.sigs.git ``` Setting up the Gitian image @@ -441,7 +441,7 @@ Then when building, override the remote URLs that gbuild would otherwise pull fr ```bash cd /some/root/path/ -git clone https://github.com/bitcoin/bitcoin-detached-sigs.git +git clone https://github.com/bitcoin-core/bitcoin-detached-sigs.git BTCPATH=/some/root/path/bitcoin.git SIGPATH=/some/root/path/bitcoin-detached-sigs.git @@ -473,5 +473,5 @@ Uploading signatures --------------------- After building and signing you can push your signatures (both the `.assert` and `.assert.sig` files) to the -[bitcoin/gitian.sigs](https://github.com/bitcoin/gitian.sigs/) repository, or if that's not possible create a pull +[bitcoin-core/gitian.sigs](https://github.com/bitcoin-core/gitian.sigs/) repository, or if that's not possible create a pull request. You can also mail the files to Wladimir (laanwj@gmail.com) and he will commit them. diff --git a/doc/release-notes/release-notes-0.12.0.md b/doc/release-notes/release-notes-0.12.0.md index 135cd68a7c78f..1b7bd06ece6a2 100644 --- a/doc/release-notes/release-notes-0.12.0.md +++ b/doc/release-notes/release-notes-0.12.0.md @@ -61,7 +61,7 @@ Signature validation using libsecp256k1 --------------------------------------- ECDSA signatures inside Bitcoin transactions now use validation using -[libsecp256k1](https://github.com/bitcoin/secp256k1) instead of OpenSSL. +[libsecp256k1](https://github.com/bitcoin-core/secp256k1) instead of OpenSSL. Depending on the platform, this means a significant speedup for raw signature validation speed. The advantage is largest on x86_64, where validation is over diff --git a/doc/release-process.md b/doc/release-process.md index 34dead86bc1e4..3bfcc38177bb2 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -20,8 +20,8 @@ Before every major release: Check out the source code in the following directory hierarchy. cd /path/to/your/toplevel/build - git clone https://github.com/bitcoin/gitian.sigs.git - git clone https://github.com/bitcoin/bitcoin-detached-sigs.git + git clone https://github.com/bitcoin-core/gitian.sigs.git + git clone https://github.com/bitcoin-core/bitcoin-detached-sigs.git git clone https://github.com/devrandom/gitian-builder.git git clone https://github.com/bitcoin/bitcoin.git @@ -170,7 +170,7 @@ Commit your signature to gitian.sigs: Wait for Windows/OS X detached signatures: - Once the Windows/OS X builds each have 3 matching signatures, they will be signed with their respective release keys. -- Detached signatures will then be committed to the [bitcoin-detached-sigs](https://github.com/bitcoin/bitcoin-detached-sigs) repository, which can be combined with the unsigned apps to create signed binaries. +- Detached signatures will then be committed to the [bitcoin-detached-sigs](https://github.com/bitcoin-core/bitcoin-detached-sigs) repository, which can be combined with the unsigned apps to create signed binaries. Create (and optionally verify) the signed OS X binary: From d90351f0504c5d4057e560d64107a2f36d7bf3d4 Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Fri, 29 Apr 2016 14:23:51 +0000 Subject: [PATCH 0245/1802] More comments on the design of AttemptToEvictConnection. Some developers clearly don't get this and have been posting "improvements" that create clear vulnerabilities. It should have been better explained in the code, since the design is somewhat subtle and getting it right is important. --- src/net.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 7dec8fc1cf599..ced371164addc 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -877,6 +877,14 @@ class CompareNetGroupKeyed } }; +/** Try to find a connection to evict when the node is full. + * Extreme care must be taken to avoid opening the node to attacker + * triggered network partitioning. + * The strategy used here is to protect a small number of peers + * for each of several distinct characteristics which are difficult + * to forge. In order to partition a node the attacker must be + * simultaneously better at all of them than honest peers. + */ static bool AttemptToEvictConnection(bool fPreferNewConnection) { std::vector vEvictionCandidates; { @@ -905,7 +913,7 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) { if (vEvictionCandidates.empty()) return false; - // Protect the 8 nodes with the best ping times. + // Protect the 8 nodes with the lowest minimum ping time. // An attacker cannot manipulate this metric without physically moving nodes closer to the target. std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), ReverseCompareNodeMinPingTime); vEvictionCandidates.erase(vEvictionCandidates.end() - std::min(8, static_cast(vEvictionCandidates.size())), vEvictionCandidates.end()); @@ -913,7 +921,7 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) { if (vEvictionCandidates.empty()) return false; // Protect the half of the remaining nodes which have been connected the longest. - // This replicates the existing implicit behavior. + // This replicates the non-eviction implicit behavior, and precludes attacks that start later. std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), ReverseCompareNodeTimeConnected); vEvictionCandidates.erase(vEvictionCandidates.end() - static_cast(vEvictionCandidates.size() / 2), vEvictionCandidates.end()); @@ -941,6 +949,7 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) { vEvictionCandidates = mapAddrCounts[naMostConnections]; // Do not disconnect peers if there is only one unprotected connection from their network group. + // This step excessively favors netgroup diversity, and should be removed once more protective criteria are established. if (vEvictionCandidates.size() <= 1) // unless we prefer the new connection (for whitelisted peers) if (!fPreferNewConnection) From f7c4f79f07c777801db7dc047cd45eaf2bba81c9 Mon Sep 17 00:00:00 2001 From: Daniel Kraft Date: Sat, 30 Apr 2016 19:25:00 +0200 Subject: [PATCH 0246/1802] [trivial] Add missing const qualifiers. Add some const qualifiers to references that are not modified and should be marked as const. --- src/main.cpp | 2 +- src/txmempool.cpp | 2 +- src/txmempool.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 11ccab253e4ed..2777245654a0a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1468,7 +1468,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, const Consensus::P if (fAllowSlow) { // use coin database to locate block that contains transaction, and scan it int nHeight = -1; { - CCoinsViewCache &view = *pcoinsTip; + const CCoinsViewCache& view = *pcoinsTip; const CCoins* coins = view.AccessCoins(hash); if (coins) nHeight = coins->nHeight; diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 52c7793118331..420f6896b371e 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -885,7 +885,7 @@ bool CTxMemPool::HasNoInputsOf(const CTransaction &tx) const return true; } -CCoinsViewMemPool::CCoinsViewMemPool(CCoinsView *baseIn, CTxMemPool &mempoolIn) : CCoinsViewBacked(baseIn), mempool(mempoolIn) { } +CCoinsViewMemPool::CCoinsViewMemPool(CCoinsView* baseIn, const CTxMemPool& mempoolIn) : CCoinsViewBacked(baseIn), mempool(mempoolIn) { } bool CCoinsViewMemPool::GetCoins(const uint256 &txid, CCoins &coins) const { // If an entry in the mempool exists, always return that one, as it's guaranteed to never diff --git a/src/txmempool.h b/src/txmempool.h index de4ba0b371a42..d17e3322d307b 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -672,10 +672,10 @@ class CTxMemPool class CCoinsViewMemPool : public CCoinsViewBacked { protected: - CTxMemPool &mempool; + const CTxMemPool& mempool; public: - CCoinsViewMemPool(CCoinsView *baseIn, CTxMemPool &mempoolIn); + CCoinsViewMemPool(CCoinsView* baseIn, const CTxMemPool& mempoolIn); bool GetCoins(const uint256 &txid, CCoins &coins) const; bool HaveCoins(const uint256 &txid) const; }; From c8b92486c4eca1287546b0683b6af3551db1fe67 Mon Sep 17 00:00:00 2001 From: 21E14 <21xe14@gmail.com> Date: Fri, 29 Apr 2016 23:45:20 -0400 Subject: [PATCH 0247/1802] Remove obsolete reference to CValidationState from UpdateCoins. --- src/main.cpp | 8 ++++---- src/main.h | 2 +- src/test/coins_tests.cpp | 3 +-- src/txmempool.cpp | 4 ++-- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 11ccab253e4ed..c5c61469301d2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1744,7 +1744,7 @@ void static InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state } } -void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight) +void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo &txundo, int nHeight) { // mark inputs spent if (!tx.IsCoinBase()) { @@ -1770,10 +1770,10 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach inputs.ModifyNewCoins(tx.GetHash(), tx.IsCoinBase())->FromTx(tx, nHeight); } -void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, int nHeight) +void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight) { CTxUndo txundo; - UpdateCoins(tx, state, inputs, txundo, nHeight); + UpdateCoins(tx, inputs, txundo, nHeight); } bool CScriptCheck::operator()() { @@ -2385,7 +2385,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (i > 0) { blockundo.vtxundo.push_back(CTxUndo()); } - UpdateCoins(tx, state, view, i == 0 ? undoDummy : blockundo.vtxundo.back(), pindex->nHeight); + UpdateCoins(tx, view, i == 0 ? undoDummy : blockundo.vtxundo.back(), pindex->nHeight); vPos.push_back(std::make_pair(tx.GetHash(), pos)); pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION); diff --git a/src/main.h b/src/main.h index 2c9635bcf2b8f..792747a33464b 100644 --- a/src/main.h +++ b/src/main.h @@ -359,7 +359,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi unsigned int flags, bool cacheStore, std::vector *pvChecks = NULL); /** Apply the effects of this transaction on the UTXO set represented by view */ -void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, int nHeight); +void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight); /** Context-independent validity checks */ bool CheckTransaction(const CTransaction& tx, CValidationState& state); diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 129ce04e0bca1..e6923265592d7 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -297,8 +297,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) CCoins &coins = result[tx.GetHash()]; coins.FromTx(tx, height); - CValidationState dummy; - UpdateCoins(tx, dummy, *(stack.back()), height); + UpdateCoins(tx, *(stack.back()), height); } // Once every 1000 iterations and at the end, verify the full cache. diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 52c7793118331..f9c33087fdc69 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -720,7 +720,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const else { CValidationState state; assert(CheckInputs(tx, state, mempoolDuplicate, false, 0, false, NULL)); - UpdateCoins(tx, state, mempoolDuplicate, 1000000); + UpdateCoins(tx, mempoolDuplicate, 1000000); } } unsigned int stepsSinceLastRemove = 0; @@ -734,7 +734,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const assert(stepsSinceLastRemove < waitingOnDependants.size()); } else { assert(CheckInputs(entry->GetTx(), state, mempoolDuplicate, false, 0, false, NULL)); - UpdateCoins(entry->GetTx(), state, mempoolDuplicate, 1000000); + UpdateCoins(entry->GetTx(), mempoolDuplicate, 1000000); stepsSinceLastRemove = 0; } } From de982901555b3f168a721a8911dc1ce8a51d3f59 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 28 Apr 2016 17:46:35 -0400 Subject: [PATCH 0248/1802] build: No need to check for leveldb atomics They're guaranteed with c++11 --- configure.ac | 14 -------------- src/Makefile.leveldb.include | 7 ++----- 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/configure.ac b/configure.ac index 558835bbbd9b5..a1c04daf53601 100644 --- a/configure.ac +++ b/configure.ac @@ -555,18 +555,6 @@ if test x$use_reduce_exports = xyes; then [AC_MSG_ERROR([Cannot set default symbol visibility. Use --disable-reduce-exports.])]) fi -dnl This can go away when we require c++11 -TEMP_CXXFLAGS="$CXXFLAGS" -CXXFLAGS="$CXXFLAGS -std=c++0x" -AC_MSG_CHECKING(for c++11 atomics) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ - #include - ]],[[]])], - [ AC_MSG_RESULT(yes); LEVELDB_ATOMIC_CPPFLAGS="-DLEVELDB_ATOMIC_PRESENT"; LEVELDB_ATOMIC_CXXFLAGS="-std=c++0x"], - [ AC_MSG_RESULT(no)] -) -CXXFLAGS="$TEMP_CXXFLAGS" - LEVELDB_CPPFLAGS= LIBLEVELDB= LIBMEMENV= @@ -1069,8 +1057,6 @@ AC_SUBST(TESTDEFS) AC_SUBST(LEVELDB_TARGET_FLAGS) AC_SUBST(MINIUPNPC_CPPFLAGS) AC_SUBST(MINIUPNPC_LIBS) -AC_SUBST(LEVELDB_ATOMIC_CPPFLAGS) -AC_SUBST(LEVELDB_ATOMIC_CXXFLAGS) AC_CONFIG_FILES([Makefile src/Makefile share/setup.nsi share/qt/Info.plist src/test/buildenv.py]) AC_CONFIG_FILES([qa/pull-tester/run-bitcoind-for-test.sh],[chmod +x qa/pull-tester/run-bitcoind-for-test.sh]) AC_CONFIG_FILES([qa/pull-tester/tests_config.py],[chmod +x qa/pull-tester/tests_config.py]) diff --git a/src/Makefile.leveldb.include b/src/Makefile.leveldb.include index 36a6bc4095ad0..88bb0c19326f1 100644 --- a/src/Makefile.leveldb.include +++ b/src/Makefile.leveldb.include @@ -13,7 +13,7 @@ LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/helpers/memenv LEVELDB_CPPFLAGS_INT = LEVELDB_CPPFLAGS_INT += -I$(srcdir)/leveldb LEVELDB_CPPFLAGS_INT += $(LEVELDB_TARGET_FLAGS) -LEVELDB_CPPFLAGS_INT += $(LEVELDB_ATOMIC_CPPFLAGS) +LEVELDB_CPPFLAGS_INT += -DLEVELDB_ATOMIC_PRESENT LEVELDB_CPPFLAGS_INT += -D__STDC_LIMIT_MACROS if TARGET_WINDOWS @@ -22,11 +22,8 @@ else LEVELDB_CPPFLAGS_INT += -DLEVELDB_PLATFORM_POSIX endif -LEVELDB_CXXFLAGS_INT = -LEVELDB_CXXFLAGS_INT += $(LEVELDB_ATOMIC_CXXFLAGS) - leveldb_libleveldb_a_CPPFLAGS = $(AM_CPPFLAGS) $(LEVELDB_CPPFLAGS_INT) $(LEVELDB_CPPFLAGS) -leveldb_libleveldb_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) $(LEVELDB_CXXFLAGS_INT) +leveldb_libleveldb_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) leveldb_libleveldb_a_SOURCES= leveldb_libleveldb_a_SOURCES += leveldb/db/builder.cc From 9a8a7d011564c43231d16e6e3a25c73f0c76fde1 Mon Sep 17 00:00:00 2001 From: Puru Date: Mon, 2 May 2016 22:33:04 +0545 Subject: [PATCH 0249/1802] bitcoin-cli.cpp: Use symbolic constant for exit code --- src/bitcoin-cli.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 49935699fd5d8..a04101d3ed847 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -314,7 +314,7 @@ int main(int argc, char* argv[]) SetupEnvironment(); if (!SetupNetworking()) { fprintf(stderr, "Error: Initializing networking failed\n"); - exit(1); + return EXIT_FAILURE; } try { From fa17f93fbd2889c020849b941a94c5bd8a619a3c Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sat, 30 Apr 2016 23:16:06 +0200 Subject: [PATCH 0250/1802] [qa] smartfees: Properly use ordered dict --- qa/rpc-tests/smartfees.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/qa/rpc-tests/smartfees.py b/qa/rpc-tests/smartfees.py index 2c064ad8a03a9..b3fb8fb1007c6 100755 --- a/qa/rpc-tests/smartfees.py +++ b/qa/rpc-tests/smartfees.py @@ -7,6 +7,7 @@ # Test fee estimation code # +from collections import OrderedDict from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * @@ -49,8 +50,8 @@ def small_txpuzzle_randfee(from_node, conflist, unconflist, amount, min_fee, fee if total_in <= amount + fee: raise RuntimeError("Insufficient funds: need %d, have %d"%(amount+fee, total_in)) outputs = {} - outputs[P2SH_1] = total_in - amount - fee - outputs[P2SH_2] = amount + outputs = OrderedDict([(P2SH_1, total_in - amount - fee), + (P2SH_2, amount)]) rawtx = from_node.createrawtransaction(inputs, outputs) # Createrawtransaction constructions a transaction that is ready to be signed # These transactions don't need to be signed, but we still have to insert the ScriptSig @@ -78,12 +79,10 @@ def split_inputs(from_node, txins, txouts, initial_split = False): ''' prevtxout = txins.pop() inputs = [] - outputs = {} inputs.append({ "txid" : prevtxout["txid"], "vout" : prevtxout["vout"] }) half_change = satoshi_round(prevtxout["amount"]/2) rem_change = prevtxout["amount"] - half_change - Decimal("0.00001000") - outputs[P2SH_1] = half_change - outputs[P2SH_2] = rem_change + outputs = OrderedDict([(P2SH_1, half_change), (P2SH_2, rem_change)]) rawtx = from_node.createrawtransaction(inputs, outputs) # If this is the initial split we actually need to sign the transaction # Otherwise we just need to insert the property ScriptSig From 43bbcd075355630544a530f3cc52014edb3787b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Mon, 2 May 2016 22:23:21 +0200 Subject: [PATCH 0251/1802] [qa] Fix typos in doc and comments --- qa/rpc-tests/smartfees.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/qa/rpc-tests/smartfees.py b/qa/rpc-tests/smartfees.py index b3fb8fb1007c6..7239e5a0da825 100755 --- a/qa/rpc-tests/smartfees.py +++ b/qa/rpc-tests/smartfees.py @@ -23,7 +23,7 @@ def small_txpuzzle_randfee(from_node, conflist, unconflist, amount, min_fee, fee_increment): ''' Create and send a transaction with a random fee. - The transaction pays to a trival P2SH script, and assumes that its inputs + The transaction pays to a trivial P2SH script, and assumes that its inputs are of the same form. The function takes a list of confirmed outputs and unconfirmed outputs and attempts to use the confirmed list first for its inputs. @@ -53,7 +53,7 @@ def small_txpuzzle_randfee(from_node, conflist, unconflist, amount, min_fee, fee outputs = OrderedDict([(P2SH_1, total_in - amount - fee), (P2SH_2, amount)]) rawtx = from_node.createrawtransaction(inputs, outputs) - # Createrawtransaction constructions a transaction that is ready to be signed + # createrawtransaction constructs a transaction that is ready to be signed. # These transactions don't need to be signed, but we still have to insert the ScriptSig # that will satisfy the ScriptPubKey. completetx = rawtx[0:10] @@ -223,7 +223,7 @@ def transact_and_mine(self, numblocks, mining_node): sync_mempools(self.nodes[0:3],.1) mined = mining_node.getblock(mining_node.generate(1)[0],True)["tx"] sync_blocks(self.nodes[0:3],.1) - #update which txouts are confirmed + # update which txouts are confirmed newmem = [] for utx in self.memutxo: if utx["txid"] in mined: From 9eaa0afa6ec5d3dd01e4d01121314ef51f2bc305 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 4 May 2016 11:35:44 +0200 Subject: [PATCH 0252/1802] tinyformat: force USE_VARIADIC_TEMPLATES Now that we started using c++11, force use of variadic templates. The autodetection may be wonky on some compilers, see discussion [here](https://github.com/bitcoin/bitcoin/pull/7982#issuecomment-216222357) and is unnecessary for us anyhow. --- src/tinyformat.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tinyformat.h b/src/tinyformat.h index 73d49a1fe4d79..c6ec0419b3943 100644 --- a/src/tinyformat.h +++ b/src/tinyformat.h @@ -113,7 +113,7 @@ namespace tfm = tinyformat; // Define for C++11 variadic templates which make the code shorter & more // general. If you don't define this, C++11 support is autodetected below. -// #define TINYFORMAT_USE_VARIADIC_TEMPLATES +#define TINYFORMAT_USE_VARIADIC_TEMPLATES //------------------------------------------------------------------------------ From 47eda2d8820b8161b6ef550af6575cbe4f1a3207 Mon Sep 17 00:00:00 2001 From: fanquake Date: Wed, 4 May 2016 19:03:59 +0800 Subject: [PATCH 0253/1802] [depends] Add -stdlib=libc++ to darwin CXX flags --- depends/builders/darwin.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/depends/builders/darwin.mk b/depends/builders/darwin.mk index 200d6ed22a230..27f550ab036ae 100644 --- a/depends/builders/darwin.mk +++ b/depends/builders/darwin.mk @@ -11,7 +11,7 @@ build_darwin_DOWNLOAD = curl --location --fail --connect-timeout $(DOWNLOAD_CONN #darwin host on darwin builder. overrides darwin host preferences. darwin_CC=$(shell xcrun -f clang) -mmacosx-version-min=$(OSX_MIN_VERSION) -darwin_CXX:=$(shell xcrun -f clang++) -mmacosx-version-min=$(OSX_MIN_VERSION) +darwin_CXX:=$(shell xcrun -f clang++) -mmacosx-version-min=$(OSX_MIN_VERSION) -stdlib=libc++ darwin_AR:=$(shell xcrun -f ar) darwin_RANLIB:=$(shell xcrun -f ranlib) darwin_STRIP:=$(shell xcrun -f strip) From 08d7b563e91ed2ad226ec2505a5a850ab869d2f0 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 4 May 2016 14:21:04 +0200 Subject: [PATCH 0254/1802] util: switch LogPrint and error to variadic templates --- src/util.h | 43 ++++++++++++++++++------------------------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/src/util.h b/src/util.h index ac099f11845d3..25c9b733e871f 100644 --- a/src/util.h +++ b/src/util.h @@ -76,40 +76,33 @@ int LogPrintStr(const std::string &str); #define LogPrintf(...) LogPrint(NULL, __VA_ARGS__) -/** - * When we switch to C++11, this can be switched to variadic templates instead - * of this macro-based construction (see tinyformat.h). - */ -#define MAKE_ERROR_AND_LOG_FUNC(n) \ - /** Print to debug.log if -debug=category switch is given OR category is NULL. */ \ - template \ - static inline int LogPrint(const char* category, const char* format, TINYFORMAT_VARARGS(n)) \ - { \ - if(!LogAcceptCategory(category)) return 0; \ - return LogPrintStr(tfm::format(format, TINYFORMAT_PASSARGS(n))); \ - } \ - /** Log error and return false */ \ - template \ - static inline bool error(const char* format, TINYFORMAT_VARARGS(n)) \ - { \ - LogPrintStr("ERROR: " + tfm::format(format, TINYFORMAT_PASSARGS(n)) + "\n"); \ - return false; \ - } +template +static inline int LogPrint(const char* category, const char* fmt, const T1& v1, const Args&... args) +{ + if(!LogAcceptCategory(category)) return 0; \ + return LogPrintStr(tfm::format(fmt, v1, args...)); +} -TINYFORMAT_FOREACH_ARGNUM(MAKE_ERROR_AND_LOG_FUNC) +template +bool error(const char* fmt, const T1& v1, const Args&... args) +{ + LogPrintStr("ERROR: " + tfm::format(fmt, v1, args...) + "\n"); + return false; +} /** * Zero-arg versions of logging and error, these are not covered by - * TINYFORMAT_FOREACH_ARGNUM + * the variadic templates above (and don't take format arguments but + * bare strings). */ -static inline int LogPrint(const char* category, const char* format) +static inline int LogPrint(const char* category, const char* s) { if(!LogAcceptCategory(category)) return 0; - return LogPrintStr(format); + return LogPrintStr(s); } -static inline bool error(const char* format) +static inline bool error(const char* s) { - LogPrintStr(std::string("ERROR: ") + format + "\n"); + LogPrintStr(std::string("ERROR: ") + s + "\n"); return false; } From 0281678d6ebf68dacfb6ecaf7c231fedcd971d66 Mon Sep 17 00:00:00 2001 From: Warren Togami Date: Thu, 28 Apr 2016 15:07:31 -0700 Subject: [PATCH 0255/1802] doc: Fedora build requirements --- doc/build-unix.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/doc/build-unix.md b/doc/build-unix.md index dc754fc7339c9..27c57088af015 100644 --- a/doc/build-unix.md +++ b/doc/build-unix.md @@ -124,6 +124,24 @@ libqrencode (optional) can be installed with: Once these are installed, they will be found by configure and a bitcoin-qt executable will be built by default. +Dependency Build Instructions: Fedora +------------------------------------- +Build requirements: + + sudo dnf install libtool make autoconf automake openssl-devel libevent-devel boost-devel libdb4-devel libdb4-cxx-devel + +Optional: + + sudo dnf install miniupnpc-devel + +To build with Qt 5 (recommended) you need the following: + + sudo dnf install qt5-qttools-devel qtr5-qtbase-devel protobuf-devel + +libqrencode (optional) can be installed with: + + sudo dnf install qrencode-devel + Notes ----- The release is built with GCC and then "strip bitcoind" to strip the debug From 1475ecf61141e03f63a79d59831c411e0e8a5c0a Mon Sep 17 00:00:00 2001 From: EthanHeilman Date: Wed, 16 Mar 2016 12:54:30 -0400 Subject: [PATCH 0256/1802] Fix de-serialization bug where AddrMan is corrupted after exception * CAddrDB modified so that when de-serialization code throws an exception Addrman is reset to a clean state * CAddrDB modified to make unit tests possible * Regression test created to ensure bug is fixed * StartNode modifed to clear adrman if CAddrDB::Read returns an error code. --- src/Makefile.test.include | 1 + src/net.cpp | 8 +++ src/net.h | 1 + src/test/net_tests.cpp | 136 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 146 insertions(+) create mode 100644 src/test/net_tests.cpp diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 468d3043a7155..edeca6b28c2e2 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -60,6 +60,7 @@ BITCOIN_TESTS =\ test/merkle_tests.cpp \ test/miner_tests.cpp \ test/multisig_tests.cpp \ + test/net_tests.cpp \ test/netbase_tests.cpp \ test/pmt_tests.cpp \ test/policyestimator_tests.cpp \ diff --git a/src/net.cpp b/src/net.cpp index d9c4c117379c5..cf53816034c15 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1944,6 +1944,7 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler) if (adb.Read(addrman)) LogPrintf("Loaded %i addresses from peers.dat %dms\n", addrman.size(), GetTimeMillis() - nStart); else { + addrman.Clear(); // Addrman can be in an inconsistent state after failure, reset it LogPrintf("Invalid or missing peers.dat; recreating\n"); DumpAddresses(); } @@ -2336,6 +2337,11 @@ bool CAddrDB::Read(CAddrMan& addr) if (hashIn != hashTmp) return error("%s: Checksum mismatch, data corrupted", __func__); + return Read(addr, ssPeers); +} + +bool CAddrDB::Read(CAddrMan& addr, CDataStream& ssPeers) +{ unsigned char pchMsgTmp[4]; try { // de-serialize file header (network specific magic number) and .. @@ -2349,6 +2355,8 @@ bool CAddrDB::Read(CAddrMan& addr) ssPeers >> addr; } catch (const std::exception& e) { + // de-serialization has failed, ensure addrman is left in a clean state + addr.Clear(); return error("%s: Deserialize or I/O error - %s", __func__, e.what()); } diff --git a/src/net.h b/src/net.h index 833c9cf07cb0b..dfa270544f22f 100644 --- a/src/net.h +++ b/src/net.h @@ -779,6 +779,7 @@ class CAddrDB CAddrDB(); bool Write(const CAddrMan& addr); bool Read(CAddrMan& addr); + bool Read(CAddrMan& addr, CDataStream& ssPeers); }; /** Access to the banlist database (banlist.dat) */ diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp new file mode 100644 index 0000000000000..6debf6ac5e168 --- /dev/null +++ b/src/test/net_tests.cpp @@ -0,0 +1,136 @@ +// Copyright (c) 2012-2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "addrman.h" +#include "test/test_bitcoin.h" +#include +#include +#include "hash.h" +#include "serialize.h" +#include "streams.h" +#include "net.h" +#include "chainparams.h" + +using namespace std; + +class CAddrManSerializationMock : public CAddrMan +{ +public: + virtual void Serialize(CDataStream& s, int nType, int nVersionDummy) const = 0; +}; + +class CAddrManUncorrupted : public CAddrManSerializationMock +{ +public: + void Serialize(CDataStream& s, int nType, int nVersionDummy) const + { + CAddrMan::Serialize(s, nType, nVersionDummy); + } +}; + +class CAddrManCorrupted : public CAddrManSerializationMock +{ +public: + void Serialize(CDataStream& s, int nType, int nVersionDummy) const + { + // Produces corrupt output that claims addrman has 20 addrs when it only has one addr. + unsigned char nVersion = 1; + s << nVersion; + s << ((unsigned char)32); + s << nKey; + s << 10; // nNew + s << 10; // nTried + + int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30); + s << nUBuckets; + + CAddress addr = CAddress(CService("252.1.1.1", 7777)); + CAddrInfo info = CAddrInfo(addr, CNetAddr("252.2.2.2")); + s << info; + } +}; + +CDataStream AddrmanToStream(CAddrManSerializationMock& addrman) +{ + CDataStream ssPeersIn(SER_DISK, CLIENT_VERSION); + ssPeersIn << FLATDATA(Params().MessageStart()); + ssPeersIn << addrman; + std::string str = ssPeersIn.str(); + vector vchData(str.begin(), str.end()); + return CDataStream(vchData, SER_DISK, CLIENT_VERSION); +} + +BOOST_FIXTURE_TEST_SUITE(net_tests, BasicTestingSetup) + +BOOST_AUTO_TEST_CASE(caddrdb_read) +{ + CAddrManUncorrupted addrmanUncorrupted; + + CService addr1 = CService("250.7.1.1", 8333); + CService addr2 = CService("250.7.2.2", 9999); + CService addr3 = CService("250.7.3.3", 9999); + + // Add three addresses to new table. + addrmanUncorrupted.Add(CAddress(addr1), CService("252.5.1.1", 8333)); + addrmanUncorrupted.Add(CAddress(addr2), CService("252.5.1.1", 8333)); + addrmanUncorrupted.Add(CAddress(addr3), CService("252.5.1.1", 8333)); + + // Test that the de-serialization does not throw an exception. + CDataStream ssPeers1 = AddrmanToStream(addrmanUncorrupted); + bool exceptionThrown = false; + CAddrMan addrman1; + + BOOST_CHECK(addrman1.size() == 0); + try { + unsigned char pchMsgTmp[4]; + ssPeers1 >> FLATDATA(pchMsgTmp); + ssPeers1 >> addrman1; + } catch (const std::exception& e) { + exceptionThrown = true; + } + + BOOST_CHECK(addrman1.size() == 3); + BOOST_CHECK(exceptionThrown == false); + + // Test that CAddrDB::Read creates an addrman with the correct number of addrs. + CDataStream ssPeers2 = AddrmanToStream(addrmanUncorrupted); + + CAddrMan addrman2; + CAddrDB adb; + BOOST_CHECK(addrman2.size() == 0); + adb.Read(addrman2, ssPeers2); + BOOST_CHECK(addrman2.size() == 3); +} + + +BOOST_AUTO_TEST_CASE(caddrdb_read_corrupted) +{ + CAddrManCorrupted addrmanCorrupted; + + // Test that the de-serialization of corrupted addrman throws an exception. + CDataStream ssPeers1 = AddrmanToStream(addrmanCorrupted); + bool exceptionThrown = false; + CAddrMan addrman1; + BOOST_CHECK(addrman1.size() == 0); + try { + unsigned char pchMsgTmp[4]; + ssPeers1 >> FLATDATA(pchMsgTmp); + ssPeers1 >> addrman1; + } catch (const std::exception& e) { + exceptionThrown = true; + } + // Even through de-serialization failed adddrman is not left in a clean state. + BOOST_CHECK(addrman1.size() == 1); + BOOST_CHECK(exceptionThrown); + + // Test that CAddrDB::Read leaves addrman in a clean state if de-serialization fails. + CDataStream ssPeers2 = AddrmanToStream(addrmanCorrupted); + + CAddrMan addrman2; + CAddrDB adb; + BOOST_CHECK(addrman2.size() == 0); + adb.Read(addrman2, ssPeers2); + BOOST_CHECK(addrman2.size() == 0); +} + +BOOST_AUTO_TEST_SUITE_END() From 091d6e04998d2c88dd7f42ad2d90929f428764c2 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 28 Apr 2016 19:03:05 +0200 Subject: [PATCH 0257/1802] http: Do a pending c++11 simplification Use std::unique_ptr for handling work items. This makes the code more RAII and, as mentioned in the comment, is what I planned when I wrote the code in the first place. --- src/httpserver.cpp | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/httpserver.cpp b/src/httpserver.cpp index a98eff7c167d7..8297b6f758398 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -71,8 +71,7 @@ class WorkQueue /** Mutex protects entire object */ CWaitableCriticalSection cs; CConditionVariable cond; - /* XXX in C++11 we can use std::unique_ptr here and avoid manual cleanup */ - std::deque queue; + std::deque> queue; bool running; size_t maxDepth; int numThreads; @@ -101,15 +100,11 @@ class WorkQueue numThreads(0) { } - /*( Precondition: worker threads have all stopped + /** Precondition: worker threads have all stopped * (call WaitExit) */ ~WorkQueue() { - while (!queue.empty()) { - delete queue.front(); - queue.pop_front(); - } } /** Enqueue a work item */ bool Enqueue(WorkItem* item) @@ -118,7 +113,7 @@ class WorkQueue if (queue.size() >= maxDepth) { return false; } - queue.push_back(item); + queue.emplace_back(std::unique_ptr(item)); cond.notify_one(); return true; } @@ -127,18 +122,17 @@ class WorkQueue { ThreadCounter count(*this); while (running) { - WorkItem* i = 0; + std::unique_ptr i; { boost::unique_lock lock(cs); while (running && queue.empty()) cond.wait(lock); if (!running) break; - i = queue.front(); + i = std::move(queue.front()); queue.pop_front(); } (*i)(); - delete i; } } /** Interrupt and exit loops */ From f97b410fdd57743f9a26ea49086534000eb9626a Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 4 May 2016 15:37:26 +0200 Subject: [PATCH 0258/1802] http: Add log message when work queue is full More useful error reporting. --- src/httpserver.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/httpserver.cpp b/src/httpserver.cpp index 8297b6f758398..67a9e1e92f7b4 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -286,8 +286,10 @@ static void http_request_cb(struct evhttp_request* req, void* arg) assert(workQueue); if (workQueue->Enqueue(item.get())) item.release(); /* if true, queue took ownership */ - else + else { + LogPrintf("WARNING: request rejected because http work queue depth exceeded, it can be increased with the -rpcworkqueue= setting\n"); item->req->WriteReply(HTTP_INTERNAL, "Work queue depth exceeded"); + } } else { hreq->WriteReply(HTTP_NOTFOUND); } From 37b21372a0a3e5d876a87f03c8cbef2e02d8dc92 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 4 May 2016 15:55:23 +0200 Subject: [PATCH 0259/1802] http: Change boost::scoped_ptr to std::unique_ptr in HTTPRequest No need for boost here. --- src/httpserver.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/httpserver.cpp b/src/httpserver.cpp index 67a9e1e92f7b4..c193d2af1bac2 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -36,7 +36,6 @@ #include // for to_lower() #include -#include /** Maximum size of http request (request line + headers) */ static const size_t MAX_HEADERS_SIZE = 8192; @@ -54,7 +53,7 @@ class HTTPWorkItem : public HTTPClosure func(req.get(), path); } - boost::scoped_ptr req; + std::unique_ptr req; private: std::string path; From f0188f9178a22fd493ed228c008d4cc25ac2952d Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 4 May 2016 16:05:17 +0200 Subject: [PATCH 0260/1802] http: use std::move to move HTTPRequest into HTTPWorkItem Thanks to Cory Fields for the idea. --- src/httpserver.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/httpserver.cpp b/src/httpserver.cpp index c193d2af1bac2..812940eaf9861 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -44,8 +44,8 @@ static const size_t MAX_HEADERS_SIZE = 8192; class HTTPWorkItem : public HTTPClosure { public: - HTTPWorkItem(HTTPRequest* req, const std::string &path, const HTTPRequestHandler& func): - req(req), path(path), func(func) + HTTPWorkItem(std::unique_ptr req, const std::string &path, const HTTPRequestHandler& func): + req(std::move(req)), path(path), func(func) { } void operator()() @@ -281,7 +281,7 @@ static void http_request_cb(struct evhttp_request* req, void* arg) // Dispatch to worker thread if (i != iend) { - std::unique_ptr item(new HTTPWorkItem(hreq.release(), path, i->handler)); + std::unique_ptr item(new HTTPWorkItem(std::move(hreq), path, i->handler)); assert(workQueue); if (workQueue->Enqueue(item.get())) item.release(); /* if true, queue took ownership */ From fa389d4edc367073e2ccc6d1f0790c4b72ba17f2 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sat, 19 Mar 2016 20:58:06 +0100 Subject: [PATCH 0261/1802] [qa] Switch to py3 --- .travis.yml | 10 +- doc/zmq.md | 2 +- qa/README.md | 4 +- qa/pull-tester/rpc-tests.py | 10 +- qa/pull-tester/tests_config.py.in | 6 +- qa/rpc-tests/abandonconflict.py | 17 ++- qa/rpc-tests/bip65-cltv-p2p.py | 15 ++- qa/rpc-tests/bip65-cltv.py | 8 +- qa/rpc-tests/bip68-112-113-p2p.py | 109 +++++++++--------- qa/rpc-tests/bip68-sequence.py | 30 ++--- qa/rpc-tests/bip9-softforks.py | 9 +- qa/rpc-tests/bipdersig-p2p.py | 15 ++- qa/rpc-tests/bipdersig.py | 8 +- qa/rpc-tests/blockchain.py | 18 +-- qa/rpc-tests/decodescript.py | 4 +- qa/rpc-tests/disablewallet.py | 4 +- qa/rpc-tests/forknotify.py | 4 +- qa/rpc-tests/fundrawtransaction.py | 12 +- qa/rpc-tests/getblocktemplate_longpoll.py | 6 +- qa/rpc-tests/getblocktemplate_proposals.py | 12 +- qa/rpc-tests/getchaintips.py | 4 +- qa/rpc-tests/httpbasics.py | 38 +++--- qa/rpc-tests/importprunedfunds.py | 4 +- qa/rpc-tests/invalidateblock.py | 30 ++--- qa/rpc-tests/invalidblockrequest.py | 11 +- qa/rpc-tests/invalidtxrequest.py | 11 +- qa/rpc-tests/keypool.py | 4 +- qa/rpc-tests/listtransactions.py | 4 +- qa/rpc-tests/maxblocksinflight.py | 11 +- qa/rpc-tests/maxuploadtarget.py | 35 +++--- qa/rpc-tests/mempool_limit.py | 6 +- qa/rpc-tests/mempool_packages.py | 24 ++-- qa/rpc-tests/mempool_reorg.py | 4 +- qa/rpc-tests/mempool_resurrect_test.py | 4 +- qa/rpc-tests/mempool_spendcoinbase.py | 4 +- qa/rpc-tests/merkle_blocks.py | 6 +- qa/rpc-tests/multi_rpc.py | 29 ++--- qa/rpc-tests/nodehandling.py | 16 +-- qa/rpc-tests/p2p-acceptblock.py | 37 +++--- qa/rpc-tests/p2p-feefilter.py | 14 +-- qa/rpc-tests/p2p-fullblocktest.py | 7 +- qa/rpc-tests/p2p-versionbits-warning.py | 7 +- qa/rpc-tests/prioritise_transaction.py | 14 +-- qa/rpc-tests/proxy_test.py | 7 +- qa/rpc-tests/pruning.py | 68 +++++------ qa/rpc-tests/rawtransactions.py | 4 +- qa/rpc-tests/receivedby.py | 4 +- qa/rpc-tests/reindex.py | 6 +- qa/rpc-tests/replace-by-fee.py | 26 ++--- qa/rpc-tests/rest.py | 25 ++-- qa/rpc-tests/rpcbind_test.py | 6 +- qa/rpc-tests/sendheaders.py | 45 ++++---- qa/rpc-tests/signmessages.py | 2 +- qa/rpc-tests/signrawtransactions.py | 4 +- qa/rpc-tests/smartfees.py | 6 +- qa/rpc-tests/test_framework/bignum.py | 5 +- qa/rpc-tests/test_framework/blockstore.py | 13 ++- qa/rpc-tests/test_framework/blocktools.py | 6 +- qa/rpc-tests/test_framework/comptool.py | 17 ++- qa/rpc-tests/test_framework/coverage.py | 7 +- qa/rpc-tests/test_framework/mininode.py | 77 +++++++------ qa/rpc-tests/test_framework/netutil.py | 4 +- qa/rpc-tests/test_framework/script.py | 11 +- qa/rpc-tests/test_framework/socks5.py | 9 +- qa/rpc-tests/test_framework/test_framework.py | 8 +- qa/rpc-tests/test_framework/util.py | 21 ++-- qa/rpc-tests/txn_clone.py | 4 +- qa/rpc-tests/txn_doublespend.py | 4 +- qa/rpc-tests/wallet.py | 8 +- qa/rpc-tests/walletbackup.py | 4 +- qa/rpc-tests/zapwallettxes.py | 6 +- qa/rpc-tests/zmq_test.py | 17 +-- 72 files changed, 504 insertions(+), 547 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2f3ea4e76f859..fd70d3ab52d7c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,15 +37,15 @@ matrix: - compiler: ": ARM" env: HOST=arm-linux-gnueabihf PACKAGES="g++-arm-linux-gnueabihf" DEP_OPTS="NO_QT=1" CHECK_DOC=1 GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" - compiler: ": Win32" - env: HOST=i686-w64-mingw32 DPKG_ADD_ARCH="i386" DEP_OPTS="NO_QT=1" PACKAGES="nsis g++-mingw-w64-i686 wine1.6 bc" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-reduce-exports" + env: HOST=i686-w64-mingw32 DPKG_ADD_ARCH="i386" DEP_OPTS="NO_QT=1" PACKAGES="python3 nsis g++-mingw-w64-i686 wine1.6 bc" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-reduce-exports" - compiler: ": 32-bit + dash" - env: HOST=i686-pc-linux-gnu PACKAGES="g++-multilib bc python-zmq" DEP_OPTS="NO_QT=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++" USE_SHELL="/bin/dash" + env: HOST=i686-pc-linux-gnu PACKAGES="g++-multilib bc python3-zmq" DEP_OPTS="NO_QT=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++" USE_SHELL="/bin/dash" - compiler: ": Win64" - env: HOST=x86_64-w64-mingw32 DPKG_ADD_ARCH="i386" DEP_OPTS="NO_QT=1" PACKAGES="nsis g++-mingw-w64-x86-64 wine1.6 bc" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-reduce-exports" + env: HOST=x86_64-w64-mingw32 DPKG_ADD_ARCH="i386" DEP_OPTS="NO_QT=1" PACKAGES="python3 nsis g++-mingw-w64-x86-64 wine1.6 bc" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-reduce-exports" - compiler: ": bitcoind" - env: HOST=x86_64-unknown-linux-gnu PACKAGES="bc python-zmq" DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports CPPFLAGS=-DDEBUG_LOCKORDER" + env: HOST=x86_64-unknown-linux-gnu PACKAGES="bc python3-zmq" DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports CPPFLAGS=-DDEBUG_LOCKORDER" - compiler: ": No wallet" - env: HOST=x86_64-unknown-linux-gnu DEP_OPTS="NO_WALLET=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" + env: HOST=x86_64-unknown-linux-gnu PACKAGES="python3" DEP_OPTS="NO_WALLET=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" - compiler: ": Cross-Mac" env: HOST=x86_64-apple-darwin11 PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev" BITCOIN_CONFIG="--enable-reduce-exports" OSX_SDK=10.9 GOAL="deploy" exclude: diff --git a/doc/zmq.md b/doc/zmq.md index 8d795a388a9b4..6079e3254f783 100644 --- a/doc/zmq.md +++ b/doc/zmq.md @@ -38,7 +38,7 @@ newer. Typically, it is packaged by distributions as something like *libzmq3-dev*. The C++ wrapper for ZeroMQ is *not* needed. In order to run the example Python client scripts in contrib/ one must -also install *python-zmq*, though this is not necessary for daemon +also install *python3-zmq*, though this is not necessary for daemon operation. ## Enabling diff --git a/qa/README.md b/qa/README.md index 2b476c4d8d93f..3e0a526d1306f 100644 --- a/qa/README.md +++ b/qa/README.md @@ -11,9 +11,9 @@ Before running the tests, the following must be installed. Unix ---- -The python-zmq library is required. On Ubuntu or Debian it can be installed via: +The python3-zmq library is required. On Ubuntu or Debian it can be installed via: ``` -sudo apt-get install python-zmq +sudo apt-get install python3-zmq ``` Running tests diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index 26142c35e9992..15153b7f586fc 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -70,14 +70,14 @@ if EXEEXT == ".exe" and "-win" not in opts: # https://github.com/bitcoin/bitcoin/commit/d52802551752140cf41f0d9a225a43e84404d3e9 # https://github.com/bitcoin/bitcoin/pull/5677#issuecomment-136646964 - print "Win tests currently disabled by default. Use -win option to enable" + print("Win tests currently disabled by default. Use -win option to enable") sys.exit(0) if not (ENABLE_WALLET == 1 and ENABLE_UTILS == 1 and ENABLE_BITCOIND == 1): - print "No rpc tests to run. Wallet, utils, and bitcoind must all be enabled" + print("No rpc tests to run. Wallet, utils, and bitcoind must all be enabled") sys.exit(0) -# python-zmq may not be installed. Handle this gracefully and with some helpful info +# python3-zmq may not be installed. Handle this gracefully and with some helpful info if ENABLE_ZMQ: try: import zmq diff --git a/qa/pull-tester/tests_config.py.in b/qa/pull-tester/tests_config.py.in index 937b4231f12f8..2356b5200ebfe 100644 --- a/qa/pull-tester/tests_config.py.in +++ b/qa/pull-tester/tests_config.py.in @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2013-2014 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2013-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -11,5 +11,3 @@ EXEEXT="@EXEEXT@" @BUILD_BITCOIN_UTILS_TRUE@ENABLE_UTILS=1 @BUILD_BITCOIND_TRUE@ENABLE_BITCOIND=1 @ENABLE_ZMQ_TRUE@ENABLE_ZMQ=1 - - diff --git a/qa/rpc-tests/abandonconflict.py b/qa/rpc-tests/abandonconflict.py index a83aa97fcd806..b6c4b9db48fbf 100755 --- a/qa/rpc-tests/abandonconflict.py +++ b/qa/rpc-tests/abandonconflict.py @@ -1,15 +1,12 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * -try: - import urllib.parse as urlparse -except ImportError: - import urlparse +import urllib.parse class AbandonConflictTest(BitcoinTestFramework): @@ -34,7 +31,7 @@ def run_test(self): assert(balance - newbalance < Decimal("0.001")) #no more than fees lost balance = newbalance - url = urlparse.urlparse(self.nodes[1].url) + url = urllib.parse.urlparse(self.nodes[1].url) self.nodes[0].disconnectnode(url.hostname+":"+str(p2p_port(1))) # Identify the 10btc outputs @@ -151,9 +148,9 @@ def run_test(self): self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash()) newbalance = self.nodes[0].getbalance() #assert(newbalance == balance - Decimal("10")) - print "If balance has not declined after invalidateblock then out of mempool wallet tx which is no longer" - print "conflicted has not resumed causing its inputs to be seen as spent. See Issue #7315" - print balance , " -> " , newbalance , " ?" + print("If balance has not declined after invalidateblock then out of mempool wallet tx which is no longer") + print("conflicted has not resumed causing its inputs to be seen as spent. See Issue #7315") + print(str(balance) + " -> " + str(newbalance) + " ?") if __name__ == '__main__': AbandonConflictTest().main() diff --git a/qa/rpc-tests/bip65-cltv-p2p.py b/qa/rpc-tests/bip65-cltv-p2p.py index 99d74344aef95..60923b9dda90a 100755 --- a/qa/rpc-tests/bip65-cltv-p2p.py +++ b/qa/rpc-tests/bip65-cltv-p2p.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python2 -# Copyright (c) 2015 The Bitcoin Core developers -# Distributed under the MIT/X11 software license, see the accompanying +#!/usr/bin/env python3 +# Copyright (c) 2015-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. -# from test_framework.test_framework import ComparisonTestFramework from test_framework.util import * @@ -67,13 +66,13 @@ def get_tests(self): self.coinbase_blocks = self.nodes[0].generate(2) height = 3 # height of the next block to build - self.tip = int ("0x" + self.nodes[0].getbestblockhash() + "L", 0) + self.tip = int("0x" + self.nodes[0].getbestblockhash(), 0) self.nodeaddress = self.nodes[0].getnewaddress() self.last_block_time = int(time.time()) ''' 98 more version 3 blocks ''' test_blocks = [] - for i in xrange(98): + for i in range(98): block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1) block.nVersion = 3 block.rehash() @@ -86,7 +85,7 @@ def get_tests(self): ''' Mine 749 version 4 blocks ''' test_blocks = [] - for i in xrange(749): + for i in range(749): block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1) block.nVersion = 4 block.rehash() @@ -138,7 +137,7 @@ def get_tests(self): ''' Mine 199 new version blocks on last valid tip ''' test_blocks = [] - for i in xrange(199): + for i in range(199): block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1) block.nVersion = 4 block.rehash() diff --git a/qa/rpc-tests/bip65-cltv.py b/qa/rpc-tests/bip65-cltv.py index f666a07c9b769..9d83fc947b166 100755 --- a/qa/rpc-tests/bip65-cltv.py +++ b/qa/rpc-tests/bip65-cltv.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2015-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -32,7 +32,7 @@ def run_test(self): raise AssertionError("Failed to mine 100 version=3 blocks") # Mine 750 new-version blocks - for i in xrange(15): + for i in range(15): self.nodes[2].generate(50) self.sync_all() if (self.nodes[0].getblockcount() != cnt + 850): @@ -49,7 +49,7 @@ def run_test(self): # TODO: check that new CHECKLOCKTIMEVERIFY rules are enforced # Mine 198 new-version blocks - for i in xrange(2): + for i in range(2): self.nodes[2].generate(99) self.sync_all() if (self.nodes[0].getblockcount() != cnt + 1049): diff --git a/qa/rpc-tests/bip68-112-113-p2p.py b/qa/rpc-tests/bip68-112-113-p2p.py index 3bcfdabe269a1..eedb60e3a0958 100755 --- a/qa/rpc-tests/bip68-112-113-p2p.py +++ b/qa/rpc-tests/bip68-112-113-p2p.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # Copyright (c) 2015 The Bitcoin Core developers -# Distributed under the MIT/X11 software license, see the accompanying +# Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. -# from test_framework.test_framework import ComparisonTestFramework from test_framework.util import * @@ -63,13 +62,13 @@ # b31,b25,b22,b18 represent the 31st, 25th, 22nd and 18th bits respectively in the nSequence field # relative_locktimes[b31][b25][b22][b18] is a base_relative_locktime with the indicated bits set if their indices are 1 relative_locktimes = [] -for b31 in xrange(2): +for b31 in range(2): b25times = [] - for b25 in xrange(2): + for b25 in range(2): b22times = [] - for b22 in xrange(2): + for b22 in range(2): b18times = [] - for b18 in xrange(2): + for b18 in range(2): rlt = base_relative_locktime if (b31): rlt = rlt | seq_disable_flag @@ -86,10 +85,10 @@ def all_rlt_txs(txarray): txs = [] - for b31 in xrange(2): - for b25 in xrange(2): - for b22 in xrange(2): - for b18 in xrange(2): + for b31 in range(2): + for b25 in range(2): + for b22 in range(2): + for b18 in range(2): txs.append(txarray[b31][b25][b22][b18]) return txs @@ -131,7 +130,7 @@ def sign_transaction(self, node, unsignedtx): return tx def generate_blocks(self, number, version, test_blocks = []): - for i in xrange(number): + for i in range(number): block = self.create_test_block([], version) test_blocks.append([block, True]) self.last_block_time += 600 @@ -152,13 +151,13 @@ def create_bip68txs(self, bip68inputs, txversion, locktime_delta = 0): txs = [] assert(len(bip68inputs) >= 16) i = 0 - for b31 in xrange(2): + for b31 in range(2): b25txs = [] - for b25 in xrange(2): + for b25 in range(2): b22txs = [] - for b22 in xrange(2): + for b22 in range(2): b18txs = [] - for b18 in xrange(2): + for b18 in range(2): tx = self.create_transaction(self.nodes[0], bip68inputs[i], self.nodeaddress, Decimal("49.98")) i += 1 tx.nVersion = txversion @@ -180,13 +179,13 @@ def create_bip112txs(self, bip112inputs, varyOP_CSV, txversion, locktime_delta = txs = [] assert(len(bip112inputs) >= 16) i = 0 - for b31 in xrange(2): + for b31 in range(2): b25txs = [] - for b25 in xrange(2): + for b25 in range(2): b22txs = [] - for b22 in xrange(2): + for b22 in range(2): b18txs = [] - for b18 in xrange(2): + for b18 in range(2): tx = self.create_transaction(self.nodes[0], bip112inputs[i], self.nodeaddress, Decimal("49.98")) i += 1 if (varyOP_CSV): # if varying OP_CSV, nSequence is fixed @@ -212,7 +211,7 @@ def get_tests(self): self.nodes[0].setmocktime(0) # set time back to present so yielded blocks aren't in the future as we advance last_block_time self.tipheight = 82 # height of the next block to build self.last_block_time = long_past_time - self.tip = int ("0x" + self.nodes[0].getbestblockhash() + "L", 0) + self.tip = int("0x" + self.nodes[0].getbestblockhash(), 0) self.nodeaddress = self.nodes[0].getnewaddress() assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'defined') @@ -250,20 +249,20 @@ def get_tests(self): # Note we reuse inputs for v1 and v2 txs so must test these separately # 16 normal inputs bip68inputs = [] - for i in xrange(16): + for i in range(16): bip68inputs.append(self.send_generic_input_tx(self.nodes[0], self.coinbase_blocks)) # 2 sets of 16 inputs with 10 OP_CSV OP_DROP (actually will be prepended to spending scriptSig) bip112basicinputs = [] - for j in xrange(2): + for j in range(2): inputs = [] - for i in xrange(16): + for i in range(16): inputs.append(self.send_generic_input_tx(self.nodes[0], self.coinbase_blocks)) bip112basicinputs.append(inputs) # 2 sets of 16 varied inputs with (relative_lock_time) OP_CSV OP_DROP (actually will be prepended to spending scriptSig) bip112diverseinputs = [] - for j in xrange(2): + for j in range(2): inputs = [] - for i in xrange(16): + for i in range(16): inputs.append(self.send_generic_input_tx(self.nodes[0], self.coinbase_blocks)) bip112diverseinputs.append(inputs) # 1 special input with -1 OP_CSV OP_DROP (actually will be prepended to spending scriptSig) @@ -274,7 +273,7 @@ def get_tests(self): self.nodes[0].setmocktime(self.last_block_time + 600) inputblockhash = self.nodes[0].generate(1)[0] # 1 block generated for inputs to be in chain at height 572 self.nodes[0].setmocktime(0) - self.tip = int("0x" + inputblockhash + "L", 0) + self.tip = int("0x" + inputblockhash, 0) self.tipheight += 1 self.last_block_time += 600 assert_equal(len(self.nodes[0].getblock(inputblockhash,True)["tx"]), 82+1) @@ -398,22 +397,22 @@ def get_tests(self): ### Version 2 txs ### bip68success_txs = [] # All txs with SEQUENCE_LOCKTIME_DISABLE_FLAG set pass - for b25 in xrange(2): - for b22 in xrange(2): - for b18 in xrange(2): + for b25 in range(2): + for b22 in range(2): + for b18 in range(2): bip68success_txs.append(bip68txs_v2[1][b25][b22][b18]) yield TestInstance([[self.create_test_block(bip68success_txs), True]]) # 15 self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash()) # All txs without flag fail as we are at delta height = 8 < 10 and delta time = 8 * 600 < 10 * 512 bip68timetxs = [] - for b25 in xrange(2): - for b18 in xrange(2): + for b25 in range(2): + for b18 in range(2): bip68timetxs.append(bip68txs_v2[0][b25][1][b18]) for tx in bip68timetxs: yield TestInstance([[self.create_test_block([tx]), False]]) # 16 - 19 bip68heighttxs = [] - for b25 in xrange(2): - for b18 in xrange(2): + for b25 in range(2): + for b18 in range(2): bip68heighttxs.append(bip68txs_v2[0][b25][0][b18]) for tx in bip68heighttxs: yield TestInstance([[self.create_test_block([tx]), False]]) # 20 - 23 @@ -445,9 +444,9 @@ def get_tests(self): yield TestInstance([[self.create_test_block([bip112tx_special_v1]), False]]) #32 # If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in argument to OP_CSV, version 1 txs should still pass success_txs = [] - for b25 in xrange(2): - for b22 in xrange(2): - for b18 in xrange(2): + for b25 in range(2): + for b22 in range(2): + for b18 in range(2): success_txs.append(bip112txs_vary_OP_CSV_v1[1][b25][b22][b18]) success_txs.append(bip112txs_vary_OP_CSV_9_v1[1][b25][b22][b18]) yield TestInstance([[self.create_test_block(success_txs), True]]) # 33 @@ -457,9 +456,9 @@ def get_tests(self): fail_txs = [] fail_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_v1)) fail_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_9_v1)) - for b25 in xrange(2): - for b22 in xrange(2): - for b18 in xrange(2): + for b25 in range(2): + for b22 in range(2): + for b18 in range(2): fail_txs.append(bip112txs_vary_OP_CSV_v1[0][b25][b22][b18]) fail_txs.append(bip112txs_vary_OP_CSV_9_v1[0][b25][b22][b18]) @@ -472,9 +471,9 @@ def get_tests(self): # If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in argument to OP_CSV, version 2 txs should pass (all sequence locks are met) success_txs = [] - for b25 in xrange(2): - for b22 in xrange(2): - for b18 in xrange(2): + for b25 in range(2): + for b22 in range(2): + for b18 in range(2): success_txs.append(bip112txs_vary_OP_CSV_v2[1][b25][b22][b18]) # 8/16 of vary_OP_CSV success_txs.append(bip112txs_vary_OP_CSV_9_v2[1][b25][b22][b18]) # 8/16 of vary_OP_CSV_9 @@ -485,9 +484,9 @@ def get_tests(self): # All txs with nSequence 9 should fail either due to earlier mismatch or failing the CSV check fail_txs = [] fail_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_9_v2)) # 16/16 of vary_nSequence_9 - for b25 in xrange(2): - for b22 in xrange(2): - for b18 in xrange(2): + for b25 in range(2): + for b22 in range(2): + for b18 in range(2): fail_txs.append(bip112txs_vary_OP_CSV_9_v2[0][b25][b22][b18]) # 16/16 of vary_OP_CSV_9 for tx in fail_txs: @@ -495,17 +494,17 @@ def get_tests(self): # If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in nSequence, tx should fail fail_txs = [] - for b25 in xrange(2): - for b22 in xrange(2): - for b18 in xrange(2): + for b25 in range(2): + for b22 in range(2): + for b18 in range(2): fail_txs.append(bip112txs_vary_nSequence_v2[1][b25][b22][b18]) # 8/16 of vary_nSequence for tx in fail_txs: yield TestInstance([[self.create_test_block([tx]), False]]) # 108-115 # If sequencelock types mismatch, tx should fail fail_txs = [] - for b25 in xrange(2): - for b18 in xrange(2): + for b25 in range(2): + for b18 in range(2): fail_txs.append(bip112txs_vary_nSequence_v2[0][b25][1][b18]) # 12/16 of vary_nSequence fail_txs.append(bip112txs_vary_OP_CSV_v2[0][b25][1][b18]) # 12/16 of vary_OP_CSV for tx in fail_txs: @@ -513,8 +512,8 @@ def get_tests(self): # Remaining txs should pass, just test masking works properly success_txs = [] - for b25 in xrange(2): - for b18 in xrange(2): + for b25 in range(2): + for b18 in range(2): success_txs.append(bip112txs_vary_nSequence_v2[0][b25][0][b18]) # 16/16 of vary_nSequence success_txs.append(bip112txs_vary_OP_CSV_v2[0][b25][0][b18]) # 16/16 of vary_OP_CSV yield TestInstance([[self.create_test_block(success_txs), True]]) # 124 @@ -522,8 +521,8 @@ def get_tests(self): # Additional test, of checking that comparison of two time types works properly time_txs = [] - for b25 in xrange(2): - for b18 in xrange(2): + for b25 in range(2): + for b18 in range(2): tx = bip112txs_vary_OP_CSV_v2[0][b25][1][b18] tx.vin[0].nSequence = base_relative_locktime | seq_type_flag signtx = self.sign_transaction(self.nodes[0], tx) diff --git a/qa/rpc-tests/bip68-sequence.py b/qa/rpc-tests/bip68-sequence.py index 33e05dfc51a09..717f7562cdee2 100755 --- a/qa/rpc-tests/bip68-sequence.py +++ b/qa/rpc-tests/bip68-sequence.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -35,28 +35,28 @@ def run_test(self): # Generate some coins self.nodes[0].generate(110) - print "Running test disable flag" + print("Running test disable flag") self.test_disable_flag() - print "Running test sequence-lock-confirmed-inputs" + print("Running test sequence-lock-confirmed-inputs") self.test_sequence_lock_confirmed_inputs() - print "Running test sequence-lock-unconfirmed-inputs" + print("Running test sequence-lock-unconfirmed-inputs") self.test_sequence_lock_unconfirmed_inputs() - print "Running test BIP68 not consensus before versionbits activation" + print("Running test BIP68 not consensus before versionbits activation") self.test_bip68_not_consensus() - print "Verifying nVersion=2 transactions aren't standard" + print("Verifying nVersion=2 transactions aren't standard") self.test_version2_relay(before_activation=True) - print "Activating BIP68 (and 112/113)" + print("Activating BIP68 (and 112/113)") self.activateCSV() - print "Verifying nVersion=2 transactions are now standard" + print("Verifying nVersion=2 transactions are now standard") self.test_version2_relay(before_activation=False) - print "Passed\n" + print("Passed\n") # Test that BIP68 is not in effect if tx version is 1, or if # the first sequence bit is set. @@ -125,7 +125,7 @@ def test_sequence_lock_confirmed_inputs(self): random.shuffle(addresses) num_outputs = random.randint(1, max_outputs) outputs = {} - for i in xrange(num_outputs): + for i in range(num_outputs): outputs[addresses[i]] = random.randint(1, 20)*0.01 self.nodes[0].sendmany("", outputs) self.nodes[0].generate(1) @@ -137,7 +137,7 @@ def test_sequence_lock_confirmed_inputs(self): # some of those inputs to be sequence locked (and randomly choose # between height/time locking). Small random chance of making the locks # all pass. - for i in xrange(400): + for i in range(400): # Randomly choose up to 10 inputs num_inputs = random.randint(1, 10) random.shuffle(utxos) @@ -151,7 +151,7 @@ def test_sequence_lock_confirmed_inputs(self): tx = CTransaction() tx.nVersion = 2 value = 0 - for j in xrange(num_inputs): + for j in range(num_inputs): sequence_value = 0xfffffffe # this disables sequence locks # 50% chance we enable sequence locks @@ -259,7 +259,7 @@ def test_nonzero_locks(orig_tx, node, relayfee, use_height_lock): # Use prioritisetransaction to lower the effective feerate to 0 self.nodes[0].prioritisetransaction(tx2.hash, -1e15, int(-self.relayfee*COIN)) cur_time = int(time.time()) - for i in xrange(10): + for i in range(10): self.nodes[0].setmocktime(cur_time + 600) self.nodes[0].generate(1) cur_time += 600 @@ -324,7 +324,7 @@ def test_nonzero_locks(orig_tx, node, relayfee, use_height_lock): # tx3 to be removed. tip = int(self.nodes[0].getblockhash(self.nodes[0].getblockcount()-1), 16) height = self.nodes[0].getblockcount() - for i in xrange(2): + for i in range(2): block = create_block(tip, create_coinbase(height), cur_time) block.nVersion = 3 block.rehash() diff --git a/qa/rpc-tests/bip9-softforks.py b/qa/rpc-tests/bip9-softforks.py index ddca3c2e33d34..e9b659d5082d2 100755 --- a/qa/rpc-tests/bip9-softforks.py +++ b/qa/rpc-tests/bip9-softforks.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # Copyright (c) 2015 The Bitcoin Core developers -# Distributed under the MIT/X11 software license, see the accompanying +# Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. -# from test_framework.test_framework import ComparisonTestFramework from test_framework.util import * @@ -64,7 +63,7 @@ def sign_transaction(self, node, tx): return tx def generate_blocks(self, number, version, test_blocks = []): - for i in xrange(number): + for i in range(number): block = create_block(self.tip, create_coinbase(self.height), self.last_block_time + 1) block.nVersion = version block.rehash() @@ -83,7 +82,7 @@ def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignatu # generate some coins for later self.coinbase_blocks = self.nodes[0].generate(2) self.height = 3 # height of the next block to build - self.tip = int ("0x" + self.nodes[0].getbestblockhash() + "L", 0) + self.tip = int("0x" + self.nodes[0].getbestblockhash(), 0) self.nodeaddress = self.nodes[0].getnewaddress() self.last_block_time = int(time.time()) diff --git a/qa/rpc-tests/bipdersig-p2p.py b/qa/rpc-tests/bipdersig-p2p.py index bba86a50c4c56..c4627308400b8 100755 --- a/qa/rpc-tests/bipdersig-p2p.py +++ b/qa/rpc-tests/bipdersig-p2p.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python2 -# Copyright (c) 2015 The Bitcoin Core developers -# Distributed under the MIT/X11 software license, see the accompanying +#!/usr/bin/env python3 +# Copyright (c) 2015-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. -# from test_framework.test_framework import ComparisonTestFramework from test_framework.util import * @@ -75,13 +74,13 @@ def get_tests(self): self.coinbase_blocks = self.nodes[0].generate(2) height = 3 # height of the next block to build - self.tip = int ("0x" + self.nodes[0].getbestblockhash() + "L", 0) + self.tip = int("0x" + self.nodes[0].getbestblockhash(), 0) self.nodeaddress = self.nodes[0].getnewaddress() self.last_block_time = int(time.time()) ''' 98 more version 2 blocks ''' test_blocks = [] - for i in xrange(98): + for i in range(98): block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1) block.nVersion = 2 block.rehash() @@ -94,7 +93,7 @@ def get_tests(self): ''' Mine 749 version 3 blocks ''' test_blocks = [] - for i in xrange(749): + for i in range(749): block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1) block.nVersion = 3 block.rehash() @@ -146,7 +145,7 @@ def get_tests(self): ''' Mine 199 new version blocks on last valid tip ''' test_blocks = [] - for i in xrange(199): + for i in range(199): block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1) block.nVersion = 3 block.rehash() diff --git a/qa/rpc-tests/bipdersig.py b/qa/rpc-tests/bipdersig.py index be9121c456831..f2d2c14a72c24 100755 --- a/qa/rpc-tests/bipdersig.py +++ b/qa/rpc-tests/bipdersig.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -32,7 +32,7 @@ def run_test(self): raise AssertionError("Failed to mine 100 version=2 blocks") # Mine 750 new-version blocks - for i in xrange(15): + for i in range(15): self.nodes[2].generate(50) self.sync_all() if (self.nodes[0].getblockcount() != cnt + 850): @@ -49,7 +49,7 @@ def run_test(self): # TODO: check that new DERSIG rules are enforced # Mine 198 new-version blocks - for i in xrange(2): + for i in range(2): self.nodes[2].generate(99) self.sync_all() if (self.nodes[0].getblockcount() != cnt + 1049): diff --git a/qa/rpc-tests/blockchain.py b/qa/rpc-tests/blockchain.py index 8f59ee741c366..c84047b5dd18c 100755 --- a/qa/rpc-tests/blockchain.py +++ b/qa/rpc-tests/blockchain.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -51,13 +51,13 @@ def _test_gettxoutsetinfo(self): node = self.nodes[0] res = node.gettxoutsetinfo() - assert_equal(res[u'total_amount'], Decimal('8725.00000000')) - assert_equal(res[u'transactions'], 200) - assert_equal(res[u'height'], 200) - assert_equal(res[u'txouts'], 200) - assert_equal(res[u'bytes_serialized'], 13924), - assert_equal(len(res[u'bestblock']), 64) - assert_equal(len(res[u'hash_serialized']), 64) + assert_equal(res['total_amount'], Decimal('8725.00000000')) + assert_equal(res['transactions'], 200) + assert_equal(res['height'], 200) + assert_equal(res['txouts'], 200) + assert_equal(res['bytes_serialized'], 13924), + assert_equal(len(res['bestblock']), 64) + assert_equal(len(res['hash_serialized']), 64) def _test_getblockheader(self): node = self.nodes[0] diff --git a/qa/rpc-tests/decodescript.py b/qa/rpc-tests/decodescript.py index 578844f2c5bb0..0037542e62e02 100755 --- a/qa/rpc-tests/decodescript.py +++ b/qa/rpc-tests/decodescript.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2015-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/qa/rpc-tests/disablewallet.py b/qa/rpc-tests/disablewallet.py index cb868029fa327..b25d2ba3352cf 100755 --- a/qa/rpc-tests/disablewallet.py +++ b/qa/rpc-tests/disablewallet.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2015-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/qa/rpc-tests/forknotify.py b/qa/rpc-tests/forknotify.py index 20e6ce961954b..421f3dd872973 100755 --- a/qa/rpc-tests/forknotify.py +++ b/qa/rpc-tests/forknotify.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py index 496c7fe8b0ed0..74849603f719d 100755 --- a/qa/rpc-tests/fundrawtransaction.py +++ b/qa/rpc-tests/fundrawtransaction.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -10,7 +10,7 @@ class RawTransactionsTest(BitcoinTestFramework): def setup_chain(self): - print("Initializing test directory "+self.options.tmpdir) + print(("Initializing test directory "+self.options.tmpdir)) initialize_chain_clean(self.options.tmpdir, 4) def setup_network(self, split=False): @@ -25,7 +25,7 @@ def setup_network(self, split=False): self.sync_all() def run_test(self): - print "Mining blocks..." + print("Mining blocks...") min_relay_tx_fee = self.nodes[0].getnetworkinfo()['relayfee'] # This test is not meant to test fee estimation and we'd like @@ -198,7 +198,7 @@ def run_test(self): try: self.nodes[2].fundrawtransaction(rawtx, {'foo': 'bar'}) raise AssertionError("Accepted invalid option foo") - except JSONRPCException,e: + except JSONRPCException as e: assert("Unexpected key foo" in e.error['message']) @@ -223,7 +223,7 @@ def run_test(self): try: self.nodes[2].fundrawtransaction(rawtx, {'changeAddress': 'foobar'}) raise AssertionError("Accepted invalid bitcoin address") - except JSONRPCException,e: + except JSONRPCException as e: assert("changeAddress must be a valid bitcoin address" in e.error['message']) diff --git a/qa/rpc-tests/getblocktemplate_longpoll.py b/qa/rpc-tests/getblocktemplate_longpoll.py index e2a839f718924..e443347077741 100755 --- a/qa/rpc-tests/getblocktemplate_longpoll.py +++ b/qa/rpc-tests/getblocktemplate_longpoll.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -27,7 +27,7 @@ class GetBlockTemplateLPTest(BitcoinTestFramework): ''' def run_test(self): - print "Warning: this test will take about 70 seconds in the best case. Be patient." + print("Warning: this test will take about 70 seconds in the best case. Be patient.") self.nodes[0].generate(10) templat = self.nodes[0].getblocktemplate() longpollid = templat['longpollid'] diff --git a/qa/rpc-tests/getblocktemplate_proposals.py b/qa/rpc-tests/getblocktemplate_proposals.py index be119031baf0b..1ad2af4c2e3ac 100755 --- a/qa/rpc-tests/getblocktemplate_proposals.py +++ b/qa/rpc-tests/getblocktemplate_proposals.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -46,7 +46,7 @@ def genmrklroot(leaflist): cur = n return cur[0] -def template_to_bytes(tmpl, txlist): +def template_to_bytearray(tmpl, txlist): blkver = pack(' MAX_REQUESTS: raise AssertionError("Error, too many blocks (%d) requested" % total_requests) - print "Round %d: success (total requests: %d)" % (count, total_requests) + print("Round %d: success (total requests: %d)" % (count, total_requests)) self.disconnectOkay = True self.connection.disconnect_node() @@ -78,7 +77,7 @@ def add_options(self, parser): help="Binary to test max block requests behavior") def setup_chain(self): - print "Initializing test directory "+self.options.tmpdir + print("Initializing test directory "+self.options.tmpdir) initialize_chain_clean(self.options.tmpdir, 1) def setup_network(self): diff --git a/qa/rpc-tests/maxuploadtarget.py b/qa/rpc-tests/maxuploadtarget.py index be45fecb5b32a..ec802d8155bd5 100755 --- a/qa/rpc-tests/maxuploadtarget.py +++ b/qa/rpc-tests/maxuploadtarget.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python2 -# -# Distributed under the MIT/X11 software license, see the accompanying +#!/usr/bin/env python3 +# Copyright (c) 2015-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. -# from test_framework.mininode import * from test_framework.test_framework import BitcoinTestFramework @@ -101,7 +100,7 @@ def setup_network(self): def mine_full_block(self, node, address): # Want to create a full block # We'll generate a 66k transaction below, and 14 of them is close to the 1MB block limit - for j in xrange(14): + for j in range(14): if len(self.utxo) < 14: self.utxo = node.listunspent() inputs=[] @@ -139,7 +138,7 @@ def run_test(self): test_nodes = [] connections = [] - for i in xrange(3): + for i in range(3): test_nodes.append(TestNode()) connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test_nodes[i])) test_nodes[i].add_connection(connections[i]) @@ -181,7 +180,7 @@ def run_test(self): # 144MB will be reserved for relaying new blocks, so expect this to # succeed for ~70 tries. - for i in xrange(success_count): + for i in range(success_count): test_nodes[0].send_message(getdata_request) test_nodes[0].sync_with_ping() assert_equal(test_nodes[0].block_receive_map[big_old_block], i+1) @@ -189,22 +188,22 @@ def run_test(self): assert_equal(len(self.nodes[0].getpeerinfo()), 3) # At most a couple more tries should succeed (depending on how long # the test has been running so far). - for i in xrange(3): + for i in range(3): test_nodes[0].send_message(getdata_request) test_nodes[0].wait_for_disconnect() assert_equal(len(self.nodes[0].getpeerinfo()), 2) - print "Peer 0 disconnected after downloading old block too many times" + print("Peer 0 disconnected after downloading old block too many times") # Requesting the current block on test_nodes[1] should succeed indefinitely, # even when over the max upload target. # We'll try 200 times getdata_request.inv = [CInv(2, big_new_block)] - for i in xrange(200): + for i in range(200): test_nodes[1].send_message(getdata_request) test_nodes[1].sync_with_ping() assert_equal(test_nodes[1].block_receive_map[big_new_block], i+1) - print "Peer 1 able to repeatedly download new block" + print("Peer 1 able to repeatedly download new block") # But if test_nodes[1] tries for an old block, it gets disconnected too. getdata_request.inv = [CInv(2, big_old_block)] @@ -212,9 +211,9 @@ def run_test(self): test_nodes[1].wait_for_disconnect() assert_equal(len(self.nodes[0].getpeerinfo()), 1) - print "Peer 1 disconnected after trying to download old block" + print("Peer 1 disconnected after trying to download old block") - print "Advancing system time on node to clear counters..." + print("Advancing system time on node to clear counters...") # If we advance the time by 24 hours, then the counters should reset, # and test_nodes[2] should be able to retrieve the old block. @@ -224,12 +223,12 @@ def run_test(self): test_nodes[2].sync_with_ping() assert_equal(test_nodes[2].block_receive_map[big_old_block], 1) - print "Peer 2 able to download old block" + print("Peer 2 able to download old block") [c.disconnect_node() for c in connections] #stop and start node 0 with 1MB maxuploadtarget, whitelist 127.0.0.1 - print "Restarting nodes with -whitelist=127.0.0.1" + print("Restarting nodes with -whitelist=127.0.0.1") stop_node(self.nodes[0], 0) self.nodes[0] = start_node(0, self.options.tmpdir, ["-debug", "-whitelist=127.0.0.1", "-maxuploadtarget=1", "-blockmaxsize=999000"]) @@ -237,7 +236,7 @@ def run_test(self): test_nodes = [] connections = [] - for i in xrange(3): + for i in range(3): test_nodes.append(TestNode()) connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test_nodes[i])) test_nodes[i].add_connection(connections[i]) @@ -247,7 +246,7 @@ def run_test(self): #retrieve 20 blocks which should be enough to break the 1MB limit getdata_request.inv = [CInv(2, big_new_block)] - for i in xrange(20): + for i in range(20): test_nodes[1].send_message(getdata_request) test_nodes[1].sync_with_ping() assert_equal(test_nodes[1].block_receive_map[big_new_block], i+1) @@ -257,7 +256,7 @@ def run_test(self): test_nodes[1].wait_for_disconnect() assert_equal(len(self.nodes[0].getpeerinfo()), 3) #node is still connected because of the whitelist - print "Peer 1 still connected after trying to download old block (whitelisted)" + print("Peer 1 still connected after trying to download old block (whitelisted)") [c.disconnect_node() for c in connections] diff --git a/qa/rpc-tests/mempool_limit.py b/qa/rpc-tests/mempool_limit.py index c19a63c6996d2..bc208709e9125 100755 --- a/qa/rpc-tests/mempool_limit.py +++ b/qa/rpc-tests/mempool_limit.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -41,7 +41,7 @@ def run_test(self): relayfee = self.nodes[0].getnetworkinfo()['relayfee'] base_fee = relayfee*100 - for i in xrange (4): + for i in range (4): txids.append([]) txids[i] = create_lots_of_big_transactions(self.nodes[0], self.txouts, utxos[30*i:30*i+30], (i+1)*base_fee) diff --git a/qa/rpc-tests/mempool_packages.py b/qa/rpc-tests/mempool_packages.py index bc3f9e051cef1..7ac85c1b6d3e9 100755 --- a/qa/rpc-tests/mempool_packages.py +++ b/qa/rpc-tests/mempool_packages.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -28,7 +28,7 @@ def chain_transaction(self, node, parent_txid, vout, value, fee, num_outputs): send_value = satoshi_round((value - fee)/num_outputs) inputs = [ {'txid' : parent_txid, 'vout' : vout} ] outputs = {} - for i in xrange(num_outputs): + for i in range(num_outputs): outputs[node.getnewaddress()] = send_value rawtx = node.createrawtransaction(inputs, outputs) signedtx = node.signrawtransaction(rawtx) @@ -48,7 +48,7 @@ def run_test(self): fee = Decimal("0.0001") # MAX_ANCESTORS transactions off a confirmed tx should be fine chain = [] - for i in xrange(MAX_ANCESTORS): + for i in range(MAX_ANCESTORS): (txid, sent_value) = self.chain_transaction(self.nodes[0], txid, 0, value, fee, 1) value = sent_value chain.append(txid) @@ -84,7 +84,7 @@ def run_test(self): try: self.chain_transaction(self.nodes[0], txid, vout, value, fee, 1) except JSONRPCException as e: - print "too-long-ancestor-chain successfully rejected" + print("too-long-ancestor-chain successfully rejected") # Check that prioritising a tx before it's added to the mempool works # First clear the mempool by mining a block. @@ -121,22 +121,22 @@ def run_test(self): # First create one parent tx with 10 children (txid, sent_value) = self.chain_transaction(self.nodes[0], txid, vout, value, fee, 10) parent_transaction = txid - for i in xrange(10): + for i in range(10): transaction_package.append({'txid': txid, 'vout': i, 'amount': sent_value}) - for i in xrange(MAX_DESCENDANTS): + for i in range(MAX_DESCENDANTS): utxo = transaction_package.pop(0) try: (txid, sent_value) = self.chain_transaction(self.nodes[0], utxo['txid'], utxo['vout'], utxo['amount'], fee, 10) - for j in xrange(10): + for j in range(10): transaction_package.append({'txid': txid, 'vout': j, 'amount': sent_value}) if i == MAX_DESCENDANTS - 2: mempool = self.nodes[0].getrawmempool(True) assert_equal(mempool[parent_transaction]['descendantcount'], MAX_DESCENDANTS) except JSONRPCException as e: - print e.error['message'] + print(e.error['message']) assert_equal(i, MAX_DESCENDANTS - 1) - print "tx that would create too large descendant package successfully rejected" + print("tx that would create too large descendant package successfully rejected") # TODO: check that node1's mempool is as expected @@ -171,7 +171,7 @@ def run_test(self): send_value = satoshi_round((value - fee)/2) inputs = [ {'txid' : txid, 'vout' : vout} ] outputs = {} - for i in xrange(2): + for i in range(2): outputs[self.nodes[0].getnewaddress()] = send_value rawtx = self.nodes[0].createrawtransaction(inputs, outputs) signedtx = self.nodes[0].signrawtransaction(rawtx) @@ -185,7 +185,7 @@ def run_test(self): # Create tx2-7 vout = 1 txid = tx0_id - for i in xrange(6): + for i in range(6): (txid, sent_value) = self.chain_transaction(self.nodes[0], txid, vout, value, fee, 1) vout = 0 value = sent_value diff --git a/qa/rpc-tests/mempool_reorg.py b/qa/rpc-tests/mempool_reorg.py index 5e9856e5d4318..608e9d0a06c8d 100755 --- a/qa/rpc-tests/mempool_reorg.py +++ b/qa/rpc-tests/mempool_reorg.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/qa/rpc-tests/mempool_resurrect_test.py b/qa/rpc-tests/mempool_resurrect_test.py index 0ba46e6f51e8a..b4d9f0a1a23ff 100755 --- a/qa/rpc-tests/mempool_resurrect_test.py +++ b/qa/rpc-tests/mempool_resurrect_test.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/qa/rpc-tests/mempool_spendcoinbase.py b/qa/rpc-tests/mempool_spendcoinbase.py index 507b5ff416409..c23f5ef10ae12 100755 --- a/qa/rpc-tests/mempool_spendcoinbase.py +++ b/qa/rpc-tests/mempool_spendcoinbase.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/qa/rpc-tests/merkle_blocks.py b/qa/rpc-tests/merkle_blocks.py index eb718f39e41a6..9419d9a714ced 100755 --- a/qa/rpc-tests/merkle_blocks.py +++ b/qa/rpc-tests/merkle_blocks.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -32,7 +32,7 @@ def setup_network(self): self.sync_all() def run_test(self): - print "Mining blocks..." + print("Mining blocks...") self.nodes[0].generate(105) self.sync_all() diff --git a/qa/rpc-tests/multi_rpc.py b/qa/rpc-tests/multi_rpc.py index afb18cf3da20d..577d80949d4ce 100755 --- a/qa/rpc-tests/multi_rpc.py +++ b/qa/rpc-tests/multi_rpc.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2015-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -9,16 +9,9 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * -import base64 -try: - import http.client as httplib -except ImportError: - import httplib -try: - import urllib.parse as urlparse -except ImportError: - import urlparse +import http.client +import urllib.parse class HTTPBasicsTest (BitcoinTestFramework): def setup_nodes(self): @@ -39,7 +32,7 @@ def run_test(self): ################################################## # Check correctness of the rpcauth config option # ################################################## - url = urlparse.urlparse(self.nodes[0].url) + url = urllib.parse.urlparse(self.nodes[0].url) #Old authpair authpair = url.username + ':' + url.password @@ -55,7 +48,7 @@ def run_test(self): headers = {"Authorization": "Basic " + str_to_b64str(authpair)} - conn = httplib.HTTPConnection(url.hostname, url.port) + conn = http.client.HTTPConnection(url.hostname, url.port) conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) resp = conn.getresponse() @@ -65,7 +58,7 @@ def run_test(self): #Use new authpair to confirm both work headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)} - conn = httplib.HTTPConnection(url.hostname, url.port) + conn = http.client.HTTPConnection(url.hostname, url.port) conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) resp = conn.getresponse() @@ -76,7 +69,7 @@ def run_test(self): authpairnew = "rtwrong:"+password headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)} - conn = httplib.HTTPConnection(url.hostname, url.port) + conn = http.client.HTTPConnection(url.hostname, url.port) conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) resp = conn.getresponse() @@ -87,7 +80,7 @@ def run_test(self): authpairnew = "rt:"+password+"wrong" headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)} - conn = httplib.HTTPConnection(url.hostname, url.port) + conn = http.client.HTTPConnection(url.hostname, url.port) conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) resp = conn.getresponse() @@ -98,7 +91,7 @@ def run_test(self): authpairnew = "rt2:"+password2 headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)} - conn = httplib.HTTPConnection(url.hostname, url.port) + conn = http.client.HTTPConnection(url.hostname, url.port) conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) resp = conn.getresponse() @@ -109,7 +102,7 @@ def run_test(self): authpairnew = "rt2:"+password2+"wrong" headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)} - conn = httplib.HTTPConnection(url.hostname, url.port) + conn = http.client.HTTPConnection(url.hostname, url.port) conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) resp = conn.getresponse() diff --git a/qa/rpc-tests/nodehandling.py b/qa/rpc-tests/nodehandling.py index c6c8c436e9701..1b6ba021a0cea 100755 --- a/qa/rpc-tests/nodehandling.py +++ b/qa/rpc-tests/nodehandling.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -10,14 +10,8 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * -try: - import http.client as httplib -except ImportError: - import httplib -try: - import urllib.parse as urlparse -except ImportError: - import urlparse +import http.client +import urllib.parse class NodeHandlingTest (BitcoinTestFramework): def run_test(self): @@ -69,7 +63,7 @@ def run_test(self): ########################### # RPC disconnectnode test # ########################### - url = urlparse.urlparse(self.nodes[1].url) + url = urllib.parse.urlparse(self.nodes[1].url) self.nodes[0].disconnectnode(url.hostname+":"+str(p2p_port(1))) time.sleep(2) #disconnecting a node needs a little bit of time for node in self.nodes[0].getpeerinfo(): diff --git a/qa/rpc-tests/p2p-acceptblock.py b/qa/rpc-tests/p2p-acceptblock.py index e429fcc5fe9d4..21e4c2f468521 100755 --- a/qa/rpc-tests/p2p-acceptblock.py +++ b/qa/rpc-tests/p2p-acceptblock.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python2 -# Copyright (c) 2015 The Bitcoin Core developers -# Distributed under the MIT/X11 software license, see the accompanying +#!/usr/bin/env python3 +# Copyright (c) 2015-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. -# from test_framework.mininode import * from test_framework.test_framework import BitcoinTestFramework @@ -145,13 +144,13 @@ def run_test(self): # 1. Have both nodes mine a block (leave IBD) [ n.generate(1) for n in self.nodes ] - tips = [ int ("0x" + n.getbestblockhash() + "L", 0) for n in self.nodes ] + tips = [ int("0x" + n.getbestblockhash(), 0) for n in self.nodes ] # 2. Send one block that builds on each tip. # This should be accepted. blocks_h2 = [] # the height 2 blocks on each node's chain block_time = int(time.time()) + 1 - for i in xrange(2): + for i in range(2): blocks_h2.append(create_block(tips[i], create_coinbase(2), block_time)) blocks_h2[i].solve() block_time += 1 @@ -161,11 +160,11 @@ def run_test(self): [ x.sync_with_ping() for x in [test_node, white_node] ] assert_equal(self.nodes[0].getblockcount(), 2) assert_equal(self.nodes[1].getblockcount(), 2) - print "First height 2 block accepted by both nodes" + print("First height 2 block accepted by both nodes") # 3. Send another block that builds on the original tip. blocks_h2f = [] # Blocks at height 2 that fork off the main chain - for i in xrange(2): + for i in range(2): blocks_h2f.append(create_block(tips[i], create_coinbase(2), blocks_h2[i].nTime+1)) blocks_h2f[i].solve() test_node.send_message(msg_block(blocks_h2f[0])) @@ -180,11 +179,11 @@ def run_test(self): if x['hash'] == blocks_h2f[1].hash: assert_equal(x['status'], "valid-headers") - print "Second height 2 block accepted only from whitelisted peer" + print("Second height 2 block accepted only from whitelisted peer") # 4. Now send another block that builds on the forking chain. blocks_h3 = [] - for i in xrange(2): + for i in range(2): blocks_h3.append(create_block(blocks_h2f[i].sha256, create_coinbase(3), blocks_h2f[i].nTime+1)) blocks_h3[i].solve() test_node.send_message(msg_block(blocks_h3[0])) @@ -200,13 +199,13 @@ def run_test(self): # But this block should be accepted by node0 since it has more work. try: self.nodes[0].getblock(blocks_h3[0].hash) - print "Unrequested more-work block accepted from non-whitelisted peer" + print("Unrequested more-work block accepted from non-whitelisted peer") except: raise AssertionError("Unrequested more work block was not processed") # Node1 should have accepted and reorged. assert_equal(self.nodes[1].getblockcount(), 3) - print "Successfully reorged to length 3 chain from whitelisted peer" + print("Successfully reorged to length 3 chain from whitelisted peer") # 4b. Now mine 288 more blocks and deliver; all should be processed but # the last (height-too-high) on node0. Node1 should process the tip if @@ -214,8 +213,8 @@ def run_test(self): tips = blocks_h3 headers_message = msg_headers() all_blocks = [] # node0's blocks - for j in xrange(2): - for i in xrange(288): + for j in range(2): + for i in range(288): next_block = create_block(tips[j].sha256, create_coinbase(i + 4), tips[j].nTime+1) next_block.solve() if j==0: @@ -233,7 +232,7 @@ def run_test(self): raise AssertionError("Unrequested block too far-ahead should have been ignored") except: if x == all_blocks[287]: - print "Unrequested block too far-ahead not processed" + print("Unrequested block too far-ahead not processed") else: raise AssertionError("Unrequested block with more work should have been accepted") @@ -243,7 +242,7 @@ def run_test(self): try: white_node.sync_with_ping() self.nodes[1].getblock(tips[1].hash) - print "Unrequested block far ahead of tip accepted from whitelisted peer" + print("Unrequested block far ahead of tip accepted from whitelisted peer") except: raise AssertionError("Unrequested block from whitelisted peer not accepted") @@ -259,7 +258,7 @@ def run_test(self): # a getdata request for this block. test_node.sync_with_ping() assert_equal(self.nodes[0].getblockcount(), 2) - print "Unrequested block that would complete more-work chain was ignored" + print("Unrequested block that would complete more-work chain was ignored") # 6. Try to get node to request the missing block. # Poke the node with an inv for block at height 3 and see if that @@ -275,14 +274,14 @@ def run_test(self): # Check that the getdata includes the right block assert_equal(getdata.inv[0].hash, blocks_h2f[0].sha256) - print "Inv at tip triggered getdata for unprocessed block" + print("Inv at tip triggered getdata for unprocessed block") # 7. Send the missing block for the third time (now it is requested) test_node.send_message(msg_block(blocks_h2f[0])) test_node.sync_with_ping() assert_equal(self.nodes[0].getblockcount(), 290) - print "Successfully reorged to longer chain from non-whitelisted peer" + print("Successfully reorged to longer chain from non-whitelisted peer") [ c.disconnect_node() for c in connections ] diff --git a/qa/rpc-tests/p2p-feefilter.py b/qa/rpc-tests/p2p-feefilter.py index 281b6ca37a0ce..5fb51ed0fe792 100755 --- a/qa/rpc-tests/p2p-feefilter.py +++ b/qa/rpc-tests/p2p-feefilter.py @@ -1,6 +1,6 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # Copyright (c) 2016 The Bitcoin Core developers -# Distributed under the MIT/X11 software license, see the accompanying +# Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. # @@ -18,7 +18,7 @@ def hashToHex(hash): # Wait up to 60 secs to see if the testnode has received all the expected invs def allInvsMatch(invsExpected, testnode): - for x in xrange(60): + for x in range(60): with mininode_lock: if (sorted(invsExpected) == sorted(testnode.txinvs)): return True; @@ -69,7 +69,7 @@ def run_test(self): # Test that invs are received for all txs at feerate of 20 sat/byte node1.settxfee(Decimal("0.00020000")) - txids = [node1.sendtoaddress(node1.getnewaddress(), 1) for x in xrange(3)] + txids = [node1.sendtoaddress(node1.getnewaddress(), 1) for x in range(3)] assert(allInvsMatch(txids, test_node)) test_node.clear_invs() @@ -77,13 +77,13 @@ def run_test(self): test_node.send_filter(15000) # Test that txs are still being received (paying 20 sat/byte) - txids = [node1.sendtoaddress(node1.getnewaddress(), 1) for x in xrange(3)] + txids = [node1.sendtoaddress(node1.getnewaddress(), 1) for x in range(3)] assert(allInvsMatch(txids, test_node)) test_node.clear_invs() # Change tx fee rate to 10 sat/byte and test they are no longer received node1.settxfee(Decimal("0.00010000")) - [node1.sendtoaddress(node1.getnewaddress(), 1) for x in xrange(3)] + [node1.sendtoaddress(node1.getnewaddress(), 1) for x in range(3)] sync_mempools(self.nodes) # must be sure node 0 has received all txs time.sleep(10) # wait 10 secs to be sure its doesn't relay any assert(allInvsMatch([], test_node)) @@ -91,7 +91,7 @@ def run_test(self): # Remove fee filter and check that txs are received again test_node.send_filter(0) - txids = [node1.sendtoaddress(node1.getnewaddress(), 1) for x in xrange(3)] + txids = [node1.sendtoaddress(node1.getnewaddress(), 1) for x in range(3)] assert(allInvsMatch(txids, test_node)) test_node.clear_invs() diff --git a/qa/rpc-tests/p2p-fullblocktest.py b/qa/rpc-tests/p2p-fullblocktest.py index ae82d9dca9266..56df8ffd01181 100755 --- a/qa/rpc-tests/p2p-fullblocktest.py +++ b/qa/rpc-tests/p2p-fullblocktest.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python2 -# Copyright (c) 2015 The Bitcoin Core developers -# Distributed under the MIT/X11 software license, see the accompanying +#!/usr/bin/env python3 +# Copyright (c) 2015-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. -# from test_framework.test_framework import ComparisonTestFramework from test_framework.util import * diff --git a/qa/rpc-tests/p2p-versionbits-warning.py b/qa/rpc-tests/p2p-versionbits-warning.py index 061dcbf0e1e87..8c8c2358f74e6 100755 --- a/qa/rpc-tests/p2p-versionbits-warning.py +++ b/qa/rpc-tests/p2p-versionbits-warning.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # Copyright (c) 2016 The Bitcoin Core developers -# Distributed under the MIT/X11 software license, see the accompanying +# Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. -# from test_framework.mininode import * from test_framework.test_framework import BitcoinTestFramework @@ -82,7 +81,7 @@ def send_blocks_with_version(self, peer, numblocks, nVersionToUse): block_time = self.nodes[0].getblockheader(tip)["time"]+1 tip = int(tip, 16) - for i in xrange(numblocks): + for i in range(numblocks): block = create_block(tip, create_coinbase(height+1), block_time) block.nVersion = nVersionToUse block.solve() diff --git a/qa/rpc-tests/prioritise_transaction.py b/qa/rpc-tests/prioritise_transaction.py index f8d9063b4ebc0..6ab88602b57ac 100755 --- a/qa/rpc-tests/prioritise_transaction.py +++ b/qa/rpc-tests/prioritise_transaction.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2015-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -35,7 +35,7 @@ def run_test(self): # Create 3 batches of transactions at 3 different fee rate levels range_size = utxo_count // 3 - for i in xrange(3): + for i in range(3): txids.append([]) start_range = i * range_size end_range = start_range + range_size @@ -46,7 +46,7 @@ def run_test(self): # more transactions. mempool = self.nodes[0].getrawmempool(True) sizes = [0, 0, 0] - for i in xrange(3): + for i in range(3): for j in txids[i]: assert(j in mempool) sizes[i] += mempool[j]['size'] @@ -61,7 +61,7 @@ def run_test(self): self.nodes[0].generate(1) mempool = self.nodes[0].getrawmempool() - print "Assert that prioritised transaction was mined" + print("Assert that prioritised transaction was mined") assert(txids[0][0] not in mempool) assert(txids[0][1] in mempool) @@ -93,7 +93,7 @@ def run_test(self): # High fee transaction should not have been mined, but other high fee rate # transactions should have been. mempool = self.nodes[0].getrawmempool() - print "Assert that de-prioritised transaction is still in mempool" + print("Assert that de-prioritised transaction is still in mempool") assert(high_fee_tx in mempool) for x in txids[2]: if (x != high_fee_tx): @@ -135,7 +135,7 @@ def run_test(self): # accepted. self.nodes[0].prioritisetransaction(tx2_id, 0, int(self.relayfee*COIN)) - print "Assert that prioritised free transaction is accepted to mempool" + print("Assert that prioritised free transaction is accepted to mempool") assert_equal(self.nodes[0].sendrawtransaction(tx2_hex), tx2_id) assert(tx2_id in self.nodes[0].getrawmempool()) diff --git a/qa/rpc-tests/proxy_test.py b/qa/rpc-tests/proxy_test.py index 91c871ddc9003..6c7b201d562d0 100755 --- a/qa/rpc-tests/proxy_test.py +++ b/qa/rpc-tests/proxy_test.py @@ -1,7 +1,8 @@ -#!/usr/bin/env python2 -# Copyright (c) 2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2015-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. + import socket from test_framework.socks5 import Socks5Configuration, Socks5Command, Socks5Server, AddressType @@ -55,7 +56,7 @@ def __init__(self): self.conf3.unauth = True self.conf3.auth = True else: - print "Warning: testing without local IPv6 support" + print("Warning: testing without local IPv6 support") self.serv1 = Socks5Server(self.conf1) self.serv1.start() diff --git a/qa/rpc-tests/pruning.py b/qa/rpc-tests/pruning.py index eccd157e5c085..92d33bd20ec3e 100755 --- a/qa/rpc-tests/pruning.py +++ b/qa/rpc-tests/pruning.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -57,7 +57,7 @@ def create_big_chain(self): sync_blocks(self.nodes[0:2]) self.nodes[0].generate(150) # Then mine enough full blocks to create more than 550MiB of data - for i in xrange(645): + for i in range(645): self.mine_full_block(self.nodes[0], self.address[0]) sync_blocks(self.nodes[0:3]) @@ -65,11 +65,11 @@ def create_big_chain(self): def test_height_min(self): if not os.path.isfile(self.prunedir+"blk00000.dat"): raise AssertionError("blk00000.dat is missing, pruning too early") - print "Success" - print "Though we're already using more than 550MiB, current usage:", calc_usage(self.prunedir) - print "Mining 25 more blocks should cause the first block file to be pruned" + print("Success") + print("Though we're already using more than 550MiB, current usage:", calc_usage(self.prunedir)) + print("Mining 25 more blocks should cause the first block file to be pruned") # Pruning doesn't run until we're allocating another chunk, 20 full blocks past the height cutoff will ensure this - for i in xrange(25): + for i in range(25): self.mine_full_block(self.nodes[0],self.address[0]) waitstart = time.time() @@ -78,17 +78,17 @@ def test_height_min(self): if time.time() - waitstart > 10: raise AssertionError("blk00000.dat not pruned when it should be") - print "Success" + print("Success") usage = calc_usage(self.prunedir) - print "Usage should be below target:", usage + print("Usage should be below target:", usage) if (usage > 550): raise AssertionError("Pruning target not being met") def create_chain_with_staleblocks(self): # Create stale blocks in manageable sized chunks - print "Mine 24 (stale) blocks on Node 1, followed by 25 (main chain) block reorg from Node 0, for 12 rounds" + print("Mine 24 (stale) blocks on Node 1, followed by 25 (main chain) block reorg from Node 0, for 12 rounds") - for j in xrange(12): + for j in range(12): # Disconnect node 0 so it can mine a longer reorg chain without knowing about node 1's soon-to-be-stale chain # Node 2 stays connected, so it hears about the stale blocks and then reorg's when node0 reconnects # Stopping node 0 also clears its mempool, so it doesn't have node1's transactions to accidentally mine @@ -96,7 +96,7 @@ def create_chain_with_staleblocks(self): self.nodes[0]=start_node(0, self.options.tmpdir, ["-debug","-maxreceivebuffer=20000","-blockmaxsize=999000", "-checkblocks=5"], timewait=900) # Mine 24 blocks in node 1 self.utxo = self.nodes[1].listunspent() - for i in xrange(24): + for i in range(24): if j == 0: self.mine_full_block(self.nodes[1],self.address[1]) else: @@ -104,7 +104,7 @@ def create_chain_with_staleblocks(self): # Reorg back with 25 block chain from node 0 self.utxo = self.nodes[0].listunspent() - for i in xrange(25): + for i in range(25): self.mine_full_block(self.nodes[0],self.address[0]) # Create connections in the order so both nodes can see the reorg at the same time @@ -112,7 +112,7 @@ def create_chain_with_staleblocks(self): connect_nodes(self.nodes[2], 0) sync_blocks(self.nodes[0:3]) - print "Usage can be over target because of high stale rate:", calc_usage(self.prunedir) + print("Usage can be over target because of high stale rate:", calc_usage(self.prunedir)) def reorg_test(self): # Node 1 will mine a 300 block chain starting 287 blocks back from Node 0 and Node 2's tip @@ -123,11 +123,11 @@ def reorg_test(self): self.nodes[1]=start_node(1, self.options.tmpdir, ["-debug","-maxreceivebuffer=20000","-blockmaxsize=5000", "-checkblocks=5", "-disablesafemode"], timewait=900) height = self.nodes[1].getblockcount() - print "Current block height:", height + print("Current block height:", height) invalidheight = height-287 badhash = self.nodes[1].getblockhash(invalidheight) - print "Invalidating block at height:",invalidheight,badhash + print("Invalidating block at height:",invalidheight,badhash) self.nodes[1].invalidateblock(badhash) # We've now switched to our previously mined-24 block fork on node 1, but thats not what we want @@ -139,29 +139,29 @@ def reorg_test(self): curhash = self.nodes[1].getblockhash(invalidheight - 1) assert(self.nodes[1].getblockcount() == invalidheight - 1) - print "New best height", self.nodes[1].getblockcount() + print("New best height", self.nodes[1].getblockcount()) # Reboot node1 to clear those giant tx's from mempool stop_node(self.nodes[1],1) self.nodes[1]=start_node(1, self.options.tmpdir, ["-debug","-maxreceivebuffer=20000","-blockmaxsize=5000", "-checkblocks=5", "-disablesafemode"], timewait=900) - print "Generating new longer chain of 300 more blocks" + print("Generating new longer chain of 300 more blocks") self.nodes[1].generate(300) - print "Reconnect nodes" + print("Reconnect nodes") connect_nodes(self.nodes[0], 1) connect_nodes(self.nodes[2], 1) sync_blocks(self.nodes[0:3]) - print "Verify height on node 2:",self.nodes[2].getblockcount() - print "Usage possibly still high bc of stale blocks in block files:", calc_usage(self.prunedir) + print("Verify height on node 2:",self.nodes[2].getblockcount()) + print("Usage possibly still high bc of stale blocks in block files:", calc_usage(self.prunedir)) - print "Mine 220 more blocks so we have requisite history (some blocks will be big and cause pruning of previous chain)" + print("Mine 220 more blocks so we have requisite history (some blocks will be big and cause pruning of previous chain)") self.nodes[0].generate(220) #node 0 has many large tx's in its mempool from the disconnects sync_blocks(self.nodes[0:3]) usage = calc_usage(self.prunedir) - print "Usage should be below target:", usage + print("Usage should be below target:", usage) if (usage > 550): raise AssertionError("Pruning target not being met") @@ -173,7 +173,7 @@ def reorg_back(self): self.nodes[2].getblock(self.forkhash) raise AssertionError("Old block wasn't pruned so can't test redownload") except JSONRPCException as e: - print "Will need to redownload block",self.forkheight + print("Will need to redownload block",self.forkheight) # Verify that we have enough history to reorg back to the fork point # Although this is more than 288 blocks, because this chain was written more recently @@ -197,14 +197,14 @@ def reorg_back(self): # At this point node 2 is within 288 blocks of the fork point so it will preserve its ability to reorg if self.nodes[2].getblockcount() < self.mainchainheight: blocks_to_mine = first_reorg_height + 1 - self.mainchainheight - print "Rewind node 0 to prev main chain to mine longer chain to trigger redownload. Blocks needed:", blocks_to_mine + print("Rewind node 0 to prev main chain to mine longer chain to trigger redownload. Blocks needed:", blocks_to_mine) self.nodes[0].invalidateblock(curchainhash) assert(self.nodes[0].getblockcount() == self.mainchainheight) assert(self.nodes[0].getbestblockhash() == self.mainchainhash2) goalbesthash = self.nodes[0].generate(blocks_to_mine)[-1] goalbestheight = first_reorg_height + 1 - print "Verify node 2 reorged back to the main chain, some blocks of which it had to redownload" + print("Verify node 2 reorged back to the main chain, some blocks of which it had to redownload") waitstart = time.time() while self.nodes[2].getblockcount() < goalbestheight: time.sleep(0.1) @@ -217,7 +217,7 @@ def reorg_back(self): def mine_full_block(self, node, address): # Want to create a full block # We'll generate a 66k transaction below, and 14 of them is close to the 1MB block limit - for j in xrange(14): + for j in range(14): if len(self.utxo) < 14: self.utxo = node.listunspent() inputs=[] @@ -241,8 +241,8 @@ def mine_full_block(self, node, address): def run_test(self): - print "Warning! This test requires 4GB of disk space and takes over 30 mins (up to 2 hours)" - print "Mining a big blockchain of 995 blocks" + print("Warning! This test requires 4GB of disk space and takes over 30 mins (up to 2 hours)") + print("Mining a big blockchain of 995 blocks") self.create_big_chain() # Chain diagram key: # * blocks on main chain @@ -253,12 +253,12 @@ def run_test(self): # Start by mining a simple chain that all nodes have # N0=N1=N2 **...*(995) - print "Check that we haven't started pruning yet because we're below PruneAfterHeight" + print("Check that we haven't started pruning yet because we're below PruneAfterHeight") self.test_height_min() # Extend this chain past the PruneAfterHeight # N0=N1=N2 **...*(1020) - print "Check that we'll exceed disk space target if we have a very high stale block rate" + print("Check that we'll exceed disk space target if we have a very high stale block rate") self.create_chain_with_staleblocks() # Disconnect N0 # And mine a 24 block chain on N1 and a separate 25 block chain on N0 @@ -282,7 +282,7 @@ def run_test(self): self.mainchainheight = self.nodes[2].getblockcount() #1320 self.mainchainhash2 = self.nodes[2].getblockhash(self.mainchainheight) - print "Check that we can survive a 288 block reorg still" + print("Check that we can survive a 288 block reorg still") (self.forkheight,self.forkhash) = self.reorg_test() #(1033, ) # Now create a 288 block reorg by mining a longer chain on N1 # First disconnect N1 @@ -315,7 +315,7 @@ def run_test(self): # \ # *...**(1320) - print "Test that we can rerequest a block we previously pruned if needed for a reorg" + print("Test that we can rerequest a block we previously pruned if needed for a reorg") self.reorg_back() # Verify that N2 still has block 1033 on current chain (@), but not on main chain (*) # Invalidate 1033 on current chain (@) on N2 and we should be able to reorg to @@ -335,7 +335,7 @@ def run_test(self): # # N1 doesn't change because 1033 on main chain (*) is invalid - print "Done" + print("Done") if __name__ == '__main__': PruneTest().main() diff --git a/qa/rpc-tests/rawtransactions.py b/qa/rpc-tests/rawtransactions.py index e38ef6c8b1071..7f7b6887a834f 100755 --- a/qa/rpc-tests/rawtransactions.py +++ b/qa/rpc-tests/rawtransactions.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/qa/rpc-tests/receivedby.py b/qa/rpc-tests/receivedby.py index 7d8231f5e47cf..a3f97669ea27a 100755 --- a/qa/rpc-tests/receivedby.py +++ b/qa/rpc-tests/receivedby.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/qa/rpc-tests/reindex.py b/qa/rpc-tests/reindex.py index 321c2fe422a5f..39564b32bad90 100755 --- a/qa/rpc-tests/reindex.py +++ b/qa/rpc-tests/reindex.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -26,7 +26,7 @@ def run_test(self): wait_bitcoinds() self.nodes[0]=start_node(0, self.options.tmpdir, ["-debug", "-reindex", "-checkblockindex=1"]) assert_equal(self.nodes[0].getblockcount(), 3) - print "Success" + print("Success") if __name__ == '__main__': ReindexTest().main() diff --git a/qa/rpc-tests/replace-by-fee.py b/qa/rpc-tests/replace-by-fee.py index 4c8ef6de26eb2..4afc3981da112 100755 --- a/qa/rpc-tests/replace-by-fee.py +++ b/qa/rpc-tests/replace-by-fee.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -82,34 +82,34 @@ def setup_network(self): def run_test(self): make_utxo(self.nodes[0], 1*COIN) - print "Running test simple doublespend..." + print("Running test simple doublespend...") self.test_simple_doublespend() - print "Running test doublespend chain..." + print("Running test doublespend chain...") self.test_doublespend_chain() - print "Running test doublespend tree..." + print("Running test doublespend tree...") self.test_doublespend_tree() - print "Running test replacement feeperkb..." + print("Running test replacement feeperkb...") self.test_replacement_feeperkb() - print "Running test spends of conflicting outputs..." + print("Running test spends of conflicting outputs...") self.test_spends_of_conflicting_outputs() - print "Running test new unconfirmed inputs..." + print("Running test new unconfirmed inputs...") self.test_new_unconfirmed_inputs() - print "Running test too many replacements..." + print("Running test too many replacements...") self.test_too_many_replacements() - print "Running test opt-in..." + print("Running test opt-in...") self.test_opt_in() - print "Running test prioritised transactions..." + print("Running test prioritised transactions...") self.test_prioritised_transactions() - print "Passed\n" + print("Passed\n") def test_simple_doublespend(self): """Simple doublespend""" @@ -459,7 +459,7 @@ def test_opt_in(self): except JSONRPCException as exp: assert_equal(exp.error['code'], -26) else: - print tx1b_txid + print(tx1b_txid) assert(False) tx1_outpoint = make_utxo(self.nodes[0], int(1.1*COIN)) diff --git a/qa/rpc-tests/rest.py b/qa/rpc-tests/rest.py index 359f9239fb370..ec9515528ecb7 100755 --- a/qa/rpc-tests/rest.py +++ b/qa/rpc-tests/rest.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -13,16 +13,9 @@ from struct import * from io import BytesIO from codecs import encode -import binascii -try: - import http.client as httplib -except ImportError: - import httplib -try: - import urllib.parse as urlparse -except ImportError: - import urlparse +import http.client +import urllib.parse def deser_uint256(f): r = 0 @@ -33,7 +26,7 @@ def deser_uint256(f): #allows simple http get calls def http_get_call(host, port, path, response_object = 0): - conn = httplib.HTTPConnection(host, port) + conn = http.client.HTTPConnection(host, port) conn.request('GET', path) if response_object: @@ -43,7 +36,7 @@ def http_get_call(host, port, path, response_object = 0): #allows simple http post calls with a request body def http_post_call(host, port, path, requestdata = '', response_object = 0): - conn = httplib.HTTPConnection(host, port) + conn = http.client.HTTPConnection(host, port) conn.request('POST', path, requestdata) if response_object: @@ -67,8 +60,8 @@ def setup_network(self, split=False): self.sync_all() def run_test(self): - url = urlparse.urlparse(self.nodes[0].url) - print "Mining blocks..." + url = urllib.parse.urlparse(self.nodes[0].url) + print("Mining blocks...") self.nodes[0].generate(1) self.sync_all() @@ -151,7 +144,7 @@ def run_test(self): output.write(bin_response) output.seek(0) chainHeight = unpack("i", output.read(4))[0] - hashFromBinResponse = hex(deser_uint256(output))[2:].zfill(65).rstrip("L") + hashFromBinResponse = hex(deser_uint256(output))[2:].zfill(64) assert_equal(bb_hash, hashFromBinResponse) #check if getutxo's chaintip during calculation was fine assert_equal(chainHeight, 102) #chain height must be 102 diff --git a/qa/rpc-tests/rpcbind_test.py b/qa/rpc-tests/rpcbind_test.py index 10a48b5556e40..7b7c01f993cf4 100755 --- a/qa/rpc-tests/rpcbind_test.py +++ b/qa/rpc-tests/rpcbind_test.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -51,7 +51,7 @@ def run_allowip_test(tmpdir, allow_ips, rpchost, rpcport): def run_test(tmpdir): - assert(sys.platform == 'linux2') # due to OS-specific network stats queries, this test works only on Linux + assert(sys.platform.startswith('linux')) # due to OS-specific network stats queries, this test works only on Linux # find the first non-loopback interface for testing non_loopback_ip = None for name,ip in all_interfaces(): diff --git a/qa/rpc-tests/sendheaders.py b/qa/rpc-tests/sendheaders.py index 2bc32584b5f8e..96d1da729b909 100755 --- a/qa/rpc-tests/sendheaders.py +++ b/qa/rpc-tests/sendheaders.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers -# Distributed under the MIT/X11 software license, see the accompanying +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. -# from test_framework.mininode import * from test_framework.test_framework import BitcoinTestFramework @@ -266,8 +265,8 @@ def run_test(self): # PART 1 # 1. Mine a block; expect inv announcements each time - print "Part 1: headers don't start before sendheaders message..." - for i in xrange(4): + print("Part 1: headers don't start before sendheaders message...") + for i in range(4): old_tip = tip tip = self.mine_blocks(1) assert_equal(inv_node.check_last_announcement(inv=[tip]), True) @@ -297,14 +296,14 @@ def run_test(self): inv_node.clear_last_announcement() test_node.clear_last_announcement() - print "Part 1: success!" - print "Part 2: announce blocks with headers after sendheaders message..." + print("Part 1: success!") + print("Part 2: announce blocks with headers after sendheaders message...") # PART 2 # 2. Send a sendheaders message and test that headers announcements # commence and keep working. test_node.send_message(msg_sendheaders()) prev_tip = int(self.nodes[0].getbestblockhash(), 16) - test_node.get_headers(locator=[prev_tip], hashstop=0L) + test_node.get_headers(locator=[prev_tip], hashstop=0) test_node.sync_with_ping() # Now that we've synced headers, headers announcements should work @@ -314,14 +313,14 @@ def run_test(self): height = self.nodes[0].getblockcount()+1 block_time += 10 # Advance far enough ahead - for i in xrange(10): + for i in range(10): # Mine i blocks, and alternate announcing either via # inv (of tip) or via headers. After each, new blocks # mined by the node should successfully be announced # with block header, even though the blocks are never requested - for j in xrange(2): + for j in range(2): blocks = [] - for b in xrange(i+1): + for b in range(i+1): blocks.append(create_block(tip, create_coinbase(height), block_time)) blocks[-1].solve() tip = blocks[-1].sha256 @@ -360,13 +359,13 @@ def run_test(self): height += 1 block_time += 1 - print "Part 2: success!" + print("Part 2: success!") - print "Part 3: headers announcements can stop after large reorg, and resume after headers/inv from peer..." + print("Part 3: headers announcements can stop after large reorg, and resume after headers/inv from peer...") # PART 3. Headers announcements can stop after large reorg, and resume after # getheaders or inv from peer. - for j in xrange(2): + for j in range(2): # First try mining a reorg that can propagate with header announcement new_block_hashes = self.mine_reorg(length=7) tip = new_block_hashes[-1] @@ -392,7 +391,7 @@ def run_test(self): test_node.get_data(new_block_hashes) test_node.wait_for_block(new_block_hashes[-1]) - for i in xrange(3): + for i in range(3): # Mine another block, still should get only an inv tip = self.mine_blocks(1) assert_equal(inv_node.check_last_announcement(inv=[tip]), True) @@ -414,7 +413,7 @@ def run_test(self): # of headers announcements, or mine a new block and inv it, also # triggering resumption of headers announcements. if j == 0: - test_node.get_headers(locator=[tip], hashstop=0L) + test_node.get_headers(locator=[tip], hashstop=0) test_node.sync_with_ping() else: test_node.send_block_inv(tip) @@ -424,9 +423,9 @@ def run_test(self): assert_equal(inv_node.check_last_announcement(inv=[tip]), True) assert_equal(test_node.check_last_announcement(headers=[tip]), True) - print "Part 3: success!" + print("Part 3: success!") - print "Part 4: Testing direct fetch behavior..." + print("Part 4: Testing direct fetch behavior...") tip = self.mine_blocks(1) height = self.nodes[0].getblockcount() + 1 last_time = self.nodes[0].getblock(self.nodes[0].getbestblockhash())['time'] @@ -434,7 +433,7 @@ def run_test(self): # Create 2 blocks. Send the blocks, then send the headers. blocks = [] - for b in xrange(2): + for b in range(2): blocks.append(create_block(tip, create_coinbase(height), block_time)) blocks[-1].solve() tip = blocks[-1].sha256 @@ -452,7 +451,7 @@ def run_test(self): # This time, direct fetch should work blocks = [] - for b in xrange(3): + for b in range(3): blocks.append(create_block(tip, create_coinbase(height), block_time)) blocks[-1].solve() tip = blocks[-1].sha256 @@ -473,7 +472,7 @@ def run_test(self): blocks = [] # Create extra blocks for later - for b in xrange(20): + for b in range(20): blocks.append(create_block(tip, create_coinbase(height), block_time)) blocks[-1].solve() tip = blocks[-1].sha256 @@ -507,7 +506,7 @@ def run_test(self): with mininode_lock: assert_equal(test_node.last_getdata, None) - print "Part 4: success!" + print("Part 4: success!") # Finally, check that the inv node never received a getdata request, # throughout the test diff --git a/qa/rpc-tests/signmessages.py b/qa/rpc-tests/signmessages.py index ff22f35300a4b..4a47c0ca1e198 100755 --- a/qa/rpc-tests/signmessages.py +++ b/qa/rpc-tests/signmessages.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # Copyright (c) 2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/qa/rpc-tests/signrawtransactions.py b/qa/rpc-tests/signrawtransactions.py index d51d6ee6106e0..a06ac53191846 100755 --- a/qa/rpc-tests/signrawtransactions.py +++ b/qa/rpc-tests/signrawtransactions.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2015-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/qa/rpc-tests/smartfees.py b/qa/rpc-tests/smartfees.py index 7239e5a0da825..8fcb99c1b7f4e 100755 --- a/qa/rpc-tests/smartfees.py +++ b/qa/rpc-tests/smartfees.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -238,7 +238,7 @@ def run_test(self): self.confutxo = self.txouts # Start with the set of confirmed txouts after splitting print("Will output estimates for 1/2/3/6/15/25 blocks") - for i in xrange(2): + for i in range(2): print("Creating transactions and mining them with a block size that can't keep up") # Create transactions and mine 10 small blocks with node 2, but create txs faster than we can mine self.transact_and_mine(10, self.nodes[2]) diff --git a/qa/rpc-tests/test_framework/bignum.py b/qa/rpc-tests/test_framework/bignum.py index b0c58ccd47447..ef800e4d57369 100644 --- a/qa/rpc-tests/test_framework/bignum.py +++ b/qa/rpc-tests/test_framework/bignum.py @@ -1,16 +1,15 @@ -# +#!/usr/bin/env python3 # # bignum.py # # This file is copied from python-bitcoinlib. # -# Distributed under the MIT/X11 software license, see the accompanying +# Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. # """Bignum routines""" -from __future__ import absolute_import, division, print_function, unicode_literals import struct diff --git a/qa/rpc-tests/test_framework/blockstore.py b/qa/rpc-tests/test_framework/blockstore.py index 73d9ffbb2fe05..4bc279032bf08 100644 --- a/qa/rpc-tests/test_framework/blockstore.py +++ b/qa/rpc-tests/test_framework/blockstore.py @@ -1,16 +1,17 @@ +#!/usr/bin/env python3 # BlockStore: a helper class that keeps a map of blocks and implements # helper functions for responding to getheaders and getdata, # and for constructing a getheaders message # from .mininode import * -import dbm from io import BytesIO +import dbm.ndbm class BlockStore(object): def __init__(self, datadir): - self.blockDB = dbm.open(datadir + "/blocks", 'c') - self.currentBlock = 0L + self.blockDB = dbm.ndbm.open(datadir + "/blocks", 'c') + self.currentBlock = 0 self.headers_map = dict() def close(self): @@ -67,7 +68,7 @@ def add_block(self, block): try: self.blockDB[repr(block.sha256)] = bytes(block.serialize()) except TypeError as e: - print "Unexpected error: ", sys.exc_info()[0], e.args + print("Unexpected error: ", sys.exc_info()[0], e.args) self.currentBlock = block.sha256 self.headers_map[block.sha256] = CBlockHeader(block) @@ -105,7 +106,7 @@ def get_locator(self, current_tip=None): class TxStore(object): def __init__(self, datadir): - self.txDB = dbm.open(datadir + "/transactions", 'c') + self.txDB = dbm.ndbm.open(datadir + "/transactions", 'c') def close(self): self.txDB.close() @@ -127,7 +128,7 @@ def add_transaction(self, tx): try: self.txDB[repr(tx.sha256)] = bytes(tx.serialize()) except TypeError as e: - print "Unexpected error: ", sys.exc_info()[0], e.args + print("Unexpected error: ", sys.exc_info()[0], e.args) def get_transactions(self, inv): responses = [] diff --git a/qa/rpc-tests/test_framework/blocktools.py b/qa/rpc-tests/test_framework/blocktools.py index 384f40e62dfca..44232153ac702 100644 --- a/qa/rpc-tests/test_framework/blocktools.py +++ b/qa/rpc-tests/test_framework/blocktools.py @@ -1,8 +1,8 @@ +#!/usr/bin/env python3 # blocktools.py - utilities for manipulating blocks and transactions -# Copyright (c) 2015 The Bitcoin Core developers -# Distributed under the MIT/X11 software license, see the accompanying +# Copyright (c) 2015-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. -# from .mininode import * from .script import CScript, OP_TRUE, OP_CHECKSIG diff --git a/qa/rpc-tests/test_framework/comptool.py b/qa/rpc-tests/test_framework/comptool.py index 17626cf8dada4..7c92d3f828917 100755 --- a/qa/rpc-tests/test_framework/comptool.py +++ b/qa/rpc-tests/test_framework/comptool.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python2 -# Copyright (c) 2015 The Bitcoin Core developers -# Distributed under the MIT/X11 software license, see the accompanying +#!/usr/bin/env python3 +# Copyright (c) 2015-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. -# from .mininode import * from .blockstore import BlockStore, TxStore @@ -259,10 +258,10 @@ def check_results(self, blockhash, outcome): if c.cb.bestblockhash == blockhash: return False if blockhash not in c.cb.block_reject_map: - print 'Block not in reject map: %064x' % (blockhash) + print('Block not in reject map: %064x' % (blockhash)) return False if not outcome.match(c.cb.block_reject_map[blockhash]): - print 'Block rejected with %s instead of expected %s: %064x' % (c.cb.block_reject_map[blockhash], outcome, blockhash) + print('Block rejected with %s instead of expected %s: %064x' % (c.cb.block_reject_map[blockhash], outcome, blockhash)) return False elif ((c.cb.bestblockhash == blockhash) != outcome): # print c.cb.bestblockhash, blockhash, outcome @@ -287,10 +286,10 @@ def check_mempool(self, txhash, outcome): if txhash in c.cb.lastInv: return False if txhash not in c.cb.tx_reject_map: - print 'Tx not in reject map: %064x' % (txhash) + print('Tx not in reject map: %064x' % (txhash)) return False if not outcome.match(c.cb.tx_reject_map[txhash]): - print 'Tx rejected with %s instead of expected %s: %064x' % (c.cb.tx_reject_map[txhash], outcome, txhash) + print('Tx rejected with %s instead of expected %s: %064x' % (c.cb.tx_reject_map[txhash], outcome, txhash)) return False elif ((txhash in c.cb.lastInv) != outcome): # print c.rpc.getrawmempool(), c.cb.lastInv @@ -393,7 +392,7 @@ def run(self): if (not self.check_mempool(tx.sha256, tx_outcome)): raise AssertionError("Mempool test failed at test %d" % test_number) - print "Test %d: PASS" % test_number, [ c.rpc.getblockcount() for c in self.connections ] + print("Test %d: PASS" % test_number, [ c.rpc.getblockcount() for c in self.connections ]) test_number += 1 [ c.disconnect_node() for c in self.connections ] diff --git a/qa/rpc-tests/test_framework/coverage.py b/qa/rpc-tests/test_framework/coverage.py index d21a001b6efe0..23fce61014040 100644 --- a/qa/rpc-tests/test_framework/coverage.py +++ b/qa/rpc-tests/test_framework/coverage.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python2 -# Copyright (c) 2015 The Bitcoin Core developers -# Distributed under the MIT/X11 software license, see the accompanying +#!/usr/bin/env python3 +# Copyright (c) 2015-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. -# """ This module contains utilities for doing coverage analysis on the RPC diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index 30aecfd445b0e..1617daa20008d 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -1,7 +1,12 @@ -# mininode.py - Bitcoin P2P network half-a-node -# -# Distributed under the MIT/X11 software license, see the accompanying +#!/usr/bin/env python3 +# Copyright (c) 2010 ArtForz -- public domain half-a-node +# Copyright (c) 2012 Jeff Garzik +# Copyright (c) 2010-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# +# mininode.py - Bitcoin P2P network half-a-node # # This python code was modified from ArtForz' public domain half-a-node, as # found in the mini-node branch of http://github.com/jgarzik/pynode. @@ -34,12 +39,12 @@ BIP0031_VERSION = 60000 MY_VERSION = 60001 # past bip-31 for ping/pong -MY_SUBVERSION = b"/python-mininode-tester:0.0.2/" +MY_SUBVERSION = b"/python-mininode-tester:0.0.3/" MAX_INV_SZ = 50000 MAX_BLOCK_SIZE = 1000000 -COIN = 100000000L # 1 btc in satoshis +COIN = 100000000 # 1 btc in satoshis # Keep our own socket map for asyncore, so that we can track disconnects # ourselves (to workaround an issue with closing an asyncore socket when @@ -73,20 +78,18 @@ def deser_string(f): nit = struct.unpack(">= 32 return rs def uint256_from_str(s): - r = 0L + r = 0 t = struct.unpack("> 24) & 0xFF - v = (c & 0xFFFFFFL) << (8 * (nbytes - 3)) + v = (c & 0xFFFFFF) << (8 * (nbytes - 3)) return v @@ -123,7 +126,7 @@ def deser_vector(f, c): elif nit == 255: nit = struct.unpack(" 1: newhashes = [] - for i in xrange(0, len(hashes), 2): + for i in range(0, len(hashes), 2): i2 = min(i+1, len(hashes)-1) newhashes.append(hash256(hashes[i] + hashes[i2])) hashes = newhashes @@ -781,7 +784,7 @@ class msg_getblocks(object): def __init__(self): self.locator = CBlockLocator() - self.hashstop = 0L + self.hashstop = 0 def deserialize(self, f): self.locator = CBlockLocator() @@ -869,7 +872,7 @@ def __repr__(self): class msg_ping(object): command = b"ping" - def __init__(self, nonce=0L): + def __init__(self, nonce=0): self.nonce = nonce def deserialize(self, f): @@ -941,7 +944,7 @@ class msg_getheaders(object): def __init__(self): self.locator = CBlockLocator() - self.hashstop = 0L + self.hashstop = 0 def deserialize(self, f): self.locator = CBlockLocator() @@ -989,7 +992,7 @@ def __init__(self): self.message = b"" self.code = 0 self.reason = b"" - self.data = 0L + self.data = 0 def deserialize(self, f): self.message = deser_string(f) @@ -1030,7 +1033,7 @@ def wait_until(predicate, attempts=float('inf'), timeout=float('inf')): class msg_feefilter(object): command = b"feefilter" - def __init__(self, feerate=0L): + def __init__(self, feerate=0): self.feerate = feerate def deserialize(self, f): @@ -1079,10 +1082,10 @@ def deliver(self, conn, message): time.sleep(deliver_sleep) with mininode_lock: try: - getattr(self, 'on_' + message.command)(conn, message) + getattr(self, 'on_' + message.command.decode('ascii'))(conn, message) except: - print "ERROR delivering %s (%s)" % (repr(message), - sys.exc_info()[0]) + print("ERROR delivering %s (%s)" % (repr(message), + sys.exc_info()[0])) def on_version(self, conn, message): if message.nVersion >= 209: @@ -1200,8 +1203,8 @@ def __init__(self, dstaddr, dstport, rpc, callback, net="regtest", services=1): vt.addrFrom.ip = "0.0.0.0" vt.addrFrom.port = 0 self.send_message(vt, True) - print 'MiniNode: Connecting to Bitcoin Node IP # ' + dstaddr + ':' \ - + str(dstport) + print('MiniNode: Connecting to Bitcoin Node IP # ' + dstaddr + ':' \ + + str(dstport)) try: self.connect((dstaddr, dstport)) @@ -1294,7 +1297,9 @@ def got_data(self): self.show_debug_msg("Unknown command: '" + command + "' " + repr(msg)) except Exception as e: - print 'got_data:', repr(e) + print('got_data:', repr(e)) + # import traceback + # traceback.print_tb(sys.exc_info()[2]) def send_message(self, message, pushbuf=False): if self.state != "connected" and not pushbuf: diff --git a/qa/rpc-tests/test_framework/netutil.py b/qa/rpc-tests/test_framework/netutil.py index 52a7ab74890f1..573b06772d7b3 100644 --- a/qa/rpc-tests/test_framework/netutil.py +++ b/qa/rpc-tests/test_framework/netutil.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/qa/rpc-tests/test_framework/script.py b/qa/rpc-tests/test_framework/script.py index 5fb5758f81fa3..44a894fc8f488 100644 --- a/qa/rpc-tests/test_framework/script.py +++ b/qa/rpc-tests/test_framework/script.py @@ -1,18 +1,19 @@ +#!/usr/bin/env python3 +# Copyright (c) 2015-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + # # script.py # # This file is modified from python-bitcoinlib. # -# Distributed under the MIT/X11 software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. -# """Scripts Functionality to build scripts, as well as SignatureHash(). """ -from __future__ import absolute_import, division, print_function, unicode_literals from .mininode import CTransaction, CTxOut, hash256 from binascii import hexlify @@ -658,7 +659,7 @@ def __coerce_instance(cls, other): other = bchr(CScriptOp(OP_0)) else: other = CScriptNum.encode(other) - elif isinstance(other, (int, long)): + elif isinstance(other, int): if 0 <= other <= 16: other = bytes(bchr(CScriptOp.encode_op_n(other))) elif other == -1: diff --git a/qa/rpc-tests/test_framework/socks5.py b/qa/rpc-tests/test_framework/socks5.py index f725d97701747..372f5ed605e4a 100644 --- a/qa/rpc-tests/test_framework/socks5.py +++ b/qa/rpc-tests/test_framework/socks5.py @@ -1,11 +1,12 @@ -# Copyright (c) 2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2015-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. ''' Dummy Socks5 server for testing. ''' -from __future__ import print_function, division, unicode_literals -import socket, threading, Queue + +import socket, threading, queue import traceback, sys ### Protocol constants @@ -132,7 +133,7 @@ def __init__(self, conf): self.s.listen(5) self.running = False self.thread = None - self.queue = Queue.Queue() # report connections and exceptions to client + self.queue = queue.Queue() # report connections and exceptions to client def run(self): while self.running: diff --git a/qa/rpc-tests/test_framework/test_framework.py b/qa/rpc-tests/test_framework/test_framework.py index 18ecf64b06e59..ed12e1efb6d1a 100755 --- a/qa/rpc-tests/test_framework/test_framework.py +++ b/qa/rpc-tests/test_framework/test_framework.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -140,7 +140,7 @@ def main(self): print("JSONRPC error: "+e.error['message']) traceback.print_tb(sys.exc_info()[2]) except AssertionError as e: - print("Assertion failed: "+ str(e)) + print("Assertion failed: " + str(e)) traceback.print_tb(sys.exc_info()[2]) except KeyError as e: print("key not found: "+ str(e)) @@ -189,7 +189,7 @@ def add_options(self, parser): help="bitcoind binary to use for reference nodes (if any)") def setup_chain(self): - print "Initializing test directory "+self.options.tmpdir + print("Initializing test directory "+self.options.tmpdir) initialize_chain_clean(self.options.tmpdir, self.num_nodes) def setup_network(self): diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index baa1ed6790724..ea3931cef3614 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -1,4 +1,5 @@ -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -191,10 +192,10 @@ def initialize_chain(test_dir): args.append("-connect=127.0.0.1:"+str(p2p_port(0))) bitcoind_processes[i] = subprocess.Popen(args) if os.getenv("PYTHON_DEBUG", ""): - print "initialize_chain: bitcoind started, waiting for RPC to come up" + print("initialize_chain: bitcoind started, waiting for RPC to come up") wait_for_bitcoind_start(bitcoind_processes[i], rpc_url(i), i) if os.getenv("PYTHON_DEBUG", ""): - print "initialize_chain: RPC succesfully started" + print("initialize_chain: RPC succesfully started") rpcs = [] for i in range(4): @@ -275,11 +276,11 @@ def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary= if extra_args is not None: args.extend(extra_args) bitcoind_processes[i] = subprocess.Popen(args) if os.getenv("PYTHON_DEBUG", ""): - print "start_node: bitcoind started, waiting for RPC to come up" + print("start_node: bitcoind started, waiting for RPC to come up") url = rpc_url(i, rpchost) wait_for_bitcoind_start(bitcoind_processes[i], url, i) if os.getenv("PYTHON_DEBUG", ""): - print "start_node: RPC succesfully started" + print("start_node: RPC succesfully started") proxy = get_rpc_proxy(url, i, timeout=timewait) if COVERAGE_DIR: @@ -469,7 +470,7 @@ def assert_is_hex_string(string): "Couldn't interpret %r as hexadecimal; raised: %s" % (string, e)) def assert_is_hash_string(string, length=64): - if not isinstance(string, basestring): + if not isinstance(string, str): raise AssertionError("Expected a string, got type %r" % type(string)) elif length and len(string) != length: raise AssertionError( @@ -520,7 +521,7 @@ def create_confirmed_utxos(fee, node, count): addr2 = node.getnewaddress() if iterations <= 0: return utxos - for i in xrange(iterations): + for i in range(iterations): t = utxos.pop() inputs = [] inputs.append({ "txid" : t["txid"], "vout" : t["vout"]}) @@ -546,11 +547,11 @@ def gen_return_txouts(): # So we have big transactions (and therefore can't fit very many into each block) # create one script_pubkey script_pubkey = "6a4d0200" #OP_RETURN OP_PUSH2 512 bytes - for i in xrange (512): + for i in range (512): script_pubkey = script_pubkey + "01" # concatenate 128 txouts of above script_pubkey which we'll insert before the txout for change txouts = "81" - for k in xrange(128): + for k in range(128): # add txout value txouts = txouts + "0000000000000000" # add length of script_pubkey @@ -572,7 +573,7 @@ def create_tx(node, coinbase, to_address, amount): def create_lots_of_big_transactions(node, txouts, utxos, fee): addr = node.getnewaddress() txids = [] - for i in xrange(len(utxos)): + for i in range(len(utxos)): t = utxos.pop() inputs = [] inputs.append({ "txid" : t["txid"], "vout" : t["vout"]}) diff --git a/qa/rpc-tests/txn_clone.py b/qa/rpc-tests/txn_clone.py index b132aec4b6165..5710c29aa60cd 100755 --- a/qa/rpc-tests/txn_clone.py +++ b/qa/rpc-tests/txn_clone.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/qa/rpc-tests/txn_doublespend.py b/qa/rpc-tests/txn_doublespend.py index 8d7f6e505d15b..1fbb207e22db8 100755 --- a/qa/rpc-tests/txn_doublespend.py +++ b/qa/rpc-tests/txn_doublespend.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py index 555f836482d20..42ce0a7260fa3 100755 --- a/qa/rpc-tests/wallet.py +++ b/qa/rpc-tests/wallet.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -38,7 +38,7 @@ def run_test (self): assert_equal(len(self.nodes[1].listunspent()), 0) assert_equal(len(self.nodes[2].listunspent()), 0) - print "Mining blocks..." + print("Mining blocks...") self.nodes[0].generate(1) @@ -321,7 +321,7 @@ def run_test (self): '-salvagewallet', ] for m in maintenance: - print "check " + m + print("check " + m) stop_nodes(self.nodes) wait_bitcoinds() self.nodes = start_nodes(3, self.options.tmpdir, [[m]] * 3) diff --git a/qa/rpc-tests/walletbackup.py b/qa/rpc-tests/walletbackup.py index 1221a09116791..418f3103e3ad7 100755 --- a/qa/rpc-tests/walletbackup.py +++ b/qa/rpc-tests/walletbackup.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/qa/rpc-tests/zapwallettxes.py b/qa/rpc-tests/zapwallettxes.py index 1ba4ded249aad..2f8214f87c26c 100755 --- a/qa/rpc-tests/zapwallettxes.py +++ b/qa/rpc-tests/zapwallettxes.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2014-2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -22,7 +22,7 @@ def setup_network(self, split=False): self.sync_all() def run_test (self): - print "Mining blocks..." + print("Mining blocks...") self.nodes[0].generate(1) self.sync_all() self.nodes[1].generate(101) diff --git a/qa/rpc-tests/zmq_test.py b/qa/rpc-tests/zmq_test.py index 97850bea3c022..f5617a084db7d 100755 --- a/qa/rpc-tests/zmq_test.py +++ b/qa/rpc-tests/zmq_test.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -# Copyright (c) 2015 The Bitcoin Core developers +#!/usr/bin/env python3 +# Copyright (c) 2015-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -10,17 +10,10 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * import zmq -import binascii import struct -try: - import http.client as httplib -except ImportError: - import httplib -try: - import urllib.parse as urlparse -except ImportError: - import urlparse +import http.client +import urllib.parse class ZMQTest (BitcoinTestFramework): @@ -45,7 +38,7 @@ def run_test(self): genhashes = self.nodes[0].generate(1) self.sync_all() - print "listen..." + print("listen...") msg = self.zmqSubSocket.recv_multipart() topic = msg[0] assert_equal(topic, b"hashtx") From 52cbce287a0d9b3184fd3aee9d4f1186fd2dd7da Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 15 Apr 2016 19:53:45 -0400 Subject: [PATCH 0262/1802] net: don't import std namespace This file is about to be broken up into chunks and moved around. Drop the namespace now rather than requiring other files to use it. --- src/net.cpp | 63 ++++++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 6642ef651508d..8ae31e715e36b 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -56,7 +56,6 @@ #endif #endif -using namespace std; namespace { const int MAX_OUTBOUND_CONNECTIONS = 8; @@ -78,7 +77,7 @@ bool fDiscover = true; bool fListen = true; uint64_t nLocalServices = NODE_NETWORK; CCriticalSection cs_mapLocalHost; -map mapLocalHost; +std::map mapLocalHost; static bool vfLimited[NET_MAX] = {}; static CNode* pnodeLocalHost = NULL; uint64_t nLocalHostNonce = 0; @@ -88,20 +87,20 @@ int nMaxConnections = DEFAULT_MAX_PEER_CONNECTIONS; bool fAddressesInitialized = false; std::string strSubVersion; -vector vNodes; +std::vector vNodes; CCriticalSection cs_vNodes; -map mapRelay; -deque > vRelayExpiration; +std::map mapRelay; +std::deque > vRelayExpiration; CCriticalSection cs_mapRelay; limitedmap mapAlreadyAskedFor(MAX_INV_SZ); -static deque vOneShots; +static std::deque vOneShots; CCriticalSection cs_vOneShots; -set setservAddNodeAddresses; +std::set setservAddNodeAddresses; CCriticalSection cs_setservAddNodeAddresses; -vector vAddedNodes; +std::vector vAddedNodes; CCriticalSection cs_vAddedNodes; NodeId nLastNodeId = 0; @@ -135,7 +134,7 @@ bool GetLocal(CService& addr, const CNetAddr *paddrPeer) int nBestReachability = -1; { LOCK(cs_mapLocalHost); - for (map::iterator it = mapLocalHost.begin(); it != mapLocalHost.end(); it++) + for (std::map::iterator it = mapLocalHost.begin(); it != mapLocalHost.end(); it++) { int nScore = (*it).second.nScore; int nReachability = (*it).first.GetReachabilityFrom(paddrPeer); @@ -796,7 +795,7 @@ void SocketSendData(CNode *pnode) pnode->vSendMsg.erase(pnode->vSendMsg.begin(), it); } -static list vNodesDisconnected; +static std::list vNodesDisconnected; class CNodeRef { public: @@ -1045,7 +1044,7 @@ void ThreadSocketHandler() { LOCK(cs_vNodes); // Disconnect unused nodes - vector vNodesCopy = vNodes; + std::vector vNodesCopy = vNodes; BOOST_FOREACH(CNode* pnode, vNodesCopy) { if (pnode->fDisconnect || @@ -1069,7 +1068,7 @@ void ThreadSocketHandler() } { // Delete disconnected nodes - list vNodesDisconnectedCopy = vNodesDisconnected; + std::list vNodesDisconnectedCopy = vNodesDisconnected; BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy) { // wait until threads are done using it @@ -1120,7 +1119,7 @@ void ThreadSocketHandler() BOOST_FOREACH(const ListenSocket& hListenSocket, vhListenSocket) { FD_SET(hListenSocket.socket, &fdsetRecv); - hSocketMax = max(hSocketMax, hListenSocket.socket); + hSocketMax = std::max(hSocketMax, hListenSocket.socket); have_fds = true; } @@ -1131,7 +1130,7 @@ void ThreadSocketHandler() if (pnode->hSocket == INVALID_SOCKET) continue; FD_SET(pnode->hSocket, &fdsetError); - hSocketMax = max(hSocketMax, pnode->hSocket); + hSocketMax = std::max(hSocketMax, pnode->hSocket); have_fds = true; // Implement the following logic: @@ -1198,7 +1197,7 @@ void ThreadSocketHandler() // // Service each socket // - vector vNodesCopy; + std::vector vNodesCopy; { LOCK(cs_vNodes); vNodesCopy = vNodes; @@ -1355,7 +1354,7 @@ void ThreadMapPort() } } - string strDesc = "Bitcoin " + FormatFullVersion(); + std::string strDesc = "Bitcoin " + FormatFullVersion(); try { while (true) { @@ -1441,7 +1440,7 @@ void ThreadDNSAddressSeed() } } - const vector &vSeeds = Params().DNSSeeds(); + const std::vector &vSeeds = Params().DNSSeeds(); int found = 0; LogPrintf("Loading addresses from DNS seeds (could take a while)\n"); @@ -1450,8 +1449,8 @@ void ThreadDNSAddressSeed() if (HaveNameProxy()) { AddOneShot(seed.host); } else { - vector vIPs; - vector vAdd; + std::vector vIPs; + std::vector vAdd; if (LookupHost(seed.host.c_str(), vIPs, 0, true)) { BOOST_FOREACH(const CNetAddr& ip, vIPs) @@ -1508,7 +1507,7 @@ void DumpData() void static ProcessOneShot() { - string strDest; + std::string strDest; { LOCK(cs_vOneShots); if (vOneShots.empty()) @@ -1574,7 +1573,7 @@ void ThreadOpenConnections() // Only connect out to one peer per network group (/16 for IPv4). // Do this here so we don't have to critsect vNodes inside mapAddresses critsect. int nOutbound = 0; - set > setConnected; + std::set > setConnected; { LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) { @@ -1632,7 +1631,7 @@ void ThreadOpenAddedConnections() if (HaveNameProxy()) { while(true) { - list lAddresses(0); + std::list lAddresses(0); { LOCK(cs_vAddedNodes); BOOST_FOREACH(const std::string& strAddNode, vAddedNodes) @@ -1650,16 +1649,16 @@ void ThreadOpenAddedConnections() for (unsigned int i = 0; true; i++) { - list lAddresses(0); + std::list lAddresses(0); { LOCK(cs_vAddedNodes); BOOST_FOREACH(const std::string& strAddNode, vAddedNodes) lAddresses.push_back(strAddNode); } - list > lservAddressesToAdd(0); + std::list > lservAddressesToAdd(0); BOOST_FOREACH(const std::string& strAddNode, lAddresses) { - vector vservNode(0); + std::vector vservNode(0); if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0)) { lservAddressesToAdd.push_back(vservNode); @@ -1675,7 +1674,7 @@ void ThreadOpenAddedConnections() { LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) - for (list >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++) + for (std::list >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++) BOOST_FOREACH(const CService& addrNode, *(it)) if (pnode->addr == addrNode) { @@ -1684,7 +1683,7 @@ void ThreadOpenAddedConnections() break; } } - BOOST_FOREACH(vector& vserv, lservAddressesToAdd) + BOOST_FOREACH(std::vector& vserv, lservAddressesToAdd) { CSemaphoreGrant grant(*semOutbound); OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant); @@ -1732,7 +1731,7 @@ void ThreadMessageHandler() SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL); while (true) { - vector vNodesCopy; + std::vector vNodesCopy; { LOCK(cs_vNodes); vNodesCopy = vNodes; @@ -1792,7 +1791,7 @@ void ThreadMessageHandler() -bool BindListenPort(const CService &addrBind, string& strError, bool fWhitelisted) +bool BindListenPort(const CService &addrBind, std::string& strError, bool fWhitelisted) { strError = ""; int nOne = 1; @@ -1900,7 +1899,7 @@ void static Discover(boost::thread_group& threadGroup) char pszHostName[256] = ""; if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR) { - vector vaddr; + std::vector vaddr; if (LookupHost(pszHostName, vaddr, 0, true)) { BOOST_FOREACH (const CNetAddr &addr, vaddr) @@ -2300,7 +2299,7 @@ bool CAddrDB::Read(CAddrMan& addr) // Don't try to resize to a negative number if file is small if (fileSize >= sizeof(uint256)) dataSize = fileSize - sizeof(uint256); - vector vchData; + std::vector vchData; vchData.resize(dataSize); uint256 hashIn; @@ -2580,7 +2579,7 @@ bool CBanDB::Read(banmap_t& banSet) // Don't try to resize to a negative number if file is small if (fileSize >= sizeof(uint256)) dataSize = fileSize - sizeof(uint256); - vector vchData; + std::vector vchData; vchData.resize(dataSize); uint256 hashIn; From 9faa4902cd32af9742b7ffcc163725bff226da1f Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 15 Apr 2016 20:01:40 -0400 Subject: [PATCH 0263/1802] net: remove unused set --- src/net.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 8ae31e715e36b..771d9e862499f 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -97,9 +97,6 @@ limitedmap mapAlreadyAskedFor(MAX_INV_SZ); static std::deque vOneShots; CCriticalSection cs_vOneShots; -std::set setservAddNodeAddresses; -CCriticalSection cs_setservAddNodeAddresses; - std::vector vAddedNodes; CCriticalSection cs_vAddedNodes; @@ -1660,14 +1657,7 @@ void ThreadOpenAddedConnections() BOOST_FOREACH(const std::string& strAddNode, lAddresses) { std::vector vservNode(0); if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0)) - { lservAddressesToAdd.push_back(vservNode); - { - LOCK(cs_setservAddNodeAddresses); - BOOST_FOREACH(const CService& serv, vservNode) - setservAddNodeAddresses.insert(serv); - } - } } // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry // (keeping in mind that addnode entries can have many IPs if fNameLookup) From 563f375cdeae3e67a57d8a7187362a4706c33748 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 15 Apr 2016 20:03:18 -0400 Subject: [PATCH 0264/1802] net: use the exposed GetNodeSignals() rather than g_signals directly --- src/net.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 771d9e862499f..d6034953cff7e 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -439,7 +439,7 @@ void CNode::CloseSocketDisconnect() void CNode::PushVersion() { - int nBestHeight = g_signals.GetHeight().get_value_or(0); + int nBestHeight = GetNodeSignals().GetHeight().get_value_or(0); int64_t nTime = (fInbound ? GetAdjustedTime() : GetTime()); CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0))); @@ -1742,7 +1742,7 @@ void ThreadMessageHandler() TRY_LOCK(pnode->cs_vRecvMsg, lockRecv); if (lockRecv) { - if (!g_signals.ProcessMessages(pnode)) + if (!GetNodeSignals().ProcessMessages(pnode)) pnode->CloseSocketDisconnect(); if (pnode->nSendSize < SendBufferSize()) @@ -1760,7 +1760,7 @@ void ThreadMessageHandler() { TRY_LOCK(pnode->cs_vSend, lockSend); if (lockSend) - g_signals.SendMessages(pnode); + GetNodeSignals().SendMessages(pnode); } boost::this_thread::interruption_point(); } From cca221fd211f63b338bd90afc505bd4a22a01d5d Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Mon, 18 Apr 2016 15:58:19 -0400 Subject: [PATCH 0265/1802] net: Drop CNodeRef for AttemptToEvictConnection Locking for each operation here is unnecessary, and solves the wrong problem. Additionally, it introduces a problem when cs_vNodes is held in an owning class, to which invididual CNodeRefs won't have access. These should be weak pointers anyway, once vNodes contain shared pointers. Rather than using a refcounting class, use a 3-step process instead. 1. Lock vNodes long enough to snapshot the fields necessary for comparing 2. Unlock and do the comparison 3. Re-lock and mark the resulting node for disconnection if it still exists --- src/net.cpp | 84 ++++++++++++++++++++--------------------------------- 1 file changed, 31 insertions(+), 53 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index d6034953cff7e..41e657fba3719 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -794,51 +794,22 @@ void SocketSendData(CNode *pnode) static std::list vNodesDisconnected; -class CNodeRef { -public: - CNodeRef(CNode *pnode) : _pnode(pnode) { - LOCK(cs_vNodes); - _pnode->AddRef(); - } - - ~CNodeRef() { - LOCK(cs_vNodes); - _pnode->Release(); - } - - CNode& operator *() const {return *_pnode;}; - CNode* operator ->() const {return _pnode;}; - - CNodeRef& operator =(const CNodeRef& other) - { - if (this != &other) { - LOCK(cs_vNodes); - - _pnode->Release(); - _pnode = other._pnode; - _pnode->AddRef(); - } - return *this; - } - - CNodeRef(const CNodeRef& other): - _pnode(other._pnode) - { - LOCK(cs_vNodes); - _pnode->AddRef(); - } -private: - CNode *_pnode; +struct NodeEvictionCandidate +{ + NodeId id; + int64_t nTimeConnected; + int64_t nMinPingUsecTime; + CAddress addr; }; -static bool ReverseCompareNodeMinPingTime(const CNodeRef &a, const CNodeRef &b) +static bool ReverseCompareNodeMinPingTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b) { - return a->nMinPingUsecTime > b->nMinPingUsecTime; + return a.nMinPingUsecTime > b.nMinPingUsecTime; } -static bool ReverseCompareNodeTimeConnected(const CNodeRef &a, const CNodeRef &b) +static bool ReverseCompareNodeTimeConnected(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b) { - return a->nTimeConnected > b->nTimeConnected; + return a.nTimeConnected > b.nTimeConnected; } class CompareNetGroupKeyed @@ -851,14 +822,14 @@ class CompareNetGroupKeyed GetRandBytes(vchSecretKey.data(), vchSecretKey.size()); } - bool operator()(const CNodeRef &a, const CNodeRef &b) + bool operator()(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b) { std::vector vchGroupA, vchGroupB; CSHA256 hashA, hashB; std::vector vchA(32), vchB(32); - vchGroupA = a->addr.GetGroup(); - vchGroupB = b->addr.GetGroup(); + vchGroupA = a.addr.GetGroup(); + vchGroupB = b.addr.GetGroup(); hashA.Write(begin_ptr(vchGroupA), vchGroupA.size()); hashB.Write(begin_ptr(vchGroupB), vchGroupB.size()); @@ -882,7 +853,7 @@ class CompareNetGroupKeyed * simultaneously better at all of them than honest peers. */ static bool AttemptToEvictConnection(bool fPreferNewConnection) { - std::vector vEvictionCandidates; + std::vector vEvictionCandidates; { LOCK(cs_vNodes); @@ -893,7 +864,8 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) { continue; if (node->fDisconnect) continue; - vEvictionCandidates.push_back(CNodeRef(node)); + NodeEvictionCandidate candidate = {node->id, node->nTimeConnected, node->nMinPingUsecTime, node->addr}; + vEvictionCandidates.push_back(candidate); } } @@ -928,16 +900,16 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) { std::vector naMostConnections; unsigned int nMostConnections = 0; int64_t nMostConnectionsTime = 0; - std::map, std::vector > mapAddrCounts; - BOOST_FOREACH(const CNodeRef &node, vEvictionCandidates) { - mapAddrCounts[node->addr.GetGroup()].push_back(node); - int64_t grouptime = mapAddrCounts[node->addr.GetGroup()][0]->nTimeConnected; - size_t groupsize = mapAddrCounts[node->addr.GetGroup()].size(); + std::map, std::vector > mapAddrCounts; + BOOST_FOREACH(const NodeEvictionCandidate &node, vEvictionCandidates) { + mapAddrCounts[node.addr.GetGroup()].push_back(node); + int64_t grouptime = mapAddrCounts[node.addr.GetGroup()][0].nTimeConnected; + size_t groupsize = mapAddrCounts[node.addr.GetGroup()].size(); if (groupsize > nMostConnections || (groupsize == nMostConnections && grouptime > nMostConnectionsTime)) { nMostConnections = groupsize; nMostConnectionsTime = grouptime; - naMostConnections = node->addr.GetGroup(); + naMostConnections = node.addr.GetGroup(); } } @@ -952,9 +924,15 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) { return false; // Disconnect from the network group with the most connections - vEvictionCandidates[0]->fDisconnect = true; - - return true; + NodeId evicted = vEvictionCandidates.front().id; + LOCK(cs_vNodes); + for(std::vector::const_iterator it(vNodes.begin()); it != vNodes.end(); ++it) { + if ((*it)->GetId() == evicted) { + (*it)->fDisconnect = true; + return true; + } + } + return false; } static void AcceptConnection(const ListenSocket& hListenSocket) { From e53e7c54736b98098553ba1a5191e093684f9114 Mon Sep 17 00:00:00 2001 From: Kaz Wesley Date: Thu, 5 May 2016 11:55:46 -0700 Subject: [PATCH 0266/1802] don't run ThreadMessageHandler at lowered priority There's no clear reason ThreadMessageHandler should be low priority. Fixes #8010 (priority inversion). --- src/compat.h | 11 ----------- src/net.cpp | 1 - src/util.cpp | 13 ------------- src/util.h | 1 - 4 files changed, 26 deletions(-) diff --git a/src/compat.h b/src/compat.h index 1225ea18edb85..79a297e5e4010 100644 --- a/src/compat.h +++ b/src/compat.h @@ -78,17 +78,6 @@ typedef u_int SOCKET; #define MSG_NOSIGNAL 0 #endif -#ifndef WIN32 -// PRIO_MAX is not defined on Solaris -#ifndef PRIO_MAX -#define PRIO_MAX 20 -#endif -#define THREAD_PRIORITY_LOWEST PRIO_MAX -#define THREAD_PRIORITY_BELOW_NORMAL 2 -#define THREAD_PRIORITY_NORMAL 0 -#define THREAD_PRIORITY_ABOVE_NORMAL (-2) -#endif - #if HAVE_DECL_STRNLEN == 0 size_t strnlen( const char *start, size_t max_len); #endif // HAVE_DECL_STRNLEN diff --git a/src/net.cpp b/src/net.cpp index 6642ef651508d..5e810a0f15888 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1729,7 +1729,6 @@ void ThreadMessageHandler() boost::mutex condition_mutex; boost::unique_lock lock(condition_mutex); - SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL); while (true) { vector vNodesCopy; diff --git a/src/util.cpp b/src/util.cpp index 00b75fbdbe38e..3f0f8be544768 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -790,19 +790,6 @@ bool SetupNetworking() return true; } -void SetThreadPriority(int nPriority) -{ -#ifdef WIN32 - SetThreadPriority(GetCurrentThread(), nPriority); -#else // WIN32 -#ifdef PRIO_THREAD - setpriority(PRIO_THREAD, 0, nPriority); -#else // PRIO_THREAD - setpriority(PRIO_PROCESS, 0, nPriority); -#endif // PRIO_THREAD -#endif // WIN32 -} - int GetNumCores() { #if BOOST_VERSION >= 105600 diff --git a/src/util.h b/src/util.h index 25c9b733e871f..45e81ab67f32d 100644 --- a/src/util.h +++ b/src/util.h @@ -208,7 +208,6 @@ std::string HelpMessageOpt(const std::string& option, const std::string& message */ int GetNumCores(); -void SetThreadPriority(int nPriority); void RenameThread(const char* name); /** From b06f6a992b4a80c6a9ef2387bfd81e30a407b245 Mon Sep 17 00:00:00 2001 From: JeremyRand Date: Thu, 5 May 2016 23:08:47 +0000 Subject: [PATCH 0267/1802] Fixed invalid example paths in gitian-building.md The example local paths for "Building fully offline" have an extraneous ".git". This caused an error when trying to run gbuild, like this fatal: '/home/user/bitcoin.git' does not appear to be a git repository fatal: Could not read from remote repository. This commit fixes that. --- doc/gitian-building.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/gitian-building.md b/doc/gitian-building.md index 13f8ad316b3f5..791f209bb1373 100644 --- a/doc/gitian-building.md +++ b/doc/gitian-building.md @@ -443,8 +443,8 @@ Then when building, override the remote URLs that gbuild would otherwise pull fr cd /some/root/path/ git clone https://github.com/bitcoin-core/bitcoin-detached-sigs.git -BTCPATH=/some/root/path/bitcoin.git -SIGPATH=/some/root/path/bitcoin-detached-sigs.git +BTCPATH=/some/root/path/bitcoin +SIGPATH=/some/root/path/bitcoin-detached-sigs ./bin/gbuild --url bitcoin=${BTCPATH},signature=${SIGPATH} ../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml ``` From b3d18ba072f21d5fdb43c9e3cbf6963190d787bd Mon Sep 17 00:00:00 2001 From: Warren Togami Date: Thu, 5 May 2016 18:24:27 -0700 Subject: [PATCH 0268/1802] doc: Fedora build requirements, add gcc-c++ and fix typo --- doc/build-unix.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/build-unix.md b/doc/build-unix.md index 27c57088af015..bd89978cc2a74 100644 --- a/doc/build-unix.md +++ b/doc/build-unix.md @@ -128,7 +128,7 @@ Dependency Build Instructions: Fedora ------------------------------------- Build requirements: - sudo dnf install libtool make autoconf automake openssl-devel libevent-devel boost-devel libdb4-devel libdb4-cxx-devel + sudo dnf install gcc-c++ libtool make autoconf automake openssl-devel libevent-devel boost-devel libdb4-devel libdb4-cxx-devel Optional: @@ -136,7 +136,7 @@ Optional: To build with Qt 5 (recommended) you need the following: - sudo dnf install qt5-qttools-devel qtr5-qtbase-devel protobuf-devel + sudo dnf install qt5-qttools-devel qt5-qtbase-devel protobuf-devel libqrencode (optional) can be installed with: From a4d5855a2518c0727faf737de4febcee5f5c4901 Mon Sep 17 00:00:00 2001 From: 21E14 <21xe14@gmail.com> Date: Fri, 6 May 2016 00:10:49 -0400 Subject: [PATCH 0269/1802] CCoinsViewErrorCatcher raison-d-etre --- src/init.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/init.cpp b/src/init.cpp index b06f448a001cf..d74e6272eff1c 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -136,6 +136,11 @@ bool ShutdownRequested() return fRequestShutdown; } +/** + * This is a minimally invasive approach to shutdown on LevelDB read errors from the + * chainstate, while keeping user interface out of the common library, which is shared + * between bitcoind, and bitcoin-qt and non-server tools. +*/ class CCoinsViewErrorCatcher : public CCoinsViewBacked { public: From 04eaa9095813b854c4299027c595fb9ebaf6f934 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 6 May 2016 11:01:50 +0200 Subject: [PATCH 0270/1802] Add more clear interface for CoinControl.h regarding individual feerate --- src/coincontrol.h | 5 ++++- src/wallet/rpcwallet.cpp | 6 +++++- src/wallet/wallet.cpp | 5 +++-- src/wallet/wallet.h | 2 +- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/coincontrol.h b/src/coincontrol.h index 6129397bc8f5d..e33adc4d2b00c 100644 --- a/src/coincontrol.h +++ b/src/coincontrol.h @@ -18,7 +18,9 @@ class CCoinControl bool fAllowWatchOnly; //! Minimum absolute fee (not per kilobyte) CAmount nMinimumTotalFee; - //! Feerate to use (0 = estimate fee with payTxFee fallback) + //! Override estimated feerate + bool fOverrideFeeRate; + //! Feerate to use if overrideFeeRate is true CFeeRate nFeeRate; CCoinControl() @@ -34,6 +36,7 @@ class CCoinControl setSelected.clear(); nMinimumTotalFee = 0; nFeeRate = CFeeRate(0); + fOverrideFeeRate = false; } bool HasSelected() const diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index b14d748b3917e..933cd1e80752d 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2486,6 +2486,7 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) bool includeWatching = false; bool lockUnspents = false; CFeeRate feeRate = CFeeRate(0); + bool overrideEstimatedFeerate = false; if (params.size() > 1) { if (params[1].type() == UniValue::VBOOL) { @@ -2518,7 +2519,10 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) lockUnspents = options["lockUnspents"].get_bool(); if (options.exists("feeRate")) + { feeRate = CFeeRate(options["feeRate"].get_real()); + overrideEstimatedFeerate = true; + } } } @@ -2537,7 +2541,7 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) CAmount nFeeOut; string strFailReason; - if(!pwalletMain->FundTransaction(tx, nFeeOut, feeRate, changePosition, strFailReason, includeWatching, lockUnspents, changeAddress)) + if(!pwalletMain->FundTransaction(tx, nFeeOut, overrideEstimatedFeerate, feeRate, changePosition, strFailReason, includeWatching, lockUnspents, changeAddress)) throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason); UniValue result(UniValue::VOBJ); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 6b5e3ca7f5994..96c5c416aa863 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1918,7 +1918,7 @@ bool CWallet::SelectCoins(const vector& vAvailableCoins, const CAmount& return res; } -bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, const CFeeRate& specificFeeRate, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, bool lockUnspents, const CTxDestination& destChange) +bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, bool overrideEstimatedFeeRate, const CFeeRate& specificFeeRate, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, bool lockUnspents, const CTxDestination& destChange) { vector vecSend; @@ -1933,6 +1933,7 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, const C coinControl.destChange = destChange; coinControl.fAllowOtherInputs = true; coinControl.fAllowWatchOnly = includeWatching; + coinControl.fOverrideFeeRate = overrideEstimatedFeeRate; coinControl.nFeeRate = specificFeeRate; BOOST_FOREACH(const CTxIn& txin, tx.vin) @@ -2244,7 +2245,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt if (coinControl && nFeeNeeded > 0 && coinControl->nMinimumTotalFee > nFeeNeeded) { nFeeNeeded = coinControl->nMinimumTotalFee; } - if (coinControl && coinControl->nFeeRate > CFeeRate(0)) + if (coinControl && coinControl->fOverrideFeeRate) nFeeNeeded = coinControl->nFeeRate.GetFee(nBytes); // If we made it here and we aren't even able to meet the relay fee on the next pass, give up diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 7b5168975ce11..7a9e306f6fe0a 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -740,7 +740,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface * Insert additional inputs into the transaction by * calling CreateTransaction(); */ - bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, const CFeeRate& specificFeeRate, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, bool lockUnspents, const CTxDestination& destChange = CNoDestination()); + bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, bool overrideEstimatedFeeRate, const CFeeRate& specificFeeRate, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, bool lockUnspents, const CTxDestination& destChange = CNoDestination()); /** * Create a new transaction paying the recipients with a set of coins From 0bf6f302626497184a26b88c61fe6af1741e2a44 Mon Sep 17 00:00:00 2001 From: Pedro Branco Date: Tue, 8 Mar 2016 10:37:18 +0000 Subject: [PATCH 0271/1802] Prevent multiple calls to ExtractDestination --- src/wallet/rpcwallet.cpp | 41 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 623037e76648b..8da749f525280 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2341,13 +2341,14 @@ UniValue listunspent(const UniValue& params, bool fHelp) "\nResult\n" "[ (array of json object)\n" " {\n" - " \"txid\" : \"txid\", (string) the transaction id \n" + " \"txid\" : \"txid\", (string) the transaction id \n" " \"vout\" : n, (numeric) the vout value\n" - " \"address\" : \"address\", (string) the bitcoin address\n" - " \"account\" : \"account\", (string) DEPRECATED. The associated account, or \"\" for the default account\n" - " \"scriptPubKey\" : \"key\", (string) the script key\n" + " \"address\" : \"address\", (string) the bitcoin address\n" + " \"account\" : \"account\", (string) DEPRECATED. The associated account, or \"\" for the default account\n" + " \"scriptPubKey\" : \"key\", (string) the script key\n" " \"amount\" : x.xxx, (numeric) the transaction amount in " + CURRENCY_UNIT + "\n" " \"confirmations\" : n, (numeric) The number of confirmations\n" + " \"redeemScript\" : n (string) The redeemScript if scriptPubKey is P2SH\n" " \"spendable\" : xxx, (bool) Whether we have the private keys to spend this output\n" " \"solvable\" : xxx (bool) Whether we know how to spend this output, ignoring the lack of keys\n" " }\n" @@ -2393,38 +2394,34 @@ UniValue listunspent(const UniValue& params, bool fHelp) if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth) continue; - if (setAddress.size()) { - CTxDestination address; - if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) - continue; + CTxDestination address; + const CScript& scriptPubKey = out.tx->vout[out.i].scriptPubKey; + bool fValidAddress = ExtractDestination(scriptPubKey, address); - if (!setAddress.count(address)) - continue; - } + if (setAddress.size() && (!fValidAddress || !setAddress.count(address))) + continue; - CAmount nValue = out.tx->vout[out.i].nValue; - const CScript& pk = out.tx->vout[out.i].scriptPubKey; UniValue entry(UniValue::VOBJ); entry.push_back(Pair("txid", out.tx->GetHash().GetHex())); entry.push_back(Pair("vout", out.i)); - CTxDestination address; - if (ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) { + + if (fValidAddress) { entry.push_back(Pair("address", CBitcoinAddress(address).ToString())); + if (pwalletMain->mapAddressBook.count(address)) entry.push_back(Pair("account", pwalletMain->mapAddressBook[address].name)); - } - entry.push_back(Pair("scriptPubKey", HexStr(pk.begin(), pk.end()))); - if (pk.IsPayToScriptHash()) { - CTxDestination address; - if (ExtractDestination(pk, address)) { + + if (scriptPubKey.IsPayToScriptHash()) { const CScriptID& hash = boost::get(address); CScript redeemScript; if (pwalletMain->GetCScript(hash, redeemScript)) entry.push_back(Pair("redeemScript", HexStr(redeemScript.begin(), redeemScript.end()))); } } - entry.push_back(Pair("amount",ValueFromAmount(nValue))); - entry.push_back(Pair("confirmations",out.nDepth)); + + entry.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end()))); + entry.push_back(Pair("amount", ValueFromAmount(out.tx->vout[out.i].nValue))); + entry.push_back(Pair("confirmations", out.nDepth)); entry.push_back(Pair("spendable", out.fSpendable)); entry.push_back(Pair("solvable", out.fSolvable)); results.push_back(entry); From fabbf6bd62c1d8a290841b63fb1e5acec42ba3b0 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 27 Apr 2016 22:29:52 +0200 Subject: [PATCH 0272/1802] [qa] Refactor test_framework and pull tester * log to stdout * increase range for p2p and rpc ports * UPPERCASE_CONSTANTS * Stop nodes on CTRL+C --- qa/pull-tester/rpc-tests.py | 83 +++++++++---------- qa/rpc-tests/test_framework/test_framework.py | 4 +- qa/rpc-tests/test_framework/util.py | 17 +++- qa/rpc-tests/walletbackup.py | 2 +- 4 files changed, 56 insertions(+), 50 deletions(-) diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index 15153b7f586fc..e8434b4a6059a 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -31,6 +31,14 @@ from tests_config import * +BOLD = ("","") +if os.name == 'posix': + # primitive formatting on supported + # terminal via ANSI escape sequences: + BOLD = ('\033[0m', '\033[1m') + +RPC_TESTS_DIR = BUILDDIR + '/qa/rpc-tests/' + #If imported values are not defined then set to zero (or disabled) if 'ENABLE_WALLET' not in vars(): ENABLE_WALLET=0 @@ -43,29 +51,29 @@ ENABLE_COVERAGE=0 -#Create a set to store arguments and create the passOn string +#Create a set to store arguments and create the passon string opts = set() -passOn = "" -p = re.compile("^--") +passon_args = "" +PASSON_REGEX = re.compile("^--") -bold = ("","") -if (os.name == 'posix'): - bold = ('\033[0m', '\033[1m') +print_help = False for arg in sys.argv[1:]: + if arg == "--help" or arg == "-h" or arg == "-?": + print_help = True + break if arg == '--coverage': ENABLE_COVERAGE = 1 - elif (p.match(arg) or arg == "-h"): - passOn += " " + arg + elif PASSON_REGEX.match(arg): + passon_args += " " + arg else: opts.add(arg) #Set env vars -buildDir = BUILDDIR if "BITCOIND" not in os.environ: - os.environ["BITCOIND"] = buildDir + '/src/bitcoind' + EXEEXT + os.environ["BITCOIND"] = BUILDDIR + '/src/bitcoind' + EXEEXT if "BITCOINCLI" not in os.environ: - os.environ["BITCOINCLI"] = buildDir + '/src/bitcoin-cli' + EXEEXT + os.environ["BITCOINCLI"] = BUILDDIR + '/src/bitcoin-cli' + EXEEXT if EXEEXT == ".exe" and "-win" not in opts: # https://github.com/bitcoin/bitcoin/commit/d52802551752140cf41f0d9a225a43e84404d3e9 @@ -153,48 +161,35 @@ ] def runtests(): + test_list = [] + if '-extended' in opts: + test_list = testScripts + testScriptsExt + elif len(opts) == 0 or (len(opts) == 1 and "-win" in opts): + test_list = testScripts + else: + for t in testScripts + testScriptsExt: + if t in opts or re.sub(".py$", "", t) in opts: + test_list.append(t) + + if print_help: + # Help should be the same for all scripts, so just + # call the first and exit + subprocess.check_call(RPC_TESTS_DIR + test_list[0] + ' -h', shell=True) + sys.exit(0) + coverage = None if ENABLE_COVERAGE: coverage = RPCCoverage() print("Initializing coverage directory at %s\n" % coverage.dir) - - rpcTestDir = buildDir + '/qa/rpc-tests/' - run_extended = '-extended' in opts - cov_flag = coverage.flag if coverage else '' - flags = " --srcdir %s/src %s %s" % (buildDir, cov_flag, passOn) + flags = " --srcdir %s/src %s %s" % (BUILDDIR, coverage.flag if coverage else '', passon_args) #Run Tests - for i in range(len(testScripts)): - if (len(opts) == 0 - or (len(opts) == 1 and "-win" in opts ) - or run_extended - or testScripts[i] in opts - or re.sub(".py$", "", testScripts[i]) in opts ): - - print("Running testscript %s%s%s ..." % (bold[1], testScripts[i], bold[0])) - time0 = time.time() - subprocess.check_call( - rpcTestDir + testScripts[i] + flags, shell=True) - print("Duration: %s s\n" % (int(time.time() - time0))) - - # exit if help is called so we print just one set of - # instructions - p = re.compile(" -h| --help") - if p.match(passOn): - sys.exit(0) - - # Run Extended Tests - for i in range(len(testScriptsExt)): - if (run_extended or testScriptsExt[i] in opts - or re.sub(".py$", "", testScriptsExt[i]) in opts): - - print( - "Running 2nd level testscript " - + "%s%s%s ..." % (bold[1], testScriptsExt[i], bold[0])) + for t in test_list: + print("Running testscript %s%s%s ..." % (BOLD[1], t, BOLD[0])) time0 = time.time() subprocess.check_call( - rpcTestDir + testScriptsExt[i] + flags, shell=True) + RPC_TESTS_DIR + t + flags, shell=True) print("Duration: %s s\n" % (int(time.time() - time0))) if coverage: diff --git a/qa/rpc-tests/test_framework/test_framework.py b/qa/rpc-tests/test_framework/test_framework.py index ed12e1efb6d1a..103d9a068aa3a 100755 --- a/qa/rpc-tests/test_framework/test_framework.py +++ b/qa/rpc-tests/test_framework/test_framework.py @@ -115,7 +115,7 @@ def main(self): if self.options.trace_rpc: import logging - logging.basicConfig(level=logging.DEBUG) + logging.basicConfig(level=logging.DEBUG, stream=sys.stdout) if self.options.coveragedir: enable_coverage(self.options.coveragedir) @@ -148,6 +148,8 @@ def main(self): except Exception as e: print("Unexpected exception caught during testing: " + repr(e)) traceback.print_tb(sys.exc_info()[2]) + except KeyboardInterrupt as e: + print("Exiting after " + repr(e)) if not self.options.noshutdown: print("Stopping nodes") diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index ea3931cef3614..4c129b78b5434 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -28,6 +28,13 @@ COVERAGE_DIR = None +# The maximum number of nodes a single test can spawn +MAX_NODES = 8 +# Don't assign rpc or p2p ports lower than this +PORT_MIN = 11000 +# The number of ports to "reserve" for p2p and rpc, each +PORT_RANGE = 5000 + #Set Mocktime default to OFF. #MOCKTIME is only needed for scripts that use the #cached version of the blockchain. If the cached @@ -82,9 +89,11 @@ def get_rpc_proxy(url, node_number, timeout=None): def p2p_port(n): - return 11000 + n + os.getpid()%999 + assert(n <= MAX_NODES) + return PORT_MIN + n + (MAX_NODES * os.getpid()) % (PORT_RANGE - 1 - MAX_NODES) + def rpc_port(n): - return 12000 + n + os.getpid()%999 + return PORT_MIN + PORT_RANGE + n + (MAX_NODES * os.getpid()) % (PORT_RANGE -1 - MAX_NODES) def check_json_precision(): """Make sure json library being used does not lose precision converting BTC values""" @@ -292,8 +301,8 @@ def start_nodes(num_nodes, dirname, extra_args=None, rpchost=None, binary=None): """ Start multiple bitcoinds, return RPC connections to them """ - if extra_args is None: extra_args = [ None for i in range(num_nodes) ] - if binary is None: binary = [ None for i in range(num_nodes) ] + if extra_args is None: extra_args = [ None for _ in range(num_nodes) ] + if binary is None: binary = [ None for _ in range(num_nodes) ] rpcs = [] try: for i in range(num_nodes): diff --git a/qa/rpc-tests/walletbackup.py b/qa/rpc-tests/walletbackup.py index 418f3103e3ad7..c3d53669c9fa4 100755 --- a/qa/rpc-tests/walletbackup.py +++ b/qa/rpc-tests/walletbackup.py @@ -37,7 +37,7 @@ from test_framework.util import * from random import randint import logging -logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.INFO) +logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO, stream=sys.stdout) class WalletBackupTest(BitcoinTestFramework): From 2222dae6e31c433f83aa9fd0e8f028cbee59199b Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sat, 30 Apr 2016 00:03:06 +0200 Subject: [PATCH 0273/1802] [qa] Update README.md --- qa/README.md | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/qa/README.md b/qa/README.md index 3e0a526d1306f..c7e574ff70ef4 100644 --- a/qa/README.md +++ b/qa/README.md @@ -19,15 +19,25 @@ sudo apt-get install python3-zmq Running tests ============= -You can run any single test by calling `qa/pull-tester/rpc-tests.py `. +You can run any single test by calling -Or you can run any combination of tests by calling `qa/pull-tester/rpc-tests.py ...` + qa/pull-tester/rpc-tests.py -Run the regression test suite with `qa/pull-tester/rpc-tests.py` +Or you can run any combination of tests by calling -Run all possible tests with `qa/pull-tester/rpc-tests.py -extended` + qa/pull-tester/rpc-tests.py ... -Possible options: +Run the regression test suite with + + qa/pull-tester/rpc-tests.py + +Run all possible tests with + + qa/pull-tester/rpc-tests.py -extended + +If you want to create a basic coverage report for the rpc test suite, append `--coverage`. + +Possible options, which apply to each individual test run: ``` -h, --help show this help message and exit From fafb33cdefd2d8ce065263978075d26a1672b630 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sat, 30 Apr 2016 14:55:31 +0200 Subject: [PATCH 0274/1802] [qa] Stop other nodes, even when one fails to stop --- qa/rpc-tests/test_framework/util.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index 4c129b78b5434..6dc685ea1b46f 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -16,6 +16,7 @@ from base64 import b64encode from decimal import Decimal, ROUND_DOWN import json +import http.client import random import shutil import subprocess @@ -316,13 +317,19 @@ def log_filename(dirname, n_node, logname): return os.path.join(dirname, "node"+str(n_node), "regtest", logname) def stop_node(node, i): - node.stop() + try: + node.stop() + except http.client.CannotSendRequest as e: + print("WARN: Unable to stop node: " + repr(e)) bitcoind_processes[i].wait() del bitcoind_processes[i] def stop_nodes(nodes): for node in nodes: - node.stop() + try: + node.stop() + except http.client.CannotSendRequest as e: + print("WARN: Unable to stop node: " + repr(e)) del nodes[:] # Emptying array closes connections as a side effect def set_node_times(nodes, t): From addb9d2a092b4fd0384d4ff82e9607e5411eab97 Mon Sep 17 00:00:00 2001 From: instagibbs Date: Fri, 6 May 2016 12:53:23 -0400 Subject: [PATCH 0275/1802] Remove state arg from ReconsiderBlock --- src/main.cpp | 2 +- src/main.h | 2 +- src/rpc/blockchain.cpp | 8 +++----- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 92a38f230fbdd..9489bb1c46170 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3011,7 +3011,7 @@ bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, C return true; } -bool ReconsiderBlock(CValidationState& state, CBlockIndex *pindex) { +bool ReconsiderBlock(CBlockIndex *pindex) { AssertLockHeld(cs_main); int nHeight = pindex->nHeight; diff --git a/src/main.h b/src/main.h index bdf7f5a6874c5..e48cebecb37cb 100644 --- a/src/main.h +++ b/src/main.h @@ -464,7 +464,7 @@ CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& loc bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex); /** Remove invalidity status from a block and its descendants. */ -bool ReconsiderBlock(CValidationState& state, CBlockIndex *pindex); +bool ReconsiderBlock(CBlockIndex *pindex); /** The currently-connected chain of blocks (protected by cs_main). */ extern CChain chainActive; diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 6960415e2e7d3..d221012afad33 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -973,7 +973,6 @@ UniValue reconsiderblock(const UniValue& params, bool fHelp) std::string strHash = params[0].get_str(); uint256 hash(uint256S(strHash)); - CValidationState state; { LOCK(cs_main); @@ -981,12 +980,11 @@ UniValue reconsiderblock(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); CBlockIndex* pblockindex = mapBlockIndex[hash]; - ReconsiderBlock(state, pblockindex); + ReconsiderBlock(pblockindex); } - if (state.IsValid()) { - ActivateBestChain(state, Params()); - } + CValidationState state; + ActivateBestChain(state, Params()); if (!state.IsValid()) { throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); From db18ab28c7a74bb289bfe6a5f9a4a9f963f71c0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Fri, 6 May 2016 11:00:01 +0200 Subject: [PATCH 0276/1802] Reenable multithread scheduler test. --- src/test/scheduler_tests.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/test/scheduler_tests.cpp b/src/test/scheduler_tests.cpp index 9acd0e2430a30..aa12dfbd54f8f 100644 --- a/src/test/scheduler_tests.cpp +++ b/src/test/scheduler_tests.cpp @@ -40,7 +40,6 @@ static void MicroSleep(uint64_t n) #endif } -#if 0 /* Disabled for now because there is a race condition issue in this test - see #6540 */ BOOST_AUTO_TEST_CASE(manythreads) { seed_insecure_rand(false); @@ -116,6 +115,5 @@ BOOST_AUTO_TEST_CASE(manythreads) } BOOST_CHECK_EQUAL(counterSum, 200); } -#endif BOOST_AUTO_TEST_SUITE_END() From 166e4b0dfa283fbdedc9a6a1e83296500c853a31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Fri, 6 May 2016 11:01:51 +0200 Subject: [PATCH 0277/1802] Notify other serviceQueue thread we are finished to prevent deadlocks. --- src/scheduler.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/scheduler.cpp b/src/scheduler.cpp index 184ddc28abbff..52777b61f96c8 100644 --- a/src/scheduler.cpp +++ b/src/scheduler.cpp @@ -79,6 +79,7 @@ void CScheduler::serviceQueue() } } --nThreadsServicingQueue; + newTaskScheduled.notify_one(); } void CScheduler::stop(bool drain) From fad336648c848c7a4b3e32bae68ea9a22f97e668 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 8 May 2016 14:09:49 +0200 Subject: [PATCH 0278/1802] [qa] pull-tester: Adjust comment --- qa/pull-tester/rpc-tests.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index e8434b4a6059a..c6f91f8cb3342 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -172,8 +172,7 @@ def runtests(): test_list.append(t) if print_help: - # Help should be the same for all scripts, so just - # call the first and exit + # Only print help of the first script and exit subprocess.check_call(RPC_TESTS_DIR + test_list[0] + ' -h', shell=True) sys.exit(0) From 0fd599767d2dabf25ac8c3543cb586cfc4b9d816 Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Mon, 9 May 2016 00:15:12 -0700 Subject: [PATCH 0279/1802] Fix insanity of CWalletDB::WriteTx and CWalletTx::WriteToDisk --- src/wallet/wallet.cpp | 14 ++++---------- src/wallet/wallet.h | 2 -- src/wallet/walletdb.cpp | 10 +++++----- src/wallet/walletdb.h | 2 +- 4 files changed, 10 insertions(+), 18 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 29d7138547bd1..d6895b80f53bc 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -729,7 +729,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD // Write to disk if (fInsertedNew || fUpdated) - if (!wtx.WriteToDisk(pwalletdb)) + if (!pwalletdb->WriteTx(wtx)) return false; // Break debit/credit balance caches: @@ -829,7 +829,7 @@ bool CWallet::AbandonTransaction(const uint256& hashTx) wtx.nIndex = -1; wtx.setAbandoned(); wtx.MarkDirty(); - wtx.WriteToDisk(&walletdb); + walletdb.WriteTx(wtx); NotifyTransactionChanged(this, wtx.GetHash(), CT_UPDATED); // Iterate over all its outputs, and mark transactions in the wallet that spend them abandoned too TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(hashTx, 0)); @@ -891,7 +891,7 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx) wtx.nIndex = -1; wtx.hashBlock = hashBlock; wtx.MarkDirty(); - wtx.WriteToDisk(&walletdb); + walletdb.WriteTx(wtx); // Iterate over all its outputs, and mark transactions in the wallet that spend them conflicted too TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(now, 0)); while (iter != mapTxSpends.end() && iter->first.hash == now) { @@ -1186,12 +1186,6 @@ void CWalletTx::GetAccountAmounts(const string& strAccount, CAmount& nReceived, } } - -bool CWalletTx::WriteToDisk(CWalletDB *pwalletdb) -{ - return pwalletdb->WriteTx(GetHash(), *this); -} - /** * Scan the block chain (starting in pindexStart) for transactions * from or to us. If fUpdate is true, found transactions that already @@ -3194,7 +3188,7 @@ bool CWallet::InitLoadWallet() copyTo->fFromMe = copyFrom->fFromMe; copyTo->strFromAccount = copyFrom->strFromAccount; copyTo->nOrderPos = copyFrom->nOrderPos; - copyTo->WriteToDisk(&walletdb); + walletdb.WriteTx(*copyTo); } } } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index c3bd343edd3e7..cc568c3749b7c 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -394,8 +394,6 @@ class CWalletTx : public CMerkleTx bool InMempool() const; bool IsTrusted() const; - bool WriteToDisk(CWalletDB *pwalletdb); - int64_t GetTxTime() const; int GetRequestCount() const; diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index f2b5408e92b5d..48579b2821e8e 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -55,10 +55,10 @@ bool CWalletDB::ErasePurpose(const string& strPurpose) return Erase(make_pair(string("purpose"), strPurpose)); } -bool CWalletDB::WriteTx(uint256 hash, const CWalletTx& wtx) +bool CWalletDB::WriteTx(const CWalletTx& wtx) { nWalletDBUpdated++; - return Write(std::make_pair(std::string("tx"), hash), wtx); + return Write(std::make_pair(std::string("tx"), wtx.GetHash()), wtx); } bool CWalletDB::EraseTx(uint256 hash) @@ -291,7 +291,7 @@ DBErrors CWalletDB::ReorderTransactions(CWallet* pwallet) if (pwtx) { - if (!WriteTx(pwtx->GetHash(), *pwtx)) + if (!WriteTx(*pwtx)) return DB_LOAD_FAIL; } else @@ -315,7 +315,7 @@ DBErrors CWalletDB::ReorderTransactions(CWallet* pwallet) // Since we're changing the order, write it back if (pwtx) { - if (!WriteTx(pwtx->GetHash(), *pwtx)) + if (!WriteTx(*pwtx)) return DB_LOAD_FAIL; } else @@ -698,7 +698,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet) pwallet->nTimeFirstKey = 1; // 0 would be considered 'no value' BOOST_FOREACH(uint256 hash, wss.vWalletUpgrade) - WriteTx(hash, pwallet->mapWallet[hash]); + WriteTx(pwallet->mapWallet[hash]); // Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc: if (wss.fIsEncrypted && (wss.nFileVersion == 40000 || wss.nFileVersion == 50000)) diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index fe6c366343599..5345c0907e9cd 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -87,7 +87,7 @@ class CWalletDB : public CDB bool WritePurpose(const std::string& strAddress, const std::string& purpose); bool ErasePurpose(const std::string& strAddress); - bool WriteTx(uint256 hash, const CWalletTx& wtx); + bool WriteTx(const CWalletTx& wtx); bool EraseTx(uint256 hash); bool WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata &keyMeta); From 65fee8e699eb458291810e2d70cfa904d994fecf Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 9 May 2016 12:08:56 +0200 Subject: [PATCH 0280/1802] test: Revert fatal-ness of missing python-zmq It looks like travis is using the `travis.yml` from the branch, but runs the test script from the branch merged into master. This causes pull requests created before the QA tests python 3 transition to fail. This temporarily reverts fa05e22e919b7e2e816606f0c0d3dea1bd325bfd (#7851). It can be restored when this is no longer an issue. --- qa/pull-tester/rpc-tests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index 15153b7f586fc..01c2736e6693a 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -82,9 +82,9 @@ try: import zmq except ImportError as e: - print("ERROR: \"import zmq\" failed. Set ENABLE_ZMQ=0 or " \ + print("WARNING: \"import zmq\" failed. Set ENABLE_ZMQ=0 or " \ "to run zmq tests, see dependency info in /qa/README.md.") - raise e + ENABLE_ZMQ=0 #Tests testScripts = [ From fe80102d3320c973b34daa245b3e41fb38413223 Mon Sep 17 00:00:00 2001 From: Matthew English Date: Mon, 9 May 2016 14:00:28 +0200 Subject: [PATCH 0281/1802] changing "(tests are) automatically run" to correspond to the earlier instance of "run automatically (on the build server)" --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 85b1985560c8f..8e816e7a43fa4 100644 --- a/README.md +++ b/README.md @@ -57,8 +57,7 @@ There are also [regression and integration tests](/qa) of the RPC interface, wri in Python, that are run automatically on the build server. These tests can be run (if the [test dependencies](/qa) are installed) with: `qa/pull-tester/rpc-tests.py` -The Travis CI system makes sure that every pull request is built for Windows -and Linux, OS X, and that unit and sanity tests are automatically run. +The Travis CI system makes sure that every pull request is built for Windows, Linux, and OS X, and that unit/sanity tests are run automatically. ### Manual Quality Assurance (QA) Testing From 5ea450834ed3abae9d85deae336ed65111e02906 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 6 May 2016 12:40:12 +0200 Subject: [PATCH 0282/1802] Autofind rpc tests --srcdir --- qa/rpc-tests/test_framework/test_framework.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qa/rpc-tests/test_framework/test_framework.py b/qa/rpc-tests/test_framework/test_framework.py index ed12e1efb6d1a..0b6d1b6abc91b 100755 --- a/qa/rpc-tests/test_framework/test_framework.py +++ b/qa/rpc-tests/test_framework/test_framework.py @@ -102,7 +102,7 @@ def main(self): help="Leave bitcoinds and test.* datadir on exit or error") parser.add_option("--noshutdown", dest="noshutdown", default=False, action="store_true", help="Don't stop bitcoinds after the test execution") - parser.add_option("--srcdir", dest="srcdir", default="../../src", + parser.add_option("--srcdir", dest="srcdir", default=os.path.normpath(os.path.dirname(os.path.realpath(__file__))+"/../../../src"), help="Source directory containing bitcoind/bitcoin-cli (default: %default)") parser.add_option("--tmpdir", dest="tmpdir", default=tempfile.mkdtemp(prefix="test"), help="Root directory for datadirs") From 326231611bda6808b579ab7286e471c36f62e98c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chirag=20Dav=C3=A9?= Date: Wed, 4 May 2016 21:40:28 -0700 Subject: [PATCH 0283/1802] fReopenDebugLog and fRequestShutdown should be type sig_atomic_t This allows access as an atomic variable in the presence of async interrupts. See issue #7433 for more details fixes: #7433 --- src/init.cpp | 2 +- src/util.cpp | 2 +- src/util.h | 6 +++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index b06f448a001cf..a9b3f88a32b8f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -125,7 +125,7 @@ static const char* FEE_ESTIMATES_FILENAME="fee_estimates.dat"; // shutdown thing. // -volatile bool fRequestShutdown = false; +volatile sig_atomic_t fRequestShutdown = false; void StartShutdown() { diff --git a/src/util.cpp b/src/util.cpp index 00b75fbdbe38e..579be338e617c 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -113,7 +113,7 @@ string strMiscWarning; bool fLogTimestamps = DEFAULT_LOGTIMESTAMPS; bool fLogTimeMicros = DEFAULT_LOGTIMEMICROS; bool fLogIPs = DEFAULT_LOGIPS; -volatile bool fReopenDebugLog = false; +volatile sig_atomic_t fReopenDebugLog = false; CTranslationInterface translationInterface; /** Init OpenSSL library multithreading support */ diff --git a/src/util.h b/src/util.h index ac099f11845d3..33db0f9e4acda 100644 --- a/src/util.h +++ b/src/util.h @@ -28,6 +28,10 @@ #include #include +#ifndef WIN32 +#include +#endif + static const bool DEFAULT_LOGTIMEMICROS = false; static const bool DEFAULT_LOGIPS = false; static const bool DEFAULT_LOGTIMESTAMPS = true; @@ -50,7 +54,7 @@ extern std::string strMiscWarning; extern bool fLogTimestamps; extern bool fLogTimeMicros; extern bool fLogIPs; -extern volatile bool fReopenDebugLog; +extern volatile sig_atomic_t fReopenDebugLog; extern CTranslationInterface translationInterface; extern const char * const BITCOIN_CONF_FILENAME; From 657e07efa34ffe9d8614a618e00452c9ee7c0e0d Mon Sep 17 00:00:00 2001 From: instagibbs Date: Mon, 9 May 2016 11:26:37 -0400 Subject: [PATCH 0284/1802] Rename ReconsiderBlock func to reflect real behavior --- src/main.cpp | 2 +- src/main.h | 2 +- src/rpc/blockchain.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 9489bb1c46170..11eaa055d71c9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3011,7 +3011,7 @@ bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, C return true; } -bool ReconsiderBlock(CBlockIndex *pindex) { +bool ResetBlockFailureFlags(CBlockIndex *pindex) { AssertLockHeld(cs_main); int nHeight = pindex->nHeight; diff --git a/src/main.h b/src/main.h index e48cebecb37cb..ebbd12c8c39c2 100644 --- a/src/main.h +++ b/src/main.h @@ -464,7 +464,7 @@ CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& loc bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex); /** Remove invalidity status from a block and its descendants. */ -bool ReconsiderBlock(CBlockIndex *pindex); +bool ResetBlockFailureFlags(CBlockIndex *pindex); /** The currently-connected chain of blocks (protected by cs_main). */ extern CChain chainActive; diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index d221012afad33..cf3c73c4dfef6 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -980,7 +980,7 @@ UniValue reconsiderblock(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); CBlockIndex* pblockindex = mapBlockIndex[hash]; - ReconsiderBlock(pblockindex); + ResetBlockFailureFlags(pblockindex); } CValidationState state; From fa494dec79b9d469b7eb38d2f0b8cf9832cdc398 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Fri, 29 Apr 2016 12:51:15 +0200 Subject: [PATCH 0285/1802] [qa] pull-tester: Run rpc test in parallel --- qa/README.md | 3 ++ qa/pull-tester/rpc-tests.py | 92 +++++++++++++++++++++++++++++++----- qa/rpc-tests/create_cache.py | 23 +++++++++ 3 files changed, 105 insertions(+), 13 deletions(-) create mode 100755 qa/rpc-tests/create_cache.py diff --git a/qa/README.md b/qa/README.md index c7e574ff70ef4..7489eb5130ac0 100644 --- a/qa/README.md +++ b/qa/README.md @@ -35,6 +35,9 @@ Run all possible tests with qa/pull-tester/rpc-tests.py -extended +By default, tests will be run in parallel if you want to specify how many +tests should be run in parallel, append `-paralell=n` (default n=4). + If you want to create a basic coverage report for the rpc test suite, append `--coverage`. Possible options, which apply to each individual test run: diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index 10c3799b86c25..f926398d58259 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -53,10 +53,12 @@ #Create a set to store arguments and create the passon string opts = set() -passon_args = "" +passon_args = [] PASSON_REGEX = re.compile("^--") +PARALLEL_REGEX = re.compile('^-parallel=') print_help = False +run_parallel = 4 for arg in sys.argv[1:]: if arg == "--help" or arg == "-h" or arg == "-?": @@ -65,7 +67,9 @@ if arg == '--coverage': ENABLE_COVERAGE = 1 elif PASSON_REGEX.match(arg): - passon_args += " " + arg + passon_args.append(arg) + elif PARALLEL_REGEX.match(arg): + run_parallel = int(arg.split(sep='=', maxsplit=1)[1]) else: opts.add(arg) @@ -96,6 +100,7 @@ #Tests testScripts = [ + 'walletbackup.py', 'bip68-112-113-p2p.py', 'wallet.py', 'listtransactions.py', @@ -116,7 +121,6 @@ 'merkle_blocks.py', 'fundrawtransaction.py', 'signrawtransactions.py', - 'walletbackup.py', 'nodehandling.py', 'reindex.py', 'decodescript.py', @@ -131,7 +135,7 @@ 'abandonconflict.py', 'p2p-versionbits-warning.py', 'importprunedfunds.py', - 'signmessages.py' + 'signmessages.py', ] if ENABLE_ZMQ: testScripts.append('zmq_test.py') @@ -160,6 +164,7 @@ 'pruning.py', # leave pruning last as it takes a REALLY long time ] + def runtests(): test_list = [] if '-extended' in opts: @@ -173,7 +178,7 @@ def runtests(): if print_help: # Only print help of the first script and exit - subprocess.check_call(RPC_TESTS_DIR + test_list[0] + ' -h', shell=True) + subprocess.check_call((RPC_TESTS_DIR + test_list[0]).split() + ['-h']) sys.exit(0) coverage = None @@ -181,15 +186,34 @@ def runtests(): if ENABLE_COVERAGE: coverage = RPCCoverage() print("Initializing coverage directory at %s\n" % coverage.dir) - flags = " --srcdir %s/src %s %s" % (BUILDDIR, coverage.flag if coverage else '', passon_args) + flags = ["--srcdir=%s/src" % BUILDDIR] + passon_args + if coverage: + flags.append(coverage.flag) + + if len(test_list) > 1: + # Populate cache + subprocess.check_output([RPC_TESTS_DIR + 'create_cache.py'] + flags) #Run Tests - for t in test_list: - print("Running testscript %s%s%s ..." % (BOLD[1], t, BOLD[0])) - time0 = time.time() - subprocess.check_call( - RPC_TESTS_DIR + t + flags, shell=True) - print("Duration: %s s\n" % (int(time.time() - time0))) + max_len_name = len(max(test_list, key=len)) + time_sum = 0 + time0 = time.time() + job_queue = RPCTestHandler(run_parallel, test_list, flags) + results = BOLD[1] + "%s | %s | %s\n\n" % ("TEST".ljust(max_len_name), "PASSED", "DURATION") + BOLD[0] + all_passed = True + for _ in range(len(test_list)): + (name, stdout, stderr, passed, duration) = job_queue.get_next() + all_passed = all_passed and passed + time_sum += duration + + print('\n' + BOLD[1] + name + BOLD[0] + ":") + print(stdout) + print('stderr:\n' if not stderr == '' else '', stderr) + results += "%s | %s | %s s\n" % (name.ljust(max_len_name), str(passed).ljust(6), duration) + print("Pass: %s%s%s, Duration: %s s\n" % (BOLD[1], passed, BOLD[0], duration)) + results += BOLD[1] + "\n%s | %s | %s s (accumulated)" % ("ALL".ljust(max_len_name), str(all_passed).ljust(6), time_sum) + BOLD[0] + print(results) + print("\nRuntime: %s s" % (int(time.time() - time0))) if coverage: coverage.report_rpc_coverage() @@ -197,6 +221,48 @@ def runtests(): print("Cleaning up coverage data") coverage.cleanup() + sys.exit(not all_passed) + + +class RPCTestHandler: + """ + Trigger the testscrips passed in via the list. + """ + + def __init__(self, num_tests_parallel, test_list=None, flags=None): + assert(num_tests_parallel >= 1) + self.num_jobs = num_tests_parallel + self.test_list = test_list + self.flags = flags + self.num_running = 0 + self.jobs = [] + + def get_next(self): + while self.num_running < self.num_jobs and self.test_list: + # Add tests + self.num_running += 1 + t = self.test_list.pop(0) + self.jobs.append((t, + time.time(), + subprocess.Popen((RPC_TESTS_DIR + t).split() + self.flags, + universal_newlines=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE))) + if not self.jobs: + raise IndexError('%s from empty list' % __name__) + while True: + # Return first proc that finishes + time.sleep(.5) + for j in self.jobs: + (name, time0, proc) = j + if proc.poll() is not None: + (stdout, stderr) = proc.communicate(timeout=3) + passed = stderr == "" and proc.returncode == 0 + self.num_running -= 1 + self.jobs.remove(j) + return name, stdout, stderr, passed, int(time.time() - time0) + print('.', end='', flush=True) + class RPCCoverage(object): """ @@ -215,7 +281,7 @@ class RPCCoverage(object): """ def __init__(self): self.dir = tempfile.mkdtemp(prefix="coverage") - self.flag = '--coveragedir %s' % self.dir + self.flag = '--coveragedir=%s' % self.dir def report_rpc_coverage(self): """ diff --git a/qa/rpc-tests/create_cache.py b/qa/rpc-tests/create_cache.py new file mode 100755 index 0000000000000..b6161e0917d07 --- /dev/null +++ b/qa/rpc-tests/create_cache.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +# Copyright (c) 2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# +# Helper script to create the cache +# (see BitcoinTestFramework.setup_chain) +# + +from test_framework.test_framework import BitcoinTestFramework + +class CreateCache(BitcoinTestFramework): + + def setup_network(self): + # Don't setup any test nodes + self.options.noshutdown = True + + def run_test(self): + pass + +if __name__ == '__main__': + CreateCache().main() From ccccc591a456f9a8fcf5f8e68a5bacdbbaeb0937 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 9 May 2016 19:55:49 +0200 Subject: [PATCH 0286/1802] [qa] Add option --portseed to test_framework --- qa/pull-tester/rpc-tests.py | 3 ++- qa/rpc-tests/test_framework/test_framework.py | 13 ++++++++----- qa/rpc-tests/test_framework/util.py | 10 +++++++--- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index f926398d58259..f810f89a5991a 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -242,9 +242,10 @@ def get_next(self): # Add tests self.num_running += 1 t = self.test_list.pop(0) + port_seed = ["--portseed=%s" % len(self.test_list)] self.jobs.append((t, time.time(), - subprocess.Popen((RPC_TESTS_DIR + t).split() + self.flags, + subprocess.Popen((RPC_TESTS_DIR + t).split() + self.flags + port_seed, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE))) diff --git a/qa/rpc-tests/test_framework/test_framework.py b/qa/rpc-tests/test_framework/test_framework.py index 4e7246309660f..3480de6c6e20c 100755 --- a/qa/rpc-tests/test_framework/test_framework.py +++ b/qa/rpc-tests/test_framework/test_framework.py @@ -5,10 +5,10 @@ # Base class for RPC testing -# Add python-bitcoinrpc to module search path: +import logging +import optparse import os import sys - import shutil import tempfile import traceback @@ -25,8 +25,9 @@ enable_coverage, check_json_precision, initialize_chain_clean, + PortSeed, ) -from .authproxy import AuthServiceProxy, JSONRPCException +from .authproxy import JSONRPCException class BitcoinTestFramework(object): @@ -95,7 +96,6 @@ def join_network(self): self.setup_network(False) def main(self): - import optparse parser = optparse.OptionParser(usage="%prog [options]") parser.add_option("--nocleanup", dest="nocleanup", default=False, action="store_true", @@ -108,18 +108,21 @@ def main(self): help="Root directory for datadirs") parser.add_option("--tracerpc", dest="trace_rpc", default=False, action="store_true", help="Print out all RPC calls as they are made") + parser.add_option("--portseed", dest="port_seed", default=os.getpid(), type='int', + help="The seed to use for assigning port numbers (default: current process id)") parser.add_option("--coveragedir", dest="coveragedir", help="Write tested RPC commands into this directory") self.add_options(parser) (self.options, self.args) = parser.parse_args() if self.options.trace_rpc: - import logging logging.basicConfig(level=logging.DEBUG, stream=sys.stdout) if self.options.coveragedir: enable_coverage(self.options.coveragedir) + PortSeed.n = self.options.port_seed + os.environ['PATH'] = self.options.srcdir+":"+self.options.srcdir+"/qt:"+os.environ['PATH'] check_json_precision() diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index 6dc685ea1b46f..6784177aaac57 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -8,7 +8,6 @@ # Helpful routines for regression testing # -# Add python-bitcoinrpc to module search path: import os import sys @@ -36,6 +35,11 @@ # The number of ports to "reserve" for p2p and rpc, each PORT_RANGE = 5000 + +class PortSeed: + # Must be initialized with a unique integer for each process + n = None + #Set Mocktime default to OFF. #MOCKTIME is only needed for scripts that use the #cached version of the blockchain. If the cached @@ -91,10 +95,10 @@ def get_rpc_proxy(url, node_number, timeout=None): def p2p_port(n): assert(n <= MAX_NODES) - return PORT_MIN + n + (MAX_NODES * os.getpid()) % (PORT_RANGE - 1 - MAX_NODES) + return PORT_MIN + n + (MAX_NODES * PortSeed.n) % (PORT_RANGE - 1 - MAX_NODES) def rpc_port(n): - return PORT_MIN + PORT_RANGE + n + (MAX_NODES * os.getpid()) % (PORT_RANGE -1 - MAX_NODES) + return PORT_MIN + PORT_RANGE + n + (MAX_NODES * PortSeed.n) % (PORT_RANGE - 1 - MAX_NODES) def check_json_precision(): """Make sure json library being used does not lose precision converting BTC values""" From 00678bdb0aeb296456501f818faaa012a75ce18e Mon Sep 17 00:00:00 2001 From: Warren Togami Date: Mon, 9 May 2016 17:01:33 -0700 Subject: [PATCH 0287/1802] Make failures to connect via Socks5() more informative and less unnecessarily scary. * The "ERROR" was printed far too often during normal operation for what was not an error. * Makes the Socks5() connect failure similar to the IP connect failure in debug.log. Before: `2016-05-09 00:15:00 ERROR: Proxy error: host unreachable` After: `2016-05-09 00:15:00 Socks5() connect to t6xj6wilh4ytvcs7.onion:18333 failed: host unreachable"` --- src/netbase.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/netbase.cpp b/src/netbase.cpp index b44a8b16e20cc..6e81fdcac29b6 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -379,19 +379,21 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials return error("Proxy failed to accept request"); } if (pchRet2[1] != 0x00) { + // Failures to connect to a peer that are not proxy errors CloseSocket(hSocket); switch (pchRet2[1]) { - case 0x01: return error("Proxy error: general failure"); - case 0x02: return error("Proxy error: connection not allowed"); - case 0x03: return error("Proxy error: network unreachable"); - case 0x04: return error("Proxy error: host unreachable"); - case 0x05: return error("Proxy error: connection refused"); - case 0x06: return error("Proxy error: TTL expired"); - case 0x07: return error("Proxy error: protocol error"); - case 0x08: return error("Proxy error: address type not supported"); - default: return error("Proxy error: unknown"); + case 0x01: LogPrintf("Socks5() connect to %s:%d failed: general failure\n", strDest, port); break; + case 0x02: LogPrintf("Socks5() connect to %s:%d failed: connection not allowed\n", strDest, port); break; + case 0x03: LogPrintf("Socks5() connect to %s:%d failed: network unreachable\n", strDest, port); break; + case 0x04: LogPrintf("Socks5() connect to %s:%d failed: host unreachable\n", strDest, port); break; + case 0x05: LogPrintf("Socks5() connect to %s:%d failed: connection refused\n", strDest, port); break; + case 0x06: LogPrintf("Socks5() connect to %s:%d failed: TTL expired\n", strDest, port); break; + case 0x07: LogPrintf("Socks5() connect to %s:%d failed: protocol error\n", strDest, port); break; + case 0x08: LogPrintf("Socks5() connect to %s:%d failed: address type not supported\n", strDest, port); break; + default: LogPrintf("Socks5() connect to %s:%d failed: unknown\n", strDest, port); } + return false; } if (pchRet2[2] != 0x00) { CloseSocket(hSocket); From 0d9af79e5084dc2fb6a73abd9dd113dda4e993b4 Mon Sep 17 00:00:00 2001 From: Warren Togami Date: Mon, 9 May 2016 17:35:14 -0700 Subject: [PATCH 0288/1802] SOCKS5 connecting and connected messages with -debug=net. They were too noisy and not necessary for normal operation. --- src/netbase.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/netbase.cpp b/src/netbase.cpp index 6e81fdcac29b6..5ab12c9a7c43e 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -294,7 +294,7 @@ struct ProxyCredentials /** Connect using SOCKS5 (as described in RFC1928) */ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials *auth, SOCKET& hSocket) { - LogPrintf("SOCKS5 connecting %s\n", strDest); + LogPrint("net", "SOCKS5 connecting %s\n", strDest); if (strDest.size() > 255) { CloseSocket(hSocket); return error("Hostname too long"); @@ -425,7 +425,7 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials CloseSocket(hSocket); return error("Error reading from proxy"); } - LogPrintf("SOCKS5 connected %s\n", strDest); + LogPrint("net", "SOCKS5 connected %s\n", strDest); return true; } From 3902a291abecad4da25d496f0e3e2b45f43a7947 Mon Sep 17 00:00:00 2001 From: Tyler Hardin Date: Mon, 9 May 2016 22:26:57 -0400 Subject: [PATCH 0289/1802] Qt: Delay user confirmation of send I made a subclass of QMessageBox that disables the send button in exec() and starts a timer that calls a slot to re-enable it after a configurable delay. It also has a countdown in the send/yes button while it is disabled to hint to the user why the send button is disabled (and that it is actually supposed to be disabled). --- src/qt/sendcoinsdialog.cpp | 53 +++++++++++++++++++++++++++++++++++--- src/qt/sendcoinsdialog.h | 22 ++++++++++++++++ 2 files changed, 71 insertions(+), 4 deletions(-) diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 780a6c9709ed8..54ebd25833827 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -26,6 +26,9 @@ #include #include #include +#include + +#define SEND_CONFIRM_DELAY 3 SendCoinsDialog::SendCoinsDialog(const PlatformStyle *platformStyle, QWidget *parent) : QDialog(parent), @@ -311,10 +314,10 @@ void SendCoinsDialog::on_sendButton_clicked() questionString.append(QString("
(=%2)
") .arg(alternativeUnits.join(" " + tr("or") + "
"))); - QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm send coins"), - questionString.arg(formatted.join("
")), - QMessageBox::Yes | QMessageBox::Cancel, - QMessageBox::Cancel); + SendConfirmationDialog confirmationDialog(tr("Confirm send coins"), + questionString.arg(formatted.join("
")), SEND_CONFIRM_DELAY, this); + confirmationDialog.exec(); + QMessageBox::StandardButton retval = (QMessageBox::StandardButton)confirmationDialog.result(); if(retval != QMessageBox::Yes) { @@ -828,3 +831,45 @@ void SendCoinsDialog::coinControlUpdateLabels() ui->labelCoinControlInsuffFunds->hide(); } } + +SendConfirmationDialog::SendConfirmationDialog(const QString &title, const QString &text, int secDelay, + QWidget *parent) : + QMessageBox(QMessageBox::Question, title, text, QMessageBox::Yes | QMessageBox::Cancel, parent), secDelay(secDelay) +{ + setDefaultButton(QMessageBox::Cancel); + yesButton = button(QMessageBox::Yes); + updateYesButton(); + connect(&countDownTimer, SIGNAL(timeout()), this, SLOT(countDown())); +} + +int SendConfirmationDialog::exec() +{ + updateYesButton(); + countDownTimer.start(1000); + return QMessageBox::exec(); +} + +void SendConfirmationDialog::countDown() +{ + secDelay--; + updateYesButton(); + + if(secDelay <= 0) + { + countDownTimer.stop(); + } +} + +void SendConfirmationDialog::updateYesButton() +{ + if(secDelay > 0) + { + yesButton->setEnabled(false); + yesButton->setText(tr("Yes") + " (" + QString::number(secDelay) + ")"); + } + else + { + yesButton->setEnabled(true); + yesButton->setText(tr("Yes")); + } +} diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h index ec171734faa20..be4f2ee44ba03 100644 --- a/src/qt/sendcoinsdialog.h +++ b/src/qt/sendcoinsdialog.h @@ -8,7 +8,9 @@ #include "walletmodel.h" #include +#include #include +#include class ClientModel; class OptionsModel; @@ -100,4 +102,24 @@ private Q_SLOTS: void message(const QString &title, const QString &message, unsigned int style); }; + + +class SendConfirmationDialog : public QMessageBox +{ + Q_OBJECT + +public: + SendConfirmationDialog(const QString &title, const QString &text, int secDelay = 0, QWidget *parent = 0); + int exec(); + +private Q_SLOTS: + void countDown(); + void updateYesButton(); + +private: + QAbstractButton *yesButton; + QTimer countDownTimer; + int secDelay; +}; + #endif // BITCOIN_QT_SENDCOINSDIALOG_H From 2d5603c7e8316c3051304ed22553da64d686df56 Mon Sep 17 00:00:00 2001 From: Tyler Hardin Date: Mon, 9 May 2016 22:46:33 -0400 Subject: [PATCH 0290/1802] Qt: Sort transactions by date Conflicted transactions can get stuck at the top. This fixes that. --- src/qt/overviewpage.cpp | 2 +- src/qt/transactionview.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index d577345e49097..6a0404cbf702f 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -219,7 +219,7 @@ void OverviewPage::setWalletModel(WalletModel *model) filter->setDynamicSortFilter(true); filter->setSortRole(Qt::EditRole); filter->setShowInactive(false); - filter->sort(TransactionTableModel::Status, Qt::DescendingOrder); + filter->sort(TransactionTableModel::Date, Qt::DescendingOrder); ui->listTransactions->setModel(filter); ui->listTransactions->setModelColumn(TransactionTableModel::ToAddress); diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index eb6111e682e9f..199a7b2d77b1b 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -203,7 +203,7 @@ void TransactionView::setModel(WalletModel *model) transactionView->setSelectionBehavior(QAbstractItemView::SelectRows); transactionView->setSelectionMode(QAbstractItemView::ExtendedSelection); transactionView->setSortingEnabled(true); - transactionView->sortByColumn(TransactionTableModel::Status, Qt::DescendingOrder); + transactionView->sortByColumn(TransactionTableModel::Date, Qt::DescendingOrder); transactionView->verticalHeader()->hide(); transactionView->setColumnWidth(TransactionTableModel::Status, STATUS_COLUMN_WIDTH); From 90963e53707cf244e6a2a804341e9280628b0c34 Mon Sep 17 00:00:00 2001 From: fanquake Date: Tue, 10 May 2016 14:23:49 +0800 Subject: [PATCH 0291/1802] [doc] Add basic git squash example --- CONTRIBUTING.md | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 53d6527d40718..5c1138b812d47 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,13 +17,13 @@ To contribute a patch, the workflow is as follows: - Create topic branch - Commit patches -The project coding conventions in [doc/developer-notes.md](doc/developer-notes.md) must be adhered to. +The project coding conventions in the [developer notes](doc/developer-notes.md) must be adhered to. In general [commits should be atomic](https://en.wikipedia.org/wiki/Atomic_commit#Atomic_commit_convention) and diffs should be easy to read. For this reason do not mix any formatting fixes or code moves with actual code changes. Commit messages should be verbose by default consisting of a short subject line (50 chars max), a blank line and detailed explanatory text as separate paragraph(s); unless the title alone is self-explanatory (like "Corrected typo in main.cpp") then a single title line is sufficient. Commit messages should be helpful to people reading your code in the future, so explain the reasoning for your decisions. Further explanation [here](http://chris.beams.io/posts/git-commit/). -If a particular commit references another issue, please add the reference, for example "refs #1234", or "fixes #4321". Using "fixes or closes" keywords will cause the corresponding issue to be closed when the pull request is merged. +If a particular commit references another issue, please add the reference, for example `refs #1234`, or `fixes #4321`. Using the `fixes` or `closes` keywords will cause the corresponding issue to be closed when the pull request is merged. Please refer to the [Git manual](https://git-scm.com/doc) for more information about Git. @@ -35,13 +35,27 @@ The title of the pull request should be prefixed by the component or area that t Consensus: Add new opcode for BIP-XXXX OP_CHECKAWESOMESIG Net: Automatically create hidden service, listen on Tor Qt: Add feed bump button - Trivial: fix typo + Trivial: Fix typo in main.cpp -If a pull request is specifically not to be considered for merging (yet) please prefix the title with [WIP] or use [Tasks Lists](https://github.com/blog/1375-task-lists-in-gfm-issues-pulls-comments) in the body of the pull request to indicate tasks are pending. +If a pull request is specifically not to be considered for merging (yet) please prefix the title with [WIP] or use [Tasks Lists](https://help.github.com/articles/basic-writing-and-formatting-syntax/#task-lists) in the body of the pull request to indicate tasks are pending. The body of the pull request should contain enough description about what the patch does together with any justification/reasoning. You should include references to any discussions (for example other tickets or mailing list discussions). -At this stage one should expect comments and review from other contributors. You can add more commits to your pull request by committing them locally and pushing to your fork until you have satisfied all feedback. If your pull request is accepted for merging, you may be asked by a maintainer to squash and or rebase your commits before it will be merged. The length of time required for peer review is unpredictable and will vary from patch to patch. +At this stage one should expect comments and review from other contributors. You can add more commits to your pull request by committing them locally and pushing to your fork until you have satisfied all feedback. + +Squashing Commits +--------------------------- +If your pull request is accepted for merging, you may be asked by a maintainer to squash and or [rebase](https://git-scm.com/docs/git-rebase) your commits before it will be merged. The basic squashing workflow is shown below. + + git checkout your_branch_name + git rebase -i HEAD~n + # n is normally the number of commits in the pull + # set commits from 'pick' to 'squash', save and quit + # on the next screen, edit/refine commit messages + # save and quit + git push -f # (force push to GitHub) + +The length of time required for peer review is unpredictable and will vary from pull request to pull request. Pull Request Philosophy @@ -61,7 +75,7 @@ Refactoring is a necessary part of any software project's evolution. The followi There are three categories of refactoring, code only moves, code style fixes, code refactoring. In general refactoring pull requests should not mix these three kinds of activity in order to make refactoring pull requests easy to review and uncontroversial. In all cases, refactoring PRs must not change the behaviour of code within the pull request (bugs must be preserved as is). -Project maintainers aim for a quick turnaround on refactoring pull requests, so where possible keep them short, uncomplex and easy to verify. +Project maintainers aim for a quick turnaround on refactoring pull requests, so where possible keep them short, uncomplex and easy to verify. "Decision Making" Process @@ -69,7 +83,7 @@ Project maintainers aim for a quick turnaround on refactoring pull requests, so The following applies to code changes to the Bitcoin Core project (and related projects such as libsecp256k1), and is not to be confused with overall Bitcoin Network Protocol consensus changes. -Whether a pull request is merged into Bitcoin Core rests with the project merge maintainers and ultimately the project lead. +Whether a pull request is merged into Bitcoin Core rests with the project merge maintainers and ultimately the project lead. Maintainers will take into consideration if a patch is in line with the general principles of the project; meets the minimum standards for inclusion; and will judge the general consensus of contributors. From 3e2c946cfdfdaae4b00793a554157762d1971705 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 10 May 2016 12:53:49 +0200 Subject: [PATCH 0292/1802] init: Move berkeleydb version reporting to wallet Move the version reporting to Wallet::Verify, before starting verification of the wallet. This removes the dependency of init on a specific wallet database library. A further, trivial step towards resolving #7965. --- src/init.cpp | 5 ----- src/wallet/wallet.cpp | 1 + 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index b06f448a001cf..a46cc52a845e9 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -37,9 +37,7 @@ #include "utilmoneystr.h" #include "validationinterface.h" #ifdef ENABLE_WALLET -#include "wallet/db.h" #include "wallet/wallet.h" -#include "wallet/walletdb.h" #endif #include #include @@ -986,9 +984,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (fPrintToDebugLog) OpenDebugLog(); -#ifdef ENABLE_WALLET - LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(0, 0, 0)); -#endif if (!fLogTimestamps) LogPrintf("Startup time: %s\n", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime())); LogPrintf("Default data directory %s\n", GetDefaultDataDir().string()); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 29d7138547bd1..d32fe43ed84f6 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -368,6 +368,7 @@ void CWallet::Flush(bool shutdown) bool CWallet::Verify() { + LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(0, 0, 0)); std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT); LogPrintf("Using wallet %s\n", walletFile); From ac40ed780079861e67d5c026e5026e8cc387eb24 Mon Sep 17 00:00:00 2001 From: error10 Date: Fri, 4 Dec 2015 14:00:18 -0500 Subject: [PATCH 0293/1802] Increase timeout waiting for pruned blk00000.dat In my ever-growing list of test failures, I was seeing this one intermittently. ``` Running 2nd level testscript pruning.py... Initializing test directory /tmp/testY5ypCv Warning! This test requires 4GB of disk space and takes over 30 mins (up to 2 hours) Mining a big blockchain of 995 blocks Check that we haven't started pruning yet because we're below PruneAfterHeight Success Though we're already using more than 550MB, current usage: 587 Mining 25 more blocks should cause the first block file to be pruned Assertion failed: blk00000.dat not pruned when it should be File "/home/error/bitcoinxt-0.11D/qa/rpc-tests/test_framework/test_framework.py", line 118, in main self.run_test() File "/home/error/bitcoinxt-0.11D/qa/rpc-tests/pruning.py", line 272, in run_test self.test_height_min() File "/home/error/bitcoinxt-0.11D/qa/rpc-tests/pruning.py", line 94, in test_height_min raise AssertionError("blk00000.dat not pruned when it should be") Stopping nodes Failed ``` After digging into the test, I found that the code is waiting 10 seconds for blk00000.dat to be deleted, and then throwing this failure if it still exists after 10 seconds. I increased this amount, had the script print the actual time taken, and ran the test a few more times. The time taken ranged between 8 to 12 seconds. So, I feel that this timeout is too short. After changing the timeout to 30 seconds, the test passes consistently. (cherry picked from commit 3469911c89a48dd2fefe4d1c2a0c176256e14ee0) --- qa/rpc-tests/pruning.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qa/rpc-tests/pruning.py b/qa/rpc-tests/pruning.py index 92d33bd20ec3e..eac2272db25c0 100755 --- a/qa/rpc-tests/pruning.py +++ b/qa/rpc-tests/pruning.py @@ -75,7 +75,7 @@ def test_height_min(self): waitstart = time.time() while os.path.isfile(self.prunedir+"blk00000.dat"): time.sleep(0.1) - if time.time() - waitstart > 10: + if time.time() - waitstart > 30: raise AssertionError("blk00000.dat not pruned when it should be") print("Success") From fa72f7d99deeebe8bd088753a9a378170ec71f91 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Tue, 10 May 2016 17:54:34 +0200 Subject: [PATCH 0294/1802] [doc] Remove outdated line from listunspent RPC help, fix typo --- src/wallet/rpcwallet.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 623037e76648b..27596929f1484 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2233,7 +2233,7 @@ UniValue settxfee(const UniValue& params, bool fHelp) "settxfee amount\n" "\nSet the transaction fee per kB. Overwrites the paytxfee parameter.\n" "\nArguments:\n" - "1. amount (numeric or sting, required) The transaction fee in " + CURRENCY_UNIT + "/kB\n" + "1. amount (numeric or string, required) The transaction fee in " + CURRENCY_UNIT + "/kB\n" "\nResult\n" "true|false (boolean) Returns true if successful\n" "\nExamples:\n" @@ -2328,8 +2328,6 @@ UniValue listunspent(const UniValue& params, bool fHelp) "\nReturns array of unspent transaction outputs\n" "with between minconf and maxconf (inclusive) confirmations.\n" "Optionally filter to only include txouts paid to specified addresses.\n" - "Results are an array of Objects, each of which has:\n" - "{txid, vout, scriptPubKey, amount, confirmations}\n" "\nArguments:\n" "1. minconf (numeric, optional, default=1) The minimum confirmations to filter\n" "2. maxconf (numeric, optional, default=9999999) The maximum confirmations to filter\n" From fadd0485922de94720dfe60c859633041d67b22f Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 14 Mar 2016 22:13:04 +0100 Subject: [PATCH 0295/1802] [doc] Link to clang-format in the developer notes --- doc/developer-notes.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/developer-notes.md b/doc/developer-notes.md index 8affb2158a913..add2fb5004d8e 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -5,7 +5,9 @@ Various coding styles have been used during the history of the codebase, and the result is not very consistent. However, we're now trying to converge to a single style, so please use it in new code. Old code will be converted gradually. -- Basic rules specified in src/.clang-format. Use a recent clang-format-3.5 to format automatically. +- Basic rules specified in [src/.clang-format](/src/.clang-format). + Use a recent clang-format to format automatically using one of the [dev scripts] + (/contrib/devtools/README.md#clang-formatpy). - Braces on new lines for namespaces, classes, functions, methods. - Braces on the same line for everything else. - 4 space indentation (no tabs) for every block except namespaces. From fa83a5dbce0b76e78744c9ad5578c93e89b123e5 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Tue, 10 May 2016 17:22:01 +0200 Subject: [PATCH 0296/1802] [qa] wallet: Temporarily disable salvagewallet test --- qa/rpc-tests/wallet.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py index 42ce0a7260fa3..f321f5e90b15e 100755 --- a/qa/rpc-tests/wallet.py +++ b/qa/rpc-tests/wallet.py @@ -306,7 +306,7 @@ def run_test (self): # Check that the txid and balance is found by node1 self.nodes[1].gettransaction(cbTxId) - #check if wallet or blochchain maintenance changes the balance + # check if wallet or blockchain maintenance changes the balance self.sync_all() blocks = self.nodes[0].generate(2) self.sync_all() @@ -318,7 +318,8 @@ def run_test (self): '-reindex', '-zapwallettxes=1', '-zapwallettxes=2', - '-salvagewallet', + # disabled until issue is fixed: https://github.com/bitcoin/bitcoin/issues/7463 + # '-salvagewallet', ] for m in maintenance: print("check " + m) @@ -338,4 +339,4 @@ def run_test (self): assert_equal(len(self.nodes[0].listsinceblock(blocks[1])["transactions"]), 0) if __name__ == '__main__': - WalletTest ().main () + WalletTest().main() From 8b8f87714df8c1e0868e6411c8f09c838ea736ab Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Mon, 18 Apr 2016 17:02:43 -0400 Subject: [PATCH 0297/1802] net: make Ban/Unban/ClearBan functionality consistent - Ban/Unban/ClearBan call uiInterface.BannedListChanged() as necessary - Ban/Unban/ClearBan sync to disk if the operation is user-invoked - Mark node for disconnection automatically when banning - Lock cs_vNodes while setting disconnected - Don't spin in a tight loop while setting disconnected --- src/net.cpp | 44 +++++++++++++++++++++++++++++++------------ src/qt/rpcconsole.cpp | 5 +---- src/rpc/net.cpp | 10 ---------- 3 files changed, 33 insertions(+), 26 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 41e657fba3719..3f953a72d5fad 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -463,9 +463,13 @@ bool CNode::setBannedIsDirty; void CNode::ClearBanned() { - LOCK(cs_setBanned); - setBanned.clear(); - setBannedIsDirty = true; + { + LOCK(cs_setBanned); + setBanned.clear(); + setBannedIsDirty = true; + } + DumpBanlist(); //store banlist to disk + uiInterface.BannedListChanged(); } bool CNode::IsBanned(CNetAddr ip) @@ -516,11 +520,25 @@ void CNode::Ban(const CSubNet& subNet, const BanReason &banReason, int64_t banti } banEntry.nBanUntil = (sinceUnixEpoch ? 0 : GetTime() )+bantimeoffset; - LOCK(cs_setBanned); - if (setBanned[subNet].nBanUntil < banEntry.nBanUntil) - setBanned[subNet] = banEntry; - - setBannedIsDirty = true; + { + LOCK(cs_setBanned); + if (setBanned[subNet].nBanUntil < banEntry.nBanUntil) { + setBanned[subNet] = banEntry; + setBannedIsDirty = true; + } + else + return; + } + uiInterface.BannedListChanged(); + { + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) { + if (subNet.Match((CNetAddr)pnode->addr)) + pnode->fDisconnect = true; + } + } + if(banReason == BanReasonManuallyAdded) + DumpBanlist(); //store banlist to disk immediately if user requested ban } bool CNode::Unban(const CNetAddr &addr) { @@ -529,13 +547,15 @@ bool CNode::Unban(const CNetAddr &addr) { } bool CNode::Unban(const CSubNet &subNet) { - LOCK(cs_setBanned); - if (setBanned.erase(subNet)) { + LOCK(cs_setBanned); + if (!setBanned.erase(subNet)) + return false; setBannedIsDirty = true; - return true; } - return false; + uiInterface.BannedListChanged(); + DumpBanlist(); //store banlist to disk immediately + return true; } void CNode::GetBanned(banmap_t &banMap) diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index d8647d902a0e7..18552f0736acd 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -885,15 +885,13 @@ void RPCConsole::banSelectedNode(int bantime) // Get currently selected peer address QString strNode = GUIUtil::getEntryData(ui->peerWidget, 0, PeerTableModel::Address); // Find possible nodes, ban it and clear the selected node - if (CNode *bannedNode = FindNode(strNode.toStdString())) { + if (FindNode(strNode.toStdString())) { std::string nStr = strNode.toStdString(); std::string addr; int port = 0; SplitHostPort(nStr, port, addr); CNode::Ban(CNetAddr(addr), BanReasonManuallyAdded, bantime); - bannedNode->fDisconnect = true; - DumpBanlist(); clearSelectedNode(); clientModel->getBanTableModel()->refresh(); @@ -912,7 +910,6 @@ void RPCConsole::unbanSelectedNode() if (possibleSubnet.IsValid()) { CNode::Unban(possibleSubnet); - DumpBanlist(); clientModel->getBanTableModel()->refresh(); } } diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 320091b9c4d4d..e09af89656832 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -565,20 +565,12 @@ UniValue setban(const UniValue& params, bool fHelp) absolute = true; isSubnet ? CNode::Ban(subNet, BanReasonManuallyAdded, banTime, absolute) : CNode::Ban(netAddr, BanReasonManuallyAdded, banTime, absolute); - - //disconnect possible nodes - while(CNode *bannedNode = (isSubnet ? FindNode(subNet) : FindNode(netAddr))) - bannedNode->fDisconnect = true; } else if(strCommand == "remove") { if (!( isSubnet ? CNode::Unban(subNet) : CNode::Unban(netAddr) )) throw JSONRPCError(RPC_MISC_ERROR, "Error: Unban failed"); } - - DumpBanlist(); //store banlist to disk - uiInterface.BannedListChanged(); - return NullUniValue; } @@ -624,8 +616,6 @@ UniValue clearbanned(const UniValue& params, bool fHelp) ); CNode::ClearBanned(); - DumpBanlist(); //store banlist to disk - uiInterface.BannedListChanged(); return NullUniValue; } From e9ed6206b32a05547dfa4bfa1e090044ddad7c82 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Mon, 18 Apr 2016 17:59:31 -0400 Subject: [PATCH 0298/1802] net: No need to export DumpBanlist --- src/net.cpp | 40 ++++++++++++++++++++-------------------- src/net.h | 2 -- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 3f953a72d5fad..f5aa6abde85d9 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -422,6 +422,26 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest) return NULL; } +static void DumpBanlist() +{ + CNode::SweepBanned(); // clean unused entries (if bantime has expired) + + if (!CNode::BannedSetIsDirty()) + return; + + int64_t nStart = GetTimeMillis(); + + CBanDB bandb; + banmap_t banmap; + CNode::SetBannedSetDirty(false); + CNode::GetBanned(banmap); + if (!bandb.Write(banmap)) + CNode::SetBannedSetDirty(true); + + LogPrint("net", "Flushed %d banned node ips/subnets to banlist.dat %dms\n", + banmap.size(), GetTimeMillis() - nStart); +} + void CNode::CloseSocketDisconnect() { fDisconnect = true; @@ -2607,26 +2627,6 @@ bool CBanDB::Read(banmap_t& banSet) return true; } -void DumpBanlist() -{ - CNode::SweepBanned(); // clean unused entries (if bantime has expired) - - if (!CNode::BannedSetIsDirty()) - return; - - int64_t nStart = GetTimeMillis(); - - CBanDB bandb; - banmap_t banmap; - CNode::SetBannedSetDirty(false); - CNode::GetBanned(banmap); - if (!bandb.Write(banmap)) - CNode::SetBannedSetDirty(true); - - LogPrint("net", "Flushed %d banned node ips/subnets to banlist.dat %dms\n", - banmap.size(), GetTimeMillis() - nStart); -} - int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds) { return nNow + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5); } diff --git a/src/net.h b/src/net.h index b6ec7bf3e2c28..167dc36a53ad5 100644 --- a/src/net.h +++ b/src/net.h @@ -807,8 +807,6 @@ class CBanDB bool Read(banmap_t& banSet); }; -void DumpBanlist(); - /** Return a timestamp in the future (in microseconds) for exponentially distributed events. */ int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds); From 5d5e7a097a87e0fe6efb5e2d622daadc10c2ad79 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Sat, 16 Apr 2016 14:46:14 -0400 Subject: [PATCH 0299/1802] net: No need to export ConnectNode --- src/net.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/net.h b/src/net.h index 167dc36a53ad5..70df27573ee79 100644 --- a/src/net.h +++ b/src/net.h @@ -83,7 +83,6 @@ CNode* FindNode(const CNetAddr& ip); CNode* FindNode(const CSubNet& subNet); CNode* FindNode(const std::string& addrName); CNode* FindNode(const CService& ip); -CNode* ConnectNode(CAddress addrConnect, const char *pszDest = NULL); bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false); void MapPort(bool fUseUPnP); unsigned short GetListenPort(); From 10e83d795672ba2790f66cb023f9a78e7105c0e6 Mon Sep 17 00:00:00 2001 From: Chris Stewart Date: Tue, 3 May 2016 09:18:36 -0500 Subject: [PATCH 0300/1802] Adding basic tests for OP_CSV inside of script_tests.json Changing NOP3 op name to OP_CHECKSEQUENCEVERIFY, renaming instances of OP_NOP3 in script_tests.json to CHECKSEQUENCEVERIFY Cleaning up NOP3 comment Re-adding test cases that were accidentally deleted, removing dupicated test case, fixing formatting Removing re-labeling of OP_NOP3 to OP_CSV Fixing whitespace issues --- src/test/data/script_tests.json | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json index e75b7825ed545..757d94b526857 100644 --- a/src/test/data/script_tests.json +++ b/src/test/data/script_tests.json @@ -700,6 +700,8 @@ ["0x17 0x3014020002107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "Zero-length R is correctly encoded"], ["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "", "OK", "Zero-length S is correctly encoded for DERSIG"], ["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "Negative S is correctly encoded"], + +["2147483648", "NOP3", "CHECKSEQUENCEVERIFY", "OK", "CSV passes if stack top bit 1 << 31 is set"], ["", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE", "Test the test: we should have an empty stack after scriptSig evaluation"], [" ", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE", "and multiple spaces should not change that."], @@ -855,7 +857,7 @@ ["2 2 LSHIFT", "8 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], ["2 1 RSHIFT", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], -["1","NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 2 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], +["1", "NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 2 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], ["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_11' EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], ["Ensure 100% coverage of discouraged NOPS"], @@ -1820,5 +1822,12 @@ "P2SH with CLEANSTACK" ], +["CHECKSEQUENCEVERIFY tests"], +["", "NOP3", "CHECKSEQUENCEVERIFY", "INVALID_STACK_OPERATION", "CSV automatically fails on a empty stack"], +["-1", "NOP3", "CHECKSEQUENCEVERIFY", "NEGATIVE_LOCKTIME", "CSV automatically fails if stack top is negative"], +["0x0100", "NOP3", "CHECKSEQUENCEVERIFY,MINIMALDATA", "UNKNOWN_ERROR", "CSV fails if stack top is not minimally encoded"], +["0", "NOP3", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME", "CSV fails if stack top bit 1 << 31 is set and the tx version < 2"], +["4294967296", "NOP3", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME", + "CSV fails if stack top bit 1 << 31 is not set, and tx version < 2"], ["The End"] ] From fad60b3911236eabf89f4e06274500e57bb08d0d Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 11 May 2016 13:19:10 +0200 Subject: [PATCH 0301/1802] [qa] Fix bip9-softforks blockstore issue --- qa/rpc-tests/bip9-softforks.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/qa/rpc-tests/bip9-softforks.py b/qa/rpc-tests/bip9-softforks.py index e9b659d5082d2..a8fb878dcb1e6 100755 --- a/qa/rpc-tests/bip9-softforks.py +++ b/qa/rpc-tests/bip9-softforks.py @@ -3,6 +3,7 @@ # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. +from test_framework.blockstore import BlockStore from test_framework.test_framework import ComparisonTestFramework from test_framework.util import * from test_framework.mininode import CTransaction, NetworkThread @@ -167,11 +168,13 @@ def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignatu yield TestInstance([[block, False]]) # Restart all + self.test.block_store.close() stop_nodes(self.nodes) wait_bitcoinds() shutil.rmtree(self.options.tmpdir) self.setup_chain() self.setup_network() + self.test.block_store = BlockStore(self.options.tmpdir) self.test.clear_all_connections() self.test.add_all_connections(self.nodes) NetworkThread().start() # Start up network handling in another thread From a545127fbccef4ee674d18d43732ce00ba97f782 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 11 May 2016 19:36:38 +0200 Subject: [PATCH 0302/1802] Squashed 'src/crypto/ctaes/' content from commit cd3c3ac git-subtree-dir: src/crypto/ctaes git-subtree-split: cd3c3ac31fac41cc253bf5780b55ecd8d7368545 --- COPYING | 21 +++ README.md | 41 ++++ bench.c | 170 +++++++++++++++++ ctaes.c | 556 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ctaes.h | 41 ++++ test.c | 110 +++++++++++ 6 files changed, 939 insertions(+) create mode 100644 COPYING create mode 100644 README.md create mode 100644 bench.c create mode 100644 ctaes.c create mode 100644 ctaes.h create mode 100644 test.c diff --git a/COPYING b/COPYING new file mode 100644 index 0000000000000..415b202a2a54e --- /dev/null +++ b/COPYING @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Pieter Wuille + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000000000..0e7fe1775153e --- /dev/null +++ b/README.md @@ -0,0 +1,41 @@ +ctaes +===== + +Simple C module for constant-time AES encryption and decryption. + +Features: +* Simple, pure C code without any dependencies. +* No tables or data-dependent branches whatsoever, but using bit sliced approach from https://eprint.iacr.org/2009/129.pdf. +* Very small object code: slightly over 4k of executable code when compiled with -Os. +* Slower than implementations based on precomputed tables or specialized instructions, but can do ~15 MB/s on modern CPUs. + +Performance +----------- + +Compiled with GCC 5.3.1 with -O3, on an Intel(R) Core(TM) i7-4800MQ CPU, numbers in CPU cycles: + +| Algorithm | Key schedule | Encryption per byte | Decryption per byte | +| --------- | ------------:| -------------------:| -------------------:| +| AES-128 | 2.8k | 154 | 161 | +| AES-192 | 3.1k | 169 | 181 | +| AES-256 | 4.0k | 191 | 203 | + +Build steps +----------- + +Object code: + + $ gcc -O3 ctaes.c -c -o ctaes.o + +Tests: + + $ gcc -O3 ctaes.c test.c -o test + +Benchmark: + + $ gcc -O3 ctaes.c bench.c -o bench + +Review +------ + +Results of a formal review of the code can be found in http://bitcoin.sipa.be/ctaes/review.zip diff --git a/bench.c b/bench.c new file mode 100644 index 0000000000000..a86df496c8300 --- /dev/null +++ b/bench.c @@ -0,0 +1,170 @@ +#include +#include +#include "sys/time.h" + +#include "ctaes.h" + +static double gettimedouble(void) { + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_usec * 0.000001 + tv.tv_sec; +} + +static void print_number(double x) { + double y = x; + int c = 0; + if (y < 0.0) { + y = -y; + } + while (y < 100.0) { + y *= 10.0; + c++; + } + printf("%.*f", c, x); +} + +static void run_benchmark(char *name, void (*benchmark)(void*), void (*setup)(void*), void (*teardown)(void*), void* data, int count, int iter) { + int i; + double min = HUGE_VAL; + double sum = 0.0; + double max = 0.0; + for (i = 0; i < count; i++) { + double begin, total; + if (setup != NULL) { + setup(data); + } + begin = gettimedouble(); + benchmark(data); + total = gettimedouble() - begin; + if (teardown != NULL) { + teardown(data); + } + if (total < min) { + min = total; + } + if (total > max) { + max = total; + } + sum += total; + } + printf("%s: min ", name); + print_number(min * 1000000000.0 / iter); + printf("ns / avg "); + print_number((sum / count) * 1000000000.0 / iter); + printf("ns / max "); + print_number(max * 1000000000.0 / iter); + printf("ns\n"); +} + +static void bench_AES128_init(void* data) { + AES128_ctx* ctx = (AES128_ctx*)data; + int i; + for (i = 0; i < 50000; i++) { + AES128_init(ctx, (unsigned char*)ctx); + } +} + +static void bench_AES128_encrypt_setup(void* data) { + AES128_ctx* ctx = (AES128_ctx*)data; + static const unsigned char key[16] = {0}; + AES128_init(ctx, key); +} + +static void bench_AES128_encrypt(void* data) { + const AES128_ctx* ctx = (const AES128_ctx*)data; + unsigned char scratch[16] = {0}; + int i; + for (i = 0; i < 4000000 / 16; i++) { + AES128_encrypt(ctx, 1, scratch, scratch); + } +} + +static void bench_AES128_decrypt(void* data) { + const AES128_ctx* ctx = (const AES128_ctx*)data; + unsigned char scratch[16] = {0}; + int i; + for (i = 0; i < 4000000 / 16; i++) { + AES128_decrypt(ctx, 1, scratch, scratch); + } +} + +static void bench_AES192_init(void* data) { + AES192_ctx* ctx = (AES192_ctx*)data; + int i; + for (i = 0; i < 50000; i++) { + AES192_init(ctx, (unsigned char*)ctx); + } +} + +static void bench_AES192_encrypt_setup(void* data) { + AES192_ctx* ctx = (AES192_ctx*)data; + static const unsigned char key[16] = {0}; + AES192_init(ctx, key); +} + +static void bench_AES192_encrypt(void* data) { + const AES192_ctx* ctx = (const AES192_ctx*)data; + unsigned char scratch[16] = {0}; + int i; + for (i = 0; i < 4000000 / 16; i++) { + AES192_encrypt(ctx, 1, scratch, scratch); + } +} + +static void bench_AES192_decrypt(void* data) { + const AES192_ctx* ctx = (const AES192_ctx*)data; + unsigned char scratch[16] = {0}; + int i; + for (i = 0; i < 4000000 / 16; i++) { + AES192_decrypt(ctx, 1, scratch, scratch); + } +} + +static void bench_AES256_init(void* data) { + AES256_ctx* ctx = (AES256_ctx*)data; + int i; + for (i = 0; i < 50000; i++) { + AES256_init(ctx, (unsigned char*)ctx); + } +} + + +static void bench_AES256_encrypt_setup(void* data) { + AES256_ctx* ctx = (AES256_ctx*)data; + static const unsigned char key[16] = {0}; + AES256_init(ctx, key); +} + +static void bench_AES256_encrypt(void* data) { + const AES256_ctx* ctx = (const AES256_ctx*)data; + unsigned char scratch[16] = {0}; + int i; + for (i = 0; i < 4000000 / 16; i++) { + AES256_encrypt(ctx, 1, scratch, scratch); + } +} + +static void bench_AES256_decrypt(void* data) { + const AES256_ctx* ctx = (const AES256_ctx*)data; + unsigned char scratch[16] = {0}; + int i; + for (i = 0; i < 4000000 / 16; i++) { + AES256_decrypt(ctx, 1, scratch, scratch); + } +} + +int main(void) { + AES128_ctx ctx128; + AES192_ctx ctx192; + AES256_ctx ctx256; + run_benchmark("aes128_init", bench_AES128_init, NULL, NULL, &ctx128, 20, 50000); + run_benchmark("aes128_encrypt_byte", bench_AES128_encrypt, bench_AES128_encrypt_setup, NULL, &ctx128, 20, 4000000); + run_benchmark("aes128_decrypt_byte", bench_AES128_decrypt, bench_AES128_encrypt_setup, NULL, &ctx128, 20, 4000000); + run_benchmark("aes192_init", bench_AES192_init, NULL, NULL, &ctx192, 20, 50000); + run_benchmark("aes192_encrypt_byte", bench_AES192_encrypt, bench_AES192_encrypt_setup, NULL, &ctx192, 20, 4000000); + run_benchmark("aes192_decrypt_byte", bench_AES192_decrypt, bench_AES192_encrypt_setup, NULL, &ctx192, 20, 4000000); + run_benchmark("aes256_init", bench_AES256_init, NULL, NULL, &ctx256, 20, 50000); + run_benchmark("aes256_encrypt_byte", bench_AES256_encrypt, bench_AES256_encrypt_setup, NULL, &ctx256, 20, 4000000); + run_benchmark("aes256_decrypt_byte", bench_AES256_decrypt, bench_AES256_encrypt_setup, NULL, &ctx256, 20, 4000000); + return 0; +} diff --git a/ctaes.c b/ctaes.c new file mode 100644 index 0000000000000..2389fc0bb254f --- /dev/null +++ b/ctaes.c @@ -0,0 +1,556 @@ + /********************************************************************* + * Copyright (c) 2016 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +/* Constant time, unoptimized, concise, plain C, AES implementation + * Based On: + * Emilia Kasper and Peter Schwabe, Faster and Timing-Attack Resistant AES-GCM + * http://www.iacr.org/archive/ches2009/57470001/57470001.pdf + * But using 8 16-bit integers representing a single AES state rather than 8 128-bit + * integers representing 8 AES states. + */ + +#include "ctaes.h" + +/* Slice variable slice_i contains the i'th bit of the 16 state variables in this order: + * 0 1 2 3 + * 4 5 6 7 + * 8 9 10 11 + * 12 13 14 15 + */ + +/** Convert a byte to sliced form, storing it corresponding to given row and column in s */ +static void LoadByte(AES_state* s, unsigned char byte, int r, int c) { + int i; + for (i = 0; i < 8; i++) { + s->slice[i] |= (byte & 1) << (r * 4 + c); + byte >>= 1; + } +} + +/** Load 16 bytes of data into 8 sliced integers */ +static void LoadBytes(AES_state *s, const unsigned char* data16) { + int c; + for (c = 0; c < 4; c++) { + int r; + for (r = 0; r < 4; r++) { + LoadByte(s, *(data16++), r, c); + } + } +} + +/** Convert 8 sliced integers into 16 bytes of data */ +static void SaveBytes(unsigned char* data16, const AES_state *s) { + int c; + for (c = 0; c < 4; c++) { + int r; + for (r = 0; r < 4; r++) { + int b; + uint8_t v = 0; + for (b = 0; b < 8; b++) { + v |= ((s->slice[b] >> (r * 4 + c)) & 1) << b; + } + *(data16++) = v; + } + } +} + +/* S-box implementation based on the gate logic from: + * Joan Boyar and Rene Peralta, A depth-16 circuit for the AES S-box. + * https://eprint.iacr.org/2011/332.pdf +*/ +static void SubBytes(AES_state *s, int inv) { + /* Load the bit slices */ + uint16_t U0 = s->slice[7], U1 = s->slice[6], U2 = s->slice[5], U3 = s->slice[4]; + uint16_t U4 = s->slice[3], U5 = s->slice[2], U6 = s->slice[1], U7 = s->slice[0]; + + uint16_t T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16; + uint16_t T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, D; + uint16_t M1, M6, M11, M13, M15, M20, M21, M22, M23, M25, M37, M38, M39, M40; + uint16_t M41, M42, M43, M44, M45, M46, M47, M48, M49, M50, M51, M52, M53, M54; + uint16_t M55, M56, M57, M58, M59, M60, M61, M62, M63; + + if (inv) { + uint16_t R5, R13, R17, R18, R19; + /* Undo linear postprocessing */ + T23 = U0 ^ U3; + T22 = ~(U1 ^ U3); + T2 = ~(U0 ^ U1); + T1 = U3 ^ U4; + T24 = ~(U4 ^ U7); + R5 = U6 ^ U7; + T8 = ~(U1 ^ T23); + T19 = T22 ^ R5; + T9 = ~(U7 ^ T1); + T10 = T2 ^ T24; + T13 = T2 ^ R5; + T3 = T1 ^ R5; + T25 = ~(U2 ^ T1); + R13 = U1 ^ U6; + T17 = ~(U2 ^ T19); + T20 = T24 ^ R13; + T4 = U4 ^ T8; + R17 = ~(U2 ^ U5); + R18 = ~(U5 ^ U6); + R19 = ~(U2 ^ U4); + D = U0 ^ R17; + T6 = T22 ^ R17; + T16 = R13 ^ R19; + T27 = T1 ^ R18; + T15 = T10 ^ T27; + T14 = T10 ^ R18; + T26 = T3 ^ T16; + } else { + /* Linear preprocessing. */ + T1 = U0 ^ U3; + T2 = U0 ^ U5; + T3 = U0 ^ U6; + T4 = U3 ^ U5; + T5 = U4 ^ U6; + T6 = T1 ^ T5; + T7 = U1 ^ U2; + T8 = U7 ^ T6; + T9 = U7 ^ T7; + T10 = T6 ^ T7; + T11 = U1 ^ U5; + T12 = U2 ^ U5; + T13 = T3 ^ T4; + T14 = T6 ^ T11; + T15 = T5 ^ T11; + T16 = T5 ^ T12; + T17 = T9 ^ T16; + T18 = U3 ^ U7; + T19 = T7 ^ T18; + T20 = T1 ^ T19; + T21 = U6 ^ U7; + T22 = T7 ^ T21; + T23 = T2 ^ T22; + T24 = T2 ^ T10; + T25 = T20 ^ T17; + T26 = T3 ^ T16; + T27 = T1 ^ T12; + D = U7; + } + + /* Non-linear transformation (identical to the code in SubBytes) */ + M1 = T13 & T6; + M6 = T3 & T16; + M11 = T1 & T15; + M13 = (T4 & T27) ^ M11; + M15 = (T2 & T10) ^ M11; + M20 = T14 ^ M1 ^ (T23 & T8) ^ M13; + M21 = (T19 & D) ^ M1 ^ T24 ^ M15; + M22 = T26 ^ M6 ^ (T22 & T9) ^ M13; + M23 = (T20 & T17) ^ M6 ^ M15 ^ T25; + M25 = M22 & M20; + M37 = M21 ^ ((M20 ^ M21) & (M23 ^ M25)); + M38 = M20 ^ M25 ^ (M21 | (M20 & M23)); + M39 = M23 ^ ((M22 ^ M23) & (M21 ^ M25)); + M40 = M22 ^ M25 ^ (M23 | (M21 & M22)); + M41 = M38 ^ M40; + M42 = M37 ^ M39; + M43 = M37 ^ M38; + M44 = M39 ^ M40; + M45 = M42 ^ M41; + M46 = M44 & T6; + M47 = M40 & T8; + M48 = M39 & D; + M49 = M43 & T16; + M50 = M38 & T9; + M51 = M37 & T17; + M52 = M42 & T15; + M53 = M45 & T27; + M54 = M41 & T10; + M55 = M44 & T13; + M56 = M40 & T23; + M57 = M39 & T19; + M58 = M43 & T3; + M59 = M38 & T22; + M60 = M37 & T20; + M61 = M42 & T1; + M62 = M45 & T4; + M63 = M41 & T2; + + if (inv){ + /* Undo linear preprocessing */ + uint16_t P0 = M52 ^ M61; + uint16_t P1 = M58 ^ M59; + uint16_t P2 = M54 ^ M62; + uint16_t P3 = M47 ^ M50; + uint16_t P4 = M48 ^ M56; + uint16_t P5 = M46 ^ M51; + uint16_t P6 = M49 ^ M60; + uint16_t P7 = P0 ^ P1; + uint16_t P8 = M50 ^ M53; + uint16_t P9 = M55 ^ M63; + uint16_t P10 = M57 ^ P4; + uint16_t P11 = P0 ^ P3; + uint16_t P12 = M46 ^ M48; + uint16_t P13 = M49 ^ M51; + uint16_t P14 = M49 ^ M62; + uint16_t P15 = M54 ^ M59; + uint16_t P16 = M57 ^ M61; + uint16_t P17 = M58 ^ P2; + uint16_t P18 = M63 ^ P5; + uint16_t P19 = P2 ^ P3; + uint16_t P20 = P4 ^ P6; + uint16_t P22 = P2 ^ P7; + uint16_t P23 = P7 ^ P8; + uint16_t P24 = P5 ^ P7; + uint16_t P25 = P6 ^ P10; + uint16_t P26 = P9 ^ P11; + uint16_t P27 = P10 ^ P18; + uint16_t P28 = P11 ^ P25; + uint16_t P29 = P15 ^ P20; + s->slice[7] = P13 ^ P22; + s->slice[6] = P26 ^ P29; + s->slice[5] = P17 ^ P28; + s->slice[4] = P12 ^ P22; + s->slice[3] = P23 ^ P27; + s->slice[2] = P19 ^ P24; + s->slice[1] = P14 ^ P23; + s->slice[0] = P9 ^ P16; + } else { + /* Linear postprocessing */ + uint16_t L0 = M61 ^ M62; + uint16_t L1 = M50 ^ M56; + uint16_t L2 = M46 ^ M48; + uint16_t L3 = M47 ^ M55; + uint16_t L4 = M54 ^ M58; + uint16_t L5 = M49 ^ M61; + uint16_t L6 = M62 ^ L5; + uint16_t L7 = M46 ^ L3; + uint16_t L8 = M51 ^ M59; + uint16_t L9 = M52 ^ M53; + uint16_t L10 = M53 ^ L4; + uint16_t L11 = M60 ^ L2; + uint16_t L12 = M48 ^ M51; + uint16_t L13 = M50 ^ L0; + uint16_t L14 = M52 ^ M61; + uint16_t L15 = M55 ^ L1; + uint16_t L16 = M56 ^ L0; + uint16_t L17 = M57 ^ L1; + uint16_t L18 = M58 ^ L8; + uint16_t L19 = M63 ^ L4; + uint16_t L20 = L0 ^ L1; + uint16_t L21 = L1 ^ L7; + uint16_t L22 = L3 ^ L12; + uint16_t L23 = L18 ^ L2; + uint16_t L24 = L15 ^ L9; + uint16_t L25 = L6 ^ L10; + uint16_t L26 = L7 ^ L9; + uint16_t L27 = L8 ^ L10; + uint16_t L28 = L11 ^ L14; + uint16_t L29 = L11 ^ L17; + s->slice[7] = L6 ^ L24; + s->slice[6] = ~(L16 ^ L26); + s->slice[5] = ~(L19 ^ L28); + s->slice[4] = L6 ^ L21; + s->slice[3] = L20 ^ L22; + s->slice[2] = L25 ^ L29; + s->slice[1] = ~(L13 ^ L27); + s->slice[0] = ~(L6 ^ L23); + } +} + +#define BIT_RANGE(from,to) (((1 << ((to) - (from))) - 1) << (from)) + +#define BIT_RANGE_LEFT(x,from,to,shift) (((x) & BIT_RANGE((from), (to))) << (shift)) +#define BIT_RANGE_RIGHT(x,from,to,shift) (((x) & BIT_RANGE((from), (to))) >> (shift)) + +static void ShiftRows(AES_state* s) { + int i; + for (i = 0; i < 8; i++) { + uint16_t v = s->slice[i]; + s->slice[i] = + (v & BIT_RANGE(0, 4)) | + BIT_RANGE_LEFT(v, 4, 5, 3) | BIT_RANGE_RIGHT(v, 5, 8, 1) | + BIT_RANGE_LEFT(v, 8, 10, 2) | BIT_RANGE_RIGHT(v, 10, 12, 2) | + BIT_RANGE_LEFT(v, 12, 15, 1) | BIT_RANGE_RIGHT(v, 15, 16, 3); + } +} + +static void InvShiftRows(AES_state* s) { + int i; + for (i = 0; i < 8; i++) { + uint16_t v = s->slice[i]; + s->slice[i] = + (v & BIT_RANGE(0, 4)) | + BIT_RANGE_LEFT(v, 4, 7, 1) | BIT_RANGE_RIGHT(v, 7, 8, 3) | + BIT_RANGE_LEFT(v, 8, 10, 2) | BIT_RANGE_RIGHT(v, 10, 12, 2) | + BIT_RANGE_LEFT(v, 12, 13, 3) | BIT_RANGE_RIGHT(v, 13, 16, 1); + } +} + +#define ROT(x,b) (((x) >> ((b) * 4)) | ((x) << ((4-(b)) * 4))) + +static void MixColumns(AES_state* s, int inv) { + /* The MixColumns transform treats the bytes of the columns of the state as + * coefficients of a 3rd degree polynomial over GF(2^8) and multiplies them + * by the fixed polynomial a(x) = {03}x^3 + {01}x^2 + {01}x + {02}, modulo + * x^4 + {01}. + * + * In the inverse transform, we multiply by the inverse of a(x), + * a^-1(x) = {0b}x^3 + {0d}x^2 + {09}x + {0e}. This is equal to + * a(x) * ({04}x^2 + {05}), so we can reuse the forward transform's code + * (found in OpenSSL's bsaes-x86_64.pl, attributed to Jussi Kivilinna) + * + * In the bitsliced representation, a multiplication of every column by x + * mod x^4 + 1 is simply a right rotation. + */ + + /* Shared for both directions is a multiplication by a(x), which can be + * rewritten as (x^3 + x^2 + x) + {02}*(x^3 + {01}). + * + * First compute s into the s? variables, (x^3 + {01}) * s into the s?_01 + * variables and (x^3 + x^2 + x)*s into the s?_123 variables. + */ + uint16_t s0 = s->slice[0], s1 = s->slice[1], s2 = s->slice[2], s3 = s->slice[3]; + uint16_t s4 = s->slice[4], s5 = s->slice[5], s6 = s->slice[6], s7 = s->slice[7]; + uint16_t s0_01 = s0 ^ ROT(s0, 1), s0_123 = ROT(s0_01, 1) ^ ROT(s0, 3); + uint16_t s1_01 = s1 ^ ROT(s1, 1), s1_123 = ROT(s1_01, 1) ^ ROT(s1, 3); + uint16_t s2_01 = s2 ^ ROT(s2, 1), s2_123 = ROT(s2_01, 1) ^ ROT(s2, 3); + uint16_t s3_01 = s3 ^ ROT(s3, 1), s3_123 = ROT(s3_01, 1) ^ ROT(s3, 3); + uint16_t s4_01 = s4 ^ ROT(s4, 1), s4_123 = ROT(s4_01, 1) ^ ROT(s4, 3); + uint16_t s5_01 = s5 ^ ROT(s5, 1), s5_123 = ROT(s5_01, 1) ^ ROT(s5, 3); + uint16_t s6_01 = s6 ^ ROT(s6, 1), s6_123 = ROT(s6_01, 1) ^ ROT(s6, 3); + uint16_t s7_01 = s7 ^ ROT(s7, 1), s7_123 = ROT(s7_01, 1) ^ ROT(s7, 3); + /* Now compute s = s?_123 + {02} * s?_01. */ + s->slice[0] = s7_01 ^ s0_123; + s->slice[1] = s7_01 ^ s0_01 ^ s1_123; + s->slice[2] = s1_01 ^ s2_123; + s->slice[3] = s7_01 ^ s2_01 ^ s3_123; + s->slice[4] = s7_01 ^ s3_01 ^ s4_123; + s->slice[5] = s4_01 ^ s5_123; + s->slice[6] = s5_01 ^ s6_123; + s->slice[7] = s6_01 ^ s7_123; + if (inv) { + /* In the reverse direction, we further need to multiply by + * {04}x^2 + {05}, which can be written as {04} * (x^2 + {01}) + {01}. + * + * First compute (x^2 + {01}) * s into the t?_02 variables: */ + uint16_t t0_02 = s->slice[0] ^ ROT(s->slice[0], 2); + uint16_t t1_02 = s->slice[1] ^ ROT(s->slice[1], 2); + uint16_t t2_02 = s->slice[2] ^ ROT(s->slice[2], 2); + uint16_t t3_02 = s->slice[3] ^ ROT(s->slice[3], 2); + uint16_t t4_02 = s->slice[4] ^ ROT(s->slice[4], 2); + uint16_t t5_02 = s->slice[5] ^ ROT(s->slice[5], 2); + uint16_t t6_02 = s->slice[6] ^ ROT(s->slice[6], 2); + uint16_t t7_02 = s->slice[7] ^ ROT(s->slice[7], 2); + /* And then update s += {04} * t?_02 */ + s->slice[0] ^= t6_02; + s->slice[1] ^= t6_02 ^ t7_02; + s->slice[2] ^= t0_02 ^ t7_02; + s->slice[3] ^= t1_02 ^ t6_02; + s->slice[4] ^= t2_02 ^ t6_02 ^ t7_02; + s->slice[5] ^= t3_02 ^ t7_02; + s->slice[6] ^= t4_02; + s->slice[7] ^= t5_02; + } +} + +static void AddRoundKey(AES_state* s, const AES_state* round) { + int b; + for (b = 0; b < 8; b++) { + s->slice[b] ^= round->slice[b]; + } +} + +/** column_0(s) = column_c(a) */ +static void GetOneColumn(AES_state* s, const AES_state* a, int c) { + int b; + for (b = 0; b < 8; b++) { + s->slice[b] = (a->slice[b] >> c) & 0x1111; + } +} + +/** column_c1(r) |= (column_0(s) ^= column_c2(a)) */ +static void KeySetupColumnMix(AES_state* s, AES_state* r, const AES_state* a, int c1, int c2) { + int b; + for (b = 0; b < 8; b++) { + r->slice[b] |= ((s->slice[b] ^= ((a->slice[b] >> c2) & 0x1111)) & 0x1111) << c1; + } +} + +/** Rotate the rows in s one position upwards, and xor in r */ +static void KeySetupTransform(AES_state* s, const AES_state* r) { + int b; + for (b = 0; b < 8; b++) { + s->slice[b] = ((s->slice[b] >> 4) | (s->slice[b] << 12)) ^ r->slice[b]; + } +} + +/* Multiply the cells in s by x, as polynomials over GF(2) mod x^8 + x^4 + x^3 + x + 1 */ +static void MultX(AES_state* s) { + uint16_t top = s->slice[7]; + s->slice[7] = s->slice[6]; + s->slice[6] = s->slice[5]; + s->slice[5] = s->slice[4]; + s->slice[4] = s->slice[3] ^ top; + s->slice[3] = s->slice[2] ^ top; + s->slice[2] = s->slice[1]; + s->slice[1] = s->slice[0] ^ top; + s->slice[0] = top; +} + +/** Expand the cipher key into the key schedule. + * + * state must be a pointer to an array of size nrounds + 1. + * key must be a pointer to 4 * nkeywords bytes. + * + * AES128 uses nkeywords = 4, nrounds = 10 + * AES192 uses nkeywords = 6, nrounds = 12 + * AES256 uses nkeywords = 8, nrounds = 14 + */ +static void AES_setup(AES_state* rounds, const uint8_t* key, int nkeywords, int nrounds) +{ + int i; + + /* The one-byte round constant */ + AES_state rcon = {{1,0,0,0,0,0,0,0}}; + /* The number of the word being generated, modulo nkeywords */ + int pos = 0; + /* The column representing the word currently being processed */ + AES_state column; + + for (i = 0; i < nrounds + 1; i++) { + int b; + for (b = 0; b < 8; b++) { + rounds[i].slice[b] = 0; + } + } + + /* The first nkeywords round columns are just taken from the key directly. */ + for (i = 0; i < nkeywords; i++) { + int r; + for (r = 0; r < 4; r++) { + LoadByte(&rounds[i >> 2], *(key++), r, i & 3); + } + } + + GetOneColumn(&column, &rounds[(nkeywords - 1) >> 2], (nkeywords - 1) & 3); + + for (i = nkeywords; i < 4 * (nrounds + 1); i++) { + /* Transform column */ + if (pos == 0) { + SubBytes(&column, 0); + KeySetupTransform(&column, &rcon); + MultX(&rcon); + } else if (nkeywords > 6 && pos == 4) { + SubBytes(&column, 0); + } + if (++pos == nkeywords) pos = 0; + KeySetupColumnMix(&column, &rounds[i >> 2], &rounds[(i - nkeywords) >> 2], i & 3, (i - nkeywords) & 3); + } +} + +static void AES_encrypt(const AES_state* rounds, int nrounds, unsigned char* cipher16, const unsigned char* plain16) { + AES_state s = {{0}}; + int round; + + LoadBytes(&s, plain16); + AddRoundKey(&s, rounds++); + + for (round = 1; round < nrounds; round++) { + SubBytes(&s, 0); + ShiftRows(&s); + MixColumns(&s, 0); + AddRoundKey(&s, rounds++); + } + + SubBytes(&s, 0); + ShiftRows(&s); + AddRoundKey(&s, rounds); + + SaveBytes(cipher16, &s); +} + +static void AES_decrypt(const AES_state* rounds, int nrounds, unsigned char* plain16, const unsigned char* cipher16) { + /* Most AES decryption implementations use the alternate scheme + * (the Equivalent Inverse Cipher), which looks more like encryption, but + * needs different round constants. We can't reuse any code here anyway, so + * don't bother. */ + AES_state s = {{0}}; + int round; + + rounds += nrounds; + + LoadBytes(&s, cipher16); + AddRoundKey(&s, rounds--); + + for (round = 1; round < nrounds; round++) { + InvShiftRows(&s); + SubBytes(&s, 1); + AddRoundKey(&s, rounds--); + MixColumns(&s, 1); + } + + InvShiftRows(&s); + SubBytes(&s, 1); + AddRoundKey(&s, rounds); + + SaveBytes(plain16, &s); +} + +void AES128_init(AES128_ctx* ctx, const unsigned char* key16) { + AES_setup(ctx->rk, key16, 4, 10); +} + +void AES128_encrypt(const AES128_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16) { + while (blocks--) { + AES_encrypt(ctx->rk, 10, cipher16, plain16); + cipher16 += 16; + plain16 += 16; + } +} + +void AES128_decrypt(const AES128_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16) { + while (blocks--) { + AES_decrypt(ctx->rk, 10, plain16, cipher16); + cipher16 += 16; + plain16 += 16; + } +} + +void AES192_init(AES192_ctx* ctx, const unsigned char* key24) { + AES_setup(ctx->rk, key24, 6, 12); +} + +void AES192_encrypt(const AES192_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16) { + while (blocks--) { + AES_encrypt(ctx->rk, 12, cipher16, plain16); + cipher16 += 16; + plain16 += 16; + } + +} + +void AES192_decrypt(const AES192_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16) { + while (blocks--) { + AES_decrypt(ctx->rk, 12, plain16, cipher16); + cipher16 += 16; + plain16 += 16; + } +} + +void AES256_init(AES256_ctx* ctx, const unsigned char* key32) { + AES_setup(ctx->rk, key32, 8, 14); +} + +void AES256_encrypt(const AES256_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16) { + while (blocks--) { + AES_encrypt(ctx->rk, 14, cipher16, plain16); + cipher16 += 16; + plain16 += 16; + } +} + +void AES256_decrypt(const AES256_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16) { + while (blocks--) { + AES_decrypt(ctx->rk, 14, plain16, cipher16); + cipher16 += 16; + plain16 += 16; + } +} diff --git a/ctaes.h b/ctaes.h new file mode 100644 index 0000000000000..2f0af04216053 --- /dev/null +++ b/ctaes.h @@ -0,0 +1,41 @@ + /********************************************************************* + * Copyright (c) 2016 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _CTAES_H_ +#define _CTAES_H_ 1 + +#include +#include + +typedef struct { + uint16_t slice[8]; +} AES_state; + +typedef struct { + AES_state rk[11]; +} AES128_ctx; + +typedef struct { + AES_state rk[13]; +} AES192_ctx; + +typedef struct { + AES_state rk[15]; +} AES256_ctx; + +void AES128_init(AES128_ctx* ctx, const unsigned char* key16); +void AES128_encrypt(const AES128_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16); +void AES128_decrypt(const AES128_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16); + +void AES192_init(AES192_ctx* ctx, const unsigned char* key24); +void AES192_encrypt(const AES192_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16); +void AES192_decrypt(const AES192_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16); + +void AES256_init(AES256_ctx* ctx, const unsigned char* key32); +void AES256_encrypt(const AES256_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16); +void AES256_decrypt(const AES256_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16); + +#endif diff --git a/test.c b/test.c new file mode 100644 index 0000000000000..fce1696acdc2d --- /dev/null +++ b/test.c @@ -0,0 +1,110 @@ + /********************************************************************* + * Copyright (c) 2016 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#include "ctaes.h" + +#include +#include +#include + +typedef struct { + int keysize; + const char* key; + const char* plain; + const char* cipher; +} ctaes_test; + +static const ctaes_test ctaes_tests[] = { + /* AES test vectors from FIPS 197. */ + {128, "000102030405060708090a0b0c0d0e0f", "00112233445566778899aabbccddeeff", "69c4e0d86a7b0430d8cdb78070b4c55a"}, + {192, "000102030405060708090a0b0c0d0e0f1011121314151617", "00112233445566778899aabbccddeeff", "dda97ca4864cdfe06eaf70a0ec0d7191"}, + {256, "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "00112233445566778899aabbccddeeff", "8ea2b7ca516745bfeafc49904b496089"}, + + /* AES-ECB test vectors from NIST sp800-38a. */ + {128, "2b7e151628aed2a6abf7158809cf4f3c", "6bc1bee22e409f96e93d7e117393172a", "3ad77bb40d7a3660a89ecaf32466ef97"}, + {128, "2b7e151628aed2a6abf7158809cf4f3c", "ae2d8a571e03ac9c9eb76fac45af8e51", "f5d3d58503b9699de785895a96fdbaaf"}, + {128, "2b7e151628aed2a6abf7158809cf4f3c", "30c81c46a35ce411e5fbc1191a0a52ef", "43b1cd7f598ece23881b00e3ed030688"}, + {128, "2b7e151628aed2a6abf7158809cf4f3c", "f69f2445df4f9b17ad2b417be66c3710", "7b0c785e27e8ad3f8223207104725dd4"}, + {192, "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "6bc1bee22e409f96e93d7e117393172a", "bd334f1d6e45f25ff712a214571fa5cc"}, + {192, "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "ae2d8a571e03ac9c9eb76fac45af8e51", "974104846d0ad3ad7734ecb3ecee4eef"}, + {192, "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "30c81c46a35ce411e5fbc1191a0a52ef", "ef7afd2270e2e60adce0ba2face6444e"}, + {192, "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "f69f2445df4f9b17ad2b417be66c3710", "9a4b41ba738d6c72fb16691603c18e0e"}, + {256, "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "6bc1bee22e409f96e93d7e117393172a", "f3eed1bdb5d2a03c064b5a7e3db181f8"}, + {256, "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "ae2d8a571e03ac9c9eb76fac45af8e51", "591ccb10d410ed26dc5ba74a31362870"}, + {256, "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "30c81c46a35ce411e5fbc1191a0a52ef", "b6ed21b99ca6f4f9f153e7b1beafed1d"}, + {256, "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "f69f2445df4f9b17ad2b417be66c3710", "23304b7a39f9f3ff067d8d8f9e24ecc7"} +}; + +static void from_hex(unsigned char* data, int len, const char* hex) { + int p; + for (p = 0; p < len; p++) { + int v = 0; + int n; + for (n = 0; n < 2; n++) { + assert((*hex >= '0' && *hex <= '9') || (*hex >= 'a' && *hex <= 'f')); + if (*hex >= '0' && *hex <= '9') { + v |= (*hex - '0') << (4 * (1 - n)); + } else { + v |= (*hex - 'a' + 10) << (4 * (1 - n)); + } + hex++; + } + *(data++) = v; + } + assert(*hex == 0); +} + +int main(void) { + int i; + int fail = 0; + for (i = 0; i < sizeof(ctaes_tests) / sizeof(ctaes_tests[0]); i++) { + unsigned char key[32], plain[16], cipher[16], ciphered[16], deciphered[16]; + const ctaes_test* test = &ctaes_tests[i]; + assert(test->keysize == 128 || test->keysize == 192 || test->keysize == 256); + from_hex(plain, 16, test->plain); + from_hex(cipher, 16, test->cipher); + switch (test->keysize) { + case 128: { + AES128_ctx ctx; + from_hex(key, 16, test->key); + AES128_init(&ctx, key); + AES128_encrypt(&ctx, 1, ciphered, plain); + AES128_decrypt(&ctx, 1, deciphered, cipher); + break; + } + case 192: { + AES192_ctx ctx; + from_hex(key, 24, test->key); + AES192_init(&ctx, key); + AES192_encrypt(&ctx, 1, ciphered, plain); + AES192_decrypt(&ctx, 1, deciphered, cipher); + break; + } + case 256: { + AES256_ctx ctx; + from_hex(key, 32, test->key); + AES256_init(&ctx, key); + AES256_encrypt(&ctx, 1, ciphered, plain); + AES256_decrypt(&ctx, 1, deciphered, cipher); + break; + } + } + if (memcmp(cipher, ciphered, 16)) { + fprintf(stderr, "E(key=\"%s\", plain=\"%s\") != \"%s\"\n", test->key, test->plain, test->cipher); + fail++; + } + if (memcmp(plain, deciphered, 16)) { + fprintf(stderr, "D(key=\"%s\", cipher=\"%s\") != \"%s\"\n", test->key, test->cipher, test->plain); + fail++; + } + } + if (fail == 0) { + fprintf(stderr, "All tests succesful\n"); + } else { + fprintf(stderr, "%i tests failed\n", fail); + } + return (fail != 0); +} From 32114dd63493fd169bf666fc3a5b4a912c083766 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 10 May 2016 18:19:03 +0200 Subject: [PATCH 0303/1802] bench: Add crypto hash benchmarks Add benchmarks for the cryptographic hash algorithms: - RIPEMD160 - SHA1 - SHA256 - SHA512 Continues work on #7883. --- src/Makefile.bench.include | 3 ++- src/bench/crypto_hash.cpp | 53 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 src/bench/crypto_hash.cpp diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include index 24e2b3e0c85e1..65fd24e051cae 100644 --- a/src/Makefile.bench.include +++ b/src/Makefile.bench.include @@ -8,7 +8,8 @@ bench_bench_bitcoin_SOURCES = \ bench/bench.cpp \ bench/bench.h \ bench/Examples.cpp \ - bench/rollingbloom.cpp + bench/rollingbloom.cpp \ + bench/crypto_hash.cpp bench_bench_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CLFAGS) $(EVENT_PTHREADS_CFLAGS) -I$(builddir)/bench/ bench_bench_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) diff --git a/src/bench/crypto_hash.cpp b/src/bench/crypto_hash.cpp new file mode 100644 index 0000000000000..6b753f6308371 --- /dev/null +++ b/src/bench/crypto_hash.cpp @@ -0,0 +1,53 @@ +// Copyright (c) 2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include "bench.h" +#include "bloom.h" +#include "utiltime.h" +#include "crypto/ripemd160.h" +#include "crypto/sha1.h" +#include "crypto/sha256.h" +#include "crypto/sha512.h" + +/* Number of bytes to hash per iteration */ +static const uint64_t BUFFER_SIZE = 1000*1000; + +static void RIPEMD160(benchmark::State& state) +{ + uint8_t hash[CRIPEMD160::OUTPUT_SIZE]; + std::vector in(BUFFER_SIZE,0); + while (state.KeepRunning()) + CRIPEMD160().Write(begin_ptr(in), in.size()).Finalize(hash); +} + +static void SHA1(benchmark::State& state) +{ + uint8_t hash[CSHA1::OUTPUT_SIZE]; + std::vector in(BUFFER_SIZE,0); + while (state.KeepRunning()) + CSHA1().Write(begin_ptr(in), in.size()).Finalize(hash); +} + +static void SHA256(benchmark::State& state) +{ + uint8_t hash[CSHA256::OUTPUT_SIZE]; + std::vector in(BUFFER_SIZE,0); + while (state.KeepRunning()) + CSHA256().Write(begin_ptr(in), in.size()).Finalize(hash); +} + +static void SHA512(benchmark::State& state) +{ + uint8_t hash[CSHA512::OUTPUT_SIZE]; + std::vector in(BUFFER_SIZE,0); + while (state.KeepRunning()) + CSHA512().Write(begin_ptr(in), in.size()).Finalize(hash); +} + +BENCHMARK(RIPEMD160); +BENCHMARK(SHA1); +BENCHMARK(SHA256); +BENCHMARK(SHA512); From 8b0e4970281de15472a93a529302f3de15163943 Mon Sep 17 00:00:00 2001 From: Tyler Hardin Date: Wed, 11 May 2016 22:28:02 -0400 Subject: [PATCH 0304/1802] Qt: Add option to hide the system tray icon My changes leave all tray icon and menu creation/initialization logic untouched. It only shows or hides the icon according to the setting. A new checkbox was added to the OptionsDialog under the Window tab. A bool option named "hideTrayIcon" was added to OptionsModel. This checkbox was mapped like other all options to the OptionsModel. A signal was added to the OptionsModel for broadcasting changes the the hideTrayIcon option. This signal was connected to a new slot added to BitcoinGUI named setTrayIconVisible(bool). The slot simply hides or shows the trayIcon in BitcoinGUI according to the parameter recieved. --- src/qt/bitcoingui.cpp | 20 +++++++++++++++++++- src/qt/bitcoingui.h | 3 +++ src/qt/forms/optionsdialog.ui | 10 ++++++++++ src/qt/optionsdialog.cpp | 14 ++++++++++++++ src/qt/optionsdialog.h | 2 ++ src/qt/optionsmodel.cpp | 14 +++++++++++++- src/qt/optionsmodel.h | 4 ++++ 7 files changed, 65 insertions(+), 2 deletions(-) diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index b00cdfcaf2bdd..99844863640f4 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -474,6 +474,16 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel) } #endif // ENABLE_WALLET unitDisplayControl->setOptionsModel(clientModel->getOptionsModel()); + + OptionsModel* optionsModel = clientModel->getOptionsModel(); + if(optionsModel) + { + // be aware of the tray icon disable state change reported by the OptionsModel object. + connect(optionsModel,SIGNAL(hideTrayIconChanged(bool)),this,SLOT(setTrayIconVisible(bool))); + + // initialize the disable state of the tray icon with the current value in the model. + setTrayIconVisible(optionsModel->getHideTrayIcon()); + } } else { // Disable possibility to show main window via action toggleHideAction->setEnabled(false); @@ -535,7 +545,7 @@ void BitcoinGUI::createTrayIcon(const NetworkStyle *networkStyle) QString toolTip = tr("%1 client").arg(tr(PACKAGE_NAME)) + " " + networkStyle->getTitleAddText(); trayIcon->setToolTip(toolTip); trayIcon->setIcon(networkStyle->getTrayAndWindowIcon()); - trayIcon->show(); + trayIcon->hide(); #endif notificator = new Notificator(QApplication::applicationName(), trayIcon, this); @@ -1044,6 +1054,14 @@ void BitcoinGUI::showProgress(const QString &title, int nProgress) progressDialog->setValue(nProgress); } +void BitcoinGUI::setTrayIconVisible(bool fHideTrayIcon) +{ + if (trayIcon) + { + trayIcon->setVisible(!fHideTrayIcon); + } +} + static bool ThreadSafeMessageBox(BitcoinGUI *gui, const std::string& message, const std::string& caption, unsigned int style) { bool modal = (style & CClientUIInterface::MODAL); diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 871ca1ba347e9..27ef11c75c079 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -218,6 +218,9 @@ private Q_SLOTS: /** Show progress dialog e.g. for verifychain */ void showProgress(const QString &title, int nProgress); + + /** When hideTrayIcon setting is changed in OptionsModel hide or show the icon accordingly. */ + void setTrayIconVisible(bool); }; class UnitDisplayStatusBarControl : public QLabel diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui index c712e6ea01793..0b292018727ed 100644 --- a/src/qt/forms/optionsdialog.ui +++ b/src/qt/forms/optionsdialog.ui @@ -504,6 +504,16 @@ &Window + + + + &Hide the icon from the system tray. + + + Hide tray icon + + + diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index 95a3fa8d21a4d..f2db3988991a0 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -198,6 +198,7 @@ void OptionsDialog::setMapper() /* Window */ #ifndef Q_OS_MAC + mapper->addMapping(ui->hideTrayIcon, OptionsModel::HideTrayIcon); mapper->addMapping(ui->minimizeToTray, OptionsModel::MinimizeToTray); mapper->addMapping(ui->minimizeOnClose, OptionsModel::MinimizeOnClose); #endif @@ -243,6 +244,19 @@ void OptionsDialog::on_cancelButton_clicked() reject(); } +void OptionsDialog::on_hideTrayIcon_stateChanged(int fState) +{ + if(fState) + { + ui->minimizeToTray->setChecked(false); + ui->minimizeToTray->setEnabled(false); + } + else + { + ui->minimizeToTray->setEnabled(true); + } +} + void OptionsDialog::showRestartWarning(bool fPersistent) { ui->statusLabel->setStyleSheet("QLabel { color: red; }"); diff --git a/src/qt/optionsdialog.h b/src/qt/optionsdialog.h index e944fb9ee9b2a..41b56d1386257 100644 --- a/src/qt/optionsdialog.h +++ b/src/qt/optionsdialog.h @@ -49,6 +49,8 @@ private Q_SLOTS: void on_resetButton_clicked(); void on_okButton_clicked(); void on_cancelButton_clicked(); + + void on_hideTrayIcon_stateChanged(int fState); void showRestartWarning(bool fPersistent = false); void clearStatusLabel(); diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index d091bb9e610aa..cc2cbc0e66419 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -51,9 +51,14 @@ void OptionsModel::Init(bool resetSettings) // These are Qt-only settings: // Window + if (!settings.contains("fHideTrayIcon")) + settings.setValue("fHideTrayIcon", false); + fHideTrayIcon = settings.value("fHideTrayIcon").toBool(); + Q_EMIT hideTrayIconChanged(fHideTrayIcon); + if (!settings.contains("fMinimizeToTray")) settings.setValue("fMinimizeToTray", false); - fMinimizeToTray = settings.value("fMinimizeToTray").toBool(); + fMinimizeToTray = settings.value("fMinimizeToTray").toBool() && !fHideTrayIcon; if (!settings.contains("fMinimizeOnClose")) settings.setValue("fMinimizeOnClose", false); @@ -166,6 +171,8 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const { case StartAtStartup: return GUIUtil::GetStartOnSystemStartup(); + case HideTrayIcon: + return fHideTrayIcon; case MinimizeToTray: return fMinimizeToTray; case MapPortUPnP: @@ -242,6 +249,11 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in case StartAtStartup: successful = GUIUtil::SetStartOnSystemStartup(value.toBool()); break; + case HideTrayIcon: + fHideTrayIcon = value.toBool(); + settings.setValue("fHideTrayIcon", fHideTrayIcon); + Q_EMIT hideTrayIconChanged(fHideTrayIcon); + break; case MinimizeToTray: fMinimizeToTray = value.toBool(); settings.setValue("fMinimizeToTray", fMinimizeToTray); diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index 841711dd2d978..3b491ceac2cde 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -28,6 +28,7 @@ class OptionsModel : public QAbstractListModel enum OptionID { StartAtStartup, // bool + HideTrayIcon, // bool MinimizeToTray, // bool MapPortUPnP, // bool MinimizeOnClose, // bool @@ -58,6 +59,7 @@ class OptionsModel : public QAbstractListModel void setDisplayUnit(const QVariant &value); /* Explicit getters */ + bool getHideTrayIcon() { return fHideTrayIcon; } bool getMinimizeToTray() { return fMinimizeToTray; } bool getMinimizeOnClose() { return fMinimizeOnClose; } int getDisplayUnit() { return nDisplayUnit; } @@ -72,6 +74,7 @@ class OptionsModel : public QAbstractListModel private: /* Qt-only settings */ + bool fHideTrayIcon; bool fMinimizeToTray; bool fMinimizeOnClose; QString language; @@ -87,6 +90,7 @@ class OptionsModel : public QAbstractListModel Q_SIGNALS: void displayUnitChanged(int unit); void coinControlFeaturesChanged(bool); + void hideTrayIconChanged(bool); }; #endif // BITCOIN_QT_OPTIONSMODEL_H From 276ce84fd3a9561a11ae4c5a00c71ff44d3a59a9 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Wed, 11 May 2016 21:08:36 +0200 Subject: [PATCH 0305/1802] [Qt] Disable some menu items during splashscreen/verification state --- src/qt/bitcoingui.cpp | 12 ++++++++++++ src/qt/bitcoingui.h | 1 + 2 files changed, 13 insertions(+) diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index b00cdfcaf2bdd..aa8276a69bc4b 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -320,12 +320,14 @@ void BitcoinGUI::createActions() aboutAction = new QAction(platformStyle->TextColorIcon(":/icons/about"), tr("&About %1").arg(tr(PACKAGE_NAME)), this); aboutAction->setStatusTip(tr("Show information about %1").arg(tr(PACKAGE_NAME))); aboutAction->setMenuRole(QAction::AboutRole); + aboutAction->setEnabled(false); aboutQtAction = new QAction(platformStyle->TextColorIcon(":/icons/about_qt"), tr("About &Qt"), this); aboutQtAction->setStatusTip(tr("Show information about Qt")); aboutQtAction->setMenuRole(QAction::AboutQtRole); optionsAction = new QAction(platformStyle->TextColorIcon(":/icons/options"), tr("&Options..."), this); optionsAction->setStatusTip(tr("Modify configuration options for %1").arg(tr(PACKAGE_NAME))); optionsAction->setMenuRole(QAction::PreferencesRole); + optionsAction->setEnabled(false); toggleHideAction = new QAction(platformStyle->TextColorIcon(":/icons/about"), tr("&Show / Hide"), this); toggleHideAction->setStatusTip(tr("Show or hide the main Window")); @@ -343,6 +345,8 @@ void BitcoinGUI::createActions() openRPCConsoleAction = new QAction(platformStyle->TextColorIcon(":/icons/debugwindow"), tr("&Debug window"), this); openRPCConsoleAction->setStatusTip(tr("Open debugging and diagnostic console")); + // initially disable the debug window menu item + openRPCConsoleAction->setEnabled(false); usedSendingAddressesAction = new QAction(platformStyle->TextColorIcon(":/icons/address-book"), tr("&Sending addresses..."), this); usedSendingAddressesAction->setStatusTip(tr("Show the list of used sending addresses and labels")); @@ -891,6 +895,14 @@ void BitcoinGUI::closeEvent(QCloseEvent *event) QMainWindow::closeEvent(event); } +void BitcoinGUI::showEvent(QShowEvent *event) +{ + // enable the debug window when the main window shows up + openRPCConsoleAction->setEnabled(true); + aboutAction->setEnabled(true); + optionsAction->setEnabled(true); +} + #ifdef ENABLE_WALLET void BitcoinGUI::incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label) { diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 871ca1ba347e9..ef8b8726f7193 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -72,6 +72,7 @@ class BitcoinGUI : public QMainWindow protected: void changeEvent(QEvent *e); void closeEvent(QCloseEvent *event); + void showEvent(QShowEvent *event); void dragEnterEvent(QDragEnterEvent *event); void dropEvent(QDropEvent *event); bool eventFilter(QObject *object, QEvent *event); From 34ebceb25a40a2160349656265951cbe9a5b0f34 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 12 May 2016 09:51:43 +0200 Subject: [PATCH 0306/1802] [Qt][OSX] Fix Cmd-Q / Menu Quit shutdown on OSX --- src/qt/bitcoin.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 9c21bb24cee28..6218ab6ab0542 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -370,6 +370,7 @@ void BitcoinApplication::createSplashScreen(const NetworkStyle *networkStyle) splash->setAttribute(Qt::WA_DeleteOnClose); splash->show(); connect(this, SIGNAL(splashFinished(QWidget*)), splash, SLOT(slotFinish(QWidget*))); + connect(this, SIGNAL(requestedShutdown()), splash, SLOT(close())); } void BitcoinApplication::startThread() From fab5233fe6c99d446a2cebc48cf479c3f026c2cc Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 12 May 2016 12:54:00 +0200 Subject: [PATCH 0307/1802] [qa] test_framework: Set wait-timeout for bitcoind procs --- qa/rpc-tests/test_framework/util.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index 6784177aaac57..d62b8ac55c533 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -35,6 +35,8 @@ # The number of ports to "reserve" for p2p and rpc, each PORT_RANGE = 5000 +BITCOIND_PROC_WAIT_TIMEOUT = 60 + class PortSeed: # Must be initialized with a unique integer for each process @@ -325,7 +327,7 @@ def stop_node(node, i): node.stop() except http.client.CannotSendRequest as e: print("WARN: Unable to stop node: " + repr(e)) - bitcoind_processes[i].wait() + bitcoind_processes[i].wait(timeout=BITCOIND_PROC_WAIT_TIMEOUT) del bitcoind_processes[i] def stop_nodes(nodes): @@ -343,7 +345,7 @@ def set_node_times(nodes, t): def wait_bitcoinds(): # Wait for all bitcoinds to cleanly exit for bitcoind in bitcoind_processes.values(): - bitcoind.wait() + bitcoind.wait(timeout=BITCOIND_PROC_WAIT_TIMEOUT) bitcoind_processes.clear() def connect_nodes(from_connection, node_num): From e5764e69cbd0bf4eb98c96eeb31c94349bbe7b7c Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 12 May 2016 13:48:58 +0200 Subject: [PATCH 0308/1802] doc: Remove outdated qt4 install information from README.md This text is aimed at users installing the binaries. Now that Qt5 is linked statically, there is no need to install Qt as a run-time dependency. --- doc/README.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/doc/README.md b/doc/README.md index cf475ef18e5fc..a5524889d2976 100644 --- a/doc/README.md +++ b/doc/README.md @@ -11,17 +11,11 @@ The following are some helpful notes on how to run Bitcoin on your native platfo ### Unix -You need the Qt4 run-time libraries to run Bitcoin-Qt. On Debian or Ubuntu: - - sudo apt-get install libqtgui4 - Unpack the files into a directory and run: - bin/32/bitcoin-qt (GUI, 32-bit) or bin/32/bitcoind (headless, 32-bit) - bin/64/bitcoin-qt (GUI, 64-bit) or bin/64/bitcoind (headless, 64-bit) - - ### Windows Unpack the files into a directory, and then run bitcoin-qt.exe. From 581ddff05c92eb835a20c2be9ccf5d2d37b94883 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 12 May 2016 14:00:22 +0200 Subject: [PATCH 0309/1802] net: Add fRelayTxes flag Add a fRelayTxes to keep track of the relay transaction flag we send to other peers. --- src/init.cpp | 1 + src/main.cpp | 4 ++-- src/net.cpp | 3 ++- src/net.h | 1 + 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index d19ca530b3831..3218321a322da 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1102,6 +1102,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) fListen = GetBoolArg("-listen", DEFAULT_LISTEN); fDiscover = GetBoolArg("-discover", true); fNameLookup = GetBoolArg("-dns", DEFAULT_NAME_LOOKUP); + fRelayTxes = !GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY); bool fBound = false; if (fListen) { diff --git a/src/main.cpp b/src/main.cpp index ee30954b48545..f813056a7a905 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4751,7 +4751,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, return error("message inv size() = %u", vInv.size()); } - bool fBlocksOnly = GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY); + bool fBlocksOnly = !fRelayTxes; // Allow whitelisted peers to send data other than blocks in blocks only mode if whitelistrelay is true if (pfrom->fWhitelisted && GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY)) @@ -4934,7 +4934,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, { // Stop processing the transaction early if // We are in blocks only mode and peer is either not whitelisted or whitelistrelay is off - if (GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY) && (!pfrom->fWhitelisted || !GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY))) + if (!fRelayTxes && (!pfrom->fWhitelisted || !GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY))) { LogPrint("net", "transaction sent in violation of protocol peer=%d\n", pfrom->id); return true; diff --git a/src/net.cpp b/src/net.cpp index 5e810a0f15888..da5090dbc624a 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -77,6 +77,7 @@ const static std::string NET_MESSAGE_COMMAND_OTHER = "*other*"; bool fDiscover = true; bool fListen = true; uint64_t nLocalServices = NODE_NETWORK; +bool fRelayTxes = true; CCriticalSection cs_mapLocalHost; map mapLocalHost; static bool vfLimited[NET_MAX] = {}; @@ -454,7 +455,7 @@ void CNode::PushVersion() else LogPrint("net", "send version message: version %d, blocks=%d, us=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), id); PushMessage(NetMsgType::VERSION, PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe, - nLocalHostNonce, strSubVersion, nBestHeight, !GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY)); + nLocalHostNonce, strSubVersion, nBestHeight, fRelayTxes); } diff --git a/src/net.h b/src/net.h index b6ec7bf3e2c28..66511e0fbd430 100644 --- a/src/net.h +++ b/src/net.h @@ -153,6 +153,7 @@ CAddress GetLocalAddress(const CNetAddr *paddrPeer = NULL); extern bool fDiscover; extern bool fListen; extern uint64_t nLocalServices; +extern bool fRelayTxes; extern uint64_t nLocalHostNonce; extern CAddrMan addrman; From 1ab1dc3140ff521df42f1f396a49a50e91bf2740 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 12 May 2016 14:09:43 +0200 Subject: [PATCH 0310/1802] rpc: Add `relaytxes` flag to `getnetworkinfo` Re-work of PR #7841 by dragongem45. Closes #7771. --- src/rpc/net.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 320091b9c4d4d..3297d2c6ee74c 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -460,6 +460,7 @@ UniValue getnetworkinfo(const UniValue& params, bool fHelp) " \"subversion\": \"/Satoshi:x.x.x/\", (string) the server subversion string\n" " \"protocolversion\": xxxxx, (numeric) the protocol version\n" " \"localservices\": \"xxxxxxxxxxxxxxxx\", (string) the services we offer to the network\n" + " \"localrelay\": true|false, (bool) true if transaction relay is requested from peers\n" " \"timeoffset\": xxxxx, (numeric) the time offset\n" " \"connections\": xxxxx, (numeric) the number of connections\n" " \"networks\": [ (array) information per network\n" @@ -494,6 +495,7 @@ UniValue getnetworkinfo(const UniValue& params, bool fHelp) obj.push_back(Pair("subversion", strSubVersion)); obj.push_back(Pair("protocolversion",PROTOCOL_VERSION)); obj.push_back(Pair("localservices", strprintf("%016x", nLocalServices))); + obj.push_back(Pair("localrelay", fRelayTxes)); obj.push_back(Pair("timeoffset", GetTimeOffset())); obj.push_back(Pair("connections", (int)vNodes.size())); obj.push_back(Pair("networks", GetNetworksInfo())); From 2692e1b10bd7a0be644ed8a69c54152bc741e855 Mon Sep 17 00:00:00 2001 From: fanquake Date: Mon, 9 May 2016 16:30:27 +0800 Subject: [PATCH 0311/1802] [Doc] Simplify OS X build notes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add —c++11 flags to brew dependancies that support it Remove release-build section, this is covered by depends/release-notes --- doc/build-osx.md | 136 +++++++++++++++++------------------------------ 1 file changed, 50 insertions(+), 86 deletions(-) diff --git a/doc/build-osx.md b/doc/build-osx.md index 296e0aa1f0726..89d7816c9a42b 100644 --- a/doc/build-osx.md +++ b/doc/build-osx.md @@ -1,129 +1,93 @@ Mac OS X Build Instructions and Notes ==================================== -This guide will show you how to build Bitcoin Core for OS X. - -Notes ------ - -* Tested on OS X 10.7 through 10.11 on 64-bit Intel processors only. - -* All of the commands should be executed in a Terminal application. The -built-in one is located in `/Applications/Utilities`. +The commands in this guide should be executed in a Terminal application. +The built-in one is located in `/Applications/Utilities/Terminal.app`. Preparation ----------- +Download and install [Xcode](https://developer.apple.com/xcode/download). -You need to install Xcode with all the options checked so that the compiler -and everything is available in /usr not just /Developer. Xcode should be -available on your OS X installation media, but if not, you can get the -current version from https://developer.apple.com/xcode/. If you install -Xcode 4.3 or later, you'll need to install its command line tools. This can -be done in `Xcode > Preferences > Downloads > Components` and generally must -be re-done or updated every time Xcode is updated. - -You will also need to install [Homebrew](http://brew.sh) in order to install library -dependencies. +Once installed, run `xcode-select --install` to install the OS X command line tools. -The installation of the actual dependencies is covered in the instructions -sections below. +Install [Homebrew](http://brew.sh). -Instructions: Homebrew +Dependencies ---------------------- -#### Install dependencies using Homebrew + brew install automake berkeley-db4 libtool boost --c++11 miniupnpc openssl pkg-config protobuf --c++11 qt5 libevent - brew install autoconf automake berkeley-db4 libtool boost miniupnpc openssl pkg-config protobuf qt5 libevent +NOTE: Building with Qt4 is still supported, however, could result in a broken UI. Building with Qt5 is recommended. -NOTE: Building with Qt4 is still supported, however, could result in a broken UI. As such, building with Qt5 is recommended. - -### Building `bitcoin` +Build Bitcoin Core +------------------------ -1. Clone the GitHub tree to get the source code and go into the directory. +1. Clone the bitcoin source code and cd into `bitcoin` - git clone https://github.com/bitcoin/bitcoin.git + git clone https://github.com/bitcoin/bitcoin cd bitcoin 2. Build bitcoin-core: - This will configure and build the headless bitcoin binaries as well as the gui (if Qt is found). - You can disable the gui build by passing `--without-gui` to configure. + + Configure and build the headless bitcoin binaries as well as the GUI (if Qt is found). + + You can disable the GUI build by passing `--without-gui` to configure. ./autogen.sh ./configure make -3. It is also a good idea to build and run the unit tests: +3. It is recommended to build and run the unit tests: make check -4. (Optional) You can also install bitcoind to your path: - - make install - -Use Qt Creator as IDE ------------------------- -You can use Qt Creator as IDE, for debugging and for manipulating forms, etc. -Download Qt Creator from https://www.qt.io/download/. Download the "community edition" and only install Qt Creator (uncheck the rest during the installation process). - -1. Make sure you installed everything through Homebrew mentioned above -2. Do a proper ./configure --enable-debug -3. In Qt Creator do "New Project" -> Import Project -> Import Existing Project -4. Enter "bitcoin-qt" as project name, enter src/qt as location -5. Leave the file selection as it is -6. Confirm the "summary page" -7. In the "Projects" tab select "Manage Kits..." -8. Select the default "Desktop" kit and select "Clang (x86 64bit in /usr/bin)" as compiler -9. Select LLDB as debugger (you might need to set the path to your installation) -10. Start debugging with Qt Creator - -Creating a release build ------------------------- -You can ignore this section if you are building `bitcoind` for your own use. - -bitcoind/bitcoin-cli binaries are not included in the Bitcoin-Qt.app bundle. - -If you are building `bitcoind` or `Bitcoin Core` for others, your build machine should be set up -as follows for maximum compatibility: +4. You can also create a .dmg that contains the .app bundle (optional): -All dependencies should be compiled with these flags: - - -mmacosx-version-min=10.7 - -arch x86_64 - -isysroot $(xcode-select --print-path)/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk - -Once dependencies are compiled, see [doc/release-process.md](release-process.md) for how the Bitcoin Core -bundle is packaged and signed to create the .dmg disk image that is distributed. + make deploy Running ------- -It's now available at `./bitcoind`, provided that you are still in the `src` -directory. We have to first create the RPC configuration file, though. +Bitcoin Core is now available at `./src/bitcoind` -Run `./bitcoind` to get the filename where it should be put, or just try these -commands: +Before running, it's recommended you create an RPC configuration file. echo -e "rpcuser=bitcoinrpc\nrpcpassword=$(xxd -l 16 -p /dev/urandom)" > "/Users/${USER}/Library/Application Support/Bitcoin/bitcoin.conf" + chmod 600 "/Users/${USER}/Library/Application Support/Bitcoin/bitcoin.conf" -The next time you run it, it will start downloading the blockchain, but it won't -output anything while it's doing this. This process may take several hours; -you can monitor its process by looking at the debug.log file, like this: +The first time you run bitcoind, it will start downloading the blockchain. This process could take several hours. + +You can monitor the download process by looking at the debug.log file: tail -f $HOME/Library/Application\ Support/Bitcoin/debug.log Other commands: ------- - ./bitcoind -daemon # to start the bitcoin daemon. - ./bitcoin-cli --help # for a list of command-line options. - ./bitcoin-cli help # When the daemon is running, to get a list of RPC commands + ./src/bitcoind -daemon # Starts the bitcoin daemon. + ./src/bitcoin-cli --help # Outputs a list of command-line options. + ./src/bitcoin-cli help # Outputs a list of RPC commands when the daemon is running. + +Using Qt Creator as IDE +------------------------ +You can use Qt Creator as an IDE, for bitcoin development. +Download and install the community edition of [Qt Creator](https://www.qt.io/download/). +Uncheck everything except Qt Creator during the installation process. -Using Qt official installer while building ------------------------------------------- +1. Make sure you installed everything through Homebrew mentioned above +2. Do a proper ./configure --enable-debug +3. In Qt Creator do "New Project" -> Import Project -> Import Existing Project +4. Enter "bitcoin-qt" as project name, enter src/qt as location +5. Leave the file selection as it is +6. Confirm the "summary page" +7. In the "Projects" tab select "Manage Kits..." +8. Select the default "Desktop" kit and select "Clang (x86 64bit in /usr/bin)" as compiler +9. Select LLDB as debugger (you might need to set the path to your installation) +10. Start debugging with Qt Creator + +Notes +----- + +* Tested on OS X 10.7 through 10.11 on 64-bit Intel processors only. -If you prefer to use the latest Qt installed from the official binary -installer over the brew version, you have to make several changes to -the installed tree and its binaries (all these changes are contained -in the brew version already). The changes needed are described in -[#7714](https://github.com/bitcoin/bitcoin/issues/7714). We do not -support building Bitcoin Core this way though. +* Building with downloaded Qt binaries is not officially supported. See the notes in [#7714](https://github.com/bitcoin/bitcoin/issues/7714) From 6bec172eb95e195847bb6dd6d4e62ada79c98c6d Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 30 Mar 2016 15:37:41 +0200 Subject: [PATCH 0312/1802] Add ctaes-based constant time AES implementation --- src/Makefile.am | 4 ++- src/crypto/aes.cpp | 73 +++++++++++++++++++++++++++++++++++++++ src/crypto/aes.h | 66 +++++++++++++++++++++++++++++++++++ src/test/crypto_tests.cpp | 56 ++++++++++++++++++++++++++++++ 4 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 src/crypto/aes.cpp create mode 100644 src/crypto/aes.h diff --git a/src/Makefile.am b/src/Makefile.am index 3c056386fac7b..0ab0d66ac21cb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -225,6 +225,8 @@ libbitcoin_wallet_a_SOURCES = \ crypto_libbitcoin_crypto_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_CONFIG_INCLUDES) crypto_libbitcoin_crypto_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) crypto_libbitcoin_crypto_a_SOURCES = \ + crypto/aes.cpp \ + crypto/aes.h \ crypto/common.h \ crypto/hmac_sha256.cpp \ crypto/hmac_sha256.h \ @@ -434,7 +436,7 @@ CLEANFILES += zmq/*.gcda zmq/*.gcno DISTCLEANFILES = obj/build.h -EXTRA_DIST = leveldb +EXTRA_DIST = leveldb crypto/ctaes clean-local: -$(MAKE) -C leveldb clean diff --git a/src/crypto/aes.cpp b/src/crypto/aes.cpp new file mode 100644 index 0000000000000..035abd75bdbdc --- /dev/null +++ b/src/crypto/aes.cpp @@ -0,0 +1,73 @@ +// Copyright (c) 2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "aes.h" +#include "crypto/common.h" + +#include +#include + +extern "C" { +#include "crypto/ctaes/ctaes.c" +} + +AES128Encrypt::AES128Encrypt(const unsigned char key[16]) +{ + AES128_init(&ctx, key); +} + +AES128Encrypt::~AES128Encrypt() +{ + memset(&ctx, 0, sizeof(ctx)); +} + +void AES128Encrypt::Encrypt(unsigned char ciphertext[16], const unsigned char plaintext[16]) const +{ + AES128_encrypt(&ctx, 1, ciphertext, plaintext); +} + +AES128Decrypt::AES128Decrypt(const unsigned char key[16]) +{ + AES128_init(&ctx, key); +} + +AES128Decrypt::~AES128Decrypt() +{ + memset(&ctx, 0, sizeof(ctx)); +} + +void AES128Decrypt::Decrypt(unsigned char plaintext[16], const unsigned char ciphertext[16]) const +{ + AES128_decrypt(&ctx, 1, plaintext, ciphertext); +} + +AES256Encrypt::AES256Encrypt(const unsigned char key[32]) +{ + AES256_init(&ctx, key); +} + +AES256Encrypt::~AES256Encrypt() +{ + memset(&ctx, 0, sizeof(ctx)); +} + +void AES256Encrypt::Encrypt(unsigned char ciphertext[16], const unsigned char plaintext[16]) const +{ + AES256_encrypt(&ctx, 1, ciphertext, plaintext); +} + +AES256Decrypt::AES256Decrypt(const unsigned char key[32]) +{ + AES256_init(&ctx, key); +} + +AES256Decrypt::~AES256Decrypt() +{ + memset(&ctx, 0, sizeof(ctx)); +} + +void AES256Decrypt::Decrypt(unsigned char plaintext[16], const unsigned char ciphertext[16]) const +{ + AES256_decrypt(&ctx, 1, plaintext, ciphertext); +} diff --git a/src/crypto/aes.h b/src/crypto/aes.h new file mode 100644 index 0000000000000..4bf17a33eae55 --- /dev/null +++ b/src/crypto/aes.h @@ -0,0 +1,66 @@ +// Copyright (c) 2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// +// C++ wrapper around ctaes, a constant-time AES implementation + +#ifndef BITCOIN_CRYPTO_AES_H +#define BITCOIN_CRYPTO_AES_H + +extern "C" { +#include "crypto/ctaes/ctaes.h" +} + +static const int AES_BLOCKSIZE = 16; +static const int AES128_KEYSIZE = 16; +static const int AES256_KEYSIZE = 32; + +/** An encryption class for AES-128. */ +class AES128Encrypt +{ +private: + AES128_ctx ctx; + +public: + AES128Encrypt(const unsigned char key[16]); + ~AES128Encrypt(); + void Encrypt(unsigned char ciphertext[16], const unsigned char plaintext[16]) const; +}; + +/** A decryption class for AES-128. */ +class AES128Decrypt +{ +private: + AES128_ctx ctx; + +public: + AES128Decrypt(const unsigned char key[16]); + ~AES128Decrypt(); + void Decrypt(unsigned char plaintext[16], const unsigned char ciphertext[16]) const; +}; + +/** An encryption class for AES-256. */ +class AES256Encrypt +{ +private: + AES256_ctx ctx; + +public: + AES256Encrypt(const unsigned char key[32]); + ~AES256Encrypt(); + void Encrypt(unsigned char ciphertext[16], const unsigned char plaintext[16]) const; +}; + +/** A decryption class for AES-256. */ +class AES256Decrypt +{ +private: + AES256_ctx ctx; + +public: + AES256Decrypt(const unsigned char key[32]); + ~AES256Decrypt(); + void Decrypt(unsigned char plaintext[16], const unsigned char ciphertext[16]) const; +}; + +#endif // BITCOIN_CRYPTO_AES_H diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index 0b46d718d1d13..3fc9855d6ab63 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -2,6 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "crypto/aes.h" #include "crypto/ripemd160.h" #include "crypto/sha1.h" #include "crypto/sha256.h" @@ -63,6 +64,45 @@ void TestHMACSHA512(const std::string &hexkey, const std::string &hexin, const s TestVector(CHMAC_SHA512(&key[0], key.size()), ParseHex(hexin), ParseHex(hexout)); } +void TestAES128(const std::string &hexkey, const std::string &hexin, const std::string &hexout) +{ + std::vector key = ParseHex(hexkey); + std::vector in = ParseHex(hexin); + std::vector correctout = ParseHex(hexout); + std::vector buf, buf2; + + assert(key.size() == 16); + assert(in.size() == 16); + assert(correctout.size() == 16); + AES128Encrypt enc(&key[0]); + buf.resize(correctout.size()); + buf2.resize(correctout.size()); + enc.Encrypt(&buf[0], &in[0]); + BOOST_CHECK_EQUAL(HexStr(buf), HexStr(correctout)); + AES128Decrypt dec(&key[0]); + dec.Decrypt(&buf2[0], &buf[0]); + BOOST_CHECK_EQUAL(HexStr(buf2), HexStr(in)); +} + +void TestAES256(const std::string &hexkey, const std::string &hexin, const std::string &hexout) +{ + std::vector key = ParseHex(hexkey); + std::vector in = ParseHex(hexin); + std::vector correctout = ParseHex(hexout); + std::vector buf; + + assert(key.size() == 32); + assert(in.size() == 16); + assert(correctout.size() == 16); + AES256Encrypt enc(&key[0]); + buf.resize(correctout.size()); + enc.Encrypt(&buf[0], &in[0]); + BOOST_CHECK(buf == correctout); + AES256Decrypt dec(&key[0]); + dec.Decrypt(&buf[0], &buf[0]); + BOOST_CHECK(buf == in); +} + std::string LongTestString(void) { std::string ret; for (int i=0; i<200000; i++) { @@ -248,4 +288,20 @@ BOOST_AUTO_TEST_CASE(hmac_sha512_testvectors) { "b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58"); } +BOOST_AUTO_TEST_CASE(aes_testvectors) { + // AES test vectors from FIPS 197. + TestAES128("000102030405060708090a0b0c0d0e0f", "00112233445566778899aabbccddeeff", "69c4e0d86a7b0430d8cdb78070b4c55a"); + TestAES256("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "00112233445566778899aabbccddeeff", "8ea2b7ca516745bfeafc49904b496089"); + + // AES-ECB test vectors from NIST sp800-38a. + TestAES128("2b7e151628aed2a6abf7158809cf4f3c", "6bc1bee22e409f96e93d7e117393172a", "3ad77bb40d7a3660a89ecaf32466ef97"); + TestAES128("2b7e151628aed2a6abf7158809cf4f3c", "ae2d8a571e03ac9c9eb76fac45af8e51", "f5d3d58503b9699de785895a96fdbaaf"); + TestAES128("2b7e151628aed2a6abf7158809cf4f3c", "30c81c46a35ce411e5fbc1191a0a52ef", "43b1cd7f598ece23881b00e3ed030688"); + TestAES128("2b7e151628aed2a6abf7158809cf4f3c", "f69f2445df4f9b17ad2b417be66c3710", "7b0c785e27e8ad3f8223207104725dd4"); + TestAES256("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "6bc1bee22e409f96e93d7e117393172a", "f3eed1bdb5d2a03c064b5a7e3db181f8"); + TestAES256("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "ae2d8a571e03ac9c9eb76fac45af8e51", "591ccb10d410ed26dc5ba74a31362870"); + TestAES256("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "30c81c46a35ce411e5fbc1191a0a52ef", "b6ed21b99ca6f4f9f153e7b1beafed1d"); + TestAES256("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "f69f2445df4f9b17ad2b417be66c3710", "23304b7a39f9f3ff067d8d8f9e24ecc7"); +} + BOOST_AUTO_TEST_SUITE_END() From 27a212dcb4fe842ead77d01b98f2c1a58ecca609 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 20 Mar 2015 00:49:13 -0400 Subject: [PATCH 0313/1802] crypto: add AES 128/256 CBC classes The output should always match openssl's, even for failed operations. Even for a decrypt with broken padding, the output is always deterministic (and attemtps to be constant-time). --- src/crypto/aes.cpp | 144 +++++++++++++++++++++++++++++++++++++++++++++ src/crypto/aes.h | 52 ++++++++++++++++ 2 files changed, 196 insertions(+) diff --git a/src/crypto/aes.cpp b/src/crypto/aes.cpp index 035abd75bdbdc..1d469d0fb4622 100644 --- a/src/crypto/aes.cpp +++ b/src/crypto/aes.cpp @@ -71,3 +71,147 @@ void AES256Decrypt::Decrypt(unsigned char plaintext[16], const unsigned char cip { AES256_decrypt(&ctx, 1, plaintext, ciphertext); } + + +template +static int CBCEncrypt(const T& enc, const unsigned char iv[AES_BLOCKSIZE], const unsigned char* data, int size, bool pad, unsigned char* out) +{ + int written = 0; + int padsize = size % AES_BLOCKSIZE; + unsigned char mixed[AES_BLOCKSIZE]; + + if (!data || !size || !out) + return 0; + + if (!pad && padsize != 0) + return 0; + + memcpy(mixed, iv, AES_BLOCKSIZE); + + // Write all but the last block + while (written + AES_BLOCKSIZE <= size) { + for (int i = 0; i != AES_BLOCKSIZE; i++) + mixed[i] ^= *data++; + enc.Encrypt(out + written, mixed); + memcpy(mixed, out + written, AES_BLOCKSIZE); + written += AES_BLOCKSIZE; + } + if (pad) { + // For all that remains, pad each byte with the value of the remaining + // space. If there is none, pad by a full block. + for (int i = 0; i != padsize; i++) + mixed[i] ^= *data++; + for (int i = padsize; i != AES_BLOCKSIZE; i++) + mixed[i] ^= AES_BLOCKSIZE - padsize; + enc.Encrypt(out + written, mixed); + written += AES_BLOCKSIZE; + } + return written; +} + +template +static int CBCDecrypt(const T& dec, const unsigned char iv[AES_BLOCKSIZE], const unsigned char* data, int size, bool pad, unsigned char* out) +{ + unsigned char padsize = 0; + int written = 0; + bool fail = false; + const unsigned char* prev = iv; + + if (!data || !size || !out) + return 0; + + if (size % AES_BLOCKSIZE != 0) + return 0; + + // Decrypt all data. Padding will be checked in the output. + while (written != size) { + dec.Decrypt(out, data + written); + for (int i = 0; i != AES_BLOCKSIZE; i++) + *out++ ^= prev[i]; + prev = data + written; + written += AES_BLOCKSIZE; + } + + // When decrypting padding, attempt to run in constant-time + if (pad) { + // If used, padding size is the value of the last decrypted byte. For + // it to be valid, It must be between 1 and AES_BLOCKSIZE. + padsize = *--out; + fail = !padsize | (padsize > AES_BLOCKSIZE); + + // If not well-formed, treat it as though there's no padding. + padsize *= !fail; + + // All padding must equal the last byte otherwise it's not well-formed + for (int i = AES_BLOCKSIZE; i != 0; i--) + fail |= ((i > AES_BLOCKSIZE - padsize) & (*out-- != padsize)); + + written -= padsize; + } + return written * !fail; +} + +AES256CBCEncrypt::AES256CBCEncrypt(const unsigned char key[AES256_KEYSIZE], const unsigned char ivIn[AES_BLOCKSIZE], bool padIn) + : enc(key), pad(padIn) +{ + memcpy(iv, ivIn, AES_BLOCKSIZE); +} + +int AES256CBCEncrypt::Encrypt(const unsigned char* data, int size, unsigned char* out) const +{ + return CBCEncrypt(enc, iv, data, size, pad, out); +} + +AES256CBCEncrypt::~AES256CBCEncrypt() +{ + memset(iv, 0, sizeof(iv)); +} + +AES256CBCDecrypt::AES256CBCDecrypt(const unsigned char key[AES256_KEYSIZE], const unsigned char ivIn[AES_BLOCKSIZE], bool padIn) + : dec(key), pad(padIn) +{ + memcpy(iv, ivIn, AES_BLOCKSIZE); +} + + +int AES256CBCDecrypt::Decrypt(const unsigned char* data, int size, unsigned char* out) const +{ + return CBCDecrypt(dec, iv, data, size, pad, out); +} + +AES256CBCDecrypt::~AES256CBCDecrypt() +{ + memset(iv, 0, sizeof(iv)); +} + +AES128CBCEncrypt::AES128CBCEncrypt(const unsigned char key[AES128_KEYSIZE], const unsigned char ivIn[AES_BLOCKSIZE], bool padIn) + : enc(key), pad(padIn) +{ + memcpy(iv, ivIn, AES_BLOCKSIZE); +} + +AES128CBCEncrypt::~AES128CBCEncrypt() +{ + memset(iv, 0, AES_BLOCKSIZE); +} + +int AES128CBCEncrypt::Encrypt(const unsigned char* data, int size, unsigned char* out) const +{ + return CBCEncrypt(enc, iv, data, size, pad, out); +} + +AES128CBCDecrypt::AES128CBCDecrypt(const unsigned char key[AES128_KEYSIZE], const unsigned char ivIn[AES_BLOCKSIZE], bool padIn) + : dec(key), pad(padIn) +{ + memcpy(iv, ivIn, AES_BLOCKSIZE); +} + +AES128CBCDecrypt::~AES128CBCDecrypt() +{ + memset(iv, 0, AES_BLOCKSIZE); +} + +int AES128CBCDecrypt::Decrypt(const unsigned char* data, int size, unsigned char* out) const +{ + return CBCDecrypt(dec, iv, data, size, pad, out); +} diff --git a/src/crypto/aes.h b/src/crypto/aes.h index 4bf17a33eae55..8cae357c1287e 100644 --- a/src/crypto/aes.h +++ b/src/crypto/aes.h @@ -63,4 +63,56 @@ class AES256Decrypt void Decrypt(unsigned char plaintext[16], const unsigned char ciphertext[16]) const; }; +class AES256CBCEncrypt +{ +public: + AES256CBCEncrypt(const unsigned char key[AES256_KEYSIZE], const unsigned char ivIn[AES_BLOCKSIZE], bool padIn); + ~AES256CBCEncrypt(); + int Encrypt(const unsigned char* data, int size, unsigned char* out) const; + +private: + const AES256Encrypt enc; + const bool pad; + unsigned char iv[AES_BLOCKSIZE]; +}; + +class AES256CBCDecrypt +{ +public: + AES256CBCDecrypt(const unsigned char key[AES256_KEYSIZE], const unsigned char ivIn[AES_BLOCKSIZE], bool padIn); + ~AES256CBCDecrypt(); + int Decrypt(const unsigned char* data, int size, unsigned char* out) const; + +private: + const AES256Decrypt dec; + const bool pad; + unsigned char iv[AES_BLOCKSIZE]; +}; + +class AES128CBCEncrypt +{ +public: + AES128CBCEncrypt(const unsigned char key[AES128_KEYSIZE], const unsigned char ivIn[AES_BLOCKSIZE], bool padIn); + ~AES128CBCEncrypt(); + int Encrypt(const unsigned char* data, int size, unsigned char* out) const; + +private: + const AES128Encrypt enc; + const bool pad; + unsigned char iv[AES_BLOCKSIZE]; +}; + +class AES128CBCDecrypt +{ +public: + AES128CBCDecrypt(const unsigned char key[AES128_KEYSIZE], const unsigned char ivIn[AES_BLOCKSIZE], bool padIn); + ~AES128CBCDecrypt(); + int Decrypt(const unsigned char* data, int size, unsigned char* out) const; + +private: + const AES128Decrypt dec; + const bool pad; + unsigned char iv[AES_BLOCKSIZE]; +}; + #endif // BITCOIN_CRYPTO_AES_H From daa384120a63542257d4ca73047d775f16fac654 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 20 Mar 2015 00:52:58 -0400 Subject: [PATCH 0314/1802] crypto: add aes cbc tests --- src/test/crypto_tests.cpp | 135 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index 3fc9855d6ab63..58a62ee02262d 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -17,6 +17,8 @@ #include #include +#include +#include BOOST_FIXTURE_TEST_SUITE(crypto_tests, BasicTestingSetup) @@ -103,6 +105,88 @@ void TestAES256(const std::string &hexkey, const std::string &hexin, const std:: BOOST_CHECK(buf == in); } +void TestAES128CBC(const std::string &hexkey, const std::string &hexiv, bool pad, const std::string &hexin, const std::string &hexout) +{ + std::vector key = ParseHex(hexkey); + std::vector iv = ParseHex(hexiv); + std::vector in = ParseHex(hexin); + std::vector correctout = ParseHex(hexout); + std::vector realout(in.size() + AES_BLOCKSIZE); + + // Encrypt the plaintext and verify that it equals the cipher + AES128CBCEncrypt enc(&key[0], &iv[0], pad); + int size = enc.Encrypt(&in[0], in.size(), &realout[0]); + realout.resize(size); + BOOST_CHECK(realout.size() == correctout.size()); + BOOST_CHECK_MESSAGE(realout == correctout, HexStr(realout) + std::string(" != ") + hexout); + + // Decrypt the cipher and verify that it equals the plaintext + std::vector decrypted(correctout.size()); + AES128CBCDecrypt dec(&key[0], &iv[0], pad); + size = dec.Decrypt(&correctout[0], correctout.size(), &decrypted[0]); + decrypted.resize(size); + BOOST_CHECK(decrypted.size() == in.size()); + BOOST_CHECK_MESSAGE(decrypted == in, HexStr(decrypted) + std::string(" != ") + hexin); + + // Encrypt and re-decrypt substrings of the plaintext and verify that they equal each-other + for(std::vector::iterator i(in.begin()); i != in.end(); ++i) + { + std::vector sub(i, in.end()); + std::vector subout(sub.size() + AES_BLOCKSIZE); + int size = enc.Encrypt(&sub[0], sub.size(), &subout[0]); + if (size != 0) + { + subout.resize(size); + std::vector subdecrypted(subout.size()); + size = dec.Decrypt(&subout[0], subout.size(), &subdecrypted[0]); + subdecrypted.resize(size); + BOOST_CHECK(decrypted.size() == in.size()); + BOOST_CHECK_MESSAGE(subdecrypted == sub, HexStr(subdecrypted) + std::string(" != ") + HexStr(sub)); + } + } +} + +void TestAES256CBC(const std::string &hexkey, const std::string &hexiv, bool pad, const std::string &hexin, const std::string &hexout) +{ + std::vector key = ParseHex(hexkey); + std::vector iv = ParseHex(hexiv); + std::vector in = ParseHex(hexin); + std::vector correctout = ParseHex(hexout); + std::vector realout(in.size() + AES_BLOCKSIZE); + + // Encrypt the plaintext and verify that it equals the cipher + AES256CBCEncrypt enc(&key[0], &iv[0], pad); + int size = enc.Encrypt(&in[0], in.size(), &realout[0]); + realout.resize(size); + BOOST_CHECK(realout.size() == correctout.size()); + BOOST_CHECK_MESSAGE(realout == correctout, HexStr(realout) + std::string(" != ") + hexout); + + // Decrypt the cipher and verify that it equals the plaintext + std::vector decrypted(correctout.size()); + AES256CBCDecrypt dec(&key[0], &iv[0], pad); + size = dec.Decrypt(&correctout[0], correctout.size(), &decrypted[0]); + decrypted.resize(size); + BOOST_CHECK(decrypted.size() == in.size()); + BOOST_CHECK_MESSAGE(decrypted == in, HexStr(decrypted) + std::string(" != ") + hexin); + + // Encrypt and re-decrypt substrings of the plaintext and verify that they equal each-other + for(std::vector::iterator i(in.begin()); i != in.end(); ++i) + { + std::vector sub(i, in.end()); + std::vector subout(sub.size() + AES_BLOCKSIZE); + int size = enc.Encrypt(&sub[0], sub.size(), &subout[0]); + if (size != 0) + { + subout.resize(size); + std::vector subdecrypted(subout.size()); + size = dec.Decrypt(&subout[0], subout.size(), &subdecrypted[0]); + subdecrypted.resize(size); + BOOST_CHECK(decrypted.size() == in.size()); + BOOST_CHECK_MESSAGE(subdecrypted == sub, HexStr(subdecrypted) + std::string(" != ") + HexStr(sub)); + } + } +} + std::string LongTestString(void) { std::string ret; for (int i=0; i<200000; i++) { @@ -304,4 +388,55 @@ BOOST_AUTO_TEST_CASE(aes_testvectors) { TestAES256("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "f69f2445df4f9b17ad2b417be66c3710", "23304b7a39f9f3ff067d8d8f9e24ecc7"); } +BOOST_AUTO_TEST_CASE(aes_cbc_testvectors) { + + // NIST AES CBC 128-bit encryption test-vectors + TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", false, \ + "6bc1bee22e409f96e93d7e117393172a", "7649abac8119b246cee98e9b12e9197d"); + TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "7649ABAC8119B246CEE98E9B12E9197D", false, \ + "ae2d8a571e03ac9c9eb76fac45af8e51", "5086cb9b507219ee95db113a917678b2"); + TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "5086cb9b507219ee95db113a917678b2", false, \ + "30c81c46a35ce411e5fbc1191a0a52ef", "73bed6b8e3c1743b7116e69e22229516"); + TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "73bed6b8e3c1743b7116e69e22229516", false, \ + "f69f2445df4f9b17ad2b417be66c3710", "3ff1caa1681fac09120eca307586e1a7"); + + // The same vectors with padding enabled + TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", true, \ + "6bc1bee22e409f96e93d7e117393172a", "7649abac8119b246cee98e9b12e9197d8964e0b149c10b7b682e6e39aaeb731c"); + TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "7649ABAC8119B246CEE98E9B12E9197D", true, \ + "ae2d8a571e03ac9c9eb76fac45af8e51", "5086cb9b507219ee95db113a917678b255e21d7100b988ffec32feeafaf23538"); + TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "5086cb9b507219ee95db113a917678b2", true, \ + "30c81c46a35ce411e5fbc1191a0a52ef", "73bed6b8e3c1743b7116e69e22229516f6eccda327bf8e5ec43718b0039adceb"); + TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "73bed6b8e3c1743b7116e69e22229516", true, \ + "f69f2445df4f9b17ad2b417be66c3710", "3ff1caa1681fac09120eca307586e1a78cb82807230e1321d3fae00d18cc2012"); + + // NIST AES CBC 256-bit encryption test-vectors + TestAES256CBC("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", \ + "000102030405060708090A0B0C0D0E0F", false, "6bc1bee22e409f96e93d7e117393172a", \ + "f58c4c04d6e5f1ba779eabfb5f7bfbd6"); + TestAES256CBC("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", \ + "F58C4C04D6E5F1BA779EABFB5F7BFBD6", false, "ae2d8a571e03ac9c9eb76fac45af8e51", \ + "9cfc4e967edb808d679f777bc6702c7d"); + TestAES256CBC("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", \ + "9CFC4E967EDB808D679F777BC6702C7D", false, "30c81c46a35ce411e5fbc1191a0a52ef", + "39f23369a9d9bacfa530e26304231461"); + TestAES256CBC("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", \ + "39F23369A9D9BACFA530E26304231461", false, "f69f2445df4f9b17ad2b417be66c3710", \ + "b2eb05e2c39be9fcda6c19078c6a9d1b"); + + // The same vectors with padding enabled + TestAES256CBC("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", \ + "000102030405060708090A0B0C0D0E0F", true, "6bc1bee22e409f96e93d7e117393172a", \ + "f58c4c04d6e5f1ba779eabfb5f7bfbd6485a5c81519cf378fa36d42b8547edc0"); + TestAES256CBC("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", \ + "F58C4C04D6E5F1BA779EABFB5F7BFBD6", true, "ae2d8a571e03ac9c9eb76fac45af8e51", \ + "9cfc4e967edb808d679f777bc6702c7d3a3aa5e0213db1a9901f9036cf5102d2"); + TestAES256CBC("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", \ + "9CFC4E967EDB808D679F777BC6702C7D", true, "30c81c46a35ce411e5fbc1191a0a52ef", + "39f23369a9d9bacfa530e263042314612f8da707643c90a6f732b3de1d3f5cee"); + TestAES256CBC("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", \ + "39F23369A9D9BACFA530E26304231461", true, "f69f2445df4f9b17ad2b417be66c3710", \ + "b2eb05e2c39be9fcda6c19078c6a9d1b3f461796d6b0d6b2e0c2a72b4d80e644"); +} + BOOST_AUTO_TEST_SUITE_END() From 1c391a5866e1342617b51041afebee2215e9a30c Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 20 Mar 2015 01:05:47 -0400 Subject: [PATCH 0315/1802] crypter: fix the stored initialization vector size AES IV's are 16bytes, not 32. This was harmless but confusing. Add WALLET_CRYPTO_IV_SIZE to make its usage explicit. --- src/wallet/crypter.cpp | 10 +++++----- src/wallet/crypter.h | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp index 95aa4c2593164..8f555579fa3b5 100644 --- a/src/wallet/crypter.cpp +++ b/src/wallet/crypter.cpp @@ -37,7 +37,7 @@ bool CCrypter::SetKeyFromPassphrase(const SecureString& strKeyData, const std::v bool CCrypter::SetKey(const CKeyingMaterial& chNewKey, const std::vector& chNewIV) { - if (chNewKey.size() != WALLET_CRYPTO_KEY_SIZE || chNewIV.size() != WALLET_CRYPTO_KEY_SIZE) + if (chNewKey.size() != WALLET_CRYPTO_KEY_SIZE || chNewIV.size() != WALLET_CRYPTO_IV_SIZE) return false; memcpy(&chKey[0], &chNewKey[0], sizeof chKey); @@ -105,8 +105,8 @@ bool CCrypter::Decrypt(const std::vector& vchCiphertext, CKeyingM static bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256& nIV, std::vector &vchCiphertext) { CCrypter cKeyCrypter; - std::vector chIV(WALLET_CRYPTO_KEY_SIZE); - memcpy(&chIV[0], &nIV, WALLET_CRYPTO_KEY_SIZE); + std::vector chIV(WALLET_CRYPTO_IV_SIZE); + memcpy(&chIV[0], &nIV, WALLET_CRYPTO_IV_SIZE); if(!cKeyCrypter.SetKey(vMasterKey, chIV)) return false; return cKeyCrypter.Encrypt(*((const CKeyingMaterial*)&vchPlaintext), vchCiphertext); @@ -115,8 +115,8 @@ static bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMateri static bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext) { CCrypter cKeyCrypter; - std::vector chIV(WALLET_CRYPTO_KEY_SIZE); - memcpy(&chIV[0], &nIV, WALLET_CRYPTO_KEY_SIZE); + std::vector chIV(WALLET_CRYPTO_IV_SIZE); + memcpy(&chIV[0], &nIV, WALLET_CRYPTO_IV_SIZE); if(!cKeyCrypter.SetKey(vMasterKey, chIV)) return false; return cKeyCrypter.Decrypt(vchCiphertext, *((CKeyingMaterial*)&vchPlaintext)); diff --git a/src/wallet/crypter.h b/src/wallet/crypter.h index eb06a7866a96c..b4727ac8ac090 100644 --- a/src/wallet/crypter.h +++ b/src/wallet/crypter.h @@ -13,6 +13,7 @@ class uint256; const unsigned int WALLET_CRYPTO_KEY_SIZE = 32; const unsigned int WALLET_CRYPTO_SALT_SIZE = 8; +const unsigned int WALLET_CRYPTO_IV_SIZE = 16; /** * Private key encryption is done based on a CMasterKey, @@ -71,7 +72,7 @@ class CCrypter { private: unsigned char chKey[WALLET_CRYPTO_KEY_SIZE]; - unsigned char chIV[WALLET_CRYPTO_KEY_SIZE]; + unsigned char chIV[WALLET_CRYPTO_IV_SIZE]; bool fKeySet; public: From fb96831c1ff767cd86099f66127fa4dc1ec6e277 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 26 Mar 2015 17:37:29 -0400 Subject: [PATCH 0316/1802] crypter: constify encrypt/decrypt This makes CCrypter easier to pass aroundf for tests --- src/wallet/crypter.cpp | 4 ++-- src/wallet/crypter.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp index 8f555579fa3b5..e37a9c4c85d4e 100644 --- a/src/wallet/crypter.cpp +++ b/src/wallet/crypter.cpp @@ -47,7 +47,7 @@ bool CCrypter::SetKey(const CKeyingMaterial& chNewKey, const std::vector &vchCiphertext) +bool CCrypter::Encrypt(const CKeyingMaterial& vchPlaintext, std::vector &vchCiphertext) const { if (!fKeySet) return false; @@ -74,7 +74,7 @@ bool CCrypter::Encrypt(const CKeyingMaterial& vchPlaintext, std::vector& vchCiphertext, CKeyingMaterial& vchPlaintext) +bool CCrypter::Decrypt(const std::vector& vchCiphertext, CKeyingMaterial& vchPlaintext) const { if (!fKeySet) return false; diff --git a/src/wallet/crypter.h b/src/wallet/crypter.h index b4727ac8ac090..3457d40ffd029 100644 --- a/src/wallet/crypter.h +++ b/src/wallet/crypter.h @@ -77,8 +77,8 @@ class CCrypter public: bool SetKeyFromPassphrase(const SecureString &strKeyData, const std::vector& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod); - bool Encrypt(const CKeyingMaterial& vchPlaintext, std::vector &vchCiphertext); - bool Decrypt(const std::vector& vchCiphertext, CKeyingMaterial& vchPlaintext); + bool Encrypt(const CKeyingMaterial& vchPlaintext, std::vector &vchCiphertext) const; + bool Decrypt(const std::vector& vchCiphertext, CKeyingMaterial& vchPlaintext) const; bool SetKey(const CKeyingMaterial& chNewKey, const std::vector& chNewIV); void CleanKey() From 9049cde4d962862f507f9ddf1c0dbd49ea04be51 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 20 Mar 2015 01:10:30 -0400 Subject: [PATCH 0317/1802] crypter: hook up the new aes cbc classes --- src/wallet/crypter.cpp | 45 +++++++++++++----------------------------- 1 file changed, 14 insertions(+), 31 deletions(-) diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp index e37a9c4c85d4e..0a19139a3172a 100644 --- a/src/wallet/crypter.cpp +++ b/src/wallet/crypter.cpp @@ -4,6 +4,7 @@ #include "crypter.h" +#include "crypto/aes.h" #include "script/script.h" #include "script/standard.h" #include "util.h" @@ -53,24 +54,15 @@ bool CCrypter::Encrypt(const CKeyingMaterial& vchPlaintext, std::vector (nCLen); + // n + AES_BLOCKSIZE bytes + vchCiphertext.resize(vchPlaintext.size() + AES_BLOCKSIZE); - EVP_CIPHER_CTX ctx; - - bool fOk = true; - - EVP_CIPHER_CTX_init(&ctx); - if (fOk) fOk = EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV) != 0; - if (fOk) fOk = EVP_EncryptUpdate(&ctx, &vchCiphertext[0], &nCLen, &vchPlaintext[0], nLen) != 0; - if (fOk) fOk = EVP_EncryptFinal_ex(&ctx, (&vchCiphertext[0]) + nCLen, &nFLen) != 0; - EVP_CIPHER_CTX_cleanup(&ctx); - - if (!fOk) return false; + AES256CBCEncrypt enc(chKey, chIV, true); + size_t nLen = enc.Encrypt(&vchPlaintext[0], vchPlaintext.size(), &vchCiphertext[0]); + if(nLen < vchPlaintext.size()) + return false; + vchCiphertext.resize(nLen); - vchCiphertext.resize(nCLen + nFLen); return true; } @@ -81,23 +73,14 @@ bool CCrypter::Decrypt(const std::vector& vchCiphertext, CKeyingM // plaintext will always be equal to or lesser than length of ciphertext int nLen = vchCiphertext.size(); - int nPLen = nLen, nFLen = 0; - - vchPlaintext = CKeyingMaterial(nPLen); - EVP_CIPHER_CTX ctx; + vchPlaintext.resize(nLen); - bool fOk = true; - - EVP_CIPHER_CTX_init(&ctx); - if (fOk) fOk = EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV) != 0; - if (fOk) fOk = EVP_DecryptUpdate(&ctx, &vchPlaintext[0], &nPLen, &vchCiphertext[0], nLen) != 0; - if (fOk) fOk = EVP_DecryptFinal_ex(&ctx, (&vchPlaintext[0]) + nPLen, &nFLen) != 0; - EVP_CIPHER_CTX_cleanup(&ctx); - - if (!fOk) return false; - - vchPlaintext.resize(nPLen + nFLen); + AES256CBCDecrypt dec(chKey, chIV, true); + nLen = dec.Decrypt(&vchCiphertext[0], vchCiphertext.size(), &vchPlaintext[0]); + if(nLen == 0) + return false; + vchPlaintext.resize(nLen); return true; } From 976f9ec2645242032d34ab68a60d963f2ac586d8 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 20 Mar 2015 01:24:12 -0400 Subject: [PATCH 0318/1802] crypter: add a BytesToKey clone to replace the use of openssl BytesToKeySHA512AES should be functionally identical to EVP_BytesToKey, but drops the dependency on openssl. --- src/wallet/crypter.cpp | 33 +++++++++++++++++++++++++++++---- src/wallet/crypter.h | 2 ++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp index 0a19139a3172a..190f8ecf2ab49 100644 --- a/src/wallet/crypter.cpp +++ b/src/wallet/crypter.cpp @@ -5,6 +5,7 @@ #include "crypter.h" #include "crypto/aes.h" +#include "crypto/sha512.h" #include "script/script.h" #include "script/standard.h" #include "util.h" @@ -12,8 +13,33 @@ #include #include #include -#include -#include + +int CCrypter::BytesToKeySHA512AES(const std::vector& chSalt, const SecureString& strKeyData, int count, unsigned char *key,unsigned char *iv) const +{ + // This mimics the behavior of openssl's EVP_BytesToKey with an aes256cbc + // cipher and sha512 message digest. Because sha512's output size (64b) is + // greater than the aes256 block size (16b) + aes256 key size (32b), + // there's no need to process more than once (D_0). + + if(!count || !key || !iv) + return 0; + + unsigned char buf[CSHA512::OUTPUT_SIZE]; + CSHA512 di; + + di.Write((const unsigned char*)strKeyData.c_str(), strKeyData.size()); + if(chSalt.size()) + di.Write(&chSalt[0], chSalt.size()); + di.Finalize(buf); + + for(int i = 0; i != count - 1; i++) + di.Reset().Write(buf, sizeof(buf)).Finalize(buf); + + memcpy(key, buf, WALLET_CRYPTO_KEY_SIZE); + memcpy(iv, buf + WALLET_CRYPTO_KEY_SIZE, WALLET_CRYPTO_IV_SIZE); + memory_cleanse(buf, sizeof(buf)); + return WALLET_CRYPTO_KEY_SIZE; +} bool CCrypter::SetKeyFromPassphrase(const SecureString& strKeyData, const std::vector& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod) { @@ -22,8 +48,7 @@ bool CCrypter::SetKeyFromPassphrase(const SecureString& strKeyData, const std::v int i = 0; if (nDerivationMethod == 0) - i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha512(), &chSalt[0], - (unsigned char *)&strKeyData[0], strKeyData.size(), nRounds, chKey, chIV); + i = BytesToKeySHA512AES(chSalt, strKeyData, nRounds, chKey, chIV); if (i != (int)WALLET_CRYPTO_KEY_SIZE) { diff --git a/src/wallet/crypter.h b/src/wallet/crypter.h index 3457d40ffd029..16f2ba622069c 100644 --- a/src/wallet/crypter.h +++ b/src/wallet/crypter.h @@ -75,6 +75,8 @@ class CCrypter unsigned char chIV[WALLET_CRYPTO_IV_SIZE]; bool fKeySet; + int BytesToKeySHA512AES(const std::vector& chSalt, const SecureString& strKeyData, int count, unsigned char *key,unsigned char *iv) const; + public: bool SetKeyFromPassphrase(const SecureString &strKeyData, const std::vector& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod); bool Encrypt(const CKeyingMaterial& vchPlaintext, std::vector &vchCiphertext) const; From 0a36b9af281e31b080ca0835eec7704097527bda Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 26 Mar 2015 19:15:28 -0400 Subject: [PATCH 0319/1802] crypter: shuffle Makefile so that crypto can be used by the wallet Wallet must come before crypto, otherwise linking fails on some platforms. Includes a tangentially-related general cleanup rather than making the Makefile sloppier. --- src/Makefile.am | 55 +++++++++++++++++++++---------------------------- 1 file changed, 23 insertions(+), 32 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 0ab0d66ac21cb..31917f1350e46 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -15,13 +15,12 @@ LIBUNIVALUE = $(UNIVALUE_LIBS) endif BITCOIN_CONFIG_INCLUDES=-I$(builddir)/config -BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) $(SSL_CFLAGS) +BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) $(SSL_CFLAGS) BITCOIN_INCLUDES += -I$(srcdir)/secp256k1/include BITCOIN_INCLUDES += $(UNIVALUE_CFLAGS) LIBBITCOIN_SERVER=libbitcoin_server.a -LIBBITCOIN_WALLET=libbitcoin_wallet.a LIBBITCOIN_COMMON=libbitcoin_common.a LIBBITCOIN_CONSENSUS=libbitcoin_consensus.a LIBBITCOIN_CLI=libbitcoin_cli.a @@ -30,32 +29,32 @@ LIBBITCOIN_CRYPTO=crypto/libbitcoin_crypto.a LIBBITCOINQT=qt/libbitcoinqt.a LIBSECP256K1=secp256k1/libsecp256k1.la +if ENABLE_ZMQ +LIBBITCOIN_ZMQ=libbitcoin_zmq.a +endif +if BUILD_BITCOIN_LIBS +LIBBITCOINCONSENSUS=libbitcoinconsensus.la +endif +if ENABLE_WALLET +LIBBITCOIN_WALLET=libbitcoin_wallet.a +endif + $(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*) $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) # Make is not made aware of per-object dependencies to avoid limiting building parallelization # But to build the less dependent modules first, we manually select their order here: EXTRA_LIBRARIES += \ - crypto/libbitcoin_crypto.a \ - libbitcoin_util.a \ - libbitcoin_common.a \ - libbitcoin_consensus.a \ - libbitcoin_server.a \ - libbitcoin_cli.a -if ENABLE_WALLET -BITCOIN_INCLUDES += $(BDB_CPPFLAGS) -EXTRA_LIBRARIES += libbitcoin_wallet.a -endif -if ENABLE_ZMQ -EXTRA_LIBRARIES += libbitcoin_zmq.a -endif + $(LIBBITCOIN_CRYPTO) \ + $(LIBBITCOIN_UTIL) \ + $(LIBBITCOIN_COMMON) \ + $(LIBBITCOIN_CONSENSUS) \ + $(LIBBITCOIN_SERVER) \ + $(LIBBITCOIN_CLI) \ + $(LIBBITCOIN_WALLET) \ + $(LIBBITCOIN_ZMQ) -if BUILD_BITCOIN_LIBS -lib_LTLIBRARIES = libbitcoinconsensus.la -LIBBITCOINCONSENSUS=libbitcoinconsensus.la -else -LIBBITCOINCONSENSUS= -endif +lib_LTLIBRARIES = $(LIBBITCOINCONSENSUS) bin_PROGRAMS = TESTS = @@ -196,8 +195,6 @@ libbitcoin_server_a_SOURCES = \ $(BITCOIN_CORE_H) if ENABLE_ZMQ -LIBBITCOIN_ZMQ=libbitcoin_zmq.a - libbitcoin_zmq_a_CPPFLAGS = $(BITCOIN_INCLUDES) $(ZMQ_CFLAGS) libbitcoin_zmq_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_zmq_a_SOURCES = \ @@ -347,21 +344,15 @@ bitcoind_LDADD = \ $(LIBBITCOIN_COMMON) \ $(LIBUNIVALUE) \ $(LIBBITCOIN_UTIL) \ + $(LIBBITCOIN_WALLET) \ + $(LIBBITCOIN_ZMQ) \ $(LIBBITCOIN_CONSENSUS) \ $(LIBBITCOIN_CRYPTO) \ $(LIBLEVELDB) \ $(LIBMEMENV) \ $(LIBSECP256K1) -if ENABLE_ZMQ -bitcoind_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS) -endif - -if ENABLE_WALLET -bitcoind_LDADD += libbitcoin_wallet.a -endif - -bitcoind_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) +bitcoind_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS) # bitcoin-cli binary # bitcoin_cli_SOURCES = bitcoin-cli.cpp From 34ed64a404fb6da691f67f00f47c4dd748e3e428 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 20 Mar 2015 01:27:50 -0400 Subject: [PATCH 0320/1802] crypter: add tests for crypter Verify that results correct (match known values), consistent (encrypt->decrypt matches the original), and compatible with the previous openssl implementation. Also check that failed encrypts/decrypts fail the exact same way as openssl. --- src/Makefile.test.include | 1 + src/wallet/crypter.h | 6 + src/wallet/test/crypto_tests.cpp | 230 +++++++++++++++++++++++++++++++ 3 files changed, 237 insertions(+) create mode 100644 src/wallet/test/crypto_tests.cpp diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 08e2f6af4db73..d443b6d34aff1 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -94,6 +94,7 @@ BITCOIN_TESTS += \ wallet/test/wallet_test_fixture.h \ wallet/test/accounting_tests.cpp \ wallet/test/wallet_tests.cpp \ + wallet/test/crypto_tests.cpp \ wallet/test/rpc_wallet_tests.cpp endif diff --git a/src/wallet/crypter.h b/src/wallet/crypter.h index 16f2ba622069c..5d0a4a3305b8c 100644 --- a/src/wallet/crypter.h +++ b/src/wallet/crypter.h @@ -67,9 +67,15 @@ class CMasterKey typedef std::vector > CKeyingMaterial; +namespace wallet_crypto +{ + class TestCrypter; +} + /** Encryption/decryption context with key information */ class CCrypter { +friend class wallet_crypto::TestCrypter; // for test access to chKey/chIV private: unsigned char chKey[WALLET_CRYPTO_KEY_SIZE]; unsigned char chIV[WALLET_CRYPTO_IV_SIZE]; diff --git a/src/wallet/test/crypto_tests.cpp b/src/wallet/test/crypto_tests.cpp new file mode 100644 index 0000000000000..05387f5f2b5e6 --- /dev/null +++ b/src/wallet/test/crypto_tests.cpp @@ -0,0 +1,230 @@ +// Copyright (c) 2014 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "random.h" +#include "utilstrencodings.h" +#include "test/test_bitcoin.h" +#include "wallet/crypter.h" + +#include + +#include +#include +#include + +BOOST_FIXTURE_TEST_SUITE(wallet_crypto, BasicTestingSetup) + +bool OldSetKeyFromPassphrase(const SecureString& strKeyData, const std::vector& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod, unsigned char* chKey, unsigned char* chIV) +{ + if (nRounds < 1 || chSalt.size() != WALLET_CRYPTO_SALT_SIZE) + return false; + + int i = 0; + if (nDerivationMethod == 0) + i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha512(), &chSalt[0], + (unsigned char *)&strKeyData[0], strKeyData.size(), nRounds, chKey, chIV); + + if (i != (int)WALLET_CRYPTO_KEY_SIZE) + { + memory_cleanse(chKey, sizeof(chKey)); + memory_cleanse(chIV, sizeof(chIV)); + return false; + } + return true; +} + +bool OldEncrypt(const CKeyingMaterial& vchPlaintext, std::vector &vchCiphertext, const unsigned char chKey[32], const unsigned char chIV[16]) +{ + // max ciphertext len for a n bytes of plaintext is + // n + AES_BLOCK_SIZE - 1 bytes + int nLen = vchPlaintext.size(); + int nCLen = nLen + AES_BLOCK_SIZE, nFLen = 0; + vchCiphertext = std::vector (nCLen); + + EVP_CIPHER_CTX ctx; + + bool fOk = true; + + EVP_CIPHER_CTX_init(&ctx); + if (fOk) fOk = EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV) != 0; + if (fOk) fOk = EVP_EncryptUpdate(&ctx, &vchCiphertext[0], &nCLen, &vchPlaintext[0], nLen) != 0; + if (fOk) fOk = EVP_EncryptFinal_ex(&ctx, (&vchCiphertext[0]) + nCLen, &nFLen) != 0; + EVP_CIPHER_CTX_cleanup(&ctx); + + if (!fOk) return false; + + vchCiphertext.resize(nCLen + nFLen); + return true; +} + +bool OldDecrypt(const std::vector& vchCiphertext, CKeyingMaterial& vchPlaintext, const unsigned char chKey[32], const unsigned char chIV[16]) +{ + // plaintext will always be equal to or lesser than length of ciphertext + int nLen = vchCiphertext.size(); + int nPLen = nLen, nFLen = 0; + + vchPlaintext = CKeyingMaterial(nPLen); + + EVP_CIPHER_CTX ctx; + + bool fOk = true; + + EVP_CIPHER_CTX_init(&ctx); + if (fOk) fOk = EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV) != 0; + if (fOk) fOk = EVP_DecryptUpdate(&ctx, &vchPlaintext[0], &nPLen, &vchCiphertext[0], nLen) != 0; + if (fOk) fOk = EVP_DecryptFinal_ex(&ctx, (&vchPlaintext[0]) + nPLen, &nFLen) != 0; + EVP_CIPHER_CTX_cleanup(&ctx); + + if (!fOk) return false; + + vchPlaintext.resize(nPLen + nFLen); + return true; +} + +class TestCrypter +{ +public: +static void TestPassphraseSingle(const std::vector& vchSalt, const SecureString& passphrase, uint32_t rounds, + const std::vector& correctKey = std::vector(), + const std::vector& correctIV=std::vector()) +{ + unsigned char chKey[WALLET_CRYPTO_KEY_SIZE]; + unsigned char chIV[WALLET_CRYPTO_IV_SIZE]; + + CCrypter crypt; + crypt.SetKeyFromPassphrase(passphrase, vchSalt, rounds, 0); + + OldSetKeyFromPassphrase(passphrase, vchSalt, rounds, 0, chKey, chIV); + + BOOST_CHECK_MESSAGE(memcmp(chKey, crypt.chKey, sizeof(chKey)) == 0, \ + HexStr(chKey, chKey+sizeof(chKey)) + std::string(" != ") + HexStr(crypt.chKey, crypt.chKey + (sizeof crypt.chKey))); + BOOST_CHECK_MESSAGE(memcmp(chIV, crypt.chIV, sizeof(chIV)) == 0, \ + HexStr(chIV, chIV+sizeof(chIV)) + std::string(" != ") + HexStr(crypt.chIV, crypt.chIV + (sizeof crypt.chIV))); + + if(!correctKey.empty()) + BOOST_CHECK_MESSAGE(memcmp(chKey, &correctKey[0], sizeof(chKey)) == 0, \ + HexStr(chKey, chKey+sizeof(chKey)) + std::string(" != ") + HexStr(correctKey.begin(), correctKey.end())); + if(!correctIV.empty()) + BOOST_CHECK_MESSAGE(memcmp(chIV, &correctIV[0], sizeof(chIV)) == 0, + HexStr(chIV, chIV+sizeof(chIV)) + std::string(" != ") + HexStr(correctIV.begin(), correctIV.end())); +} + +static void TestPassphrase(const std::vector& vchSalt, const SecureString& passphrase, uint32_t rounds, + const std::vector& correctKey = std::vector(), + const std::vector& correctIV=std::vector()) +{ + TestPassphraseSingle(vchSalt, passphrase, rounds, correctKey, correctIV); + for(SecureString::const_iterator i(passphrase.begin()); i != passphrase.end(); ++i) + TestPassphraseSingle(vchSalt, SecureString(i, passphrase.end()), rounds); +} + + +static void TestDecrypt(const CCrypter& crypt, const std::vector& vchCiphertext, \ + const std::vector& vchPlaintext = std::vector()) +{ + CKeyingMaterial vchDecrypted1; + CKeyingMaterial vchDecrypted2; + int result1, result2; + result1 = crypt.Decrypt(vchCiphertext, vchDecrypted1); + result2 = OldDecrypt(vchCiphertext, vchDecrypted2, crypt.chKey, crypt.chIV); + BOOST_CHECK(result1 == result2); + + // These two should be equal. However, OpenSSL 1.0.1j introduced a change + // that would zero all padding except for the last byte for failed decrypts. + // This behavior was reverted for 1.0.1k. + if (vchDecrypted1 != vchDecrypted2 && vchDecrypted1.size() >= AES_BLOCK_SIZE && SSLeay() == 0x100010afL) + { + for(CKeyingMaterial::iterator it = vchDecrypted1.end() - AES_BLOCK_SIZE; it != vchDecrypted1.end() - 1; it++) + *it = 0; + } + + BOOST_CHECK_MESSAGE(vchDecrypted1 == vchDecrypted2, HexStr(vchDecrypted1.begin(), vchDecrypted1.end()) + " != " + HexStr(vchDecrypted2.begin(), vchDecrypted2.end())); + + if (vchPlaintext.size()) + BOOST_CHECK(CKeyingMaterial(vchPlaintext.begin(), vchPlaintext.end()) == vchDecrypted2); +} + +static void TestEncryptSingle(const CCrypter& crypt, const CKeyingMaterial& vchPlaintext, + const std::vector& vchCiphertextCorrect = std::vector()) +{ + std::vector vchCiphertext1; + std::vector vchCiphertext2; + int result1 = crypt.Encrypt(vchPlaintext, vchCiphertext1); + + int result2 = OldEncrypt(vchPlaintext, vchCiphertext2, crypt.chKey, crypt.chIV); + BOOST_CHECK(result1 == result2); + BOOST_CHECK(vchCiphertext1 == vchCiphertext2); + + if (!vchCiphertextCorrect.empty()) + BOOST_CHECK(vchCiphertext2 == vchCiphertextCorrect); + + const std::vector vchPlaintext2(vchPlaintext.begin(), vchPlaintext.end()); + + if(vchCiphertext1 == vchCiphertext2) + TestDecrypt(crypt, vchCiphertext1, vchPlaintext2); +} + +static void TestEncrypt(const CCrypter& crypt, const std::vector& vchPlaintextIn, \ + const std::vector& vchCiphertextCorrect = std::vector()) +{ + TestEncryptSingle(crypt, CKeyingMaterial(vchPlaintextIn.begin(), vchPlaintextIn.end()), vchCiphertextCorrect); + for(std::vector::const_iterator i(vchPlaintextIn.begin()); i != vchPlaintextIn.end(); ++i) + TestEncryptSingle(crypt, CKeyingMaterial(i, vchPlaintextIn.end())); +} + +}; + +BOOST_AUTO_TEST_CASE(passphrase) { + // These are expensive. + + TestCrypter::TestPassphrase(ParseHex("0000deadbeef0000"), "test", 25000, \ + ParseHex("fc7aba077ad5f4c3a0988d8daa4810d0d4a0e3bcb53af662998898f33df0556a"), \ + ParseHex("cf2f2691526dd1aa220896fb8bf7c369")); + + std::string hash(GetRandHash().ToString()); + std::vector vchSalt(8); + GetRandBytes(&vchSalt[0], vchSalt.size()); + uint32_t rounds = insecure_rand(); + if (rounds > 30000) + rounds = 30000; + TestCrypter::TestPassphrase(vchSalt, SecureString(hash.begin(), hash.end()), rounds); +} + +BOOST_AUTO_TEST_CASE(encrypt) { + std::vector vchSalt = ParseHex("0000deadbeef0000"); + BOOST_CHECK(vchSalt.size() == WALLET_CRYPTO_SALT_SIZE); + CCrypter crypt; + crypt.SetKeyFromPassphrase("passphrase", vchSalt, 25000, 0); + TestCrypter::TestEncrypt(crypt, ParseHex("22bcade09ac03ff6386914359cfe885cfeb5f77ff0d670f102f619687453b29d")); + + for (int i = 0; i != 100; i++) + { + uint256 hash(GetRandHash()); + TestCrypter::TestEncrypt(crypt, std::vector(hash.begin(), hash.end())); + } + +} + +BOOST_AUTO_TEST_CASE(decrypt) { + std::vector vchSalt = ParseHex("0000deadbeef0000"); + BOOST_CHECK(vchSalt.size() == WALLET_CRYPTO_SALT_SIZE); + CCrypter crypt; + crypt.SetKeyFromPassphrase("passphrase", vchSalt, 25000, 0); + + // Some corner cases the came up while testing + TestCrypter::TestDecrypt(crypt,ParseHex("795643ce39d736088367822cdc50535ec6f103715e3e48f4f3b1a60a08ef59ca")); + TestCrypter::TestDecrypt(crypt,ParseHex("de096f4a8f9bd97db012aa9d90d74de8cdea779c3ee8bc7633d8b5d6da703486")); + TestCrypter::TestDecrypt(crypt,ParseHex("32d0a8974e3afd9c6c3ebf4d66aa4e6419f8c173de25947f98cf8b7ace49449c")); + TestCrypter::TestDecrypt(crypt,ParseHex("e7c055cca2faa78cb9ac22c9357a90b4778ded9b2cc220a14cea49f931e596ea")); + TestCrypter::TestDecrypt(crypt,ParseHex("b88efddd668a6801d19516d6830da4ae9811988ccbaf40df8fbb72f3f4d335fd")); + TestCrypter::TestDecrypt(crypt,ParseHex("8cae76aa6a43694e961ebcb28c8ca8f8540b84153d72865e8561ddd93fa7bfa9")); + + for (int i = 0; i != 100; i++) + { + uint256 hash(GetRandHash()); + TestCrypter::TestDecrypt(crypt, std::vector(hash.begin(), hash.end())); + } +} + +BOOST_AUTO_TEST_SUITE_END() From fac93497986b5f74716383bf26c78406253c625a Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sat, 14 May 2016 13:01:31 +0200 Subject: [PATCH 0321/1802] [qa] Remove hardcoded "4 nodes" from test_framework --- qa/rpc-tests/abandonconflict.py | 4 +++ qa/rpc-tests/bip65-cltv-p2p.py | 3 +- qa/rpc-tests/bip65-cltv.py | 4 +++ qa/rpc-tests/bip68-112-113-p2p.py | 3 +- qa/rpc-tests/bip68-sequence.py | 4 +++ qa/rpc-tests/bip9-softforks.py | 3 +- qa/rpc-tests/bipdersig-p2p.py | 3 +- qa/rpc-tests/bipdersig.py | 4 +++ qa/rpc-tests/blockchain.py | 10 +++--- qa/rpc-tests/decodescript.py | 9 ++--- qa/rpc-tests/disablewallet.py | 9 ++--- qa/rpc-tests/forknotify.py | 5 +++ qa/rpc-tests/fundrawtransaction.py | 11 ++++--- qa/rpc-tests/getblocktemplate_longpoll.py | 5 +++ qa/rpc-tests/getblocktemplate_proposals.py | 9 +++++ qa/rpc-tests/getchaintips.py | 5 ++- qa/rpc-tests/httpbasics.py | 9 +++-- qa/rpc-tests/importprunedfunds.py | 9 ++--- qa/rpc-tests/invalidateblock.py | 9 ++--- qa/rpc-tests/invalidblockrequest.py | 1 + qa/rpc-tests/invalidtxrequest.py | 1 + qa/rpc-tests/keypool.py | 11 +++---- qa/rpc-tests/listtransactions.py | 6 +++- qa/rpc-tests/maxblocksinflight.py | 9 ++--- qa/rpc-tests/maxuploadtarget.py | 12 ++++--- qa/rpc-tests/mempool_limit.py | 12 +++---- qa/rpc-tests/mempool_packages.py | 4 +++ qa/rpc-tests/mempool_reorg.py | 4 +++ qa/rpc-tests/mempool_resurrect_test.py | 5 +++ qa/rpc-tests/mempool_spendcoinbase.py | 5 +++ qa/rpc-tests/merkle_blocks.py | 7 ++-- qa/rpc-tests/multi_rpc.py | 16 ++++++--- qa/rpc-tests/nodehandling.py | 6 ++++ qa/rpc-tests/p2p-acceptblock.py | 6 ++-- qa/rpc-tests/p2p-feefilter.py | 6 ++++ qa/rpc-tests/p2p-fullblocktest.py | 1 + qa/rpc-tests/p2p-versionbits-warning.py | 6 ++-- qa/rpc-tests/prioritise_transaction.py | 8 ++--- qa/rpc-tests/proxy_test.py | 6 +++- qa/rpc-tests/pruning.py | 8 ++--- qa/rpc-tests/rawtransactions.py | 9 ++--- qa/rpc-tests/receivedby.py | 7 +++- qa/rpc-tests/reindex.py | 7 ++-- qa/rpc-tests/replace-by-fee.py | 5 +++ qa/rpc-tests/rest.py | 9 ++--- qa/rpc-tests/rpcbind_test.py | 4 +-- qa/rpc-tests/sendheaders.py | 8 +++-- qa/rpc-tests/signmessages.py | 9 ++--- qa/rpc-tests/signrawtransactions.py | 9 ++--- qa/rpc-tests/smartfees.py | 5 +++ qa/rpc-tests/test_framework/test_framework.py | 25 +++++++------- qa/rpc-tests/test_framework/util.py | 33 +++++++++++-------- qa/rpc-tests/txn_clone.py | 5 +++ qa/rpc-tests/txn_doublespend.py | 5 +++ qa/rpc-tests/wallet.py | 7 ++-- qa/rpc-tests/walletbackup.py | 9 ++--- qa/rpc-tests/zapwallettxes.py | 9 ++--- qa/rpc-tests/zmq_test.py | 6 +++- 58 files changed, 291 insertions(+), 138 deletions(-) diff --git a/qa/rpc-tests/abandonconflict.py b/qa/rpc-tests/abandonconflict.py index b6c4b9db48fbf..c50c3cc562e5f 100755 --- a/qa/rpc-tests/abandonconflict.py +++ b/qa/rpc-tests/abandonconflict.py @@ -9,6 +9,10 @@ import urllib.parse class AbandonConflictTest(BitcoinTestFramework): + def __init__(self): + super().__init__() + self.num_nodes = 2 + self.setup_clean_chain = False def setup_network(self): self.nodes = [] diff --git a/qa/rpc-tests/bip65-cltv-p2p.py b/qa/rpc-tests/bip65-cltv-p2p.py index 60923b9dda90a..754b6873b71ff 100755 --- a/qa/rpc-tests/bip65-cltv-p2p.py +++ b/qa/rpc-tests/bip65-cltv-p2p.py @@ -37,11 +37,12 @@ def cltv_invalidate(tx): class BIP65Test(ComparisonTestFramework): def __init__(self): + super().__init__() self.num_nodes = 1 def setup_network(self): # Must set the blockversion for this test - self.nodes = start_nodes(1, self.options.tmpdir, + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[['-debug', '-whitelist=127.0.0.1', '-blockversion=3']], binary=[self.options.testbinary]) diff --git a/qa/rpc-tests/bip65-cltv.py b/qa/rpc-tests/bip65-cltv.py index 9d83fc947b166..abba7fc20e7d9 100755 --- a/qa/rpc-tests/bip65-cltv.py +++ b/qa/rpc-tests/bip65-cltv.py @@ -11,6 +11,10 @@ from test_framework.util import * class BIP65Test(BitcoinTestFramework): + def __init__(self): + super().__init__() + self.num_nodes = 3 + self.setup_clean_chain = False def setup_network(self): self.nodes = [] diff --git a/qa/rpc-tests/bip68-112-113-p2p.py b/qa/rpc-tests/bip68-112-113-p2p.py index eedb60e3a0958..8ba07043849a6 100755 --- a/qa/rpc-tests/bip68-112-113-p2p.py +++ b/qa/rpc-tests/bip68-112-113-p2p.py @@ -94,11 +94,12 @@ def all_rlt_txs(txarray): class BIP68_112_113Test(ComparisonTestFramework): def __init__(self): + super().__init__() self.num_nodes = 1 def setup_network(self): # Must set the blockversion for this test - self.nodes = start_nodes(1, self.options.tmpdir, + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[['-debug', '-whitelist=127.0.0.1', '-blockversion=4']], binary=[self.options.testbinary]) diff --git a/qa/rpc-tests/bip68-sequence.py b/qa/rpc-tests/bip68-sequence.py index 717f7562cdee2..a12bf10ebd758 100755 --- a/qa/rpc-tests/bip68-sequence.py +++ b/qa/rpc-tests/bip68-sequence.py @@ -22,6 +22,10 @@ NOT_FINAL_ERROR = "64: non-BIP68-final" class BIP68Test(BitcoinTestFramework): + def __init__(self): + super().__init__() + self.num_nodes = 2 + self.setup_clean_chain = False def setup_network(self): self.nodes = [] diff --git a/qa/rpc-tests/bip9-softforks.py b/qa/rpc-tests/bip9-softforks.py index a8fb878dcb1e6..aae258315e0b7 100755 --- a/qa/rpc-tests/bip9-softforks.py +++ b/qa/rpc-tests/bip9-softforks.py @@ -32,10 +32,11 @@ class BIP9SoftForksTest(ComparisonTestFramework): def __init__(self): + super().__init__() self.num_nodes = 1 def setup_network(self): - self.nodes = start_nodes(1, self.options.tmpdir, + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[['-debug', '-whitelist=127.0.0.1']], binary=[self.options.testbinary]) diff --git a/qa/rpc-tests/bipdersig-p2p.py b/qa/rpc-tests/bipdersig-p2p.py index c4627308400b8..4e4936a4ae6de 100755 --- a/qa/rpc-tests/bipdersig-p2p.py +++ b/qa/rpc-tests/bipdersig-p2p.py @@ -45,11 +45,12 @@ def unDERify(tx): class BIP66Test(ComparisonTestFramework): def __init__(self): + super().__init__() self.num_nodes = 1 def setup_network(self): # Must set the blockversion for this test - self.nodes = start_nodes(1, self.options.tmpdir, + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[['-debug', '-whitelist=127.0.0.1', '-blockversion=2']], binary=[self.options.testbinary]) diff --git a/qa/rpc-tests/bipdersig.py b/qa/rpc-tests/bipdersig.py index f2d2c14a72c24..17c2ced79ac1e 100755 --- a/qa/rpc-tests/bipdersig.py +++ b/qa/rpc-tests/bipdersig.py @@ -11,6 +11,10 @@ from test_framework.util import * class BIP66Test(BitcoinTestFramework): + def __init__(self): + super().__init__() + self.num_nodes = 3 + self.setup_clean_chain = False def setup_network(self): self.nodes = [] diff --git a/qa/rpc-tests/blockchain.py b/qa/rpc-tests/blockchain.py index c84047b5dd18c..410b85d15e35f 100755 --- a/qa/rpc-tests/blockchain.py +++ b/qa/rpc-tests/blockchain.py @@ -13,7 +13,6 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.authproxy import JSONRPCException from test_framework.util import ( - initialize_chain, assert_equal, assert_raises, assert_is_hex_string, @@ -32,12 +31,13 @@ class BlockchainTest(BitcoinTestFramework): """ - def setup_chain(self): - print("Initializing test directory " + self.options.tmpdir) - initialize_chain(self.options.tmpdir) + def __init__(self): + super().__init__() + self.setup_clean_chain = False + self.num_nodes = 2 def setup_network(self, split=False): - self.nodes = start_nodes(2, self.options.tmpdir) + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) connect_nodes_bi(self.nodes, 0, 1) self.is_network_split = False self.sync_all() diff --git a/qa/rpc-tests/decodescript.py b/qa/rpc-tests/decodescript.py index 0037542e62e02..24768c265577a 100755 --- a/qa/rpc-tests/decodescript.py +++ b/qa/rpc-tests/decodescript.py @@ -11,12 +11,13 @@ class DecodeScriptTest(BitcoinTestFramework): """Tests decoding scripts via RPC command "decodescript".""" - def setup_chain(self): - print('Initializing test directory ' + self.options.tmpdir) - initialize_chain_clean(self.options.tmpdir, 1) + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 1 def setup_network(self, split=False): - self.nodes = start_nodes(1, self.options.tmpdir) + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) self.is_network_split = False def decodescript_script_sig(self): diff --git a/qa/rpc-tests/disablewallet.py b/qa/rpc-tests/disablewallet.py index b25d2ba3352cf..36c147edad3a6 100755 --- a/qa/rpc-tests/disablewallet.py +++ b/qa/rpc-tests/disablewallet.py @@ -13,12 +13,13 @@ class DisableWalletTest (BitcoinTestFramework): - def setup_chain(self): - print("Initializing test directory "+self.options.tmpdir) - initialize_chain_clean(self.options.tmpdir, 1) + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 1 def setup_network(self, split=False): - self.nodes = start_nodes(1, self.options.tmpdir, [['-disablewallet']]) + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [['-disablewallet']]) self.is_network_split = False self.sync_all() diff --git a/qa/rpc-tests/forknotify.py b/qa/rpc-tests/forknotify.py index 421f3dd872973..5a3f75c808741 100755 --- a/qa/rpc-tests/forknotify.py +++ b/qa/rpc-tests/forknotify.py @@ -12,6 +12,11 @@ class ForkNotifyTest(BitcoinTestFramework): + def __init__(self): + super().__init__() + self.num_nodes = 2 + self.setup_clean_chain = False + alert_filename = None # Set by setup_network def setup_network(self): diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py index 74849603f719d..57b850a6a9eaa 100755 --- a/qa/rpc-tests/fundrawtransaction.py +++ b/qa/rpc-tests/fundrawtransaction.py @@ -9,12 +9,13 @@ # Create one-input, one-output, no-fee transaction: class RawTransactionsTest(BitcoinTestFramework): - def setup_chain(self): - print(("Initializing test directory "+self.options.tmpdir)) - initialize_chain_clean(self.options.tmpdir, 4) + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 4 def setup_network(self, split=False): - self.nodes = start_nodes(4, self.options.tmpdir) + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) @@ -521,7 +522,7 @@ def run_test(self): stop_nodes(self.nodes) wait_bitcoinds() - self.nodes = start_nodes(4, self.options.tmpdir) + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) # This test is not meant to test fee estimation and we'd like # to be sure all txs are sent at a consistent desired feerate for node in self.nodes: diff --git a/qa/rpc-tests/getblocktemplate_longpoll.py b/qa/rpc-tests/getblocktemplate_longpoll.py index e443347077741..3cddf4046aaf6 100755 --- a/qa/rpc-tests/getblocktemplate_longpoll.py +++ b/qa/rpc-tests/getblocktemplate_longpoll.py @@ -26,6 +26,11 @@ class GetBlockTemplateLPTest(BitcoinTestFramework): Test longpolling with getblocktemplate. ''' + def __init__(self): + super().__init__() + self.num_nodes = 4 + self.setup_clean_chain = False + def run_test(self): print("Warning: this test will take about 70 seconds in the best case. Be patient.") self.nodes[0].generate(10) diff --git a/qa/rpc-tests/getblocktemplate_proposals.py b/qa/rpc-tests/getblocktemplate_proposals.py index 1ad2af4c2e3ac..7a4f8f8fdc3c2 100755 --- a/qa/rpc-tests/getblocktemplate_proposals.py +++ b/qa/rpc-tests/getblocktemplate_proposals.py @@ -70,6 +70,15 @@ class GetBlockTemplateProposalTest(BitcoinTestFramework): Test block proposals with getblocktemplate. ''' + def __init__(self): + super().__init__() + self.num_nodes = 2 + self.setup_clean_chain = False + + def setup_network(self): + self.nodes = self.setup_nodes() + connect_nodes_bi(self.nodes, 0, 1) + def run_test(self): node = self.nodes[0] node.generate(1) # Mine a block to leave initial block download diff --git a/qa/rpc-tests/getchaintips.py b/qa/rpc-tests/getchaintips.py index da354b0c97a01..1c66b8c28927d 100755 --- a/qa/rpc-tests/getchaintips.py +++ b/qa/rpc-tests/getchaintips.py @@ -11,9 +11,12 @@ from test_framework.util import assert_equal class GetChainTipsTest (BitcoinTestFramework): + def __init__(self): + super().__init__() + self.num_nodes = 4 + self.setup_clean_chain = False def run_test (self): - BitcoinTestFramework.run_test (self) tips = self.nodes[0].getchaintips () assert_equal (len (tips), 1) diff --git a/qa/rpc-tests/httpbasics.py b/qa/rpc-tests/httpbasics.py index c62edc8e130cc..10bc927e1a51a 100755 --- a/qa/rpc-tests/httpbasics.py +++ b/qa/rpc-tests/httpbasics.py @@ -14,8 +14,13 @@ import urllib.parse class HTTPBasicsTest (BitcoinTestFramework): - def setup_nodes(self): - return start_nodes(4, self.options.tmpdir) + def __init__(self): + super().__init__() + self.num_nodes = 3 + self.setup_clean_chain = False + + def setup_network(self): + self.nodes = self.setup_nodes() def run_test(self): diff --git a/qa/rpc-tests/importprunedfunds.py b/qa/rpc-tests/importprunedfunds.py index def1d891c3614..761c9af90c30e 100755 --- a/qa/rpc-tests/importprunedfunds.py +++ b/qa/rpc-tests/importprunedfunds.py @@ -9,12 +9,13 @@ class ImportPrunedFundsTest(BitcoinTestFramework): - def setup_chain(self): - print("Initializing test directory "+self.options.tmpdir) - initialize_chain_clean(self.options.tmpdir, 4) + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 4 def setup_network(self, split=False): - self.nodes = start_nodes(2, self.options.tmpdir) + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) connect_nodes_bi(self.nodes,0,1) self.is_network_split=False self.sync_all() diff --git a/qa/rpc-tests/invalidateblock.py b/qa/rpc-tests/invalidateblock.py index 2e3a449f5e781..0faadd33ab35a 100755 --- a/qa/rpc-tests/invalidateblock.py +++ b/qa/rpc-tests/invalidateblock.py @@ -13,10 +13,11 @@ class InvalidateTest(BitcoinTestFramework): - def setup_chain(self): - print("Initializing test directory "+self.options.tmpdir) - initialize_chain_clean(self.options.tmpdir, 3) - + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 3 + def setup_network(self): self.nodes = [] self.is_network_split = False diff --git a/qa/rpc-tests/invalidblockrequest.py b/qa/rpc-tests/invalidblockrequest.py index 78dc7199da316..3d8107a76c661 100755 --- a/qa/rpc-tests/invalidblockrequest.py +++ b/qa/rpc-tests/invalidblockrequest.py @@ -25,6 +25,7 @@ class InvalidBlockRequestTest(ComparisonTestFramework): ''' Can either run this test as 1 node with expected answers, or two and compare them. Change the "outcome" variable from each TestInstance object to only do the comparison. ''' def __init__(self): + super().__init__() self.num_nodes = 1 def run_test(self): diff --git a/qa/rpc-tests/invalidtxrequest.py b/qa/rpc-tests/invalidtxrequest.py index d4200b0e885f9..93205d79dee5b 100755 --- a/qa/rpc-tests/invalidtxrequest.py +++ b/qa/rpc-tests/invalidtxrequest.py @@ -19,6 +19,7 @@ class InvalidTxRequestTest(ComparisonTestFramework): ''' Can either run this test as 1 node with expected answers, or two and compare them. Change the "outcome" variable from each TestInstance object to only do the comparison. ''' def __init__(self): + super().__init__() self.num_nodes = 1 def run_test(self): diff --git a/qa/rpc-tests/keypool.py b/qa/rpc-tests/keypool.py index bdc144bfbc2fb..c75303ecbfc31 100755 --- a/qa/rpc-tests/keypool.py +++ b/qa/rpc-tests/keypool.py @@ -5,8 +5,6 @@ # Exercise the wallet keypool, and interaction with wallet encryption/locking -# Add python-bitcoinrpc to module search path: - from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * @@ -65,12 +63,13 @@ def run_test(self): except JSONRPCException as e: assert(e.error['code']==-12) - def setup_chain(self): - print("Initializing test directory "+self.options.tmpdir) - initialize_chain(self.options.tmpdir) + def __init__(self): + super().__init__() + self.setup_clean_chain = False + self.num_nodes = 1 def setup_network(self): - self.nodes = start_nodes(1, self.options.tmpdir) + self.nodes = self.setup_nodes() if __name__ == '__main__': KeyPoolTest().main() diff --git a/qa/rpc-tests/listtransactions.py b/qa/rpc-tests/listtransactions.py index 8dad687eddaa9..5ec6ce17e01e8 100755 --- a/qa/rpc-tests/listtransactions.py +++ b/qa/rpc-tests/listtransactions.py @@ -17,11 +17,15 @@ def txFromHex(hexstring): return tx class ListTransactionsTest(BitcoinTestFramework): + def __init__(self): + super().__init__() + self.num_nodes = 4 + self.setup_clean_chain = False def setup_nodes(self): #This test requires mocktime enable_mocktime() - return start_nodes(4, self.options.tmpdir) + return start_nodes(self.num_nodes, self.options.tmpdir) def run_test(self): # Simple send, 0 to 1: diff --git a/qa/rpc-tests/maxblocksinflight.py b/qa/rpc-tests/maxblocksinflight.py index 6f105a77e3af9..1df1c484bea12 100755 --- a/qa/rpc-tests/maxblocksinflight.py +++ b/qa/rpc-tests/maxblocksinflight.py @@ -76,12 +76,13 @@ def add_options(self, parser): default=os.getenv("BITCOIND", "bitcoind"), help="Binary to test max block requests behavior") - def setup_chain(self): - print("Initializing test directory "+self.options.tmpdir) - initialize_chain_clean(self.options.tmpdir, 1) + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 1 def setup_network(self): - self.nodes = start_nodes(1, self.options.tmpdir, + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[['-debug', '-whitelist=127.0.0.1']], binary=[self.options.testbinary]) diff --git a/qa/rpc-tests/maxuploadtarget.py b/qa/rpc-tests/maxuploadtarget.py index ec802d8155bd5..42235a511910b 100755 --- a/qa/rpc-tests/maxuploadtarget.py +++ b/qa/rpc-tests/maxuploadtarget.py @@ -80,17 +80,19 @@ def received_pong(): return success class MaxUploadTest(BitcoinTestFramework): - def __init__(self): - self.utxo = [] - self.txouts = gen_return_txouts() def add_options(self, parser): parser.add_option("--testbinary", dest="testbinary", default=os.getenv("BITCOIND", "bitcoind"), help="bitcoind binary to test") - def setup_chain(self): - initialize_chain_clean(self.options.tmpdir, 2) + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 2 + + self.utxo = [] + self.txouts = gen_return_txouts() def setup_network(self): # Start a node with maxuploadtarget of 200 MB (/24h) diff --git a/qa/rpc-tests/mempool_limit.py b/qa/rpc-tests/mempool_limit.py index bc208709e9125..c1c5558a95fc1 100755 --- a/qa/rpc-tests/mempool_limit.py +++ b/qa/rpc-tests/mempool_limit.py @@ -10,9 +10,6 @@ class MempoolLimitTest(BitcoinTestFramework): - def __init__(self): - self.txouts = gen_return_txouts() - def setup_network(self): self.nodes = [] self.nodes.append(start_node(0, self.options.tmpdir, ["-maxmempool=5", "-spendzeroconfchange=0", "-debug"])) @@ -20,9 +17,12 @@ def setup_network(self): self.sync_all() self.relayfee = self.nodes[0].getnetworkinfo()['relayfee'] - def setup_chain(self): - print("Initializing test directory "+self.options.tmpdir) - initialize_chain_clean(self.options.tmpdir, 2) + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 2 + + self.txouts = gen_return_txouts() def run_test(self): txids = [] diff --git a/qa/rpc-tests/mempool_packages.py b/qa/rpc-tests/mempool_packages.py index 7ac85c1b6d3e9..693ff593b3485 100755 --- a/qa/rpc-tests/mempool_packages.py +++ b/qa/rpc-tests/mempool_packages.py @@ -13,6 +13,10 @@ MAX_DESCENDANTS = 25 class MempoolPackagesTest(BitcoinTestFramework): + def __init__(self): + super().__init__() + self.num_nodes = 2 + self.setup_clean_chain = False def setup_network(self): self.nodes = [] diff --git a/qa/rpc-tests/mempool_reorg.py b/qa/rpc-tests/mempool_reorg.py index 608e9d0a06c8d..301b094eb08ca 100755 --- a/qa/rpc-tests/mempool_reorg.py +++ b/qa/rpc-tests/mempool_reorg.py @@ -13,6 +13,10 @@ # Create one-input, one-output, no-fee transaction: class MempoolCoinbaseTest(BitcoinTestFramework): + def __init__(self): + super().__init__() + self.num_nodes = 2 + self.setup_clean_chain = False alert_filename = None # Set by setup_network diff --git a/qa/rpc-tests/mempool_resurrect_test.py b/qa/rpc-tests/mempool_resurrect_test.py index b4d9f0a1a23ff..3db12cbf76a68 100755 --- a/qa/rpc-tests/mempool_resurrect_test.py +++ b/qa/rpc-tests/mempool_resurrect_test.py @@ -14,6 +14,11 @@ # Create one-input, one-output, no-fee transaction: class MempoolCoinbaseTest(BitcoinTestFramework): + def __init__(self): + super().__init__() + self.num_nodes = 1 + self.setup_clean_chain = False + def setup_network(self): # Just need one node for this test args = ["-checkmempool", "-debug=mempool"] diff --git a/qa/rpc-tests/mempool_spendcoinbase.py b/qa/rpc-tests/mempool_spendcoinbase.py index c23f5ef10ae12..d5e4bf52d26ce 100755 --- a/qa/rpc-tests/mempool_spendcoinbase.py +++ b/qa/rpc-tests/mempool_spendcoinbase.py @@ -19,6 +19,11 @@ # Create one-input, one-output, no-fee transaction: class MempoolSpendCoinbaseTest(BitcoinTestFramework): + def __init__(self): + super().__init__() + self.num_nodes = 1 + self.setup_clean_chain = False + def setup_network(self): # Just need one node for this test args = ["-checkmempool", "-debug=mempool"] diff --git a/qa/rpc-tests/merkle_blocks.py b/qa/rpc-tests/merkle_blocks.py index 9419d9a714ced..b2155d7fc33c3 100755 --- a/qa/rpc-tests/merkle_blocks.py +++ b/qa/rpc-tests/merkle_blocks.py @@ -12,9 +12,10 @@ class MerkleBlockTest(BitcoinTestFramework): - def setup_chain(self): - print("Initializing test directory "+self.options.tmpdir) - initialize_chain_clean(self.options.tmpdir, 4) + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 4 def setup_network(self): self.nodes = [] diff --git a/qa/rpc-tests/multi_rpc.py b/qa/rpc-tests/multi_rpc.py index 577d80949d4ce..24373b257d7e6 100755 --- a/qa/rpc-tests/multi_rpc.py +++ b/qa/rpc-tests/multi_rpc.py @@ -8,18 +8,21 @@ # from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * +from test_framework.util import str_to_b64str, assert_equal +import os import http.client import urllib.parse class HTTPBasicsTest (BitcoinTestFramework): - def setup_nodes(self): - return start_nodes(4, self.options.tmpdir) + + def __init__(self): + super().__init__() + self.setup_clean_chain = False + self.num_nodes = 1 def setup_chain(self): - print("Initializing test directory "+self.options.tmpdir) - initialize_chain(self.options.tmpdir) + super().setup_chain() #Append rpcauth to bitcoin.conf before initialization rpcauth = "rpcauth=rt:93648e835a54c573682c2eb19f882535$7681e9c5b74bdd85e78166031d2058e1069b3ed7ed967c93fc63abba06f31144" rpcauth2 = "rpcauth=rt2:f8607b1a88861fac29dfccf9b52ff9f$ff36a0c23c8c62b4846112e50fa888416e94c17bfd4c42f88fd8f55ec6a3137e" @@ -27,6 +30,9 @@ def setup_chain(self): f.write(rpcauth+"\n") f.write(rpcauth2+"\n") + def setup_network(self): + self.nodes = self.setup_nodes() + def run_test(self): ################################################## diff --git a/qa/rpc-tests/nodehandling.py b/qa/rpc-tests/nodehandling.py index 1b6ba021a0cea..e9682c4908f65 100755 --- a/qa/rpc-tests/nodehandling.py +++ b/qa/rpc-tests/nodehandling.py @@ -14,6 +14,12 @@ import urllib.parse class NodeHandlingTest (BitcoinTestFramework): + + def __init__(self): + super().__init__() + self.num_nodes = 4 + self.setup_clean_chain = False + def run_test(self): ########################### # setban/listbanned tests # diff --git a/qa/rpc-tests/p2p-acceptblock.py b/qa/rpc-tests/p2p-acceptblock.py index 21e4c2f468521..015ec34effabe 100755 --- a/qa/rpc-tests/p2p-acceptblock.py +++ b/qa/rpc-tests/p2p-acceptblock.py @@ -111,8 +111,10 @@ def add_options(self, parser): default=os.getenv("BITCOIND", "bitcoind"), help="bitcoind binary to test") - def setup_chain(self): - initialize_chain_clean(self.options.tmpdir, 2) + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 2 def setup_network(self): # Node0 will be used to test behavior of processing unrequested blocks diff --git a/qa/rpc-tests/p2p-feefilter.py b/qa/rpc-tests/p2p-feefilter.py index 5fb51ed0fe792..cd0501a3140c3 100755 --- a/qa/rpc-tests/p2p-feefilter.py +++ b/qa/rpc-tests/p2p-feefilter.py @@ -46,6 +46,12 @@ def send_filter(self, feerate): self.sync_with_ping() class FeeFilterTest(BitcoinTestFramework): + + def __init__(self): + super().__init__() + self.num_nodes = 2 + self.setup_clean_chain = False + def setup_network(self): # Node1 will be used to generate txs which should be relayed from Node0 # to our test node diff --git a/qa/rpc-tests/p2p-fullblocktest.py b/qa/rpc-tests/p2p-fullblocktest.py index 56df8ffd01181..aa0501c5e9260 100755 --- a/qa/rpc-tests/p2p-fullblocktest.py +++ b/qa/rpc-tests/p2p-fullblocktest.py @@ -29,6 +29,7 @@ class FullBlockTest(ComparisonTestFramework): ''' Can either run this test as 1 node with expected answers, or two and compare them. Change the "outcome" variable from each TestInstance object to only do the comparison. ''' def __init__(self): + super().__init__() self.num_nodes = 1 self.block_heights = {} self.coinbase_key = CECKey() diff --git a/qa/rpc-tests/p2p-versionbits-warning.py b/qa/rpc-tests/p2p-versionbits-warning.py index 8c8c2358f74e6..962cafef0b17b 100755 --- a/qa/rpc-tests/p2p-versionbits-warning.py +++ b/qa/rpc-tests/p2p-versionbits-warning.py @@ -59,8 +59,10 @@ def sync_with_ping(self, timeout=30): class VersionBitsWarningTest(BitcoinTestFramework): - def setup_chain(self): - initialize_chain_clean(self.options.tmpdir, 1) + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 1 def setup_network(self): self.nodes = [] diff --git a/qa/rpc-tests/prioritise_transaction.py b/qa/rpc-tests/prioritise_transaction.py index 6ab88602b57ac..e1771231c066e 100755 --- a/qa/rpc-tests/prioritise_transaction.py +++ b/qa/rpc-tests/prioritise_transaction.py @@ -14,11 +14,11 @@ class PrioritiseTransactionTest(BitcoinTestFramework): def __init__(self): - self.txouts = gen_return_txouts() + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 1 - def setup_chain(self): - print("Initializing test directory "+self.options.tmpdir) - initialize_chain_clean(self.options.tmpdir, 1) + self.txouts = gen_return_txouts() def setup_network(self): self.nodes = [] diff --git a/qa/rpc-tests/proxy_test.py b/qa/rpc-tests/proxy_test.py index 6c7b201d562d0..27160cae07762 100755 --- a/qa/rpc-tests/proxy_test.py +++ b/qa/rpc-tests/proxy_test.py @@ -36,6 +36,10 @@ class ProxyTest(BitcoinTestFramework): def __init__(self): + super().__init__() + self.num_nodes = 4 + self.setup_clean_chain = False + self.have_ipv6 = test_ipv6_local() # Create two proxies on different ports # ... one unauthenticated @@ -77,7 +81,7 @@ def setup_nodes(self): ] if self.have_ipv6: args[3] = ['-listen', '-debug=net', '-debug=proxy', '-proxy=[%s]:%i' % (self.conf3.addr),'-proxyrandomize=0', '-noonion'] - return start_nodes(4, self.options.tmpdir, extra_args=args) + return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=args) def node_test(self, node, proxies, auth, test_onion=True): rv = [] diff --git a/qa/rpc-tests/pruning.py b/qa/rpc-tests/pruning.py index 92d33bd20ec3e..4c0530b355a59 100755 --- a/qa/rpc-tests/pruning.py +++ b/qa/rpc-tests/pruning.py @@ -20,14 +20,14 @@ def calc_usage(blockdir): class PruneTest(BitcoinTestFramework): def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 3 + self.utxo = [] self.address = ["",""] self.txouts = gen_return_txouts() - def setup_chain(self): - print("Initializing test directory "+self.options.tmpdir) - initialize_chain_clean(self.options.tmpdir, 3) - def setup_network(self): self.nodes = [] self.is_network_split = False diff --git a/qa/rpc-tests/rawtransactions.py b/qa/rpc-tests/rawtransactions.py index 7f7b6887a834f..df02c1697f342 100755 --- a/qa/rpc-tests/rawtransactions.py +++ b/qa/rpc-tests/rawtransactions.py @@ -14,12 +14,13 @@ # Create one-input, one-output, no-fee transaction: class RawTransactionsTest(BitcoinTestFramework): - def setup_chain(self): - print("Initializing test directory "+self.options.tmpdir) - initialize_chain_clean(self.options.tmpdir, 3) + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 3 def setup_network(self, split=False): - self.nodes = start_nodes(3, self.options.tmpdir) + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) #connect to a local machine for debugging #url = "http://bitcoinrpc:DP6DvqZtqXarpeNWyN3LZTFchCCyCUuHwNF7E8pX99x1@%s:%d" % ('127.0.0.1', 18332) diff --git a/qa/rpc-tests/receivedby.py b/qa/rpc-tests/receivedby.py index a3f97669ea27a..4f17b661cb28d 100755 --- a/qa/rpc-tests/receivedby.py +++ b/qa/rpc-tests/receivedby.py @@ -27,10 +27,15 @@ def get_sub_array_from_array(object_array, to_match): class ReceivedByTest(BitcoinTestFramework): + def __init__(self): + super().__init__() + self.num_nodes = 4 + self.setup_clean_chain = False + def setup_nodes(self): #This test requires mocktime enable_mocktime() - return start_nodes(4, self.options.tmpdir) + return start_nodes(self.num_nodes, self.options.tmpdir) def run_test(self): ''' diff --git a/qa/rpc-tests/reindex.py b/qa/rpc-tests/reindex.py index 39564b32bad90..87e6239b59b32 100755 --- a/qa/rpc-tests/reindex.py +++ b/qa/rpc-tests/reindex.py @@ -11,9 +11,10 @@ class ReindexTest(BitcoinTestFramework): - def setup_chain(self): - print("Initializing test directory "+self.options.tmpdir) - initialize_chain_clean(self.options.tmpdir, 1) + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 1 def setup_network(self): self.nodes = [] diff --git a/qa/rpc-tests/replace-by-fee.py b/qa/rpc-tests/replace-by-fee.py index 4afc3981da112..34c0f9d7957c7 100755 --- a/qa/rpc-tests/replace-by-fee.py +++ b/qa/rpc-tests/replace-by-fee.py @@ -68,6 +68,11 @@ def make_utxo(node, amount, confirmed=True, scriptPubKey=CScript([1])): class ReplaceByFeeTest(BitcoinTestFramework): + def __init__(self): + super().__init__() + self.num_nodes = 1 + self.setup_clean_chain = False + def setup_network(self): self.nodes = [] self.nodes.append(start_node(0, self.options.tmpdir, ["-maxorphantx=1000", "-debug", diff --git a/qa/rpc-tests/rest.py b/qa/rpc-tests/rest.py index ec9515528ecb7..c9c2eaf7f37b9 100755 --- a/qa/rpc-tests/rest.py +++ b/qa/rpc-tests/rest.py @@ -47,12 +47,13 @@ def http_post_call(host, port, path, requestdata = '', response_object = 0): class RESTTest (BitcoinTestFramework): FORMAT_SEPARATOR = "." - def setup_chain(self): - print("Initializing test directory "+self.options.tmpdir) - initialize_chain_clean(self.options.tmpdir, 3) + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 3 def setup_network(self, split=False): - self.nodes = start_nodes(3, self.options.tmpdir) + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) diff --git a/qa/rpc-tests/rpcbind_test.py b/qa/rpc-tests/rpcbind_test.py index 7b7c01f993cf4..572273566b63a 100755 --- a/qa/rpc-tests/rpcbind_test.py +++ b/qa/rpc-tests/rpcbind_test.py @@ -24,7 +24,7 @@ def run_bind_test(tmpdir, allow_ips, connect_to, addresses, expected): if allow_ips: base_args += ['-rpcallowip=' + x for x in allow_ips] binds = ['-rpcbind='+addr for addr in addresses] - nodes = start_nodes(1, tmpdir, [base_args + binds], connect_to) + nodes = start_nodes(self.num_nodes, tmpdir, [base_args + binds], connect_to) try: pid = bitcoind_processes[0].pid assert_equal(set(get_bind_addrs(pid)), set(expected)) @@ -38,7 +38,7 @@ def run_allowip_test(tmpdir, allow_ips, rpchost, rpcport): at a non-localhost IP. ''' base_args = ['-disablewallet', '-nolisten'] + ['-rpcallowip='+x for x in allow_ips] - nodes = start_nodes(1, tmpdir, [base_args]) + nodes = start_nodes(self.num_nodes, tmpdir, [base_args]) try: # connect to node through non-loopback interface url = "http://rt:rt@%s:%d" % (rpchost, rpcport,) diff --git a/qa/rpc-tests/sendheaders.py b/qa/rpc-tests/sendheaders.py index 96d1da729b909..6ab17d59b3878 100755 --- a/qa/rpc-tests/sendheaders.py +++ b/qa/rpc-tests/sendheaders.py @@ -208,12 +208,14 @@ def __init__(self): BaseNode.__init__(self) class SendHeadersTest(BitcoinTestFramework): - def setup_chain(self): - initialize_chain_clean(self.options.tmpdir, 2) + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 2 def setup_network(self): self.nodes = [] - self.nodes = start_nodes(2, self.options.tmpdir, [["-debug", "-logtimemicros=1"]]*2) + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [["-debug", "-logtimemicros=1"]]*2) connect_nodes(self.nodes[0], 1) # mine count blocks and return the new tip diff --git a/qa/rpc-tests/signmessages.py b/qa/rpc-tests/signmessages.py index 4a47c0ca1e198..31b6f14a26562 100755 --- a/qa/rpc-tests/signmessages.py +++ b/qa/rpc-tests/signmessages.py @@ -10,12 +10,13 @@ class SignMessagesTest(BitcoinTestFramework): """Tests RPC commands for signing and verifying messages.""" - def setup_chain(self): - print('Initializing test directory ' + self.options.tmpdir) - initialize_chain_clean(self.options.tmpdir, 1) + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 1 def setup_network(self, split=False): - self.nodes = start_nodes(1, self.options.tmpdir) + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) self.is_network_split = False def run_test(self): diff --git a/qa/rpc-tests/signrawtransactions.py b/qa/rpc-tests/signrawtransactions.py index a06ac53191846..c61a280616cf7 100755 --- a/qa/rpc-tests/signrawtransactions.py +++ b/qa/rpc-tests/signrawtransactions.py @@ -10,12 +10,13 @@ class SignRawTransactionsTest(BitcoinTestFramework): """Tests transaction signing via RPC command "signrawtransaction".""" - def setup_chain(self): - print('Initializing test directory ' + self.options.tmpdir) - initialize_chain_clean(self.options.tmpdir, 1) + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 1 def setup_network(self, split=False): - self.nodes = start_nodes(1, self.options.tmpdir) + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) self.is_network_split = False def successful_signing_test(self): diff --git a/qa/rpc-tests/smartfees.py b/qa/rpc-tests/smartfees.py index 8fcb99c1b7f4e..d76fba4b075ce 100755 --- a/qa/rpc-tests/smartfees.py +++ b/qa/rpc-tests/smartfees.py @@ -145,6 +145,11 @@ def check_estimates(node, fees_seen, max_invalid, print_estimates = True): class EstimateFeeTest(BitcoinTestFramework): + def __init__(self): + super().__init__() + self.num_nodes = 3 + self.setup_clean_chain = False + def setup_network(self): ''' We'll setup the network to have 3 nodes that all mine with different parameters. diff --git a/qa/rpc-tests/test_framework/test_framework.py b/qa/rpc-tests/test_framework/test_framework.py index 3480de6c6e20c..b9b803429dec2 100755 --- a/qa/rpc-tests/test_framework/test_framework.py +++ b/qa/rpc-tests/test_framework/test_framework.py @@ -15,7 +15,6 @@ from .util import ( initialize_chain, - assert_equal, start_nodes, connect_nodes_bi, sync_blocks, @@ -32,21 +31,26 @@ class BitcoinTestFramework(object): - # These may be over-ridden by subclasses: + def __init__(self): + self.num_nodes = 4 + self.setup_clean_chain = False + self.nodes = None + def run_test(self): - for node in self.nodes: - assert_equal(node.getblockcount(), 200) - assert_equal(node.getbalance(), 25*50) + raise NotImplementedError def add_options(self, parser): pass def setup_chain(self): print("Initializing test directory "+self.options.tmpdir) - initialize_chain(self.options.tmpdir) + if self.setup_clean_chain: + initialize_chain_clean(self.options.tmpdir, self.num_nodes) + else: + initialize_chain(self.options.tmpdir, self.num_nodes) def setup_nodes(self): - return start_nodes(4, self.options.tmpdir) + return start_nodes(self.num_nodes, self.options.tmpdir) def setup_network(self, split = False): self.nodes = self.setup_nodes() @@ -181,9 +185,10 @@ def main(self): class ComparisonTestFramework(BitcoinTestFramework): - # Can override the num_nodes variable to indicate how many nodes to run. def __init__(self): + super().__init__() self.num_nodes = 2 + self.setup_clean_chain = True def add_options(self, parser): parser.add_option("--testbinary", dest="testbinary", @@ -193,10 +198,6 @@ def add_options(self, parser): default=os.getenv("BITCOIND", "bitcoind"), help="bitcoind binary to use for reference nodes (if any)") - def setup_chain(self): - print("Initializing test directory "+self.options.tmpdir) - initialize_chain_clean(self.options.tmpdir, self.num_nodes) - def setup_network(self): self.nodes = start_nodes( self.num_nodes, self.options.tmpdir, diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index 6784177aaac57..0e522e78d4853 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -182,24 +182,28 @@ def wait_for_bitcoind_start(process, url, i): raise # unkown JSON RPC exception time.sleep(0.25) -def initialize_chain(test_dir): +def initialize_chain(test_dir, num_nodes): """ - Create (or copy from cache) a 200-block-long chain and - 4 wallets. + Create a cache of a 200-block-long chain (with wallet) for MAX_NODES + Afterward, create num_nodes copies from the cache """ - if (not os.path.isdir(os.path.join("cache","node0")) - or not os.path.isdir(os.path.join("cache","node1")) - or not os.path.isdir(os.path.join("cache","node2")) - or not os.path.isdir(os.path.join("cache","node3"))): + assert num_nodes <= MAX_NODES + create_cache = False + for i in range(MAX_NODES): + if not os.path.isdir(os.path.join('cache', 'node'+str(i))): + create_cache = True + break + + if create_cache: #find and delete old cache directories if any exist - for i in range(4): + for i in range(MAX_NODES): if os.path.isdir(os.path.join("cache","node"+str(i))): shutil.rmtree(os.path.join("cache","node"+str(i))) # Create cache directories, run bitcoinds: - for i in range(4): + for i in range(MAX_NODES): datadir=initialize_datadir("cache", i) args = [ os.getenv("BITCOIND", "bitcoind"), "-server", "-keypool=1", "-datadir="+datadir, "-discover=0" ] if i > 0: @@ -212,15 +216,18 @@ def initialize_chain(test_dir): print("initialize_chain: RPC succesfully started") rpcs = [] - for i in range(4): + for i in range(MAX_NODES): try: rpcs.append(get_rpc_proxy(rpc_url(i), i)) except: sys.stderr.write("Error connecting to "+url+"\n") sys.exit(1) - # Create a 200-block-long chain; each of the 4 nodes + # Create a 200-block-long chain; each of the 4 first nodes # gets 25 mature blocks and 25 immature. + # Note: To preserve compatibility with older versions of + # initialize_chain, only 4 nodes will generate coins. + # # blocks are created with timestamps 10 minutes apart # starting from 2010 minutes in the past enable_mocktime() @@ -238,13 +245,13 @@ def initialize_chain(test_dir): stop_nodes(rpcs) wait_bitcoinds() disable_mocktime() - for i in range(4): + for i in range(MAX_NODES): os.remove(log_filename("cache", i, "debug.log")) os.remove(log_filename("cache", i, "db.log")) os.remove(log_filename("cache", i, "peers.dat")) os.remove(log_filename("cache", i, "fee_estimates.dat")) - for i in range(4): + for i in range(num_nodes): from_dir = os.path.join("cache", "node"+str(i)) to_dir = os.path.join(test_dir, "node"+str(i)) shutil.copytree(from_dir, to_dir) diff --git a/qa/rpc-tests/txn_clone.py b/qa/rpc-tests/txn_clone.py index 5710c29aa60cd..22f850ece64a2 100755 --- a/qa/rpc-tests/txn_clone.py +++ b/qa/rpc-tests/txn_clone.py @@ -12,6 +12,11 @@ class TxnMallTest(BitcoinTestFramework): + def __init__(self): + super().__init__() + self.num_nodes = 4 + self.setup_clean_chain = False + def add_options(self, parser): parser.add_option("--mineblock", dest="mine_block", default=False, action="store_true", help="Test double-spend of 1-confirmed transaction") diff --git a/qa/rpc-tests/txn_doublespend.py b/qa/rpc-tests/txn_doublespend.py index 1fbb207e22db8..84944c3c1943a 100755 --- a/qa/rpc-tests/txn_doublespend.py +++ b/qa/rpc-tests/txn_doublespend.py @@ -12,6 +12,11 @@ class TxnMallTest(BitcoinTestFramework): + def __init__(self): + super().__init__() + self.num_nodes = 4 + self.setup_clean_chain = False + def add_options(self, parser): parser.add_option("--mineblock", dest="mine_block", default=False, action="store_true", help="Test double-spend of 1-confirmed transaction") diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py index 42ce0a7260fa3..2d24ced97cffc 100755 --- a/qa/rpc-tests/wallet.py +++ b/qa/rpc-tests/wallet.py @@ -19,9 +19,10 @@ def check_fee_amount(self, curr_balance, balance_with_fee, fee_per_byte, tx_size raise AssertionError("Fee of %s BTC too high! (Should be %s BTC)"%(str(fee), str(target_fee))) return curr_balance - def setup_chain(self): - print("Initializing test directory "+self.options.tmpdir) - initialize_chain_clean(self.options.tmpdir, 4) + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 4 def setup_network(self, split=False): self.nodes = start_nodes(3, self.options.tmpdir) diff --git a/qa/rpc-tests/walletbackup.py b/qa/rpc-tests/walletbackup.py index c3d53669c9fa4..b991d5c761862 100755 --- a/qa/rpc-tests/walletbackup.py +++ b/qa/rpc-tests/walletbackup.py @@ -41,15 +41,16 @@ class WalletBackupTest(BitcoinTestFramework): - def setup_chain(self): - logging.info("Initializing test directory "+self.options.tmpdir) - initialize_chain_clean(self.options.tmpdir, 4) + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 4 # This mirrors how the network was setup in the bash test def setup_network(self, split=False): # nodes 1, 2,3 are spenders, let's give them a keypool=100 extra_args = [["-keypool=100"], ["-keypool=100"], ["-keypool=100"], []] - self.nodes = start_nodes(4, self.options.tmpdir, extra_args) + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args) connect_nodes(self.nodes[0], 3) connect_nodes(self.nodes[1], 3) connect_nodes(self.nodes[2], 3) diff --git a/qa/rpc-tests/zapwallettxes.py b/qa/rpc-tests/zapwallettxes.py index 2f8214f87c26c..17ba53a844b4f 100755 --- a/qa/rpc-tests/zapwallettxes.py +++ b/qa/rpc-tests/zapwallettxes.py @@ -9,12 +9,13 @@ class ZapWalletTXesTest (BitcoinTestFramework): - def setup_chain(self): - print("Initializing test directory "+self.options.tmpdir) - initialize_chain_clean(self.options.tmpdir, 3) + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 3 def setup_network(self, split=False): - self.nodes = start_nodes(3, self.options.tmpdir) + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) diff --git a/qa/rpc-tests/zmq_test.py b/qa/rpc-tests/zmq_test.py index f5617a084db7d..3a116317fed96 100755 --- a/qa/rpc-tests/zmq_test.py +++ b/qa/rpc-tests/zmq_test.py @@ -17,6 +17,10 @@ class ZMQTest (BitcoinTestFramework): + def __init__(self): + super().__init__() + self.num_nodes = 4 + port = 28332 def setup_nodes(self): @@ -25,7 +29,7 @@ def setup_nodes(self): self.zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"hashblock") self.zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"hashtx") self.zmqSubSocket.connect("tcp://127.0.0.1:%i" % self.port) - return start_nodes(4, self.options.tmpdir, extra_args=[ + return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[ ['-zmqpubhashtx=tcp://127.0.0.1:'+str(self.port), '-zmqpubhashblock=tcp://127.0.0.1:'+str(self.port)], [], [], From fad68f751aff024bcbc1587640c3591aab5a80f7 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 15 May 2016 12:20:15 +0200 Subject: [PATCH 0322/1802] [qa] Reduce node count for some tests --- qa/rpc-tests/importprunedfunds.py | 2 +- qa/rpc-tests/maxuploadtarget.py | 2 +- qa/rpc-tests/mempool_limit.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/qa/rpc-tests/importprunedfunds.py b/qa/rpc-tests/importprunedfunds.py index 761c9af90c30e..d86f51b7f3aaf 100755 --- a/qa/rpc-tests/importprunedfunds.py +++ b/qa/rpc-tests/importprunedfunds.py @@ -12,7 +12,7 @@ class ImportPrunedFundsTest(BitcoinTestFramework): def __init__(self): super().__init__() self.setup_clean_chain = True - self.num_nodes = 4 + self.num_nodes = 2 def setup_network(self, split=False): self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) diff --git a/qa/rpc-tests/maxuploadtarget.py b/qa/rpc-tests/maxuploadtarget.py index 42235a511910b..5087f0762033a 100755 --- a/qa/rpc-tests/maxuploadtarget.py +++ b/qa/rpc-tests/maxuploadtarget.py @@ -89,7 +89,7 @@ def add_options(self, parser): def __init__(self): super().__init__() self.setup_clean_chain = True - self.num_nodes = 2 + self.num_nodes = 1 self.utxo = [] self.txouts = gen_return_txouts() diff --git a/qa/rpc-tests/mempool_limit.py b/qa/rpc-tests/mempool_limit.py index c1c5558a95fc1..4438c152df10a 100755 --- a/qa/rpc-tests/mempool_limit.py +++ b/qa/rpc-tests/mempool_limit.py @@ -20,7 +20,7 @@ def setup_network(self): def __init__(self): super().__init__() self.setup_clean_chain = True - self.num_nodes = 2 + self.num_nodes = 1 self.txouts = gen_return_txouts() From f93c2a1b7ee912f0651ebb4c8a5eca220e434f4a Mon Sep 17 00:00:00 2001 From: Daniel Kraft Date: Sun, 15 May 2016 20:15:02 +0200 Subject: [PATCH 0323/1802] net: Avoid duplicate getheaders requests. The current logic for syncing headers may lead to lots of duplicate getheaders requests being sent: If a new block arrives while the node is in headers sync, it will send getheaders in response to the block announcement. When the headers arrive, the message will be of maximum size and so a follow-up request will be sent---all of that in addition to the existing headers syncing. This will create a second "chain" of getheaders requests. If more blocks arrive, this may even lead to arbitrarily many parallel chains of redundant requests. This patch changes the behaviour to only request more headers after a maximum-sized message when it contained at least one unknown header. This avoids sustaining parallel chains of redundant requests. Note that this patch avoids the issues raised in the discussion of https://github.com/bitcoin/bitcoin/pull/6821: There is no risk of the node being permanently blocked. At the latest when a new block arrives this will trigger a new getheaders request and restart syncing. --- src/main.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index ee30954b48545..5816f799a0039 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5091,6 +5091,13 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, return true; } + // If we already know the last header in the message, then it contains + // no new information for us. In this case, we do not request + // more headers later. This prevents multiple chains of redundant + // getheader requests from running in parallel if triggered by incoming + // blocks while the node is still in initial headers sync. + const bool hasNewHeaders = (mapBlockIndex.count(headers.back().GetHash()) == 0); + CBlockIndex *pindexLast = NULL; BOOST_FOREACH(const CBlockHeader& header, headers) { CValidationState state; @@ -5111,7 +5118,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, if (pindexLast) UpdateBlockAvailability(pfrom->GetId(), pindexLast->GetBlockHash()); - if (nCount == MAX_HEADERS_RESULTS && pindexLast) { + if (nCount == MAX_HEADERS_RESULTS && pindexLast && hasNewHeaders) { // Headers message had its maximum size; the peer may have more headers. // TODO: optimize: if pindexLast is an ancestor of chainActive.Tip or pindexBestHeader, continue // from there instead. From d87b198b7334317952ca6a1377e25b5c859a1767 Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Wed, 20 Apr 2016 19:38:19 +0000 Subject: [PATCH 0324/1802] Remove unneeded feerate param from RelayTransaction/AcceptToMemoryPool. --- src/main.cpp | 23 +++++++++-------------- src/main.h | 2 +- src/net.cpp | 2 +- src/net.h | 2 +- src/rpc/rawtransaction.cpp | 5 ++--- src/test/txvalidationcache_tests.cpp | 2 +- src/wallet/wallet.cpp | 6 ++---- 7 files changed, 17 insertions(+), 25 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index ee30954b48545..09f82312a9b9e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1005,7 +1005,7 @@ std::string FormatStateMessage(const CValidationState &state) } bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const CTransaction& tx, bool fLimitFree, - bool* pfMissingInputs, CFeeRate* txFeeRate, bool fOverrideMempoolLimit, const CAmount& nAbsurdFee, + bool* pfMissingInputs, bool fOverrideMempoolLimit, const CAmount& nAbsurdFee, std::vector& vHashTxnToUncache) { const uint256 hash = tx.GetHash(); @@ -1170,9 +1170,6 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainActive.Height(), pool.HasNoInputsOf(tx), inChainInputValue, fSpendsCoinbase, nSigOps, lp); unsigned int nSize = entry.GetTxSize(); - if (txFeeRate) { - *txFeeRate = CFeeRate(nFees, nSize); - } // Check that the transaction doesn't have an excessive number of // sigops, making it impossible to mine. Since the coinbase transaction @@ -1421,10 +1418,10 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C } bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree, - bool* pfMissingInputs, CFeeRate* txFeeRate, bool fOverrideMempoolLimit, const CAmount nAbsurdFee) + bool* pfMissingInputs, bool fOverrideMempoolLimit, const CAmount nAbsurdFee) { std::vector vHashTxToUncache; - bool res = AcceptToMemoryPoolWorker(pool, state, tx, fLimitFree, pfMissingInputs, txFeeRate, fOverrideMempoolLimit, nAbsurdFee, vHashTxToUncache); + bool res = AcceptToMemoryPoolWorker(pool, state, tx, fLimitFree, pfMissingInputs, fOverrideMempoolLimit, nAbsurdFee, vHashTxToUncache); if (!res) { BOOST_FOREACH(const uint256& hashTx, vHashTxToUncache) pcoinsTip->Uncache(hashTx); @@ -2651,7 +2648,7 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara // ignore validation errors in resurrected transactions list removed; CValidationState stateDummy; - if (tx.IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL, NULL, true)) { + if (tx.IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL, true)) { mempool.removeRecursive(tx, removed); } else if (mempool.exists(tx.GetHash())) { vHashUpdate.push_back(tx.GetHash()); @@ -4956,10 +4953,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, pfrom->setAskFor.erase(inv.hash); mapAlreadyAskedFor.erase(inv.hash); - CFeeRate txFeeRate = CFeeRate(0); - if (!AlreadyHave(inv) && AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs, &txFeeRate)) { + if (!AlreadyHave(inv) && AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs)) { mempool.check(pcoinsTip); - RelayTransaction(tx, txFeeRate); + RelayTransaction(tx); vWorkQueue.push_back(inv.hash); LogPrint("mempool", "AcceptToMemoryPool: peer=%d: accepted %s (poolsz %u txn, %u kB)\n", @@ -4990,10 +4986,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, if (setMisbehaving.count(fromPeer)) continue; - CFeeRate orphanFeeRate = CFeeRate(0); - if (AcceptToMemoryPool(mempool, stateDummy, orphanTx, true, &fMissingInputs2, &orphanFeeRate)) { + if (AcceptToMemoryPool(mempool, stateDummy, orphanTx, true, &fMissingInputs2)) { LogPrint("mempool", " accepted orphan tx %s\n", orphanHash.ToString()); - RelayTransaction(orphanTx, orphanFeeRate); + RelayTransaction(orphanTx); vWorkQueue.push_back(orphanHash); vEraseQueue.push_back(orphanHash); } @@ -5046,7 +5041,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int nDoS = 0; if (!state.IsInvalid(nDoS) || nDoS == 0) { LogPrintf("Force relaying tx %s from whitelisted peer=%d\n", tx.GetHash().ToString(), pfrom->id); - RelayTransaction(tx, txFeeRate); + RelayTransaction(tx); } else { LogPrintf("Not relaying invalid transaction %s from whitelisted peer=%d (%s)\n", tx.GetHash().ToString(), pfrom->id, FormatStateMessage(state)); } diff --git a/src/main.h b/src/main.h index 548218a1b51cc..576f73b5f2ba7 100644 --- a/src/main.h +++ b/src/main.h @@ -295,7 +295,7 @@ void PruneAndFlush(); /** (try to) add transaction to memory pool **/ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree, - bool* pfMissingInputs, CFeeRate* txFeeRate, bool fOverrideMempoolLimit=false, const CAmount nAbsurdFee=0); + bool* pfMissingInputs, bool fOverrideMempoolLimit=false, const CAmount nAbsurdFee=0); /** Convert CValidationState to a human-readable message for logging */ std::string FormatStateMessage(const CValidationState &state); diff --git a/src/net.cpp b/src/net.cpp index 5e810a0f15888..aa5b47340a340 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2069,7 +2069,7 @@ class CNetCleanup instance_of_cnetcleanup; -void RelayTransaction(const CTransaction& tx, CFeeRate feerate) +void RelayTransaction(const CTransaction& tx) { CInv inv(MSG_TX, tx.GetHash()); { diff --git a/src/net.h b/src/net.h index b6ec7bf3e2c28..fd80056c6b8b7 100644 --- a/src/net.h +++ b/src/net.h @@ -783,7 +783,7 @@ class CNode class CTransaction; -void RelayTransaction(const CTransaction& tx, CFeeRate feerate); +void RelayTransaction(const CTransaction& tx); /** Access to the (IP) address database (peers.dat) */ class CAddrDB diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index de8cd68f66267..bec7ebe55f636 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -819,12 +819,11 @@ UniValue sendrawtransaction(const UniValue& params, bool fHelp) const CCoins* existingCoins = view.AccessCoins(hashTx); bool fHaveMempool = mempool.exists(hashTx); bool fHaveChain = existingCoins && existingCoins->nHeight < 1000000000; - CFeeRate txFeeRate = CFeeRate(0); if (!fHaveMempool && !fHaveChain) { // push to local node and sync with wallets CValidationState state; bool fMissingInputs; - if (!AcceptToMemoryPool(mempool, state, tx, false, &fMissingInputs, &txFeeRate, false, nMaxRawTxFee)) { + if (!AcceptToMemoryPool(mempool, state, tx, false, &fMissingInputs, false, nMaxRawTxFee)) { if (state.IsInvalid()) { throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason())); } else { @@ -837,7 +836,7 @@ UniValue sendrawtransaction(const UniValue& params, bool fHelp) } else if (fHaveChain) { throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain"); } - RelayTransaction(tx, txFeeRate); + RelayTransaction(tx); return hashTx.GetHex(); } diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp index 237b26329b1c1..c29e30792a2a9 100644 --- a/src/test/txvalidationcache_tests.cpp +++ b/src/test/txvalidationcache_tests.cpp @@ -23,7 +23,7 @@ ToMemPool(CMutableTransaction& tx) LOCK(cs_main); CValidationState state; - return AcceptToMemoryPool(mempool, state, tx, false, NULL, NULL, true, 0); + return AcceptToMemoryPool(mempool, state, tx, false, NULL, true, 0); } BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index a18b669b32d89..6b942e29d76c4 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1272,9 +1272,7 @@ bool CWalletTx::RelayWalletTransaction() { if (GetDepthInMainChain() == 0 && !isAbandoned() && InMempool()) { LogPrintf("Relaying wtx %s\n", GetHash().ToString()); - CFeeRate feeRate; - mempool.lookupFeeRate(GetHash(), feeRate); - RelayTransaction((CTransaction)*this, feeRate); + RelayTransaction((CTransaction)*this); return true; } } @@ -3331,5 +3329,5 @@ int CMerkleTx::GetBlocksToMaturity() const bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, CAmount nAbsurdFee) { CValidationState state; - return ::AcceptToMemoryPool(mempool, state, *this, fLimitFree, NULL, NULL, false, nAbsurdFee); + return ::AcceptToMemoryPool(mempool, state, *this, fLimitFree, NULL, false, nAbsurdFee); } From d253ec4baa21cc292cf72d453f71b4043b53e591 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 20 Apr 2016 14:53:36 +0200 Subject: [PATCH 0325/1802] Make ProcessNewBlock dbp const and update comment --- src/main.cpp | 4 ++-- src/main.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 09f82312a9b9e..981d987711731 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3398,7 +3398,7 @@ static bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state } /** Store block on disk. If dbp is non-NULL, the file is known to already reside on disk */ -static bool AcceptBlock(const CBlock& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, CDiskBlockPos* dbp) +static bool AcceptBlock(const CBlock& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const CDiskBlockPos* dbp) { AssertLockHeld(cs_main); @@ -3474,7 +3474,7 @@ static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned } -bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, const CNode* pfrom, const CBlock* pblock, bool fForceProcessing, CDiskBlockPos* dbp) +bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, const CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp) { { LOCK(cs_main); diff --git a/src/main.h b/src/main.h index 576f73b5f2ba7..f287171f141ba 100644 --- a/src/main.h +++ b/src/main.h @@ -212,10 +212,10 @@ void UnregisterNodeSignals(CNodeSignals& nodeSignals); * @param[in] pfrom The node which we are receiving the block from; it is added to mapBlockSource and may be penalised if the block is invalid. * @param[in] pblock The block we want to process. * @param[in] fForceProcessing Process this block even if unrequested; used for non-network block sources and whitelisted peers. - * @param[out] dbp If pblock is stored to disk (or already there), this will be set to its location. + * @param[out] dbp The already known disk position of pblock, or NULL if not yet stored. * @return True if state.IsValid() */ -bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, const CNode* pfrom, const CBlock* pblock, bool fForceProcessing, CDiskBlockPos* dbp); +bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, const CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp); /** Check whether enough disk space is available for an incoming block */ bool CheckDiskSpace(uint64_t nAdditionalBytes = 0); /** Open a block file (blk?????.dat) */ From 316623f2c197971db9b5bcb9c84e446254b552c3 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 20 Apr 2016 15:45:41 +0200 Subject: [PATCH 0326/1802] Switch reindexing to AcceptBlock in-loop and ActivateBestChain afterwards --- src/init.cpp | 20 ++++++++++---------- src/main.cpp | 13 ++++++++----- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index d19ca530b3831..beb848ddb0eff 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -404,7 +404,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-limitdescendantcount=", strprintf("Do not accept transactions if any ancestor would have or more in-mempool descendants (default: %u)", DEFAULT_DESCENDANT_LIMIT)); strUsage += HelpMessageOpt("-limitdescendantsize=", strprintf("Do not accept transactions if any ancestor would have more than kilobytes of in-mempool descendants (default: %u).", DEFAULT_DESCENDANT_SIZE_LIMIT)); } - string debugCategories = "addrman, alert, bench, coindb, db, lock, rand, rpc, selectcoins, mempool, mempoolrej, net, proxy, prune, http, libevent, tor, zmq"; // Don't translate these and qt below + string debugCategories = "addrman, alert, bench, coindb, db, http, libevent, lock, mempool, mempoolrej, net, proxy, prune, rand, reindex, rpc, selectcoins, tor, zmq"; // Don't translate these and qt below if (mode == HMM_BITCOIN_QT) debugCategories += ", qt"; strUsage += HelpMessageOpt("-debug=", strprintf(_("Output debugging information (default: %u, supplying is optional)"), 0) + ". " + @@ -554,9 +554,10 @@ void ThreadImport(std::vector vImportFiles) { const CChainParams& chainparams = Params(); RenameThread("bitcoin-loadblk"); + CImportingNow imp; + // -reindex if (fReindex) { - CImportingNow imp; int nFile = 0; while (true) { CDiskBlockPos pos(nFile, 0); @@ -581,7 +582,6 @@ void ThreadImport(std::vector vImportFiles) if (boost::filesystem::exists(pathBootstrap)) { FILE *file = fopen(pathBootstrap.string().c_str(), "rb"); if (file) { - CImportingNow imp; boost::filesystem::path pathBootstrapOld = GetDataDir() / "bootstrap.dat.old"; LogPrintf("Importing bootstrap.dat...\n"); LoadExternalBlockFile(chainparams, file); @@ -595,7 +595,6 @@ void ThreadImport(std::vector vImportFiles) BOOST_FOREACH(const boost::filesystem::path& path, vImportFiles) { FILE *file = fopen(path.string().c_str(), "rb"); if (file) { - CImportingNow imp; LogPrintf("Importing blocks file %s...\n", path.string()); LoadExternalBlockFile(chainparams, file); } else { @@ -603,6 +602,13 @@ void ThreadImport(std::vector vImportFiles) } } + // scan for better chains in the block chain database, that are not yet connected in the active best chain + CValidationState state; + if (!ActivateBestChain(state, chainparams)) { + LogPrintf("Failed to connect best block"); + StartShutdown(); + } + if (GetBoolArg("-stopafterblockimport", DEFAULT_STOPAFTERBLOCKIMPORT)) { LogPrintf("Stopping after block import\n"); StartShutdown(); @@ -1358,12 +1364,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (mapArgs.count("-blocknotify")) uiInterface.NotifyBlockTip.connect(BlockNotifyCallback); - uiInterface.InitMessage(_("Activating best chain...")); - // scan for better chains in the block chain database, that are not yet connected in the active best chain - CValidationState state; - if (!ActivateBestChain(state, chainparams)) - strErrors << "Failed to connect best block"; - std::vector vImportFiles; if (mapArgs.count("-loadblock")) { diff --git a/src/main.cpp b/src/main.cpp index 981d987711731..42733ee2de2ca 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3402,7 +3402,8 @@ static bool AcceptBlock(const CBlock& block, CValidationState& state, const CCha { AssertLockHeld(cs_main); - CBlockIndex *&pindex = *ppindex; + CBlockIndex *pindexDummy = NULL; + CBlockIndex *&pindex = ppindex ? *ppindex : pindexDummy; if (!AcceptBlockHeader(block, state, chainparams, &pindex)) return false; @@ -4037,13 +4038,14 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB // process in case the block isn't known yet if (mapBlockIndex.count(hash) == 0 || (mapBlockIndex[hash]->nStatus & BLOCK_HAVE_DATA) == 0) { + LOCK(cs_main); CValidationState state; - if (ProcessNewBlock(state, chainparams, NULL, &block, true, dbp)) + if (AcceptBlock(block, state, chainparams, NULL, true, dbp)) nLoaded++; if (state.IsError()) break; } else if (hash != chainparams.GetConsensus().hashGenesisBlock && mapBlockIndex[hash]->nHeight % 1000 == 0) { - LogPrintf("Block Import: already had block %s at height %d\n", hash.ToString(), mapBlockIndex[hash]->nHeight); + LogPrint("reindex", "Block Import: already had block %s at height %d\n", hash.ToString(), mapBlockIndex[hash]->nHeight); } // Recursively process earlier encountered successors of this block @@ -4057,10 +4059,11 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB std::multimap::iterator it = range.first; if (ReadBlockFromDisk(block, it->second, chainparams.GetConsensus())) { - LogPrintf("%s: Processing out of order child %s of %s\n", __func__, block.GetHash().ToString(), + LogPrint("reindex", "%s: Processing out of order child %s of %s\n", __func__, block.GetHash().ToString(), head.ToString()); + LOCK(cs_main); CValidationState dummy; - if (ProcessNewBlock(dummy, chainparams, NULL, &block, true, &it->second)) + if (AcceptBlock(block, dummy, chainparams, NULL, true, &it->second)) { nLoaded++; queue.push_back(block.GetHash()); From fb8fad1586ced69fa37c665a11916ae4c4d0df05 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 20 Apr 2016 16:02:19 +0200 Subject: [PATCH 0327/1802] Optimize ActivateBestChain for long chains --- src/main.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 42733ee2de2ca..38851cda3e21d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2811,10 +2811,9 @@ static void PruneBlockIndexCandidates() { * Try to make some progress towards making pindexMostWork the active block. * pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork. */ -static bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const CBlock* pblock) +static bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const CBlock* pblock, bool& fInvalidFound) { AssertLockHeld(cs_main); - bool fInvalidFound = false; const CBlockIndex *pindexOldTip = chainActive.Tip(); const CBlockIndex *pindexFork = chainActive.FindFork(pindexMostWork); @@ -2902,15 +2901,22 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, { LOCK(cs_main); CBlockIndex *pindexOldTip = chainActive.Tip(); - pindexMostWork = FindMostWorkChain(); + if (pindexMostWork == NULL) { + pindexMostWork = FindMostWorkChain(); + } // Whether we have anything to do at all. if (pindexMostWork == NULL || pindexMostWork == chainActive.Tip()) return true; - if (!ActivateBestChainStep(state, chainparams, pindexMostWork, pblock && pblock->GetHash() == pindexMostWork->GetBlockHash() ? pblock : NULL)) + bool fInvalidFound = false; + if (!ActivateBestChainStep(state, chainparams, pindexMostWork, pblock && pblock->GetHash() == pindexMostWork->GetBlockHash() ? pblock : NULL, fInvalidFound)) return false; + if (fInvalidFound) { + // Wipe cache, we may need another branch now. + pindexMostWork = NULL; + } pindexNewTip = chainActive.Tip(); pindexFork = chainActive.FindFork(pindexOldTip); fInitialDownload = IsInitialBlockDownload(); From d3d75479115bc3480f163df774ee9dd2f8bd9f54 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 21 Apr 2016 14:14:37 +0200 Subject: [PATCH 0328/1802] Add -reindex-chainstate that does not rebuild block index --- qa/rpc-tests/reindex.py | 15 +++++++++++---- src/init.cpp | 8 +++++--- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/qa/rpc-tests/reindex.py b/qa/rpc-tests/reindex.py index 39564b32bad90..cb5e413fd6a94 100755 --- a/qa/rpc-tests/reindex.py +++ b/qa/rpc-tests/reindex.py @@ -4,7 +4,7 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. # -# Test -reindex with CheckBlockIndex +# Test -reindex and -reindex-chainstate with CheckBlockIndex # from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * @@ -20,13 +20,20 @@ def setup_network(self): self.is_network_split = False self.nodes.append(start_node(0, self.options.tmpdir)) - def run_test(self): + def reindex(self, justchainstate=False): self.nodes[0].generate(3) + blockcount = self.nodes[0].getblockcount() stop_node(self.nodes[0], 0) wait_bitcoinds() - self.nodes[0]=start_node(0, self.options.tmpdir, ["-debug", "-reindex", "-checkblockindex=1"]) - assert_equal(self.nodes[0].getblockcount(), 3) + self.nodes[0]=start_node(0, self.options.tmpdir, ["-debug", "-reindex-chainstate" if justchainstate else "-reindex", "-checkblockindex=1"]) + assert_equal(self.nodes[0].getblockcount(), blockcount) print("Success") + def run_test(self): + self.reindex(False) + self.reindex(True) + self.reindex(False) + self.reindex(True) + if __name__ == '__main__': ReindexTest().main() diff --git a/src/init.cpp b/src/init.cpp index beb848ddb0eff..8688381ecff35 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -327,7 +327,8 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-prune=", strprintf(_("Reduce storage requirements by pruning (deleting) old blocks. This mode is incompatible with -txindex and -rescan. " "Warning: Reverting this setting requires re-downloading the entire blockchain. " "(default: 0 = disable pruning blocks, >%u = target size in MiB to use for block files)"), MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024)); - strUsage += HelpMessageOpt("-reindex", _("Rebuild block chain index from current blk000??.dat files on startup")); + strUsage += HelpMessageOpt("-reindex-chainstate", _("Rebuild chain state from the currently indexed blocks")); + strUsage += HelpMessageOpt("-reindex", _("Rebuild chain state and block index from the blk*.dat files on disk")); #ifndef WIN32 strUsage += HelpMessageOpt("-sysperms", _("Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)")); #endif @@ -1164,6 +1165,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // ********************************************************* Step 7: load block chain fReindex = GetBoolArg("-reindex", false); + bool fReindexChainState = GetBoolArg("-reindex-chainstate", false); // Upgrading to 0.8; hard-link the old blknnnn.dat files into /blocks/ boost::filesystem::path blocksDir = GetDataDir() / "blocks"; @@ -1225,7 +1227,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) delete pblocktree; pblocktree = new CBlockTreeDB(nBlockTreeDBCache, false, fReindex); - pcoinsdbview = new CCoinsViewDB(nCoinDBCache, false, fReindex); + pcoinsdbview = new CCoinsViewDB(nCoinDBCache, false, fReindex || fReindexChainState); pcoinscatcher = new CCoinsViewErrorCatcher(pcoinsdbview); pcoinsTip = new CCoinsViewCache(pcoinscatcher); @@ -1254,7 +1256,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // Check for changed -txindex state if (fTxIndex != GetBoolArg("-txindex", DEFAULT_TXINDEX)) { - strLoadError = _("You need to rebuild the database using -reindex to change -txindex"); + strLoadError = _("You need to rebuild the database using -reindex-chainstate to change -txindex"); break; } From b4d24e142e25a21c78ab74146c3520f2259fd7c2 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 28 Apr 2016 16:18:45 +0200 Subject: [PATCH 0329/1802] Report reindexing progress in GUI --- qa/rpc-tests/reindex.py | 3 +++ src/main.cpp | 39 ++++++++++++++++++++++++++++++++++++++ src/qt/bitcoingui.cpp | 18 ++++++++++++++---- src/qt/bitcoingui.h | 2 +- src/qt/clientmodel.cpp | 18 ++++++++++++------ src/qt/clientmodel.h | 2 +- src/qt/rpcconsole.cpp | 12 +++++++----- src/qt/rpcconsole.h | 2 +- src/qt/sendcoinsdialog.cpp | 2 +- src/ui_interface.h | 3 +++ 10 files changed, 82 insertions(+), 19 deletions(-) diff --git a/qa/rpc-tests/reindex.py b/qa/rpc-tests/reindex.py index cb5e413fd6a94..a3f4d6ea01573 100755 --- a/qa/rpc-tests/reindex.py +++ b/qa/rpc-tests/reindex.py @@ -8,6 +8,7 @@ # from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * +import time class ReindexTest(BitcoinTestFramework): @@ -26,6 +27,8 @@ def reindex(self, justchainstate=False): stop_node(self.nodes[0], 0) wait_bitcoinds() self.nodes[0]=start_node(0, self.options.tmpdir, ["-debug", "-reindex-chainstate" if justchainstate else "-reindex", "-checkblockindex=1"]) + while self.nodes[0].getblockcount() < blockcount: + time.sleep(0.1) assert_equal(self.nodes[0].getblockcount(), blockcount) print("Success") diff --git a/src/main.cpp b/src/main.cpp index 38851cda3e21d..66930b3b067b4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2883,6 +2883,28 @@ static bool ActivateBestChainStep(CValidationState& state, const CChainParams& c return true; } +static void NotifyHeaderTip() { + bool fNotify = false; + bool fInitialBlockDownload = false; + static CBlockIndex* pindexHeaderOld = NULL; + CBlockIndex* pindexHeader = NULL; + { + LOCK(cs_main); + if (!setBlockIndexCandidates.empty()) { + pindexHeader = *setBlockIndexCandidates.rbegin(); + } + if (pindexHeader != pindexHeaderOld) { + fNotify = true; + fInitialBlockDownload = IsInitialBlockDownload(); + pindexHeaderOld = pindexHeader; + } + } + // Send block tip changed notifications without cs_main + if (fNotify) { + uiInterface.NotifyHeaderTip(fInitialBlockDownload, pindexHeader); + } +} + /** * Make the best chain active, in multiple steps. The result is either failure * or an activated best chain. pblock is either NULL or a pointer to a block @@ -3499,6 +3521,8 @@ bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, c return error("%s: AcceptBlock FAILED", __func__); } + NotifyHeaderTip(); + if (!ActivateBestChain(state, chainparams, pblock)) return error("%s: ActivateBestChain failed", __func__); @@ -4054,6 +4078,16 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB LogPrint("reindex", "Block Import: already had block %s at height %d\n", hash.ToString(), mapBlockIndex[hash]->nHeight); } + // Activate the genesis block so normal node progress can continue + if (hash == chainparams.GetConsensus().hashGenesisBlock) { + CValidationState state; + if (!ActivateBestChain(state, chainparams)) { + break; + } + } + + NotifyHeaderTip(); + // Recursively process earlier encountered successors of this block deque queue; queue.push_back(hash); @@ -4077,6 +4111,7 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB } range.first++; mapBlocksUnknownParent.erase(it); + NotifyHeaderTip(); } } } catch (const std::exception& e) { @@ -5088,6 +5123,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, ReadCompactSize(vRecv); // ignore tx count; assume it is 0. } + { LOCK(cs_main); if (nCount == 0) { @@ -5171,6 +5207,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } CheckBlockIndex(chainparams.GetConsensus()); + } + + NotifyHeaderTip(); } else if (strCommand == NetMsgType::BLOCK && !fImporting && !fReindex) // Ignore blocks received while importing diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 99844863640f4..4998848e9fb98 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -457,8 +457,8 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel) setNumConnections(clientModel->getNumConnections()); connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int))); - setNumBlocks(clientModel->getNumBlocks(), clientModel->getLastBlockDate(), clientModel->getVerificationProgress(NULL)); - connect(clientModel, SIGNAL(numBlocksChanged(int,QDateTime,double)), this, SLOT(setNumBlocks(int,QDateTime,double))); + setNumBlocks(clientModel->getNumBlocks(), clientModel->getLastBlockDate(), clientModel->getVerificationProgress(NULL), false); + connect(clientModel, SIGNAL(numBlocksChanged(int,QDateTime,double,bool)), this, SLOT(setNumBlocks(int,QDateTime,double,bool))); // Receive and report messages from client model connect(clientModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int))); @@ -696,7 +696,7 @@ void BitcoinGUI::setNumConnections(int count) labelConnectionsIcon->setToolTip(tr("%n active connection(s) to Bitcoin network", "", count)); } -void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress) +void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool header) { if(!clientModel) return; @@ -708,15 +708,25 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer enum BlockSource blockSource = clientModel->getBlockSource(); switch (blockSource) { case BLOCK_SOURCE_NETWORK: + if (header) { + return; + } progressBarLabel->setText(tr("Synchronizing with network...")); break; case BLOCK_SOURCE_DISK: - progressBarLabel->setText(tr("Importing blocks from disk...")); + if (header) { + progressBarLabel->setText(tr("Indexing blocks on disk...")); + } else { + progressBarLabel->setText(tr("Processing blocks on disk...")); + } break; case BLOCK_SOURCE_REINDEX: progressBarLabel->setText(tr("Reindexing blocks on disk...")); break; case BLOCK_SOURCE_NONE: + if (header) { + return; + } // Case: not Importing, not Reindexing and no network connection progressBarLabel->setText(tr("No block source available...")); break; diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 27ef11c75c079..33639ed5a2d4b 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -150,7 +150,7 @@ public Q_SLOTS: /** Set number of connections shown in the UI */ void setNumConnections(int count); /** Set number of blocks and last block date shown in the UI */ - void setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress); + void setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool headers); /** Notify the user of an event from the core network or transaction handling code. @param[in] title the message box / notification title diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 697736cc880bb..108500654b2da 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -24,6 +24,7 @@ class CBlockIndex; static const int64_t nClientStartupTime = GetTime(); +static int64_t nLastHeaderTipUpdateNotification = 0; static int64_t nLastBlockTipUpdateNotification = 0; ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) : @@ -226,7 +227,7 @@ static void BannedListChanged(ClientModel *clientmodel) QMetaObject::invokeMethod(clientmodel, "updateBanlist", Qt::QueuedConnection); } -static void BlockTipChanged(ClientModel *clientmodel, bool initialSync, const CBlockIndex *pIndex) +static void BlockTipChanged(ClientModel *clientmodel, bool initialSync, const CBlockIndex *pIndex, bool fHeader) { // lock free async UI updates in case we have a new block tip // during initial sync, only update the UI if the last update @@ -235,14 +236,17 @@ static void BlockTipChanged(ClientModel *clientmodel, bool initialSync, const CB if (initialSync) now = GetTimeMillis(); + int64_t& nLastUpdateNotification = fHeader ? nLastHeaderTipUpdateNotification : nLastBlockTipUpdateNotification; + // if we are in-sync, update the UI regardless of last update time - if (!initialSync || now - nLastBlockTipUpdateNotification > MODEL_UPDATE_DELAY) { + if (!initialSync || now - nLastUpdateNotification > MODEL_UPDATE_DELAY) { //pass a async signal to the UI thread QMetaObject::invokeMethod(clientmodel, "numBlocksChanged", Qt::QueuedConnection, Q_ARG(int, pIndex->nHeight), Q_ARG(QDateTime, QDateTime::fromTime_t(pIndex->GetBlockTime())), - Q_ARG(double, clientmodel->getVerificationProgress(pIndex))); - nLastBlockTipUpdateNotification = now; + Q_ARG(double, clientmodel->getVerificationProgress(pIndex)), + Q_ARG(bool, fHeader)); + nLastUpdateNotification = now; } } @@ -253,7 +257,8 @@ void ClientModel::subscribeToCoreSignals() uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this, _1)); uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this)); uiInterface.BannedListChanged.connect(boost::bind(BannedListChanged, this)); - uiInterface.NotifyBlockTip.connect(boost::bind(BlockTipChanged, this, _1, _2)); + uiInterface.NotifyBlockTip.connect(boost::bind(BlockTipChanged, this, _1, _2, false)); + uiInterface.NotifyHeaderTip.connect(boost::bind(BlockTipChanged, this, _1, _2, true)); } void ClientModel::unsubscribeFromCoreSignals() @@ -263,5 +268,6 @@ void ClientModel::unsubscribeFromCoreSignals() uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1)); uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this)); uiInterface.BannedListChanged.disconnect(boost::bind(BannedListChanged, this)); - uiInterface.NotifyBlockTip.disconnect(boost::bind(BlockTipChanged, this, _1, _2)); + uiInterface.NotifyBlockTip.disconnect(boost::bind(BlockTipChanged, this, _1, _2, false)); + uiInterface.NotifyHeaderTip.disconnect(boost::bind(BlockTipChanged, this, _1, _2, true)); } diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 109f95a2a7112..439680431963e 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -89,7 +89,7 @@ class ClientModel : public QObject Q_SIGNALS: void numConnectionsChanged(int count); - void numBlocksChanged(int count, const QDateTime& blockDate, double nVerificationProgress); + void numBlocksChanged(int count, const QDateTime& blockDate, double nVerificationProgress, bool header); void mempoolSizeChanged(long count, size_t mempoolSizeInBytes); void alertsChanged(const QString &warnings); void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut); diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index d8647d902a0e7..fd627eb4afc38 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -353,8 +353,8 @@ void RPCConsole::setClientModel(ClientModel *model) setNumConnections(model->getNumConnections()); connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int))); - setNumBlocks(model->getNumBlocks(), model->getLastBlockDate(), model->getVerificationProgress(NULL)); - connect(model, SIGNAL(numBlocksChanged(int,QDateTime,double)), this, SLOT(setNumBlocks(int,QDateTime,double))); + setNumBlocks(model->getNumBlocks(), model->getLastBlockDate(), model->getVerificationProgress(NULL), false); + connect(model, SIGNAL(numBlocksChanged(int,QDateTime,double,bool)), this, SLOT(setNumBlocks(int,QDateTime,double,bool))); updateTrafficStats(model->getTotalBytesRecv(), model->getTotalBytesSent()); connect(model, SIGNAL(bytesChanged(quint64,quint64)), this, SLOT(updateTrafficStats(quint64, quint64))); @@ -585,10 +585,12 @@ void RPCConsole::setNumConnections(int count) ui->numberOfConnections->setText(connections); } -void RPCConsole::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress) +void RPCConsole::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool headers) { - ui->numberOfBlocks->setText(QString::number(count)); - ui->lastBlockTime->setText(blockDate.toString()); + if (!headers) { + ui->numberOfBlocks->setText(QString::number(count)); + ui->lastBlockTime->setText(blockDate.toString()); + } } void RPCConsole::setMempoolSize(long numberOfTxs, size_t dynUsage) diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 2923587bc82c5..28affa954dca2 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -87,7 +87,7 @@ public Q_SLOTS: /** Set number of connections shown in the UI */ void setNumConnections(int count); /** Set number of blocks and last block date shown in the UI */ - void setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress); + void setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool headers); /** Set size (number of transactions and memory usage) of the mempool in the UI */ void setMempoolSize(long numberOfTxs, size_t dynUsage); /** Go forward or back in history */ diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 54ebd25833827..6d50be56ecba7 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -124,7 +124,7 @@ void SendCoinsDialog::setClientModel(ClientModel *clientModel) this->clientModel = clientModel; if (clientModel) { - connect(clientModel, SIGNAL(numBlocksChanged(int,QDateTime,double)), this, SLOT(updateSmartFeeLabel())); + connect(clientModel, SIGNAL(numBlocksChanged(int,QDateTime,double,bool)), this, SLOT(updateSmartFeeLabel())); } } diff --git a/src/ui_interface.h b/src/ui_interface.h index a27918c50766d..7ebfc17e5dd52 100644 --- a/src/ui_interface.h +++ b/src/ui_interface.h @@ -96,6 +96,9 @@ class CClientUIInterface /** New block has been accepted */ boost::signals2::signal NotifyBlockTip; + /** Best header has changed */ + boost::signals2::signal NotifyHeaderTip; + /** Banlist did change. */ boost::signals2::signal BannedListChanged; }; From ecb9741ec3067f67f595126869d0200c62064bbd Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Mon, 16 May 2016 17:11:24 -0700 Subject: [PATCH 0330/1802] Move GetAccountBalance from rpcwallet.cpp into CWallet::GetAccountBalance --- src/wallet/rpcwallet.cpp | 38 +++----------------------------------- src/wallet/wallet.cpp | 31 +++++++++++++++++++++++++++++++ src/wallet/wallet.h | 2 ++ 3 files changed, 36 insertions(+), 35 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 623037e76648b..8bd1279b7f5ab 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -673,38 +673,6 @@ UniValue getreceivedbyaccount(const UniValue& params, bool fHelp) } -CAmount GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth, const isminefilter& filter) -{ - CAmount nBalance = 0; - - // Tally wallet transactions - for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) - { - const CWalletTx& wtx = (*it).second; - if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0) - continue; - - CAmount nReceived, nSent, nFee; - wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee, filter); - - if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth) - nBalance += nReceived; - nBalance -= nSent + nFee; - } - - // Tally internal accounting entries - nBalance += walletdb.GetAccountCreditDebit(strAccount); - - return nBalance; -} - -CAmount GetAccountBalance(const string& strAccount, int nMinDepth, const isminefilter& filter) -{ - CWalletDB walletdb(pwalletMain->strWalletFile); - return GetAccountBalance(walletdb, strAccount, nMinDepth, filter); -} - - UniValue getbalance(const UniValue& params, bool fHelp) { if (!EnsureWalletIsAvailable(fHelp)) @@ -775,7 +743,7 @@ UniValue getbalance(const UniValue& params, bool fHelp) string strAccount = AccountFromValue(params[0]); - CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, filter); + CAmount nBalance = pwalletMain->GetAccountBalance(strAccount, nMinDepth, filter); return ValueFromAmount(nBalance); } @@ -923,7 +891,7 @@ UniValue sendfrom(const UniValue& params, bool fHelp) EnsureWalletIsUnlocked(); // Check funds - CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE); + CAmount nBalance = pwalletMain->GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE); if (nAmount > nBalance) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds"); @@ -1026,7 +994,7 @@ UniValue sendmany(const UniValue& params, bool fHelp) EnsureWalletIsUnlocked(); // Check funds - CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE); + CAmount nBalance = pwalletMain->GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE); if (totalAmount > nBalance) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds"); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 6b942e29d76c4..4809e3baa6c38 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2759,6 +2759,37 @@ set< set > CWallet::GetAddressGroupings() return ret; } +CAmount CWallet::GetAccountBalance(const std::string& strAccount, int nMinDepth, const isminefilter& filter) +{ + CWalletDB walletdb(strWalletFile); + return GetAccountBalance(walletdb, strAccount, nMinDepth, filter); +} + +CAmount CWallet::GetAccountBalance(CWalletDB& walletdb, const std::string& strAccount, int nMinDepth, const isminefilter& filter) +{ + CAmount nBalance = 0; + + // Tally wallet transactions + for (map::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + { + const CWalletTx& wtx = (*it).second; + if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0) + continue; + + CAmount nReceived, nSent, nFee; + wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee, filter); + + if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth) + nBalance += nReceived; + nBalance -= nSent + nFee; + } + + // Tally internal accounting entries + nBalance += walletdb.GetAccountCreditDebit(strAccount); + + return nBalance; +} + std::set CWallet::GetAccountAddresses(const std::string& strAccount) const { LOCK(cs_wallet); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index cc568c3749b7c..631f2b31ef6d0 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -776,6 +776,8 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface std::set< std::set > GetAddressGroupings(); std::map GetAddressBalances(); + CAmount GetAccountBalance(const std::string& strAccount, int nMinDepth, const isminefilter& filter); + CAmount GetAccountBalance(CWalletDB& walletdb, const std::string& strAccount, int nMinDepth, const isminefilter& filter); std::set GetAccountAddresses(const std::string& strAccount) const; isminetype IsMine(const CTxIn& txin) const; From 380498aba4f6aebe53a8241f163e3c7fe424b7e0 Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Mon, 16 May 2016 17:31:16 -0700 Subject: [PATCH 0331/1802] Move BackupWallet to CWallet::BackupWallet --- src/qt/walletmodel.cpp | 2 +- src/wallet/rpcwallet.cpp | 2 +- src/wallet/wallet.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ src/wallet/wallet.h | 2 ++ src/wallet/walletdb.cpp | 40 ---------------------------------------- src/wallet/walletdb.h | 1 - 6 files changed, 44 insertions(+), 43 deletions(-) diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index a0d0e70442196..3867310cd6857 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -447,7 +447,7 @@ bool WalletModel::changePassphrase(const SecureString &oldPass, const SecureStri bool WalletModel::backupWallet(const QString &filename) { - return BackupWallet(*wallet, filename.toLocal8Bit().data()); + return wallet->BackupWallet(filename.toLocal8Bit().data()); } // Handlers for core signals diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 8bd1279b7f5ab..f11f299141587 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -1804,7 +1804,7 @@ UniValue backupwallet(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); string strDest = params[0].get_str(); - if (!BackupWallet(*pwalletMain, strDest)) + if (!pwalletMain->BackupWallet(strDest)) throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!"); return NullUniValue; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 4809e3baa6c38..5d1a431190954 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3283,6 +3283,46 @@ bool CWallet::ParameterInteraction() return true; } +bool CWallet::BackupWallet(const std::string& strDest) +{ + if (!fFileBacked) + return false; + while (true) + { + { + LOCK(bitdb.cs_db); + if (!bitdb.mapFileUseCount.count(strWalletFile) || bitdb.mapFileUseCount[strWalletFile] == 0) + { + // Flush log data to the dat file + bitdb.CloseDb(strWalletFile); + bitdb.CheckpointLSN(strWalletFile); + bitdb.mapFileUseCount.erase(strWalletFile); + + // Copy wallet file + boost::filesystem::path pathSrc = GetDataDir() / strWalletFile; + boost::filesystem::path pathDest(strDest); + if (boost::filesystem::is_directory(pathDest)) + pathDest /= strWalletFile; + + try { +#if BOOST_VERSION >= 104000 + boost::filesystem::copy_file(pathSrc, pathDest, boost::filesystem::copy_option::overwrite_if_exists); +#else + boost::filesystem::copy_file(pathSrc, pathDest); +#endif + LogPrintf("copied %s to %s\n", strWalletFile, pathDest.string()); + return true; + } catch (const boost::filesystem::filesystem_error& e) { + LogPrintf("error copying %s to %s - %s\n", strWalletFile, pathDest.string(), e.what()); + return false; + } + } + } + MilliSleep(100); + } + return false; +} + CKeyPool::CKeyPool() { nTime = GetTime(); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 631f2b31ef6d0..b2180a5a26bb8 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -885,6 +885,8 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface /* Wallets parameter interaction */ static bool ParameterInteraction(); + + bool BackupWallet(const std::string& strDest); }; /** A key allocated from the key pool. */ diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 48579b2821e8e..b5037c9a65abf 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -903,46 +903,6 @@ void ThreadFlushWalletDB(const string& strFile) } } -bool BackupWallet(const CWallet& wallet, const string& strDest) -{ - if (!wallet.fFileBacked) - return false; - while (true) - { - { - LOCK(bitdb.cs_db); - if (!bitdb.mapFileUseCount.count(wallet.strWalletFile) || bitdb.mapFileUseCount[wallet.strWalletFile] == 0) - { - // Flush log data to the dat file - bitdb.CloseDb(wallet.strWalletFile); - bitdb.CheckpointLSN(wallet.strWalletFile); - bitdb.mapFileUseCount.erase(wallet.strWalletFile); - - // Copy wallet file - boost::filesystem::path pathSrc = GetDataDir() / wallet.strWalletFile; - boost::filesystem::path pathDest(strDest); - if (boost::filesystem::is_directory(pathDest)) - pathDest /= wallet.strWalletFile; - - try { -#if BOOST_VERSION >= 104000 - boost::filesystem::copy_file(pathSrc, pathDest, boost::filesystem::copy_option::overwrite_if_exists); -#else - boost::filesystem::copy_file(pathSrc, pathDest); -#endif - LogPrintf("copied %s to %s\n", wallet.strWalletFile, pathDest.string()); - return true; - } catch (const boost::filesystem::filesystem_error& e) { - LogPrintf("error copying %s to %s - %s\n", wallet.strWalletFile, pathDest.string(), e.what()); - return false; - } - } - } - MilliSleep(100); - } - return false; -} - // // Try to (very carefully!) recover wallet file if there is a problem. // diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 5345c0907e9cd..00c10ea70f03b 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -141,7 +141,6 @@ class CWalletDB : public CDB bool WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry); }; -bool BackupWallet(const CWallet& wallet, const std::string& strDest); void ThreadFlushWalletDB(const std::string& strFile); #endif // BITCOIN_WALLET_WALLETDB_H From 46b0c3b688dccf6ba9ac08cbd6d6981249a73b1a Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Mon, 16 May 2016 20:33:32 -0700 Subject: [PATCH 0332/1802] Acquire lock to check for genesis block. --- src/init.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index d19ca530b3831..fd1241d930319 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1371,10 +1371,18 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) vImportFiles.push_back(strFile); } threadGroup.create_thread(boost::bind(&ThreadImport, vImportFiles)); - if (chainActive.Tip() == NULL) { - LogPrintf("Waiting for genesis block to be imported...\n"); - while (!fRequestShutdown && chainActive.Tip() == NULL) + + // Wait for genesis block to be processed + bool fHaveGenesis = false; + while (!fHaveGenesis && !fRequestShutdown) { + { + LOCK(cs_main); + fHaveGenesis = (chainActive.Tip() != NULL); + } + + if (!fHaveGenesis) { MilliSleep(10); + } } // ********************************************************* Step 11: start node From 94fd1d8d53adceb80e5a41cc6438c7704aeac0f7 Mon Sep 17 00:00:00 2001 From: Warren Togami Date: Tue, 17 May 2016 16:43:23 +0900 Subject: [PATCH 0333/1802] Make Socks5() InterruptibleRecv() timeout/failures informative. Before: 2016-05-16 06:10:45 ERROR: Error reading proxy response After: 2016-05-16 06:10:45 Socks5() connect to k7s5d6jqig4ej4v4.onion:18333 failed: InterruptibleRecv() timeout or other failure --- src/netbase.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/netbase.cpp b/src/netbase.cpp index 5ab12c9a7c43e..d2a4188ffcb54 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -318,7 +318,8 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials char pchRet1[2]; if (!InterruptibleRecv(pchRet1, 2, SOCKS5_RECV_TIMEOUT, hSocket)) { CloseSocket(hSocket); - return error("Error reading proxy response"); + LogPrintf("Socks5() connect to %s:%d failed: InterruptibleRecv() timeout or other failure\n", strDest, port); + return false; } if (pchRet1[0] != 0x05) { CloseSocket(hSocket); From fad184550e1c507a897be59169f9c5dabce8d652 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 3 Apr 2016 20:36:27 +0200 Subject: [PATCH 0334/1802] [qa] test_framework: Use different rpc_auth_pair for each node --- qa/rpc-tests/test_framework/util.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index 6784177aaac57..d6bb32b18ca7c 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -150,17 +150,22 @@ def initialize_datadir(dirname, n): datadir = os.path.join(dirname, "node"+str(n)) if not os.path.isdir(datadir): os.makedirs(datadir) + rpc_u, rpc_p = rpc_auth_pair(n) with open(os.path.join(datadir, "bitcoin.conf"), 'w') as f: f.write("regtest=1\n") - f.write("rpcuser=rt\n") - f.write("rpcpassword=rt\n") + f.write("rpcuser=" + rpc_u + "\n") + f.write("rpcpassword=" + rpc_p + "\n") f.write("port="+str(p2p_port(n))+"\n") f.write("rpcport="+str(rpc_port(n))+"\n") f.write("listenonion=0\n") return datadir +def rpc_auth_pair(n): + return 'rpcuser💻' + str(n), 'rpcpass🔑' + str(n) + def rpc_url(i, rpchost=None): - return "http://rt:rt@%s:%d" % (rpchost or '127.0.0.1', rpc_port(i)) + rpc_u, rpc_p = rpc_auth_pair(i) + return "http://%s:%s@%s:%d" % (rpc_u, rpc_p, rpchost or '127.0.0.1', rpc_port(i)) def wait_for_bitcoind_start(process, url, i): ''' From 5ec0cde371149e5be6ca5e9803183021b10928f8 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Mon, 4 Jan 2016 13:43:17 -0500 Subject: [PATCH 0335/1802] Refactor logic for converting mempool entries to JSON --- src/rpc/blockchain.cpp | 90 ++++++++++++++++++++++++------------------ 1 file changed, 51 insertions(+), 39 deletions(-) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index cf3c73c4dfef6..fe628097a920a 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -183,6 +183,54 @@ UniValue getdifficulty(const UniValue& params, bool fHelp) return GetDifficulty(); } +std::string EntryDescriptionString() +{ + return " \"size\" : n, (numeric) transaction size in bytes\n" + " \"fee\" : n, (numeric) transaction fee in " + CURRENCY_UNIT + "\n" + " \"modifiedfee\" : n, (numeric) transaction fee with fee deltas used for mining priority\n" + " \"time\" : n, (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT\n" + " \"height\" : n, (numeric) block height when transaction entered pool\n" + " \"startingpriority\" : n, (numeric) priority when transaction entered pool\n" + " \"currentpriority\" : n, (numeric) transaction priority now\n" + " \"descendantcount\" : n, (numeric) number of in-mempool descendant transactions (including this one)\n" + " \"descendantsize\" : n, (numeric) size of in-mempool descendants (including this one)\n" + " \"descendantfees\" : n, (numeric) modified fees (see above) of in-mempool descendants (including this one)\n" + " \"depends\" : [ (array) unconfirmed transactions used as inputs for this transaction\n" + " \"transactionid\", (string) parent transaction id\n" + " ... ]\n"; +} + +void entryToJSON(UniValue &info, const CTxMemPoolEntry &e) +{ + AssertLockHeld(mempool.cs); + + info.push_back(Pair("size", (int)e.GetTxSize())); + info.push_back(Pair("fee", ValueFromAmount(e.GetFee()))); + info.push_back(Pair("modifiedfee", ValueFromAmount(e.GetModifiedFee()))); + info.push_back(Pair("time", e.GetTime())); + info.push_back(Pair("height", (int)e.GetHeight())); + info.push_back(Pair("startingpriority", e.GetPriority(e.GetHeight()))); + info.push_back(Pair("currentpriority", e.GetPriority(chainActive.Height()))); + info.push_back(Pair("descendantcount", e.GetCountWithDescendants())); + info.push_back(Pair("descendantsize", e.GetSizeWithDescendants())); + info.push_back(Pair("descendantfees", e.GetModFeesWithDescendants())); + const CTransaction& tx = e.GetTx(); + set setDepends; + BOOST_FOREACH(const CTxIn& txin, tx.vin) + { + if (mempool.exists(txin.prevout.hash)) + setDepends.insert(txin.prevout.hash.ToString()); + } + + UniValue depends(UniValue::VARR); + BOOST_FOREACH(const string& dep, setDepends) + { + depends.push_back(dep); + } + + info.push_back(Pair("depends", depends)); +} + UniValue mempoolToJSON(bool fVerbose = false) { if (fVerbose) @@ -193,31 +241,7 @@ UniValue mempoolToJSON(bool fVerbose = false) { const uint256& hash = e.GetTx().GetHash(); UniValue info(UniValue::VOBJ); - info.push_back(Pair("size", (int)e.GetTxSize())); - info.push_back(Pair("fee", ValueFromAmount(e.GetFee()))); - info.push_back(Pair("modifiedfee", ValueFromAmount(e.GetModifiedFee()))); - info.push_back(Pair("time", e.GetTime())); - info.push_back(Pair("height", (int)e.GetHeight())); - info.push_back(Pair("startingpriority", e.GetPriority(e.GetHeight()))); - info.push_back(Pair("currentpriority", e.GetPriority(chainActive.Height()))); - info.push_back(Pair("descendantcount", e.GetCountWithDescendants())); - info.push_back(Pair("descendantsize", e.GetSizeWithDescendants())); - info.push_back(Pair("descendantfees", e.GetModFeesWithDescendants())); - const CTransaction& tx = e.GetTx(); - set setDepends; - BOOST_FOREACH(const CTxIn& txin, tx.vin) - { - if (mempool.exists(txin.prevout.hash)) - setDepends.insert(txin.prevout.hash.ToString()); - } - - UniValue depends(UniValue::VARR); - BOOST_FOREACH(const string& dep, setDepends) - { - depends.push_back(dep); - } - - info.push_back(Pair("depends", depends)); + entryToJSON(info, e); o.push_back(Pair(hash.ToString(), info)); } return o; @@ -251,20 +275,8 @@ UniValue getrawmempool(const UniValue& params, bool fHelp) "\nResult: (for verbose = true):\n" "{ (json object)\n" " \"transactionid\" : { (json object)\n" - " \"size\" : n, (numeric) transaction size in bytes\n" - " \"fee\" : n, (numeric) transaction fee in " + CURRENCY_UNIT + "\n" - " \"modifiedfee\" : n, (numeric) transaction fee with fee deltas used for mining priority\n" - " \"time\" : n, (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT\n" - " \"height\" : n, (numeric) block height when transaction entered pool\n" - " \"startingpriority\" : n, (numeric) priority when transaction entered pool\n" - " \"currentpriority\" : n, (numeric) transaction priority now\n" - " \"descendantcount\" : n, (numeric) number of in-mempool descendant transactions (including this one)\n" - " \"descendantsize\" : n, (numeric) size of in-mempool descendants (including this one)\n" - " \"descendantfees\" : n, (numeric) modified fees (see above) of in-mempool descendants (including this one)\n" - " \"depends\" : [ (array) unconfirmed transactions used as inputs for this transaction\n" - " \"transactionid\", (string) parent transaction id\n" - " ... ]\n" - " }, ...\n" + + EntryDescriptionString() + + " }, ...\n" "}\n" "\nExamples\n" + HelpExampleCli("getrawmempool", "true") From 8f7b5dc4afb28e38ce0223339b8ce77aa0a47845 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Mon, 4 Jan 2016 13:58:59 -0500 Subject: [PATCH 0336/1802] Add getmempoolancestors RPC call --- src/rpc/blockchain.cpp | 65 ++++++++++++++++++++++++++++++++++++++++++ src/rpc/client.cpp | 1 + 2 files changed, 66 insertions(+) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index fe628097a920a..6c005068d86d2 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -292,6 +292,70 @@ UniValue getrawmempool(const UniValue& params, bool fHelp) return mempoolToJSON(fVerbose); } +UniValue getmempoolancestors(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 2) { + throw runtime_error( + "getmempoolancestors txid (verbose)\n" + "\nIf txid is in the mempool, returns all in-mempool ancestors.\n" + "\nArguments:\n" + "1. \"txid\" (string, required) The transaction id (must be in mempool)\n" + "2. verbose (boolean, optional, default=false) true for a json object, false for array of transaction ids\n" + "\nResult (for verbose=false):\n" + "[ (json array of string)\n" + " \"transactionid\" (string) The transaction id of an in-mempool ancestor transaction\n" + " ,...\n" + "]\n" + "\nResult (for verbose=true):\n" + "{ (json object)\n" + " \"transactionid\" : { (json object)\n" + + EntryDescriptionString() + + " }, ...\n" + "}\n" + "\nExamples\n" + + HelpExampleCli("getmempoolancestors", "\"mytxid\"") + + HelpExampleRpc("getmempoolancestors", "\"mytxid\"") + ); + } + + bool fVerbose = false; + if (params.size() > 1) + fVerbose = params[1].get_bool(); + + uint256 hash = ParseHashV(params[0], "parameter 1"); + + LOCK(mempool.cs); + + CTxMemPool::txiter it = mempool.mapTx.find(hash); + if (it == mempool.mapTx.end()) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not in mempool"); + } + + CTxMemPool::setEntries setAncestors; + uint64_t noLimit = std::numeric_limits::max(); + std::string dummy; + mempool.CalculateMemPoolAncestors(*it, setAncestors, noLimit, noLimit, noLimit, noLimit, dummy, false); + + if (!fVerbose) { + UniValue o(UniValue::VARR); + BOOST_FOREACH(CTxMemPool::txiter ancestorIt, setAncestors) { + o.push_back(ancestorIt->GetTx().GetHash().ToString()); + } + + return o; + } else { + UniValue o(UniValue::VOBJ); + BOOST_FOREACH(CTxMemPool::txiter ancestorIt, setAncestors) { + const CTxMemPoolEntry &e = *ancestorIt; + const uint256& hash = e.GetTx().GetHash(); + UniValue info(UniValue::VOBJ); + entryToJSON(info, e); + o.push_back(Pair(hash.ToString(), info)); + } + return o; + } +} + UniValue getblockhash(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 1) @@ -1016,6 +1080,7 @@ static const CRPCCommand commands[] = { "blockchain", "getblockheader", &getblockheader, true }, { "blockchain", "getchaintips", &getchaintips, true }, { "blockchain", "getdifficulty", &getdifficulty, true }, + { "blockchain", "getmempoolancestors", &getmempoolancestors, true }, { "blockchain", "getmempoolinfo", &getmempoolinfo, true }, { "blockchain", "getrawmempool", &getrawmempool, true }, { "blockchain", "gettxout", &gettxout, true }, diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index c89af6bfa7c52..3dfc27fff78af 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -102,6 +102,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "prioritisetransaction", 2 }, { "setban", 2 }, { "setban", 3 }, + { "getmempoolancestors", 1 }, }; class CRPCConvertTable From 0b1295b066b9369decb2e664e60b0129dbc30dfb Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 6 May 2016 20:41:28 +0200 Subject: [PATCH 0337/1802] Add SipHash-2-4 primitives to hash --- src/hash.cpp | 94 +++++++++++++++++++++++++++++++++++++++++ src/hash.h | 15 +++++++ src/test/hash_tests.cpp | 20 +++++++++ src/uint256.h | 13 ++++++ 4 files changed, 142 insertions(+) diff --git a/src/hash.cpp b/src/hash.cpp index 7f3cf1a1faa74..a518314a5376a 100644 --- a/src/hash.cpp +++ b/src/hash.cpp @@ -81,3 +81,97 @@ void BIP32Hash(const ChainCode &chainCode, unsigned int nChild, unsigned char he num[3] = (nChild >> 0) & 0xFF; CHMAC_SHA512(chainCode.begin(), chainCode.size()).Write(&header, 1).Write(data, 32).Write(num, 4).Finalize(output); } + +#define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b)))) + +#define SIPROUND do { \ + v0 += v1; v1 = ROTL(v1, 13); v1 ^= v0; \ + v0 = ROTL(v0, 32); \ + v2 += v3; v3 = ROTL(v3, 16); v3 ^= v2; \ + v0 += v3; v3 = ROTL(v3, 21); v3 ^= v0; \ + v2 += v1; v1 = ROTL(v1, 17); v1 ^= v2; \ + v2 = ROTL(v2, 32); \ +} while (0) + +CSipHasher::CSipHasher(uint64_t k0, uint64_t k1) +{ + v[0] = 0x736f6d6570736575ULL ^ k0; + v[1] = 0x646f72616e646f6dULL ^ k1; + v[2] = 0x6c7967656e657261ULL ^ k0; + v[3] = 0x7465646279746573ULL ^ k1; + count = 0; +} + +CSipHasher& CSipHasher::Write(uint64_t data) +{ + uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3]; + + v3 ^= data; + SIPROUND; + SIPROUND; + v0 ^= data; + + v[0] = v0; + v[1] = v1; + v[2] = v2; + v[3] = v3; + + count++; + return *this; +} + +uint64_t CSipHasher::Finalize() const +{ + uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3]; + + v3 ^= ((uint64_t)count) << 59; + SIPROUND; + SIPROUND; + v0 ^= ((uint64_t)count) << 59; + v2 ^= 0xFF; + SIPROUND; + SIPROUND; + SIPROUND; + SIPROUND; + return v0 ^ v1 ^ v2 ^ v3; +} + +uint64_t SipHashUint256(uint64_t k0, uint64_t k1, const uint256& val) +{ + /* Specialized implementation for efficiency */ + uint64_t d = val.GetUint64(0); + + uint64_t v0 = 0x736f6d6570736575ULL ^ k0; + uint64_t v1 = 0x646f72616e646f6dULL ^ k1; + uint64_t v2 = 0x6c7967656e657261ULL ^ k0; + uint64_t v3 = 0x7465646279746573ULL ^ k1 ^ d; + + SIPROUND; + SIPROUND; + v0 ^= d; + d = val.GetUint64(1); + v3 ^= d; + SIPROUND; + SIPROUND; + v0 ^= d; + d = val.GetUint64(2); + v3 ^= d; + SIPROUND; + SIPROUND; + v0 ^= d; + d = val.GetUint64(3); + v3 ^= d; + SIPROUND; + SIPROUND; + v0 ^= d; + v3 ^= ((uint64_t)4) << 59; + SIPROUND; + SIPROUND; + v0 ^= ((uint64_t)4) << 59; + v2 ^= 0xFF; + SIPROUND; + SIPROUND; + SIPROUND; + SIPROUND; + return v0 ^ v1 ^ v2 ^ v3; +} diff --git a/src/hash.h b/src/hash.h index 97955c8d5ad6d..600dabec56087 100644 --- a/src/hash.h +++ b/src/hash.h @@ -171,4 +171,19 @@ unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector void Serialize(Stream& s, int nType, int nVersion) const { From 382c871d28b95cc52309a128edd8dc23822bcd60 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 6 May 2016 20:47:12 +0200 Subject: [PATCH 0338/1802] Use SipHash-2-4 for CCoinsCache index This is ~1.7x slower than the Lookup3-of-Xor-with-salt construct we were using before, but it is a primitive designed for exactly this. --- src/coins.cpp | 6 ++++- src/coins.h | 14 ++++++----- src/uint256.cpp | 64 ------------------------------------------------- src/uint256.h | 5 ---- 4 files changed, 13 insertions(+), 76 deletions(-) diff --git a/src/coins.cpp b/src/coins.cpp index 1c329740b45f6..b7dd293d69564 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -56,7 +56,11 @@ void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; } bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return base->BatchWrite(mapCoins, hashBlock); } CCoinsViewCursor *CCoinsViewBacked::Cursor() const { return base->Cursor(); } -CCoinsKeyHasher::CCoinsKeyHasher() : salt(GetRandHash()) {} +SaltedTxidHasher::SaltedTxidHasher() +{ + GetRandBytes((unsigned char*)&k0, sizeof(k0)); + GetRandBytes((unsigned char*)&k1, sizeof(k1)); +} CCoinsViewCache::CCoinsViewCache(CCoinsView *baseIn) : CCoinsViewBacked(baseIn), hasModifier(false), cachedCoinsUsage(0) { } diff --git a/src/coins.h b/src/coins.h index d72f8854731eb..1dd908700b12b 100644 --- a/src/coins.h +++ b/src/coins.h @@ -8,6 +8,7 @@ #include "compressor.h" #include "core_memusage.h" +#include "hash.h" #include "memusage.h" #include "serialize.h" #include "uint256.h" @@ -264,21 +265,22 @@ class CCoins } }; -class CCoinsKeyHasher +class SaltedTxidHasher { private: - uint256 salt; + /** Salt */ + uint64_t k0, k1; public: - CCoinsKeyHasher(); + SaltedTxidHasher(); /** * This *must* return size_t. With Boost 1.46 on 32-bit systems the * unordered_map will behave unpredictably if the custom hasher returns a * uint64_t, resulting in failures when syncing the chain (#4634). */ - size_t operator()(const uint256& key) const { - return key.GetHash(salt); + size_t operator()(const uint256& txid) const { + return SipHashUint256(k0, k1, txid); } }; @@ -295,7 +297,7 @@ struct CCoinsCacheEntry CCoinsCacheEntry() : coins(), flags(0) {} }; -typedef boost::unordered_map CCoinsMap; +typedef boost::unordered_map CCoinsMap; /** Cursor for iterating over CoinsView state */ class CCoinsViewCursor diff --git a/src/uint256.cpp b/src/uint256.cpp index c58c88bf4a8f1..f22ddcd1effce 100644 --- a/src/uint256.cpp +++ b/src/uint256.cpp @@ -80,67 +80,3 @@ template std::string base_blob<256>::GetHex() const; template std::string base_blob<256>::ToString() const; template void base_blob<256>::SetHex(const char*); template void base_blob<256>::SetHex(const std::string&); - -static void inline HashMix(uint32_t& a, uint32_t& b, uint32_t& c) -{ - // Taken from lookup3, by Bob Jenkins. - a -= c; - a ^= ((c << 4) | (c >> 28)); - c += b; - b -= a; - b ^= ((a << 6) | (a >> 26)); - a += c; - c -= b; - c ^= ((b << 8) | (b >> 24)); - b += a; - a -= c; - a ^= ((c << 16) | (c >> 16)); - c += b; - b -= a; - b ^= ((a << 19) | (a >> 13)); - a += c; - c -= b; - c ^= ((b << 4) | (b >> 28)); - b += a; -} - -static void inline HashFinal(uint32_t& a, uint32_t& b, uint32_t& c) -{ - // Taken from lookup3, by Bob Jenkins. - c ^= b; - c -= ((b << 14) | (b >> 18)); - a ^= c; - a -= ((c << 11) | (c >> 21)); - b ^= a; - b -= ((a << 25) | (a >> 7)); - c ^= b; - c -= ((b << 16) | (b >> 16)); - a ^= c; - a -= ((c << 4) | (c >> 28)); - b ^= a; - b -= ((a << 14) | (a >> 18)); - c ^= b; - c -= ((b << 24) | (b >> 8)); -} - -uint64_t uint256::GetHash(const uint256& salt) const -{ - uint32_t a, b, c; - const uint32_t *pn = (const uint32_t*)data; - const uint32_t *salt_pn = (const uint32_t*)salt.data; - a = b = c = 0xdeadbeef + WIDTH; - - a += pn[0] ^ salt_pn[0]; - b += pn[1] ^ salt_pn[1]; - c += pn[2] ^ salt_pn[2]; - HashMix(a, b, c); - a += pn[3] ^ salt_pn[3]; - b += pn[4] ^ salt_pn[4]; - c += pn[5] ^ salt_pn[5]; - HashMix(a, b, c); - a += pn[6] ^ salt_pn[6]; - b += pn[7] ^ salt_pn[7]; - HashFinal(a, b, c); - - return ((((uint64_t)b) << 32) | c); -} diff --git a/src/uint256.h b/src/uint256.h index af1f3ab7d99e5..dd8432d74cab5 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -140,11 +140,6 @@ class uint256 : public base_blob<256> { { return ReadLE64(data); } - - /** A more secure, salted hash function. - * @note This hash is not stable between little and big endian. - */ - uint64_t GetHash(const uint256& salt) const; }; /* uint256 from const char *. From 8cc9cfe1605432be43d49e09094121bdb93caac8 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 6 May 2016 21:36:36 +0200 Subject: [PATCH 0339/1802] Switch CTxMempool::mapTx to use a hash index for txids --- src/txmempool.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/txmempool.h b/src/txmempool.h index bca8dd9791bda..3e1d387975b6f 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -17,6 +17,7 @@ #undef foreach #include "boost/multi_index_container.hpp" #include "boost/multi_index/ordered_index.hpp" +#include "boost/multi_index/hashed_index.hpp" class CAutoFile; class CBlockIndex; @@ -422,7 +423,7 @@ class CTxMemPool CTxMemPoolEntry, boost::multi_index::indexed_by< // sorted by txid - boost::multi_index::ordered_unique, + boost::multi_index::hashed_unique, // sorted by fee rate boost::multi_index::ordered_non_unique< boost::multi_index::tag, From a68ec21f7ed2978d8945a0f4cfd7e80bfa5fd917 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 6 May 2016 21:53:38 +0200 Subject: [PATCH 0340/1802] Use SipHash-2-4 for address relay selection --- src/main.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 09f82312a9b9e..a1c027bef38c5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4698,25 +4698,23 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, LOCK(cs_vNodes); // Use deterministic randomness to send to the same nodes for 24 hours // at a time so the addrKnowns of the chosen nodes prevent repeats - static uint256 hashSalt; - if (hashSalt.IsNull()) - hashSalt = GetRandHash(); + static uint64_t salt0 = 0, salt1 = 0; + while (salt0 == 0 && salt1 == 0) { + GetRandBytes((unsigned char*)&salt0, sizeof(salt0)); + GetRandBytes((unsigned char*)&salt1, sizeof(salt1)); + } uint64_t hashAddr = addr.GetHash(); - uint256 hashRand = ArithToUint256(UintToArith256(hashSalt) ^ (hashAddr<<32) ^ ((GetTime()+hashAddr)/(24*60*60))); - hashRand = Hash(BEGIN(hashRand), END(hashRand)); - multimap mapMix; + multimap mapMix; + const CSipHasher hasher = CSipHasher(salt0, salt1).Write(hashAddr << 32).Write((GetTime() + hashAddr) / (24*60*60)); BOOST_FOREACH(CNode* pnode, vNodes) { if (pnode->nVersion < CADDR_TIME_VERSION) continue; - unsigned int nPointer; - memcpy(&nPointer, &pnode, sizeof(nPointer)); - uint256 hashKey = ArithToUint256(UintToArith256(hashRand) ^ nPointer); - hashKey = Hash(BEGIN(hashKey), END(hashKey)); + uint64_t hashKey = CSipHasher(hasher).Write(pnode->id).Finalize(); mapMix.insert(make_pair(hashKey, pnode)); } int nRelayNodes = fReachable ? 2 : 1; // limited relaying of addresses outside our network(s) - for (multimap::iterator mi = mapMix.begin(); mi != mapMix.end() && nRelayNodes-- > 0; ++mi) + for (multimap::iterator mi = mapMix.begin(); mi != mapMix.end() && nRelayNodes-- > 0; ++mi) ((*mi).second)->PushAddress(addr); } } From 269a4402a8617a539a70b2c332e86f0fe292a7a6 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 2 May 2016 17:52:31 -0700 Subject: [PATCH 0341/1802] Add test for dbwrapper iterators with same-prefix keys. --- src/test/dbwrapper_tests.cpp | 86 ++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp index 8745d1439ca33..a0bdcf4afbc70 100644 --- a/src/test/dbwrapper_tests.cpp +++ b/src/test/dbwrapper_tests.cpp @@ -238,4 +238,90 @@ BOOST_AUTO_TEST_CASE(iterator_ordering) } } +struct StringContentsSerializer { + // Used to make two serialized objects the same while letting them have a different lengths + // This is a terrible idea + string str; + StringContentsSerializer() {} + StringContentsSerializer(const string& inp) : str(inp) {} + + StringContentsSerializer& operator+=(const string& s) { + str += s; + return *this; + } + StringContentsSerializer& operator+=(const StringContentsSerializer& s) { return *this += s.str; } + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + if (ser_action.ForRead()) { + str.clear(); + char c = 0; + while (true) { + try { + READWRITE(c); + str.push_back(c); + } catch (const std::ios_base::failure& e) { + break; + } + } + } else { + for (size_t i = 0; i < str.size(); i++) + READWRITE(str[i]); + } + } +}; + +BOOST_AUTO_TEST_CASE(iterator_string_ordering) +{ + char buf[10]; + + path ph = temp_directory_path() / unique_path(); + CDBWrapper dbw(ph, (1 << 20), true, false, false); + for (int x=0x00; x<10; ++x) { + for (int y = 0; y < 10; y++) { + sprintf(buf, "%d", x); + StringContentsSerializer key(buf); + for (int z = 0; z < y; z++) + key += key; + uint32_t value = x*x; + BOOST_CHECK(dbw.Write(key, value)); + } + } + + boost::scoped_ptr it(const_cast(&dbw)->NewIterator()); + for (int c=0; c<2; ++c) { + int seek_start; + if (c == 0) + seek_start = 0; + else + seek_start = 5; + sprintf(buf, "%d", seek_start); + StringContentsSerializer seek_key(buf); + it->Seek(seek_key); + for (int x=seek_start; x<10; ++x) { + for (int y = 0; y < 10; y++) { + sprintf(buf, "%d", x); + string exp_key(buf); + for (int z = 0; z < y; z++) + exp_key += exp_key; + StringContentsSerializer key; + uint32_t value; + BOOST_CHECK(it->Valid()); + if (!it->Valid()) // Avoid spurious errors about invalid iterator's key and value in case of failure + break; + BOOST_CHECK(it->GetKey(key)); + BOOST_CHECK(it->GetValue(value)); + BOOST_CHECK_EQUAL(key.str, exp_key); + BOOST_CHECK_EQUAL(value, x*x); + it->Next(); + } + } + BOOST_CHECK(!it->Valid()); + } +} + + + BOOST_AUTO_TEST_SUITE_END() From 6075bc4d67bcd5f95561dc6d53b4fdbaf2c63f4b Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 18 May 2016 11:10:34 +0200 Subject: [PATCH 0342/1802] doc: 32 and 64 bit packages are seperate --- doc/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/README.md b/doc/README.md index a5524889d2976..357334dfb23f5 100644 --- a/doc/README.md +++ b/doc/README.md @@ -13,8 +13,8 @@ The following are some helpful notes on how to run Bitcoin on your native platfo Unpack the files into a directory and run: -- bin/32/bitcoin-qt (GUI, 32-bit) or bin/32/bitcoind (headless, 32-bit) -- bin/64/bitcoin-qt (GUI, 64-bit) or bin/64/bitcoind (headless, 64-bit) +- `bin/bitcoin-qt` (GUI) or +- `bin/bitcoind` (headless) ### Windows From f4119c6c988ea24a5218aa6bc67e57e47e051547 Mon Sep 17 00:00:00 2001 From: EthanHeilman Date: Wed, 18 May 2016 12:04:07 -0400 Subject: [PATCH 0343/1802] Remove non-determinism which is breaking net_tests #8069 --- src/test/net_tests.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index 6debf6ac5e168..df1a4d2fb1918 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -17,6 +17,13 @@ class CAddrManSerializationMock : public CAddrMan { public: virtual void Serialize(CDataStream& s, int nType, int nVersionDummy) const = 0; + + //! Ensure that bucket placement is always the same for testing purposes. + void MakeDeterministic() + { + nKey.SetNull(); + seed_insecure_rand(true); + } }; class CAddrManUncorrupted : public CAddrManSerializationMock @@ -65,6 +72,7 @@ BOOST_FIXTURE_TEST_SUITE(net_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(caddrdb_read) { CAddrManUncorrupted addrmanUncorrupted; + addrmanUncorrupted.MakeDeterministic(); CService addr1 = CService("250.7.1.1", 8333); CService addr2 = CService("250.7.2.2", 9999); @@ -106,6 +114,7 @@ BOOST_AUTO_TEST_CASE(caddrdb_read) BOOST_AUTO_TEST_CASE(caddrdb_read_corrupted) { CAddrManCorrupted addrmanCorrupted; + addrmanCorrupted.MakeDeterministic(); // Test that the de-serialization of corrupted addrman throws an exception. CDataStream ssPeers1 = AddrmanToStream(addrmanCorrupted); From 4dc94d1036576fe988a066fdabc047350ccddda9 Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Tue, 15 Dec 2015 15:26:44 -0500 Subject: [PATCH 0344/1802] Refactor CreateNewBlock to be a method of the BlockAssembler class --- src/miner.cpp | 444 ++++++++++++++++++++++---------------- src/miner.h | 56 ++++- src/rpc/mining.cpp | 4 +- src/test/miner_tests.cpp | 28 +-- src/test/test_bitcoin.cpp | 2 +- 5 files changed, 328 insertions(+), 206 deletions(-) diff --git a/src/miner.cpp b/src/miner.cpp index eaf29a767b594..91e05f9ce48bf 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -71,231 +71,299 @@ int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParam return nNewTime - nOldTime; } -CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& scriptPubKeyIn) +BlockAssembler::BlockAssembler(const CChainParams& _chainparams) + : chainparams(_chainparams) { - // Create new block - std::unique_ptr pblocktemplate(new CBlockTemplate()); + // Largest block you're willing to create: + nBlockMaxSize = GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE); + // Limit to between 1K and MAX_BLOCK_SIZE-1K for sanity: + nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE-1000), nBlockMaxSize)); + + // Minimum block size you want to create; block will be filled with free transactions + // until there are no more or the block reaches this size: + nBlockMinSize = GetArg("-blockminsize", DEFAULT_BLOCK_MIN_SIZE); + nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize); +} + +void BlockAssembler::resetBlock() +{ + inBlock.clear(); + + // Reserve space for coinbase tx + nBlockSize = 1000; + nBlockSigOps = 100; + + // These counters do not include coinbase tx + nBlockTx = 0; + nFees = 0; + + lastFewTxs = 0; + blockFinished = false; +} + +CBlockTemplate* BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn) +{ + resetBlock(); + + pblocktemplate.reset(new CBlockTemplate()); + if(!pblocktemplate.get()) return NULL; - CBlock *pblock = &pblocktemplate->block; // pointer for convenience - - // Create coinbase tx - CMutableTransaction txNew; - txNew.vin.resize(1); - txNew.vin[0].prevout.SetNull(); - txNew.vout.resize(1); - txNew.vout[0].scriptPubKey = scriptPubKeyIn; + pblock = &pblocktemplate->block; // pointer for convenience // Add dummy coinbase tx as first transaction pblock->vtx.push_back(CTransaction()); pblocktemplate->vTxFees.push_back(-1); // updated at end pblocktemplate->vTxSigOps.push_back(-1); // updated at end - // Largest block you're willing to create: - unsigned int nBlockMaxSize = GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE); - // Limit to between 1K and MAX_BLOCK_SIZE-1K for sanity: - nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE-1000), nBlockMaxSize)); + LOCK2(cs_main, mempool.cs); + CBlockIndex* pindexPrev = chainActive.Tip(); + nHeight = pindexPrev->nHeight + 1; + + pblock->nVersion = ComputeBlockVersion(pindexPrev, chainparams.GetConsensus()); + // -regtest only: allow overriding block.nVersion with + // -blockversion=N to test forking scenarios + if (chainparams.MineBlocksOnDemand()) + pblock->nVersion = GetArg("-blockversion", pblock->nVersion); + + pblock->nTime = GetAdjustedTime(); + const int64_t nMedianTimePast = pindexPrev->GetMedianTimePast(); + + nLockTimeCutoff = (STANDARD_LOCKTIME_VERIFY_FLAGS & LOCKTIME_MEDIAN_TIME_PAST) + ? nMedianTimePast + : pblock->GetBlockTime(); + + addPriorityTxs(); + addScoreTxs(); + + nLastBlockTx = nBlockTx; + nLastBlockSize = nBlockSize; + LogPrintf("CreateNewBlock(): total size %u txs: %u fees: %ld sigops %d\n", nBlockSize, nBlockTx, nFees, nBlockSigOps); + + // Create coinbase transaction. + CMutableTransaction coinbaseTx; + coinbaseTx.vin.resize(1); + coinbaseTx.vin[0].prevout.SetNull(); + coinbaseTx.vout.resize(1); + coinbaseTx.vout[0].scriptPubKey = scriptPubKeyIn; + coinbaseTx.vout[0].nValue = nFees + GetBlockSubsidy(nHeight, chainparams.GetConsensus()); + coinbaseTx.vin[0].scriptSig = CScript() << nHeight << OP_0; + pblock->vtx[0] = coinbaseTx; + pblocktemplate->vTxFees[0] = -nFees; + + // Fill in header + pblock->hashPrevBlock = pindexPrev->GetBlockHash(); + UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev); + pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, chainparams.GetConsensus()); + pblock->nNonce = 0; + pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]); + + CValidationState state; + if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) { + throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, FormatStateMessage(state))); + } - // How much of the block should be dedicated to high-priority transactions, - // included regardless of the fees they pay - unsigned int nBlockPrioritySize = GetArg("-blockprioritysize", DEFAULT_BLOCK_PRIORITY_SIZE); - nBlockPrioritySize = std::min(nBlockMaxSize, nBlockPrioritySize); + return pblocktemplate.release(); +} - // Minimum block size you want to create; block will be filled with free transactions - // until there are no more or the block reaches this size: - unsigned int nBlockMinSize = GetArg("-blockminsize", DEFAULT_BLOCK_MIN_SIZE); - nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize); +bool BlockAssembler::isStillDependent(CTxMemPool::txiter iter) +{ + BOOST_FOREACH(CTxMemPool::txiter parent, mempool.GetMemPoolParents(iter)) + { + if (!inBlock.count(parent)) { + return true; + } + } + return false; +} - // Collect memory pool transactions into the block - CTxMemPool::setEntries inBlock; - CTxMemPool::setEntries waitSet; - // This vector will be sorted into a priority queue: - vector vecPriority; - TxCoinAgePriorityCompare pricomparer; - std::map waitPriMap; - typedef std::map::iterator waitPriIter; - double actualPriority = -1; - std::priority_queue, ScoreCompare> clearedTxs; +bool BlockAssembler::TestForBlock(CTxMemPool::txiter iter) +{ + if (nBlockSize + iter->GetTxSize() >= nBlockMaxSize) { + // If the block is so close to full that no more txs will fit + // or if we've tried more than 50 times to fill remaining space + // then flag that the block is finished + if (nBlockSize > nBlockMaxSize - 100 || lastFewTxs > 50) { + blockFinished = true; + return false; + } + // Once we're within 1000 bytes of a full block, only look at 50 more txs + // to try to fill the remaining space. + if (nBlockSize > nBlockMaxSize - 1000) { + lastFewTxs++; + } + return false; + } + + if (nBlockSigOps + iter->GetSigOpCount() >= MAX_BLOCK_SIGOPS) { + // If the block has room for no more sig ops then + // flag that the block is finished + if (nBlockSigOps > MAX_BLOCK_SIGOPS - 2) { + blockFinished = true; + return false; + } + // Otherwise attempt to find another tx with fewer sigops + // to put in the block. + return false; + } + + // Must check that lock times are still valid + // This can be removed once MTP is always enforced + // as long as reorgs keep the mempool consistent. + if (!IsFinalTx(iter->GetTx(), nHeight, nLockTimeCutoff)) + return false; + + return true; +} + +void BlockAssembler::AddToBlock(CTxMemPool::txiter iter) +{ + pblock->vtx.push_back(iter->GetTx()); + pblocktemplate->vTxFees.push_back(iter->GetFee()); + pblocktemplate->vTxSigOps.push_back(iter->GetSigOpCount()); + nBlockSize += iter->GetTxSize(); + ++nBlockTx; + nBlockSigOps += iter->GetSigOpCount(); + nFees += iter->GetFee(); + inBlock.insert(iter); + bool fPrintPriority = GetBoolArg("-printpriority", DEFAULT_PRINTPRIORITY); - uint64_t nBlockSize = 1000; - uint64_t nBlockTx = 0; - unsigned int nBlockSigOps = 100; - int lastFewTxs = 0; - CAmount nFees = 0; + if (fPrintPriority) { + double dPriority = iter->GetPriority(nHeight); + CAmount dummy; + mempool.ApplyDeltas(iter->GetTx().GetHash(), dPriority, dummy); + LogPrintf("priority %.1f fee %s txid %s\n", + dPriority, + CFeeRate(iter->GetModifiedFee(), iter->GetTxSize()).ToString(), + iter->GetTx().GetHash().ToString()); + } +} +void BlockAssembler::addScoreTxs() +{ + std::priority_queue, ScoreCompare> clearedTxs; + CTxMemPool::setEntries waitSet; + CTxMemPool::indexed_transaction_set::index::type::iterator mi = mempool.mapTx.get().begin(); + CTxMemPool::txiter iter; + while (!blockFinished && (mi != mempool.mapTx.get().end() || !clearedTxs.empty())) { - LOCK2(cs_main, mempool.cs); - CBlockIndex* pindexPrev = chainActive.Tip(); - const int nHeight = pindexPrev->nHeight + 1; - pblock->nTime = GetAdjustedTime(); - const int64_t nMedianTimePast = pindexPrev->GetMedianTimePast(); - - pblock->nVersion = ComputeBlockVersion(pindexPrev, chainparams.GetConsensus()); - // -regtest only: allow overriding block.nVersion with - // -blockversion=N to test forking scenarios - if (chainparams.MineBlocksOnDemand()) - pblock->nVersion = GetArg("-blockversion", pblock->nVersion); - - int64_t nLockTimeCutoff = (STANDARD_LOCKTIME_VERIFY_FLAGS & LOCKTIME_MEDIAN_TIME_PAST) - ? nMedianTimePast - : pblock->GetBlockTime(); - - bool fPriorityBlock = nBlockPrioritySize > 0; - if (fPriorityBlock) { - vecPriority.reserve(mempool.mapTx.size()); - for (CTxMemPool::indexed_transaction_set::iterator mi = mempool.mapTx.begin(); - mi != mempool.mapTx.end(); ++mi) - { - double dPriority = mi->GetPriority(nHeight); - CAmount dummy; - mempool.ApplyDeltas(mi->GetTx().GetHash(), dPriority, dummy); - vecPriority.push_back(TxCoinAgePriority(dPriority, mi)); - } - std::make_heap(vecPriority.begin(), vecPriority.end(), pricomparer); + // If no txs that were previously postponed are available to try + // again, then try the next highest score tx + if (clearedTxs.empty()) { + iter = mempool.mapTx.project<0>(mi); + mi++; + } + // If a previously postponed tx is available to try again, then it + // has higher score than all untried so far txs + else { + iter = clearedTxs.top(); + clearedTxs.pop(); } - CTxMemPool::indexed_transaction_set::index::type::iterator mi = mempool.mapTx.get().begin(); - CTxMemPool::txiter iter; - - while (mi != mempool.mapTx.get().end() || !clearedTxs.empty()) - { - bool priorityTx = false; - if (fPriorityBlock && !vecPriority.empty()) { // add a tx from priority queue to fill the blockprioritysize - priorityTx = true; - iter = vecPriority.front().second; - actualPriority = vecPriority.front().first; - std::pop_heap(vecPriority.begin(), vecPriority.end(), pricomparer); - vecPriority.pop_back(); - } - else if (clearedTxs.empty()) { // add tx with next highest score - iter = mempool.mapTx.project<0>(mi); - mi++; - } - else { // try to add a previously postponed child tx - iter = clearedTxs.top(); - clearedTxs.pop(); - } + // If tx is dependent on other mempool txs which haven't yet been included + // then put it in the waitSet + if (isStillDependent(iter)) { + waitSet.insert(iter); + continue; + } - if (inBlock.count(iter)) - continue; // could have been added to the priorityBlock + // If the fee rate is below the min fee rate for mining, then we're done + // adding txs based on score (fee rate) + if (iter->GetModifiedFee() < ::minRelayTxFee.GetFee(iter->GetTxSize()) && nBlockSize >= nBlockMinSize) { + return; + } - const CTransaction& tx = iter->GetTx(); + // If this tx fits in the block add it, otherwise keep looping + if (TestForBlock(iter)) { + AddToBlock(iter); - bool fOrphan = false; - BOOST_FOREACH(CTxMemPool::txiter parent, mempool.GetMemPoolParents(iter)) + // This tx was successfully added, so + // add transactions that depend on this one to the priority queue to try again + BOOST_FOREACH(CTxMemPool::txiter child, mempool.GetMemPoolChildren(iter)) { - if (!inBlock.count(parent)) { - fOrphan = true; - break; + if (waitSet.count(child)) { + clearedTxs.push(child); + waitSet.erase(child); } } - if (fOrphan) { - if (priorityTx) - waitPriMap.insert(std::make_pair(iter,actualPriority)); - else - waitSet.insert(iter); - continue; - } + } + } +} - unsigned int nTxSize = iter->GetTxSize(); - if (fPriorityBlock && - (nBlockSize + nTxSize >= nBlockPrioritySize || !AllowFree(actualPriority))) { - fPriorityBlock = false; - waitPriMap.clear(); - } - if (!priorityTx && - (iter->GetModifiedFee() < ::minRelayTxFee.GetFee(nTxSize) && nBlockSize >= nBlockMinSize)) { - break; - } - if (nBlockSize + nTxSize >= nBlockMaxSize) { - if (nBlockSize > nBlockMaxSize - 100 || lastFewTxs > 50) { - break; - } - // Once we're within 1000 bytes of a full block, only look at 50 more txs - // to try to fill the remaining space. - if (nBlockSize > nBlockMaxSize - 1000) { - lastFewTxs++; - } - continue; - } +void BlockAssembler::addPriorityTxs() +{ + // How much of the block should be dedicated to high-priority transactions, + // included regardless of the fees they pay + unsigned int nBlockPrioritySize = GetArg("-blockprioritysize", DEFAULT_BLOCK_PRIORITY_SIZE); + nBlockPrioritySize = std::min(nBlockMaxSize, nBlockPrioritySize); - if (!IsFinalTx(tx, nHeight, nLockTimeCutoff)) - continue; + if (nBlockPrioritySize == 0) { + return; + } - unsigned int nTxSigOps = iter->GetSigOpCount(); - if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS) { - if (nBlockSigOps > MAX_BLOCK_SIGOPS - 2) { - break; - } - continue; - } + // This vector will be sorted into a priority queue: + vector vecPriority; + TxCoinAgePriorityCompare pricomparer; + std::map waitPriMap; + typedef std::map::iterator waitPriIter; + double actualPriority = -1; - CAmount nTxFees = iter->GetFee(); - // Added - pblock->vtx.push_back(tx); - pblocktemplate->vTxFees.push_back(nTxFees); - pblocktemplate->vTxSigOps.push_back(nTxSigOps); - nBlockSize += nTxSize; - ++nBlockTx; - nBlockSigOps += nTxSigOps; - nFees += nTxFees; - - if (fPrintPriority) - { - double dPriority = iter->GetPriority(nHeight); - CAmount dummy; - mempool.ApplyDeltas(tx.GetHash(), dPriority, dummy); - LogPrintf("priority %.1f fee %s txid %s\n", - dPriority , CFeeRate(iter->GetModifiedFee(), nTxSize).ToString(), tx.GetHash().ToString()); - } + vecPriority.reserve(mempool.mapTx.size()); + for (CTxMemPool::indexed_transaction_set::iterator mi = mempool.mapTx.begin(); + mi != mempool.mapTx.end(); ++mi) + { + double dPriority = mi->GetPriority(nHeight); + CAmount dummy; + mempool.ApplyDeltas(mi->GetTx().GetHash(), dPriority, dummy); + vecPriority.push_back(TxCoinAgePriority(dPriority, mi)); + } + std::make_heap(vecPriority.begin(), vecPriority.end(), pricomparer); + + CTxMemPool::txiter iter; + while (!vecPriority.empty() && !blockFinished) { // add a tx from priority queue to fill the blockprioritysize + iter = vecPriority.front().second; + actualPriority = vecPriority.front().first; + std::pop_heap(vecPriority.begin(), vecPriority.end(), pricomparer); + vecPriority.pop_back(); + + // If tx already in block, skip + if (inBlock.count(iter)) { + assert(false); // shouldn't happen for priority txs + continue; + } + + // If tx is dependent on other mempool txs which haven't yet been included + // then put it in the waitSet + if (isStillDependent(iter)) { + waitPriMap.insert(std::make_pair(iter, actualPriority)); + continue; + } - inBlock.insert(iter); + // If this tx fits in the block add it, otherwise keep looping + if (TestForBlock(iter)) { + AddToBlock(iter); - // Add transactions that depend on this one to the priority queue + // If now that this txs is added we've surpassed our desired priority size + // or have dropped below the AllowFreeThreshold, then we're done adding priority txs + if (nBlockSize + iter->GetTxSize() >= nBlockPrioritySize || !AllowFree(actualPriority)) { + return; + } + + // This tx was successfully added, so + // add transactions that depend on this one to the priority queue to try again BOOST_FOREACH(CTxMemPool::txiter child, mempool.GetMemPoolChildren(iter)) { - if (fPriorityBlock) { - waitPriIter wpiter = waitPriMap.find(child); - if (wpiter != waitPriMap.end()) { - vecPriority.push_back(TxCoinAgePriority(wpiter->second,child)); - std::push_heap(vecPriority.begin(), vecPriority.end(), pricomparer); - waitPriMap.erase(wpiter); - } - } - else { - if (waitSet.count(child)) { - clearedTxs.push(child); - waitSet.erase(child); - } + waitPriIter wpiter = waitPriMap.find(child); + if (wpiter != waitPriMap.end()) { + vecPriority.push_back(TxCoinAgePriority(wpiter->second,child)); + std::push_heap(vecPriority.begin(), vecPriority.end(), pricomparer); + waitPriMap.erase(wpiter); } } } - nLastBlockTx = nBlockTx; - nLastBlockSize = nBlockSize; - LogPrintf("CreateNewBlock(): total size %u txs: %u fees: %ld sigops %d\n", nBlockSize, nBlockTx, nFees, nBlockSigOps); - - // Compute final coinbase transaction. - txNew.vout[0].nValue = nFees + GetBlockSubsidy(nHeight, chainparams.GetConsensus()); - txNew.vin[0].scriptSig = CScript() << nHeight << OP_0; - pblock->vtx[0] = txNew; - pblocktemplate->vTxFees[0] = -nFees; - - // Fill in header - pblock->hashPrevBlock = pindexPrev->GetBlockHash(); - UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev); - pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, chainparams.GetConsensus()); - pblock->nNonce = 0; - pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]); - - CValidationState state; - if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) { - throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, FormatStateMessage(state))); - } } - - return pblocktemplate.release(); } void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned int& nExtraNonce) diff --git a/src/miner.h b/src/miner.h index cd0f1366253ab..74f19693c4b29 100644 --- a/src/miner.h +++ b/src/miner.h @@ -7,14 +7,17 @@ #define BITCOIN_MINER_H #include "primitives/block.h" +#include "txmempool.h" #include +#include class CBlockIndex; class CChainParams; class CReserveKey; class CScript; class CWallet; + namespace Consensus { struct Params; }; static const bool DEFAULT_PRINTPRIORITY = false; @@ -27,7 +30,58 @@ struct CBlockTemplate }; /** Generate a new block, without valid proof-of-work */ -CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& scriptPubKeyIn); +class BlockAssembler +{ +private: + // The constructed block template + std::unique_ptr pblocktemplate; + // A convenience pointer that always refers to the CBlock in pblocktemplate + CBlock* pblock; + + // Configuration parameters for the block size + unsigned int nBlockMaxSize, nBlockMinSize; + + // Information on the current status of the block + uint64_t nBlockSize; + uint64_t nBlockTx; + unsigned int nBlockSigOps; + CAmount nFees; + CTxMemPool::setEntries inBlock; + + // Chain context for the block + int nHeight; + int64_t nLockTimeCutoff; + const CChainParams& chainparams; + + // Variables used for addScoreTxs and addPriorityTxs + int lastFewTxs; + bool blockFinished; + +public: + BlockAssembler(const CChainParams& chainparams); + /** Construct a new block template with coinbase to scriptPubKeyIn */ + CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn); + +private: + // utility functions + /** Clear the block's state and prepare for assembling a new block */ + void resetBlock(); + /** Add a tx to the block */ + void AddToBlock(CTxMemPool::txiter iter); + + // Methods for how to add transactions to a block. + /** Add transactions based on modified feerate */ + void addScoreTxs(); + /** Add transactions based on tx "priority" */ + void addPriorityTxs(); + + // helper function for addScoreTxs and addPriorityTxs + /** Test if tx will still "fit" in the block */ + bool TestForBlock(CTxMemPool::txiter iter); + /** Test if tx still has unconfirmed parents not yet in block */ + bool isStillDependent(CTxMemPool::txiter iter); +}; + /** Modify the extranonce in a block */ void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned int& nExtraNonce); int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 9a7d9d53a07fc..bd90cca1cc189 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -111,7 +111,7 @@ UniValue generateBlocks(boost::shared_ptr coinbaseScript, int nG UniValue blockHashes(UniValue::VARR); while (nHeight < nHeightEnd) { - std::unique_ptr pblocktemplate(CreateNewBlock(Params(), coinbaseScript->reserveScript)); + std::unique_ptr pblocktemplate(BlockAssembler(Params()).CreateNewBlock(coinbaseScript->reserveScript)); if (!pblocktemplate.get()) throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block"); CBlock *pblock = &pblocktemplate->block; @@ -493,7 +493,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) pblocktemplate = NULL; } CScript scriptDummy = CScript() << OP_TRUE; - pblocktemplate = CreateNewBlock(Params(), scriptDummy); + pblocktemplate = BlockAssembler(Params()).CreateNewBlock(scriptDummy); if (!pblocktemplate) throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory"); diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 469862518c58c..329b488c0ab9d 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -89,7 +89,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) fCheckpointsEnabled = false; // Simple block creation, nothing special yet: - BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); + BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey)); // We can't make transactions until we have inputs // Therefore, load 100 blocks :) @@ -121,7 +121,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) delete pblocktemplate; // Just to make sure we can still make simple blocks - BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); + BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey)); delete pblocktemplate; const CAmount BLOCKSUBSIDY = 50*COIN; @@ -146,7 +146,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx)); tx.vin[0].prevout.hash = hash; } - BOOST_CHECK_THROW(CreateNewBlock(chainparams, scriptPubKey), std::runtime_error); + BOOST_CHECK_THROW(BlockAssembler(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error); mempool.clear(); tx.vin[0].prevout.hash = txFirst[0]->GetHash(); @@ -160,7 +160,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).SigOps(20).FromTx(tx)); tx.vin[0].prevout.hash = hash; } - BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); + BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey)); delete pblocktemplate; mempool.clear(); @@ -181,14 +181,14 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx)); tx.vin[0].prevout.hash = hash; } - BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); + BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey)); delete pblocktemplate; mempool.clear(); // orphan in mempool, template creation fails hash = tx.GetHash(); mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).FromTx(tx)); - BOOST_CHECK_THROW(CreateNewBlock(chainparams, scriptPubKey), std::runtime_error); + BOOST_CHECK_THROW(BlockAssembler(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error); mempool.clear(); // child with higher priority than parent @@ -205,7 +205,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].nValue = tx.vout[0].nValue+BLOCKSUBSIDY-HIGHERFEE; //First txn output + fresh coinbase - new txn fee hash = tx.GetHash(); mempool.addUnchecked(hash, entry.Fee(HIGHERFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); - BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); + BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey)); delete pblocktemplate; mempool.clear(); @@ -217,7 +217,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) hash = tx.GetHash(); // give it a fee so it'll get mined mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); - BOOST_CHECK_THROW(CreateNewBlock(chainparams, scriptPubKey), std::runtime_error); + BOOST_CHECK_THROW(BlockAssembler(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error); mempool.clear(); // invalid (pre-p2sh) txn in mempool, template creation fails @@ -234,7 +234,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].nValue -= LOWFEE; hash = tx.GetHash(); mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); - BOOST_CHECK_THROW(CreateNewBlock(chainparams, scriptPubKey), std::runtime_error); + BOOST_CHECK_THROW(BlockAssembler(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error); mempool.clear(); // double spend txn pair in mempool, template creation fails @@ -247,7 +247,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].scriptPubKey = CScript() << OP_2; hash = tx.GetHash(); mempool.addUnchecked(hash, entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); - BOOST_CHECK_THROW(CreateNewBlock(chainparams, scriptPubKey), std::runtime_error); + BOOST_CHECK_THROW(BlockAssembler(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error); mempool.clear(); // subsidy changing @@ -263,7 +263,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) next->BuildSkip(); chainActive.SetTip(next); } - BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); + BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey)); delete pblocktemplate; // Extend to a 210000-long block chain. while (chainActive.Tip()->nHeight < 210000) { @@ -276,7 +276,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) next->BuildSkip(); chainActive.SetTip(next); } - BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); + BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey)); delete pblocktemplate; // Delete the dummy blocks again. while (chainActive.Tip()->nHeight > nHeight) { @@ -363,7 +363,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | 1; BOOST_CHECK(!TestSequenceLocks(tx, flags)); // Sequence locks fail - BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); + BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey)); // None of the of the absolute height/time locked tx should have made // it into the template because we still check IsFinalTx in CreateNewBlock, @@ -377,7 +377,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) chainActive.Tip()->nHeight++; SetMockTime(chainActive.Tip()->GetMedianTimePast() + 1); - BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); + BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey)); BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 5); delete pblocktemplate; diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index 9bcb07626ad6d..c68320ba8b8e6 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -98,7 +98,7 @@ CBlock TestChain100Setup::CreateAndProcessBlock(const std::vector& txns, const CScript& scriptPubKey) { const CChainParams& chainparams = Params(); - CBlockTemplate *pblocktemplate = CreateNewBlock(chainparams, scriptPubKey); + CBlockTemplate *pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey); CBlock& block = pblocktemplate->block; // Replace mempool-selected txns with just coinbase plus passed-in txns: From 2a8b3589b5a6c0863012329ddb40e7d901decf0e Mon Sep 17 00:00:00 2001 From: Ethan Heilman Date: Wed, 18 May 2016 20:14:26 -0400 Subject: [PATCH 0345/1802] Fix typo adddrman to addrman as requested in #8070 --- src/test/net_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index df1a4d2fb1918..b38d61f330354 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -128,7 +128,7 @@ BOOST_AUTO_TEST_CASE(caddrdb_read_corrupted) } catch (const std::exception& e) { exceptionThrown = true; } - // Even through de-serialization failed adddrman is not left in a clean state. + // Even through de-serialization failed addrman is not left in a clean state. BOOST_CHECK(addrman1.size() == 1); BOOST_CHECK(exceptionThrown); From bf9266e017b286c36e08fd09b91d9e39f14b2cf3 Mon Sep 17 00:00:00 2001 From: Warren Togami Date: Thu, 19 May 2016 14:19:08 +0900 Subject: [PATCH 0346/1802] Use Socks5ErrorString() to decode error responses from socks proxy. --- src/netbase.cpp | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/netbase.cpp b/src/netbase.cpp index d2a4188ffcb54..572ae70871d40 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -291,6 +291,21 @@ struct ProxyCredentials std::string password; }; +std::string Socks5ErrorString(int err) +{ + switch(err) { + case 0x01: return "general failure"; + case 0x02: return "connection not allowed"; + case 0x03: return "network unreachable"; + case 0x04: return "host unreachable"; + case 0x05: return "connection refused"; + case 0x06: return "TTL expired"; + case 0x07: return "protocol error"; + case 0x08: return "address type not supported"; + default: return "unknown"; + } +} + /** Connect using SOCKS5 (as described in RFC1928) */ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials *auth, SOCKET& hSocket) { @@ -382,18 +397,7 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials if (pchRet2[1] != 0x00) { // Failures to connect to a peer that are not proxy errors CloseSocket(hSocket); - switch (pchRet2[1]) - { - case 0x01: LogPrintf("Socks5() connect to %s:%d failed: general failure\n", strDest, port); break; - case 0x02: LogPrintf("Socks5() connect to %s:%d failed: connection not allowed\n", strDest, port); break; - case 0x03: LogPrintf("Socks5() connect to %s:%d failed: network unreachable\n", strDest, port); break; - case 0x04: LogPrintf("Socks5() connect to %s:%d failed: host unreachable\n", strDest, port); break; - case 0x05: LogPrintf("Socks5() connect to %s:%d failed: connection refused\n", strDest, port); break; - case 0x06: LogPrintf("Socks5() connect to %s:%d failed: TTL expired\n", strDest, port); break; - case 0x07: LogPrintf("Socks5() connect to %s:%d failed: protocol error\n", strDest, port); break; - case 0x08: LogPrintf("Socks5() connect to %s:%d failed: address type not supported\n", strDest, port); break; - default: LogPrintf("Socks5() connect to %s:%d failed: unknown\n", strDest, port); - } + LogPrintf("Socks5() connect to %s:%d failed: %s\n", strDest, port, Socks5ErrorString(pchRet2[1])); return false; } if (pchRet2[2] != 0x00) { From 401ae654b247d80e29e76ebd094e9e37409941bd Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 17 May 2016 17:54:41 -0400 Subject: [PATCH 0347/1802] travis: 'make check' in parallel and verbose - 'make check' in parallel, since the log will take care of clean output - 'make check' verbose, so that test failure causes aren't hidden --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index fd70d3ab52d7c..bc2c7faf7ee57 100644 --- a/.travis.yml +++ b/.travis.yml @@ -78,7 +78,7 @@ script: - ./configure --cache-file=../config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false) - make $MAKEJOBS $GOAL || ( echo "Build failure. Verbose build follows." && make $GOAL V=1 ; false ) - export LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/depends/$HOST/lib - - if [ "$RUN_TESTS" = "true" ]; then make check; fi + - if [ "$RUN_TESTS" = "true" ]; then make $MAKEJOBS check VERBOSE=1; fi - if [ "$RUN_TESTS" = "true" ]; then qa/pull-tester/rpc-tests.py --coverage; fi after_script: - echo $TRAVIS_COMMIT_RANGE From 02ce2a3ca773e2d10ff37ecf50d15c71113f3335 Mon Sep 17 00:00:00 2001 From: Pavel Vasin Date: Mon, 3 Aug 2015 03:03:14 +0300 Subject: [PATCH 0348/1802] qt: askpassphrasedialog: Clear pass fields on accept This is usability improvement in a case if user gets re-asked passphrase. (e.g. made a typo) --- src/qt/askpassphrasedialog.cpp | 21 +++++++++++++++++---- src/qt/askpassphrasedialog.h | 1 + 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp index 415bffb991457..e8aa79679c04a 100644 --- a/src/qt/askpassphrasedialog.cpp +++ b/src/qt/askpassphrasedialog.cpp @@ -77,10 +77,7 @@ AskPassphraseDialog::AskPassphraseDialog(Mode mode, QWidget *parent) : AskPassphraseDialog::~AskPassphraseDialog() { - // Attempt to overwrite text so that they do not linger around in memory - ui->passEdit1->setText(QString(" ").repeated(ui->passEdit1->text().size())); - ui->passEdit2->setText(QString(" ").repeated(ui->passEdit2->text().size())); - ui->passEdit3->setText(QString(" ").repeated(ui->passEdit3->text().size())); + secureClearPassFields(); delete ui; } @@ -103,6 +100,8 @@ void AskPassphraseDialog::accept() newpass1.assign(ui->passEdit2->text().toStdString().c_str()); newpass2.assign(ui->passEdit3->text().toStdString().c_str()); + secureClearPassFields(); + switch(mode) { case Encrypt: { @@ -260,3 +259,17 @@ bool AskPassphraseDialog::eventFilter(QObject *object, QEvent *event) } return QDialog::eventFilter(object, event); } + +static void SecureClearQLineEdit(QLineEdit* edit) +{ + // Attempt to overwrite text so that they do not linger around in memory + edit->setText(QString(" ").repeated(edit->text().size())); + edit->clear(); +} + +void AskPassphraseDialog::secureClearPassFields() +{ + SecureClearQLineEdit(ui->passEdit1); + SecureClearQLineEdit(ui->passEdit2); + SecureClearQLineEdit(ui->passEdit3); +} diff --git a/src/qt/askpassphrasedialog.h b/src/qt/askpassphrasedialog.h index 727b5a1ada18a..34bf7ccb31f6f 100644 --- a/src/qt/askpassphrasedialog.h +++ b/src/qt/askpassphrasedialog.h @@ -42,6 +42,7 @@ class AskPassphraseDialog : public QDialog private Q_SLOTS: void textChanged(); + void secureClearPassFields(); protected: bool event(QEvent *event); From fa57b0c5ef8101e1228d17a2bdce28a36e6f2ff6 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 15 May 2016 11:06:23 +0200 Subject: [PATCH 0349/1802] [qa] test_framework: Append portseed to tmpdir This makes it possible to specify a tmpdir while running tests in parallel --- qa/rpc-tests/test_framework/test_framework.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qa/rpc-tests/test_framework/test_framework.py b/qa/rpc-tests/test_framework/test_framework.py index 3480de6c6e20c..091378186419a 100755 --- a/qa/rpc-tests/test_framework/test_framework.py +++ b/qa/rpc-tests/test_framework/test_framework.py @@ -115,6 +115,8 @@ def main(self): self.add_options(parser) (self.options, self.args) = parser.parse_args() + self.options.tmpdir += '/' + str(self.options.port_seed) + if self.options.trace_rpc: logging.basicConfig(level=logging.DEBUG, stream=sys.stdout) From ee9f4a5b1505113eae0fe8d70fd0414bd5bce0ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Tim=C3=B3n?= Date: Fri, 20 May 2016 14:43:37 +0200 Subject: [PATCH 0350/1802] Consensus: Decouple from chainparams.o and timedata.o Do it for the consensus-critical functions: - CheckBlockHeader - CheckBlock - ContextualCheckBlockHeader --- src/main.cpp | 27 +++++++++++++-------------- src/main.h | 6 +++--- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 9ba90b4ead2b3..f66de42aa8852 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2223,7 +2223,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin int64_t nTimeStart = GetTimeMicros(); // Check it again in case a previous version let a bad block in - if (!CheckBlock(block, state, !fJustCheck, !fJustCheck)) + if (!CheckBlock(block, state, chainparams.GetConsensus(), GetAdjustedTime(), !fJustCheck, !fJustCheck)) return error("%s: Consensus::CheckBlock: %s", __func__, FormatStateMessage(state)); // verify that the view's current state corresponds to the previous block @@ -3234,20 +3234,20 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne return true; } -bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW) +bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, int64_t nAdjustedTime, bool fCheckPOW) { // Check proof of work matches claimed amount - if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus())) + if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits, consensusParams)) return state.DoS(50, false, REJECT_INVALID, "high-hash", false, "proof of work failed"); // Check timestamp - if (block.GetBlockTime() > GetAdjustedTime() + 2 * 60 * 60) + if (block.GetBlockTime() > nAdjustedTime + 2 * 60 * 60) return state.Invalid(false, REJECT_INVALID, "time-too-new", "block timestamp too far in the future"); return true; } -bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bool fCheckMerkleRoot) +bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::Params& consensusParams, int64_t nAdjustedTime, bool fCheckPOW, bool fCheckMerkleRoot) { // These are checks that are independent of context. @@ -3256,7 +3256,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo // Check that the header is valid (particularly PoW). This is mostly // redundant with the call in AcceptBlockHeader. - if (!CheckBlockHeader(block, state, fCheckPOW)) + if (!CheckBlockHeader(block, state, consensusParams, nAdjustedTime, fCheckPOW)) return false; // Check the merkle root. @@ -3322,9 +3322,8 @@ static bool CheckIndexAgainstCheckpoint(const CBlockIndex* pindexPrev, CValidati return true; } -bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex * const pindexPrev) +bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex * const pindexPrev) { - const Consensus::Params& consensusParams = Params().GetConsensus(); // Check proof of work if (block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams)) return state.DoS(100, false, REJECT_INVALID, "bad-diffbits", false, "incorrect proof of work"); @@ -3397,7 +3396,7 @@ static bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state return true; } - if (!CheckBlockHeader(block, state)) + if (!CheckBlockHeader(block, state, chainparams.GetConsensus(), GetAdjustedTime())) return error("%s: Consensus::CheckBlockHeader: %s, %s", __func__, hash.ToString(), FormatStateMessage(state)); // Get prev block index @@ -3413,7 +3412,7 @@ static bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state if (fCheckpointsEnabled && !CheckIndexAgainstCheckpoint(pindexPrev, state, chainparams, hash)) return error("%s: CheckIndexAgainstCheckpoint(): %s", __func__, state.GetRejectReason().c_str()); - if (!ContextualCheckBlockHeader(block, state, pindexPrev)) + if (!ContextualCheckBlockHeader(block, state, chainparams.GetConsensus(), pindexPrev)) return error("%s: Consensus::ContextualCheckBlockHeader: %s, %s", __func__, hash.ToString(), FormatStateMessage(state)); } if (pindex == NULL) @@ -3457,7 +3456,7 @@ static bool AcceptBlock(const CBlock& block, CValidationState& state, const CCha if (fTooFarAhead) return true; // Block height is too high } - if ((!CheckBlock(block, state)) || !ContextualCheckBlock(block, state, pindex->pprev)) { + if ((!CheckBlock(block, state, chainparams.GetConsensus(), GetAdjustedTime())) || !ContextualCheckBlock(block, state, pindex->pprev)) { if (state.IsInvalid() && !state.CorruptionPossible()) { pindex->nStatus |= BLOCK_FAILED_VALID; setDirtyBlockIndex.insert(pindex); @@ -3542,9 +3541,9 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, indexDummy.nHeight = pindexPrev->nHeight + 1; // NOTE: CheckBlockHeader is called by CheckBlock - if (!ContextualCheckBlockHeader(block, state, pindexPrev)) + if (!ContextualCheckBlockHeader(block, state, chainparams.GetConsensus(), pindexPrev)) return error("%s: Consensus::ContextualCheckBlockHeader: %s", __func__, FormatStateMessage(state)); - if (!CheckBlock(block, state, fCheckPOW, fCheckMerkleRoot)) + if (!CheckBlock(block, state, chainparams.GetConsensus(), GetAdjustedTime(), fCheckPOW, fCheckMerkleRoot)) return error("%s: Consensus::CheckBlock: %s", __func__, FormatStateMessage(state)); if (!ContextualCheckBlock(block, state, pindexPrev)) return error("%s: Consensus::ContextualCheckBlock: %s", __func__, FormatStateMessage(state)); @@ -3876,7 +3875,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus())) return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); // check level 1: verify block validity - if (nCheckLevel >= 1 && !CheckBlock(block, state)) + if (nCheckLevel >= 1 && !CheckBlock(block, state, chainparams.GetConsensus(), GetAdjustedTime())) return error("%s: *** found bad block at %d, hash=%s (%s)\n", __func__, pindex->nHeight, pindex->GetBlockHash().ToString(), FormatStateMessage(state)); // check level 2: verify undo validity diff --git a/src/main.h b/src/main.h index f287171f141ba..4e93c084f417f 100644 --- a/src/main.h +++ b/src/main.h @@ -425,13 +425,13 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus /** Functions for validating blocks and updating the block tree */ /** Context-independent validity checks */ -bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW = true); -bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW = true, bool fCheckMerkleRoot = true); +bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, int64_t nAdjustedTime, bool fCheckPOW = true); +bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::Params& consensusParams, int64_t nAdjustedTime, bool fCheckPOW = true, bool fCheckMerkleRoot = true); /** Context-dependent validity checks. * By "context", we mean only the previous block headers, but not the UTXO * set; UTXO-related validity checks are done in ConnectBlock(). */ -bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex *pindexPrev); +bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex* pindexPrev); bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex *pindexPrev); /** Apply the effects of this block (with given index) on the UTXO set represented by coins. From beceac9bbf14bf4a81f6f63b9cca2a64157054ae Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Fri, 20 May 2016 14:44:32 +0100 Subject: [PATCH 0351/1802] Disable the mempool P2P command when bloom filters disabled Only useful to SPV peers, and attackers... like bloom is a DoS vector as far more data is sent than received. --- src/main.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 9ba90b4ead2b3..2ad2a8e3f11f1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5277,6 +5277,13 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, else if (strCommand == NetMsgType::MEMPOOL) { + if (!(nLocalServices & NODE_BLOOM) && !pfrom->fWhitelisted) + { + LogPrint("net", "mempool request with bloom filters disabled, disconnect peer=%d\n", pfrom->GetId()); + pfrom->fDisconnect = true; + return true; + } + if (CNode::OutboundTargetReached(false) && !pfrom->fWhitelisted) { LogPrint("net", "mempool request with bandwidth limit reached, disconnect peer=%d\n", pfrom->GetId()); From 3d3602faf4a47855be264f05d9d52253e8bd0f9d Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 20 May 2016 16:50:48 +0200 Subject: [PATCH 0352/1802] Add RPC test for the p2p mempool command in conjunction with disabled bloomfilters --- qa/rpc-tests/p2p-mempool.py | 99 +++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100755 qa/rpc-tests/p2p-mempool.py diff --git a/qa/rpc-tests/p2p-mempool.py b/qa/rpc-tests/p2p-mempool.py new file mode 100755 index 0000000000000..5d2daf39f8288 --- /dev/null +++ b/qa/rpc-tests/p2p-mempool.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python3 +# Copyright (c) 2015-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +from test_framework.mininode import * +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * +import time + +class TestNode(NodeConnCB): + def __init__(self): + NodeConnCB.__init__(self) + self.connection = None + self.ping_counter = 1 + self.last_pong = msg_pong() + self.block_receive_map = {} + + def add_connection(self, conn): + self.connection = conn + self.peer_disconnected = False + + def on_inv(self, conn, message): + pass + + # Track the last getdata message we receive (used in the test) + def on_getdata(self, conn, message): + self.last_getdata = message + + def on_block(self, conn, message): + message.block.calc_sha256() + try: + self.block_receive_map[message.block.sha256] += 1 + except KeyError as e: + self.block_receive_map[message.block.sha256] = 1 + + # Spin until verack message is received from the node. + # We use this to signal that our test can begin. This + # is called from the testing thread, so it needs to acquire + # the global lock. + def wait_for_verack(self): + def veracked(): + return self.verack_received + return wait_until(veracked, timeout=10) + + def wait_for_disconnect(self): + def disconnected(): + return self.peer_disconnected + return wait_until(disconnected, timeout=10) + + # Wrapper for the NodeConn's send_message function + def send_message(self, message): + self.connection.send_message(message) + + def on_pong(self, conn, message): + self.last_pong = message + + def on_close(self, conn): + self.peer_disconnected = True + + # Sync up with the node after delivery of a block + def sync_with_ping(self, timeout=30): + def received_pong(): + return (self.last_pong.nonce == self.ping_counter) + self.connection.send_message(msg_ping(nonce=self.ping_counter)) + success = wait_until(received_pong, timeout) + self.ping_counter += 1 + return success + + def send_mempool(self): + self.lastInv = [] + self.send_message(msg_mempool()) + +class P2PMempoolTests(BitcoinTestFramework): + def setup_chain(self): + initialize_chain_clean(self.options.tmpdir, 2) + + def setup_network(self): + # Start a node with maxuploadtarget of 200 MB (/24h) + self.nodes = [] + self.nodes.append(start_node(0, self.options.tmpdir, ["-debug", "-peerbloomfilters=0"])) + + def run_test(self): + #connect a mininode + aTestNode = TestNode() + node = NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], aTestNode) + aTestNode.add_connection(node) + NetworkThread().start() + aTestNode.wait_for_verack() + + #request mempool + aTestNode.send_mempool() + aTestNode.wait_for_disconnect() + + #mininode must be disconnected at this point + assert_equal(len(self.nodes[0].getpeerinfo()), 0) + +if __name__ == '__main__': + P2PMempoolTests().main() From 2ca8962a095ee29709316d163508f26ab1c340ae Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 17 May 2016 17:54:41 -0400 Subject: [PATCH 0353/1802] travis: use slim generic image, and some fixups Now that caches are distinct (https://github.com/travis-ci/travis-ci/issues/4393), we can use the Travis minimal image. The minimal image should take less time to setup and lead to quicker builds. Also addressed while I'm in here: - No need to delete the broken google-chrome repo in the minimal image - Set the hostname to work-around an openjdk bug - Remove the non-functional apt-cache option - Remove useless message at completion - Install jre where the java tests are run --- .travis.yml | 63 ++++++++++++++++++++++------------------------------- 1 file changed, 26 insertions(+), 37 deletions(-) diff --git a/.travis.yml b/.travis.yml index bc2c7faf7ee57..53fe4f8075465 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,17 +1,17 @@ -# errata: -# - A travis bug causes caches to trample eachother when using the same -# compiler key (which we don't use anyway). This is worked around for now by -# replacing the "compilers" with a build name prefixed by the no-op ":" -# command. See: https://github.com/travis-ci/travis-ci/issues/4393 -# - sudo/dist/group are set so as to get Blue Box VMs, necessary for [loopback] -# IPv6 support - sudo: required dist: trusty +#workaround for https://github.com/travis-ci/travis-ci/issues/5227 +addons: + hostname: bitcoin-tester + os: linux -language: cpp -compiler: gcc +language: generic +cache: + directories: + - depends/built + - depends/sdk-sources + - $HOME/.ccache env: global: - MAKEJOBS=-j3 @@ -25,35 +25,25 @@ env: - SDK_URL=https://bitcoincore.org/depends-sources/sdks - PYTHON_DEBUG=1 - WINEDEBUG=fixme-all -cache: - apt: true - directories: - - depends/built - - depends/sdk-sources - - $HOME/.ccache -matrix: - fast_finish: true - include: - - compiler: ": ARM" - env: HOST=arm-linux-gnueabihf PACKAGES="g++-arm-linux-gnueabihf" DEP_OPTS="NO_QT=1" CHECK_DOC=1 GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" - - compiler: ": Win32" - env: HOST=i686-w64-mingw32 DPKG_ADD_ARCH="i386" DEP_OPTS="NO_QT=1" PACKAGES="python3 nsis g++-mingw-w64-i686 wine1.6 bc" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-reduce-exports" - - compiler: ": 32-bit + dash" - env: HOST=i686-pc-linux-gnu PACKAGES="g++-multilib bc python3-zmq" DEP_OPTS="NO_QT=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++" USE_SHELL="/bin/dash" - - compiler: ": Win64" - env: HOST=x86_64-w64-mingw32 DPKG_ADD_ARCH="i386" DEP_OPTS="NO_QT=1" PACKAGES="python3 nsis g++-mingw-w64-x86-64 wine1.6 bc" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-reduce-exports" - - compiler: ": bitcoind" - env: HOST=x86_64-unknown-linux-gnu PACKAGES="bc python3-zmq" DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports CPPFLAGS=-DDEBUG_LOCKORDER" - - compiler: ": No wallet" - env: HOST=x86_64-unknown-linux-gnu PACKAGES="python3" DEP_OPTS="NO_WALLET=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" - - compiler: ": Cross-Mac" - env: HOST=x86_64-apple-darwin11 PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev" BITCOIN_CONFIG="--enable-reduce-exports" OSX_SDK=10.9 GOAL="deploy" - exclude: - - compiler: gcc + matrix: +# ARM + - HOST=arm-linux-gnueabihf PACKAGES="g++-arm-linux-gnueabihf" DEP_OPTS="NO_QT=1" CHECK_DOC=1 GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" +# Win32 + - HOST=i686-w64-mingw32 DPKG_ADD_ARCH="i386" DEP_OPTS="NO_QT=1" PACKAGES="python3 nsis g++-mingw-w64-i686 wine1.6 bc openjdk-7-jre-headless" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-reduce-exports" +# 32-bit + dash + - HOST=i686-pc-linux-gnu PACKAGES="g++-multilib bc python3-zmq openjdk-7-jre-headless" DEP_OPTS="NO_QT=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++" USE_SHELL="/bin/dash" +# Win64 + - HOST=x86_64-w64-mingw32 DPKG_ADD_ARCH="i386" DEP_OPTS="NO_QT=1" PACKAGES="python3 nsis g++-mingw-w64-x86-64 wine1.6 bc openjdk-7-jre-headless" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-reduce-exports" +# bitcoind + - HOST=x86_64-unknown-linux-gnu PACKAGES="bc python3-zmq openjdk-7-jre-headless" DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports CPPFLAGS=-DDEBUG_LOCKORDER" +# No wallet + - HOST=x86_64-unknown-linux-gnu PACKAGES=" openjdk-7-jre-headless python3" DEP_OPTS="NO_WALLET=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" +# Cross-Mac + - HOST=x86_64-apple-darwin11 PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev" BITCOIN_CONFIG="--enable-reduce-exports" OSX_SDK=10.9 GOAL="deploy" + before_install: - export PATH=$(echo $PATH | tr ':' "\n" | sed '/\/opt\/python/d' | tr "\n" ":" | sed "s|::|:|g") install: - - if [ -n "$PACKAGES" ]; then sudo rm -f /etc/apt/sources.list.d/google-chrome.list; fi - if [ -n "$PPA" ]; then travis_retry sudo add-apt-repository "$PPA" -y; fi - if [ -n "$DPKG_ADD_ARCH" ]; then sudo dpkg --add-architecture "$DPKG_ADD_ARCH" ; fi - if [ -n "$PACKAGES" ]; then travis_retry sudo apt-get update; fi @@ -83,4 +73,3 @@ script: after_script: - echo $TRAVIS_COMMIT_RANGE - echo $TRAVIS_COMMIT_LOG - - if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then (echo "Upload goes here. Something like: scp -r $BASE_OUTDIR server" || echo "upload failed"); fi From f7d4a25fe6b1bd52e70fa0779d1cd145f32bd2ab Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 20 May 2016 18:29:15 -0700 Subject: [PATCH 0354/1802] Make verify-commits POSIX-compliant --- contrib/verify-commits/gpg.sh | 10 +++++----- contrib/verify-commits/verify-commits.sh | 15 ++++++--------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/contrib/verify-commits/gpg.sh b/contrib/verify-commits/gpg.sh index 0218b82e11dd3..375d711725707 100755 --- a/contrib/verify-commits/gpg.sh +++ b/contrib/verify-commits/gpg.sh @@ -1,8 +1,9 @@ #!/bin/sh -INPUT=$(/dev/null); do case "$LINE" in "[GNUPG:] VALIDSIG "*) @@ -13,10 +14,9 @@ for LINE in $(echo "$INPUT" | gpg --trust-model always "$@" 2>/dev/null); do "[GNUPG:] REVKEYSIG "*) [ "$BITCOIN_VERIFY_COMMITS_ALLOW_REVSIG" != 1 ] && exit 1 while read KEY; do - case "$LINE" in "[GNUPG:] REVKEYSIG ${KEY:24:40} "*) + case "$LINE" in "[GNUPG:] REVKEYSIG ${KEY#????????????????????????} "*) REVSIG=true - GOODREVSIG="[GNUPG:] GOODSIG ${KEY:24:40} " - ;; + GOODREVSIG="[GNUPG:] GOODSIG ${KEY#????????????????????????} " esac done < ./contrib/verify-commits/trusted-keys ;; diff --git a/contrib/verify-commits/verify-commits.sh b/contrib/verify-commits/verify-commits.sh index 9ba781008a658..c9d2b96d8c8a9 100755 --- a/contrib/verify-commits/verify-commits.sh +++ b/contrib/verify-commits/verify-commits.sh @@ -1,4 +1,6 @@ #!/bin/sh +# Not technically POSIX-compliant due to use of "local", but almost every +# shell anyone uses today supports it, so its probably fine DIR=$(dirname "$0") @@ -6,20 +8,14 @@ echo "Please verify all commits in the following list are not evil:" git log "$DIR" VERIFIED_ROOT=$(cat "${DIR}/trusted-git-root") - -IS_REVSIG_ALLOWED () { - while read LINE; do - [ "$LINE" = "$1" ] && return 0 - done < "${DIR}/allow-revsig-commits" - return 1 -} +REVSIG_ALLOWED=$(cat "${DIR}/allow-revsig-commits") HAVE_FAILED=false IS_SIGNED () { if [ $1 = $VERIFIED_ROOT ]; then return 0; fi - if IS_REVSIG_ALLOWED "$1"; then + if [ "${REVSIG_ALLOWED#*$1}" != "$REVSIG_ALLOWED" ]; then export BITCOIN_VERIFY_COMMITS_ALLOW_REVSIG=1 else export BITCOIN_VERIFY_COMMITS_ALLOW_REVSIG=0 @@ -27,7 +23,8 @@ IS_SIGNED () { if ! git -c "gpg.program=${DIR}/gpg.sh" verify-commit $1 > /dev/null 2>&1; then return 1; fi - local PARENTS=$(git show -s --format=format:%P $1) + local PARENTS + PARENTS=$(git show -s --format=format:%P $1) for PARENT in $PARENTS; do if IS_SIGNED $PARENT > /dev/null; then return 0; From 9523e8adafd24f1c9358c437b857f0f2f25eeb47 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sat, 21 May 2016 01:44:29 -0700 Subject: [PATCH 0355/1802] Make verify-commits path-independent --- contrib/verify-commits/verify-commits.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/verify-commits/verify-commits.sh b/contrib/verify-commits/verify-commits.sh index c9d2b96d8c8a9..a859e67852448 100755 --- a/contrib/verify-commits/verify-commits.sh +++ b/contrib/verify-commits/verify-commits.sh @@ -3,6 +3,7 @@ # shell anyone uses today supports it, so its probably fine DIR=$(dirname "$0") +[ "/${DIR#/}" != "$DIR" ] && DIR=$(dirname "$(pwd)/$0") echo "Please verify all commits in the following list are not evil:" git log "$DIR" From 22421faa199b7922259b4b55e6471a1b5f91d0da Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Fri, 18 Mar 2016 06:04:08 -0400 Subject: [PATCH 0356/1802] Remove pointless warning Any attacker who managed to make an evil commit that changed something in the contrib/verify-commits/ directory could just as easily remove the warning and/or modify it to not display the evil commits; telling the user to check those commits specifically misleads them into checking just those commits rather than the script itself. --- contrib/verify-commits/verify-commits.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/contrib/verify-commits/verify-commits.sh b/contrib/verify-commits/verify-commits.sh index a859e67852448..5219331e2e5bc 100755 --- a/contrib/verify-commits/verify-commits.sh +++ b/contrib/verify-commits/verify-commits.sh @@ -5,9 +5,6 @@ DIR=$(dirname "$0") [ "/${DIR#/}" != "$DIR" ] && DIR=$(dirname "$(pwd)/$0") -echo "Please verify all commits in the following list are not evil:" -git log "$DIR" - VERIFIED_ROOT=$(cat "${DIR}/trusted-git-root") REVSIG_ALLOWED=$(cat "${DIR}/allow-revsig-commits") From 11164ec0b4c1790059220b09b5827e5618a46c76 Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Fri, 20 May 2016 08:55:57 +0100 Subject: [PATCH 0357/1802] Remove keys that are no longer used for merging Also updated trusted git root to be right after gmaxwell's last merge. --- contrib/verify-commits/trusted-git-root | 2 +- contrib/verify-commits/trusted-keys | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/contrib/verify-commits/trusted-git-root b/contrib/verify-commits/trusted-git-root index 838b8d1ea84bd..c60f8ab695e9c 100644 --- a/contrib/verify-commits/trusted-git-root +++ b/contrib/verify-commits/trusted-git-root @@ -1 +1 @@ -165e323d851cc87213c7673c6f278e87a6f2e752 +82bcf405f6db1d55b684a1f63a4aabad376cdad7 diff --git a/contrib/verify-commits/trusted-keys b/contrib/verify-commits/trusted-keys index ad1b28be0cc47..9c36d58cd2a30 100644 --- a/contrib/verify-commits/trusted-keys +++ b/contrib/verify-commits/trusted-keys @@ -1,8 +1,5 @@ 71A3B16735405025D447E8F274810B012346C9A6 1F4410F6A89268CE3197A84C57896D2FF8F0B657 -01CDF4627A3B88AAE4A571C87588242FBE38D3A8 -AF8BE07C7049F3A26B239D5325B3083201782B2F -81291FA67D2C379A006A053FEAB5AF94D9E9ABE7 3F1888C6DCA92A6499C4911FDBA1A67379A1A931 32EE5C4C3FA15CCADB46ABE529D4BCB6416F53EC FE09B823E6D83A3BC7983EAA2D7F2372E50FE137 From bd477f4e8ba9e632f42649f2fca10d698c6b7181 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Fri, 20 May 2016 04:59:57 -0400 Subject: [PATCH 0358/1802] VerifyDB: don't check blocks that have been pruned --- src/init.cpp | 4 ++-- src/main.cpp | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 8688381ecff35..a17377f6f332f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1269,8 +1269,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) uiInterface.InitMessage(_("Verifying blocks...")); if (fHavePruned && GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) > MIN_BLOCKS_TO_KEEP) { - LogPrintf("Prune: pruned datadir may not have more than %d blocks; -checkblocks=%d may fail\n", - MIN_BLOCKS_TO_KEEP, GetArg("-checkblocks", DEFAULT_CHECKBLOCKS)); + LogPrintf("Prune: pruned datadir may not have more than %d blocks; only checking available blocks", + MIN_BLOCKS_TO_KEEP); } { diff --git a/src/main.cpp b/src/main.cpp index 9ba90b4ead2b3..33abf3957869f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3871,6 +3871,11 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, uiInterface.ShowProgress(_("Verifying blocks..."), std::max(1, std::min(99, (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100))))); if (pindex->nHeight < chainActive.Height()-nCheckDepth) break; + if (fPruneMode && !(pindex->nStatus & BLOCK_HAVE_DATA)) { + // If pruning, only go back as far as we have data. + LogPrintf("VerifyDB(): block verification stopping at height %d (pruning, no data)\n", pindex->nHeight); + break; + } CBlock block; // check level 0: read from disk if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus())) From 678513cc94995a243a7e56593fe3e44e003cb597 Mon Sep 17 00:00:00 2001 From: Mitchell Cash Date: Tue, 24 May 2016 10:43:01 +1000 Subject: [PATCH 0359/1802] Correct small typo in extract_strings_qt.py --- share/qt/extract_strings_qt.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/share/qt/extract_strings_qt.py b/share/qt/extract_strings_qt.py index 7728a4377590b..2ba8bb9b3acb7 100755 --- a/share/qt/extract_strings_qt.py +++ b/share/qt/extract_strings_qt.py @@ -32,7 +32,7 @@ def parse_po(text): in_msgstr = False # message start in_msgid = True - + msgid = [line[6:]] elif line.startswith('msgstr '): in_msgid = False @@ -67,7 +67,7 @@ def parse_po(text): #include -// Automatically generated by extract_strings.py +// Automatically generated by extract_strings_qt.py #ifdef __GNUC__ #define UNUSED __attribute__((unused)) #else From a27876474819ffff80614f966fea06d5da2d5c15 Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Tue, 24 May 2016 14:23:15 -0400 Subject: [PATCH 0360/1802] FIX: Account for txs already added to block in addPriorityTxs --- src/miner.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/miner.cpp b/src/miner.cpp index 91e05f9ce48bf..1eab8f949d41d 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -74,7 +74,7 @@ int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParam BlockAssembler::BlockAssembler(const CChainParams& _chainparams) : chainparams(_chainparams) { - // Largest block you're willing to create: + // Largest block you're willing to create: nBlockMaxSize = GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE); // Limit to between 1K and MAX_BLOCK_SIZE-1K for sanity: nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE-1000), nBlockMaxSize)); @@ -262,6 +262,11 @@ void BlockAssembler::addScoreTxs() clearedTxs.pop(); } + // If tx already in block, skip (added by addPriorityTxs) + if (inBlock.count(iter)) { + continue; + } + // If tx is dependent on other mempool txs which haven't yet been included // then put it in the waitSet if (isStillDependent(iter)) { From 1ad933950884ae3411cce78e3b8e92e9a649e735 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Tue, 24 May 2016 11:35:06 -0400 Subject: [PATCH 0361/1802] Test framework: only cleanup on successful test runs --- qa/rpc-tests/test_framework/test_framework.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/qa/rpc-tests/test_framework/test_framework.py b/qa/rpc-tests/test_framework/test_framework.py index b9b803429dec2..49f4192269f02 100755 --- a/qa/rpc-tests/test_framework/test_framework.py +++ b/qa/rpc-tests/test_framework/test_framework.py @@ -165,9 +165,11 @@ def main(self): else: print("Note: bitcoinds were not stopped and may still be running") - if not self.options.nocleanup and not self.options.noshutdown: + if not self.options.nocleanup and not self.options.noshutdown and success: print("Cleaning up") shutil.rmtree(self.options.tmpdir) + else: + print("Not cleaning up dir %s" % self.options.tmpdir) if success: print("Tests successful") From 2d83013dc54320b3f0c978475517da6156f7b50d Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Sat, 21 May 2016 23:55:22 +0200 Subject: [PATCH 0362/1802] Add support for dnsseeds with option to filter by servicebits --- src/chainparams.cpp | 10 ++++++++++ src/chainparams.h | 7 +++++-- src/net.cpp | 5 +++-- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 5c7d190125cc3..0005115671122 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -16,6 +16,14 @@ #include "chainparamsseeds.h" +std::string CDNSSeedData::getHost(uint64_t requiredServiceBits) const { + //use default host for non-filter-capable seeds or if we use the default service bits (NODE_NETWORK) + if (!supportsServiceBitsFiltering || requiredServiceBits == NODE_NETWORK) + return host; + + return strprintf("x%x.%s", requiredServiceBits, host); +} + static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesisOutputScript, uint32_t nTime, uint32_t nNonce, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward) { CMutableTransaction txNew; @@ -197,6 +205,8 @@ class CTestNetParams : public CChainParams { vFixedSeeds.clear(); vSeeds.clear(); + // nodes with support for servicebits filtering should be at the top + vSeeds.push_back(CDNSSeedData("testnetbitcoin.jonasschnelli.ch", "testnet-seed.bitcoin.jonasschnelli.ch", true)); vSeeds.push_back(CDNSSeedData("bitcoin.petertodd.org", "testnet-seed.bitcoin.petertodd.org")); vSeeds.push_back(CDNSSeedData("bluematt.me", "testnet-seed.bluematt.me")); vSeeds.push_back(CDNSSeedData("bitcoin.schildbach.de", "testnet-seed.bitcoin.schildbach.de")); diff --git a/src/chainparams.h b/src/chainparams.h index 59202f548a3ca..7168daaf4347c 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -13,9 +13,12 @@ #include -struct CDNSSeedData { +class CDNSSeedData { +public: std::string name, host; - CDNSSeedData(const std::string &strName, const std::string &strHost) : name(strName), host(strHost) {} + bool supportsServiceBitsFiltering; + std::string getHost(uint64_t requiredServiceBits) const; + CDNSSeedData(const std::string &strName, const std::string &strHost, bool supportsServiceBitsFilteringIn = false) : name(strName), host(strHost), supportsServiceBitsFiltering(supportsServiceBitsFilteringIn) {} }; struct SeedSpec6 { diff --git a/src/net.cpp b/src/net.cpp index bbd23d292a4cc..54d14a7234d2f 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1466,12 +1466,13 @@ void ThreadDNSAddressSeed() } else { std::vector vIPs; std::vector vAdd; - if (LookupHost(seed.host.c_str(), vIPs, 0, true)) + uint64_t requiredServiceBits = NODE_NETWORK; + if (LookupHost(seed.getHost(requiredServiceBits).c_str(), vIPs, 0, true)) { BOOST_FOREACH(const CNetAddr& ip, vIPs) { int nOneDay = 24*3600; - CAddress addr = CAddress(CService(ip, Params().GetDefaultPort())); + CAddress addr = CAddress(CService(ip, Params().GetDefaultPort()), requiredServiceBits); addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old vAdd.push_back(addr); found++; From 7e908c7b826cedbf29560ce7a668af809ee71524 Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Fri, 20 May 2016 16:19:26 +0000 Subject: [PATCH 0363/1802] Do not use mempool for GETDATA for tx accepted after the last mempool req. The ability to GETDATA a transaction which has not (yet) been relayed is a privacy loss vector. The use of the mempool for this was added as part of the mempool p2p message and is only needed to fetch transactions returned by it. --- src/main.cpp | 6 +++++- src/net.cpp | 1 + src/net.h | 3 +++ src/txmempool.cpp | 10 +++++++++- src/txmempool.h | 1 + 5 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 9ba90b4ead2b3..2ee6bc531098a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4503,7 +4503,10 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam } if (!pushed && inv.type == MSG_TX) { CTransaction tx; - if (mempool.lookup(inv.hash, tx)) { + int64_t txtime; + // To protect privacy, do not answer getdata using the mempool when + // that TX couldn't have been INVed in reply to a MEMPOOL request. + if (mempool.lookup(inv.hash, tx, txtime) && txtime <= pfrom->timeLastMempoolReq) { pfrom->PushMessage(NetMsgType::TX, tx); pushed = true; } @@ -5902,6 +5905,7 @@ bool SendMessages(CNode* pto) vInv.clear(); } } + pto->timeLastMempoolReq = GetTime(); } // Determine transactions to relay diff --git a/src/net.cpp b/src/net.cpp index bbd23d292a4cc..df3221e841560 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2396,6 +2396,7 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa fRelayTxes = false; fSentAddr = false; pfilter = new CBloomFilter(); + timeLastMempoolReq = 0; nPingNonceSent = 0; nPingUsecStart = 0; nPingUsecTime = 0; diff --git a/src/net.h b/src/net.h index 998ee492608eb..66cc912a52537 100644 --- a/src/net.h +++ b/src/net.h @@ -17,6 +17,7 @@ #include "sync.h" #include "uint256.h" +#include #include #include @@ -413,6 +414,8 @@ class CNode // Used for BIP35 mempool sending, also protected by cs_inventory bool fSendMempool; + // Last time a "MEMPOOL" request was serviced. + std::atomic timeLastMempoolReq; // Ping time measurement: // The pong reply we're expecting, or 0 if no pong expected. uint64_t nPingNonceSent; diff --git a/src/txmempool.cpp b/src/txmempool.cpp index aa5df6ca4e40e..4f17e7f8cac19 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -789,15 +789,23 @@ void CTxMemPool::queryHashes(vector& vtxid) std::sort(vtxid.begin(), vtxid.end(), DepthAndScoreComparator(this)); } -bool CTxMemPool::lookup(uint256 hash, CTransaction& result) const + +bool CTxMemPool::lookup(uint256 hash, CTransaction& result, int64_t& time) const { LOCK(cs); indexed_transaction_set::const_iterator i = mapTx.find(hash); if (i == mapTx.end()) return false; result = i->GetTx(); + time = i->GetTime(); return true; } +bool CTxMemPool::lookup(uint256 hash, CTransaction& result) const +{ + int64_t time; + return CTxMemPool::lookup(hash, result, time); +} + bool CTxMemPool::lookupFeeRate(const uint256& hash, CFeeRate& feeRate) const { LOCK(cs); diff --git a/src/txmempool.h b/src/txmempool.h index 3e1d387975b6f..75cf0f4c124de 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -602,6 +602,7 @@ class CTxMemPool } bool lookup(uint256 hash, CTransaction& result) const; + bool lookup(uint256 hash, CTransaction& result, int64_t& time) const; bool lookupFeeRate(const uint256& hash, CFeeRate& feeRate) const; /** Estimate fee rate needed to get into the next nBlocks From c769c4af11fc58dd4813d328c7f71042bc577676 Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Sun, 19 Apr 2015 12:34:43 -0700 Subject: [PATCH 0364/1802] Avoid counting failed connect attempts when probably offline. If a node is offline failed outbound connection attempts will crank up the addrman counter and effectively blow away our state. This change reduces the problem by only counting attempts made while the node believes it has outbound connections to at least two netgroups. Connect and addnode connections are also not counted, as there is no reason to unequally penalize them for their more frequent connections -- though there should be no real effect from this unless their addnode configureation is later removed. Wasteful repeated connection attempts while only a few connections are up are avoided via nLastTry. This is still somewhat incomplete protection because our outbound peers could be down but not timed out or might all be on 'local' networks (although the requirement for multiple netgroups helps). --- src/addrman.cpp | 4 ++-- src/addrman.h | 6 +++--- src/net.cpp | 20 ++++++++++---------- src/net.h | 2 +- src/rpc/net.cpp | 2 +- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/addrman.cpp b/src/addrman.cpp index 6c54cfa4cd2fd..0a1745c10c539 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -311,7 +311,7 @@ bool CAddrMan::Add_(const CAddress& addr, const CNetAddr& source, int64_t nTimeP return fNew; } -void CAddrMan::Attempt_(const CService& addr, int64_t nTime) +void CAddrMan::Attempt_(const CService& addr, bool fCountFailure, int64_t nTime) { CAddrInfo* pinfo = Find(addr); @@ -327,7 +327,7 @@ void CAddrMan::Attempt_(const CService& addr, int64_t nTime) // update info info.nLastTry = nTime; - info.nAttempts++; + if (fCountFailure) info.nAttempts++; } CAddrInfo CAddrMan::Select_(bool newOnly) diff --git a/src/addrman.h b/src/addrman.h index 3085450450474..65ca79fa02cfd 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -230,7 +230,7 @@ class CAddrMan bool Add_(const CAddress &addr, const CNetAddr& source, int64_t nTimePenalty); //! Mark an entry as attempted to connect. - void Attempt_(const CService &addr, int64_t nTime); + void Attempt_(const CService &addr, bool fCountFailure, int64_t nTime); //! Select an address to connect to, if newOnly is set to true, only the new table is selected from. CAddrInfo Select_(bool newOnly); @@ -532,12 +532,12 @@ class CAddrMan } //! Mark an entry as connection attempted to. - void Attempt(const CService &addr, int64_t nTime = GetAdjustedTime()) + void Attempt(const CService &addr, bool fCountFailure, int64_t nTime = GetAdjustedTime()) { { LOCK(cs); Check(); - Attempt_(addr, nTime); + Attempt_(addr, fCountFailure, nTime); Check(); } } diff --git a/src/net.cpp b/src/net.cpp index bbd23d292a4cc..f30321869a81a 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -367,7 +367,7 @@ CNode* FindNode(const CService& addr) return NULL; } -CNode* ConnectNode(CAddress addrConnect, const char *pszDest) +CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure) { if (pszDest == NULL) { if (IsLocal(addrConnect)) @@ -399,7 +399,7 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest) return NULL; } - addrman.Attempt(addrConnect); + addrman.Attempt(addrConnect, fCountFailure); // Add node CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false); @@ -416,7 +416,7 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest) } else if (!proxyConnectionFailed) { // If connecting to the node failed, and failure is not caused by a problem connecting to // the proxy, mark this as an attempt. - addrman.Attempt(addrConnect); + addrman.Attempt(addrConnect, fCountFailure); } return NULL; @@ -1533,7 +1533,7 @@ void static ProcessOneShot() CAddress addr; CSemaphoreGrant grant(*semOutbound, true); if (grant) { - if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true)) + if (!OpenNetworkConnection(addr, false, &grant, strDest.c_str(), true)) AddOneShot(strDest); } } @@ -1549,7 +1549,7 @@ void ThreadOpenConnections() BOOST_FOREACH(const std::string& strAddr, mapMultiArgs["-connect"]) { CAddress addr; - OpenNetworkConnection(addr, NULL, strAddr.c_str()); + OpenNetworkConnection(addr, false, NULL, strAddr.c_str()); for (int i = 0; i < 10 && i < nLoop; i++) { MilliSleep(500); @@ -1633,7 +1633,7 @@ void ThreadOpenConnections() } if (addrConnect.IsValid()) - OpenNetworkConnection(addrConnect, &grant); + OpenNetworkConnection(addrConnect, (int)setConnected.size() >= min(nMaxConnections - 1, 2), &grant); } } @@ -1655,7 +1655,7 @@ void ThreadOpenAddedConnections() BOOST_FOREACH(const std::string& strAddNode, lAddresses) { CAddress addr; CSemaphoreGrant grant(*semOutbound); - OpenNetworkConnection(addr, &grant, strAddNode.c_str()); + OpenNetworkConnection(addr, false, &grant, strAddNode.c_str()); MilliSleep(500); } MilliSleep(120000); // Retry every 2 minutes @@ -1694,7 +1694,7 @@ void ThreadOpenAddedConnections() BOOST_FOREACH(std::vector& vserv, lservAddressesToAdd) { CSemaphoreGrant grant(*semOutbound); - OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant); + OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), false, &grant); MilliSleep(500); } MilliSleep(120000); // Retry every 2 minutes @@ -1702,7 +1702,7 @@ void ThreadOpenAddedConnections() } // if successful, this moves the passed grant to the constructed node -bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *pszDest, bool fOneShot) +bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound, const char *pszDest, bool fOneShot) { // // Initiate outbound network connection @@ -1716,7 +1716,7 @@ bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOu } else if (FindNode(std::string(pszDest))) return false; - CNode* pnode = ConnectNode(addrConnect, pszDest); + CNode* pnode = ConnectNode(addrConnect, pszDest, fCountFailure); boost::this_thread::interruption_point(); if (!pnode) diff --git a/src/net.h b/src/net.h index 998ee492608eb..3332496c05184 100644 --- a/src/net.h +++ b/src/net.h @@ -83,7 +83,7 @@ CNode* FindNode(const CNetAddr& ip); CNode* FindNode(const CSubNet& subNet); CNode* FindNode(const std::string& addrName); CNode* FindNode(const CService& ip); -bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false); +bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false); void MapPort(bool fUseUPnP); unsigned short GetListenPort(); bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index e09af89656832..8f62d636d86fd 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -219,7 +219,7 @@ UniValue addnode(const UniValue& params, bool fHelp) if (strCommand == "onetry") { CAddress addr; - OpenNetworkConnection(addr, NULL, strNode.c_str()); + OpenNetworkConnection(addr, false, NULL, strNode.c_str()); return NullUniValue; } From 6182d10503ae3af222a7e4575724dce7ef563fec Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Sun, 19 Apr 2015 13:39:38 -0700 Subject: [PATCH 0365/1802] Do not increment nAttempts by more than one for every Good connection. This slows the increase of the nAttempts in addrman while partitioned, even if the node hasn't yet noticed the partitioning. --- src/addrman.cpp | 8 +++++++- src/addrman.h | 8 ++++++++ src/net.cpp | 2 +- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/addrman.cpp b/src/addrman.cpp index 0a1745c10c539..00f6fe99e001c 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -197,6 +197,9 @@ void CAddrMan::MakeTried(CAddrInfo& info, int nId) void CAddrMan::Good_(const CService& addr, int64_t nTime) { int nId; + + nLastGood = nTime; + CAddrInfo* pinfo = Find(addr, &nId); // if not found, bail out @@ -327,7 +330,10 @@ void CAddrMan::Attempt_(const CService& addr, bool fCountFailure, int64_t nTime) // update info info.nLastTry = nTime; - if (fCountFailure) info.nAttempts++; + if (fCountFailure && info.nLastCountAttempt < nLastGood) { + info.nLastCountAttempt = nTime; + info.nAttempts++; + } } CAddrInfo CAddrMan::Select_(bool newOnly) diff --git a/src/addrman.h b/src/addrman.h index 65ca79fa02cfd..c5923e94171c6 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -29,6 +29,9 @@ class CAddrInfo : public CAddress //! last try whatsoever by us (memory only) int64_t nLastTry; + //! last counted attempt (memory only) + int64_t nLastCountAttempt; + private: //! where knowledge about this address first came from CNetAddr source; @@ -66,6 +69,7 @@ class CAddrInfo : public CAddress { nLastSuccess = 0; nLastTry = 0; + nLastCountAttempt = 0; nAttempts = 0; nRefCount = 0; fInTried = false; @@ -200,6 +204,9 @@ class CAddrMan //! list of "new" buckets int vvNew[ADDRMAN_NEW_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE]; + //! last time Good was called (memory only) + int64_t nLastGood; + protected: //! secret key to randomize bucket select with uint256 nKey; @@ -458,6 +465,7 @@ class CAddrMan nIdCount = 0; nTried = 0; nNew = 0; + nLastGood = 1; //Initially at 1 so that "never" is strictly worse. } CAddrMan() diff --git a/src/net.cpp b/src/net.cpp index f30321869a81a..c15a4692e169b 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1633,7 +1633,7 @@ void ThreadOpenConnections() } if (addrConnect.IsValid()) - OpenNetworkConnection(addrConnect, (int)setConnected.size() >= min(nMaxConnections - 1, 2), &grant); + OpenNetworkConnection(addrConnect, (int)setConnected.size() >= std::min(nMaxConnections - 1, 2), &grant); } } From 52b02ecd6d7ce918676c76c725678cf0ae2561d2 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 26 May 2016 18:44:14 +0200 Subject: [PATCH 0366/1802] Use global ::fRelayTxes instead of CNode one --- src/net.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net.cpp b/src/net.cpp index 44cdfd2ae26c5..a0c670e595f4e 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -471,7 +471,7 @@ void CNode::PushVersion() else LogPrint("net", "send version message: version %d, blocks=%d, us=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), id); PushMessage(NetMsgType::VERSION, PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe, - nLocalHostNonce, strSubVersion, nBestHeight, fRelayTxes); + nLocalHostNonce, strSubVersion, nBestHeight, ::fRelayTxes); } From e871f8338ad180428ff997b80a476d9719d8073f Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Thu, 26 May 2016 14:19:07 -0400 Subject: [PATCH 0367/1802] Tests: add timeout to sync_blocks() and sync_mempools() Previously these functions would infinitely loop if sync failed; now they have a default timeout of 60 seconds, after which an AssertionError is raised. sync_blocks() has also been improved and now compares the tip hash of each node, rather than just using block count. --- qa/rpc-tests/test_framework/util.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index 3948b664e31ca..fc66ef287d715 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -121,30 +121,34 @@ def hex_str_to_bytes(hex_str): def str_to_b64str(string): return b64encode(string.encode('utf-8')).decode('ascii') -def sync_blocks(rpc_connections, wait=1): +def sync_blocks(rpc_connections, wait=1, timeout=60): """ - Wait until everybody has the same block count + Wait until everybody has the same tip """ - while True: - counts = [ x.getblockcount() for x in rpc_connections ] - if counts == [ counts[0] ]*len(counts): - break + while timeout > 0: + tips = [ x.getbestblockhash() for x in rpc_connections ] + if tips == [ tips[0] ]*len(tips): + return True time.sleep(wait) + timeout -= wait + raise AssertionError("Block sync failed") -def sync_mempools(rpc_connections, wait=1): +def sync_mempools(rpc_connections, wait=1, timeout=60): """ Wait until everybody has the same transactions in their memory pools """ - while True: + while timeout > 0: pool = set(rpc_connections[0].getrawmempool()) num_match = 1 for i in range(1, len(rpc_connections)): if set(rpc_connections[i].getrawmempool()) == pool: num_match = num_match+1 if num_match == len(rpc_connections): - break + return True time.sleep(wait) + timeout -= wait + raise AssertionError("Mempool sync failed") bitcoind_processes = {} From 5fac1f33fb5afad4cbcb51b7c85ab2cd759846e1 Mon Sep 17 00:00:00 2001 From: Yuri Zhykin Date: Fri, 27 May 2016 05:32:58 +0300 Subject: [PATCH 0368/1802] bench: Added base58 encoding/decoding benchmarks --- src/Makefile.bench.include | 3 +- src/bench/base58.cpp | 56 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 src/bench/base58.cpp diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include index 65fd24e051cae..4067ceb3993e8 100644 --- a/src/Makefile.bench.include +++ b/src/Makefile.bench.include @@ -9,7 +9,8 @@ bench_bench_bitcoin_SOURCES = \ bench/bench.h \ bench/Examples.cpp \ bench/rollingbloom.cpp \ - bench/crypto_hash.cpp + bench/crypto_hash.cpp \ + bench/base58.cpp bench_bench_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CLFAGS) $(EVENT_PTHREADS_CFLAGS) -I$(builddir)/bench/ bench_bench_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) diff --git a/src/bench/base58.cpp b/src/bench/base58.cpp new file mode 100644 index 0000000000000..1279c3e7df5dd --- /dev/null +++ b/src/bench/base58.cpp @@ -0,0 +1,56 @@ +// Copyright (c) 2016 the Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "bench.h" + +#include "main.h" +#include "base58.h" + +#include +#include + + +static void Base58Encode(benchmark::State& state) +{ + unsigned char buff[32] = { + 17, 79, 8, 99, 150, 189, 208, 162, 22, 23, 203, 163, 36, 58, 147, + 227, 139, 2, 215, 100, 91, 38, 11, 141, 253, 40, 117, 21, 16, 90, + 200, 24 + }; + unsigned char* b = buff; + while (state.KeepRunning()) { + EncodeBase58(b, b + 32); + } +} + + +static void Base58CheckEncode(benchmark::State& state) +{ + unsigned char buff[32] = { + 17, 79, 8, 99, 150, 189, 208, 162, 22, 23, 203, 163, 36, 58, 147, + 227, 139, 2, 215, 100, 91, 38, 11, 141, 253, 40, 117, 21, 16, 90, + 200, 24 + }; + unsigned char* b = buff; + std::vector vch; + vch.assign(b, b + 32); + while (state.KeepRunning()) { + EncodeBase58Check(vch); + } +} + + +static void Base58Decode(benchmark::State& state) +{ + const char* addr = "17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem"; + std::vector vch; + while (state.KeepRunning()) { + DecodeBase58(addr, vch); + } +} + + +BENCHMARK(Base58Encode); +BENCHMARK(Base58CheckEncode); +BENCHMARK(Base58Decode); From 13c455823f6d74c9632bc85191a0bebad973da1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Fri, 27 May 2016 07:46:36 +0200 Subject: [PATCH 0369/1802] Remove unused local variable shadowing upper local --- src/test/sighash_tests.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index 04c6fa9625caa..e43b2ff6c45dc 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -195,7 +195,6 @@ BOOST_AUTO_TEST_CASE(sighash_from_data) nHashType = test[3].get_int(); sigHashHex = test[4].get_str(); - uint256 sh; CDataStream stream(ParseHex(raw_tx), SER_NETWORK, PROTOCOL_VERSION); stream >> tx; From 88f14b999cb70f6c556633f2889e698a05305158 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 27 May 2016 13:30:36 +0200 Subject: [PATCH 0370/1802] Include signal.h for sig_atomic_t in WIN32 --- src/util.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/util.h b/src/util.h index 88a00d3ca1fcb..c6f8af4cdf07d 100644 --- a/src/util.h +++ b/src/util.h @@ -28,9 +28,7 @@ #include #include -#ifndef WIN32 #include -#endif static const bool DEFAULT_LOGTIMEMICROS = false; static const bool DEFAULT_LOGIPS = false; From 723779c6504453cfb5ccdacf864e7e2f09bb6c32 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 27 May 2016 14:14:44 -0400 Subject: [PATCH 0371/1802] build: Enumerate ctaes rather than globbing --- src/Makefile.am | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index 31917f1350e46..cb8a99fe9aedb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -410,6 +410,12 @@ libbitcoinconsensus_la_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) endif # +CTAES_DIST = crypto/ctaes/bench.c +CTAES_DIST += crypto/ctaes/ctaes.c +CTAES_DIST += crypto/ctaes/ctaes.h +CTAES_DIST += crypto/ctaes/README.md +CTAES_DIST += crypto/ctaes/test.c + CLEANFILES = leveldb/libleveldb.a leveldb/libmemenv.a CLEANFILES += $(EXTRA_LIBRARIES) CLEANFILES += *.gcda *.gcno @@ -427,7 +433,7 @@ CLEANFILES += zmq/*.gcda zmq/*.gcno DISTCLEANFILES = obj/build.h -EXTRA_DIST = leveldb crypto/ctaes +EXTRA_DIST = leveldb $(CTAES_DIST) clean-local: -$(MAKE) -C leveldb clean From 619d5691c20bee5d08be2ce85aafa2cb570dbca4 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 27 May 2016 13:30:08 +0200 Subject: [PATCH 0372/1802] Benchmark SipHash --- src/bench/crypto_hash.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/bench/crypto_hash.cpp b/src/bench/crypto_hash.cpp index 6b753f6308371..168006154f8fe 100644 --- a/src/bench/crypto_hash.cpp +++ b/src/bench/crypto_hash.cpp @@ -6,6 +6,8 @@ #include "bench.h" #include "bloom.h" +#include "hash.h" +#include "uint256.h" #include "utiltime.h" #include "crypto/ripemd160.h" #include "crypto/sha1.h" @@ -39,6 +41,16 @@ static void SHA256(benchmark::State& state) CSHA256().Write(begin_ptr(in), in.size()).Finalize(hash); } +static void SHA256_32b(benchmark::State& state) +{ + std::vector in(32,0); + while (state.KeepRunning()) { + for (int i = 0; i < 1000000; i++) { + CSHA256().Write(begin_ptr(in), in.size()).Finalize(&in[0]); + } + } +} + static void SHA512(benchmark::State& state) { uint8_t hash[CSHA512::OUTPUT_SIZE]; @@ -47,7 +59,20 @@ static void SHA512(benchmark::State& state) CSHA512().Write(begin_ptr(in), in.size()).Finalize(hash); } +static void SipHash_32b(benchmark::State& state) +{ + uint256 x; + while (state.KeepRunning()) { + for (int i = 0; i < 1000000; i++) { + *((uint64_t*)x.begin()) = SipHashUint256(0, i, x); + } + } +} + BENCHMARK(RIPEMD160); BENCHMARK(SHA1); BENCHMARK(SHA256); BENCHMARK(SHA512); + +BENCHMARK(SHA256_32b); +BENCHMARK(SipHash_32b); From fa2637a3beb8677067015df3d9d7b394fa837c2f Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 16 Apr 2016 12:25:12 +0200 Subject: [PATCH 0373/1802] Always require OS randomness when generating secret keys --- src/Makefile.am | 3 ++- src/init.cpp | 2 -- src/key.cpp | 3 +-- src/main.cpp | 1 - src/random.cpp | 48 ++++++++++++++++++++++++++++++++++++++++++- src/random.h | 11 ++++++---- src/wallet/wallet.cpp | 8 ++------ 7 files changed, 59 insertions(+), 17 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 3c056386fac7b..f630ad4aa1bb1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -374,7 +374,8 @@ endif bitcoin_cli_LDADD = \ $(LIBBITCOIN_CLI) \ $(LIBUNIVALUE) \ - $(LIBBITCOIN_UTIL) + $(LIBBITCOIN_UTIL) \ + $(LIBBITCOIN_CRYPTO) bitcoin_cli_LDADD += $(BOOST_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(EVENT_LIBS) # diff --git a/src/init.cpp b/src/init.cpp index 9b6943c5866c2..98c0894122783 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1401,8 +1401,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (!strErrors.str().empty()) return InitError(strErrors.str()); - RandAddSeedPerfmon(); - //// debug print LogPrintf("mapBlockIndex.size() = %u\n", mapBlockIndex.size()); LogPrintf("nBestHeight = %d\n", chainActive.Height()); diff --git a/src/key.cpp b/src/key.cpp index 6a3d9aa140906..79023566c3e61 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -124,9 +124,8 @@ bool CKey::Check(const unsigned char *vch) { } void CKey::MakeNewKey(bool fCompressedIn) { - RandAddSeedPerfmon(); do { - GetRandBytes(vch, sizeof(vch)); + GetStrongRandBytes(vch, sizeof(vch)); } while (!Check(vch)); fValid = true; fCompressed = fCompressedIn; diff --git a/src/main.cpp b/src/main.cpp index ed157b53dced7..ffc57d48be973 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4547,7 +4547,6 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams) { - RandAddSeedPerfmon(); LogPrint("net", "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->id); if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0) { diff --git a/src/random.cpp b/src/random.cpp index 6155c0d8cf23a..8ad0a9b007b4b 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -5,9 +5,11 @@ #include "random.h" +#include "crypto/sha512.h" #include "support/cleanse.h" #ifdef WIN32 #include "compat.h" // for Windows API +#include #endif #include "serialize.h" // for begin_ptr(vec) #include "util.h" // for LogPrint() @@ -43,7 +45,7 @@ void RandAddSeed() memory_cleanse((void*)&nCounter, sizeof(nCounter)); } -void RandAddSeedPerfmon() +static void RandAddSeedPerfmon() { RandAddSeed(); @@ -83,6 +85,29 @@ void RandAddSeedPerfmon() #endif } +/** Get 32 bytes of system entropy. */ +static void GetOSRand(unsigned char *ent32) +{ +#ifdef WIN32 + HCRYPTPROV hProvider; + int ret = CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); + assert(ret); + ret = CryptGenRandom(hProvider, 32, ent32); + assert(ret); + CryptReleaseContext(hProvider, 0); +#else + int f = open("/dev/urandom", O_RDONLY); + assert(f != -1); + int have = 0; + do { + ssize_t n = read(f, ent32 + have, 32 - have); + assert(n > 0 && n <= 32 - have); + have += n; + } while (have < 32); + close(f); +#endif +} + void GetRandBytes(unsigned char* buf, int num) { if (RAND_bytes(buf, num) != 1) { @@ -91,6 +116,27 @@ void GetRandBytes(unsigned char* buf, int num) } } +void GetStrongRandBytes(unsigned char* out, int num) +{ + assert(num <= 32); + CSHA512 hasher; + unsigned char buf[64]; + + // First source: OpenSSL's RNG + RandAddSeedPerfmon(); + GetRandBytes(buf, 32); + hasher.Write(buf, 32); + + // Second source: OS RNG + GetOSRand(buf); + hasher.Write(buf, 32); + + // Produce output + hasher.Finalize(buf); + memcpy(out, buf, num); + memory_cleanse(buf, 64); +} + uint64_t GetRand(uint64_t nMax) { if (nMax == 0) diff --git a/src/random.h b/src/random.h index 1a2d3e8ee24ca..31b80bd565bdc 100644 --- a/src/random.h +++ b/src/random.h @@ -10,11 +10,8 @@ #include -/** - * Seed OpenSSL PRNG with additional entropy data - */ +/* Seed OpenSSL PRNG with additional entropy data */ void RandAddSeed(); -void RandAddSeedPerfmon(); /** * Functions to gather random data via the OpenSSL PRNG @@ -24,6 +21,12 @@ uint64_t GetRand(uint64_t nMax); int GetRandInt(int nMax); uint256 GetRandHash(); +/** + * Function to gather random data from multiple sources, failing whenever any + * of those source fail to provide a result. + */ +void GetStrongRandBytes(unsigned char* buf, int num); + /** * Seed insecure_rand using the random pool. * @param Deterministic Use a deterministic seed diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 5d1a431190954..da0d6f272bfef 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -509,16 +509,14 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) return false; CKeyingMaterial vMasterKey; - RandAddSeedPerfmon(); vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE); - GetRandBytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE); + GetStrongRandBytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE); CMasterKey kMasterKey; - RandAddSeedPerfmon(); kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE); - GetRandBytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE); + GetStrongRandBytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE); CCrypter crypter; int64_t nStartTime = GetTimeMillis(); @@ -3147,8 +3145,6 @@ bool CWallet::InitLoadWallet() if (fFirstRun) { // Create new keyUser and set as default key - RandAddSeedPerfmon(); - CPubKey newDefaultKey; if (walletInstance->GetKeyFromPool(newDefaultKey)) { walletInstance->SetDefaultKey(newDefaultKey); From 628cf1440aca8b5b259458a4ed41cc138cae34fa Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 23 Apr 2016 18:07:35 +0200 Subject: [PATCH 0374/1802] Don't use assert for catching randomness failures --- src/random.cpp | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/random.cpp b/src/random.cpp index 8ad0a9b007b4b..d9a8cc145ea91 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -15,6 +15,7 @@ #include "util.h" // for LogPrint() #include "utilstrencodings.h" // for GetTime() +#include #include #ifndef WIN32 @@ -24,6 +25,12 @@ #include #include +static void RandFailure() +{ + LogPrintf("Failed to read randomness, aborting\n"); + abort(); +} + static inline int64_t GetPerformanceCounter() { int64_t nCounter = 0; @@ -91,17 +98,25 @@ static void GetOSRand(unsigned char *ent32) #ifdef WIN32 HCRYPTPROV hProvider; int ret = CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); - assert(ret); + if (!ret) { + RandFailure(); + } ret = CryptGenRandom(hProvider, 32, ent32); - assert(ret); + if (!ret) { + RandFailure(); + } CryptReleaseContext(hProvider, 0); #else int f = open("/dev/urandom", O_RDONLY); - assert(f != -1); + if (f == -1) { + RandFailure(); + } int have = 0; do { ssize_t n = read(f, ent32 + have, 32 - have); - assert(n > 0 && n <= 32 - have); + if (n <= 0 || n + have > 32) { + RandFailure(); + } have += n; } while (have < 32); close(f); @@ -111,8 +126,7 @@ static void GetOSRand(unsigned char *ent32) void GetRandBytes(unsigned char* buf, int num) { if (RAND_bytes(buf, num) != 1) { - LogPrintf("%s: OpenSSL RAND_bytes() failed with error: %s\n", __func__, ERR_error_string(ERR_get_error(), NULL)); - assert(false); + RandFailure(); } } From 1a8c4d575d9ae15c954a850a2516ef4a75eabf7a Mon Sep 17 00:00:00 2001 From: fanquake Date: Fri, 27 May 2016 16:01:14 +0800 Subject: [PATCH 0375/1802] [Doc] Add benchmarking notes --- doc/README.md | 1 + doc/benchmarking.md | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 doc/benchmarking.md diff --git a/doc/README.md b/doc/README.md index 357334dfb23f5..c30f29452b786 100644 --- a/doc/README.md +++ b/doc/README.md @@ -57,6 +57,7 @@ The Bitcoin repo's [root README](/README.md) contains relevant information on th - [Shared Libraries](shared-libraries.md) - [BIPS](bips.md) - [Dnsseed Policy](dnsseed-policy.md) +- [Benchmarking](benchmarking.md) ### Resources * Discuss on the [BitcoinTalk](https://bitcointalk.org/) forums, in the [Development & Technical Discussion board](https://bitcointalk.org/index.php?board=6.0). diff --git a/doc/benchmarking.md b/doc/benchmarking.md new file mode 100644 index 0000000000000..0ba75afcda3cb --- /dev/null +++ b/doc/benchmarking.md @@ -0,0 +1,30 @@ +Benchmarking +============ + +Bitcoin Core has an internal benchmarking framework, with benchmarks +for cryptographic algorithms such as SHA1, SHA256, SHA512 and RIPEMD160. As well as the rolling bloom filter. + +After compiling bitcoin-core, the benchmarks can be run with: +`src/bench/bench_bitcoin` + +The output will look similar to: +``` +#Benchmark,count,min,max,average +RIPEMD160,448,0.001245033173334,0.002638196945190,0.002461894814457 +RollingBloom-refresh,1,0.000635000000000,0.000635000000000,0.000635000000000 +RollingBloom-refresh,1,0.000108000000000,0.000108000000000,0.000108000000000 +RollingBloom-refresh,1,0.000107000000000,0.000107000000000,0.000107000000000 +RollingBloom-refresh,1,0.000204000000000,0.000204000000000,0.000204000000000 +SHA1,640,0.000909024336207,0.001938136418660,0.001843086257577 +SHA256,256,0.002209486499909,0.008500099182129,0.004300644621253 +SHA512,384,0.001319904176016,0.002813005447388,0.002615700786312 +Sleep100ms,10,0.205592155456543,0.210056066513062,0.104166316986084 +Trig,67108864,0.000000014997003,0.000000015448112,0.000000015188842 +``` + +More benchmarks are needed for, in no particular order: +- Script Validation +- CCoinDBView caching +- Coins database +- Memory pool +- Wallet coin selection From bd0f41387783ee91623d7fac15e89e57db37df82 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 30 May 2016 11:43:53 +0200 Subject: [PATCH 0376/1802] Reduce unnecessary hashing in signrawtransaction --- src/rpc/rawtransaction.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index bec7ebe55f636..1bc31c4e3cac1 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -743,6 +743,9 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp) // Script verification errors UniValue vErrors(UniValue::VARR); + // Use CTransaction for the constant parts of the + // transaction to avoid rehashing. + const CTransaction txConst(mergedTx); // Sign what we can: for (unsigned int i = 0; i < mergedTx.vin.size(); i++) { CTxIn& txin = mergedTx.vin[i]; @@ -760,10 +763,10 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp) // ... and merge in other signatures: BOOST_FOREACH(const CMutableTransaction& txv, txVariants) { - txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig); + txin.scriptSig = CombineSignatures(prevPubKey, txConst, i, txin.scriptSig, txv.vin[i].scriptSig); } ScriptError serror = SCRIPT_ERR_OK; - if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i), &serror)) { + if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i), &serror)) { TxInErrorToJSON(txin, vErrors, ScriptErrorString(serror)); } } From e4f73c76b3a408037fdf32d9700d57f3d0e77a47 Mon Sep 17 00:00:00 2001 From: fanquake Date: Mon, 30 May 2016 20:43:46 +0800 Subject: [PATCH 0377/1802] [Doc] Update implemented BIPs list --- doc/bips.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/bips.md b/doc/bips.md index b8efabbcf251c..b4b62e781ec61 100644 --- a/doc/bips.md +++ b/doc/bips.md @@ -1,5 +1,6 @@ -BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.12.0**): +BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.13.0**): +* [`BIP 9`](https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki): The changes allowing multiple soft-forks to be deployed in parallel have been implemented since **v0.12.1** ([PR #7575](https://github.com/bitcoin/bitcoin/pull/7575)) * [`BIP 11`](https://github.com/bitcoin/bips/blob/master/bip-0011.mediawiki): Multisig outputs are standard since **v0.6.0** ([PR #669](https://github.com/bitcoin/bitcoin/pull/669)). * [`BIP 13`](https://github.com/bitcoin/bips/blob/master/bip-0013.mediawiki): The address format for P2SH addresses has been implemented since **v0.6.0** ([PR #669](https://github.com/bitcoin/bitcoin/pull/669)). * [`BIP 14`](https://github.com/bitcoin/bips/blob/master/bip-0014.mediawiki): The subversion string is being used as User Agent since **v0.6.0** ([PR #669](https://github.com/bitcoin/bitcoin/pull/669)). @@ -16,8 +17,11 @@ BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.12.0**): * [`BIP 61`](https://github.com/bitcoin/bips/blob/master/bip-0061.mediawiki): The 'reject' protocol message (and the protocol version bump to 70002) was added in **v0.9.0** ([PR #3185](https://github.com/bitcoin/bitcoin/pull/3185)). * [`BIP 65`](https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki): The CHECKLOCKTIMEVERIFY softfork was merged in **v0.12.0** ([PR #6351](https://github.com/bitcoin/bitcoin/pull/6351)), and backported to **v0.11.2** and **v0.10.4**. Mempool-only CLTV was added in [PR #6124](https://github.com/bitcoin/bitcoin/pull/6124). * [`BIP 66`](https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki): The strict DER rules and associated version 3 blocks have been implemented since **v0.10.0** ([PR #5713](https://github.com/bitcoin/bitcoin/pull/5713)). +* [`BIP 68`](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki): Sequence locks have been implemented as of **v0.12.1** ([PR #7184](https://github.com/bitcoin/bitcoin/pull/7184)). * [`BIP 70`](https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki) [`71`](https://github.com/bitcoin/bips/blob/master/bip-0071.mediawiki) [`72`](https://github.com/bitcoin/bips/blob/master/bip-0072.mediawiki): Payment Protocol support has been available in Bitcoin Core GUI since **v0.9.0** ([PR #5216](https://github.com/bitcoin/bitcoin/pull/5216)). * [`BIP 111`](https://github.com/bitcoin/bips/blob/master/bip-0111.mediawiki): `NODE_BLOOM` service bit added, and enforced for all peer versions as of **v0.13.0** ([PR #6579](https://github.com/bitcoin/bitcoin/pull/6579) and [PR #6641](https://github.com/bitcoin/bitcoin/pull/6641)). +* [`BIP 112`](https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki): The CHECKSEQUENCEVERIFY opcode has been implemented since **v0.12.1** ([PR #7524](https://github.com/bitcoin/bitcoin/pull/7524)). +* [`BIP 113`](https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki): Median time past lock-time calculations have been implemented since **v0.12.1** ([PR #6566](https://github.com/bitcoin/bitcoin/pull/6566)). * [`BIP 125`](https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki): Opt-in full replace-by-fee signaling honoured in mempool and mining as of **v0.12.0** ([PR 6871](https://github.com/bitcoin/bitcoin/pull/6871)). * [`BIP 130`](https://github.com/bitcoin/bips/blob/master/bip-0130.mediawiki): direct headers announcement is negotiated with peer versions `>=70012` as of **v0.12.0** ([PR 6494](https://github.com/bitcoin/bitcoin/pull/6494)). * [`BIP 133`](https://github.com/bitcoin/bips/blob/master/bip-0133.mediawiki): feefilter messages are respected and sent for peer versions `>=70013` as of **v0.13.0** ([PR 7542](https://github.com/bitcoin/bitcoin/pull/7542)). From b682960a28137966306e0a3646c96fa5f4b811ff Mon Sep 17 00:00:00 2001 From: Chris Stewart Date: Mon, 23 May 2016 14:23:07 -0500 Subject: [PATCH 0378/1802] Adding P2SH(p2pkh) script test case Fixing formatting Adding test case into automatically generated test case set Clean up commits removing extra whitespace from eol Removing extra whitespace on macro line --- src/test/data/script_tests.json | 7 +++++++ src/test/script_tests.cpp | 5 ++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json index 757d94b526857..0bdac182e0079 100644 --- a/src/test/data/script_tests.json +++ b/src/test/data/script_tests.json @@ -1310,6 +1310,13 @@ "EVAL_FALSE", "P2SH(P2PK), bad redeemscript" ], +[ + "0x47 0x30440220781ba4f59a7b207a10db87628bc2168df4d59b844b397d2dbc9a5835fb2f2b7602206ed8fbcc1072fe2dfc5bb25909269e5dc42ffcae7ec2bc81d59692210ff30c2b01 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x19 0x76a91491b24bf9f5288532960ac687abb035127b1d28a588ac", + "HASH160 0x14 0x7f67f0521934a57d3039f77f9f32cf313f3ac74b EQUAL", + "P2SH", + "OK", + "P2SH(P2PKH)" +], [ "0x47 0x304402204e2eb034be7b089534ac9e798cf6a2c79f38bcb34d1b179efd6f2de0841735db022071461beb056b5a7be1819da6a3e3ce3662831ecc298419ca101eb6887b5dd6a401 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac", "HASH160 0x14 0x2df519943d5acc0ef5222091f9dfe3543f489a82 EQUAL", diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 5e9711a4a7e26..39089f103d0c2 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -427,7 +427,10 @@ BOOST_AUTO_TEST_CASE(script_build) tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG, "P2SH(P2PK), bad redeemscript", SCRIPT_VERIFY_P2SH, true ).PushSig(keys.key0).PushRedeem().DamagePush(10).ScriptError(SCRIPT_ERR_EVAL_FALSE)); - + + tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << ToByteVector(keys.pubkey0.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG, + "P2SH(P2PKH)", SCRIPT_VERIFY_P2SH, true + ).PushSig(keys.key0).Push(keys.pubkey0).PushRedeem()); tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << ToByteVector(keys.pubkey1.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG, "P2SH(P2PKH), bad sig but no VERIFY_P2SH", 0, true ).PushSig(keys.key0).DamagePush(10).PushRedeem()); From 63ff57db4beb2e92b3d8ed396da016f29f790195 Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Sun, 29 May 2016 01:36:52 +0000 Subject: [PATCH 0379/1802] Avoid integer division in the benchmark inner-most loop. Previously the benchmark code used an integer division (%) with a non-constant in the inner-loop. This is quite slow on many processors, especially ones like ARM that lack a hardware divide. Even on fairly recent x86_64 like haswell an integer division can take something like 100 cycles-- making it comparable to the runtime of siphash. This change avoids the division by using bitmasking instead. This was especially easy since the count was only increased by doubling. This change also restarts the timing when the execution time was very low this avoids mintimes of zero in cases where one execution ends up below the timer resolution. It also reduces the impact of the overhead on the final result. The formatting of the prints is changed to not use scientific notation make it more machine readable (in particular, gnuplot croaks on the non-fixedpoint, and it doesn't sort correctly). This also hoists out all the floating point divisions out of the semi-hot path because it was easy to do so. It might be prudent to break out the critical test into a macro just to guarantee that it gets inlined. It might also make sense to just save out the intermediate counts and times and get the floating point completely out of the timing loop (because e.g. on hardware without a fast hardware FPU like some ARM it will still be slow enough to distort the results). I haven't done either of these in this commit. --- src/bench/bench.cpp | 35 ++++++++++++++++++++++++----------- src/bench/bench.h | 7 ++++--- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/bench/bench.cpp b/src/bench/bench.cpp index 6ee3cdc27a49e..227546a7a78a3 100644 --- a/src/bench/bench.cpp +++ b/src/bench/bench.cpp @@ -5,6 +5,7 @@ #include "bench.h" #include +#include #include using namespace benchmark; @@ -25,7 +26,7 @@ BenchRunner::BenchRunner(std::string name, BenchFunction func) void BenchRunner::RunAll(double elapsedTimeForOne) { - std::cout << "Benchmark" << "," << "count" << "," << "min" << "," << "max" << "," << "average" << "\n"; + std::cout << "#Benchmark" << "," << "count" << "," << "min" << "," << "max" << "," << "average" << "\n"; for (std::map::iterator it = benchmarks.begin(); it != benchmarks.end(); ++it) { @@ -38,22 +39,34 @@ BenchRunner::RunAll(double elapsedTimeForOne) bool State::KeepRunning() { + if (count & countMask) { + ++count; + return true; + } double now; if (count == 0) { - beginTime = now = gettimedouble(); + lastTime = beginTime = now = gettimedouble(); } else { - // timeCheckCount is used to avoid calling gettime most of the time, - // so benchmarks that run very quickly get consistent results. - if ((count+1)%timeCheckCount != 0) { - ++count; - return true; // keep going - } now = gettimedouble(); - double elapsedOne = (now - lastTime)/timeCheckCount; + double elapsed = now - lastTime; + double elapsedOne = elapsed * countMaskInv; if (elapsedOne < minTime) minTime = elapsedOne; if (elapsedOne > maxTime) maxTime = elapsedOne; - if (elapsedOne*timeCheckCount < maxElapsed/16) timeCheckCount *= 2; + if (elapsed*128 < maxElapsed) { + // If the execution was much too fast (1/128th of maxElapsed), increase the count mask by 8x and restart timing. + // The restart avoids including the overhead of this code in the measurement. + countMask = ((countMask<<3)|7) & ((1LL<<60)-1); + countMaskInv = 1./(countMask+1); + count = 0; + minTime = std::numeric_limits::max(); + maxTime = std::numeric_limits::min(); + return true; + } + if (elapsed*16 < maxElapsed) { + countMask = ((countMask<<1)|1) & ((1LL<<60)-1); + countMaskInv = 1./(countMask+1); + } } lastTime = now; ++count; @@ -64,7 +77,7 @@ bool State::KeepRunning() // Output results double average = (now-beginTime)/count; - std::cout << name << "," << count << "," << minTime << "," << maxTime << "," << average << "\n"; + std::cout << std::fixed << std::setprecision(15) << name << "," << count << "," << minTime << "," << maxTime << "," << average << "\n"; return false; } diff --git a/src/bench/bench.h b/src/bench/bench.h index 5ce13c642b59b..f13b145aaf0c7 100644 --- a/src/bench/bench.h +++ b/src/bench/bench.h @@ -40,14 +40,15 @@ namespace benchmark { std::string name; double maxElapsed; double beginTime; - double lastTime, minTime, maxTime; + double lastTime, minTime, maxTime, countMaskInv; int64_t count; - int64_t timeCheckCount; + int64_t countMask; public: State(std::string _name, double _maxElapsed) : name(_name), maxElapsed(_maxElapsed), count(0) { minTime = std::numeric_limits::max(); maxTime = std::numeric_limits::min(); - timeCheckCount = 1; + countMask = 1; + countMaskInv = 1./(countMask + 1); } bool KeepRunning(); }; From 16698cb77e455ae1e2fffd8d0225d2486232a366 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Tue, 31 May 2016 05:30:35 +0300 Subject: [PATCH 0380/1802] PR #7772 is not enough to fix the issue with QCompleter, use event filter instead of `connect` --- src/qt/rpcconsole.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index b11648e46fcf2..11f3e49a06d9b 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -327,6 +327,14 @@ bool RPCConsole::eventFilter(QObject* obj, QEvent *event) return true; } break; + case Qt::Key_Return: + case Qt::Key_Enter: + // forward these events to lineEdit + if(obj == autoCompleter->popup()) { + QApplication::postEvent(ui->lineEdit, new QKeyEvent(*keyevt)); + return true; + } + break; default: // Typing in messages widget brings focus to line edit, and redirects key there // Exclude most combinations and keys that emit no text, except paste shortcuts @@ -458,9 +466,7 @@ void RPCConsole::setClientModel(ClientModel *model) autoCompleter = new QCompleter(wordList, this); ui->lineEdit->setCompleter(autoCompleter); - - // clear the lineEdit after activating from QCompleter - connect(autoCompleter, SIGNAL(activated(const QString&)), ui->lineEdit, SLOT(clear()), Qt::QueuedConnection); + autoCompleter->popup()->installEventFilter(this); } } From f19025106de47a92396f9fb98e6d3bbc568c40b5 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Sat, 2 Jan 2016 12:34:08 +0100 Subject: [PATCH 0381/1802] [Wallet] Add simplest BIP32/deterministic key generation implementation --- src/wallet/wallet.cpp | 86 +++++++++++++++++++++++++++++++++++++++-- src/wallet/wallet.h | 12 ++++++ src/wallet/walletdb.cpp | 17 ++++++++ src/wallet/walletdb.h | 32 +++++++++++++++ 4 files changed, 143 insertions(+), 4 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index da0d6f272bfef..fdb46472a83a1 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -91,7 +91,48 @@ CPubKey CWallet::GenerateNewKey() bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets CKey secret; - secret.MakeNewKey(fCompressed); + + // Create new metadata + int64_t nCreationTime = GetTime(); + CKeyMetadata metadata(nCreationTime); + + // use HD key derivation if HD was enabled during wallet creation + if (!hdChain.masterKeyID.IsNull()) { + // for now we use a fixed keypath scheme of m/0'/0'/k + CKey key; //master key seed (256bit) + CExtKey masterKey; //hd master key + CExtKey accountKey; //key at m/0' + CExtKey externalChainChildKey; //key at m/0'/0' + CExtKey childKey; //key at m/0'/0'/' + + // try to get the master key + if (!GetKey(hdChain.masterKeyID, key)) + throw std::runtime_error("CWallet::GenerateNewKey(): Master key not found"); + + masterKey.SetMaster(key.begin(), key.size()); + + // derive m/0' + // use hardened derivation (child keys > 0x80000000 are hardened after bip32) + masterKey.Derive(accountKey, 0 | 0x80000000); + + // derive m/0'/0' + accountKey.Derive(externalChainChildKey, 0 | 0x80000000); + + // derive child key at next index, skip keys already known to the wallet + do + { + externalChainChildKey.Derive(childKey, hdChain.nExternalChainCounter | 0x80000000); + // increment childkey index + hdChain.nExternalChainCounter++; + } while(HaveKey(childKey.key.GetPubKey().GetID())); + secret = childKey.key; + + // update the chain model in the database + if (!CWalletDB(strWalletFile).WriteHDChain(hdChain)) + throw std::runtime_error("CWallet::GenerateNewKey(): Writing HD chain model failed"); + } else { + secret.MakeNewKey(fCompressed); + } // Compressed public keys were introduced in version 0.6.0 if (fCompressed) @@ -100,9 +141,7 @@ CPubKey CWallet::GenerateNewKey() CPubKey pubkey = secret.GetPubKey(); assert(secret.VerifyPubKey(pubkey)); - // Create new metadata - int64_t nCreationTime = GetTime(); - mapKeyMetadata[pubkey.GetID()] = CKeyMetadata(nCreationTime); + mapKeyMetadata[pubkey.GetID()] = metadata; if (!nTimeFirstKey || nCreationTime < nTimeFirstKey) nTimeFirstKey = nCreationTime; @@ -1049,6 +1088,37 @@ CAmount CWallet::GetChange(const CTransaction& tx) const return nChange; } +bool CWallet::SetHDMasterKey(const CKey& key) +{ + LOCK(cs_wallet); + + // store the key as normal "key"/"ckey" object + // in the database + // key metadata is not required + CPubKey pubkey = key.GetPubKey(); + if (!AddKeyPubKey(key, pubkey)) + throw std::runtime_error("CWallet::GenerateNewKey(): AddKey failed"); + + // store the keyid (hash160) together with + // the child index counter in the database + // as a hdchain object + CHDChain newHdChain; + newHdChain.masterKeyID = pubkey.GetID(); + SetHDChain(newHdChain, false); + + return true; +} + +bool CWallet::SetHDChain(const CHDChain& chain, bool memonly) +{ + LOCK(cs_wallet); + if (!memonly && !CWalletDB(strWalletFile).WriteHDChain(chain)) + throw runtime_error("AddHDChain(): writing chain failed"); + + hdChain = chain; + return true; +} + int64_t CWalletTx::GetTxTime() const { int64_t n = nTimeSmart; @@ -3058,6 +3128,7 @@ std::string CWallet::GetWalletHelpString(bool showDebug) strUsage += HelpMessageOpt("-sendfreetransactions", strprintf(_("Send transactions as zero-fee transactions if possible (default: %u)"), DEFAULT_SEND_FREE_TRANSACTIONS)); strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), DEFAULT_SPEND_ZEROCONF_CHANGE)); strUsage += HelpMessageOpt("-txconfirmtarget=", strprintf(_("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)"), DEFAULT_TX_CONFIRM_TARGET)); + strUsage += HelpMessageOpt("-usehd", _("Use hierarchical deterministic key generation (HD) after bip32. Only has effect during wallet creation/first start") + " " + strprintf(_("(default: %u)"), DEFAULT_USE_HD_WALLET)); strUsage += HelpMessageOpt("-upgradewallet", _("Upgrade wallet to latest format on startup")); strUsage += HelpMessageOpt("-wallet=", _("Specify wallet file (within data directory)") + " " + strprintf(_("(default: %s)"), DEFAULT_WALLET_DAT)); strUsage += HelpMessageOpt("-walletbroadcast", _("Make the wallet broadcast transactions") + " " + strprintf(_("(default: %u)"), DEFAULT_WALLETBROADCAST)); @@ -3145,6 +3216,13 @@ bool CWallet::InitLoadWallet() if (fFirstRun) { // Create new keyUser and set as default key + if (GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET)) { + // generate a new master key + CKey key; + key.MakeNewKey(true); + if (!walletInstance->SetHDMasterKey(key)) + throw std::runtime_error("CWallet::GenerateNewKey(): Storing master key failed"); + } CPubKey newDefaultKey; if (walletInstance->GetKeyFromPool(newDefaultKey)) { walletInstance->SetDefaultKey(newDefaultKey); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index b2180a5a26bb8..a819c03266e5e 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -57,6 +57,9 @@ static const unsigned int DEFAULT_TX_CONFIRM_TARGET = 2; static const unsigned int MAX_FREE_TRANSACTION_CREATE_SIZE = 1000; static const bool DEFAULT_WALLETBROADCAST = true; +//! if set, all keys will be derived by using BIP32 +static const bool DEFAULT_USE_HD_WALLET = true; + extern const char * DEFAULT_WALLET_DAT; class CBlockIndex; @@ -574,6 +577,9 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface void SyncMetaData(std::pair); + /* the hd chain data model (external chain counters) */ + CHDChain hdChain; + public: /* * Main wallet lock. @@ -887,6 +893,12 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface static bool ParameterInteraction(); bool BackupWallet(const std::string& strDest); + + /* Set the hd chain model (chain child index counters) */ + bool SetHDChain(const CHDChain& chain, bool memonly); + + /* Set the current hd master key (will reset the chain child index counters) */ + bool SetHDMasterKey(const CKey& key); }; /** A key allocated from the key pool. */ diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index b5037c9a65abf..7bfd4909506f3 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -599,6 +599,16 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, return false; } } + else if (strType == "hdchain") + { + CHDChain chain; + ssValue >> chain; + if (!pwallet->SetHDChain(chain, true)) + { + strErr = "Error reading wallet database: SetHDChain failed"; + return false; + } + } } catch (...) { return false; @@ -1003,3 +1013,10 @@ bool CWalletDB::EraseDestData(const std::string &address, const std::string &key nWalletDBUpdated++; return Erase(std::make_pair(std::string("destdata"), std::make_pair(address, key))); } + + +bool CWalletDB::WriteHDChain(const CHDChain& chain) +{ + nWalletDBUpdated++; + return Write(std::string("hdchain"), chain); +} diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 00c10ea70f03b..71b0ff26db173 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -40,6 +40,35 @@ enum DBErrors DB_NEED_REWRITE }; +/* simple hd chain data model */ +class CHDChain +{ +public: + uint32_t nExternalChainCounter; + CKeyID masterKeyID; //!< master key hash160 + + static const int CURRENT_VERSION = 1; + int nVersion; + + CHDChain() { SetNull(); } + ADD_SERIALIZE_METHODS; + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + { + READWRITE(this->nVersion); + nVersion = this->nVersion; + READWRITE(nExternalChainCounter); + READWRITE(masterKeyID); + } + + void SetNull() + { + nVersion = CHDChain::CURRENT_VERSION; + nExternalChainCounter = 0; + masterKeyID.SetNull(); + } +}; + class CKeyMetadata { public: @@ -134,6 +163,9 @@ class CWalletDB : public CDB static bool Recover(CDBEnv& dbenv, const std::string& filename, bool fOnlyKeys); static bool Recover(CDBEnv& dbenv, const std::string& filename); + //! write the hdchain model (external chain child index counter) + bool WriteHDChain(const CHDChain& chain); + private: CWalletDB(const CWalletDB&); void operator=(const CWalletDB&); From 4d8993b3469915d8c9ba4cd3b918f16782edf0de Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Sat, 21 May 2016 09:45:32 +0000 Subject: [PATCH 0382/1802] Defer inserting into maprelay until just before relaying. This reduces the rate of not founds by better matching the far end expectations, it also improves privacy by removing the ability to use getdata to probe for a node having a txn before it has been relayed. --- src/main.cpp | 43 ++++++++++++++++++++++++++++++------------- src/net.cpp | 15 --------------- src/net.h | 3 --- 3 files changed, 30 insertions(+), 31 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index c2905784f0455..f9b8ab37e3f6d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -80,6 +80,10 @@ uint64_t nPruneTarget = 0; int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE; bool fEnableReplacement = DEFAULT_ENABLE_REPLACEMENT; +std::map mapRelay; +std::deque > vRelayExpiration; +CCriticalSection cs_mapRelay; + CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE); CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE; @@ -4501,27 +4505,28 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam } else if (inv.IsKnownType()) { + CTransaction tx; // Send stream from relay memory - bool pushed = false; + bool push = false; { LOCK(cs_mapRelay); map::iterator mi = mapRelay.find(inv.hash); if (mi != mapRelay.end()) { - pfrom->PushMessage(inv.GetCommand(), (*mi).second); - pushed = true; + tx = (*mi).second; + push = true; } } - if (!pushed && inv.type == MSG_TX) { - CTransaction tx; + if (!push && inv.type == MSG_TX) { int64_t txtime; // To protect privacy, do not answer getdata using the mempool when // that TX couldn't have been INVed in reply to a MEMPOOL request. if (mempool.lookup(inv.hash, tx, txtime) && txtime <= pfrom->timeLastMempoolReq) { - pfrom->PushMessage(NetMsgType::TX, tx); - pushed = true; + push = true; } } - if (!pushed) { + if (push) { + pfrom->PushMessage(inv.GetCommand(), tx); + } else { vNotFound.push_back(inv); } } @@ -5958,14 +5963,26 @@ bool SendMessages(CNode* pto) if (filterrate && feeRate.GetFeePerK() < filterrate) { continue; } - if (pto->pfilter) { - CTransaction tx; - if (!mempool.lookup(hash, tx)) continue; - if (!pto->pfilter->IsRelevantAndUpdate(tx)) continue; - } + CTransaction tx; + if (!mempool.lookup(hash, tx)) continue; + if (pto->pfilter && !pto->pfilter->IsRelevantAndUpdate(tx)) continue; // Send vInv.push_back(CInv(MSG_TX, hash)); nRelayedTransactions++; + { + LOCK(cs_mapRelay); + // Expire old relay messages + while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime()) + { + mapRelay.erase(vRelayExpiration.front().second); + vRelayExpiration.pop_front(); + } + + auto ret = mapRelay.insert(std::make_pair(hash, tx)); + if (ret.second) { + vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, hash)); + } + } if (vInv.size() == MAX_INV_SZ) { pto->PushMessage(NetMsgType::INV, vInv); vInv.clear(); diff --git a/src/net.cpp b/src/net.cpp index 78a914ebdf8f6..c09e3aedb6b76 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -90,9 +90,6 @@ std::string strSubVersion; std::vector vNodes; CCriticalSection cs_vNodes; -std::map mapRelay; -std::deque > vRelayExpiration; -CCriticalSection cs_mapRelay; limitedmap mapAlreadyAskedFor(MAX_INV_SZ); static std::deque vOneShots; @@ -2081,18 +2078,6 @@ instance_of_cnetcleanup; void RelayTransaction(const CTransaction& tx) { CInv inv(MSG_TX, tx.GetHash()); - { - LOCK(cs_mapRelay); - // Expire old relay messages - while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime()) - { - mapRelay.erase(vRelayExpiration.front().second); - vRelayExpiration.pop_front(); - } - - mapRelay.insert(std::make_pair(inv.hash, tx)); - vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv.hash)); - } LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) { diff --git a/src/net.h b/src/net.h index 0b4cd0bcb37c5..403653e8c83a3 100644 --- a/src/net.h +++ b/src/net.h @@ -162,9 +162,6 @@ extern int nMaxConnections; extern std::vector vNodes; extern CCriticalSection cs_vNodes; -extern std::map mapRelay; -extern std::deque > vRelayExpiration; -extern CCriticalSection cs_mapRelay; extern limitedmap mapAlreadyAskedFor; extern std::vector vAddedNodes; From 8c9e681ff8bae61c803cdcc1d05d69cbea5da7bf Mon Sep 17 00:00:00 2001 From: mrbandrews Date: Tue, 31 May 2016 14:21:40 -0400 Subject: [PATCH 0383/1802] Tests: Rework blockstore to avoid re-serialization. --- qa/rpc-tests/test_framework/blockstore.py | 59 +++++++++++++++-------- qa/rpc-tests/test_framework/mininode.py | 13 +++++ 2 files changed, 53 insertions(+), 19 deletions(-) diff --git a/qa/rpc-tests/test_framework/blockstore.py b/qa/rpc-tests/test_framework/blockstore.py index 4bc279032bf08..6120dd574b5dd 100644 --- a/qa/rpc-tests/test_framework/blockstore.py +++ b/qa/rpc-tests/test_framework/blockstore.py @@ -13,20 +13,31 @@ def __init__(self, datadir): self.blockDB = dbm.ndbm.open(datadir + "/blocks", 'c') self.currentBlock = 0 self.headers_map = dict() - + def close(self): self.blockDB.close() + def erase(self, blockhash): + del self.blockDB[repr(blockhash)] + + # lookup an entry and return the item as raw bytes def get(self, blockhash): - serialized_block = None + value = None try: - serialized_block = self.blockDB[repr(blockhash)] + value = self.blockDB[repr(blockhash)] except KeyError: return None - f = BytesIO(serialized_block) - ret = CBlock() - ret.deserialize(f) - ret.calc_sha256() + return value + + # lookup an entry and return it as a CBlock + def get_block(self, blockhash): + ret = None + serialized_block = self.get(blockhash) + if serialized_block is not None: + f = BytesIO(serialized_block) + ret = CBlock() + ret.deserialize(f) + ret.calc_sha256() return ret def get_header(self, blockhash): @@ -75,13 +86,16 @@ def add_block(self, block): def add_header(self, header): self.headers_map[header.sha256] = header + # lookup the hashes in "inv", and return p2p messages for delivering + # blocks found. def get_blocks(self, inv): responses = [] for i in inv: if (i.type == 2): # MSG_BLOCK - block = self.get(i.hash) - if block is not None: - responses.append(msg_block(block)) + data = self.get(i.hash) + if data is not None: + # Use msg_generic to avoid re-serialization + responses.append(msg_generic(b"block", data)) return responses def get_locator(self, current_tip=None): @@ -90,11 +104,11 @@ def get_locator(self, current_tip=None): r = [] counter = 0 step = 1 - lastBlock = self.get(current_tip) + lastBlock = self.get_block(current_tip) while lastBlock is not None: r.append(lastBlock.hashPrevBlock) for i in range(step): - lastBlock = self.get(lastBlock.hashPrevBlock) + lastBlock = self.get_block(lastBlock.hashPrevBlock) if lastBlock is None: break counter += 1 @@ -111,16 +125,23 @@ def __init__(self, datadir): def close(self): self.txDB.close() + # lookup an entry and return the item as raw bytes def get(self, txhash): - serialized_tx = None + value = None try: - serialized_tx = self.txDB[repr(txhash)] + value = self.txDB[repr(txhash)] except KeyError: return None - f = BytesIO(serialized_tx) - ret = CTransaction() - ret.deserialize(f) - ret.calc_sha256() + return value + + def get_transaction(self, txhash): + ret = None + serialized_tx = self.get(txhash) + if serialized_tx is not None: + f = BytesIO(serialized_tx) + ret = CTransaction() + ret.deserialize(f) + ret.calc_sha256() return ret def add_transaction(self, tx): @@ -136,5 +157,5 @@ def get_transactions(self, inv): if (i.type == 1): # MSG_TX tx = self.get(i.hash) if tx is not None: - responses.append(msg_tx(tx)) + responses.append(msg_generic(b"tx", tx)) return responses diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index 1617daa20008d..e85399c960bb7 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -556,6 +556,7 @@ def solve(self): self.nNonce += 1 self.rehash() + def __repr__(self): return "CBlock(nVersion=%i hashPrevBlock=%064x hashMerkleRoot=%064x nTime=%s nBits=%08x nNonce=%08x vtx=%s)" \ % (self.nVersion, self.hashPrevBlock, self.hashMerkleRoot, @@ -836,6 +837,18 @@ def serialize(self): def __repr__(self): return "msg_block(block=%s)" % (repr(self.block)) +# for cases where a user needs tighter control over what is sent over the wire +# note that the user must supply the name of the command, and the data +class msg_generic(object): + def __init__(self, command, data=None): + self.command = command + self.data = data + + def serialize(self): + return self.data + + def __repr__(self): + return "msg_generic()" class msg_getaddr(object): command = b"getaddr" From c2dd5a3c39156749e8ee24772d1fcb01404f2b6f Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Wed, 1 Jun 2016 12:29:03 -0400 Subject: [PATCH 0384/1802] FIX: correctly measure size of priority block --- src/miner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/miner.cpp b/src/miner.cpp index 1eab8f949d41d..99eb0a2ebd0f7 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -352,7 +352,7 @@ void BlockAssembler::addPriorityTxs() // If now that this txs is added we've surpassed our desired priority size // or have dropped below the AllowFreeThreshold, then we're done adding priority txs - if (nBlockSize + iter->GetTxSize() >= nBlockPrioritySize || !AllowFree(actualPriority)) { + if (nBlockSize >= nBlockPrioritySize || !AllowFree(actualPriority)) { return; } From 16cf85fa2c2da7ff73b2c72afcbb5de26a2bede2 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 1 Jun 2016 19:18:06 +0200 Subject: [PATCH 0385/1802] Revert "Include signal.h for sig_atomic_t in WIN32" This reverts commit 88f14b999cb70f6c556633f2889e698a05305158. --- src/util.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/util.h b/src/util.h index c6f8af4cdf07d..88a00d3ca1fcb 100644 --- a/src/util.h +++ b/src/util.h @@ -28,7 +28,9 @@ #include #include +#ifndef WIN32 #include +#endif static const bool DEFAULT_LOGTIMEMICROS = false; static const bool DEFAULT_LOGIPS = false; From a886dbf8e7b6b007153a53e8d8d1fd63b7fc9ee2 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 30 May 2016 15:39:37 +0200 Subject: [PATCH 0386/1802] Use std::atomic for fRequestShutdown and fReopenDebugLog --- src/init.cpp | 2 +- src/util.cpp | 2 +- src/util.h | 7 ++----- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 98c0894122783..9a22501859428 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -123,7 +123,7 @@ static const char* FEE_ESTIMATES_FILENAME="fee_estimates.dat"; // shutdown thing. // -volatile sig_atomic_t fRequestShutdown = false; +std::atomic fRequestShutdown(false); void StartShutdown() { diff --git a/src/util.cpp b/src/util.cpp index 80f2193016ef2..9a9209c62140b 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -113,7 +113,7 @@ string strMiscWarning; bool fLogTimestamps = DEFAULT_LOGTIMESTAMPS; bool fLogTimeMicros = DEFAULT_LOGTIMEMICROS; bool fLogIPs = DEFAULT_LOGIPS; -volatile sig_atomic_t fReopenDebugLog = false; +std::atomic fReopenDebugLog(false); CTranslationInterface translationInterface; /** Init OpenSSL library multithreading support */ diff --git a/src/util.h b/src/util.h index 88a00d3ca1fcb..ac4b947785f43 100644 --- a/src/util.h +++ b/src/util.h @@ -18,6 +18,7 @@ #include "tinyformat.h" #include "utiltime.h" +#include #include #include #include @@ -28,10 +29,6 @@ #include #include -#ifndef WIN32 -#include -#endif - static const bool DEFAULT_LOGTIMEMICROS = false; static const bool DEFAULT_LOGIPS = false; static const bool DEFAULT_LOGTIMESTAMPS = true; @@ -54,7 +51,7 @@ extern std::string strMiscWarning; extern bool fLogTimestamps; extern bool fLogTimeMicros; extern bool fLogIPs; -extern volatile sig_atomic_t fReopenDebugLog; +extern std::atomic fReopenDebugLog; extern CTranslationInterface translationInterface; extern const char * const BITCOIN_CONF_FILENAME; From c022e5b15dd0b26bb6ef77a382279987c2efa93f Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Wed, 1 Jun 2016 20:29:39 +0200 Subject: [PATCH 0387/1802] [Wallet] use constant for bip32 hardened key limit --- src/wallet/wallet.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index fdb46472a83a1..1c212d01476dd 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -42,6 +42,7 @@ bool bSpendZeroConfChange = DEFAULT_SPEND_ZEROCONF_CHANGE; bool fSendFreeTransactions = DEFAULT_SEND_FREE_TRANSACTIONS; const char * DEFAULT_WALLET_DAT = "wallet.dat"; +const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000; /** * Fees smaller than this (in satoshi) are considered zero fee (for transaction creation) @@ -112,16 +113,19 @@ CPubKey CWallet::GenerateNewKey() masterKey.SetMaster(key.begin(), key.size()); // derive m/0' - // use hardened derivation (child keys > 0x80000000 are hardened after bip32) - masterKey.Derive(accountKey, 0 | 0x80000000); + // use hardened derivation (child keys >= 0x80000000 are hardened after bip32) + masterKey.Derive(accountKey, BIP32_HARDENED_KEY_LIMIT); // derive m/0'/0' - accountKey.Derive(externalChainChildKey, 0 | 0x80000000); + accountKey.Derive(externalChainChildKey, BIP32_HARDENED_KEY_LIMIT); // derive child key at next index, skip keys already known to the wallet do { - externalChainChildKey.Derive(childKey, hdChain.nExternalChainCounter | 0x80000000); + // always derive hardened keys + // childIndex | BIP32_HARDENED_KEY_LIMIT = derive childIndex in hardened child-index-range + // example: 1 | BIP32_HARDENED_KEY_LIMIT == 0x80000001 == 2147483649 + externalChainChildKey.Derive(childKey, hdChain.nExternalChainCounter | BIP32_HARDENED_KEY_LIMIT); // increment childkey index hdChain.nExternalChainCounter++; } while(HaveKey(childKey.key.GetPubKey().GetID())); From 0cb0f2626e1553426e16a52fc6928d35824827f5 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 1 Jun 2016 18:05:09 -0400 Subject: [PATCH 0388/1802] build: out-of-tree fixups Don't glob the leveldb for dist. That means we need to enumerate the headers. --- Makefile.am | 10 ------- src/Makefile.am | 7 ++--- src/Makefile.leveldb.include | 56 ++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 14 deletions(-) diff --git a/Makefile.am b/Makefile.am index 5783c1fdd8f55..bfdf76568a304 100644 --- a/Makefile.am +++ b/Makefile.am @@ -53,18 +53,8 @@ COVERAGE_INFO = baseline_filtered_combined.info baseline.info block_test.info \ leveldb_baseline_filtered.info test_bitcoin_coverage.info test_bitcoin.info dist-hook: - -$(MAKE) -C $(top_distdir)/src/leveldb clean - -$(MAKE) -C $(top_distdir)/src/secp256k1 distclean -$(GIT) archive --format=tar HEAD -- src/clientversion.cpp | $(AMTAR) -C $(top_distdir) -xf - -distcheck-hook: - $(MKDIR_P) $(top_distdir)/_build/src/leveldb - cp -rf $(top_srcdir)/src/leveldb/* $(top_distdir)/_build/src/leveldb/ - -$(MAKE) -C $(top_distdir)/_build/src/leveldb clean - -distcleancheck: - @: - $(BITCOIN_WIN_INSTALLER): all-recursive $(MKDIR_P) $(top_builddir)/release STRIPPROG="$(STRIP)" $(INSTALL_STRIP_PROGRAM) $(BITCOIND_BIN) $(top_builddir)/release diff --git a/src/Makefile.am b/src/Makefile.am index ea49efe92d2af..c833272ff9db7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -417,8 +417,8 @@ CTAES_DIST += crypto/ctaes/ctaes.h CTAES_DIST += crypto/ctaes/README.md CTAES_DIST += crypto/ctaes/test.c -CLEANFILES = leveldb/libleveldb.a leveldb/libmemenv.a -CLEANFILES += $(EXTRA_LIBRARIES) +CLEANFILES = $(EXTRA_LIBRARIES) + CLEANFILES += *.gcda *.gcno CLEANFILES += compat/*.gcda compat/*.gcno CLEANFILES += consensus/*.gcda consensus/*.gcno @@ -434,10 +434,9 @@ CLEANFILES += zmq/*.gcda zmq/*.gcno DISTCLEANFILES = obj/build.h -EXTRA_DIST = leveldb $(CTAES_DIST) +EXTRA_DIST = $(CTAES_DIST) clean-local: - -$(MAKE) -C leveldb clean -$(MAKE) -C secp256k1 clean -$(MAKE) -C univalue clean -rm -f leveldb/*/*.gcda leveldb/*/*.gcno leveldb/helpers/memenv/*.gcda leveldb/helpers/memenv/*.gcno diff --git a/src/Makefile.leveldb.include b/src/Makefile.leveldb.include index 88bb0c19326f1..4b3cd6364a29b 100644 --- a/src/Makefile.leveldb.include +++ b/src/Makefile.leveldb.include @@ -26,6 +26,61 @@ leveldb_libleveldb_a_CPPFLAGS = $(AM_CPPFLAGS) $(LEVELDB_CPPFLAGS_INT) $(LEVELDB leveldb_libleveldb_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) leveldb_libleveldb_a_SOURCES= +leveldb_libleveldb_a_SOURCES += leveldb/port/atomic_pointer.h +leveldb_libleveldb_a_SOURCES += leveldb/port/port_example.h +leveldb_libleveldb_a_SOURCES += leveldb/port/port_posix.h +leveldb_libleveldb_a_SOURCES += leveldb/port/win/stdint.h +leveldb_libleveldb_a_SOURCES += leveldb/port/port.h +leveldb_libleveldb_a_SOURCES += leveldb/port/port_win.h +leveldb_libleveldb_a_SOURCES += leveldb/port/thread_annotations.h +leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/db.h +leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/options.h +leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/comparator.h +leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/filter_policy.h +leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/slice.h +leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/table_builder.h +leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/env.h +leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/c.h +leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/iterator.h +leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/cache.h +leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/dumpfile.h +leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/table.h +leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/write_batch.h +leveldb_libleveldb_a_SOURCES += leveldb/include/leveldb/status.h +leveldb_libleveldb_a_SOURCES += leveldb/db/log_format.h +leveldb_libleveldb_a_SOURCES += leveldb/db/memtable.h +leveldb_libleveldb_a_SOURCES += leveldb/db/version_set.h +leveldb_libleveldb_a_SOURCES += leveldb/db/write_batch_internal.h +leveldb_libleveldb_a_SOURCES += leveldb/db/filename.h +leveldb_libleveldb_a_SOURCES += leveldb/db/version_edit.h +leveldb_libleveldb_a_SOURCES += leveldb/db/dbformat.h +leveldb_libleveldb_a_SOURCES += leveldb/db/builder.h +leveldb_libleveldb_a_SOURCES += leveldb/db/log_writer.h +leveldb_libleveldb_a_SOURCES += leveldb/db/db_iter.h +leveldb_libleveldb_a_SOURCES += leveldb/db/skiplist.h +leveldb_libleveldb_a_SOURCES += leveldb/db/db_impl.h +leveldb_libleveldb_a_SOURCES += leveldb/db/table_cache.h +leveldb_libleveldb_a_SOURCES += leveldb/db/snapshot.h +leveldb_libleveldb_a_SOURCES += leveldb/db/log_reader.h +leveldb_libleveldb_a_SOURCES += leveldb/table/filter_block.h +leveldb_libleveldb_a_SOURCES += leveldb/table/block_builder.h +leveldb_libleveldb_a_SOURCES += leveldb/table/block.h +leveldb_libleveldb_a_SOURCES += leveldb/table/two_level_iterator.h +leveldb_libleveldb_a_SOURCES += leveldb/table/merger.h +leveldb_libleveldb_a_SOURCES += leveldb/table/format.h +leveldb_libleveldb_a_SOURCES += leveldb/table/iterator_wrapper.h +leveldb_libleveldb_a_SOURCES += leveldb/util/crc32c.h +leveldb_libleveldb_a_SOURCES += leveldb/util/arena.h +leveldb_libleveldb_a_SOURCES += leveldb/util/random.h +leveldb_libleveldb_a_SOURCES += leveldb/util/posix_logger.h +leveldb_libleveldb_a_SOURCES += leveldb/util/hash.h +leveldb_libleveldb_a_SOURCES += leveldb/util/histogram.h +leveldb_libleveldb_a_SOURCES += leveldb/util/coding.h +leveldb_libleveldb_a_SOURCES += leveldb/util/testutil.h +leveldb_libleveldb_a_SOURCES += leveldb/util/mutexlock.h +leveldb_libleveldb_a_SOURCES += leveldb/util/logging.h +leveldb_libleveldb_a_SOURCES += leveldb/util/testharness.h + leveldb_libleveldb_a_SOURCES += leveldb/db/builder.cc leveldb_libleveldb_a_SOURCES += leveldb/db/c.cc leveldb_libleveldb_a_SOURCES += leveldb/db/dbformat.cc @@ -76,3 +131,4 @@ endif leveldb_libmemenv_a_CPPFLAGS = $(leveldb_libleveldb_a_CPPFLAGS) leveldb_libmemenv_a_CXXFLAGS = $(leveldb_libleveldb_a_CXXFLAGS) leveldb_libmemenv_a_SOURCES = leveldb/helpers/memenv/memenv.cc +leveldb_libmemenv_a_SOURCES += leveldb/helpers/memenv/memenv.h From fc4ad0c7fcf2e5841756c9d1003f95c879ee5cd2 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 1 Jun 2016 18:06:40 -0400 Subject: [PATCH 0389/1802] build: more out-of-tree fixups - clear the __pycache__ during 'make clean' - Copy the qrc locale file to a temp location and remove it when finished (rcc expects everything to be in the same path) --- src/Makefile.am | 1 + src/Makefile.qt.include | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index c833272ff9db7..5e33c6a869d7a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -441,6 +441,7 @@ clean-local: -$(MAKE) -C univalue clean -rm -f leveldb/*/*.gcda leveldb/*/*.gcno leveldb/helpers/memenv/*.gcda leveldb/helpers/memenv/*.gcno -rm -f config.h + -rm -rf test/__pycache__ .rc.o: @test -f $(WINDRES) diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 3b39919441088..29e3a264ccc7c 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -400,9 +400,10 @@ translate: qt/bitcoinstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_QT_CPP) $(QT_QRC_LOCALE_CPP): $(QT_QRC_LOCALE) $(QT_QM) @test -f $(RCC) - @test -f $(@D)/$( $@ + @rm $(@D)/temp_$( Date: Wed, 1 Jun 2016 18:47:21 -0400 Subject: [PATCH 0390/1802] build: a few ugly hacks to get the rpc tests working out-of-tree - Link pull-tester/rpc-tests.py to the build dir - Add the build-dir's config to the python path so that tests can find it - The tests themselves are in srcdir - Clean up __pycache__ in 'make clean' --- Makefile.am | 1 + configure.ac | 1 + qa/pull-tester/rpc-tests.py | 3 ++- qa/pull-tester/tests_config.py.in | 1 + 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index bfdf76568a304..9957968f81888 100644 --- a/Makefile.am +++ b/Makefile.am @@ -228,3 +228,4 @@ CLEANFILES = $(OSX_DMG) $(BITCOIN_WIN_INSTALLER) clean-local: rm -rf coverage_percent.txt test_bitcoin.coverage/ total.coverage/ qa/tmp/ cache/ $(OSX_APP) + rm -rf qa/pull-tester/__pycache__ diff --git a/configure.ac b/configure.ac index a1c04daf53601..7f9ff20cd7be5 100644 --- a/configure.ac +++ b/configure.ac @@ -1060,6 +1060,7 @@ AC_SUBST(MINIUPNPC_LIBS) AC_CONFIG_FILES([Makefile src/Makefile share/setup.nsi share/qt/Info.plist src/test/buildenv.py]) AC_CONFIG_FILES([qa/pull-tester/run-bitcoind-for-test.sh],[chmod +x qa/pull-tester/run-bitcoind-for-test.sh]) AC_CONFIG_FILES([qa/pull-tester/tests_config.py],[chmod +x qa/pull-tester/tests_config.py]) +AC_CONFIG_LINKS([qa/pull-tester/rpc-tests.py:qa/pull-tester/rpc-tests.py]) dnl boost's m4 checks do something really nasty: they export these vars. As a dnl result, they leak into secp256k1's configure and crazy things happen. diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index f810f89a5991a..57a576f1c7bf0 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -29,6 +29,7 @@ import tempfile import re +sys.path.append("qa/pull-tester/") from tests_config import * BOLD = ("","") @@ -37,7 +38,7 @@ # terminal via ANSI escape sequences: BOLD = ('\033[0m', '\033[1m') -RPC_TESTS_DIR = BUILDDIR + '/qa/rpc-tests/' +RPC_TESTS_DIR = SRCDIR + '/qa/rpc-tests/' #If imported values are not defined then set to zero (or disabled) if 'ENABLE_WALLET' not in vars(): diff --git a/qa/pull-tester/tests_config.py.in b/qa/pull-tester/tests_config.py.in index 2356b5200ebfe..a0d0a3d98a86b 100644 --- a/qa/pull-tester/tests_config.py.in +++ b/qa/pull-tester/tests_config.py.in @@ -3,6 +3,7 @@ # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. +SRCDIR="@abs_top_srcdir@" BUILDDIR="@abs_top_builddir@" EXEEXT="@EXEEXT@" From 2b2d52ea3a2c48ce9a221a51bb0c8eef2068582b Mon Sep 17 00:00:00 2001 From: fanquake Date: Tue, 3 May 2016 20:42:42 +0800 Subject: [PATCH 0391/1802] [depends] Freetype 2.6.3 Update FreeType, and change the download location to gnu.org. This is the other official download location listed on freetype.org --- depends/packages/freetype.mk | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/depends/packages/freetype.mk b/depends/packages/freetype.mk index f7d6e0f9fc58d..7cea28ff0bbf9 100644 --- a/depends/packages/freetype.mk +++ b/depends/packages/freetype.mk @@ -1,8 +1,8 @@ package=freetype -$(package)_version=2.5.3 -$(package)_download_path=http://downloads.sourceforge.net/$(package) +$(package)_version=2.6.3 +$(package)_download_path=http://download.savannah.gnu.org/releases/$(package) $(package)_file_name=$(package)-$($(package)_version).tar.bz2 -$(package)_sha256_hash=c0848b29d52ef3ca27ad92e08351f023c5e24ce8cea7d8fe69fc96358e65f75e +$(package)_sha256_hash=371e707aa522acf5b15ce93f11183c725b8ed1ee8546d7b3af549863045863a2 define $(package)_set_vars $(package)_config_opts=--without-zlib --without-png --disable-static From 0385202befb3416c5d4a39c1665865de7b1e44df Mon Sep 17 00:00:00 2001 From: fanquake Date: Tue, 3 May 2016 20:51:29 +0800 Subject: [PATCH 0392/1802] [depends] ccache 3.2.5 --- depends/packages/native_ccache.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/depends/packages/native_ccache.mk b/depends/packages/native_ccache.mk index cc76f9a794655..9216e175983a9 100644 --- a/depends/packages/native_ccache.mk +++ b/depends/packages/native_ccache.mk @@ -1,8 +1,8 @@ package=native_ccache -$(package)_version=3.2.4 +$(package)_version=3.2.5 $(package)_download_path=http://samba.org/ftp/ccache $(package)_file_name=ccache-$($(package)_version).tar.bz2 -$(package)_sha256_hash=ffeb967edb549e67da0bd5f44f729a2022de9fdde65dfd80d2a7204d7f75332e +$(package)_sha256_hash=7a553809e90faf9de3a23ee9c5b5f786cfd4836bf502744bedb824a24bee1097 define $(package)_set_vars $(package)_config_opts= From bd3cbd53330e001603bfd4be4edfbdb9c952bb36 Mon Sep 17 00:00:00 2001 From: fanquake Date: Tue, 3 May 2016 20:52:10 +0800 Subject: [PATCH 0393/1802] [depends] ZeroMQ 4.1.4 --- depends/packages/zeromq.mk | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/depends/packages/zeromq.mk b/depends/packages/zeromq.mk index b3f18db056968..f8901f72c26c6 100644 --- a/depends/packages/zeromq.mk +++ b/depends/packages/zeromq.mk @@ -1,11 +1,11 @@ package=zeromq -$(package)_version=4.0.7 +$(package)_version=4.1.4 $(package)_download_path=http://download.zeromq.org $(package)_file_name=$(package)-$($(package)_version).tar.gz -$(package)_sha256_hash=e00b2967e074990d0538361cc79084a0a92892df2c6e7585da34e4c61ee47b03 +$(package)_sha256_hash=e99f44fde25c2e4cb84ce440f87ca7d3fe3271c2b8cfbc67d55e4de25e6fe378 define $(package)_set_vars - $(package)_config_opts=--without-documentation --disable-shared + $(package)_config_opts=--without-documentation --disable-shared --without-libsodium $(package)_config_opts_linux=--with-pic $(package)_cxxflags=-std=c++11 endef @@ -15,11 +15,11 @@ define $(package)_config_cmds endef define $(package)_build_cmds - $(MAKE) -C src + $(MAKE) libzmq.la endef define $(package)_stage_cmds - $(MAKE) -C src DESTDIR=$($(package)_staging_dir) install + $(MAKE) DESTDIR=$($(package)_staging_dir) install-libLTLIBRARIES install-includeHEADERS install-pkgconfigDATA endef define $(package)_postprocess_cmds From 87b8175d999e10082049afd1fb6440cf54d86f1e Mon Sep 17 00:00:00 2001 From: fanquake Date: Tue, 3 May 2016 20:52:34 +0800 Subject: [PATCH 0394/1802] [depends] Latest config.guess & config.sub --- depends/config.guess | 37 +++++++++++++++++++++---------------- depends/config.sub | 6 ++++-- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/depends/config.guess b/depends/config.guess index 373a659a06760..c4bd827a7bedc 100755 --- a/depends/config.guess +++ b/depends/config.guess @@ -2,7 +2,7 @@ # Attempt to guess a canonical system name. # Copyright 1992-2016 Free Software Foundation, Inc. -timestamp='2016-02-11' +timestamp='2016-05-15' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -186,9 +186,12 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. + # to ELF recently (or will in the future) and ABI. case "${UNAME_MACHINE_ARCH}" in - arm*|earm*|i386|m68k|ns32k|sh3*|sparc|vax) + earm*) + os=netbsdelf + ;; + arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ @@ -386,7 +389,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # This test works for both compilers. if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH=x86_64 @@ -684,7 +687,7 @@ EOF exit (0); } EOF - (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac @@ -701,7 +704,7 @@ EOF # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 - if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH=hppa2.0w @@ -900,7 +903,7 @@ EOF exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix @@ -1276,6 +1279,9 @@ EOF SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; + SX-ACE:SUPER-UX:*:*) + echo sxace-nec-superux${UNAME_RELEASE} + exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; @@ -1291,7 +1297,7 @@ EOF if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in @@ -1386,7 +1392,7 @@ EOF echo i386-pc-xenix exit ;; i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'` exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos @@ -1405,18 +1411,17 @@ esac cat >&2 < in order to provide the needed -information to handle your system. +If $0 has already been updated, send the following data and any +information you think might be pertinent to config-patches@gnu.org to +provide the necessary information to handle your system. config.guess timestamp = $timestamp diff --git a/depends/config.sub b/depends/config.sub index 6223dde931918..6d86a1e2f77b3 100755 --- a/depends/config.sub +++ b/depends/config.sub @@ -2,7 +2,7 @@ # Configuration validation subroutine script. # Copyright 1992-2016 Free Software Foundation, Inc. -timestamp='2016-01-01' +timestamp='2016-05-10' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -1399,7 +1399,7 @@ case $os in | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ - | -onefs* | -tirtos*) + | -onefs* | -tirtos* | -phoenix*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1531,6 +1531,8 @@ case $os in ;; -nacl*) ;; + -ios) + ;; -none) ;; *) From 3e0587bf816b9912126ed74ba173edf3d601d2ad Mon Sep 17 00:00:00 2001 From: fanquake Date: Tue, 10 May 2016 12:50:56 +0800 Subject: [PATCH 0395/1802] [depends] miniupnpc 2.0 --- depends/packages/miniupnpc.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/depends/packages/miniupnpc.mk b/depends/packages/miniupnpc.mk index 45fa03631f89d..e34cf7be2f1bf 100644 --- a/depends/packages/miniupnpc.mk +++ b/depends/packages/miniupnpc.mk @@ -1,8 +1,8 @@ package=miniupnpc -$(package)_version=1.9.20160209 +$(package)_version=2.0 $(package)_download_path=http://miniupnp.free.fr/files $(package)_file_name=$(package)-$($(package)_version).tar.gz -$(package)_sha256_hash=572171eacc1d72537ce47b6f4571260757ab7bcfdaf54c3a55c7f88594d94b6f +$(package)_sha256_hash=d434ceb8986efbe199c5ca53f90ed53eab290b1e6d0530b717eb6fa49d61f93b define $(package)_set_vars $(package)_build_opts=CC="$($(package)_cc)" From 6a4cf16e2bea6e35507fd90846fa4f2441ba93af Mon Sep 17 00:00:00 2001 From: fanquake Date: Thu, 12 May 2016 19:44:45 +0800 Subject: [PATCH 0396/1802] [depends] expat 2.1.1 --- depends/packages/expat.mk | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/depends/packages/expat.mk b/depends/packages/expat.mk index 1ac443537420b..bd2927563850b 100644 --- a/depends/packages/expat.mk +++ b/depends/packages/expat.mk @@ -1,8 +1,8 @@ package=expat -$(package)_version=2.1.0 -$(package)_download_path=http://sourceforge.net/projects/expat/files/expat/$($(package)_version) -$(package)_file_name=$(package)-$($(package)_version).tar.gz -$(package)_sha256_hash=823705472f816df21c8f6aa026dd162b280806838bb55b3432b0fb1fcca7eb86 +$(package)_version=2.1.1 +$(package)_download_path=https://downloads.sourceforge.net/project/expat/expat/$($(package)_version) +$(package)_file_name=$(package)-$($(package)_version).tar.bz2 +$(package)_sha256_hash=aff584e5a2f759dcfc6d48671e9529f6afe1e30b0cd6a4cec200cbe3f793de67 define $(package)_set_vars $(package)_config_opts=--disable-static From 92e37a368900542700480143af278f66cbe558db Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 1 Jun 2016 22:19:29 -0400 Subject: [PATCH 0397/1802] build: fix out-of-tree 'make deploy' for osx The plist is generated, lives in builddir. --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 9957968f81888..b93748e324e24 100644 --- a/Makefile.am +++ b/Makefile.am @@ -28,7 +28,7 @@ OSX_DSSTORE_GEN=$(top_srcdir)/contrib/macdeploy/custom_dsstore.py OSX_DEPLOY_SCRIPT=$(top_srcdir)/contrib/macdeploy/macdeployqtplus OSX_FANCY_PLIST=$(top_srcdir)/contrib/macdeploy/fancy.plist OSX_INSTALLER_ICONS=$(top_srcdir)/src/qt/res/icons/bitcoin.icns -OSX_PLIST=$(top_srcdir)/share/qt/Info.plist #not installed +OSX_PLIST=$(top_builddir)/share/qt/Info.plist #not installed OSX_QT_TRANSLATIONS = da,de,es,hu,ru,uk,zh_CN,zh_TW DIST_DOCS = $(wildcard doc/*.md) $(wildcard doc/release-notes/*.md) From 142ffc7e6136607b9a31709f31256f360b26588b Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 1 Jun 2016 19:24:29 -0400 Subject: [PATCH 0398/1802] travis: use out-of-tree build --- .travis.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index bc2c7faf7ee57..f5e306f0a6b85 100644 --- a/.travis.yml +++ b/.travis.yml @@ -72,10 +72,8 @@ script: - BITCOIN_CONFIG_ALL="--disable-dependency-tracking --prefix=$TRAVIS_BUILD_DIR/depends/$HOST --bindir=$OUTDIR/bin --libdir=$OUTDIR/lib" - depends/$HOST/native/bin/ccache --max-size=$CCACHE_SIZE - test -n "$USE_SHELL" && eval '"$USE_SHELL" -c "./autogen.sh"' || ./autogen.sh - - ./configure --cache-file=config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false) - - make distdir PACKAGE=bitcoin VERSION=$HOST - - cd bitcoin-$HOST - - ./configure --cache-file=../config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false) + - mkdir build && cd build + - ../configure $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false) - make $MAKEJOBS $GOAL || ( echo "Build failure. Verbose build follows." && make $GOAL V=1 ; false ) - export LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/depends/$HOST/lib - if [ "$RUN_TESTS" = "true" ]; then make $MAKEJOBS check VERBOSE=1; fi From 9dfaa1cb70670eb0a4c82a7ddfcba71ba5ebea94 Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Thu, 2 Jun 2016 06:00:59 -0700 Subject: [PATCH 0399/1802] Improve CWallet API with new AccountMove function. --- src/wallet/rpcwallet.cpp | 28 +--------------------------- src/wallet/wallet.cpp | 34 ++++++++++++++++++++++++++++++++++ src/wallet/wallet.h | 1 + 3 files changed, 36 insertions(+), 27 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index b9f086b09205e..f7d5210eb095d 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -804,33 +804,7 @@ UniValue movecmd(const UniValue& params, bool fHelp) if (params.size() > 4) strComment = params[4].get_str(); - CWalletDB walletdb(pwalletMain->strWalletFile); - if (!walletdb.TxnBegin()) - throw JSONRPCError(RPC_DATABASE_ERROR, "database error"); - - int64_t nNow = GetAdjustedTime(); - - // Debit - CAccountingEntry debit; - debit.nOrderPos = pwalletMain->IncOrderPosNext(&walletdb); - debit.strAccount = strFrom; - debit.nCreditDebit = -nAmount; - debit.nTime = nNow; - debit.strOtherAccount = strTo; - debit.strComment = strComment; - pwalletMain->AddAccountingEntry(debit, walletdb); - - // Credit - CAccountingEntry credit; - credit.nOrderPos = pwalletMain->IncOrderPosNext(&walletdb); - credit.strAccount = strTo; - credit.nCreditDebit = nAmount; - credit.nTime = nNow; - credit.strOtherAccount = strFrom; - credit.strComment = strComment; - pwalletMain->AddAccountingEntry(credit, walletdb); - - if (!walletdb.TxnCommit()) + if (!pwalletMain->AccountMove(strFrom, strTo, nAmount, strComment)) throw JSONRPCError(RPC_DATABASE_ERROR, "database error"); return true; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index da0d6f272bfef..482eb6aa65d7d 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -606,6 +606,40 @@ int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb) return nRet; } +bool CWallet::AccountMove(std::string strFrom, std::string strTo, CAmount nAmount, std::string strComment) +{ + CWalletDB walletdb(strWalletFile); + if (!walletdb.TxnBegin()) + return false; + + int64_t nNow = GetAdjustedTime(); + + // Debit + CAccountingEntry debit; + debit.nOrderPos = IncOrderPosNext(&walletdb); + debit.strAccount = strFrom; + debit.nCreditDebit = -nAmount; + debit.nTime = nNow; + debit.strOtherAccount = strTo; + debit.strComment = strComment; + AddAccountingEntry(debit, walletdb); + + // Credit + CAccountingEntry credit; + credit.nOrderPos = IncOrderPosNext(&walletdb); + credit.strAccount = strTo; + credit.nCreditDebit = nAmount; + credit.nTime = nNow; + credit.strOtherAccount = strFrom; + credit.strComment = strComment; + AddAccountingEntry(credit, walletdb); + + if (!walletdb.TxnCommit()) + return false; + + return true; +} + void CWallet::MarkDirty() { { diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index b2180a5a26bb8..9fb2eba23c02a 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -718,6 +718,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface * @return next transaction order id */ int64_t IncOrderPosNext(CWalletDB *pwalletdb = NULL); + bool AccountMove(std::string strFrom, std::string strTo, CAmount nAmount, std::string strComment = ""); void MarkDirty(); bool AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletDB* pwalletdb); From 595b22e5c0bf1c3e8ee73aea2f28397c12046a60 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 14 Mar 2016 18:55:19 +0100 Subject: [PATCH 0400/1802] Stop treating importaddress'ed scripts as change Before this, if someone imported a scriptPubKey directly (in hex form) using importaddress, outputs sending to it would be treated as change, as the corresponding CTxDestination was not added to the address book. Fix this by trying to detect scriptPubKeys that are in fact convertible to a CTxDestination and add them anyway. Add a warning to the RPC help to warn against importing raw non-standard scripts. --- src/wallet/rpcdump.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index bb40cf724536a..70a8462da0d32 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -167,6 +167,11 @@ void ImportScript(const CScript& script, const string& strLabel, bool isRedeemSc if (!pwalletMain->HaveCScript(script) && !pwalletMain->AddCScript(script)) throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2sh redeemScript to wallet"); ImportAddress(CBitcoinAddress(CScriptID(script)), strLabel); + } else { + CTxDestination destination; + if (ExtractDestination(script, destination)) { + pwalletMain->SetAddressBook(destination, strLabel, "receive"); + } } } @@ -195,6 +200,8 @@ UniValue importaddress(const UniValue& params, bool fHelp) "4. p2sh (boolean, optional, default=false) Add the P2SH version of the script as well\n" "\nNote: This call can take minutes to complete if rescan is true.\n" "If you have the full public key, you should call importpubkey instead of this.\n" + "\nNote: If you import a non-standard raw script in hex form, outputs sending to it will be treated\n" + "as change, and not show up in many RPCs.\n" "\nExamples:\n" "\nImport a script with rescan\n" + HelpExampleCli("importaddress", "\"myscript\"") + From f45f51e3ae4fca24bc49474ca61c3262186c447d Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 13 May 2016 04:49:19 +0200 Subject: [PATCH 0401/1802] Fix interrupted HTTP RPC connection workaround for Python 3.5+ --- qa/rpc-tests/test_framework/authproxy.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/qa/rpc-tests/test_framework/authproxy.py b/qa/rpc-tests/test_framework/authproxy.py index e5f7ab3656167..95b2be658cffe 100644 --- a/qa/rpc-tests/test_framework/authproxy.py +++ b/qa/rpc-tests/test_framework/authproxy.py @@ -124,6 +124,11 @@ def _request(self, method, path, postdata): return self._get_response() else: raise + except BrokenPipeError: + # Python 3.5+ raises this instead of BadStatusLine when the connection was reset + self.__conn.close() + self.__conn.request(method, path, postdata, headers) + return self._get_response() def __call__(self, *args): AuthServiceProxy.__id_count += 1 From 291f8aa5daf80eed56d6cefa3d410652b412150a Mon Sep 17 00:00:00 2001 From: mrbandrews Date: Thu, 2 Jun 2016 14:42:09 -0400 Subject: [PATCH 0402/1802] Continuing port of java comptool --- qa/rpc-tests/p2p-fullblocktest.py | 1097 +++++++++++++++++++-- qa/rpc-tests/test_framework/blocktools.py | 23 +- qa/rpc-tests/test_framework/mininode.py | 1 - 3 files changed, 1010 insertions(+), 111 deletions(-) diff --git a/qa/rpc-tests/p2p-fullblocktest.py b/qa/rpc-tests/p2p-fullblocktest.py index aa0501c5e9260..19b90d4db11eb 100755 --- a/qa/rpc-tests/p2p-fullblocktest.py +++ b/qa/rpc-tests/p2p-fullblocktest.py @@ -9,7 +9,8 @@ from test_framework.blocktools import * import time from test_framework.key import CECKey -from test_framework.script import CScript, SignatureHash, SIGHASH_ALL, OP_TRUE, OP_FALSE +from test_framework.script import * +import struct class PreviousSpendableOutput(object): def __init__(self, tx = CTransaction(), n = -1): @@ -24,10 +25,36 @@ def __init__(self, tx = CTransaction(), n = -1): each test. ''' +def hash160(s): + return hashlib.new('ripemd160', sha256(s)).digest() + +# Use this class for tests that require behavior other than normal "mininode" behavior. +# For now, it is used to serialize a bloated varint (b64). +class CBrokenBlock(CBlock): + def __init__(self, header=None): + super(CBrokenBlock, self).__init__(header) + + def initialize(self, base_block): + self.vtx = copy.deepcopy(base_block.vtx) + self.hashMerkleRoot = self.calc_merkle_root() + + def serialize(self): + r = b"" + r += super(CBlock, self).serialize() + r += struct.pack(" b1 (0) -> b2 (1) - out0 = get_spendable_output() - block(1, spend=out0) + block(1, spend=out[0]) save_spendable_output() yield accepted() - out1 = get_spendable_output() - b2 = block(2, spend=out1) + block(2, spend=out[1]) yield accepted() - + save_spendable_output() # so fork like this: - # + # # genesis -> b1 (0) -> b2 (1) # \-> b3 (1) - # + # # Nothing should happen at this point. We saw b2 first so it takes priority. tip(1) - b3 = block(3, spend=out1) - txout_b3 = PreviousSpendableOutput(b3.vtx[1], 1) + b3 = block(3, spend=out[1]) + txout_b3 = PreviousSpendableOutput(b3.vtx[1], 0) yield rejected() # Now we add another block to make the alternative chain longer. - # + # # genesis -> b1 (0) -> b2 (1) # \-> b3 (1) -> b4 (2) - out2 = get_spendable_output() - block(4, spend=out2) + block(4, spend=out[2]) yield accepted() @@ -197,46 +232,41 @@ def update_block(block_number, new_transactions): # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3) # \-> b3 (1) -> b4 (2) tip(2) - block(5, spend=out2) + block(5, spend=out[2]) save_spendable_output() yield rejected() - out3 = get_spendable_output() - block(6, spend=out3) + block(6, spend=out[3]) yield accepted() - # Try to create a fork that double-spends # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3) # \-> b7 (2) -> b8 (4) # \-> b3 (1) -> b4 (2) tip(5) - block(7, spend=out2) + block(7, spend=out[2]) yield rejected() - out4 = get_spendable_output() - block(8, spend=out4) + block(8, spend=out[4]) yield rejected() - # Try to create a block that has too much fee # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3) # \-> b9 (4) # \-> b3 (1) -> b4 (2) tip(6) - block(9, spend=out4, additional_coinbase_value=1) + block(9, spend=out[4], additional_coinbase_value=1) yield rejected(RejectResult(16, b'bad-cb-amount')) - # Create a fork that ends in a block with too much fee (the one that causes the reorg) # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3) # \-> b10 (3) -> b11 (4) # \-> b3 (1) -> b4 (2) tip(5) - block(10, spend=out3) + block(10, spend=out[3]) yield rejected() - block(11, spend=out4, additional_coinbase_value=1) + block(11, spend=out[4], additional_coinbase_value=1) yield rejected(RejectResult(16, b'bad-cb-amount')) @@ -246,19 +276,17 @@ def update_block(block_number, new_transactions): # (b12 added last) # \-> b3 (1) -> b4 (2) tip(5) - b12 = block(12, spend=out3) + b12 = block(12, spend=out[3]) save_spendable_output() - #yield TestInstance([[b12, False]]) - b13 = block(13, spend=out4) + b13 = block(13, spend=out[4]) # Deliver the block header for b12, and the block b13. # b13 should be accepted but the tip won't advance until b12 is delivered. yield TestInstance([[CBlockHeader(b12), None], [b13, False]]) save_spendable_output() - out5 = get_spendable_output() # b14 is invalid, but the node won't know that until it tries to connect # Tip still can't advance because b12 is missing - block(14, spend=out5, additional_coinbase_value=1) + block(14, spend=out[5], additional_coinbase_value=1) yield rejected() yield TestInstance([[b12, True, b13.sha256]]) # New tip should be b13. @@ -267,18 +295,18 @@ def update_block(block_number, new_transactions): # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3) # \-> b12 (3) -> b13 (4) -> b15 (5) -> b16 (6) # \-> b3 (1) -> b4 (2) - + # Test that a block with a lot of checksigs is okay - lots_of_checksigs = CScript([OP_CHECKSIG] * (1000000 // 50 - 1)) + lots_of_checksigs = CScript([OP_CHECKSIG] * (MAX_BLOCK_SIGOPS - 1)) tip(13) - block(15, spend=out5, script=lots_of_checksigs) + block(15, spend=out[5], script=lots_of_checksigs) yield accepted() + save_spendable_output() # Test that a block with too many checksigs is rejected - out6 = get_spendable_output() - too_many_checksigs = CScript([OP_CHECKSIG] * (1000000 // 50)) - block(16, spend=out6, script=too_many_checksigs) + too_many_checksigs = CScript([OP_CHECKSIG] * (MAX_BLOCK_SIGOPS)) + block(16, spend=out[6], script=too_many_checksigs) yield rejected(RejectResult(16, b'bad-blk-sigops')) @@ -299,7 +327,7 @@ def update_block(block_number, new_transactions): block(18, spend=txout_b3) yield rejected() - block(19, spend=out6) + block(19, spend=out[6]) yield rejected() # Attempt to spend a coinbase at depth too low @@ -307,8 +335,7 @@ def update_block(block_number, new_transactions): # \-> b12 (3) -> b13 (4) -> b15 (5) -> b20 (7) # \-> b3 (1) -> b4 (2) tip(15) - out7 = get_spendable_output() - block(20, spend=out7) + block(20, spend=out[7]) yield rejected(RejectResult(16, b'bad-txns-premature-spend-of-coinbase')) # Attempt to spend a coinbase at depth too low (on a fork this time) @@ -317,10 +344,10 @@ def update_block(block_number, new_transactions): # \-> b21 (6) -> b22 (5) # \-> b3 (1) -> b4 (2) tip(13) - block(21, spend=out6) + block(21, spend=out[6]) yield rejected() - block(22, spend=out5) + block(22, spend=out[5]) yield rejected() # Create a block on either side of MAX_BLOCK_SIZE and make sure its accepted/rejected @@ -329,21 +356,21 @@ def update_block(block_number, new_transactions): # \-> b24 (6) -> b25 (7) # \-> b3 (1) -> b4 (2) tip(15) - b23 = block(23, spend=out6) - old_hash = b23.sha256 + b23 = block(23, spend=out[6]) tx = CTransaction() script_length = MAX_BLOCK_SIZE - len(b23.serialize()) - 69 script_output = CScript([b'\x00' * script_length]) tx.vout.append(CTxOut(0, script_output)) - tx.vin.append(CTxIn(COutPoint(b23.vtx[1].sha256, 1))) + tx.vin.append(CTxIn(COutPoint(b23.vtx[1].sha256, 0))) b23 = update_block(23, [tx]) # Make sure the math above worked out to produce a max-sized block assert_equal(len(b23.serialize()), MAX_BLOCK_SIZE) yield accepted() + save_spendable_output() # Make the next block one byte bigger and check that it fails tip(15) - b24 = block(24, spend=out6) + b24 = block(24, spend=out[6]) script_length = MAX_BLOCK_SIZE - len(b24.serialize()) - 69 script_output = CScript([b'\x00' * (script_length+1)]) tx.vout = [CTxOut(0, script_output)] @@ -351,7 +378,7 @@ def update_block(block_number, new_transactions): assert_equal(len(b24.serialize()), MAX_BLOCK_SIZE+1) yield rejected(RejectResult(16, b'bad-blk-length')) - b25 = block(25, spend=out7) + block(25, spend=out[7]) yield rejected() # Create blocks with a coinbase input script size out of range @@ -360,7 +387,7 @@ def update_block(block_number, new_transactions): # \-> ... (6) -> ... (7) # \-> b3 (1) -> b4 (2) tip(15) - b26 = block(26, spend=out6) + b26 = block(26, spend=out[6]) b26.vtx[0].vin[0].scriptSig = b'\x00' b26.vtx[0].rehash() # update_block causes the merkle root to get updated, even with no new @@ -369,23 +396,20 @@ def update_block(block_number, new_transactions): yield rejected(RejectResult(16, b'bad-cb-length')) # Extend the b26 chain to make sure bitcoind isn't accepting b26 - b27 = block(27, spend=out7) - yield rejected() + b27 = block(27, spend=out[7]) + yield rejected(RejectResult(16, b'bad-prevblk')) # Now try a too-large-coinbase script tip(15) - b28 = block(28, spend=out6) + b28 = block(28, spend=out[6]) b28.vtx[0].vin[0].scriptSig = b'\x00' * 101 b28.vtx[0].rehash() b28 = update_block(28, []) yield rejected(RejectResult(16, b'bad-cb-length')) - # Extend the b28 chain to make sure bitcoind isn't accepted b28 - b29 = block(29, spend=out7) - # TODO: Should get a reject message back with "bad-prevblk", except - # there's a bug that prevents this from being detected. Just note - # failure for now, and add the reject result later. - yield rejected() + # Extend the b28 chain to make sure bitcoind isn't accepting b28 + b29 = block(29, spend=out[7]) + yield rejected(RejectResult(16, b'bad-prevblk')) # b30 has a max-sized coinbase scriptSig. tip(23) @@ -394,6 +418,867 @@ def update_block(block_number, new_transactions): b30.vtx[0].rehash() b30 = update_block(30, []) yield accepted() + save_spendable_output() + + # b31 - b35 - check sigops of OP_CHECKMULTISIG / OP_CHECKMULTISIGVERIFY / OP_CHECKSIGVERIFY + # + # genesis -> ... -> b30 (7) -> b31 (8) -> b33 (9) -> b35 (10) + # \-> b36 (11) + # \-> b34 (10) + # \-> b32 (9) + # + + # MULTISIG: each op code counts as 20 sigops. To create the edge case, pack another 19 sigops at the end. + lots_of_multisigs = CScript([OP_CHECKMULTISIG] * ((MAX_BLOCK_SIGOPS-1) // 20) + [OP_CHECKSIG] * 19) + b31 = block(31, spend=out[8], script=lots_of_multisigs) + assert_equal(get_legacy_sigopcount_block(b31), MAX_BLOCK_SIGOPS) + yield accepted() + save_spendable_output() + + # this goes over the limit because the coinbase has one sigop + too_many_multisigs = CScript([OP_CHECKMULTISIG] * (MAX_BLOCK_SIGOPS // 20)) + b32 = block(32, spend=out[9], script=too_many_multisigs) + assert_equal(get_legacy_sigopcount_block(b32), MAX_BLOCK_SIGOPS + 1) + yield rejected(RejectResult(16, b'bad-blk-sigops')) + + + # CHECKMULTISIGVERIFY + tip(31) + lots_of_multisigs = CScript([OP_CHECKMULTISIGVERIFY] * ((MAX_BLOCK_SIGOPS-1) // 20) + [OP_CHECKSIG] * 19) + block(33, spend=out[9], script=lots_of_multisigs) + yield accepted() + save_spendable_output() + + too_many_multisigs = CScript([OP_CHECKMULTISIGVERIFY] * (MAX_BLOCK_SIGOPS // 20)) + block(34, spend=out[10], script=too_many_multisigs) + yield rejected(RejectResult(16, b'bad-blk-sigops')) + + + # CHECKSIGVERIFY + tip(33) + lots_of_checksigs = CScript([OP_CHECKSIGVERIFY] * (MAX_BLOCK_SIGOPS - 1)) + b35 = block(35, spend=out[10], script=lots_of_checksigs) + yield accepted() + save_spendable_output() + + too_many_checksigs = CScript([OP_CHECKSIGVERIFY] * (MAX_BLOCK_SIGOPS)) + block(36, spend=out[11], script=too_many_checksigs) + yield rejected(RejectResult(16, b'bad-blk-sigops')) + + + # Check spending of a transaction in a block which failed to connect + # + # b6 (3) + # b12 (3) -> b13 (4) -> b15 (5) -> b23 (6) -> b30 (7) -> b31 (8) -> b33 (9) -> b35 (10) + # \-> b37 (11) + # \-> b38 (11/37) + # + + # save 37's spendable output, but then double-spend out11 to invalidate the block + tip(35) + b37 = block(37, spend=out[11]) + txout_b37 = PreviousSpendableOutput(b37.vtx[1], 0) + tx = create_and_sign_tx(out[11].tx, out[11].n, 0) + b37 = update_block(37, [tx]) + yield rejected(RejectResult(16, b'bad-txns-inputs-missingorspent')) + + # attempt to spend b37's first non-coinbase tx, at which point b37 was still considered valid + tip(35) + block(38, spend=txout_b37) + yield rejected(RejectResult(16, b'bad-txns-inputs-missingorspent')) + + # Check P2SH SigOp counting + # + # + # 13 (4) -> b15 (5) -> b23 (6) -> b30 (7) -> b31 (8) -> b33 (9) -> b35 (10) -> b39 (11) -> b41 (12) + # \-> b40 (12) + # + # b39 - create some P2SH outputs that will require 6 sigops to spend: + # + # redeem_script = COINBASE_PUBKEY, (OP_2DUP+OP_CHECKSIGVERIFY) * 5, OP_CHECKSIG + # p2sh_script = OP_HASH160, ripemd160(sha256(script)), OP_EQUAL + # + tip(35) + b39 = block(39) + b39_outputs = 0 + b39_sigops_per_output = 6 + + # Build the redeem script, hash it, use hash to create the p2sh script + redeem_script = CScript([self.coinbase_pubkey] + [OP_2DUP, OP_CHECKSIGVERIFY]*5 + [OP_CHECKSIG]) + redeem_script_hash = hash160(redeem_script) + p2sh_script = CScript([OP_HASH160, redeem_script_hash, OP_EQUAL]) + + # Create a transaction that spends one satoshi to the p2sh_script, the rest to OP_TRUE + # This must be signed because it is spending a coinbase + spend = out[11] + tx = create_tx(spend.tx, spend.n, 1, p2sh_script) + tx.vout.append(CTxOut(spend.tx.vout[spend.n].nValue - 1, CScript([OP_TRUE]))) + self.sign_tx(tx, spend.tx, spend.n) + tx.rehash() + b39 = update_block(39, [tx]) + b39_outputs += 1 + + # Until block is full, add tx's with 1 satoshi to p2sh_script, the rest to OP_TRUE + tx_new = None + tx_last = tx + total_size=len(b39.serialize()) + while(total_size < MAX_BLOCK_SIZE): + tx_new = create_tx(tx_last, 1, 1, p2sh_script) + tx_new.vout.append(CTxOut(tx_last.vout[1].nValue - 1, CScript([OP_TRUE]))) + tx_new.rehash() + total_size += len(tx_new.serialize()) + if total_size >= MAX_BLOCK_SIZE: + break + b39.vtx.append(tx_new) # add tx to block + tx_last = tx_new + b39_outputs += 1 + + b39 = update_block(39, []) + yield accepted() + save_spendable_output() + + + # Test sigops in P2SH redeem scripts + # + # b40 creates 3333 tx's spending the 6-sigop P2SH outputs from b39 for a total of 19998 sigops. + # The first tx has one sigop and then at the end we add 2 more to put us just over the max. + # + # b41 does the same, less one, so it has the maximum sigops permitted. + # + tip(39) + b40 = block(40, spend=out[12]) + sigops = get_legacy_sigopcount_block(b40) + numTxes = (MAX_BLOCK_SIGOPS - sigops) // b39_sigops_per_output + assert_equal(numTxes <= b39_outputs, True) + + lastOutpoint = COutPoint(b40.vtx[1].sha256, 0) + new_txs = [] + for i in range(1, numTxes+1): + tx = CTransaction() + tx.vout.append(CTxOut(1, CScript([OP_TRUE]))) + tx.vin.append(CTxIn(lastOutpoint, b'')) + # second input is corresponding P2SH output from b39 + tx.vin.append(CTxIn(COutPoint(b39.vtx[i].sha256, 0), b'')) + # Note: must pass the redeem_script (not p2sh_script) to the signature hash function + (sighash, err) = SignatureHash(redeem_script, tx, 1, SIGHASH_ALL) + sig = self.coinbase_key.sign(sighash) + bytes(bytearray([SIGHASH_ALL])) + scriptSig = CScript([sig, redeem_script]) + + tx.vin[1].scriptSig = scriptSig + tx.rehash() + new_txs.append(tx) + lastOutpoint = COutPoint(tx.sha256, 0) + + b40_sigops_to_fill = MAX_BLOCK_SIGOPS - (numTxes * b39_sigops_per_output + sigops) + 1 + tx = CTransaction() + tx.vin.append(CTxIn(lastOutpoint, b'')) + tx.vout.append(CTxOut(1, CScript([OP_CHECKSIG] * b40_sigops_to_fill))) + tx.rehash() + new_txs.append(tx) + update_block(40, new_txs) + yield rejected(RejectResult(16, b'bad-blk-sigops')) + + # same as b40, but one less sigop + tip(39) + b41 = block(41, spend=None) + update_block(41, b40.vtx[1:-1]) + b41_sigops_to_fill = b40_sigops_to_fill - 1 + tx = CTransaction() + tx.vin.append(CTxIn(lastOutpoint, b'')) + tx.vout.append(CTxOut(1, CScript([OP_CHECKSIG] * b41_sigops_to_fill))) + tx.rehash() + update_block(41, [tx]) + yield accepted() + + # Fork off of b39 to create a constant base again + # + # b23 (6) -> b30 (7) -> b31 (8) -> b33 (9) -> b35 (10) -> b39 (11) -> b42 (12) -> b43 (13) + # \-> b41 (12) + # + tip(39) + block(42, spend=out[12]) + yield rejected() + save_spendable_output() + + block(43, spend=out[13]) + yield accepted() + save_spendable_output() + + + # Test a number of really invalid scenarios + # + # -> b31 (8) -> b33 (9) -> b35 (10) -> b39 (11) -> b42 (12) -> b43 (13) -> b44 (14) + # \-> ??? (15) + + # The next few blocks are going to be created "by hand" since they'll do funky things, such as having + # the first transaction be non-coinbase, etc. The purpose of b44 is to make sure this works. + height = self.block_heights[self.tip.sha256] + 1 + coinbase = create_coinbase(height, self.coinbase_pubkey) + b44 = CBlock() + b44.nTime = self.tip.nTime + 1 + b44.hashPrevBlock = self.tip.sha256 + b44.nBits = 0x207fffff + b44.vtx.append(coinbase) + b44.hashMerkleRoot = b44.calc_merkle_root() + b44.solve() + self.tip = b44 + self.block_heights[b44.sha256] = height + self.blocks[44] = b44 + yield accepted() + + # A block with a non-coinbase as the first tx + non_coinbase = create_tx(out[15].tx, out[15].n, 1) + b45 = CBlock() + b45.nTime = self.tip.nTime + 1 + b45.hashPrevBlock = self.tip.sha256 + b45.nBits = 0x207fffff + b45.vtx.append(non_coinbase) + b45.hashMerkleRoot = b45.calc_merkle_root() + b45.calc_sha256() + b45.solve() + self.block_heights[b45.sha256] = self.block_heights[self.tip.sha256]+1 + self.tip = b45 + self.blocks[45] = b45 + yield rejected(RejectResult(16, b'bad-cb-missing')) + + # A block with no txns + tip(44) + b46 = CBlock() + b46.nTime = b44.nTime+1 + b46.hashPrevBlock = b44.sha256 + b46.nBits = 0x207fffff + b46.vtx = [] + b46.hashMerkleRoot = 0 + b46.solve() + self.block_heights[b46.sha256] = self.block_heights[b44.sha256]+1 + self.tip = b46 + assert 46 not in self.blocks + self.blocks[46] = b46 + s = ser_uint256(b46.hashMerkleRoot) + yield rejected(RejectResult(16, b'bad-blk-length')) + + # A block with invalid work + tip(44) + b47 = block(47, solve=False) + target = uint256_from_compact(b47.nBits) + while b47.sha256 < target: #changed > to < + b47.nNonce += 1 + b47.rehash() + yield rejected(RejectResult(16, b'high-hash')) + + # A block with timestamp > 2 hrs in the future + tip(44) + b48 = block(48, solve=False) + b48.nTime = int(time.time()) + 60 * 60 * 3 + b48.solve() + yield rejected(RejectResult(16, b'time-too-new')) + + # A block with an invalid merkle hash + tip(44) + b49 = block(49) + b49.hashMerkleRoot += 1 + b49.solve() + yield rejected(RejectResult(16, b'bad-txnmrklroot')) + + # A block with an incorrect POW limit + tip(44) + b50 = block(50) + b50.nBits = b50.nBits - 1 + b50.solve() + yield rejected(RejectResult(16, b'bad-diffbits')) + + # A block with two coinbase txns + tip(44) + b51 = block(51) + cb2 = create_coinbase(51, self.coinbase_pubkey) + b51 = update_block(51, [cb2]) + yield rejected(RejectResult(16, b'bad-cb-multiple')) + + # A block w/ duplicate txns + # Note: txns have to be in the right position in the merkle tree to trigger this error + tip(44) + b52 = block(52, spend=out[15]) + tx = create_tx(b52.vtx[1], 0, 1) + b52 = update_block(52, [tx, tx]) + yield rejected(RejectResult(16, b'bad-txns-duplicate')) + + # Test block timestamps + # -> b31 (8) -> b33 (9) -> b35 (10) -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) + # \-> b54 (15) + # + tip(43) + block(53, spend=out[14]) + yield rejected() # rejected since b44 is at same height + save_spendable_output() + + # invalid timestamp (b35 is 5 blocks back, so its time is MedianTimePast) + b54 = block(54, spend=out[15]) + b54.nTime = b35.nTime - 1 + b54.solve() + yield rejected(RejectResult(16, b'time-too-old')) + + # valid timestamp + tip(53) + b55 = block(55, spend=out[15]) + b55.nTime = b35.nTime + update_block(55, []) + yield accepted() + save_spendable_output() + + + # Test CVE-2012-2459 + # + # -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57p2 (16) + # \-> b57 (16) + # \-> b56p2 (16) + # \-> b56 (16) + # + # Merkle tree malleability (CVE-2012-2459): repeating sequences of transactions in a block without + # affecting the merkle root of a block, while still invalidating it. + # See: src/consensus/merkle.h + # + # b57 has three txns: coinbase, tx, tx1. The merkle root computation will duplicate tx. + # Result: OK + # + # b56 copies b57 but duplicates tx1 and does not recalculate the block hash. So it has a valid merkle + # root but duplicate transactions. + # Result: Fails + # + # b57p2 has six transactions in its merkle tree: + # - coinbase, tx, tx1, tx2, tx3, tx4 + # Merkle root calculation will duplicate as necessary. + # Result: OK. + # + # b56p2 copies b57p2 but adds both tx3 and tx4. The purpose of the test is to make sure the code catches + # duplicate txns that are not next to one another with the "bad-txns-duplicate" error (which indicates + # that the error was caught early, avoiding a DOS vulnerability.) + + # b57 - a good block with 2 txs, don't submit until end + tip(55) + b57 = block(57) + tx = create_and_sign_tx(out[16].tx, out[16].n, 1) + tx1 = create_tx(tx, 0, 1) + b57 = update_block(57, [tx, tx1]) + + # b56 - copy b57, add a duplicate tx + tip(55) + b56 = copy.deepcopy(b57) + self.blocks[56] = b56 + assert_equal(len(b56.vtx),3) + b56 = update_block(56, [tx1]) + assert_equal(b56.hash, b57.hash) + yield rejected(RejectResult(16, b'bad-txns-duplicate')) + + # b57p2 - a good block with 6 tx'es, don't submit until end + tip(55) + b57p2 = block("57p2") + tx = create_and_sign_tx(out[16].tx, out[16].n, 1) + tx1 = create_tx(tx, 0, 1) + tx2 = create_tx(tx1, 0, 1) + tx3 = create_tx(tx2, 0, 1) + tx4 = create_tx(tx3, 0, 1) + b57p2 = update_block("57p2", [tx, tx1, tx2, tx3, tx4]) + + # b56p2 - copy b57p2, duplicate two non-consecutive tx's + tip(55) + b56p2 = copy.deepcopy(b57p2) + self.blocks["b56p2"] = b56p2 + assert_equal(b56p2.hash, b57p2.hash) + assert_equal(len(b56p2.vtx),6) + b56p2 = update_block("b56p2", [tx3, tx4]) + yield rejected(RejectResult(16, b'bad-txns-duplicate')) + + tip("57p2") + yield accepted() + + tip(57) + yield rejected() #rejected because 57p2 seen first + save_spendable_output() + + # Test a few invalid tx types + # + # -> b35 (10) -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) + # \-> ??? (17) + # + + # tx with prevout.n out of range + tip(57) + b58 = block(58, spend=out[17]) + tx = CTransaction() + assert(len(out[17].tx.vout) < 42) + tx.vin.append(CTxIn(COutPoint(out[17].tx.sha256, 42), CScript([OP_TRUE]), 0xffffffff)) + tx.vout.append(CTxOut(0, b"")) + tx.calc_sha256() + b58 = update_block(58, [tx]) + yield rejected(RejectResult(16, b'bad-txns-inputs-missingorspent')) + + # tx with output value > input value out of range + tip(57) + b59 = block(59) + tx = create_and_sign_tx(out[17].tx, out[17].n, 51*COIN) + b59 = update_block(59, [tx]) + yield rejected(RejectResult(16, b'bad-txns-in-belowout')) + + # reset to good chain + tip(57) + b60 = block(60, spend=out[17]) + yield accepted() + save_spendable_output() + + # Test BIP30 + # + # -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) + # \-> b61 (18) + # + # Blocks are not allowed to contain a transaction whose id matches that of an earlier, + # not-fully-spent transaction in the same chain. To test, make identical coinbases; + # the second one should be rejected. + # + tip(60) + b61 = block(61, spend=out[18]) + b61.vtx[0].vin[0].scriptSig = b60.vtx[0].vin[0].scriptSig #equalize the coinbases + b61.vtx[0].rehash() + b61 = update_block(61, []) + assert_equal(b60.vtx[0].serialize(), b61.vtx[0].serialize()) + yield rejected(RejectResult(16, b'bad-txns-BIP30')) + + + # Test tx.isFinal is properly rejected (not an exhaustive tx.isFinal test, that should be in data-driven transaction tests) + # + # -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) + # \-> b62 (18) + # + tip(60) + b62 = block(62) + tx = CTransaction() + tx.nLockTime = 0xffffffff #this locktime is non-final + assert(out[18].n < len(out[18].tx.vout)) + tx.vin.append(CTxIn(COutPoint(out[18].tx.sha256, out[18].n))) # don't set nSequence + tx.vout.append(CTxOut(0, CScript([OP_TRUE]))) + assert(tx.vin[0].nSequence < 0xffffffff) + tx.calc_sha256() + b62 = update_block(62, [tx]) + yield rejected(RejectResult(16, b'bad-txns-nonfinal')) + + + # Test a non-final coinbase is also rejected + # + # -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) + # \-> b63 (-) + # + tip(60) + b63 = block(63) + b63.vtx[0].nLockTime = 0xffffffff + b63.vtx[0].vin[0].nSequence = 0xDEADBEEF + b63.vtx[0].rehash() + b63 = update_block(63, []) + yield rejected(RejectResult(16, b'bad-txns-nonfinal')) + + + # This checks that a block with a bloated VARINT between the block_header and the array of tx is rejected + # (previous behavior was that it was accepted.) It also checks that if you subsequently send that block + # with correct encoding, it should be accepted (i.e., the receiving node should not reject it on the + # basis that it's the same as an already-rejected block, which would be a DoS vulnerability.) + # + # -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) + # \ + # b64a (18) + # b64a is a bloated block (non-canonical varint) + # b64 is a good block (same as b64 but w/ canonical varint) + # + tip(60) + regular_block = block("64a", spend=out[18]) + + # make it a "broken_block," with non-canonical serialization + b64a = CBrokenBlock(regular_block) + b64a.initialize(regular_block) + self.blocks["64a"] = b64a + self.tip = b64a + tx = CTransaction() + + # use canonical serialization to calculate size + script_length = MAX_BLOCK_SIZE - len(b64a.normal_serialize()) - 69 + script_output = CScript([b'\x00' * script_length]) + tx.vout.append(CTxOut(0, script_output)) + tx.vin.append(CTxIn(COutPoint(b64a.vtx[1].sha256, 0))) + b64a = update_block("64a", [tx]) + assert_equal(len(b64a.serialize()), MAX_BLOCK_SIZE + 8) + yield rejected() + + # comptool workaround: to make sure b64 is delivered, manually erase b64a from blockstore + self.test.block_store.erase(b64a.sha256) + + tip(60) + b64 = CBlock(b64a) + b64.vtx = copy.deepcopy(b64a.vtx) + assert_equal(b64.hash, b64a.hash) + assert_equal(len(b64.serialize()), MAX_BLOCK_SIZE) + self.blocks[64] = b64 + update_block(64, []) + yield accepted() + save_spendable_output() + + # Spend an output created in the block itself + # + # -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19) + # + tip(64) + b65 = block(65) + tx1 = create_and_sign_tx(out[19].tx, out[19].n, out[19].tx.vout[0].nValue) + tx2 = create_and_sign_tx(tx1, 0, 0) + update_block(65, [tx1, tx2]) + yield accepted() + save_spendable_output() + + # Attempt to spend an output created later in the same block + # + # -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19) + # \-> b66 (20) + tip(65) + b66 = block(66) + tx1 = create_and_sign_tx(out[20].tx, out[20].n, out[20].tx.vout[0].nValue) + tx2 = create_and_sign_tx(tx1, 0, 1) + update_block(66, [tx2, tx1]) + yield rejected(RejectResult(16, b'bad-txns-inputs-missingorspent')) + + + # Attempt to double-spend a transaction created in a block + # + # -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19) + # \-> b67 (20) + # + # + tip(65) + b67 = block(67) + tx1 = create_and_sign_tx(out[20].tx, out[20].n, out[20].tx.vout[0].nValue) + tx2 = create_and_sign_tx(tx1, 0, 1) + tx3 = create_and_sign_tx(tx1, 0, 2) + update_block(67, [tx1, tx2, tx3]) + yield rejected(RejectResult(16, b'bad-txns-inputs-missingorspent')) + + # More tests of block subsidy + # + # -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19) -> b69 (20) + # \-> b68 (20) + # + # b68 - coinbase with an extra 10 satoshis, + # creates a tx that has 9 satoshis from out[20] go to fees + # this fails because the coinbase is trying to claim 1 satoshi too much in fees + # + # b69 - coinbase with extra 10 satoshis, and a tx that gives a 10 satoshi fee + # this succeeds + # + tip(65) + b68 = block(68, additional_coinbase_value=10) + tx = create_and_sign_tx(out[20].tx, out[20].n, out[20].tx.vout[0].nValue-9) + update_block(68, [tx]) + yield rejected(RejectResult(16, b'bad-cb-amount')) + + tip(65) + b69 = block(69, additional_coinbase_value=10) + tx = create_and_sign_tx(out[20].tx, out[20].n, out[20].tx.vout[0].nValue-10) + update_block(69, [tx]) + yield accepted() + save_spendable_output() + + # Test spending the outpoint of a non-existent transaction + # + # -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19) -> b69 (20) + # \-> b70 (21) + # + tip(69) + block(70, spend=out[21]) + bogus_tx = CTransaction() + bogus_tx.sha256 = uint256_from_str(b"23c70ed7c0506e9178fc1a987f40a33946d4ad4c962b5ae3a52546da53af0c5c") + tx = CTransaction() + tx.vin.append(CTxIn(COutPoint(bogus_tx.sha256, 0), b"", 0xffffffff)) + tx.vout.append(CTxOut(1, b"")) + update_block(70, [tx]) + yield rejected(RejectResult(16, b'bad-txns-inputs-missingorspent')) + + + # Test accepting an invalid block which has the same hash as a valid one (via merkle tree tricks) + # + # -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19) -> b69 (20) -> b72 (21) + # \-> b71 (21) + # + # b72 is a good block. + # b71 is a copy of 72, but re-adds one of its transactions. However, it has the same hash as b71. + # + tip(69) + b72 = block(72) + tx1 = create_and_sign_tx(out[21].tx, out[21].n, 2) + tx2 = create_and_sign_tx(tx1, 0, 1) + b72 = update_block(72, [tx1, tx2]) # now tip is 72 + b71 = copy.deepcopy(b72) + b71.vtx.append(tx2) # add duplicate tx2 + self.block_heights[b71.sha256] = self.block_heights[b69.sha256] + 1 # b71 builds off b69 + self.blocks[71] = b71 + + assert_equal(len(b71.vtx), 4) + assert_equal(len(b72.vtx), 3) + assert_equal(b72.sha256, b71.sha256) + + tip(71) + yield rejected(RejectResult(16, b'bad-txns-duplicate')) + tip(72) + yield accepted() + save_spendable_output() + + + # Test some invalid scripts and MAX_BLOCK_SIGOPS + # + # -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19) -> b69 (20) -> b72 (21) + # \-> b** (22) + # + + # b73 - tx with excessive sigops that are placed after an excessively large script element. + # The purpose of the test is to make sure those sigops are counted. + # + # script is a bytearray of size 20,526 + # + # bytearray[0-19,998] : OP_CHECKSIG + # bytearray[19,999] : OP_PUSHDATA4 + # bytearray[20,000-20,003]: 521 (max_script_element_size+1, in little-endian format) + # bytearray[20,004-20,525]: unread data (script_element) + # bytearray[20,526] : OP_CHECKSIG (this puts us over the limit) + # + tip(72) + b73 = block(73) + size = MAX_BLOCK_SIGOPS - 1 + MAX_SCRIPT_ELEMENT_SIZE + 1 + 5 + 1 + a = bytearray([OP_CHECKSIG] * size) + a[MAX_BLOCK_SIGOPS - 1] = int("4e",16) # OP_PUSHDATA4 + + element_size = MAX_SCRIPT_ELEMENT_SIZE + 1 + a[MAX_BLOCK_SIGOPS] = element_size % 256 + a[MAX_BLOCK_SIGOPS+1] = element_size // 256 + a[MAX_BLOCK_SIGOPS+2] = 0 + a[MAX_BLOCK_SIGOPS+3] = 0 + + tx = create_and_sign_tx(out[22].tx, 0, 1, CScript(a)) + b73 = update_block(73, [tx]) + assert_equal(get_legacy_sigopcount_block(b73), MAX_BLOCK_SIGOPS+1) + yield rejected(RejectResult(16, b'bad-blk-sigops')) + + # b74/75 - if we push an invalid script element, all prevous sigops are counted, + # but sigops after the element are not counted. + # + # The invalid script element is that the push_data indicates that + # there will be a large amount of data (0xffffff bytes), but we only + # provide a much smaller number. These bytes are CHECKSIGS so they would + # cause b75 to fail for excessive sigops, if those bytes were counted. + # + # b74 fails because we put MAX_BLOCK_SIGOPS+1 before the element + # b75 succeeds because we put MAX_BLOCK_SIGOPS before the element + # + # + tip(72) + b74 = block(74) + size = MAX_BLOCK_SIGOPS - 1 + MAX_SCRIPT_ELEMENT_SIZE + 42 # total = 20,561 + a = bytearray([OP_CHECKSIG] * size) + a[MAX_BLOCK_SIGOPS] = 0x4e + a[MAX_BLOCK_SIGOPS+1] = 0xfe + a[MAX_BLOCK_SIGOPS+2] = 0xff + a[MAX_BLOCK_SIGOPS+3] = 0xff + a[MAX_BLOCK_SIGOPS+4] = 0xff + tx = create_and_sign_tx(out[22].tx, 0, 1, CScript(a)) + b74 = update_block(74, [tx]) + yield rejected(RejectResult(16, b'bad-blk-sigops')) + + tip(72) + b75 = block(75) + size = MAX_BLOCK_SIGOPS - 1 + MAX_SCRIPT_ELEMENT_SIZE + 42 + a = bytearray([OP_CHECKSIG] * size) + a[MAX_BLOCK_SIGOPS-1] = 0x4e + a[MAX_BLOCK_SIGOPS] = 0xff + a[MAX_BLOCK_SIGOPS+1] = 0xff + a[MAX_BLOCK_SIGOPS+2] = 0xff + a[MAX_BLOCK_SIGOPS+3] = 0xff + tx = create_and_sign_tx(out[22].tx, 0, 1, CScript(a)) + b75 = update_block(75, [tx]) + yield accepted() + save_spendable_output() + + # Check that if we push an element filled with CHECKSIGs, they are not counted + tip(75) + b76 = block(76) + size = MAX_BLOCK_SIGOPS - 1 + MAX_SCRIPT_ELEMENT_SIZE + 1 + 5 + a = bytearray([OP_CHECKSIG] * size) + a[MAX_BLOCK_SIGOPS-1] = 0x4e # PUSHDATA4, but leave the following bytes as just checksigs + tx = create_and_sign_tx(out[23].tx, 0, 1, CScript(a)) + b76 = update_block(76, [tx]) + yield accepted() + save_spendable_output() + + # Test transaction resurrection + # + # -> b77 (24) -> b78 (25) -> b79 (26) + # \-> b80 (25) -> b81 (26) -> b82 (27) + # + # b78 creates a tx, which is spent in b79. After b82, both should be in mempool + # + # The tx'es must be unsigned and pass the node's mempool policy. It is unsigned for the + # rather obscure reason that the Python signature code does not distinguish between + # Low-S and High-S values (whereas the bitcoin code has custom code which does so); + # as a result of which, the odds are 50% that the python code will use the right + # value and the transaction will be accepted into the mempool. Until we modify the + # test framework to support low-S signing, we are out of luck. + # + # To get around this issue, we construct transactions which are not signed and which + # spend to OP_TRUE. If the standard-ness rules change, this test would need to be + # updated. (Perhaps to spend to a P2SH OP_TRUE script) + # + tip(76) + block(77) + tx77 = create_and_sign_tx(out[24].tx, out[24].n, 10*COIN) + update_block(77, [tx77]) + yield accepted() + save_spendable_output() + + block(78) + tx78 = create_tx(tx77, 0, 9*COIN) + update_block(78, [tx78]) + yield accepted() + + block(79) + tx79 = create_tx(tx78, 0, 8*COIN) + update_block(79, [tx79]) + yield accepted() + + # mempool should be empty + assert_equal(len(self.nodes[0].getrawmempool()), 0) + + tip(77) + block(80, spend=out[25]) + yield rejected() + save_spendable_output() + + block(81, spend=out[26]) + yield rejected() # other chain is same length + save_spendable_output() + + block(82, spend=out[27]) + yield accepted() # now this chain is longer, triggers re-org + save_spendable_output() + + # now check that tx78 and tx79 have been put back into the peer's mempool + mempool = self.nodes[0].getrawmempool() + assert_equal(len(mempool), 2) + assert(tx78.hash in mempool) + assert(tx79.hash in mempool) + + + # Test invalid opcodes in dead execution paths. + # + # -> b81 (26) -> b82 (27) -> b83 (28) + # + b83 = block(83) + op_codes = [OP_IF, OP_INVALIDOPCODE, OP_ELSE, OP_TRUE, OP_ENDIF] + script = CScript(op_codes) + tx1 = create_and_sign_tx(out[28].tx, out[28].n, out[28].tx.vout[0].nValue, script) + + tx2 = create_and_sign_tx(tx1, 0, 0, CScript([OP_TRUE])) + tx2.vin[0].scriptSig = CScript([OP_FALSE]) + tx2.rehash() + + update_block(83, [tx1, tx2]) + yield accepted() + save_spendable_output() + + + # Reorg on/off blocks that have OP_RETURN in them (and try to spend them) + # + # -> b81 (26) -> b82 (27) -> b83 (28) -> b84 (29) -> b87 (30) -> b88 (31) + # \-> b85 (29) -> b86 (30) \-> b89a (32) + # + # + b84 = block(84) + tx1 = create_tx(out[29].tx, out[29].n, 0, CScript([OP_RETURN])) + tx1.vout.append(CTxOut(0, CScript([OP_TRUE]))) + tx1.vout.append(CTxOut(0, CScript([OP_TRUE]))) + tx1.vout.append(CTxOut(0, CScript([OP_TRUE]))) + tx1.vout.append(CTxOut(0, CScript([OP_TRUE]))) + tx1.calc_sha256() + self.sign_tx(tx1, out[29].tx, out[29].n) + tx1.rehash() + tx2 = create_tx(tx1, 1, 0, CScript([OP_RETURN])) + tx2.vout.append(CTxOut(0, CScript([OP_RETURN]))) + tx3 = create_tx(tx1, 2, 0, CScript([OP_RETURN])) + tx3.vout.append(CTxOut(0, CScript([OP_TRUE]))) + tx4 = create_tx(tx1, 3, 0, CScript([OP_TRUE])) + tx4.vout.append(CTxOut(0, CScript([OP_RETURN]))) + tx5 = create_tx(tx1, 4, 0, CScript([OP_RETURN])) + + update_block(84, [tx1,tx2,tx3,tx4,tx5]) + yield accepted() + save_spendable_output() + + tip(83) + block(85, spend=out[29]) + yield rejected() + + block(86, spend=out[30]) + yield accepted() + + tip(84) + block(87, spend=out[30]) + yield rejected() + save_spendable_output() + + block(88, spend=out[31]) + yield accepted() + save_spendable_output() + + # trying to spend the OP_RETURN output is rejected + block("89a", spend=out[32]) + tx = create_tx(tx1, 0, 0, CScript([OP_TRUE])) + update_block("89a", [tx]) + yield rejected() + + + # Test re-org of a week's worth of blocks (1088 blocks) + # This test takes a minute or two and can be accomplished in memory + # + tip(88) + LARGE_REORG_SIZE = 1088 + test1 = TestInstance(sync_every_block=False) + spend=out[32] + for i in range(89, LARGE_REORG_SIZE + 89): + b = block(i, spend) + tx = CTransaction() + script_length = MAX_BLOCK_SIZE - len(b.serialize()) - 69 + script_output = CScript([b'\x00' * script_length]) + tx.vout.append(CTxOut(0, script_output)) + tx.vin.append(CTxIn(COutPoint(b.vtx[1].sha256, 0))) + b = update_block(i, [tx]) + assert_equal(len(b.serialize()), MAX_BLOCK_SIZE) + test1.blocks_and_transactions.append([self.tip, True]) + save_spendable_output() + spend = get_spendable_output() + + yield test1 + chain1_tip = i + + # now create alt chain of same length + tip(88) + test2 = TestInstance(sync_every_block=False) + for i in range(89, LARGE_REORG_SIZE + 89): + block("alt"+str(i)) + test2.blocks_and_transactions.append([self.tip, False]) + yield test2 + + # extend alt chain to trigger re-org + block("alt" + str(chain1_tip + 1)) + yield accepted() + + # ... and re-org back to the first chain + tip(chain1_tip) + block(chain1_tip + 1) + yield rejected() + block(chain1_tip + 2) + yield accepted() + + chain1_tip += 2 if __name__ == '__main__': diff --git a/qa/rpc-tests/test_framework/blocktools.py b/qa/rpc-tests/test_framework/blocktools.py index 44232153ac702..26cc3963151ed 100644 --- a/qa/rpc-tests/test_framework/blocktools.py +++ b/qa/rpc-tests/test_framework/blocktools.py @@ -56,12 +56,27 @@ def create_coinbase(height, pubkey = None): coinbase.calc_sha256() return coinbase -# Create a transaction with an anyone-can-spend output, that spends the -# nth output of prevtx. -def create_transaction(prevtx, n, sig, value): +# Create a transaction. +# If the scriptPubKey is not specified, make it anyone-can-spend. +def create_transaction(prevtx, n, sig, value, scriptPubKey=CScript()): tx = CTransaction() assert(n < len(prevtx.vout)) tx.vin.append(CTxIn(COutPoint(prevtx.sha256, n), sig, 0xffffffff)) - tx.vout.append(CTxOut(value, b"")) + tx.vout.append(CTxOut(value, scriptPubKey)) tx.calc_sha256() return tx + +def get_legacy_sigopcount_block(block, fAccurate=True): + count = 0 + for tx in block.vtx: + count += get_legacy_sigopcount_tx(tx, fAccurate) + return count + +def get_legacy_sigopcount_tx(tx, fAccurate=True): + count = 0 + for i in tx.vout: + count += i.scriptPubKey.GetSigOpCount(fAccurate) + for j in tx.vin: + # scriptSig might be of type bytes, so convert to CScript for the moment + count += CScript(j.scriptSig).GetSigOpCount(fAccurate) + return count diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index e85399c960bb7..c0b59f38579d7 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -556,7 +556,6 @@ def solve(self): self.nNonce += 1 self.rehash() - def __repr__(self): return "CBlock(nVersion=%i hashPrevBlock=%064x hashMerkleRoot=%064x nTime=%s nBits=%08x nNonce=%08x vtx=%s)" \ % (self.nVersion, self.hashPrevBlock, self.hashMerkleRoot, From 12c5a16c4e635799cfb6cadbca79dfa83555da72 Mon Sep 17 00:00:00 2001 From: mrbandrews Date: Thu, 2 Jun 2016 14:43:18 -0400 Subject: [PATCH 0403/1802] Catch exceptions from non-canonical encoding and print only to log --- src/main.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index ed157b53dced7..885b1b56fb533 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5567,6 +5567,11 @@ bool ProcessMessages(CNode* pfrom) // Allow exceptions from over-long size LogPrintf("%s(%s, %u bytes): Exception '%s' caught\n", __func__, SanitizeString(strCommand), nMessageSize, e.what()); } + else if (strstr(e.what(), "non-canonical ReadCompactSize()")) + { + // Allow exceptions from non-canonical encoding + LogPrintf("%s(%s, %u bytes): Exception '%s' caught\n", __func__, SanitizeString(strCommand), nMessageSize, e.what()); + } else { PrintExceptionContinue(&e, "ProcessMessages()"); From 9805f4af7ecb6becf8a146bd845fb131ffa625c9 Mon Sep 17 00:00:00 2001 From: Kaz Wesley Date: Sat, 30 Apr 2016 21:45:26 -0700 Subject: [PATCH 0404/1802] mapNextTx: use pointer as key, simplify value Saves about 10% of application memory usage once the mempool warms up. Since the mempool is DynamicUsage-regulated, this will translate to a larger mempool in the same amount of space. Map value type: eliminate the vin index; no users of the map need to know which input of the transaction is spending the prevout. Map key type: replace the COutPoint with a pointer to a COutPoint. A COutPoint is 36 bytes, but each COutPoint is accessible from the same map entry's value. A trivial DereferencingComparator functor allows indirect map keys, but the resulting syntax is misleading: `map.find(&outpoint)`. Implement an indirectmap that acts as a wrapper to a map that uses a DereferencingComparator, supporting a syntax that accurately reflect the container's semantics: inserts and iterators use pointers since they store pointers and need them to remain constant and dereferenceable, but lookup functions take const references. --- src/Makefile.am | 1 + src/indirectmap.h | 52 +++++++++++++++++++++++++++++++++++++++++++++++ src/main.cpp | 5 +++-- src/memusage.h | 16 +++++++++++++++ src/txmempool.cpp | 46 ++++++++++++++++++++--------------------- src/txmempool.h | 17 ++-------------- 6 files changed, 96 insertions(+), 41 deletions(-) create mode 100644 src/indirectmap.h diff --git a/src/Makefile.am b/src/Makefile.am index 3c056386fac7b..ad61e4f108db4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -94,6 +94,7 @@ BITCOIN_CORE_H = \ core_memusage.h \ httprpc.h \ httpserver.h \ + indirectmap.h \ init.h \ key.h \ keystore.h \ diff --git a/src/indirectmap.h b/src/indirectmap.h new file mode 100644 index 0000000000000..28e1e8deddbde --- /dev/null +++ b/src/indirectmap.h @@ -0,0 +1,52 @@ +#ifndef BITCOIN_INDIRECTMAP_H +#define BITCOIN_INDIRECTMAP_H + +template +struct DereferencingComparator { bool operator()(const T a, const T b) const { return *a < *b; } }; + +/* Map whose keys are pointers, but are compared by their dereferenced values. + * + * Differs from a plain std::map > in + * that methods that take a key for comparison take a K rather than taking a K* + * (taking a K* would be confusing, since it's the value rather than the address + * of the object for comparison that matters due to the dereferencing comparator). + * + * Objects pointed to by keys must not be modified in any way that changes the + * result of DereferencingComparator. + */ +template +class indirectmap { +private: + typedef std::map > base; + base m; +public: + typedef typename base::iterator iterator; + typedef typename base::const_iterator const_iterator; + typedef typename base::size_type size_type; + typedef typename base::value_type value_type; + + // passthrough (pointer interface) + std::pair insert(const value_type& value) { return m.insert(value); } + + // pass address (value interface) + iterator find(const K& key) { return m.find(&key); } + const_iterator find(const K& key) const { return m.find(&key); } + iterator lower_bound(const K& key) { return m.lower_bound(&key); } + const_iterator lower_bound(const K& key) const { return m.lower_bound(&key); } + size_type erase(const K& key) { return m.erase(&key); } + size_type count(const K& key) const { return m.count(&key); } + + // passthrough + bool empty() const { return m.empty(); } + size_type size() const { return m.size(); } + size_type max_size() const { return m.max_size(); } + void clear() { m.clear(); } + iterator begin() { return m.begin(); } + iterator end() { return m.end(); } + const_iterator begin() const { return m.begin(); } + const_iterator end() const { return m.end(); } + const_iterator cbegin() const { return m.cbegin(); } + const_iterator cend() const { return m.cend(); } +}; + +#endif // BITCOIN_INDIRECTMAP_H diff --git a/src/main.cpp b/src/main.cpp index 11ccab253e4ed..13da2137e5295 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1049,9 +1049,10 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C LOCK(pool.cs); // protect pool.mapNextTx BOOST_FOREACH(const CTxIn &txin, tx.vin) { - if (pool.mapNextTx.count(txin.prevout)) + auto itConflicting = pool.mapNextTx.find(txin.prevout); + if (itConflicting != pool.mapNextTx.end()) { - const CTransaction *ptxConflicting = pool.mapNextTx[txin.prevout].ptx; + const CTransaction *ptxConflicting = itConflicting->second; if (!setConflicts.count(ptxConflicting->GetHash())) { // Allow opt-out of transaction replacement by setting diff --git a/src/memusage.h b/src/memusage.h index 49760e64c78cd..9c98e5c2cf22e 100644 --- a/src/memusage.h +++ b/src/memusage.h @@ -5,6 +5,8 @@ #ifndef BITCOIN_MEMUSAGE_H #define BITCOIN_MEMUSAGE_H +#include "indirectmap.h" + #include #include @@ -106,6 +108,20 @@ static inline size_t IncrementalDynamicUsage(const std::map& m) return MallocUsage(sizeof(stl_tree_node >)); } +// indirectmap has underlying map with pointer as key + +template +static inline size_t DynamicUsage(const indirectmap& m) +{ + return MallocUsage(sizeof(stl_tree_node >)) * m.size(); +} + +template +static inline size_t IncrementalDynamicUsage(const indirectmap& m) +{ + return MallocUsage(sizeof(stl_tree_node >)); +} + // Boost data structures template diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 52c7793118331..d7fb77661bd47 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -147,11 +147,11 @@ void CTxMemPool::UpdateTransactionsFromBlock(const std::vector &vHashes if (it == mapTx.end()) { continue; } - std::map::iterator iter = mapNextTx.lower_bound(COutPoint(hash, 0)); + auto iter = mapNextTx.lower_bound(COutPoint(hash, 0)); // First calculate the children, and update setMemPoolChildren to // include them, and update their setMemPoolParents to include this tx. - for (; iter != mapNextTx.end() && iter->first.hash == hash; ++iter) { - const uint256 &childHash = iter->second.ptx->GetHash(); + for (; iter != mapNextTx.end() && iter->first->hash == hash; ++iter) { + const uint256 &childHash = iter->second->GetHash(); txiter childIter = mapTx.find(childHash); assert(childIter != mapTx.end()); // We can skip updating entries we've encountered before or that @@ -365,11 +365,11 @@ void CTxMemPool::pruneSpent(const uint256 &hashTx, CCoins &coins) { LOCK(cs); - std::map::iterator it = mapNextTx.lower_bound(COutPoint(hashTx, 0)); + auto it = mapNextTx.lower_bound(COutPoint(hashTx, 0)); // iterate over all COutPoints in mapNextTx whose hash equals the provided hashTx - while (it != mapNextTx.end() && it->first.hash == hashTx) { - coins.Spend(it->first.n); // and remove those outputs from coins + while (it != mapNextTx.end() && it->first->hash == hashTx) { + coins.Spend(it->first->n); // and remove those outputs from coins it++; } } @@ -414,7 +414,7 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, const CTransaction& tx = newit->GetTx(); std::set setParentTransactions; for (unsigned int i = 0; i < tx.vin.size(); i++) { - mapNextTx[tx.vin[i].prevout] = CInPoint(&tx, i); + mapNextTx.insert(std::make_pair(&tx.vin[i].prevout, &tx)); setParentTransactions.insert(tx.vin[i].prevout.hash); } // Don't bother worrying about child transactions of this one. @@ -500,10 +500,10 @@ void CTxMemPool::removeRecursive(const CTransaction &origTx, std::list::iterator it = mapNextTx.find(COutPoint(origTx.GetHash(), i)); + auto it = mapNextTx.find(COutPoint(origTx.GetHash(), i)); if (it == mapNextTx.end()) continue; - txiter nextit = mapTx.find(it->second.ptx->GetHash()); + txiter nextit = mapTx.find(it->second->GetHash()); assert(nextit != mapTx.end()); txToRemove.insert(nextit); } @@ -561,9 +561,9 @@ void CTxMemPool::removeConflicts(const CTransaction &tx, std::list list result; LOCK(cs); BOOST_FOREACH(const CTxIn &txin, tx.vin) { - std::map::iterator it = mapNextTx.find(txin.prevout); + auto it = mapNextTx.find(txin.prevout); if (it != mapNextTx.end()) { - const CTransaction &txConflict = *it->second.ptx; + const CTransaction &txConflict = *it->second; if (txConflict != tx) { removeRecursive(txConflict, removed); @@ -671,10 +671,10 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const assert(coins && coins->IsAvailable(txin.prevout.n)); } // Check whether its inputs are marked in mapNextTx. - std::map::const_iterator it3 = mapNextTx.find(txin.prevout); + auto it3 = mapNextTx.find(txin.prevout); assert(it3 != mapNextTx.end()); - assert(it3->second.ptx == &tx); - assert(it3->second.n == i); + assert(it3->first == &txin.prevout); + assert(it3->second == &tx); i++; } assert(setParentCheck == GetMemPoolParents(it)); @@ -701,10 +701,10 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const // Check children against mapNextTx CTxMemPool::setEntries setChildrenCheck; - std::map::const_iterator iter = mapNextTx.lower_bound(COutPoint(it->GetTx().GetHash(), 0)); + auto iter = mapNextTx.lower_bound(COutPoint(it->GetTx().GetHash(), 0)); int64_t childSizes = 0; - for (; iter != mapNextTx.end() && iter->first.hash == it->GetTx().GetHash(); ++iter) { - txiter childit = mapTx.find(iter->second.ptx->GetHash()); + for (; iter != mapNextTx.end() && iter->first->hash == it->GetTx().GetHash(); ++iter) { + txiter childit = mapTx.find(iter->second->GetHash()); assert(childit != mapTx.end()); // mapNextTx points to in-mempool transactions if (setChildrenCheck.insert(childit).second) { childSizes += childit->GetTxSize(); @@ -738,14 +738,12 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const stepsSinceLastRemove = 0; } } - for (std::map::const_iterator it = mapNextTx.begin(); it != mapNextTx.end(); it++) { - uint256 hash = it->second.ptx->GetHash(); + for (auto it = mapNextTx.cbegin(); it != mapNextTx.cend(); it++) { + uint256 hash = it->second->GetHash(); indexed_transaction_set::const_iterator it2 = mapTx.find(hash); const CTransaction& tx = it2->GetTx(); assert(it2 != mapTx.end()); - assert(&tx == it->second.ptx); - assert(tx.vin.size() > it->second.n); - assert(it->first == it->second.ptx->vin[it->second.n].prevout); + assert(&tx == it->second); } assert(totalTxSize == checkTotal); @@ -1044,8 +1042,8 @@ void CTxMemPool::TrimToSize(size_t sizelimit, std::vector* pvNoSpendsRe BOOST_FOREACH(const CTxIn& txin, tx.vin) { if (exists(txin.prevout.hash)) continue; - std::map::iterator it = mapNextTx.lower_bound(COutPoint(txin.prevout.hash, 0)); - if (it == mapNextTx.end() || it->first.hash != txin.prevout.hash) + auto it = mapNextTx.lower_bound(COutPoint(txin.prevout.hash, 0)); + if (it == mapNextTx.end() || it->first->hash != txin.prevout.hash) pvNoSpendsRemaining->push_back(txin.prevout.hash); } } diff --git a/src/txmempool.h b/src/txmempool.h index de4ba0b371a42..7ad5579a066a9 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -11,6 +11,7 @@ #include "amount.h" #include "coins.h" +#include "indirectmap.h" #include "primitives/transaction.h" #include "sync.h" @@ -305,20 +306,6 @@ struct ancestor_score {}; class CBlockPolicyEstimator; -/** An inpoint - a combination of a transaction and an index n into its vin */ -class CInPoint -{ -public: - const CTransaction* ptx; - uint32_t n; - - CInPoint() { SetNull(); } - CInPoint(const CTransaction* ptxIn, uint32_t nIn) { ptx = ptxIn; n = nIn; } - void SetNull() { ptx = NULL; n = (uint32_t) -1; } - bool IsNull() const { return (ptx == NULL && n == (uint32_t) -1); } - size_t DynamicMemoryUsage() const { return 0; } -}; - /** * CTxMemPool stores valid-according-to-the-current-best-chain * transactions that may be included in the next block. @@ -477,7 +464,7 @@ class CTxMemPool void UpdateChild(txiter entry, txiter child, bool add); public: - std::map mapNextTx; + indirectmap mapNextTx; std::map > mapDeltas; /** Create a new CTxMemPool. From e39dc698adf46dc3306526971ca6f0f6401f30ca Mon Sep 17 00:00:00 2001 From: instagibbs Date: Fri, 3 Jun 2016 10:05:51 -0400 Subject: [PATCH 0405/1802] comment nit: miners don't vote --- src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index c98f42d7c93c2..527d4f570ef7f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1886,8 +1886,8 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi // such nodes as they are not following the protocol. That // said during an upgrade careful thought should be taken // as to the correct behavior - we may want to continue - // peering with non-upgraded nodes even after a soft-fork - // super-majority vote has passed. + // peering with non-upgraded nodes even after soft-fork + // super-majority signaling has occurred. return state.DoS(100,false, REJECT_INVALID, strprintf("mandatory-script-verify-flag-failed (%s)", ScriptErrorString(check.GetScriptError()))); } } From 340012d9c978901d23ccedad5805c6630c49e756 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 3 Jun 2016 14:00:38 -0400 Subject: [PATCH 0406/1802] build: add temporary fix for "bad magic number" error in out-of-tree builds This was caused by an pyc files hanging around from previous python2 invocations, when the matching .py missing from that path. This should not be a problem with python3's tagged caches. --- Makefile.am | 3 +++ src/Makefile.test.include | 3 +++ 2 files changed, 6 insertions(+) diff --git a/Makefile.am b/Makefile.am index b93748e324e24..b10d0850664c8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -224,6 +224,9 @@ EXTRA_DIST = $(top_srcdir)/share/genbuild.sh qa/pull-tester/rpc-tests.py qa/rpc- CLEANFILES = $(OSX_DMG) $(BITCOIN_WIN_INSTALLER) +# This file is problematic for out-of-tree builds if it exists. +DISTCLEANFILES = qa/pull-tester/tests_config.pyc + .INTERMEDIATE: $(COVERAGE_INFO) clean-local: diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 77cf1001e1d9d..ff3351fe725c9 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -123,6 +123,9 @@ CLEAN_BITCOIN_TEST = test/*.gcda test/*.gcno $(GENERATED_TEST_FILES) CLEANFILES += $(CLEAN_BITCOIN_TEST) +# This file is problematic for out-of-tree builds if it exists. +DISTCLEANFILES += test/buildenv.pyc + bitcoin_test: $(TEST_BINARY) bitcoin_test_check: $(TEST_BINARY) FORCE From 1b9e6d3c1a0f0e7eeff5ddb2e0386911fe9ab2b6 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 30 May 2016 16:50:14 +0200 Subject: [PATCH 0407/1802] Add support for unique_ptr and shared_ptr to memusage --- src/memusage.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/memusage.h b/src/memusage.h index 9c98e5c2cf22e..3810bfad07a91 100644 --- a/src/memusage.h +++ b/src/memusage.h @@ -72,6 +72,15 @@ struct stl_tree_node X x; }; +struct stl_shared_counter +{ + /* Various platforms use different sized counters here. + * Conservatively assume that they won't be larger than size_t. */ + void* class_type; + size_t use_count; + size_t weak_count; +}; + template static inline size_t DynamicUsage(const std::vector& v) { @@ -122,6 +131,21 @@ static inline size_t IncrementalDynamicUsage(const indirectmap& m) return MallocUsage(sizeof(stl_tree_node >)); } +template +static inline size_t DynamicUsage(const std::unique_ptr& p) +{ + return p ? MallocUsage(sizeof(X)) : 0; +} + +template +static inline size_t DynamicUsage(const std::shared_ptr& p) +{ + // A shared_ptr can either use a single continuous memory block for both + // the counter and the storage (when using std::make_shared), or separate. + // We can't observe the difference, however, so assume the worst. + return p ? MallocUsage(sizeof(X)) + MallocUsage(sizeof(stl_shared_counter)) : 0; +} + // Boost data structures template From 8d39d7a2cf1559e0ba40681b0ab90f13ea6c0618 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 30 May 2016 17:06:24 +0200 Subject: [PATCH 0408/1802] Switch CTransaction storage in mempool to std::shared_ptr --- src/main.cpp | 32 ++++++++---------- src/txmempool.cpp | 84 +++++++++++++++++++++++++++++++++-------------- src/txmempool.h | 28 +++++++++++++--- 3 files changed, 97 insertions(+), 47 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 527d4f570ef7f..d71f35bf7e4fc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4519,10 +4519,11 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam } } if (!push && inv.type == MSG_TX) { - int64_t txtime; + auto txinfo = mempool.info(inv.hash); // To protect privacy, do not answer getdata using the mempool when // that TX couldn't have been INVed in reply to a MEMPOOL request. - if (mempool.lookup(inv.hash, tx, txtime) && txtime <= pfrom->timeLastMempoolReq) { + if (txinfo.tx && txinfo.nTime <= pfrom->timeLastMempoolReq) { + tx = *txinfo.tx; push = true; } } @@ -5900,8 +5901,7 @@ bool SendMessages(CNode* pto) // Respond to BIP35 mempool requests if (fSendTrickle && pto->fSendMempool) { - std::vector vtxid; - mempool.queryHashes(vtxid); + auto vtxinfo = mempool.infoAll(); pto->fSendMempool = false; CAmount filterrate = 0; { @@ -5911,20 +5911,16 @@ bool SendMessages(CNode* pto) LOCK(pto->cs_filter); - BOOST_FOREACH(const uint256& hash, vtxid) { + for (const auto& txinfo : vtxinfo) { + const uint256& hash = txinfo.tx->GetHash(); CInv inv(MSG_TX, hash); pto->setInventoryTxToSend.erase(hash); if (filterrate) { - CFeeRate feeRate; - mempool.lookupFeeRate(hash, feeRate); - if (feeRate.GetFeePerK() < filterrate) + if (txinfo.feeRate.GetFeePerK() < filterrate) continue; } if (pto->pfilter) { - CTransaction tx; - bool fInMemPool = mempool.lookup(hash, tx); - if (!fInMemPool) continue; // another thread removed since queryHashes, maybe... - if (!pto->pfilter->IsRelevantAndUpdate(tx)) continue; + if (!pto->pfilter->IsRelevantAndUpdate(*txinfo.tx)) continue; } pto->filterInventoryKnown.insert(hash); vInv.push_back(inv); @@ -5970,16 +5966,14 @@ bool SendMessages(CNode* pto) continue; } // Not in the mempool anymore? don't bother sending it. - CFeeRate feeRate; - if (!mempool.lookupFeeRate(hash, feeRate)) { + auto txinfo = mempool.info(hash); + if (!txinfo.tx) { continue; } - if (filterrate && feeRate.GetFeePerK() < filterrate) { + if (filterrate && txinfo.feeRate.GetFeePerK() < filterrate) { continue; } - CTransaction tx; - if (!mempool.lookup(hash, tx)) continue; - if (pto->pfilter && !pto->pfilter->IsRelevantAndUpdate(tx)) continue; + if (pto->pfilter && !pto->pfilter->IsRelevantAndUpdate(*txinfo.tx)) continue; // Send vInv.push_back(CInv(MSG_TX, hash)); nRelayedTransactions++; @@ -5992,7 +5986,7 @@ bool SendMessages(CNode* pto) vRelayExpiration.pop_front(); } - auto ret = mapRelay.insert(std::make_pair(hash, tx)); + auto ret = mapRelay.insert(std::make_pair(hash, *txinfo.tx)); if (ret.second) { vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, hash)); } diff --git a/src/txmempool.cpp b/src/txmempool.cpp index f44e450363f09..d39c9577f2484 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -23,18 +23,18 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee, int64_t _nTime, double _entryPriority, unsigned int _entryHeight, bool poolHasNoInputsOf, CAmount _inChainInputValue, bool _spendsCoinbase, unsigned int _sigOps, LockPoints lp): - tx(_tx), nFee(_nFee), nTime(_nTime), entryPriority(_entryPriority), entryHeight(_entryHeight), + tx(std::make_shared(_tx)), nFee(_nFee), nTime(_nTime), entryPriority(_entryPriority), entryHeight(_entryHeight), hadNoDependencies(poolHasNoInputsOf), inChainInputValue(_inChainInputValue), spendsCoinbase(_spendsCoinbase), sigOpCount(_sigOps), lockPoints(lp) { - nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); - nModSize = tx.CalculateModifiedSize(nTxSize); - nUsageSize = RecursiveDynamicUsage(tx); + nTxSize = ::GetSerializeSize(_tx, SER_NETWORK, PROTOCOL_VERSION); + nModSize = _tx.CalculateModifiedSize(nTxSize); + nUsageSize = RecursiveDynamicUsage(*tx) + memusage::DynamicUsage(tx); nCountWithDescendants = 1; nSizeWithDescendants = nTxSize; nModFeesWithDescendants = nFee; - CAmount nValueIn = tx.GetValueOut()+nFee; + CAmount nValueIn = _tx.GetValueOut()+nFee; assert(inChainInputValue <= nValueIn); feeDelta = 0; @@ -768,50 +768,86 @@ bool CTxMemPool::CompareDepthAndScore(const uint256& hasha, const uint256& hashb namespace { class DepthAndScoreComparator { - CTxMemPool *mp; public: - DepthAndScoreComparator(CTxMemPool *mempool) : mp(mempool) {} - bool operator()(const uint256& a, const uint256& b) { return mp->CompareDepthAndScore(a, b); } + bool operator()(const CTxMemPool::indexed_transaction_set::const_iterator& a, const CTxMemPool::indexed_transaction_set::const_iterator& b) + { + uint64_t counta = a->GetCountWithAncestors(); + uint64_t countb = b->GetCountWithAncestors(); + if (counta == countb) { + return CompareTxMemPoolEntryByScore()(*a, *b); + } + return counta < countb; + } }; } -void CTxMemPool::queryHashes(vector& vtxid) +std::vector CTxMemPool::GetSortedDepthAndScore() const { - vtxid.clear(); + std::vector iters; + AssertLockHeld(cs); + + iters.reserve(mapTx.size()); + for (indexed_transaction_set::iterator mi = mapTx.begin(); mi != mapTx.end(); ++mi) { + iters.push_back(mi); + } + std::sort(iters.begin(), iters.end(), DepthAndScoreComparator()); + return iters; +} + +void CTxMemPool::queryHashes(vector& vtxid) +{ LOCK(cs); + auto iters = GetSortedDepthAndScore(); + + vtxid.clear(); vtxid.reserve(mapTx.size()); - for (indexed_transaction_set::iterator mi = mapTx.begin(); mi != mapTx.end(); ++mi) - vtxid.push_back(mi->GetTx().GetHash()); - std::sort(vtxid.begin(), vtxid.end(), DepthAndScoreComparator(this)); + for (auto it : iters) { + vtxid.push_back(it->GetTx().GetHash()); + } } +std::vector CTxMemPool::infoAll() const +{ + LOCK(cs); + auto iters = GetSortedDepthAndScore(); + + std::vector ret; + ret.reserve(mapTx.size()); + for (auto it : iters) { + ret.push_back(TxMempoolInfo{it->GetSharedTx(), it->GetTime(), CFeeRate(it->GetFee(), it->GetTxSize())}); + } + + return ret; +} -bool CTxMemPool::lookup(uint256 hash, CTransaction& result, int64_t& time) const +std::shared_ptr CTxMemPool::get(const uint256& hash) const { LOCK(cs); indexed_transaction_set::const_iterator i = mapTx.find(hash); - if (i == mapTx.end()) return false; - result = i->GetTx(); - time = i->GetTime(); - return true; + if (i == mapTx.end()) + return nullptr; + return i->GetSharedTx(); } bool CTxMemPool::lookup(uint256 hash, CTransaction& result) const { - int64_t time; - return CTxMemPool::lookup(hash, result, time); + auto tx = get(hash); + if (tx) { + result = *tx; + return true; + } + return false; } -bool CTxMemPool::lookupFeeRate(const uint256& hash, CFeeRate& feeRate) const +TxMempoolInfo CTxMemPool::info(const uint256& hash) const { LOCK(cs); indexed_transaction_set::const_iterator i = mapTx.find(hash); if (i == mapTx.end()) - return false; - feeRate = CFeeRate(i->GetFee(), i->GetTxSize()); - return true; + return TxMempoolInfo(); + return TxMempoolInfo{i->GetSharedTx(), i->GetTime(), CFeeRate(i->GetFee(), i->GetTxSize())}; } CFeeRate CTxMemPool::estimateFee(int nBlocks) const diff --git a/src/txmempool.h b/src/txmempool.h index 3cf84159cc36b..2f407fe008efe 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -7,6 +7,7 @@ #define BITCOIN_TXMEMPOOL_H #include +#include #include #include "amount.h" @@ -75,7 +76,7 @@ class CTxMemPool; class CTxMemPoolEntry { private: - CTransaction tx; + std::shared_ptr tx; CAmount nFee; //!< Cached to avoid expensive parent-transaction lookups size_t nTxSize; //!< ... and avoid recomputing tx size size_t nModSize; //!< ... and modified size for priority @@ -112,7 +113,8 @@ class CTxMemPoolEntry unsigned int nSigOps, LockPoints lp); CTxMemPoolEntry(const CTxMemPoolEntry& other); - const CTransaction& GetTx() const { return this->tx; } + const CTransaction& GetTx() const { return *this->tx; } + std::shared_ptr GetSharedTx() const { return this->tx; } /** * Fast calculation of lower bound of current priority as update * from entry priority. Only inputs that were originally in-chain will age. @@ -307,6 +309,21 @@ struct ancestor_score {}; class CBlockPolicyEstimator; +/** + * Information about a mempool transaction. + */ +struct TxMempoolInfo +{ + /** The transaction itself */ + std::shared_ptr tx; + + /** Time the transaction entered the mempool. */ + int64_t nTime; + + /** Feerate of the transaction. */ + CFeeRate feeRate; +}; + /** * CTxMemPool stores valid-according-to-the-current-best-chain * transactions that may be included in the next block. @@ -464,6 +481,8 @@ class CTxMemPool void UpdateParent(txiter entry, txiter parent, bool add); void UpdateChild(txiter entry, txiter child, bool add); + std::vector GetSortedDepthAndScore() const; + public: indirectmap mapNextTx; std::map > mapDeltas; @@ -589,8 +608,9 @@ class CTxMemPool } bool lookup(uint256 hash, CTransaction& result) const; - bool lookup(uint256 hash, CTransaction& result, int64_t& time) const; - bool lookupFeeRate(const uint256& hash, CFeeRate& feeRate) const; + std::shared_ptr get(const uint256& hash) const; + TxMempoolInfo info(const uint256& hash) const; + std::vector infoAll() const; /** Estimate fee rate needed to get into the next nBlocks * If no answer can be given at nBlocks, return an estimate From f0fdda0181e1b05b66541bf235c6702c41664170 Mon Sep 17 00:00:00 2001 From: Kaz Wesley Date: Tue, 26 Apr 2016 17:21:22 -0700 Subject: [PATCH 0409/1802] IsInitialBlockDownload: usually avoid locking Optimistically test the latch bool before taking the lock. For all IsInitialBlockDownload calls after the first to return false, this avoids the need to lock cs_main. --- src/main.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index d2b7c6bc4fba2..aed8a7c4213ca 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -37,6 +37,7 @@ #include "validationinterface.h" #include "versionbits.h" +#include #include #include @@ -1574,18 +1575,24 @@ CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams) bool IsInitialBlockDownload() { const CChainParams& chainParams = Params(); + + // Once this function has returned false, it must remain false. + static std::atomic latchToFalse{false}; + // Optimization: pre-test latch before taking the lock. + if (latchToFalse.load(std::memory_order_relaxed)) + return false; + LOCK(cs_main); + if (latchToFalse.load(std::memory_order_relaxed)) + return false; if (fImporting || fReindex) return true; if (fCheckpointsEnabled && chainActive.Height() < Checkpoints::GetTotalBlocksEstimate(chainParams.Checkpoints())) return true; - static bool lockIBDState = false; - if (lockIBDState) - return false; bool state = (chainActive.Height() < pindexBestHeader->nHeight - 24 * 6 || std::max(chainActive.Tip()->GetBlockTime(), pindexBestHeader->GetBlockTime()) < GetTime() - nMaxTipAge); if (!state) - lockIBDState = true; + latchToFalse.store(true, std::memory_order_relaxed); return state; } From dbfb426b96fbd79fb76734c6b747ef8ee10ad5ab Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 31 May 2016 19:51:45 +0200 Subject: [PATCH 0410/1802] Optimize the relay map to use shared_ptr's * Switch mapRelay to use shared_ptr * Switch the relay code to copy mempool shared_ptr's, rather than copying the transaction itself. * Change vRelayExpiration to store mapRelay iterators rather than hashes (smaller and faster). --- src/main.cpp | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index d71f35bf7e4fc..bf0f0d8964ea0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -80,9 +80,6 @@ uint64_t nPruneTarget = 0; int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE; bool fEnableReplacement = DEFAULT_ENABLE_REPLACEMENT; -std::map mapRelay; -std::deque > vRelayExpiration; -CCriticalSection cs_mapRelay; CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE); CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE; @@ -215,6 +212,12 @@ namespace { /** Number of peers from which we're downloading blocks. */ int nPeersWithValidatedDownloads = 0; + + /** Relay map, protected by cs_main. */ + typedef std::map> MapRelay; + MapRelay mapRelay; + /** Expiration-time ordered list of (expire time, relay map entry) pairs, protected by cs_main). */ + std::deque> vRelayExpiration; } // anon namespace ////////////////////////////////////////////////////////////////////////////// @@ -4505,31 +4508,24 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam } } } - else if (inv.IsKnownType()) + else if (inv.type == MSG_TX) { - CTransaction tx; // Send stream from relay memory bool push = false; - { - LOCK(cs_mapRelay); - map::iterator mi = mapRelay.find(inv.hash); - if (mi != mapRelay.end()) { - tx = (*mi).second; - push = true; - } - } - if (!push && inv.type == MSG_TX) { + auto mi = mapRelay.find(inv.hash); + if (mi != mapRelay.end()) { + pfrom->PushMessage(NetMsgType::TX, *mi->second); + push = true; + } else { auto txinfo = mempool.info(inv.hash); // To protect privacy, do not answer getdata using the mempool when // that TX couldn't have been INVed in reply to a MEMPOOL request. if (txinfo.tx && txinfo.nTime <= pfrom->timeLastMempoolReq) { - tx = *txinfo.tx; + pfrom->PushMessage(NetMsgType::TX, *txinfo.tx); push = true; } } - if (push) { - pfrom->PushMessage(inv.GetCommand(), tx); - } else { + if (!push) { vNotFound.push_back(inv); } } @@ -5978,7 +5974,6 @@ bool SendMessages(CNode* pto) vInv.push_back(CInv(MSG_TX, hash)); nRelayedTransactions++; { - LOCK(cs_mapRelay); // Expire old relay messages while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime()) { @@ -5986,9 +5981,9 @@ bool SendMessages(CNode* pto) vRelayExpiration.pop_front(); } - auto ret = mapRelay.insert(std::make_pair(hash, *txinfo.tx)); + auto ret = mapRelay.insert(std::make_pair(hash, std::move(txinfo.tx))); if (ret.second) { - vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, hash)); + vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, ret.first)); } } if (vInv.size() == MAX_INV_SZ) { From e9b4780b292122fd727426471f025ec3d3eb7b08 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 31 May 2016 20:34:27 +0200 Subject: [PATCH 0411/1802] Optimization: don't check the mempool at all if no mempool req ever --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index bf0f0d8964ea0..68368e402b3d1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4516,7 +4516,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam if (mi != mapRelay.end()) { pfrom->PushMessage(NetMsgType::TX, *mi->second); push = true; - } else { + } else if (pfrom->timeLastMempoolReq) { auto txinfo = mempool.info(inv.hash); // To protect privacy, do not answer getdata using the mempool when // that TX couldn't have been INVed in reply to a MEMPOOL request. From c2a4724642400bc9200aeef4c725b5c07eee9d90 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 31 May 2016 20:35:44 +0200 Subject: [PATCH 0412/1802] Optimization: use usec in expiration and reuse nNow --- src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 68368e402b3d1..db0580bda6142 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5975,7 +5975,7 @@ bool SendMessages(CNode* pto) nRelayedTransactions++; { // Expire old relay messages - while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime()) + while (!vRelayExpiration.empty() && vRelayExpiration.front().first < nNow) { mapRelay.erase(vRelayExpiration.front().second); vRelayExpiration.pop_front(); @@ -5983,7 +5983,7 @@ bool SendMessages(CNode* pto) auto ret = mapRelay.insert(std::make_pair(hash, std::move(txinfo.tx))); if (ret.second) { - vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, ret.first)); + vRelayExpiration.push_back(std::make_pair(nNow + 15 * 60 * 1000000, ret.first)); } } if (vInv.size() == MAX_INV_SZ) { From e6b141acf9dcc0a12f49d53c0bb8a892bae72217 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 6 Jun 2016 10:23:51 +0200 Subject: [PATCH 0413/1802] qt: translation strings update --- src/qt/bitcoinstrings.cpp | 108 ++-- src/qt/locale/bitcoin_en.ts | 1004 +++++++++++++++++++---------------- 2 files changed, 606 insertions(+), 506 deletions(-) diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp index 41f1d5841a659..23be8e016bddf 100644 --- a/src/qt/bitcoinstrings.cpp +++ b/src/qt/bitcoinstrings.cpp @@ -1,26 +1,35 @@ -// Copyright (c) 2013-2015 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 -// Automatically generated by extract_strings.py +// Automatically generated by extract_strings_qt.py #ifdef __GNUC__ #define UNUSED __attribute__((unused)) #else #define UNUSED #endif static const char UNUSED *bitcoin_strings[] = { +QT_TRANSLATE_NOOP("bitcoin-core", "Bitcoin Core"), +QT_TRANSLATE_NOOP("bitcoin-core", "The %s developers"), QT_TRANSLATE_NOOP("bitcoin-core", "" "(1 = keep tx meta data e.g. account owner and payment request information, 2 " "= drop tx meta data)"), QT_TRANSLATE_NOOP("bitcoin-core", "" +"-fallbackfee is set very high! This is the transaction fee you may pay when " +"fee estimates are not available."), +QT_TRANSLATE_NOOP("bitcoin-core", "" "-maxtxfee is set very high! Fees this large could be paid on a single " "transaction."), QT_TRANSLATE_NOOP("bitcoin-core", "" "-paytxfee is set very high! This is the transaction fee you will pay if you " "send a transaction."), QT_TRANSLATE_NOOP("bitcoin-core", "" +"A fee rate (in %s/kB) that will be used when fee estimation has insufficient " +"data (default: %s)"), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Accept relayed transactions received from whitelisted peers even when not " +"relaying transactions (default: %d)"), +QT_TRANSLATE_NOOP("bitcoin-core", "" "Allow JSON-RPC connections from specified source. Valid for 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"), @@ -35,8 +44,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" "notation for IPv6. This option can be specified multiple times (default: " "bind to all interfaces)"), QT_TRANSLATE_NOOP("bitcoin-core", "" -"Cannot obtain a lock on data directory %s. Bitcoin Core is probably already " -"running."), +"Cannot obtain a lock on data directory %s. %s is probably already running."), QT_TRANSLATE_NOOP("bitcoin-core", "" "Create new files with system default permissions, instead of umask 077 (only " "effective with disabled wallet functionality)"), @@ -52,8 +60,8 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" QT_TRANSLATE_NOOP("bitcoin-core", "" "Do not keep transactions in the mempool longer than hours (default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "" -"Error reading wallet.dat! All keys read correctly, but transaction data or " -"address book entries might be missing or incorrect."), +"Error reading %s! All keys read correctly, but transaction data or address " +"book entries might be missing or incorrect."), QT_TRANSLATE_NOOP("bitcoin-core", "" "Error: Listening for incoming connections failed (listen returned error %s)"), QT_TRANSLATE_NOOP("bitcoin-core", "" @@ -72,6 +80,9 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" "Fees (in %s/kB) smaller than this are considered zero fee for transaction " "creation (default: %s)"), QT_TRANSLATE_NOOP("bitcoin-core", "" +"Force relay of transactions from whitelisted peers even they violate local " +"relay policy (default: %d)"), +QT_TRANSLATE_NOOP("bitcoin-core", "" "How thorough the block verification of -checkblocks is (0-4, default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "" "If is not supplied or if = 1, output all debugging " @@ -86,18 +97,22 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" "Maintain a full transaction index, used by the getrawtransaction rpc call " "(default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "" +"Maximum allowed median peer time offset adjustment. Local perspective of " +"time may be influenced by peers forward or backward by this amount. " +"(default: %u seconds)"), +QT_TRANSLATE_NOOP("bitcoin-core", "" "Maximum size of data in data carrier transactions we relay and mine " "(default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "" -"Maximum total fees (in %s) to use in a single wallet transaction; setting " -"this too low may abort large transactions (default: %s)"), +"Maximum total fees (in %s) to use in a single wallet transaction or raw " +"transaction; setting this too low may abort large transactions (default: %s)"), QT_TRANSLATE_NOOP("bitcoin-core", "" "Number of seconds to keep misbehaving peers from reconnecting (default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "" "Output debugging information (default: %u, supplying is optional)"), QT_TRANSLATE_NOOP("bitcoin-core", "" "Please check that your computer's date and time are correct! If your clock " -"is wrong Bitcoin Core will not work properly."), +"is wrong, %s will not work properly."), QT_TRANSLATE_NOOP("bitcoin-core", "" "Prune configured below the minimum of %d MiB. Please use a higher number."), QT_TRANSLATE_NOOP("bitcoin-core", "" @@ -123,11 +138,10 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" "Set the number of script verification threads (%u to %d, 0 = auto, <0 = " "leave that many cores free, default: %d)"), QT_TRANSLATE_NOOP("bitcoin-core", "" -"Set the number of threads for coin generation if enabled (-1 = all cores, " -"default: %d)"), -QT_TRANSLATE_NOOP("bitcoin-core", "" "Support filtering of blocks and transaction with bloom filters (default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "" +"Tell other nodes to filter invs to us by our mempool min fee (default: %u)"), +QT_TRANSLATE_NOOP("bitcoin-core", "" "The block database contains a block which appears to be from the future. " "This may be due to your computer's date and time being set incorrectly. Only " "rebuild the block database if you are sure that your computer's date and " @@ -148,12 +162,12 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" "Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = " "no limit (default: %d)"), QT_TRANSLATE_NOOP("bitcoin-core", "" -"Unable to bind to %s on this computer. Bitcoin Core is probably already " -"running."), -QT_TRANSLATE_NOOP("bitcoin-core", "" "Unsupported argument -socks found. Setting SOCKS version isn't possible " "anymore, only SOCKS5 proxies are supported."), QT_TRANSLATE_NOOP("bitcoin-core", "" +"Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/" +"or -whitelistforcerelay."), +QT_TRANSLATE_NOOP("bitcoin-core", "" "Use UPnP to map the listening port (default: 1 when listening and no -proxy)"), QT_TRANSLATE_NOOP("bitcoin-core", "" "Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: " @@ -172,13 +186,16 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" "Warning: The network does not appear to fully agree! Some miners appear to " "be experiencing issues."), QT_TRANSLATE_NOOP("bitcoin-core", "" +"Warning: Unknown block versions being mined! It's possible unknown rules are " +"in effect"), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; " +"if your balance or transactions are incorrect you should restore from a " +"backup."), +QT_TRANSLATE_NOOP("bitcoin-core", "" "Warning: We do not appear to fully agree with our peers! You may need to " "upgrade, or other nodes may need to upgrade."), QT_TRANSLATE_NOOP("bitcoin-core", "" -"Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as " -"wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect " -"you should restore from a backup."), -QT_TRANSLATE_NOOP("bitcoin-core", "" "Whitelist peers connecting from the given netmask or IP address. Can be " "specified multiple times."), QT_TRANSLATE_NOOP("bitcoin-core", "" @@ -187,6 +204,9 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" QT_TRANSLATE_NOOP("bitcoin-core", "" "You need to rebuild the database using -reindex to go back to unpruned " "mode. This will redownload the entire blockchain"), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"You need to rebuild the database using -reindex-chainstate to change -txindex"), +QT_TRANSLATE_NOOP("bitcoin-core", "%s corrupt, salvage failed"), QT_TRANSLATE_NOOP("bitcoin-core", "(default: %s)"), QT_TRANSLATE_NOOP("bitcoin-core", "(default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "-maxmempool must be at least %d MB"), @@ -194,24 +214,22 @@ QT_TRANSLATE_NOOP("bitcoin-core", " can be:"), QT_TRANSLATE_NOOP("bitcoin-core", "Accept command line and JSON-RPC commands"), QT_TRANSLATE_NOOP("bitcoin-core", "Accept connections from outside (default: 1 if no -proxy or -connect)"), QT_TRANSLATE_NOOP("bitcoin-core", "Accept public REST requests (default: %u)"), -QT_TRANSLATE_NOOP("bitcoin-core", "Activating best chain..."), QT_TRANSLATE_NOOP("bitcoin-core", "Add a node to connect to and attempt to keep the connection open"), QT_TRANSLATE_NOOP("bitcoin-core", "Allow DNS lookups for -addnode, -seednode and -connect"), QT_TRANSLATE_NOOP("bitcoin-core", "Always query for peer addresses via DNS lookup (default: %u)"), -QT_TRANSLATE_NOOP("bitcoin-core", "Always relay transactions received from whitelisted peers (default: %d)"), -QT_TRANSLATE_NOOP("bitcoin-core", "Attempt to recover private keys from a corrupt wallet.dat on startup"), +QT_TRANSLATE_NOOP("bitcoin-core", "Append comment to the user agent string"), +QT_TRANSLATE_NOOP("bitcoin-core", "Attempt to recover private keys from a corrupt wallet on startup"), QT_TRANSLATE_NOOP("bitcoin-core", "Automatically create Tor hidden service (default: %d)"), QT_TRANSLATE_NOOP("bitcoin-core", "Block creation options:"), QT_TRANSLATE_NOOP("bitcoin-core", "Cannot downgrade wallet"), -QT_TRANSLATE_NOOP("bitcoin-core", "Cannot resolve -bind address: '%s'"), -QT_TRANSLATE_NOOP("bitcoin-core", "Cannot resolve -externalip address: '%s'"), -QT_TRANSLATE_NOOP("bitcoin-core", "Cannot resolve -whitebind address: '%s'"), +QT_TRANSLATE_NOOP("bitcoin-core", "Cannot resolve -%s address: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Cannot write default address"), +QT_TRANSLATE_NOOP("bitcoin-core", "Change index out of range"), QT_TRANSLATE_NOOP("bitcoin-core", "Connect only to the specified node(s)"), QT_TRANSLATE_NOOP("bitcoin-core", "Connect through SOCKS5 proxy"), QT_TRANSLATE_NOOP("bitcoin-core", "Connect to a node to retrieve peer addresses, and disconnect"), QT_TRANSLATE_NOOP("bitcoin-core", "Connection options:"), -QT_TRANSLATE_NOOP("bitcoin-core", "Copyright (C) 2009-%i The Bitcoin Core Developers"), +QT_TRANSLATE_NOOP("bitcoin-core", "Copyright (C) %i-%i"), QT_TRANSLATE_NOOP("bitcoin-core", "Corrupted block database detected"), QT_TRANSLATE_NOOP("bitcoin-core", "Debugging/Testing options:"), QT_TRANSLATE_NOOP("bitcoin-core", "Do not load the wallet and disable wallet RPC calls"), @@ -221,12 +239,13 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Enable publish hash block in
"), QT_TRANSLATE_NOOP("bitcoin-core", "Enable publish hash transaction in
"), QT_TRANSLATE_NOOP("bitcoin-core", "Enable publish raw block in
"), QT_TRANSLATE_NOOP("bitcoin-core", "Enable publish raw transaction in
"), +QT_TRANSLATE_NOOP("bitcoin-core", "Enable transaction replacement in the memory pool (default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "Error initializing block database"), QT_TRANSLATE_NOOP("bitcoin-core", "Error initializing wallet database environment %s!"), +QT_TRANSLATE_NOOP("bitcoin-core", "Error loading %s"), +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.dat"), -QT_TRANSLATE_NOOP("bitcoin-core", "Error loading wallet.dat: Wallet corrupted"), -QT_TRANSLATE_NOOP("bitcoin-core", "Error loading wallet.dat: Wallet requires newer version of Bitcoin Core"), 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"), @@ -234,34 +253,34 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Error: A fatal internal error occurred, see d QT_TRANSLATE_NOOP("bitcoin-core", "Error: Disk space is low!"), QT_TRANSLATE_NOOP("bitcoin-core", "Failed to listen on any port. Use -listen=0 if you want this."), QT_TRANSLATE_NOOP("bitcoin-core", "Fee (in %s/kB) to add to transactions you send (default: %s)"), -QT_TRANSLATE_NOOP("bitcoin-core", "Generate coins (default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "How many blocks to check at startup (default: %u, 0 = all)"), QT_TRANSLATE_NOOP("bitcoin-core", "Importing..."), QT_TRANSLATE_NOOP("bitcoin-core", "Imports blocks from external blk000??.dat file on startup"), QT_TRANSLATE_NOOP("bitcoin-core", "Include IP addresses in debug output (default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "Incorrect or no genesis block found. Wrong datadir for network?"), QT_TRANSLATE_NOOP("bitcoin-core", "Information"), -QT_TRANSLATE_NOOP("bitcoin-core", "Initialization sanity check failed. Bitcoin Core is shutting down."), +QT_TRANSLATE_NOOP("bitcoin-core", "Initialization sanity check failed. %s is shutting down."), QT_TRANSLATE_NOOP("bitcoin-core", "Insufficient funds"), QT_TRANSLATE_NOOP("bitcoin-core", "Invalid -onion address: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Invalid -proxy address: '%s'"), -QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -maxtxfee=: '%s'"), -QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -minrelaytxfee=: '%s'"), -QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -mintxfee=: '%s'"), +QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -%s=: '%s'"), +QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -fallbackfee=: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -paytxfee=: '%s' (must be at least %s)"), -QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -paytxfee=: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Invalid netmask specified in -whitelist: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Keep at most unconnectable transactions in memory (default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "Keep the transaction memory pool below megabytes (default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "Listen for JSON-RPC connections on (default: %u or testnet: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "Listen for connections on (default: %u or testnet: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "Loading addresses..."), +QT_TRANSLATE_NOOP("bitcoin-core", "Loading banlist..."), QT_TRANSLATE_NOOP("bitcoin-core", "Loading block index..."), QT_TRANSLATE_NOOP("bitcoin-core", "Loading wallet..."), +QT_TRANSLATE_NOOP("bitcoin-core", "Location of the auth cookie (default: data dir)"), QT_TRANSLATE_NOOP("bitcoin-core", "Maintain at most connections to peers (default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "Make the wallet broadcast transactions"), QT_TRANSLATE_NOOP("bitcoin-core", "Maximum per-connection receive buffer, *1000 bytes (default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "Maximum per-connection send buffer, *1000 bytes (default: %u)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Minimum bytes per sigop in transactions we relay and mine (default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "Need to specify a port with -whitebind: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Node relay options:"), QT_TRANSLATE_NOOP("bitcoin-core", "Not enough file descriptors available."), @@ -269,12 +288,14 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Only connect to nodes in network (ipv4, QT_TRANSLATE_NOOP("bitcoin-core", "Options:"), QT_TRANSLATE_NOOP("bitcoin-core", "Password for JSON-RPC connections"), QT_TRANSLATE_NOOP("bitcoin-core", "Prepend debug output with timestamp (default: %u)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Print this help message and exit"), +QT_TRANSLATE_NOOP("bitcoin-core", "Print version and exit"), QT_TRANSLATE_NOOP("bitcoin-core", "Prune cannot be configured with a negative value."), QT_TRANSLATE_NOOP("bitcoin-core", "Prune mode is incompatible with -txindex."), QT_TRANSLATE_NOOP("bitcoin-core", "Pruning blockstore..."), QT_TRANSLATE_NOOP("bitcoin-core", "RPC server options:"), -QT_TRANSLATE_NOOP("bitcoin-core", "Rebuild block chain index from current blk000??.dat files on startup"), -QT_TRANSLATE_NOOP("bitcoin-core", "Receive and display P2P network alerts (default: %u)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Rebuild chain state and block index from the blk*.dat files on disk"), +QT_TRANSLATE_NOOP("bitcoin-core", "Rebuild chain state from the currently indexed blocks"), QT_TRANSLATE_NOOP("bitcoin-core", "Reducing -maxconnections from %d to %d, because of system limitations."), QT_TRANSLATE_NOOP("bitcoin-core", "Relay and mine data carrier transactions (default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "Relay non-P2SH multisig (default: %u)"), @@ -299,7 +320,6 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Specify wallet file (within data directory)") QT_TRANSLATE_NOOP("bitcoin-core", "Specify your own public address"), QT_TRANSLATE_NOOP("bitcoin-core", "Spend unconfirmed change when sending transactions (default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "The transaction amount is too small to pay the fee"), -QT_TRANSLATE_NOOP("bitcoin-core", "This help message"), QT_TRANSLATE_NOOP("bitcoin-core", "This is experimental software."), QT_TRANSLATE_NOOP("bitcoin-core", "Threshold for disconnecting misbehaving peers (default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "Tor control port password (default: empty)"), @@ -309,6 +329,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Transaction amounts must be positive"), QT_TRANSLATE_NOOP("bitcoin-core", "Transaction too large for fee policy"), QT_TRANSLATE_NOOP("bitcoin-core", "Transaction too large"), QT_TRANSLATE_NOOP("bitcoin-core", "Unable to bind to %s on this computer (bind returned error %s)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Unable to bind to %s on this computer. %s is probably already running."), QT_TRANSLATE_NOOP("bitcoin-core", "Unable to start HTTP server. See debug log for details."), QT_TRANSLATE_NOOP("bitcoin-core", "Unknown network specified in -onlynet: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Unsupported argument -benchmark ignored, use -debug=bench."), @@ -321,13 +342,12 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Username for JSON-RPC connections"), QT_TRANSLATE_NOOP("bitcoin-core", "Verifying blocks..."), QT_TRANSLATE_NOOP("bitcoin-core", "Verifying wallet..."), QT_TRANSLATE_NOOP("bitcoin-core", "Wallet %s resides outside data directory %s"), -QT_TRANSLATE_NOOP("bitcoin-core", "Wallet needed to be rewritten: restart Bitcoin Core to complete"), +QT_TRANSLATE_NOOP("bitcoin-core", "Wallet debugging/testing options:"), +QT_TRANSLATE_NOOP("bitcoin-core", "Wallet needed to be rewritten: restart %s to complete"), QT_TRANSLATE_NOOP("bitcoin-core", "Wallet options:"), QT_TRANSLATE_NOOP("bitcoin-core", "Warning"), -QT_TRANSLATE_NOOP("bitcoin-core", "Warning: This version is obsolete; upgrade required!"), +QT_TRANSLATE_NOOP("bitcoin-core", "Warning: unknown new rules activated (versionbit %i)"), QT_TRANSLATE_NOOP("bitcoin-core", "Whether to operate in a blocks only mode (default: %u)"), -QT_TRANSLATE_NOOP("bitcoin-core", "You need to rebuild the database using -reindex to change -txindex"), QT_TRANSLATE_NOOP("bitcoin-core", "Zapping all transactions from wallet..."), QT_TRANSLATE_NOOP("bitcoin-core", "ZeroMQ notification options:"), -QT_TRANSLATE_NOOP("bitcoin-core", "wallet.dat corrupt, salvage failed"), }; diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts index 00411741f1b9a..5549ccd4f80f9 100644 --- a/src/qt/locale/bitcoin_en.ts +++ b/src/qt/locale/bitcoin_en.ts @@ -165,7 +165,7 @@ Repeat new passphrase - + Encrypt wallet Encrypt wallet @@ -195,7 +195,7 @@ Change passphrase - + Confirm wallet encryption Confirm wallet encryption @@ -210,12 +210,7 @@ Are you sure you wish to encrypt your wallet? - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - - - - + 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. 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. @@ -232,7 +227,7 @@ Wallet encrypted - + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. @@ -242,7 +237,12 @@ - + + %1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. + + + + @@ -299,17 +299,17 @@ BitcoinGUI - + Sign &message... Sign &message... - + Synchronizing with network... Synchronizing with network... - + &Overview &Overview @@ -344,7 +344,17 @@ Quit application - + + &About %1 + + + + + Show information about %1 + + + + About &Qt About &Qt @@ -358,6 +368,11 @@ &Options... &Options... + + + Modify configuration options for %1 + + &Encrypt Wallet... @@ -374,7 +389,7 @@ &Change Passphrase... - + &Sending addresses... @@ -389,27 +404,17 @@ - - Bitcoin Core client - - - - - Importing blocks from disk... - Importing blocks from disk... - - - + Reindexing blocks on disk... Reindexing blocks on disk... - + Send coins to a Bitcoin address Send coins to a Bitcoin address - + Backup wallet to another location Backup wallet to another location @@ -434,12 +439,12 @@ &Verify message... - + Bitcoin Bitcoin - + Wallet Wallet @@ -454,12 +459,7 @@ &Receive - - Show information about Bitcoin Core - - - - + &Show / Hide &Show / Hide @@ -484,7 +484,7 @@ Verify messages to ensure they were signed with specified Bitcoin addresses - + &File &File @@ -504,27 +504,12 @@ Tabs toolbar - - Bitcoin Core - Bitcoin Core - - - + Request payments (generates QR codes and bitcoin: URIs) - - &About Bitcoin Core - - - - - Modify configuration options for Bitcoin Core - - - - + Show the list of used sending addresses and labels @@ -543,13 +528,8 @@ &Command-line options - - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - - - + %n active connection(s) to Bitcoin network %n active connection to Bitcoin network @@ -557,7 +537,17 @@ - + + Indexing blocks on disk... + + + + + Processing blocks on disk... + + + + No block source available... No block source available... @@ -643,12 +633,22 @@ Up to date - + + Show the %1 help message to get a list with possible Bitcoin command-line options + + + + + %1 client + + + + Catching up... Catching up... - + Date: %1 @@ -698,14 +698,6 @@ Wallet is <b>encrypted</b> and currently <b>locked</b> - - ClientModel - - - Network Alert - Network Alert - - CoinControlDialog @@ -870,7 +862,7 @@ - + highest @@ -935,12 +927,7 @@ - - This label turns red if any recipient receives an amount smaller than %1. - - - - + Can vary +/- %1 satoshi(s) per input. @@ -971,7 +958,12 @@ - + + This label turns red if any recipient receives an amount smaller than the current dust threshold. + + + + (no label) (no label) @@ -1058,7 +1050,7 @@ FreespaceChecker - + A new data directory will be created. A new data directory will be created. @@ -1086,12 +1078,7 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin Core - - - + version version @@ -1103,7 +1090,7 @@ - About Bitcoin Core + About %1 @@ -1166,17 +1153,17 @@ - Welcome to Bitcoin Core. + Welcome to %1. - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. + As this is the first time the program is launched, you can choose where %1 will store its data. - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. + %1 will download and store a copy of the Bitcoin block chain. At least %2GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. @@ -1190,12 +1177,7 @@ Use a custom data directory: - - Bitcoin Core - Bitcoin Core - - - + Error: Specified data directory "%1" cannot be created. @@ -1262,7 +1244,17 @@ &Main - + + Automatically start %1 after logging in to the system. + + + + + &Start %1 on system login + + + + Size of &database cache @@ -1293,17 +1285,12 @@ - + 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. - - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - - - - + 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 |. @@ -1329,22 +1316,12 @@ &Reset Options - + &Network &Network - - Automatically start Bitcoin Core after logging in to the system. - - - - - &Start Bitcoin Core on system login - - - - + (0 = auto, <0 = leave that many cores free) @@ -1455,6 +1432,16 @@ + &Hide the icon from the system tray. + + + + + Hide tray icon + + + + Show only a tray icon after minimizing the window. Show only a tray icon after minimizing the window. @@ -1479,7 +1466,12 @@ User Interface &language: - + + The user interface language can be set here. This setting will take effect after restarting %1. + + + + &Unit to show amounts in: &Unit to show amounts in: @@ -1489,12 +1481,12 @@ Choose the default subdivision unit to show in the interface and when sending coins. - + Whether to show coin control features or not. - + &OK &OK @@ -1504,7 +1496,7 @@ &Cancel - + default default @@ -1514,23 +1506,23 @@ - + Confirm options reset Confirm options reset - + Client restart required to activate changes. - + Client will be shut down. Do you want to proceed? - + This change would require a client restart. @@ -1781,12 +1773,12 @@ QObject - + Amount Amount - + Enter a Bitcoin address (e.g. %1) @@ -1807,7 +1799,7 @@ - + %1 s @@ -1862,16 +1854,15 @@ - - - - + + - + + @@ -1892,7 +1883,7 @@ N/A - + Client version Client version @@ -1913,26 +1904,26 @@ - Using OpenSSL version - Using OpenSSL version + Using BerkeleyDB version + - Using BerkeleyDB version + Datadir - + Startup time Startup time - + Network Network - + Name @@ -1962,41 +1953,36 @@ - + Memory usage - - Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. - - - - - + + Received - - + + Sent - + &Peers - + Banned peers - - - + + + Select a peer to view detailed information. @@ -2031,13 +2017,28 @@ - - + + User Agent - + + Open the %1 debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Decrease font size + + + + + Increase font size + + + + Services @@ -2082,12 +2083,12 @@ - + Last block time Last block time - + &Open &Open @@ -2097,7 +2098,7 @@ &Console - + &Network Traffic @@ -2112,7 +2113,7 @@ - + In: @@ -2122,22 +2123,17 @@ - - Build date - Build date - - - + Debug log file Debug log file - + Clear console Clear console - + &Disconnect Node @@ -2175,8 +2171,8 @@ - - Welcome to the Bitcoin Core RPC console. + + Welcome to the %1 RPC console. @@ -2190,7 +2186,7 @@ Type <b>help</b> for an overview of available commands. - + %1 B @@ -2444,9 +2440,14 @@ Message - - Amount - Amount + + (no amount requested) + + + + + Requested + @@ -2458,17 +2459,12 @@ (no message) - - - (no amount) - - SendCoinsDialog - + Send Coins Send Coins @@ -2615,17 +2611,7 @@ - - Send as zero-fee transaction if possible - - - - - (confirmation may take longer) - - - - + Send to multiple recipients at once Send to multiple recipients at once @@ -2640,12 +2626,12 @@ - + Dust: - + Clear &All Clear &All @@ -2678,7 +2664,7 @@ - + Copy quantity @@ -2713,7 +2699,7 @@ - + Total Amount %1 @@ -2758,12 +2744,12 @@ - + Pay only the required fee of %1 - + Estimated to begin confirmation within %n block(s). Estimated to begin confirmation within %n block. @@ -2796,12 +2782,12 @@ - + Copy dust - + Are you sure you want to send? @@ -2920,11 +2906,20 @@ + + SendConfirmationDialog + + + + Yes + + + ShutdownWindow - Bitcoin Core is shutting down... + %1 is shutting down... @@ -3117,16 +3112,6 @@ SplashScreen - - - Bitcoin Core - Bitcoin Core - - - - The Bitcoin Core developers - - [testnet] @@ -3149,14 +3134,29 @@ Open until %1 - - conflicted - + + %1/offline + %1/offline - %1/offline - %1/offline + 0/unconfirmed, %1 + + + + + in memory pool + + + + + not in memory pool + + + + + abandoned + @@ -3231,12 +3231,12 @@ - + Credit Credit - + matures in %n more block(s) matures in %n more block @@ -3251,12 +3251,12 @@ - + Debit Debit - + Total debit @@ -3277,12 +3277,12 @@ - + Message Message - + Comment Comment @@ -3291,6 +3291,11 @@ Transaction ID Transaction ID + + + Output index + + Merchant @@ -3334,12 +3339,12 @@ false - + , has not been successfully broadcast yet , has not been successfully broadcast yet - + Open for %n more block(s) Open for %n more block @@ -3347,7 +3352,12 @@ - + + conflicted with a transaction with %1 confirmations + + + + unknown unknown @@ -3355,15 +3365,15 @@ TransactionDescDialog - - Transaction details - Transaction details - - - + This pane shows a detailed description of the transaction This pane shows a detailed description of the transaction + + + Details for %1 + + TransactionTableModel @@ -3378,12 +3388,12 @@ Type - + Immature (%1 confirmations, will be available after %2) - + Open for %n more block(s) Open for %n more block @@ -3396,7 +3406,7 @@ Open until %1 - + Confirmed (%1 confirmations) Confirmed (%1 confirmations) @@ -3411,7 +3421,7 @@ Generated but not accepted - + Offline @@ -3425,6 +3435,11 @@ Unconfirmed + + + Abandoned + + Confirming (%1 of %2 recommended confirmations) @@ -3471,7 +3486,12 @@ (n/a) - + + (no label) + (no label) + + + Transaction status. Hover over this field to show number of confirmations. Transaction status. Hover over this field to show number of confirmations. @@ -3576,6 +3596,11 @@ + Abandon transaction + + + + Copy address Copy address @@ -3599,6 +3624,11 @@ Copy raw transaction + + + Copy full transaction details + + Edit label @@ -3610,7 +3640,7 @@ Show transaction details - + Export Transaction History @@ -3675,7 +3705,7 @@ ID - + Range: Range: @@ -3688,7 +3718,7 @@ UnitDisplayStatusBarControl - + Unit to show amounts in. Click to select another unit. @@ -3755,47 +3785,37 @@ bitcoin-core - + Options: Options: - + Specify data directory Specify data directory - + Connect to a node to retrieve peer addresses, and disconnect Connect to a node to retrieve peer addresses, and disconnect - + Specify your own public address Specify your own public address - + Accept command line and JSON-RPC commands Accept command line and JSON-RPC commands - + If <category> is not supplied or if <category> = 1, output all debugging information. - - Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s) - - - - - Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. - - - - + Prune configured below the minimum of %d MiB. Please use a higher number. @@ -3815,7 +3835,7 @@ - + Error: A fatal internal error occurred, see debug.log for details @@ -3825,7 +3845,7 @@ - + Pruning blockstore... @@ -3840,17 +3860,47 @@ - + Accept connections from outside (default: 1 if no -proxy or -connect) Accept connections from outside (default: 1 if no -proxy or -connect) - + + Bitcoin Core + Bitcoin Core + + + + The %s developers + + + + + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. + + + + + A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s) + + + + + Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d) + + + + Bind to given address and always listen on it. Use [host]:port notation for IPv6 Bind to given address and always listen on it. Use [host]:port notation for IPv6 - + + Cannot obtain a lock on data directory %s. %s is probably already running. + + + + Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup @@ -3860,17 +3910,47 @@ - + + Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) - + + Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) + + + + + Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds) + + + + + Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s) + + + + + Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly. + + + + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) - + + Tell other nodes to filter invs to us by our mempool min fee (default: %u) + + + + 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 @@ -3880,12 +3960,7 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications - - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - - - - + Use UPnP to map the listening port (default: 1 when listening and no -proxy) @@ -3905,22 +3980,27 @@ Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. - + Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. + - - Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. + + You need to rebuild the database using -reindex-chainstate to change -txindex - + + %s corrupt, salvage failed + + + + -maxmempool must be at least %d MB @@ -3930,12 +4010,32 @@ - + + Append comment to the user agent string + + + + + Attempt to recover private keys from a corrupt wallet on startup + + + + Block creation options: Block creation options: - + + Cannot resolve -%s address: '%s' + + + + + Change index out of range + + + + Connect only to the specified node(s) Connect only to the specified node(s) @@ -3945,7 +4045,12 @@ - + + Copyright (C) %i-%i + + + + Corrupted block database detected Corrupted block database detected @@ -3984,6 +4089,11 @@ Enable publish raw transaction in <address> + + + Enable transaction replacement in the memory pool (default: %u) + + Error initializing block database @@ -3994,13 +4104,28 @@ Error initializing wallet database environment %s! Error initializing wallet database environment %s! + + + Error loading %s + + + + + Error loading %s: Wallet corrupted + + + + + Error loading %s: Wallet requires newer version of %s + + Error loading block database Error loading block database - + Error opening block database Error opening block database @@ -4015,7 +4140,7 @@ Failed to listen on any port. Use -listen=0 if you want this. - + Importing... @@ -4025,17 +4150,47 @@ Incorrect or no genesis block found. Wrong datadir for network? - + + Initialization sanity check failed. %s is shutting down. + + + + Invalid -onion address: '%s' - + + Invalid amount for -%s=<amount>: '%s' + + + + + Invalid amount for -fallbackfee=<amount>: '%s' + + + + Keep the transaction memory pool below <n> megabytes (default: %u) - + + Loading banlist... + + + + + Location of the auth cookie (default: data dir) + + + + + Minimum bytes per sigop in transactions we relay and mine (default: %u) + + + + Not enough file descriptors available. Not enough file descriptors available. @@ -4046,6 +4201,16 @@ + Print this help message and exit + + + + + Print version and exit + + + + Prune cannot be configured with a negative value. @@ -4055,7 +4220,17 @@ - + + Rebuild chain state and block index from the blk*.dat files on disk + + + + + Rebuild chain state from the currently indexed blocks + + + + Set database cache size in megabytes (%d to %d, default: %d) @@ -4070,7 +4245,12 @@ Specify wallet file (within data directory) - + + Unable to bind to %s on this computer. %s is probably already running. + + + + Unsupported argument -benchmark ignored, use -debug=bench. @@ -4110,22 +4290,22 @@ Wallet %s resides outside data directory %s - - Wallet options: + + Wallet debugging/testing options: - - Warning: This version is obsolete; upgrade required! + + Wallet needed to be rewritten: restart %s to complete - - You need to rebuild the database using -reindex to change -txindex - You need to rebuild the database using -reindex to change -txindex + + Wallet options: + - + 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 @@ -4140,12 +4320,7 @@ - - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - - - - + Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) @@ -4170,7 +4345,7 @@ - + If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u) @@ -4180,7 +4355,7 @@ - + Maximum size of data in data carrier transactions we relay and mine (default: %u) @@ -4200,12 +4375,7 @@ - - Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) - - - - + The transaction amount is too small to send after the fee has been deducted @@ -4215,7 +4385,7 @@ - + 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 @@ -4225,7 +4395,7 @@ - + (default: %u) @@ -4235,52 +4405,22 @@ - - Activating best chain... - - - - - Always relay transactions received from whitelisted peers (default: %d) - - - - - Attempt to recover private keys from a corrupt wallet.dat on startup - - - - + Automatically create Tor hidden service (default: %d) - - Cannot resolve -whitebind address: '%s' - - - - + Connect through SOCKS5 proxy - - Copyright (C) 2009-%i The Bitcoin Core Developers - - - - - Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - - - - + Error reading from database, shutting down. - + Imports blocks from external blk000??.dat file on startup @@ -4290,32 +4430,12 @@ Information - - Initialization sanity check failed. Bitcoin Core is shutting down. - - - - - Invalid amount for -maxtxfee=<amount>: '%s' - - - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Invalid amount for -minrelaytxfee=<amount>: '%s' - - - - Invalid amount for -mintxfee=<amount>: '%s' - Invalid amount for -mintxfee=<amount>: '%s' - - - + Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) - + Invalid netmask specified in -whitelist: '%s' @@ -4325,7 +4445,7 @@ - + Need to specify a port with -whitebind: '%s' @@ -4335,22 +4455,12 @@ - + RPC server options: - - Rebuild block chain index from current blk000??.dat files on startup - - - - - Receive and display P2P network alerts (default: %u) - - - - + Reducing -maxconnections from %d to %d, because of system limitations. @@ -4390,7 +4500,7 @@ - + This is experimental software. @@ -4430,7 +4540,7 @@ - + Upgrade wallet to latest format on startup @@ -4440,72 +4550,57 @@ Username for JSON-RPC connections - - Wallet needed to be rewritten: restart Bitcoin Core to complete - - - - + Warning Warning - - Whether to operate in a blocks only mode (default: %u) + + Warning: unknown new rules activated (versionbit %i) - - Zapping all transactions from wallet... + + Whether to operate in a blocks only mode (default: %u) - ZeroMQ notification options: + Zapping all transactions from wallet... - wallet.dat corrupt, salvage failed - wallet.dat corrupt, salvage failed + ZeroMQ notification options: + - + Password for JSON-RPC connections Password for JSON-RPC connections - + Execute command when the best block changes (%s in cmd is replaced by block hash) Execute command when the best block changes (%s in cmd is replaced by block hash) - - This help message - This help message - - - + Allow DNS lookups for -addnode, -seednode and -connect Allow DNS lookups for -addnode, -seednode and -connect - + Loading addresses... Loading addresses... - - Error loading wallet.dat: Wallet corrupted - Error loading wallet.dat: Wallet corrupted - - - + (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) - + -maxtxfee is set very high! Fees this large could be paid on a single transaction. @@ -4515,22 +4610,17 @@ - + Do not keep transactions in the mempool longer than <n> hours (default: %u) - - Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. - - - - + Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) - + How thorough the block verification of -checkblocks is (0-4, default: %u) @@ -4540,7 +4630,7 @@ - + Number of seconds to keep misbehaving peers from reconnecting (default: %u) @@ -4550,12 +4640,12 @@ - + Support filtering of blocks and transaction with bloom filters (default: %u) - + Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments. @@ -4565,10 +4655,15 @@ - + Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported. + + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + + Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s) @@ -4580,27 +4675,27 @@ - - (default: %s) + + Warning: Unknown block versions being mined! It's possible unknown rules are in effect - - Always query for peer addresses via DNS lookup (default: %u) + + Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup. - - Error loading wallet.dat - Error loading wallet.dat + + (default: %s) + - - Generate coins (default: %u) + + Always query for peer addresses via DNS lookup (default: %u) - + How many blocks to check at startup (default: %u, 0 = all) @@ -4615,7 +4710,7 @@ Invalid -proxy address: '%s' - + Listen for JSON-RPC connections on <port> (default: %u or testnet: %u) @@ -4625,7 +4720,7 @@ - + Maintain at most <n> connections to peers (default: %u) @@ -4645,12 +4740,12 @@ - + Prepend debug output with timestamp (default: %u) - + Relay and mine data carrier transactions (default: %u) @@ -4695,72 +4790,57 @@ - + Threshold for disconnecting misbehaving peers (default: %u) - + Unknown network specified in -onlynet: '%s' Unknown network specified in -onlynet: '%s' - - Cannot resolve -bind address: '%s' - Cannot resolve -bind address: '%s' - - - - Cannot resolve -externalip address: '%s' - Cannot resolve -externalip address: '%s' - - - - Invalid amount for -paytxfee=<amount>: '%s' - Invalid amount for -paytxfee=<amount>: '%s' - - - + Insufficient funds Insufficient funds - + Loading block index... Loading block index... - + Add a node to connect to and attempt to keep the connection open Add a node to connect to and attempt to keep the connection open - + Loading wallet... Loading wallet... - + Cannot downgrade wallet Cannot downgrade wallet - + Cannot write default address Cannot write default address - + Rescanning... Rescanning... - + Done loading Done loading - + Error Error From 2e494489c35499dbe7891d4c07b4c35b178341d1 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 17 Mar 2016 12:49:16 +0100 Subject: [PATCH 0414/1802] tor: Change auth order to only use HASHEDPASSWORD if -torpassword Change authentication order to make it more clear (see #7700). - If the `-torpassword` option is provided, force use of `HASHEDPASSWORD` auth. - Give error message if `-torpassword` provided, but `HASHEDPASSWORD` auth is not available. - Give error message if only `HASHEDPASSWORD` available, but `-torpassword` not given. --- src/torcontrol.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index 1c7bc2dbeee6b..6fabe54afeb90 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -574,7 +574,15 @@ void TorController::protocolinfo_cb(TorControlConnection& conn, const TorControl * password: "password" */ std::string torpassword = GetArg("-torpassword", ""); - if (methods.count("NULL")) { + if (!torpassword.empty()) { + if (methods.count("HASHEDPASSWORD")) { + LogPrint("tor", "tor: Using HASHEDPASSWORD authentication\n"); + boost::replace_all(torpassword, "\"", "\\\""); + conn.Command("AUTHENTICATE \"" + torpassword + "\"", boost::bind(&TorController::auth_cb, this, _1, _2)); + } else { + LogPrintf("tor: Password provided with -torpassword, but HASHEDPASSWORD authentication is not available\n"); + } + } else if (methods.count("NULL")) { LogPrint("tor", "tor: Using NULL authentication\n"); conn.Command("AUTHENTICATE", boost::bind(&TorController::auth_cb, this, _1, _2)); } else if (methods.count("SAFECOOKIE")) { @@ -595,13 +603,7 @@ void TorController::protocolinfo_cb(TorControlConnection& conn, const TorControl } } } else if (methods.count("HASHEDPASSWORD")) { - if (!torpassword.empty()) { - LogPrint("tor", "tor: Using HASHEDPASSWORD authentication\n"); - boost::replace_all(torpassword, "\"", "\\\""); - conn.Command("AUTHENTICATE \"" + torpassword + "\"", boost::bind(&TorController::auth_cb, this, _1, _2)); - } else { - LogPrintf("tor: Password authentication required, but no password provided with -torpassword\n"); - } + LogPrintf("tor: The only supported authentication mechanism left is password, but no password provided with -torpassword\n"); } else { LogPrintf("tor: No supported authentication method\n"); } From 152ab236ea1c1106340196f45918fd84f57a0b63 Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Thu, 2 Jun 2016 23:16:42 -0700 Subject: [PATCH 0415/1802] Improve CWallet API with new GetAccountPubkey function. Remove one more caller that is passing CWalletDB. --- src/wallet/rpcwallet.cpp | 34 ++++------------------------------ src/wallet/wallet.cpp | 38 ++++++++++++++++++++++++++++++++++++++ src/wallet/wallet.h | 1 + 3 files changed, 43 insertions(+), 30 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 42b37ea7784f0..5e6afcd7cb124 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -146,38 +146,12 @@ UniValue getnewaddress(const UniValue& params, bool fHelp) CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false) { - CWalletDB walletdb(pwalletMain->strWalletFile); - - CAccount account; - walletdb.ReadAccount(strAccount, account); - - if (!bForceNew) { - if (!account.vchPubKey.IsValid()) - bForceNew = true; - else { - // Check if the current key has been used - CScript scriptPubKey = GetScriptForDestination(account.vchPubKey.GetID()); - for (map::iterator it = pwalletMain->mapWallet.begin(); - it != pwalletMain->mapWallet.end() && account.vchPubKey.IsValid(); - ++it) - BOOST_FOREACH(const CTxOut& txout, (*it).second.vout) - if (txout.scriptPubKey == scriptPubKey) { - bForceNew = true; - break; - } - } - } - - // Generate a new key - if (bForceNew) { - if (!pwalletMain->GetKeyFromPool(account.vchPubKey)) - throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first"); - - pwalletMain->SetAddressBook(account.vchPubKey.GetID(), strAccount, "receive"); - walletdb.WriteAccount(strAccount, account); + CPubKey pubKey; + if (!pwalletMain->GetAccountPubkey(pubKey, strAccount, bForceNew)) { + throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first"); } - return CBitcoinAddress(account.vchPubKey.GetID()); + return CBitcoinAddress(pubKey.GetID()); } UniValue getaccountaddress(const UniValue& params, bool fHelp) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index fb56e7c1db7a0..f3d165472aec2 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -640,6 +640,44 @@ bool CWallet::AccountMove(std::string strFrom, std::string strTo, CAmount nAmoun return true; } +bool CWallet::GetAccountPubkey(CPubKey &pubKey, std::string strAccount, bool bForceNew) +{ + CWalletDB walletdb(strWalletFile); + + CAccount account; + walletdb.ReadAccount(strAccount, account); + + if (!bForceNew) { + if (!account.vchPubKey.IsValid()) + bForceNew = true; + else { + // Check if the current key has been used + CScript scriptPubKey = GetScriptForDestination(account.vchPubKey.GetID()); + for (map::iterator it = mapWallet.begin(); + it != mapWallet.end() && account.vchPubKey.IsValid(); + ++it) + BOOST_FOREACH(const CTxOut& txout, (*it).second.vout) + if (txout.scriptPubKey == scriptPubKey) { + bForceNew = true; + break; + } + } + } + + // Generate a new key + if (bForceNew) { + if (!GetKeyFromPool(account.vchPubKey)) + return false; + + SetAddressBook(account.vchPubKey.GetID(), strAccount, "receive"); + walletdb.WriteAccount(strAccount, account); + } + + pubKey = account.vchPubKey; + + return true; +} + void CWallet::MarkDirty() { { diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 3077bf461f809..683c901444c1b 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -719,6 +719,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface */ int64_t IncOrderPosNext(CWalletDB *pwalletdb = NULL); bool AccountMove(std::string strFrom, std::string strTo, CAmount nAmount, std::string strComment = ""); + bool GetAccountPubkey(CPubKey &pubKey, std::string strAccount, bool bForceNew = false); void MarkDirty(); bool AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletDB* pwalletdb); From d3df40e51a29bd98830043dd19829126390d1bc4 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Sat, 23 Apr 2016 23:30:20 +0000 Subject: [PATCH 0416/1802] Implement BIP 9 GBT changes - BIP9DeploymentInfo struct for static deployment info - VersionBitsDeploymentInfo: Avoid C++11ism by commenting parameter names - getblocktemplate: Make sure to set deployments in the version if it is LOCKED_IN - In this commit, all rules are considered required for clients to support --- src/consensus/params.h | 1 + src/main.cpp | 2 +- src/main.h | 2 ++ src/rpc/mining.cpp | 50 ++++++++++++++++++++++++++++++++++++++++-- src/versionbits.cpp | 11 ++++++++++ src/versionbits.h | 7 ++++++ 6 files changed, 70 insertions(+), 3 deletions(-) diff --git a/src/consensus/params.h b/src/consensus/params.h index 4f3480b89ba69..6c4cc49479ba1 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -16,6 +16,7 @@ enum DeploymentPos { DEPLOYMENT_TESTDUMMY, DEPLOYMENT_CSV, // Deployment of BIP68, BIP112, and BIP113. + // NOTE: Also add new deployments to VersionBitsDeploymentInfo in versionbits.cpp MAX_VERSION_BITS_DEPLOYMENTS }; diff --git a/src/main.cpp b/src/main.cpp index f74cb30574ce3..623d77985ca87 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2122,7 +2122,7 @@ void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const } // Protected by cs_main -static VersionBitsCache versionbitscache; +VersionBitsCache versionbitscache; int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params) { diff --git a/src/main.h b/src/main.h index 6936b5379ae4b..404a787e4dce5 100644 --- a/src/main.h +++ b/src/main.h @@ -551,6 +551,8 @@ extern CBlockTreeDB *pblocktree; */ int GetSpendHeight(const CCoinsViewCache& inputs); +extern VersionBitsCache versionbitscache; + /** * Determine what nVersion a new block should use. */ diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index c33082fca0c04..277696fe0b561 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -7,6 +7,7 @@ #include "chain.h" #include "chainparams.h" #include "consensus/consensus.h" +#include "consensus/params.h" #include "consensus/validation.h" #include "core_io.h" #include "init.h" @@ -260,6 +261,13 @@ static UniValue BIP22ValidationResult(const CValidationState& state) return "valid?"; } +std::string gbt_vb_name(const Consensus::DeploymentPos pos) { + const struct BIP9DeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos]; + std::string s = vbinfo.name; + s.insert(s.begin(), '!'); + return s; +} + UniValue getblocktemplate(const UniValue& params, bool fHelp) { if (fHelp || params.size() > 1) @@ -267,7 +275,9 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) "getblocktemplate ( \"jsonrequestobject\" )\n" "\nIf the request parameters include a 'mode' key, that is used to explicitly select between the default 'template' request or a 'proposal'.\n" "It returns data needed to construct a block to work on.\n" - "See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n" + "For full specification, see BIPs 22 and 9:\n" + " https://github.com/bitcoin/bips/blob/master/bip-0022.mediawiki\n" + " https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki#getblocktemplate_changes\n" "\nArguments:\n" "1. \"jsonrequestobject\" (string, optional) A json object in the following spec\n" @@ -283,6 +293,12 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) "\nResult:\n" "{\n" " \"version\" : n, (numeric) The block version\n" + " \"rules\" : [ \"rulename\", ... ], (array of strings) specific block rules that are to be enforced\n" + " \"vbavailable\" : { (json object) set of pending, supported versionbit (BIP 9) softfork deployments\n" + " \"rulename\" : bitnumber (numeric) identifies the bit number as indicating acceptance and readiness for the named softfork rule\n" + " ,...\n" + " },\n" + " \"vbrequired\" : n, (numeric) bit mask of versionbits the server requires set in submissions\n" " \"previousblockhash\" : \"xxxx\", (string) The hash of current highest block\n" " \"transactions\" : [ (array) contents of non-coinbase transactions that should be included in the next block\n" " {\n" @@ -458,9 +474,10 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) pindexPrev = pindexPrevNew; } CBlock* pblock = &pblocktemplate->block; // pointer for convenience + const Consensus::Params& consensusParams = Params().GetConsensus(); // Update nTime - UpdateTime(pblock, Params().GetConsensus(), pindexPrev); + UpdateTime(pblock, consensusParams, pindexPrev); pblock->nNonce = 0; UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal"); @@ -511,7 +528,36 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) UniValue result(UniValue::VOBJ); result.push_back(Pair("capabilities", aCaps)); + + UniValue aRules(UniValue::VARR); + UniValue vbavailable(UniValue::VOBJ); + for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++i) { + Consensus::DeploymentPos pos = Consensus::DeploymentPos(i); + ThresholdState state = VersionBitsState(pindexPrev, consensusParams, pos, versionbitscache); + switch (state) { + case THRESHOLD_DEFINED: + case THRESHOLD_FAILED: + // Not exposed to GBT at all + break; + case THRESHOLD_LOCKED_IN: + // Ensure bit is set in block version + pblock->nVersion |= VersionBitsMask(consensusParams, pos); + // FALL THROUGH to get vbavailable set... + case THRESHOLD_STARTED: + // Add to vbavailable (and it's presumably in version already) + vbavailable.push_back(Pair(gbt_vb_name(pos), consensusParams.vDeployments[pos].bit)); + break; + case THRESHOLD_ACTIVE: + // Add to rules only + aRules.push_back(gbt_vb_name(pos)); + break; + } + } result.push_back(Pair("version", pblock->nVersion)); + result.push_back(Pair("rules", aRules)); + result.push_back(Pair("vbavailable", vbavailable)); + result.push_back(Pair("vbrequired", int(0))); + result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex())); result.push_back(Pair("transactions", transactions)); result.push_back(Pair("coinbaseaux", aux)); diff --git a/src/versionbits.cpp b/src/versionbits.cpp index fbb60c0fc598e..041ca2adbcafc 100644 --- a/src/versionbits.cpp +++ b/src/versionbits.cpp @@ -4,6 +4,17 @@ #include "versionbits.h" +#include "consensus/params.h" + +const struct BIP9DeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_BITS_DEPLOYMENTS] = { + { + /*.name =*/ "testdummy", + }, + { + /*.name =*/ "csv", + } +}; + ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const { int nPeriod = Period(params); diff --git a/src/versionbits.h b/src/versionbits.h index 04f4738272796..d80594202884b 100644 --- a/src/versionbits.h +++ b/src/versionbits.h @@ -30,6 +30,13 @@ enum ThresholdState { // will either be NULL or a block with (height + 1) % Period() == 0. typedef std::map ThresholdConditionCache; +struct BIP9DeploymentInfo { + /** Deployment name */ + const char *name; +}; + +extern const struct BIP9DeploymentInfo VersionBitsDeploymentInfo[]; + /** * Abstract class that implements BIP9-style threshold logic, and caches results. */ From 72cd6b20cae3d1eda2f917f1608a8ae7f1e606f7 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Sat, 21 May 2016 08:39:34 +0000 Subject: [PATCH 0417/1802] qa/rpc-tests: bip9-softforks: Add tests for getblocktemplate versionbits updates --- qa/rpc-tests/bip9-softforks.py | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/qa/rpc-tests/bip9-softforks.py b/qa/rpc-tests/bip9-softforks.py index cbb1b7d4cee89..1b1f5dd0dcce4 100755 --- a/qa/rpc-tests/bip9-softforks.py +++ b/qa/rpc-tests/bip9-softforks.py @@ -85,7 +85,7 @@ def get_bip9_status(self, key): raise IndexError ('key:"%s" not found' % key) - def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignature): + def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignature, bitno): # generate some coins for later self.coinbase_blocks = self.nodes[0].generate(2) self.height = 3 # height of the next block to build @@ -94,6 +94,11 @@ def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignatu self.last_block_time = time.time() assert_equal(self.get_bip9_status(bipName)['status'], 'defined') + tmpl = self.nodes[0].getblocktemplate({}) + assert(bipName not in tmpl['rules']) + assert(bipName not in tmpl['vbavailable']) + assert_equal(tmpl['vbrequired'], 0) + assert_equal(tmpl['version'], 0x20000000) # Test 1 # Advance from DEFINED to STARTED @@ -101,6 +106,11 @@ def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignatu yield TestInstance(test_blocks, sync_every_block=False) assert_equal(self.get_bip9_status(bipName)['status'], 'started') + tmpl = self.nodes[0].getblocktemplate({}) + assert(bipName not in tmpl['rules']) + assert_equal(tmpl['vbavailable'][bipName], bitno) + assert_equal(tmpl['vbrequired'], 0) + assert(tmpl['version'] & activated_version) # Test 2 # Fail to achieve LOCKED_IN 100 out of 144 signal bit 1 @@ -112,6 +122,11 @@ def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignatu yield TestInstance(test_blocks, sync_every_block=False) assert_equal(self.get_bip9_status(bipName)['status'], 'started') + tmpl = self.nodes[0].getblocktemplate({}) + assert(bipName not in tmpl['rules']) + assert_equal(tmpl['vbavailable'][bipName], bitno) + assert_equal(tmpl['vbrequired'], 0) + assert(tmpl['version'] & activated_version) # Test 3 # 108 out of 144 signal bit 1 to achieve LOCKED_IN @@ -123,6 +138,8 @@ def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignatu yield TestInstance(test_blocks, sync_every_block=False) assert_equal(self.get_bip9_status(bipName)['status'], 'locked_in') + tmpl = self.nodes[0].getblocktemplate({}) + assert(bipName not in tmpl['rules']) # Test 4 # 143 more version 536870913 blocks (waiting period-1) @@ -130,6 +147,8 @@ def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignatu yield TestInstance(test_blocks, sync_every_block=False) assert_equal(self.get_bip9_status(bipName)['status'], 'locked_in') + tmpl = self.nodes[0].getblocktemplate({}) + assert(bipName not in tmpl['rules']) # Test 5 # Check that the new rule is enforced @@ -153,6 +172,11 @@ def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignatu yield TestInstance([[block, True]]) assert_equal(self.get_bip9_status(bipName)['status'], 'active') + tmpl = self.nodes[0].getblocktemplate({}) + assert(bipName in tmpl['rules']) + assert(bipName not in tmpl['vbavailable']) + assert_equal(tmpl['vbrequired'], 0) + assert(not (tmpl['version'] & (1 << bitno))) # Test 6 # Check that the new sequence lock rules are enforced @@ -187,9 +211,9 @@ def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignatu def get_tests(self): for test in itertools.chain( - self.test_BIP('csv', 536870913, self.sequence_lock_invalidate, self.donothing), - self.test_BIP('csv', 536870913, self.mtp_invalidate, self.donothing), - self.test_BIP('csv', 536870913, self.donothing, self.csv_invalidate) + self.test_BIP('csv', 0x20000001, self.sequence_lock_invalidate, self.donothing, 0), + self.test_BIP('csv', 0x20000001, self.mtp_invalidate, self.donothing, 0), + self.test_BIP('csv', 0x20000001, self.donothing, self.csv_invalidate, 0) ): yield test From 98790608a43e60b8025346034d28ff1f58cebab0 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Wed, 1 Jun 2016 16:47:36 +0000 Subject: [PATCH 0418/1802] getblocktemplate: Explicitly handle the distinction between GBT-affecting softforks vs not --- src/rpc/mining.cpp | 32 ++++++++++++++++++++++++++++++-- src/versionbits.cpp | 2 ++ src/versionbits.h | 2 ++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 277696fe0b561..9558b4c20ef8f 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -264,7 +264,9 @@ static UniValue BIP22ValidationResult(const CValidationState& state) std::string gbt_vb_name(const Consensus::DeploymentPos pos) { const struct BIP9DeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos]; std::string s = vbinfo.name; - s.insert(s.begin(), '!'); + if (!vbinfo.gbt_force) { + s.insert(s.begin(), '!'); + } return s; } @@ -342,6 +344,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) std::string strMode = "template"; UniValue lpval = NullUniValue; + std::set setClientRules; if (params.size() > 0) { const UniValue& oparam = params[0].get_obj(); @@ -385,6 +388,14 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) TestBlockValidity(state, Params(), block, pindexPrev, false, true); return BIP22ValidationResult(state); } + + const UniValue& aClientRules = find_value(oparam, "rules"); + if (aClientRules.isArray()) { + for (unsigned int i = 0; i < aClientRules.size(); ++i) { + const UniValue& v = aClientRules[i]; + setClientRules.insert(v.get_str()); + } + } } if (strMode != "template") @@ -544,13 +555,30 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) pblock->nVersion |= VersionBitsMask(consensusParams, pos); // FALL THROUGH to get vbavailable set... case THRESHOLD_STARTED: - // Add to vbavailable (and it's presumably in version already) + { + const struct BIP9DeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos]; vbavailable.push_back(Pair(gbt_vb_name(pos), consensusParams.vDeployments[pos].bit)); + if (setClientRules.find(vbinfo.name) == setClientRules.end()) { + if (!vbinfo.gbt_force) { + // If the client doesn't support this, don't indicate it in the [default] version + pblock->nVersion &= ~VersionBitsMask(consensusParams, pos); + } + } break; + } case THRESHOLD_ACTIVE: + { // Add to rules only + const struct BIP9DeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos]; aRules.push_back(gbt_vb_name(pos)); + if (setClientRules.find(vbinfo.name) == setClientRules.end()) { + // Not supported by the client; make sure it's safe to proceed + if (!vbinfo.gbt_force) { + throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Support for '%s' rule requires explicit client support", vbinfo.name)); + } + } break; + } } } result.push_back(Pair("version", pblock->nVersion)); diff --git a/src/versionbits.cpp b/src/versionbits.cpp index 041ca2adbcafc..c06c9907be944 100644 --- a/src/versionbits.cpp +++ b/src/versionbits.cpp @@ -9,9 +9,11 @@ const struct BIP9DeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_BITS_DEPLOYMENTS] = { { /*.name =*/ "testdummy", + /*.gbt_force =*/ true, }, { /*.name =*/ "csv", + /*.gbt_force =*/ true, } }; diff --git a/src/versionbits.h b/src/versionbits.h index d80594202884b..ede2dcdda8a7a 100644 --- a/src/versionbits.h +++ b/src/versionbits.h @@ -33,6 +33,8 @@ typedef std::map ThresholdConditionCache; struct BIP9DeploymentInfo { /** Deployment name */ const char *name; + /** Whether GBT clients can safely ignore this rule in simplified usage */ + bool gbt_force; }; extern const struct BIP9DeploymentInfo VersionBitsDeploymentInfo[]; From 12c708a4b3a799478fbb3f93fda696706177a824 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Wed, 1 Jun 2016 16:51:54 +0000 Subject: [PATCH 0419/1802] getblocktemplate: Use version/force mutation to support pre-BIP9 clients --- src/rpc/mining.cpp | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 9558b4c20ef8f..5a06d15c53f78 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -345,6 +345,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) std::string strMode = "template"; UniValue lpval = NullUniValue; std::set setClientRules; + int64_t nMaxVersionPreVB = -1; if (params.size() > 0) { const UniValue& oparam = params[0].get_obj(); @@ -395,6 +396,12 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) const UniValue& v = aClientRules[i]; setClientRules.insert(v.get_str()); } + } else { + // NOTE: It is important that this NOT be read if versionbits is supported + const UniValue& uvMaxVersion = find_value(oparam, "maxversion"); + if (uvMaxVersion.isNum()) { + nMaxVersionPreVB = uvMaxVersion.get_int64(); + } } } @@ -529,13 +536,10 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits); - static UniValue aMutable(UniValue::VARR); - if (aMutable.empty()) - { - aMutable.push_back("time"); - aMutable.push_back("transactions"); - aMutable.push_back("prevblock"); - } + UniValue aMutable(UniValue::VARR); + aMutable.push_back("time"); + aMutable.push_back("transactions"); + aMutable.push_back("prevblock"); UniValue result(UniValue::VOBJ); result.push_back(Pair("capabilities", aCaps)); @@ -574,6 +578,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) if (setClientRules.find(vbinfo.name) == setClientRules.end()) { // Not supported by the client; make sure it's safe to proceed if (!vbinfo.gbt_force) { + // If we do anything other than throw an exception here, be sure version/force isn't sent to old clients throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Support for '%s' rule requires explicit client support", vbinfo.name)); } } @@ -586,6 +591,14 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) result.push_back(Pair("vbavailable", vbavailable)); result.push_back(Pair("vbrequired", int(0))); + if (nMaxVersionPreVB >= 2) { + // If VB is supported by the client, nMaxVersionPreVB is -1, so we won't get here + // Because BIP 34 changed how the generation transaction is serialised, we can only use version/force back to v2 blocks + // This is safe to do [otherwise-]unconditionally only because we are throwing an exception above if a non-force deployment gets activated + // Note that this can probably also be removed entirely after the first BIP9 non-force deployment (ie, probably segwit) gets activated + aMutable.push_back("version/force"); + } + result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex())); result.push_back(Pair("transactions", transactions)); result.push_back(Pair("coinbaseaux", aux)); From faf82e8fc819b2f1f8b60983ac72cb111c47e8ba Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Fri, 3 Jun 2016 19:07:08 +0200 Subject: [PATCH 0420/1802] [rpc] fundrawtransaction: Fix help text and interface --- qa/rpc-tests/fundrawtransaction.py | 2 +- src/wallet/rpcwallet.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py index 5c11d3ab18162..3040752dcb470 100755 --- a/qa/rpc-tests/fundrawtransaction.py +++ b/qa/rpc-tests/fundrawtransaction.py @@ -681,7 +681,7 @@ def run_test(self): inputs = [] outputs = {self.nodes[2].getnewaddress() : 1} rawtx = self.nodes[3].createrawtransaction(inputs, outputs) - result = self.nodes[3].fundrawtransaction(rawtx, ) + result = self.nodes[3].fundrawtransaction(rawtx) # 1000 sat via settxfee result2 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2000}) result3 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 10000}) assert_equal(result['fee']*2, result2['fee']) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 5e6afcd7cb124..68895ac526577 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2369,13 +2369,13 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) " \"changePosition\" (numeric, optional, default random) The index of the change output\n" " \"includeWatching\" (boolean, optional, default false) Also select inputs which are watch only\n" " \"lockUnspents\" (boolean, optional, default false) Lock selected unspent outputs\n" - " \"feeRate\" (numeric, optional, default 0=estimate) Set a specific feerate (fee per KB)\n" + " \"feeRate\" (numeric, optional, default not set: makes wallet determine the fee) Set a specific feerate (satoshis per KB)\n" " }\n" " for backward compatibility: passing in a true instead of an object will result in {\"includeWatching\":true}\n" "\nResult:\n" "{\n" " \"hex\": \"value\", (string) The resulting raw transaction (hex-encoded string)\n" - " \"fee\": n, (numeric) Fee the resulting transaction pays\n" + " \"fee\": n, (numeric) Fee in " + CURRENCY_UNIT + " the resulting transaction pays\n" " \"changepos\": n (numeric) The position of the added change output, or -1\n" "}\n" "\"hex\" \n" From d3d02d51453943bfe3a9edb944eb48f9f1e01aca Mon Sep 17 00:00:00 2001 From: Kaz Wesley Date: Mon, 6 Jun 2016 14:42:34 -0700 Subject: [PATCH 0421/1802] drop vAddrToSend after sending big addr message We send a newly-accepted peer a 1000-entry addr message, and then only use vAddrToSend for small messages. Deallocate vAddrToSend after it's been used for the big message to save about 40 kB per connected inbound peer. --- src/main.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index fc8e72a7dbc98..5fff4187ace62 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5713,6 +5713,9 @@ bool SendMessages(CNode* pto) pto->vAddrToSend.clear(); if (!vAddr.empty()) pto->PushMessage(NetMsgType::ADDR, vAddr); + // we only send the big addr message once + if (pto->vAddrToSend.capacity() > 40) + pto->vAddrToSend.shrink_to_fit(); } CNodeState &state = *State(pto->GetId()); From fa51a1d2b73580e240a4750144ceb14022deeae2 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 6 Jun 2016 17:20:58 +0200 Subject: [PATCH 0422/1802] [init] Make feefilter option debug option --- src/init.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/init.cpp b/src/init.cpp index 9a22501859428..3a260d16db5a2 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -319,7 +319,8 @@ std::string HelpMessage(HelpMessageMode mode) } strUsage += HelpMessageOpt("-datadir=", _("Specify data directory")); strUsage += HelpMessageOpt("-dbcache=", strprintf(_("Set database cache size in megabytes (%d to %d, default: %d)"), nMinDbCache, nMaxDbCache, nDefaultDbCache)); - strUsage += HelpMessageOpt("-feefilter", strprintf(_("Tell other nodes to filter invs to us by our mempool min fee (default: %u)"), DEFAULT_FEEFILTER)); + if (showDebug) + strUsage += HelpMessageOpt("-feefilter", strprintf("Tell other nodes to filter invs to us by our mempool min fee (default: %u)", DEFAULT_FEEFILTER)); strUsage += HelpMessageOpt("-loadblock=", _("Imports blocks from external blk000??.dat file on startup")); strUsage += HelpMessageOpt("-maxorphantx=", strprintf(_("Keep at most unconnectable transactions in memory (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS)); strUsage += HelpMessageOpt("-maxmempool=", strprintf(_("Keep the transaction memory pool below megabytes (default: %u)"), DEFAULT_MAX_MEMPOOL_SIZE)); From 8b78486d02ed3c1c217d79ebca78a70d73e0d570 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 2 Jun 2016 13:52:09 +0200 Subject: [PATCH 0423/1802] Log/report in 10% steps during VerifyDB --- src/main.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 162c8b986caec..a712698210df8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3873,10 +3873,18 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, CBlockIndex* pindexFailure = NULL; int nGoodTransactions = 0; CValidationState state; + int reportDone = 0; + LogPrintf("[0%]..."); for (CBlockIndex* pindex = chainActive.Tip(); pindex && pindex->pprev; pindex = pindex->pprev) { boost::this_thread::interruption_point(); - uiInterface.ShowProgress(_("Verifying blocks..."), std::max(1, std::min(99, (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100))))); + int percentageDone = std::max(1, std::min(99, (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100)))); + if (reportDone < percentageDone/10) { + // report every 10% step + LogPrintf("[%d%%]...", percentageDone); + reportDone = percentageDone/10; + } + uiInterface.ShowProgress(_("Verifying blocks..."), percentageDone); if (pindex->nHeight < chainActive.Height()-nCheckDepth) break; if (fPruneMode && !(pindex->nStatus & BLOCK_HAVE_DATA)) { @@ -3934,6 +3942,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, } } + LogPrintf("[DONE].\n"); LogPrintf("No coin database inconsistencies in last %i blocks (%i transactions)\n", chainActive.Height() - pindexState->nHeight, nGoodTransactions); return true; From fa7f4f577cbab2b4bc03b5427704c2ec16680c34 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 6 Jun 2016 17:50:50 +0200 Subject: [PATCH 0424/1802] [rpc] fundrawtransaction feeRate: Use BTC/kB Also introduce UniValueType UniValueType is a wrapper for UniValue::VType which allows setting a typeAny flag. This flag indicates the type does not matter. (Used by RPCTypeCheckObj) --- qa/rpc-tests/fundrawtransaction.py | 6 +++--- src/rpc/rawtransaction.cpp | 15 +++++++++++++-- src/rpc/server.cpp | 14 ++++++-------- src/rpc/server.h | 15 ++++++++++++--- src/wallet/rpcwallet.cpp | 20 ++++++++++++++++---- 5 files changed, 50 insertions(+), 20 deletions(-) diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py index 3040752dcb470..998f822afe81d 100755 --- a/qa/rpc-tests/fundrawtransaction.py +++ b/qa/rpc-tests/fundrawtransaction.py @@ -681,9 +681,9 @@ def run_test(self): inputs = [] outputs = {self.nodes[2].getnewaddress() : 1} rawtx = self.nodes[3].createrawtransaction(inputs, outputs) - result = self.nodes[3].fundrawtransaction(rawtx) # 1000 sat via settxfee - result2 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2000}) - result3 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 10000}) + result = self.nodes[3].fundrawtransaction(rawtx) # uses min_relay_tx_fee (set by settxfee) + result2 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2*min_relay_tx_fee}) + result3 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 10*min_relay_tx_fee}) assert_equal(result['fee']*2, result2['fee']) assert_equal(result['fee']*10, result3['fee']) diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 483fe746ca10f..f92ddb282e8da 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -675,7 +675,12 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp) UniValue prevOut = p.get_obj(); - RPCTypeCheckObj(prevOut, boost::assign::map_list_of("txid", UniValue::VSTR)("vout", UniValue::VNUM)("scriptPubKey", UniValue::VSTR)); + RPCTypeCheckObj(prevOut, + { + {"txid", UniValueType(UniValue::VSTR)}, + {"vout", UniValueType(UniValue::VNUM)}, + {"scriptPubKey", UniValueType(UniValue::VSTR)}, + }); uint256 txid = ParseHashO(prevOut, "txid"); @@ -703,7 +708,13 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp) // if redeemScript given and not using the local wallet (private keys // given), add redeemScript to the tempKeystore so it can be signed: if (fGivenKeys && scriptPubKey.IsPayToScriptHash()) { - RPCTypeCheckObj(prevOut, boost::assign::map_list_of("txid", UniValue::VSTR)("vout", UniValue::VNUM)("scriptPubKey", UniValue::VSTR)("redeemScript",UniValue::VSTR)); + RPCTypeCheckObj(prevOut, + { + {"txid", UniValueType(UniValue::VSTR)}, + {"vout", UniValueType(UniValue::VNUM)}, + {"scriptPubKey", UniValueType(UniValue::VSTR)}, + {"redeemScript", UniValueType(UniValue::VSTR)}, + }); UniValue v = find_value(prevOut, "redeemScript"); if (!v.isNull()) { vector rsData(ParseHexV(v, "redeemScript")); diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index d06a9142b6819..23149baa6d945 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -88,20 +88,18 @@ void RPCTypeCheck(const UniValue& params, } void RPCTypeCheckObj(const UniValue& o, - const map& typesExpected, - bool fAllowNull, - bool fStrict) + const map& typesExpected, + bool fAllowNull, + bool fStrict) { - BOOST_FOREACH(const PAIRTYPE(string, UniValue::VType)& t, typesExpected) - { + for (const auto& t : typesExpected) { const UniValue& v = find_value(o, t.first); if (!fAllowNull && v.isNull()) throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing %s", t.first)); - if (!((v.type() == t.second) || (fAllowNull && (v.isNull())))) - { + if (!(t.second.typeAny || v.type() == t.second.type || (fAllowNull && v.isNull()))) { string err = strprintf("Expected type %s for %s, got %s", - uvTypeName(t.second), t.first, uvTypeName(v.type())); + uvTypeName(t.second.type), t.first, uvTypeName(v.type())); throw JSONRPCError(RPC_TYPE_ERROR, err); } } diff --git a/src/rpc/server.h b/src/rpc/server.h index b4713366172ae..b5ccc153d07ef 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -32,6 +32,15 @@ namespace RPCServer class CBlockIndex; class CNetAddr; +/** Wrapper for UniValue::VType, which includes typeAny: + * Used to denote don't care type. Only used by RPCTypeCheckObj */ +struct UniValueType { + UniValueType(UniValue::VType _type) : typeAny(false), type(_type) {} + UniValueType() : typeAny(true) {} + bool typeAny; + UniValue::VType type; +}; + class JSONRequest { public: @@ -60,17 +69,17 @@ bool RPCIsInWarmup(std::string *statusOut); /** * Type-check arguments; throws JSONRPCError if wrong type given. Does not check that * the right number of arguments are passed, just that any passed are the correct type. - * Use like: RPCTypeCheck(params, boost::assign::list_of(str_type)(int_type)(obj_type)); */ void RPCTypeCheck(const UniValue& params, const std::list& typesExpected, bool fAllowNull=false); /* Check for expected keys/value types in an Object. - Use like: RPCTypeCheckObj(object, boost::assign::map_list_of("name", str_type)("value", int_type)); */ void RPCTypeCheckObj(const UniValue& o, - const std::map& typesExpected, bool fAllowNull=false, bool fStrict=false); + const std::map& typesExpected, + bool fAllowNull = false, + bool fStrict = false); /** Opaque base class for timers returned by NewTimerFunc. * This provides no methods at the moment, but makes sure that delete diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 68895ac526577..1300e39aa9412 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2069,7 +2069,11 @@ UniValue lockunspent(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected object"); const UniValue& o = output.get_obj(); - RPCTypeCheckObj(o, boost::assign::map_list_of("txid", UniValue::VSTR)("vout", UniValue::VNUM)); + RPCTypeCheckObj(o, + { + {"txid", UniValueType(UniValue::VSTR)}, + {"vout", UniValueType(UniValue::VNUM)}, + }); string txid = find_value(o, "txid").get_str(); if (!IsHex(txid)) @@ -2369,7 +2373,7 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) " \"changePosition\" (numeric, optional, default random) The index of the change output\n" " \"includeWatching\" (boolean, optional, default false) Also select inputs which are watch only\n" " \"lockUnspents\" (boolean, optional, default false) Lock selected unspent outputs\n" - " \"feeRate\" (numeric, optional, default not set: makes wallet determine the fee) Set a specific feerate (satoshis per KB)\n" + " \"feeRate\" (numeric, optional, default not set: makes wallet determine the fee) Set a specific feerate (" + CURRENCY_UNIT + " per KB)\n" " }\n" " for backward compatibility: passing in a true instead of an object will result in {\"includeWatching\":true}\n" "\nResult:\n" @@ -2409,7 +2413,15 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) UniValue options = params[1]; - RPCTypeCheckObj(options, boost::assign::map_list_of("changeAddress", UniValue::VSTR)("changePosition", UniValue::VNUM)("includeWatching", UniValue::VBOOL)("lockUnspents", UniValue::VBOOL)("feeRate", UniValue::VNUM), true, true); + RPCTypeCheckObj(options, + { + {"changeAddress", UniValueType(UniValue::VSTR)}, + {"changePosition", UniValueType(UniValue::VNUM)}, + {"includeWatching", UniValueType(UniValue::VBOOL)}, + {"lockUnspents", UniValueType(UniValue::VBOOL)}, + {"feeRate", UniValueType()}, // will be checked below + }, + true, true); if (options.exists("changeAddress")) { CBitcoinAddress address(options["changeAddress"].get_str()); @@ -2431,7 +2443,7 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) if (options.exists("feeRate")) { - feeRate = CFeeRate(options["feeRate"].get_real()); + feeRate = CFeeRate(AmountFromValue(options["feeRate"])); overrideEstimatedFeerate = true; } } From 288d85ddf2e0a0c9d25a23db56052883170466d0 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 7 Jun 2016 13:44:56 +0200 Subject: [PATCH 0425/1802] Get rid of CTxMempool::lookup() entirely --- src/main.cpp | 4 +++- src/test/policyestimator_tests.cpp | 18 +++++++++--------- src/txmempool.cpp | 16 +++------------- src/txmempool.h | 1 - 4 files changed, 15 insertions(+), 24 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index db0580bda6142..b581ece09ac4f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1445,8 +1445,10 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, const Consensus::P LOCK(cs_main); - if (mempool.lookup(hash, txOut)) + std::shared_ptr ptx = mempool.get(hash); + if (ptx) { + txOut = *ptx; return true; } diff --git a/src/test/policyestimator_tests.cpp b/src/test/policyestimator_tests.cpp index 644c3da213a99..2b00e6f567fa8 100644 --- a/src/test/policyestimator_tests.cpp +++ b/src/test/policyestimator_tests.cpp @@ -74,9 +74,9 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates) // 9/10 blocks add 2nd highest and so on until ... // 1/10 blocks add lowest fee/pri transactions while (txHashes[9-h].size()) { - CTransaction btx; - if (mpool.lookup(txHashes[9-h].back(), btx)) - block.push_back(btx); + std::shared_ptr ptx = mpool.get(txHashes[9-h].back()); + if (ptx) + block.push_back(*ptx); txHashes[9-h].pop_back(); } } @@ -160,9 +160,9 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates) // Estimates should still not be below original for (int j = 0; j < 10; j++) { while(txHashes[j].size()) { - CTransaction btx; - if (mpool.lookup(txHashes[j].back(), btx)) - block.push_back(btx); + std::shared_ptr ptx = mpool.get(txHashes[j].back()); + if (ptx) + block.push_back(*ptx); txHashes[j].pop_back(); } } @@ -181,9 +181,9 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates) tx.vin[0].prevout.n = 10000*blocknum+100*j+k; uint256 hash = tx.GetHash(); mpool.addUnchecked(hash, entry.Fee(feeV[k/4][j]).Time(GetTime()).Priority(priV[k/4][j]).Height(blocknum).FromTx(tx, &mpool)); - CTransaction btx; - if (mpool.lookup(hash, btx)) - block.push_back(btx); + std::shared_ptr ptx = mpool.get(hash); + if (ptx) + block.push_back(*ptx); } } mpool.removeForBlock(block, ++blocknum, dummyConflicted); diff --git a/src/txmempool.cpp b/src/txmempool.cpp index d39c9577f2484..205ffd6379351 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -831,16 +831,6 @@ std::shared_ptr CTxMemPool::get(const uint256& hash) const return i->GetSharedTx(); } -bool CTxMemPool::lookup(uint256 hash, CTransaction& result) const -{ - auto tx = get(hash); - if (tx) { - result = *tx; - return true; - } - return false; -} - TxMempoolInfo CTxMemPool::info(const uint256& hash) const { LOCK(cs); @@ -960,9 +950,9 @@ bool CCoinsViewMemPool::GetCoins(const uint256 &txid, CCoins &coins) const { // If an entry in the mempool exists, always return that one, as it's guaranteed to never // conflict with the underlying cache, and it cannot have pruned entries (as it contains full) // transactions. First checking the underlying cache risks returning a pruned entry instead. - CTransaction tx; - if (mempool.lookup(txid, tx)) { - coins = CCoins(tx, MEMPOOL_HEIGHT); + shared_ptr ptx = mempool.get(txid); + if (ptx) { + coins = CCoins(*ptx, MEMPOOL_HEIGHT); return true; } return (base->GetCoins(txid, coins) && !coins.IsPruned()); diff --git a/src/txmempool.h b/src/txmempool.h index 2f407fe008efe..f0e9b2e2c6975 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -607,7 +607,6 @@ class CTxMemPool return (mapTx.count(hash) != 0); } - bool lookup(uint256 hash, CTransaction& result) const; std::shared_ptr get(const uint256& hash) const; TxMempoolInfo info(const uint256& hash) const; std::vector infoAll() const; From 053930ffc41ba33fe7ce26bde7097951fe0b8462 Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Mon, 23 May 2016 00:21:05 -0700 Subject: [PATCH 0426/1802] Avoid recalculating vchKeyedNetGroup in eviction logic. Lazy calculate vchKeyedNetGroup in CNode::GetKeyedNetGroup. --- src/net.cpp | 43 +++++++++---------------------------------- src/net.h | 20 ++++++++++++++++++++ 2 files changed, 29 insertions(+), 34 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index c09e3aedb6b76..eb62ee8a06e53 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -14,6 +14,7 @@ #include "clientversion.h" #include "consensus/consensus.h" #include "crypto/common.h" +#include "crypto/sha256.h" #include "hash.h" #include "primitives/transaction.h" #include "scheduler.h" @@ -838,6 +839,7 @@ struct NodeEvictionCandidate int64_t nTimeConnected; int64_t nMinPingUsecTime; CAddress addr; + std::vector vchKeyedNetGroup; }; static bool ReverseCompareNodeMinPingTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b) @@ -850,36 +852,8 @@ static bool ReverseCompareNodeTimeConnected(const NodeEvictionCandidate &a, cons return a.nTimeConnected > b.nTimeConnected; } -class CompareNetGroupKeyed -{ - std::vector vchSecretKey; -public: - CompareNetGroupKeyed() - { - vchSecretKey.resize(32, 0); - GetRandBytes(vchSecretKey.data(), vchSecretKey.size()); - } - - bool operator()(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b) - { - std::vector vchGroupA, vchGroupB; - CSHA256 hashA, hashB; - std::vector vchA(32), vchB(32); - - vchGroupA = a.addr.GetGroup(); - vchGroupB = b.addr.GetGroup(); - - hashA.Write(begin_ptr(vchGroupA), vchGroupA.size()); - hashB.Write(begin_ptr(vchGroupB), vchGroupB.size()); - - hashA.Write(begin_ptr(vchSecretKey), vchSecretKey.size()); - hashB.Write(begin_ptr(vchSecretKey), vchSecretKey.size()); - - hashA.Finalize(begin_ptr(vchA)); - hashB.Finalize(begin_ptr(vchB)); - - return vchA < vchB; - } +static bool CompareNetGroupKeyed(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b) { + return a.vchKeyedNetGroup < b.vchKeyedNetGroup; }; /** Try to find a connection to evict when the node is full. @@ -902,7 +876,7 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) { continue; if (node->fDisconnect) continue; - NodeEvictionCandidate candidate = {node->id, node->nTimeConnected, node->nMinPingUsecTime, node->addr}; + NodeEvictionCandidate candidate = {node->id, node->nTimeConnected, node->nMinPingUsecTime, node->addr, node->vchKeyedNetGroup}; vEvictionCandidates.push_back(candidate); } } @@ -912,9 +886,8 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) { // Protect connections with certain characteristics // Deterministically select 4 peers to protect by netgroup. - // An attacker cannot predict which netgroups will be protected. - static CompareNetGroupKeyed comparerNetGroupKeyed; - std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), comparerNetGroupKeyed); + // An attacker cannot predict which netgroups will be protected + std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), CompareNetGroupKeyed); vEvictionCandidates.erase(vEvictionCandidates.end() - std::min(4, static_cast(vEvictionCandidates.size())), vEvictionCandidates.end()); if (vEvictionCandidates.empty()) return false; @@ -2392,6 +2365,8 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa lastSentFeeFilter = 0; nextSendTimeFeeFilter = 0; + CalculateKeyedNetGroup(); + BOOST_FOREACH(const std::string &msg, getAllNetMessageTypes()) mapRecvBytesPerMsgCmd[msg] = 0; mapRecvBytesPerMsgCmd[NET_MESSAGE_COMMAND_OTHER] = 0; diff --git a/src/net.h b/src/net.h index 403653e8c83a3..019a3f7ee3e20 100644 --- a/src/net.h +++ b/src/net.h @@ -9,6 +9,8 @@ #include "amount.h" #include "bloom.h" #include "compat.h" +#include "crypto/common.h" +#include "crypto/sha256.h" #include "limitedmap.h" #include "netbase.h" #include "protocol.h" @@ -362,6 +364,8 @@ class CNode CBloomFilter* pfilter; int nRefCount; NodeId id; + + std::vector vchKeyedNetGroup; protected: // Denial-of-service detection/prevention @@ -450,6 +454,22 @@ class CNode CNode(const CNode&); void operator=(const CNode&); + void CalculateKeyedNetGroup() { + static std::vector vchSecretKey; + if (vchSecretKey.empty()) { + vchSecretKey.resize(32, 0); + GetRandBytes(vchSecretKey.data(), vchSecretKey.size()); + } + + std::vector vchNetGroup(this->addr.GetGroup()); + + CSHA256 hash; + hash.Write(begin_ptr(vchNetGroup), vchNetGroup.size()); + hash.Write(begin_ptr(vchSecretKey), vchSecretKey.size()); + + vchKeyedNetGroup.resize(32, 0); + hash.Finalize(begin_ptr(vchKeyedNetGroup)); + } public: NodeId GetId() const { From 9bf156bb9ee4915fa7e8f84589d65f6598563c97 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 22 May 2016 11:06:18 +0200 Subject: [PATCH 0427/1802] Support SipHash with arbitrary byte writes --- src/hash.cpp | 39 ++++++++++++++++++++++++++++++++++++--- src/hash.h | 21 ++++++++++++++++++++- src/test/hash_tests.cpp | 17 +++++++++++++---- 3 files changed, 69 insertions(+), 8 deletions(-) diff --git a/src/hash.cpp b/src/hash.cpp index a518314a5376a..20a83342db4c9 100644 --- a/src/hash.cpp +++ b/src/hash.cpp @@ -100,12 +100,15 @@ CSipHasher::CSipHasher(uint64_t k0, uint64_t k1) v[2] = 0x6c7967656e657261ULL ^ k0; v[3] = 0x7465646279746573ULL ^ k1; count = 0; + tmp = 0; } CSipHasher& CSipHasher::Write(uint64_t data) { uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3]; + assert(count % 8 == 0); + v3 ^= data; SIPROUND; SIPROUND; @@ -116,7 +119,35 @@ CSipHasher& CSipHasher::Write(uint64_t data) v[2] = v2; v[3] = v3; - count++; + count += 8; + return *this; +} + +CSipHasher& CSipHasher::Write(const unsigned char* data, size_t size) +{ + uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3]; + uint64_t t = tmp; + int c = count; + + while (size--) { + t |= ((uint64_t)(*(data++))) << (8 * (c % 8)); + c++; + if ((c & 7) == 0) { + v3 ^= t; + SIPROUND; + SIPROUND; + v0 ^= t; + t = 0; + } + } + + v[0] = v0; + v[1] = v1; + v[2] = v2; + v[3] = v3; + count = c; + tmp = t; + return *this; } @@ -124,10 +155,12 @@ uint64_t CSipHasher::Finalize() const { uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3]; - v3 ^= ((uint64_t)count) << 59; + uint64_t t = tmp | (((uint64_t)count) << 56); + + v3 ^= t; SIPROUND; SIPROUND; - v0 ^= ((uint64_t)count) << 59; + v0 ^= t; v2 ^= 0xFF; SIPROUND; SIPROUND; diff --git a/src/hash.h b/src/hash.h index 600dabec56087..db4e130ae7fec 100644 --- a/src/hash.h +++ b/src/hash.h @@ -171,19 +171,38 @@ unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector Date: Wed, 25 May 2016 15:38:32 +0200 Subject: [PATCH 0428/1802] Use 64-bit SipHash of netgroups in eviction --- src/net.cpp | 39 ++++++++++++++++++++++++++------------- src/net.h | 22 +++------------------- 2 files changed, 29 insertions(+), 32 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index eb62ee8a06e53..0bc501601dd97 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -839,7 +839,7 @@ struct NodeEvictionCandidate int64_t nTimeConnected; int64_t nMinPingUsecTime; CAddress addr; - std::vector vchKeyedNetGroup; + uint64_t nKeyedNetGroup; }; static bool ReverseCompareNodeMinPingTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b) @@ -853,7 +853,7 @@ static bool ReverseCompareNodeTimeConnected(const NodeEvictionCandidate &a, cons } static bool CompareNetGroupKeyed(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b) { - return a.vchKeyedNetGroup < b.vchKeyedNetGroup; + return a.nKeyedNetGroup < b.nKeyedNetGroup; }; /** Try to find a connection to evict when the node is full. @@ -876,7 +876,7 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) { continue; if (node->fDisconnect) continue; - NodeEvictionCandidate candidate = {node->id, node->nTimeConnected, node->nMinPingUsecTime, node->addr, node->vchKeyedNetGroup}; + NodeEvictionCandidate candidate = {node->id, node->nTimeConnected, node->nMinPingUsecTime, node->addr, node->nKeyedNetGroup}; vEvictionCandidates.push_back(candidate); } } @@ -908,24 +908,24 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) { // Identify the network group with the most connections and youngest member. // (vEvictionCandidates is already sorted by reverse connect time) - std::vector naMostConnections; + uint64_t naMostConnections; unsigned int nMostConnections = 0; int64_t nMostConnectionsTime = 0; - std::map, std::vector > mapAddrCounts; + std::map > mapAddrCounts; BOOST_FOREACH(const NodeEvictionCandidate &node, vEvictionCandidates) { - mapAddrCounts[node.addr.GetGroup()].push_back(node); - int64_t grouptime = mapAddrCounts[node.addr.GetGroup()][0].nTimeConnected; - size_t groupsize = mapAddrCounts[node.addr.GetGroup()].size(); + mapAddrCounts[node.nKeyedNetGroup].push_back(node); + int64_t grouptime = mapAddrCounts[node.nKeyedNetGroup][0].nTimeConnected; + size_t groupsize = mapAddrCounts[node.nKeyedNetGroup].size(); if (groupsize > nMostConnections || (groupsize == nMostConnections && grouptime > nMostConnectionsTime)) { nMostConnections = groupsize; nMostConnectionsTime = grouptime; - naMostConnections = node.addr.GetGroup(); + naMostConnections = node.nKeyedNetGroup; } } // Reduce to the network group with the most connections - vEvictionCandidates = mapAddrCounts[naMostConnections]; + vEvictionCandidates = std::move(mapAddrCounts[naMostConnections]); // Do not disconnect peers if there is only one unprotected connection from their network group. // This step excessively favors netgroup diversity, and should be removed once more protective criteria are established. @@ -2318,6 +2318,8 @@ unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", DEFAULT_MAX CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNameIn, bool fInboundIn) : ssSend(SER_NETWORK, INIT_PROTO_VERSION), + addr(addrIn), + nKeyedNetGroup(CalculateKeyedNetGroup(addrIn)), addrKnown(5000, 0.001), filterInventoryKnown(50000, 0.000001) { @@ -2330,7 +2332,6 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa nRecvBytes = 0; nTimeConnected = GetTime(); nTimeOffset = 0; - addr = addrIn; addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn; nVersion = 0; strSubVer = ""; @@ -2365,8 +2366,6 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa lastSentFeeFilter = 0; nextSendTimeFeeFilter = 0; - CalculateKeyedNetGroup(); - BOOST_FOREACH(const std::string &msg, getAllNetMessageTypes()) mapRecvBytesPerMsgCmd[msg] = 0; mapRecvBytesPerMsgCmd[NET_MESSAGE_COMMAND_OTHER] = 0; @@ -2599,3 +2598,17 @@ bool CBanDB::Read(banmap_t& banSet) int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds) { return nNow + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5); } + +/* static */ uint64_t CNode::CalculateKeyedNetGroup(const CAddress& ad) +{ + static uint64_t k0 = 0, k1 = 0; + while (k0 == 0 && k1 == 0) { + // Make sure this only runs on the first invocation. + GetRandBytes((unsigned char*)&k0, sizeof(k0)); + GetRandBytes((unsigned char*)&k1, sizeof(k1)); + } + + std::vector vchNetGroup(ad.GetGroup()); + + return CSipHasher(k0, k1).Write(&vchNetGroup[0], vchNetGroup.size()).Finalize(); +} diff --git a/src/net.h b/src/net.h index 019a3f7ee3e20..8df3cb421fea4 100644 --- a/src/net.h +++ b/src/net.h @@ -9,8 +9,6 @@ #include "amount.h" #include "bloom.h" #include "compat.h" -#include "crypto/common.h" -#include "crypto/sha256.h" #include "limitedmap.h" #include "netbase.h" #include "protocol.h" @@ -337,7 +335,7 @@ class CNode int64_t nLastRecv; int64_t nTimeConnected; int64_t nTimeOffset; - CAddress addr; + const CAddress addr; std::string addrName; CService addrLocal; int nVersion; @@ -365,7 +363,7 @@ class CNode int nRefCount; NodeId id; - std::vector vchKeyedNetGroup; + const uint64_t nKeyedNetGroup; protected: // Denial-of-service detection/prevention @@ -454,22 +452,8 @@ class CNode CNode(const CNode&); void operator=(const CNode&); - void CalculateKeyedNetGroup() { - static std::vector vchSecretKey; - if (vchSecretKey.empty()) { - vchSecretKey.resize(32, 0); - GetRandBytes(vchSecretKey.data(), vchSecretKey.size()); - } - - std::vector vchNetGroup(this->addr.GetGroup()); + static uint64_t CalculateKeyedNetGroup(const CAddress& ad); - CSHA256 hash; - hash.Write(begin_ptr(vchNetGroup), vchNetGroup.size()); - hash.Write(begin_ptr(vchSecretKey), vchSecretKey.size()); - - vchKeyedNetGroup.resize(32, 0); - hash.Finalize(begin_ptr(vchKeyedNetGroup)); - } public: NodeId GetId() const { From 888483098e60f2a944f1d246bbfec4d14a2975f8 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 7 Jun 2016 16:29:03 +0200 Subject: [PATCH 0429/1802] Use C++11 thread-safe static initializers --- src/coins.cpp | 6 +----- src/coins.h | 2 +- src/main.cpp | 7 ++----- src/net.cpp | 8 ++------ 4 files changed, 6 insertions(+), 17 deletions(-) diff --git a/src/coins.cpp b/src/coins.cpp index b7dd293d69564..39db7dedfbbe1 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -56,11 +56,7 @@ void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; } bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return base->BatchWrite(mapCoins, hashBlock); } CCoinsViewCursor *CCoinsViewBacked::Cursor() const { return base->Cursor(); } -SaltedTxidHasher::SaltedTxidHasher() -{ - GetRandBytes((unsigned char*)&k0, sizeof(k0)); - GetRandBytes((unsigned char*)&k1, sizeof(k1)); -} +SaltedTxidHasher::SaltedTxidHasher() : k0(GetRand(std::numeric_limits::max())), k1(GetRand(std::numeric_limits::max())) {} CCoinsViewCache::CCoinsViewCache(CCoinsView *baseIn) : CCoinsViewBacked(baseIn), hasModifier(false), cachedCoinsUsage(0) { } diff --git a/src/coins.h b/src/coins.h index 1dd908700b12b..033651a435c04 100644 --- a/src/coins.h +++ b/src/coins.h @@ -269,7 +269,7 @@ class SaltedTxidHasher { private: /** Salt */ - uint64_t k0, k1; + const uint64_t k0, k1; public: SaltedTxidHasher(); diff --git a/src/main.cpp b/src/main.cpp index bf6e6d04b5113..da140cffacfc3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4784,11 +4784,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, LOCK(cs_vNodes); // Use deterministic randomness to send to the same nodes for 24 hours // at a time so the addrKnowns of the chosen nodes prevent repeats - static uint64_t salt0 = 0, salt1 = 0; - while (salt0 == 0 && salt1 == 0) { - GetRandBytes((unsigned char*)&salt0, sizeof(salt0)); - GetRandBytes((unsigned char*)&salt1, sizeof(salt1)); - } + static const uint64_t salt0 = GetRand(std::numeric_limits::max()); + static const uint64_t salt1 = GetRand(std::numeric_limits::max()); uint64_t hashAddr = addr.GetHash(); multimap mapMix; const CSipHasher hasher = CSipHasher(salt0, salt1).Write(hashAddr << 32).Write((GetTime() + hashAddr) / (24*60*60)); diff --git a/src/net.cpp b/src/net.cpp index 0bc501601dd97..e29053cf548c2 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2601,12 +2601,8 @@ int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds) { /* static */ uint64_t CNode::CalculateKeyedNetGroup(const CAddress& ad) { - static uint64_t k0 = 0, k1 = 0; - while (k0 == 0 && k1 == 0) { - // Make sure this only runs on the first invocation. - GetRandBytes((unsigned char*)&k0, sizeof(k0)); - GetRandBytes((unsigned char*)&k1, sizeof(k1)); - } + static const uint64_t k0 = GetRand(std::numeric_limits::max()); + static const uint64_t k1 = GetRand(std::numeric_limits::max()); std::vector vchNetGroup(ad.GetGroup()); From ae357d5ab940dea5e2640361ae17fd8722a93c9f Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 7 Jun 2016 17:37:35 +0200 Subject: [PATCH 0430/1802] [Bitcoin-Tx] Add tests for sequence number support --- src/test/data/bitcoin-util-test.json | 13 +++++++++++++ src/test/data/txcreatedata_seq0.hex | 1 + src/test/data/txcreatedata_seq1.hex | 1 + 3 files changed, 15 insertions(+) create mode 100644 src/test/data/txcreatedata_seq0.hex create mode 100644 src/test/data/txcreatedata_seq1.hex diff --git a/src/test/data/bitcoin-util-test.json b/src/test/data/bitcoin-util-test.json index 3bf80ca4348a2..5cb383de85a06 100644 --- a/src/test/data/bitcoin-util-test.json +++ b/src/test/data/bitcoin-util-test.json @@ -86,5 +86,18 @@ "outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o", "outdata=54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e"], "output_cmp": "txcreatedata2.hex" + }, + { "exec": "./bitcoin-tx", + "args": + ["-create", + "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0:4294967293", + "outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o"], + "output_cmp": "txcreatedata_seq0.hex" + }, + { "exec": "./bitcoin-tx", + "args": + ["01000000011f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000fdffffff0180a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac00000000", + "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0:1"], + "output_cmp": "txcreatedata_seq1.hex" } ] diff --git a/src/test/data/txcreatedata_seq0.hex b/src/test/data/txcreatedata_seq0.hex new file mode 100644 index 0000000000000..db02b5e4a46a7 --- /dev/null +++ b/src/test/data/txcreatedata_seq0.hex @@ -0,0 +1 @@ +01000000011f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000fdffffff0180a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac00000000 diff --git a/src/test/data/txcreatedata_seq1.hex b/src/test/data/txcreatedata_seq1.hex new file mode 100644 index 0000000000000..4cedcd975cc21 --- /dev/null +++ b/src/test/data/txcreatedata_seq1.hex @@ -0,0 +1 @@ +01000000021f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000fdffffff1f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000010000000180a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac00000000 From 86efa30ae3fd36aa77b19ff0f70bb89be9ec308e Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 7 Jun 2016 19:57:54 +0200 Subject: [PATCH 0431/1802] [Bitcoin-Tx] fix missing test fixtures, fix 32bit atoi issue --- src/Makefile.test.include | 4 +++- src/bitcoin-tx.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 77cf1001e1d9d..2d7791232daa8 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -17,7 +17,9 @@ EXTRA_DIST += \ test/data/txcreate2.hex \ test/data/txcreatedata1.hex \ test/data/txcreatedata2.hex \ - test/data/txcreatesign.hex + test/data/txcreatesign.hex \ + test/data/txcreatedata_seq0.hex \ + test/data/txcreatedata_seq1.hex JSON_TEST_FILES = \ test/data/script_tests.json \ diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index d5e2fc279bc25..f9ea94b9f42d3 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -206,7 +206,7 @@ static void MutateTxAddInput(CMutableTransaction& tx, const string& strInput) // extract the optional sequence number uint32_t nSequenceIn=std::numeric_limits::max(); if (vStrInputParts.size() > 2) - nSequenceIn = atoi(vStrInputParts[2]); + nSequenceIn = std::stoul(vStrInputParts[2]); // append to transaction input list CTxIn txin(txid, vout, CScript(), nSequenceIn); From c2715d3ab8d83be5bc256380b84d5467e85a4330 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Tue, 7 Jun 2016 21:22:48 +0200 Subject: [PATCH 0432/1802] Do not shadow local variables --- src/test/base58_tests.cpp | 4 ++-- src/test/miner_tests.cpp | 4 ++-- src/test/pmt_tests.cpp | 4 ++-- src/test/prevector_tests.cpp | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index e5a2e28b2e9de..01eb2aee9ed02 100644 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -79,7 +79,7 @@ class TestAddrTypeVisitor : public boost::static_visitor private: std::string exp_addrType; public: - TestAddrTypeVisitor(const std::string &exp_addrType) : exp_addrType(exp_addrType) { } + TestAddrTypeVisitor(const std::string &_exp_addrType) : exp_addrType(_exp_addrType) { } bool operator()(const CKeyID &id) const { return (exp_addrType == "pubkey"); @@ -100,7 +100,7 @@ class TestPayloadVisitor : public boost::static_visitor private: std::vector exp_payload; public: - TestPayloadVisitor(std::vector &exp_payload) : exp_payload(exp_payload) { } + TestPayloadVisitor(std::vector &_exp_payload) : exp_payload(_exp_payload) { } bool operator()(const CKeyID &id) const { uint160 exp_key(exp_payload); diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 469862518c58c..3f5f0ee98bbd6 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -385,8 +385,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) SetMockTime(0); mempool.clear(); - BOOST_FOREACH(CTransaction *tx, txFirst) - delete tx; + BOOST_FOREACH(CTransaction *_tx, txFirst) + delete _tx; fCheckpointsEnabled = true; } diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index 2f3f607889498..74ffe0cc74045 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -37,8 +37,8 @@ BOOST_AUTO_TEST_CASE(pmt_test1) seed_insecure_rand(false); static const unsigned int nTxCounts[] = {1, 4, 7, 17, 56, 100, 127, 256, 312, 513, 1000, 4095}; - for (int n = 0; n < 12; n++) { - unsigned int nTx = nTxCounts[n]; + for (int i = 0; i < 12; i++) { + unsigned int nTx = nTxCounts[i]; // build a block with some dummy transactions CBlock block; diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp index b39b90353053c..d1407c1da9339 100644 --- a/src/test/prevector_tests.cpp +++ b/src/test/prevector_tests.cpp @@ -192,8 +192,8 @@ BOOST_AUTO_TEST_CASE(PrevectorTestInt) if (((r >> 21) % 32) == 7) { int values[4]; int num = 1 + (insecure_rand() % 4); - for (int i = 0; i < num; i++) { - values[i] = insecure_rand(); + for (int k = 0; k < num; k++) { + values[k] = insecure_rand(); } test.insert_range(insecure_rand() % (test.size() + 1), values, values + num); } From b676f38791edd4a276f7c7937ffdd98c0cd2cf08 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 7 Jun 2016 15:45:02 -0400 Subject: [PATCH 0433/1802] depends: allow for CONFIG_SITE to be used rather than stealing prefix This does not break any existing prefix behavior, only makes new behavior work. For example: CONFIG_SITE=$PWD/depends/x86_64-pc-linux-gnu/share/config.site ./configure --prefix=/ --- depends/config.site.in | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/depends/config.site.in b/depends/config.site.in index 984ddb1e62b01..e731537bf76bd 100644 --- a/depends/config.site.in +++ b/depends/config.site.in @@ -1,24 +1,26 @@ +depends_prefix="`dirname ${ac_site_file}`/.." + cross_compiling=maybe host_alias=@HOST@ ac_tool_prefix=${host_alias}- if test -z $with_boost; then - with_boost=$prefix + with_boost=$depends_prefix fi if test -z $with_qt_plugindir; then - with_qt_plugindir=$prefix/plugins + with_qt_plugindir=$depends_prefix/plugins fi if test -z $with_qt_translationdir; then - with_qt_translationdir=$prefix/translations + with_qt_translationdir=$depends_prefix/translations fi if test -z $with_qt_bindir; then - with_qt_bindir=$prefix/native/bin + with_qt_bindir=$depends_prefix/native/bin fi if test -z $with_protoc_bindir; then - with_protoc_bindir=$prefix/native/bin + with_protoc_bindir=$depends_prefix/native/bin fi if test -z $with_comparison_tool; then - with_comparison_tool=$prefix/native/share/BitcoindComparisonTool_jar/BitcoindComparisonTool.jar + with_comparison_tool=$depends_prefix/native/share/BitcoindComparisonTool_jar/BitcoindComparisonTool.jar fi @@ -41,32 +43,32 @@ fi if test x@host_os@ = xmingw32; then if test -z $with_qt_incdir; then - with_qt_incdir=$prefix/include + with_qt_incdir=$depends_prefix/include fi if test -z $with_qt_libdir; then - with_qt_libdir=$prefix/lib + with_qt_libdir=$depends_prefix/lib fi fi -PATH=$prefix/native/bin:$PATH +PATH=$depends_prefix/native/bin:$PATH PKG_CONFIG="`which pkg-config` --static" # These two need to remain exported because pkg-config does not see them # otherwise. That means they must be unexported at the end of configure.ac to # avoid ruining the cache. Sigh. -export PKG_CONFIG_LIBDIR=$prefix/lib/pkgconfig -export PKG_CONFIG_PATH=$prefix/share/pkgconfig +export PKG_CONFIG_LIBDIR=$depends_prefix/lib/pkgconfig +export PKG_CONFIG_PATH=$depends_prefix/share/pkgconfig -CPPFLAGS="-I$prefix/include/ $CPPFLAGS" -LDFLAGS="-L$prefix/lib $LDFLAGS" +CPPFLAGS="-I$depends_prefix/include/ $CPPFLAGS" +LDFLAGS="-L$depends_prefix/lib $LDFLAGS" CC="@CC@" CXX="@CXX@" OBJC="${CC}" OBJCXX="${CXX}" -CCACHE=$prefix/native/bin/ccache -PYTHONPATH=$prefix/native/lib/python/dist-packages:$PYTHONPATH +CCACHE=$depends_prefix/native/bin/ccache +PYTHONPATH=$depends_prefix/native/lib/python/dist-packages:$PYTHONPATH if test -n "@AR@"; then AR=@AR@ From ad38204e6e114d383af0f17b18c216cae10d7686 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 7 Jun 2016 14:51:51 -0400 Subject: [PATCH 0434/1802] gitian: use CONFIG_SITE rather than hijacking the prefix --- contrib/gitian-descriptors/gitian-linux.yml | 6 +++--- contrib/gitian-descriptors/gitian-osx.yml | 6 +++--- contrib/gitian-descriptors/gitian-win.yml | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index 13941f5d55ea3..2ea6769efa3d0 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -74,7 +74,7 @@ script: | # Create the release tarball using (arbitrarily) the first host ./autogen.sh - ./configure --prefix=${BASEPREFIX}/`echo "${HOSTS}" | awk '{print $1;}'` + CONFIG_SITE=${BASEPREFIX}/`echo "${HOSTS}" | awk '{print $1;}'`/share/config.site ./configure --prefix=/ make dist SOURCEDIST=`echo bitcoin-*.tar.gz` DISTNAME=`echo ${SOURCEDIST} | sed 's/.tar.*//'` @@ -95,11 +95,11 @@ script: | mkdir -p ${INSTALLPATH} tar --strip-components=1 -xf ../$SOURCEDIST - ./configure --prefix=${BASEPREFIX}/${i} --bindir=${INSTALLPATH}/bin --includedir=${INSTALLPATH}/include --libdir=${INSTALLPATH}/lib --disable-ccache --disable-maintainer-mode --disable-dependency-tracking ${CONFIGFLAGS} + CONFIG_SITE=${BASEPREFIX}/${i}/share/config.site ./configure --prefix=/ --disable-ccache --disable-maintainer-mode --disable-dependency-tracking ${CONFIGFLAGS} make ${MAKEOPTS} make ${MAKEOPTS} -C src check-security make ${MAKEOPTS} -C src check-symbols - make install-strip + make install-strip DESTDIR=${INSTALLPATH} cd installed find . -name "lib*.la" -delete find . -name "lib*.a" -delete diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml index c430932f9da0e..b37b35d76b404 100644 --- a/contrib/gitian-descriptors/gitian-osx.yml +++ b/contrib/gitian-descriptors/gitian-osx.yml @@ -90,7 +90,7 @@ script: | # Create the release tarball using (arbitrarily) the first host ./autogen.sh - ./configure --prefix=${BASEPREFIX}/`echo "${HOSTS}" | awk '{print $1;}'` + CONFIG_SITE=${BASEPREFIX}/`echo "${HOSTS}" | awk '{print $1;}'`/share/config.site ./configure --prefix=/ make dist SOURCEDIST=`echo bitcoin-*.tar.gz` DISTNAME=`echo ${SOURCEDIST} | sed 's/.tar.*//'` @@ -112,9 +112,9 @@ script: | mkdir -p ${INSTALLPATH} tar --strip-components=1 -xf ../$SOURCEDIST - ./configure --prefix=${BASEPREFIX}/${i} --bindir=${INSTALLPATH}/bin --includedir=${INSTALLPATH}/include --libdir=${INSTALLPATH}/lib --disable-ccache --disable-maintainer-mode --disable-dependency-tracking ${CONFIGFLAGS} + CONFIG_SITE=${BASEPREFIX}/${i}/share/config.site ./configure --prefix=/ --disable-ccache --disable-maintainer-mode --disable-dependency-tracking ${CONFIGFLAGS} make ${MAKEOPTS} - make install-strip + make install-strip DESTDIR=${INSTALLPATH} make osx_volname make deploydir diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml index 9f7322f0b5a21..6504a64b3bae7 100644 --- a/contrib/gitian-descriptors/gitian-win.yml +++ b/contrib/gitian-descriptors/gitian-win.yml @@ -101,7 +101,7 @@ script: | # Create the release tarball using (arbitrarily) the first host ./autogen.sh - ./configure --prefix=${BASEPREFIX}/`echo "${HOSTS}" | awk '{print $1;}'` + CONFIG_SITE=${BASEPREFIX}/`echo "${HOSTS}" | awk '{print $1;}'`/share/config.site ./configure --prefix=/ make dist SOURCEDIST=`echo bitcoin-*.tar.gz` DISTNAME=`echo ${SOURCEDIST} | sed 's/.tar.*//'` @@ -125,11 +125,11 @@ script: | mkdir -p ${INSTALLPATH} tar --strip-components=1 -xf ../$SOURCEDIST - ./configure --prefix=${BASEPREFIX}/${i} --bindir=${INSTALLPATH}/bin --includedir=${INSTALLPATH}/include --libdir=${INSTALLPATH}/lib --disable-ccache --disable-maintainer-mode --disable-dependency-tracking ${CONFIGFLAGS} + CONFIG_SITE=${BASEPREFIX}/${i}/share/config.site ./configure --prefix=/ --disable-ccache --disable-maintainer-mode --disable-dependency-tracking ${CONFIGFLAGS} make ${MAKEOPTS} make ${MAKEOPTS} -C src check-security make deploy - make install-strip + make install-strip DESTDIR=${INSTALLPATH} cp -f bitcoin-*setup*.exe $OUTDIR/ cd installed mv ${DISTNAME}/bin/*.dll ${DISTNAME}/lib/ From 7e7eb2724e1d66b9d6675433798f312a71789a8f Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 7 Jun 2016 22:09:28 -0400 Subject: [PATCH 0435/1802] gitian: create debug packages for linux/windows The -debug tarballs/zips contain detached debugging symbols. To use them, place in the same dir as the target binary, and invoke gdb as usual. Also, because the debug symbols add a substantial space requirement, the build dirs are now deleted when they're no longer needed. --- contrib/gitian-descriptors/gitian-linux.yml | 19 ++++++++++++++----- contrib/gitian-descriptors/gitian-win.yml | 18 +++++++++++++----- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index 2ea6769efa3d0..cfd254cf15c20 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -26,9 +26,12 @@ files: [] script: | WRAP_DIR=$HOME/wrapped HOSTS="i686-pc-linux-gnu x86_64-unknown-linux-gnu" - CONFIGFLAGS="--enable-glibc-back-compat --enable-reduce-exports --disable-bench --disable-gui-tests LDFLAGS=-static-libstdc++" + CONFIGFLAGS="--enable-glibc-back-compat --enable-reduce-exports --disable-bench --disable-gui-tests" FAKETIME_HOST_PROGS="" - FAKETIME_PROGS="date ar ranlib nm strip" + FAKETIME_PROGS="date ar ranlib nm strip objcopy" + HOST_CFLAGS="-O2 -g" + HOST_CXXFLAGS="-O2 -g" + HOST_LDFLAGS=-static-libstdc++ export QT_RCC_TEST=1 export GZIP="-9n" @@ -95,20 +98,26 @@ script: | mkdir -p ${INSTALLPATH} tar --strip-components=1 -xf ../$SOURCEDIST - CONFIG_SITE=${BASEPREFIX}/${i}/share/config.site ./configure --prefix=/ --disable-ccache --disable-maintainer-mode --disable-dependency-tracking ${CONFIGFLAGS} + CONFIG_SITE=${BASEPREFIX}/${i}/share/config.site ./configure --prefix=/ --disable-ccache --disable-maintainer-mode --disable-dependency-tracking ${CONFIGFLAGS} CFLAGS="${HOST_CFLAGS}" CXXFLAGS="${HOST_CXXFLAGS}" LDFLAGS="${HOST_LDFLAGS}" make ${MAKEOPTS} make ${MAKEOPTS} -C src check-security make ${MAKEOPTS} -C src check-symbols - make install-strip DESTDIR=${INSTALLPATH} + make install DESTDIR=${INSTALLPATH} cd installed find . -name "lib*.la" -delete find . -name "lib*.a" -delete rm -rf ${DISTNAME}/lib/pkgconfig - find ${DISTNAME} | sort | tar --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-${i}.tar.gz + find ${DISTNAME}/bin -type f -executable -exec objcopy --only-keep-debug {} {}.dbg \; -exec strip -s {} \; -exec objcopy --add-gnu-debuglink={}.dbg {} \; + find ${DISTNAME}/lib -type f -exec objcopy --only-keep-debug {} {}.dbg \; -exec strip -s {} \; -exec objcopy --add-gnu-debuglink={}.dbg {} \; + find ${DISTNAME} -not -name "*.dbg" | sort | tar --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-${i}.tar.gz + find ${DISTNAME} -name "*.dbg" | sort | tar --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-${i}-debug.tar.gz cd ../../ + rm -rf distsrc-${i} done mkdir -p $OUTDIR/src mv $SOURCEDIST $OUTDIR/src + mv ${OUTDIR}/${DISTNAME}-x86_64-*-debug.tar.gz ${OUTDIR}/${DISTNAME}-linux64-debug.tar.gz + mv ${OUTDIR}/${DISTNAME}-i686-*-debug.tar.gz ${OUTDIR}/${DISTNAME}-linux32-debug.tar.gz mv ${OUTDIR}/${DISTNAME}-x86_64-*.tar.gz ${OUTDIR}/${DISTNAME}-linux64.tar.gz mv ${OUTDIR}/${DISTNAME}-i686-*.tar.gz ${OUTDIR}/${DISTNAME}-linux32.tar.gz diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml index 6504a64b3bae7..bb57d2faf75c6 100644 --- a/contrib/gitian-descriptors/gitian-win.yml +++ b/contrib/gitian-descriptors/gitian-win.yml @@ -30,8 +30,10 @@ script: | WRAP_DIR=$HOME/wrapped HOSTS="x86_64-w64-mingw32 i686-w64-mingw32" CONFIGFLAGS="--enable-reduce-exports --disable-gui-tests" - FAKETIME_HOST_PROGS="g++ ar ranlib nm windres strip" + FAKETIME_HOST_PROGS="g++ ar ranlib nm windres strip objcopy" FAKETIME_PROGS="date makensis zip" + HOST_CFLAGS="-O2 -g" + HOST_CXXFLAGS="-O2 -g" export QT_RCC_TEST=1 export GZIP="-9n" @@ -125,22 +127,28 @@ script: | mkdir -p ${INSTALLPATH} tar --strip-components=1 -xf ../$SOURCEDIST - CONFIG_SITE=${BASEPREFIX}/${i}/share/config.site ./configure --prefix=/ --disable-ccache --disable-maintainer-mode --disable-dependency-tracking ${CONFIGFLAGS} + CONFIG_SITE=${BASEPREFIX}/${i}/share/config.site ./configure --prefix=/ --disable-ccache --disable-maintainer-mode --disable-dependency-tracking ${CONFIGFLAGS} CFLAGS="${HOST_CFLAGS}" CXXFLAGS="${HOST_CXXFLAGS}" make ${MAKEOPTS} make ${MAKEOPTS} -C src check-security make deploy - make install-strip DESTDIR=${INSTALLPATH} + make install DESTDIR=${INSTALLPATH} cp -f bitcoin-*setup*.exe $OUTDIR/ cd installed mv ${DISTNAME}/bin/*.dll ${DISTNAME}/lib/ find . -name "lib*.la" -delete find . -name "lib*.a" -delete rm -rf ${DISTNAME}/lib/pkgconfig - find ${DISTNAME} -type f | sort | zip -X@ ${OUTDIR}/${DISTNAME}-${i}.zip - cd ../.. + find ${DISTNAME}/bin -type f -executable -exec ${i}-objcopy --only-keep-debug {} {}.dbg \; -exec ${i}-strip -s {} \; -exec ${i}-objcopy --add-gnu-debuglink={}.dbg {} \; + find ${DISTNAME}/lib -type f -exec ${i}-objcopy --only-keep-debug {} {}.dbg \; -exec ${i}-strip -s {} \; -exec ${i}-objcopy --add-gnu-debuglink={}.dbg {} \; + find ${DISTNAME} -not -name "*.dbg" -type f | sort | zip -X@ ${OUTDIR}/${DISTNAME}-${i}.zip + find ${DISTNAME} -name "*.dbg" -type f | sort | zip -X@ ${OUTDIR}/${DISTNAME}-${i}-debug.zip + cd ../../ + rm -rf distsrc-${i} done cd $OUTDIR rename 's/-setup\.exe$/-setup-unsigned.exe/' *-setup.exe find . -name "*-setup-unsigned.exe" | sort | tar --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-win-unsigned.tar.gz + mv ${OUTDIR}/${DISTNAME}-x86_64-*-debug.zip ${OUTDIR}/${DISTNAME}-win64-debug.zip + mv ${OUTDIR}/${DISTNAME}-i686-*-debug.zip ${OUTDIR}/${DISTNAME}-win32-debug.zip mv ${OUTDIR}/${DISTNAME}-x86_64-*.zip ${OUTDIR}/${DISTNAME}-win64.zip mv ${OUTDIR}/${DISTNAME}-i686-*.zip ${OUTDIR}/${DISTNAME}-win32.zip From e012f3cea0ca4096dd4dd59a356a973c43651912 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 8 Jun 2016 10:23:25 +0200 Subject: [PATCH 0436/1802] util: Add ParseUInt32 and ParseUInt64 Add error and range-checking parsers for unsigned 32 and 64 bit numbers. The 32-bit variant is required for parsing sequence numbers from the command line in `bitcoin-tx` (see #8164 for discussion). I've thrown in the 64-bit variant as a bonus, as I'm sure it will be needed at some point. Also adds tests, and updates `developer-notes.md`. --- doc/developer-notes.md | 2 +- src/test/util_tests.cpp | 63 ++++++++++++++++++++++++++++++++++++++++ src/utilstrencodings.cpp | 34 ++++++++++++++++++++++ src/utilstrencodings.h | 14 +++++++++ 4 files changed, 112 insertions(+), 1 deletion(-) diff --git a/doc/developer-notes.md b/doc/developer-notes.md index add2fb5004d8e..e40b73ffa7b93 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -323,7 +323,7 @@ Strings and formatting buffer overflows and surprises with `\0` characters. Also some C string manipulations tend to act differently depending on platform, or even the user locale -- Use `ParseInt32`, `ParseInt64`, `ParseDouble` from `utilstrencodings.h` for number parsing +- Use `ParseInt32`, `ParseInt64`, `ParseUInt32`, `ParseUInt64`, `ParseDouble` from `utilstrencodings.h` for number parsing - *Rationale*: These functions do overflow checking, and avoid pesky locale issues diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index b99f952a0dbc4..e467a4171d984 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -376,6 +376,69 @@ BOOST_AUTO_TEST_CASE(test_ParseInt64) BOOST_CHECK(!ParseInt64("32482348723847471234", NULL)); } +BOOST_AUTO_TEST_CASE(test_ParseUInt32) +{ + uint32_t n; + // Valid values + BOOST_CHECK(ParseUInt32("1234", NULL)); + BOOST_CHECK(ParseUInt32("0", &n) && n == 0); + BOOST_CHECK(ParseUInt32("1234", &n) && n == 1234); + BOOST_CHECK(ParseUInt32("01234", &n) && n == 1234); // no octal + 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); + // Invalid values + 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("1a", &n)); + BOOST_CHECK(!ParseUInt32("aap", &n)); + BOOST_CHECK(!ParseUInt32("0x1", &n)); // no hex + BOOST_CHECK(!ParseUInt32("0x1", &n)); // no hex + const char test_bytes[] = {'1', 0, '1'}; + std::string teststr(test_bytes, sizeof(test_bytes)); + BOOST_CHECK(!ParseUInt32(teststr, &n)); // no embedded NULs + // Overflow and underflow + BOOST_CHECK(!ParseUInt32("-2147483648", &n)); + BOOST_CHECK(!ParseUInt32("4294967296", &n)); + BOOST_CHECK(!ParseUInt32("-1234", &n)); + BOOST_CHECK(!ParseUInt32("-32482348723847471234", NULL)); + BOOST_CHECK(!ParseUInt32("32482348723847471234", NULL)); +} + +BOOST_AUTO_TEST_CASE(test_ParseUInt64) +{ + uint64_t n; + // Valid values + BOOST_CHECK(ParseUInt64("1234", NULL)); + BOOST_CHECK(ParseUInt64("0", &n) && n == 0LL); + BOOST_CHECK(ParseUInt64("1234", &n) && n == 1234LL); + BOOST_CHECK(ParseUInt64("01234", &n) && n == 1234LL); // no octal + BOOST_CHECK(ParseUInt64("2147483647", &n) && n == 2147483647LL); + BOOST_CHECK(ParseUInt64("9223372036854775807", &n) && n == 9223372036854775807ULL); + BOOST_CHECK(ParseUInt64("9223372036854775808", &n) && n == 9223372036854775808ULL); + BOOST_CHECK(ParseUInt64("18446744073709551615", &n) && n == 18446744073709551615ULL); + // Invalid values + BOOST_CHECK(!ParseUInt64("", &n)); + BOOST_CHECK(!ParseUInt64(" 1", &n)); // no padding inside + BOOST_CHECK(!ParseUInt64(" -1", &n)); + BOOST_CHECK(!ParseUInt64("1 ", &n)); + BOOST_CHECK(!ParseUInt64("1a", &n)); + BOOST_CHECK(!ParseUInt64("aap", &n)); + BOOST_CHECK(!ParseUInt64("0x1", &n)); // no hex + const char test_bytes[] = {'1', 0, '1'}; + std::string teststr(test_bytes, sizeof(test_bytes)); + BOOST_CHECK(!ParseUInt64(teststr, &n)); // no embedded NULs + // Overflow and underflow + BOOST_CHECK(!ParseUInt64("-9223372036854775809", NULL)); + BOOST_CHECK(!ParseUInt64("18446744073709551616", NULL)); + BOOST_CHECK(!ParseUInt64("-32482348723847471234", NULL)); + BOOST_CHECK(!ParseUInt64("-2147483648", &n)); + BOOST_CHECK(!ParseUInt64("-9223372036854775808", &n)); + BOOST_CHECK(!ParseUInt64("-1234", &n)); +} + BOOST_AUTO_TEST_CASE(test_ParseDouble) { double n; diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp index 0f9334cbe3738..5ffdb3be15cf4 100644 --- a/src/utilstrencodings.cpp +++ b/src/utilstrencodings.cpp @@ -461,6 +461,40 @@ bool ParseInt64(const std::string& str, int64_t *out) n <= std::numeric_limits::max(); } +bool ParseUInt32(const std::string& str, uint32_t *out) +{ + if (!ParsePrechecks(str)) + return false; + if (str.size() >= 1 && str[0] == '-') // Reject negative values, unfortunately strtoul accepts these by default if they fit in the range + return false; + char *endp = NULL; + errno = 0; // strtoul will not set errno if valid + unsigned long int n = strtoul(str.c_str(), &endp, 10); + if(out) *out = (uint32_t)n; + // Note that strtoul returns a *unsigned long int*, so even if it doesn't report a over/underflow + // we still have to check that the returned value is within the range of an *uint32_t*. On 64-bit + // platforms the size of these types may be different. + return endp && *endp == 0 && !errno && + n <= std::numeric_limits::max(); +} + +bool ParseUInt64(const std::string& str, uint64_t *out) +{ + if (!ParsePrechecks(str)) + return false; + if (str.size() >= 1 && str[0] == '-') // Reject negative values, unfortunately strtoull accepts these by default if they fit in the range + return false; + char *endp = NULL; + errno = 0; // strtoull will not set errno if valid + unsigned long long int n = strtoull(str.c_str(), &endp, 10); + if(out) *out = (uint64_t)n; + // Note that strtoull returns a *unsigned long long int*, so even if it doesn't report a over/underflow + // we still have to check that the returned value is within the range of an *uint64_t*. + return endp && *endp == 0 && !errno && + n <= std::numeric_limits::max(); +} + + bool ParseDouble(const std::string& str, double *out) { if (!ParsePrechecks(str)) diff --git a/src/utilstrencodings.h b/src/utilstrencodings.h index d40613cfc43bc..5744f78c6e631 100644 --- a/src/utilstrencodings.h +++ b/src/utilstrencodings.h @@ -70,6 +70,20 @@ bool ParseInt32(const std::string& str, int32_t *out); */ bool ParseInt64(const std::string& str, int64_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. + */ +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. + */ +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, From cdf7dff4248ec4050e535079227dd57cbfb610e4 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Wed, 8 Jun 2016 13:25:50 +0200 Subject: [PATCH 0437/1802] OSX diskimages need 0775 folder permissions Avoids endless Gatekeeper warnings (#7085) --- contrib/gitian-descriptors/gitian-osx-signer.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/gitian-descriptors/gitian-osx-signer.yml b/contrib/gitian-descriptors/gitian-osx-signer.yml index fac61aa3debed..8b2b1467cfe85 100644 --- a/contrib/gitian-descriptors/gitian-osx-signer.yml +++ b/contrib/gitian-descriptors/gitian-osx-signer.yml @@ -34,5 +34,5 @@ script: | tar -xf ${UNSIGNED} OSX_VOLNAME="$(cat osx_volname)" ./detached-sig-apply.sh ${UNSIGNED} signature/osx - ${WRAP_DIR}/genisoimage -no-cache-inodes -D -l -probe -V "${OSX_VOLNAME}" -no-pad -r -apple -o uncompressed.dmg signed-app + ${WRAP_DIR}/genisoimage -no-cache-inodes -D -l -probe -V "${OSX_VOLNAME}" -no-pad -r -dir-mode 0755 -apple -o uncompressed.dmg signed-app ${WRAP_DIR}/dmg dmg uncompressed.dmg ${OUTDIR}/${SIGNED} From 77f63a4fcd0517a6804bde7285e1859d5a087d77 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 8 Jun 2016 15:34:18 +0200 Subject: [PATCH 0438/1802] Fix two warnings for comparison between signed and unsigned --- src/wallet/rpcwallet.cpp | 2 +- src/wallet/wallet.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 1300e39aa9412..2d4e95911dd0f 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2457,7 +2457,7 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) if (origTx.vout.size() == 0) throw JSONRPCError(RPC_INVALID_PARAMETER, "TX must have at least one output"); - if (changePosition != -1 && (changePosition < 0 || changePosition > origTx.vout.size())) + if (changePosition != -1 && (changePosition < 0 || (unsigned int)changePosition > origTx.vout.size())) throw JSONRPCError(RPC_INVALID_PARAMETER, "changePosition out of bounds"); CMutableTransaction tx(origTx); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index f3d165472aec2..9faf21591fa84 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2232,7 +2232,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt // Insert change txn at random position: nChangePosInOut = GetRandInt(txNew.vout.size()+1); } - else if (nChangePosInOut > txNew.vout.size()) + else if ((unsigned int)nChangePosInOut > txNew.vout.size()) { strFailReason = _("Change index out of range"); return false; From 6fa950a57334e93e70d806532ee517cbd75a2338 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Wed, 8 Jun 2016 15:34:25 +0200 Subject: [PATCH 0439/1802] [RPC] Fix createrawtx sequence number unsigned int parsing --- qa/rpc-tests/rawtransactions.py | 14 ++++++++++++++ src/rpc/rawtransaction.cpp | 9 +++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/qa/rpc-tests/rawtransactions.py b/qa/rpc-tests/rawtransactions.py index aa403f058c538..ab6d2e8def148 100755 --- a/qa/rpc-tests/rawtransactions.py +++ b/qa/rpc-tests/rawtransactions.py @@ -143,6 +143,20 @@ def run_test(self): rawtx = self.nodes[0].createrawtransaction(inputs, outputs) decrawtx= self.nodes[0].decoderawtransaction(rawtx) assert_equal(decrawtx['vin'][0]['sequence'], 1000) + + inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : -1}] + outputs = { self.nodes[0].getnewaddress() : 1 } + assert_raises(JSONRPCException, self.nodes[0].createrawtransaction, inputs, outputs) + + inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : 4294967296}] + outputs = { self.nodes[0].getnewaddress() : 1 } + assert_raises(JSONRPCException, self.nodes[0].createrawtransaction, inputs, outputs) + + inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : 4294967294}] + outputs = { self.nodes[0].getnewaddress() : 1 } + rawtx = self.nodes[0].createrawtransaction(inputs, outputs) + decrawtx= self.nodes[0].decoderawtransaction(rawtx) + assert_equal(decrawtx['vin'][0]['sequence'], 4294967294) if __name__ == '__main__': RawTransactionsTest().main() diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 992914f88c121..9723e394d6509 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -388,8 +388,13 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp) // set the sequence number if passed in the parameters object const UniValue& sequenceObj = find_value(o, "sequence"); - if (sequenceObj.isNum()) - nSequence = sequenceObj.get_int(); + if (sequenceObj.isNum()) { + int64_t seqNr64 = sequenceObj.get_int64(); + if (seqNr64 < 0 || seqNr64 > std::numeric_limits::max()) + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, sequence number is out of range"); + else + nSequence = (uint32_t)seqNr64; + } CTxIn in(COutPoint(txid, nOutput), CScript(), nSequence); From eebc23218758d89bce0b7cb0eced9fd654cd3d15 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 8 Jun 2016 15:49:27 +0200 Subject: [PATCH 0440/1802] test: Add more test vectors for siphash Add full test vectors from spec, test per byte and per 8 bytes. Builds on #8086. --- src/test/hash_tests.cpp | 48 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/test/hash_tests.cpp b/src/test/hash_tests.cpp index f62080c1d24f8..82d61209b5e50 100644 --- a/src/test/hash_tests.cpp +++ b/src/test/hash_tests.cpp @@ -47,6 +47,38 @@ BOOST_AUTO_TEST_CASE(murmurhash3) #undef T } +/* + SipHash-2-4 output with + k = 00 01 02 ... + and + in = (empty string) + in = 00 (1 byte) + in = 00 01 (2 bytes) + in = 00 01 02 (3 bytes) + ... + in = 00 01 02 ... 3e (63 bytes) + + from: https://131002.net/siphash/siphash24.c +*/ +uint64_t siphash_4_2_testvec[] = { + 0x726fdb47dd0e0e31, 0x74f839c593dc67fd, 0x0d6c8009d9a94f5a, 0x85676696d7fb7e2d, + 0xcf2794e0277187b7, 0x18765564cd99a68d, 0xcbc9466e58fee3ce, 0xab0200f58b01d137, + 0x93f5f5799a932462, 0x9e0082df0ba9e4b0, 0x7a5dbbc594ddb9f3, 0xf4b32f46226bada7, + 0x751e8fbc860ee5fb, 0x14ea5627c0843d90, 0xf723ca908e7af2ee, 0xa129ca6149be45e5, + 0x3f2acc7f57c29bdb, 0x699ae9f52cbe4794, 0x4bc1b3f0968dd39c, 0xbb6dc91da77961bd, + 0xbed65cf21aa2ee98, 0xd0f2cbb02e3b67c7, 0x93536795e3a33e88, 0xa80c038ccd5ccec8, + 0xb8ad50c6f649af94, 0xbce192de8a85b8ea, 0x17d835b85bbb15f3, 0x2f2e6163076bcfad, + 0xde4daaaca71dc9a5, 0xa6a2506687956571, 0xad87a3535c49ef28, 0x32d892fad841c342, + 0x7127512f72f27cce, 0xa7f32346f95978e3, 0x12e0b01abb051238, 0x15e034d40fa197ae, + 0x314dffbe0815a3b4, 0x027990f029623981, 0xcadcd4e59ef40c4d, 0x9abfd8766a33735c, + 0x0e3ea96b5304a7d0, 0xad0c42d6fc585992, 0x187306c89bc215a9, 0xd4a60abcf3792b95, + 0xf935451de4f21df2, 0xa9538f0419755787, 0xdb9acddff56ca510, 0xd06c98cd5c0975eb, + 0xe612a3cb9ecba951, 0xc766e62cfcadaf96, 0xee64435a9752fe72, 0xa192d576b245165a, + 0x0a8787bf8ecb74b2, 0x81b3e73d20b49b6f, 0x7fa8220ba3b2ecea, 0x245731c13ca42499, + 0xb78dbfaf3a8d83bd, 0xea1ad565322a1a0b, 0x60e61c23a3795013, 0x6606d7e446282b93, + 0x6ca4ecb15c5f91e1, 0x9f626da15c9625f3, 0xe51b38608ef25f57, 0x958a324ceb064572 +}; + BOOST_AUTO_TEST_CASE(siphash) { CSipHasher hasher(0x0706050403020100ULL, 0x0F0E0D0C0B0A0908ULL); @@ -74,6 +106,22 @@ BOOST_AUTO_TEST_CASE(siphash) BOOST_CHECK_EQUAL(hasher.Finalize(), 0xe612a3cb9ecba951ull); BOOST_CHECK_EQUAL(SipHashUint256(0x0706050403020100ULL, 0x0F0E0D0C0B0A0908ULL, uint256S("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100")), 0x7127512f72f27cceull); + + // Check test vectors from spec, one byte at a time + CSipHasher hasher2(0x0706050403020100ULL, 0x0F0E0D0C0B0A0908ULL); + for (uint8_t x=0; x Date: Wed, 8 Jun 2016 15:09:01 -0400 Subject: [PATCH 0441/1802] Tests: Edit bloated varint test and add option for 'barely expensive' tests --- qa/rpc-tests/p2p-fullblocktest.py | 98 +++++++++++++++++-------------- 1 file changed, 53 insertions(+), 45 deletions(-) diff --git a/qa/rpc-tests/p2p-fullblocktest.py b/qa/rpc-tests/p2p-fullblocktest.py index 19b90d4db11eb..17fd40ef1dffd 100755 --- a/qa/rpc-tests/p2p-fullblocktest.py +++ b/qa/rpc-tests/p2p-fullblocktest.py @@ -65,6 +65,10 @@ def __init__(self): self.tip = None self.blocks = {} + def add_options(self, parser): + super().add_options(parser) + parser.add_option("--runbarelyexpensive", dest="runbarelyexpensive", default=True) + def run_test(self): self.test = TestManager(self, self.options.tmpdir) self.test.add_all_connections(self.nodes) @@ -875,10 +879,13 @@ def update_block(block_number, new_transactions): yield rejected(RejectResult(16, b'bad-txns-nonfinal')) - # This checks that a block with a bloated VARINT between the block_header and the array of tx is rejected - # (previous behavior was that it was accepted.) It also checks that if you subsequently send that block - # with correct encoding, it should be accepted (i.e., the receiving node should not reject it on the - # basis that it's the same as an already-rejected block, which would be a DoS vulnerability.) + # This checks that a block with a bloated VARINT between the block_header and the array of tx such that + # the block is > MAX_BLOCK_SIZE with the bloated varint, but <= MAX_BLOCK_SIZE without the bloated varint, + # does not cause a subsequent, identical block with canonical encoding to be rejected. The test does not + # care whether the bloated block is accepted or rejected; it only cares that the second block is accepted. + # + # What matters is that the receiving node should not reject the bloated block, and then reject the canonical + # block on the basis that it's the same as an already-rejected block (which would be a consensus failure.) # # -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) # \ @@ -903,7 +910,7 @@ def update_block(block_number, new_transactions): tx.vin.append(CTxIn(COutPoint(b64a.vtx[1].sha256, 0))) b64a = update_block("64a", [tx]) assert_equal(len(b64a.serialize()), MAX_BLOCK_SIZE + 8) - yield rejected() + yield TestInstance([[self.tip, None]]) # comptool workaround: to make sure b64 is delivered, manually erase b64a from blockstore self.test.block_store.erase(b64a.sha256) @@ -941,7 +948,6 @@ def update_block(block_number, new_transactions): update_block(66, [tx2, tx1]) yield rejected(RejectResult(16, b'bad-txns-inputs-missingorspent')) - # Attempt to double-spend a transaction created in a block # # -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19) @@ -1239,46 +1245,48 @@ def update_block(block_number, new_transactions): # Test re-org of a week's worth of blocks (1088 blocks) # This test takes a minute or two and can be accomplished in memory # - tip(88) - LARGE_REORG_SIZE = 1088 - test1 = TestInstance(sync_every_block=False) - spend=out[32] - for i in range(89, LARGE_REORG_SIZE + 89): - b = block(i, spend) - tx = CTransaction() - script_length = MAX_BLOCK_SIZE - len(b.serialize()) - 69 - script_output = CScript([b'\x00' * script_length]) - tx.vout.append(CTxOut(0, script_output)) - tx.vin.append(CTxIn(COutPoint(b.vtx[1].sha256, 0))) - b = update_block(i, [tx]) - assert_equal(len(b.serialize()), MAX_BLOCK_SIZE) - test1.blocks_and_transactions.append([self.tip, True]) - save_spendable_output() - spend = get_spendable_output() - - yield test1 - chain1_tip = i - - # now create alt chain of same length - tip(88) - test2 = TestInstance(sync_every_block=False) - for i in range(89, LARGE_REORG_SIZE + 89): - block("alt"+str(i)) - test2.blocks_and_transactions.append([self.tip, False]) - yield test2 - - # extend alt chain to trigger re-org - block("alt" + str(chain1_tip + 1)) - yield accepted() - - # ... and re-org back to the first chain - tip(chain1_tip) - block(chain1_tip + 1) - yield rejected() - block(chain1_tip + 2) - yield accepted() + if self.options.runbarelyexpensive: + tip(88) + LARGE_REORG_SIZE = 1088 + test1 = TestInstance(sync_every_block=False) + spend=out[32] + for i in range(89, LARGE_REORG_SIZE + 89): + b = block(i, spend) + tx = CTransaction() + script_length = MAX_BLOCK_SIZE - len(b.serialize()) - 69 + script_output = CScript([b'\x00' * script_length]) + tx.vout.append(CTxOut(0, script_output)) + tx.vin.append(CTxIn(COutPoint(b.vtx[1].sha256, 0))) + b = update_block(i, [tx]) + assert_equal(len(b.serialize()), MAX_BLOCK_SIZE) + test1.blocks_and_transactions.append([self.tip, True]) + save_spendable_output() + spend = get_spendable_output() + + yield test1 + chain1_tip = i + + # now create alt chain of same length + tip(88) + test2 = TestInstance(sync_every_block=False) + for i in range(89, LARGE_REORG_SIZE + 89): + block("alt"+str(i)) + test2.blocks_and_transactions.append([self.tip, False]) + yield test2 + + # extend alt chain to trigger re-org + block("alt" + str(chain1_tip + 1)) + yield accepted() + + # ... and re-org back to the first chain + tip(chain1_tip) + block(chain1_tip + 1) + yield rejected() + block(chain1_tip + 2) + yield accepted() + + chain1_tip += 2 - chain1_tip += 2 if __name__ == '__main__': From 74c134748291bff8b94244456ae6b97f8e587645 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 8 Jun 2016 20:21:18 +0200 Subject: [PATCH 0442/1802] gitian: Add --disable-bench to config flags for windows Forgot to do this in #7776. --- contrib/gitian-descriptors/gitian-win.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml index bb57d2faf75c6..65f76e8df81eb 100644 --- a/contrib/gitian-descriptors/gitian-win.yml +++ b/contrib/gitian-descriptors/gitian-win.yml @@ -29,7 +29,7 @@ files: [] script: | WRAP_DIR=$HOME/wrapped HOSTS="x86_64-w64-mingw32 i686-w64-mingw32" - CONFIGFLAGS="--enable-reduce-exports --disable-gui-tests" + CONFIGFLAGS="--enable-reduce-exports --disable-bench --disable-gui-tests" FAKETIME_HOST_PROGS="g++ ar ranlib nm windres strip objcopy" FAKETIME_PROGS="date makensis zip" HOST_CFLAGS="-O2 -g" From 0d53a9e72f9694e84344f230317aa2485bc07960 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 9 Jun 2016 05:20:30 +0000 Subject: [PATCH 0443/1802] Update luke-jr's PGP key Same key, extended expiration date --- contrib/gitian-keys/luke-jr-key.pgp | Bin 6518 -> 6518 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/contrib/gitian-keys/luke-jr-key.pgp b/contrib/gitian-keys/luke-jr-key.pgp index 4406e6d5be02c1e9006c6ecccc1e4c7c0dbad60c..a2d34e75e1c16c17cb721633038813800dbe45b3 100644 GIT binary patch delta 4256 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 CqBzt5 delta 4256 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 A(f|Me From d096d22446a1d126ea78170f37a148ce0ca43df2 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 9 Jun 2016 11:09:21 +0200 Subject: [PATCH 0444/1802] build: Get rid of `CLIENT_DATE` Putting the build date in the executable is a practice that has no place in these days, now that deterministic building is increasingly common. Continues #7732 which did this for the GUI. --- share/genbuild.sh | 7 ------- src/clientversion.cpp | 9 --------- src/clientversion.h | 1 - src/init.cpp | 2 +- src/wallet/rpcdump.cpp | 2 +- 5 files changed, 2 insertions(+), 19 deletions(-) diff --git a/share/genbuild.sh b/share/genbuild.sh index a15cb34e47ae6..1ef77d706f7aa 100755 --- a/share/genbuild.sh +++ b/share/genbuild.sh @@ -15,7 +15,6 @@ fi DESC="" SUFFIX="" -LAST_COMMIT_DATE="" if [ -e "$(which git 2>/dev/null)" -a "$(git rev-parse --is-inside-work-tree 2>/dev/null)" = "true" ]; then # clean 'dirty' status of touched files that haven't been modified git diff >/dev/null 2>/dev/null @@ -29,9 +28,6 @@ if [ -e "$(which git 2>/dev/null)" -a "$(git rev-parse --is-inside-work-tree 2>/ # otherwise generate suffix from git, i.e. string like "59887e8-dirty" SUFFIX=$(git rev-parse --short HEAD) git diff-index --quiet HEAD -- || SUFFIX="$SUFFIX-dirty" - - # get a string like "2012-04-10 16:27:19 +0200" - LAST_COMMIT_DATE="$(git log -n 1 --format="%ci")" fi if [ -n "$DESC" ]; then @@ -45,7 +41,4 @@ fi # only update build.h if necessary if [ "$INFO" != "$NEWINFO" ]; then echo "$NEWINFO" >"$FILE" - if [ -n "$LAST_COMMIT_DATE" ]; then - echo "#define BUILD_DATE \"$LAST_COMMIT_DATE\"" >> "$FILE" - fi fi diff --git a/src/clientversion.cpp b/src/clientversion.cpp index aae0569bba211..bfe9e16f80ee7 100644 --- a/src/clientversion.cpp +++ b/src/clientversion.cpp @@ -67,16 +67,7 @@ const std::string CLIENT_NAME("Satoshi"); #endif #endif -#ifndef BUILD_DATE -#ifdef GIT_COMMIT_DATE -#define BUILD_DATE GIT_COMMIT_DATE -#else -#define BUILD_DATE __DATE__ ", " __TIME__ -#endif -#endif - const std::string CLIENT_BUILD(BUILD_DESC CLIENT_VERSION_SUFFIX); -const std::string CLIENT_DATE(BUILD_DATE); static std::string FormatVersion(int nVersion) { diff --git a/src/clientversion.h b/src/clientversion.h index 6f255d69c96ef..47263d5344f3c 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -59,7 +59,6 @@ static const int CLIENT_VERSION = extern const std::string CLIENT_NAME; extern const std::string CLIENT_BUILD; -extern const std::string CLIENT_DATE; std::string FormatFullVersion(); diff --git a/src/init.cpp b/src/init.cpp index 3a260d16db5a2..ec4ce6b6da7b6 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -748,7 +748,7 @@ void InitLogging() fLogIPs = GetBoolArg("-logips", DEFAULT_LOGIPS); LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); - LogPrintf("Bitcoin version %s (%s)\n", FormatFullVersion(), CLIENT_DATE); + LogPrintf("Bitcoin version %s\n", FormatFullVersion()); } /** Initialize bitcoin. diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index bb40cf724536a..14c2e31d956d6 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -590,7 +590,7 @@ UniValue dumpwallet(const UniValue& params, bool fHelp) std::sort(vKeyBirth.begin(), vKeyBirth.end()); // produce output - file << strprintf("# Wallet dump created by Bitcoin %s (%s)\n", CLIENT_BUILD, CLIENT_DATE); + file << strprintf("# Wallet dump created by Bitcoin %s\n", CLIENT_BUILD); file << strprintf("# * Created on %s\n", EncodeDumpTime(GetTime())); file << strprintf("# * Best block at time of backup was %i (%s),\n", chainActive.Height(), chainActive.Tip()->GetBlockHash().ToString()); file << strprintf("# mined on %s\n", EncodeDumpTime(chainActive.Tip()->GetBlockTime())); From 31444491f2e07c5ffd4d50827b54830ee3958a4d Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 8 Jun 2016 18:07:45 +0200 Subject: [PATCH 0445/1802] Add git and github tips and tricks to developer notes --- doc/developer-notes.md | 48 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/doc/developer-notes.md b/doc/developer-notes.md index add2fb5004d8e..0caad3b7aa057 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -381,3 +381,51 @@ GUI - *Rationale*: Model classes pass through events and data from the core, they should not interact with the user. That's where View classes come in. The converse also holds: try to not directly access core data structures from Views. + +Git and github tips +--------------------- + +- For resolving merge/rebase conflicts, it can be useful to enable diff3 style using + `git config merge.conflictstyle diff3`. Instead of + + <<< + yours + === + theirs + >>> + + you will see + + <<< + yours + ||| + original + === + theirs + >>> + + This may make it much clearer what caused the conflict. In this style, you can often just look + at what changed between *original* and *theirs*, and mechanically apply that to *yours* (or the other way around). + +- When reviewing patches which change indentation in C++ files, use `git diff -w` and `git show -w`. This makes + the diff algorithm ignore whitespace changes. This feature is also available on github.com, by adding `?w=1` + at the end of any URL which shows a diff. + +- When reviewing patches that change symbol names in many places, use `git diff --word-diff`. This will instead + of showing the patch as deleted/added *lines*, show deleted/added *words*. + +- When reviewing patches that move code around, try using + `git diff --patience commit~:old/file.cpp commit:new/file/name.cpp`, and ignoring everything except the + moved body of code which should show up as neither `+` or `-` lines. In case it was not a pure move, this may + even work when combined with the `-w` or `--word-diff` options described above. + +- When looking at other's pull requests, it may make sense to add the following section to your `.git/config` + file: + + [remote "upstream-pull"] + fetch = +refs/pull/*:refs/remotes/upstream-pull/* + url = git@github.com:bitcoin/bitcoin.git + + This will add an `upstream-pull` remote to your git repository, which can be fetched using `git fetch --all` + or `git fetch upstream-pull`. Afterwards, you can use `upstream-pull/NUMBER/head` in arguments to `git show`, + `git checkout` and anywhere a commit id would be acceptable to see the changes from pull request NUMBER. From 0dfd86956dcd2ac8a2223437e9bbd4f29bd35fce Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Mon, 4 Jan 2016 14:48:22 -0500 Subject: [PATCH 0446/1802] Add getmempooldescendants RPC call --- src/rpc/blockchain.cpp | 67 +++++++++++++++++++++++++++++++++++++++++- src/rpc/client.cpp | 1 + 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 6c005068d86d2..e53ed1c1b1d4d 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -302,7 +302,7 @@ UniValue getmempoolancestors(const UniValue& params, bool fHelp) "1. \"txid\" (string, required) The transaction id (must be in mempool)\n" "2. verbose (boolean, optional, default=false) true for a json object, false for array of transaction ids\n" "\nResult (for verbose=false):\n" - "[ (json array of string)\n" + "[ (json array of strings)\n" " \"transactionid\" (string) The transaction id of an in-mempool ancestor transaction\n" " ,...\n" "]\n" @@ -356,6 +356,70 @@ UniValue getmempoolancestors(const UniValue& params, bool fHelp) } } +UniValue getmempooldescendants(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 2) { + throw runtime_error( + "getmempooldescendants txid (verbose)\n" + "\nIf txid is in the mempool, returns all in-mempool descendants.\n" + "\nArguments:\n" + "1. \"txid\" (string, required) The transaction id (must be in mempool)\n" + "2. verbose (boolean, optional, default=false) true for a json object, false for array of transaction ids\n" + "\nResult (for verbose=false):\n" + "[ (json array of strings)\n" + " \"transactionid\" (string) The transaction id of an in-mempool descendant transaction\n" + " ,...\n" + "]\n" + "\nResult (for verbose=true):\n" + "{ (json object)\n" + " \"transactionid\" : { (json object)\n" + + EntryDescriptionString() + + " }, ...\n" + "}\n" + "\nExamples\n" + + HelpExampleCli("getmempooldescendants", "\"mytxid\"") + + HelpExampleRpc("getmempooldescendants", "\"mytxid\"") + ); + } + + bool fVerbose = false; + if (params.size() > 1) + fVerbose = params[1].get_bool(); + + uint256 hash = ParseHashV(params[0], "parameter 1"); + + LOCK(mempool.cs); + + CTxMemPool::txiter it = mempool.mapTx.find(hash); + if (it == mempool.mapTx.end()) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not in mempool"); + } + + CTxMemPool::setEntries setDescendants; + mempool.CalculateDescendants(it, setDescendants); + // CTxMemPool::CalculateDescendants will include the given tx + setDescendants.erase(it); + + if (!fVerbose) { + UniValue o(UniValue::VARR); + BOOST_FOREACH(CTxMemPool::txiter descendantIt, setDescendants) { + o.push_back(descendantIt->GetTx().GetHash().ToString()); + } + + return o; + } else { + UniValue o(UniValue::VOBJ); + BOOST_FOREACH(CTxMemPool::txiter descendantIt, setDescendants) { + const CTxMemPoolEntry &e = *descendantIt; + const uint256& hash = e.GetTx().GetHash(); + UniValue info(UniValue::VOBJ); + entryToJSON(info, e); + o.push_back(Pair(hash.ToString(), info)); + } + return o; + } +} + UniValue getblockhash(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 1) @@ -1081,6 +1145,7 @@ static const CRPCCommand commands[] = { "blockchain", "getchaintips", &getchaintips, true }, { "blockchain", "getdifficulty", &getdifficulty, true }, { "blockchain", "getmempoolancestors", &getmempoolancestors, true }, + { "blockchain", "getmempooldescendants", &getmempooldescendants, true }, { "blockchain", "getmempoolinfo", &getmempoolinfo, true }, { "blockchain", "getrawmempool", &getrawmempool, true }, { "blockchain", "gettxout", &gettxout, true }, diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 3dfc27fff78af..d0675fdb49506 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -103,6 +103,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "setban", 2 }, { "setban", 3 }, { "getmempoolancestors", 1 }, + { "getmempooldescendants", 1 }, }; class CRPCConvertTable From b09b8135ae1c4df103c68543c931e479fbb907ab Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Mon, 4 Jan 2016 14:57:58 -0500 Subject: [PATCH 0447/1802] Add getmempoolentry RPC call --- src/rpc/blockchain.cpp | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index e53ed1c1b1d4d..6a07bb8c4eb10 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -420,6 +420,39 @@ UniValue getmempooldescendants(const UniValue& params, bool fHelp) } } +UniValue getmempoolentry(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 1) { + throw runtime_error( + "getmempoolentry txid\n" + "\nReturns mempool data for given transaction\n" + "\nArguments:\n" + "1. \"txid\" (string, required) The transaction id (must be in mempool)\n" + "\nResult:\n" + "{ (json object)\n" + + EntryDescriptionString() + + "}\n" + "\nExamples\n" + + HelpExampleCli("getmempoolentry", "\"mytxid\"") + + HelpExampleRpc("getmempoolentry", "\"mytxid\"") + ); + } + + uint256 hash = ParseHashV(params[0], "parameter 1"); + + LOCK(mempool.cs); + + CTxMemPool::txiter it = mempool.mapTx.find(hash); + if (it == mempool.mapTx.end()) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not in mempool"); + } + + const CTxMemPoolEntry &e = *it; + UniValue info(UniValue::VOBJ); + entryToJSON(info, e); + return info; +} + UniValue getblockhash(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 1) @@ -1146,6 +1179,7 @@ static const CRPCCommand commands[] = { "blockchain", "getdifficulty", &getdifficulty, true }, { "blockchain", "getmempoolancestors", &getmempoolancestors, true }, { "blockchain", "getmempooldescendants", &getmempooldescendants, true }, + { "blockchain", "getmempoolentry", &getmempoolentry, true }, { "blockchain", "getmempoolinfo", &getmempoolinfo, true }, { "blockchain", "getrawmempool", &getrawmempool, true }, { "blockchain", "gettxout", &gettxout, true }, From a9b8390222a19496922c05d0c3f31bd6f75e1ac6 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Mon, 4 Jan 2016 15:15:15 -0500 Subject: [PATCH 0448/1802] Add test coverage for new RPC calls --- qa/rpc-tests/mempool_packages.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/qa/rpc-tests/mempool_packages.py b/qa/rpc-tests/mempool_packages.py index 7ac85c1b6d3e9..35a7e2326de52 100755 --- a/qa/rpc-tests/mempool_packages.py +++ b/qa/rpc-tests/mempool_packages.py @@ -61,7 +61,14 @@ def run_test(self): descendant_fees = 0 descendant_size = 0 + descendants = [] + ancestors = list(chain) for x in reversed(chain): + # Check that getmempoolentry is consistent with getrawmempool + entry = self.nodes[0].getmempoolentry(x) + assert_equal(entry, mempool[x]) + + # Check that the descendant calculations are correct assert_equal(mempool[x]['descendantcount'], descendant_count) descendant_fees += mempool[x]['fee'] assert_equal(mempool[x]['modifiedfee'], mempool[x]['fee']) @@ -70,6 +77,27 @@ def run_test(self): assert_equal(mempool[x]['descendantsize'], descendant_size) descendant_count += 1 + # Check that getmempooldescendants is correct + assert_equal(sorted(descendants), sorted(self.nodes[0].getmempooldescendants(x))) + descendants.append(x) + + # Check that getmempoolancestors is correct + ancestors.remove(x) + assert_equal(sorted(ancestors), sorted(self.nodes[0].getmempoolancestors(x))) + + # Check that getmempoolancestors/getmempooldescendants correctly handle verbose=true + v_ancestors = self.nodes[0].getmempoolancestors(chain[-1], True) + assert_equal(len(v_ancestors), len(chain)-1) + for x in v_ancestors.keys(): + assert_equal(mempool[x], v_ancestors[x]) + assert(chain[-1] not in v_ancestors.keys()) + + v_descendants = self.nodes[0].getmempooldescendants(chain[0], True) + assert_equal(len(v_descendants), len(chain)-1) + for x in v_descendants.keys(): + assert_equal(mempool[x], v_descendants[x]) + assert(chain[0] not in v_descendants.keys()) + # Check that descendant modified fees includes fee deltas from # prioritisetransaction self.nodes[0].prioritisetransaction(chain[-1], 0, 1000) From 7f6eda80438be452a0b6e079737fb6fe00bb26b7 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Tue, 17 May 2016 08:42:35 -0400 Subject: [PATCH 0449/1802] Add ancestor statistics to mempool entry RPC output --- src/rpc/blockchain.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 6a07bb8c4eb10..1bb365d36cdad 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -195,6 +195,9 @@ std::string EntryDescriptionString() " \"descendantcount\" : n, (numeric) number of in-mempool descendant transactions (including this one)\n" " \"descendantsize\" : n, (numeric) size of in-mempool descendants (including this one)\n" " \"descendantfees\" : n, (numeric) modified fees (see above) of in-mempool descendants (including this one)\n" + " \"ancestorcount\" : n, (numeric) number of in-mempool ancestor transactions (including this one)\n" + " \"ancestorsize\" : n, (numeric) size of in-mempool ancestors (including this one)\n" + " \"ancestorfees\" : n, (numeric) modified fees (see above) of in-mempool ancestors (including this one)\n" " \"depends\" : [ (array) unconfirmed transactions used as inputs for this transaction\n" " \"transactionid\", (string) parent transaction id\n" " ... ]\n"; @@ -214,6 +217,9 @@ void entryToJSON(UniValue &info, const CTxMemPoolEntry &e) info.push_back(Pair("descendantcount", e.GetCountWithDescendants())); info.push_back(Pair("descendantsize", e.GetSizeWithDescendants())); info.push_back(Pair("descendantfees", e.GetModFeesWithDescendants())); + info.push_back(Pair("ancestorcount", e.GetCountWithAncestors())); + info.push_back(Pair("ancestorsize", e.GetSizeWithAncestors())); + info.push_back(Pair("ancestorfees", e.GetModFeesWithAncestors())); const CTransaction& tx = e.GetTx(); set setDepends; BOOST_FOREACH(const CTxIn& txin, tx.vin) From 176e19b571f722437043d2aa80a69ae21852c70d Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Tue, 17 May 2016 09:01:12 -0400 Subject: [PATCH 0450/1802] Mention new RPC's in release notes --- doc/release-notes.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/release-notes.md b/doc/release-notes.md index 7d44b8cda934c..be619e41c6ae0 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -80,6 +80,13 @@ The following outputs are affected by this change: - REST `/rest/block/` (JSON format when including extended tx details) - `bitcoin-tx -json` +New mempool information RPC calls +--------------------------------- + +RPC calls have been added to output detailed statistics for individual mempool +entries, as well as to calculate the in-mempool ancestors or descendants of a +transaction: see `getmempoolentry`, `getmempoolancestors`, `getmempooldescendants`. + ### ZMQ Each ZMQ notification now contains an up-counting sequence number that allows From 654a21162252294b7dbd6c982fec88008af7335e Mon Sep 17 00:00:00 2001 From: Kaz Wesley Date: Wed, 8 Jun 2016 13:26:18 -0700 Subject: [PATCH 0451/1802] developer notes: updates for C++11 - boost::scoped_ptr is obsolete - std::vector::data replaces begin_ptr / end_ptr --- doc/developer-notes.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/doc/developer-notes.md b/doc/developer-notes.md index add2fb5004d8e..94bd86203eb6b 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -265,7 +265,7 @@ General C++ the `.h` to the `.cpp` should not result in build errors - Use the RAII (Resource Acquisition Is Initialization) paradigm where possible. For example by using - `scoped_pointer` for allocations in a function. + `unique_ptr` for allocations in a function. - *Rationale*: This avoids memory and resource leaks, and ensures exception safety @@ -284,10 +284,9 @@ C++ data structures - *Rationale*: Behavior is undefined. In C++ parlor this means "may reformat the universe", in practice this has resulted in at least one hard-to-debug crash bug -- Watch out for vector out-of-bounds exceptions. `&vch[0]` is illegal for an - empty vector, `&vch[vch.size()]` is always illegal. Use `begin_ptr(vch)` and - `end_ptr(vch)` to get the begin and end pointer instead (defined in - `serialize.h`) +- Watch out for out-of-bounds vector access. `&vch[vch.size()]` is illegal, + including `&vch[0]` for an empty vector. Use `vch.data()` and `vch.data() + + vch.size()` instead. - Vector bounds checking is only enabled in debug mode. Do not rely on it From 966151e71dc33cb5b97cf4243efd18afb4cf279d Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Thu, 9 Jun 2016 13:55:12 -0400 Subject: [PATCH 0452/1802] Add README for verify-commits --- contrib/verify-commits/README.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 contrib/verify-commits/README.md diff --git a/contrib/verify-commits/README.md b/contrib/verify-commits/README.md new file mode 100644 index 0000000000000..e9e3f65da292a --- /dev/null +++ b/contrib/verify-commits/README.md @@ -0,0 +1,26 @@ +Tooling for verification of PGP signed commits +---------------------------------------------- + +This is an incomplete work in progress, but currently includes a pre-push hook +script (`pre-push-hook.sh`) for maintainers to ensure that their own commits +are PGP signed (nearly always merge commits), as well as a script to verify +commits against a trusted keys list. + + +Using verify-commits.sh safely +------------------------------ + +Remember that you can't use an untrusted script to verify itself. This means +that checking out code, then running `verify-commits.sh` against `HEAD` is +_not_ safe, because the version of `verify-commits.sh` that you just ran could +be backdoored. Instead, you need to use a trusted version of verify-commits +prior to checkout to make sure you're checking out only code signed by trusted +keys: + + git fetch origin && \ + ./contrib/verify-commits/verify-commits.sh origin/master && \ + git checkout origin/master + +Note that the above isn't a good UI/UX yet, and needs significant improvements +to make it more convenient and reduce the chance of errors; pull-reqs +improving this process would be much appreciated. From d1a3d570e5f4e59683cde9ccc0ac10d012ef7070 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 9 Jun 2016 17:49:16 -0400 Subject: [PATCH 0453/1802] bulid: fix "make translate" when out-of-tree --- src/Makefile.qt.include | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 29e3a264ccc7c..9381cca9f256c 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -390,13 +390,13 @@ QT_QM=$(QT_TS:.ts=.qm) SECONDARY: $(QT_QM) -qt/bitcoinstrings.cpp: $(libbitcoin_server_a_SOURCES) $(libbitcoin_wallet_a_SOURCES) +$(srcdir)/qt/bitcoinstrings.cpp: $(libbitcoin_server_a_SOURCES) $(libbitcoin_wallet_a_SOURCES) @test -n $(XGETTEXT) || echo "xgettext is required for updating translations" $(AM_V_GEN) cd $(srcdir); XGETTEXT=$(XGETTEXT) PACKAGE_NAME="$(PACKAGE_NAME)" COPYRIGHT_HOLDERS="$(COPYRIGHT_HOLDERS)" COPYRIGHT_HOLDERS_SUBSTITUTION="$(COPYRIGHT_HOLDERS_SUBSTITUTION)" $(PYTHON) ../share/qt/extract_strings_qt.py $^ -translate: qt/bitcoinstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_QT_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM) +translate: $(srcdir)/qt/bitcoinstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_QT_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM) @test -n $(LUPDATE) || echo "lupdate is required for updating translations" - $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(LUPDATE) $^ -locations relative -no-obsolete -ts qt/locale/bitcoin_en.ts + $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(LUPDATE) $^ -locations relative -no-obsolete -ts $(srcdir)/qt/locale/bitcoin_en.ts $(QT_QRC_LOCALE_CPP): $(QT_QRC_LOCALE) $(QT_QM) @test -f $(RCC) From ac8d0418ed2891311cb786f32d39a54242aa2759 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 10 Jun 2016 10:12:00 +0200 Subject: [PATCH 0454/1802] qt: translations update --- src/qt/bitcoinstrings.cpp | 2 -- src/qt/locale/bitcoin_en.ts | 25 ++++++++++--------------- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp index 23be8e016bddf..9e53f19591070 100644 --- a/src/qt/bitcoinstrings.cpp +++ b/src/qt/bitcoinstrings.cpp @@ -140,8 +140,6 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" QT_TRANSLATE_NOOP("bitcoin-core", "" "Support filtering of blocks and transaction with bloom filters (default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "" -"Tell other nodes to filter invs to us by our mempool min fee (default: %u)"), -QT_TRANSLATE_NOOP("bitcoin-core", "" "The block database contains a block which appears to be from the future. " "This may be due to your computer's date and time being set incorrectly. Only " "rebuild the block database if you are sure that your computer's date and " diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts index 5549ccd4f80f9..b90221f2c2535 100644 --- a/src/qt/locale/bitcoin_en.ts +++ b/src/qt/locale/bitcoin_en.ts @@ -3785,7 +3785,7 @@ bitcoin-core - + Options: Options: @@ -3810,7 +3810,7 @@ Accept command line and JSON-RPC commands - + If <category> is not supplied or if <category> = 1, output all debugging information. @@ -3835,7 +3835,7 @@ - + Error: A fatal internal error occurred, see debug.log for details @@ -3865,7 +3865,7 @@ Accept connections from outside (default: 1 if no -proxy or -connect) - + Bitcoin Core Bitcoin Core @@ -3946,11 +3946,6 @@ - Tell other nodes to filter invs to us by our mempool min fee (default: %u) - - - - 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 @@ -4305,7 +4300,7 @@ - + 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 @@ -4375,7 +4370,7 @@ - + The transaction amount is too small to send after the fee has been deducted @@ -4580,12 +4575,12 @@ Password for JSON-RPC connections - + Execute command when the best block changes (%s in cmd is replaced by block hash) Execute command when the best block changes (%s in cmd is replaced by block hash) - + Allow DNS lookups for -addnode, -seednode and -connect Allow DNS lookups for -addnode, -seednode and -connect @@ -4595,7 +4590,7 @@ Loading addresses... - + (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) @@ -4645,7 +4640,7 @@ - + Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments. From 980e7eb98c81af5acc843cdd697ad277489252ad Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 9 Jun 2016 18:13:33 -0400 Subject: [PATCH 0455/1802] depends: only build qt on linux for x86_64/x86 --- depends/Makefile | 10 +++++++--- depends/packages/packages.mk | 4 +++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/depends/Makefile b/depends/Makefile index 3ddfc85a450d0..dedb0674cf149 100644 --- a/depends/Makefile +++ b/depends/Makefile @@ -89,13 +89,17 @@ $(host_arch)_$(host_os)_id_string+=$(shell $(host_CXX) --version 2>/dev/null) $(host_arch)_$(host_os)_id_string+=$(shell $(host_RANLIB) --version 2>/dev/null) $(host_arch)_$(host_os)_id_string+=$(shell $(host_STRIP) --version 2>/dev/null) -qt_packages_$(NO_QT) = $(qt_packages) $(qt_$(host_os)_packages) -qt_native_packages_$(NO_QT) = $(qt_native_packages) +qt_packages_$(NO_QT) = $(qt_packages) $(qt_$(host_os)_packages) $(qt_$(host_arch)_$(host_os)_packages) wallet_packages_$(NO_WALLET) = $(wallet_packages) upnp_packages_$(NO_UPNP) = $(upnp_packages) packages += $($(host_arch)_$(host_os)_packages) $($(host_os)_packages) $(qt_packages_) $(wallet_packages_) $(upnp_packages_) -native_packages += $($(host_arch)_$(host_os)_native_packages) $($(host_os)_native_packages) $(qt_native_packages_) +native_packages += $($(host_arch)_$(host_os)_native_packages) $($(host_os)_native_packages) + +ifneq ($(qt_packages_),) +native_packages += $(qt_native_packages) +endif + all_packages = $(packages) $(native_packages) meta_depends = Makefile funcs.mk builders/default.mk hosts/default.mk hosts/$(host_os).mk builders/$(build_os).mk diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk index 59b009b66a27b..ac43ef4a2e304 100644 --- a/depends/packages/packages.mk +++ b/depends/packages/packages.mk @@ -6,7 +6,9 @@ native_packages := native_ccache native_comparisontool qt_native_packages = native_protobuf qt_packages = qrencode protobuf -qt_linux_packages= qt expat dbus libxcb xcb_proto libXau xproto freetype fontconfig libX11 xextproto libXext xtrans +qt_x86_64_linux_packages:=qt expat dbus libxcb xcb_proto libXau xproto freetype fontconfig libX11 xextproto libXext xtrans +qt_i686_linux_packages:=$(qt_x86_64_linux_packages) + qt_darwin_packages=qt qt_mingw32_packages=qt From 17c0131fad62bfc966da93b7e42c7f0e07948b51 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 10 Jun 2016 11:04:16 +0200 Subject: [PATCH 0456/1802] [Docs] Add release notes and bip update for Bip32/HD wallets --- doc/bips.md | 1 + doc/release-notes.md | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/doc/bips.md b/doc/bips.md index b8efabbcf251c..266544d7ac96d 100644 --- a/doc/bips.md +++ b/doc/bips.md @@ -9,6 +9,7 @@ BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.12.0**): * [`BIP 23`](https://github.com/bitcoin/bips/blob/master/bip-0023.mediawiki): Some extensions to GBT have been implemented since **v0.10.0rc1**, including longpolling and block proposals ([PR #1816](https://github.com/bitcoin/bitcoin/pull/1816)). * [`BIP 30`](https://github.com/bitcoin/bips/blob/master/bip-0030.mediawiki): The evaluation rules to forbid creating new transactions with the same txid as previous not-fully-spent transactions were implemented since **v0.6.0**, and the rule took effect on *March 15th 2012* ([PR #915](https://github.com/bitcoin/bitcoin/pull/915)). * [`BIP 31`](https://github.com/bitcoin/bips/blob/master/bip-0031.mediawiki): The 'pong' protocol message (and the protocol version bump to 60001) has been implemented since **v0.6.1** ([PR #1081](https://github.com/bitcoin/bitcoin/pull/1081)). +* [`BIP 32`](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki): Hierarchical Deterministic Wallets has been implemented since **v0.13.0** ([PR #8035](https://github.com/bitcoin/bitcoin/pull/8035)). * [`BIP 34`](https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki): The rule that requires blocks to contain their height (number) in the coinbase input, and the introduction of version 2 blocks has been implemented since **v0.7.0**. The rule took effect for version 2 blocks as of *block 224413* (March 5th 2013), and version 1 blocks are no longer allowed since *block 227931* (March 25th 2013) ([PR #1526](https://github.com/bitcoin/bitcoin/pull/1526)). * [`BIP 35`](https://github.com/bitcoin/bips/blob/master/bip-0035.mediawiki): The 'mempool' protocol message (and the protocol version bump to 60002) has been implemented since **v0.7.0** ([PR #1641](https://github.com/bitcoin/bitcoin/pull/1641)). * [`BIP 37`](https://github.com/bitcoin/bips/blob/master/bip-0037.mediawiki): The bloom filtering for transaction relaying, partial merkle trees for blocks, and the protocol version bump to 70001 (enabling low-bandwidth SPV clients) has been implemented since **v0.8.0** ([PR #1795](https://github.com/bitcoin/bitcoin/pull/1795)). diff --git a/doc/release-notes.md b/doc/release-notes.md index 7d44b8cda934c..72f69446f8f23 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -112,6 +112,24 @@ feerate. [BIP 133](https://github.com/bitcoin/bips/blob/master/bip-0133.mediawik ### Wallet +Hierarchical Deterministic Key Generation +----------------------------------------- +Newly created wallets will use hierarchical deterministic key generation +according to BIP32 (keypath m/0'/0'/k'). +Existing wallets will still use traditional key generation. + +Backups of HD wallets, regardless of when they have been created, can +therefore be used to re-generate all possible private keys, even the +ones which haven't already been generated during the time of the backup. + +HD key generation for new wallets can be disabled by `-usehd=0`. Keep in +mind that this flag only has affect on newly created wallets. +You can't disable HD key generation once you have created a HD wallet. + +There is no distinction between internal (change) and external keys. + +[Pull request](https://github.com/bitcoin/bitcoin/pull/8035/files), [BIP 32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) + ### GUI ### Tests From 9d253620874087d96d64d0c4c771a582d9774657 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 10 Jun 2016 02:56:42 -0400 Subject: [PATCH 0457/1802] build: add armhf/aarch64 gitian builds - create a script to handle split debug. This will also eventually need to check targets, and use dsymutil for osx. - update config.guess/config.sub for bdb for aarch64. - temporarily disable symbol checks for arm/aarch64 - quit renaming to linux32/linux64 and use the host directly This also adds a hack to work around an Ubuntu bug in the gcc-multilib package: https://bugs.launchpad.net/ubuntu/+source/gcc-defaults-armhf-cross/+bug/1347820 The problem is that gcc-multilib conflicts with the aarch toolchain. gcc-multilib installs a symlink that points /usr/include/asm -> /usr/include/x86_64-linux-gnu/asm. Without this link, gcc -m32 can't find asm/errno.h (and others), since /usr/include/x86_64-linux-gnu isn't in its default include path. But /usr/include/i386-linux-gnu is (though it doesn't exist on disk). So work around the problem by linking /usr/include/i386-linux-gnu/asm -> /usr/include/x86_64-linux-gnu/asm. The symlink fix is actually quite reasonable, but echoing the password into sudo is nasty, and should probably be addressed in gitian itself. It makes more sense to enable passwordless sudo for the build user by default. --- configure.ac | 2 + contrib/devtools/split-debug.sh.in | 10 +++++ contrib/gitian-descriptors/gitian-linux.yml | 45 +++++++++++++++------ depends/packages/bdb.mk | 3 +- 4 files changed, 47 insertions(+), 13 deletions(-) create mode 100644 contrib/devtools/split-debug.sh.in diff --git a/configure.ac b/configure.ac index 7f9ff20cd7be5..97af58bd7cd85 100644 --- a/configure.ac +++ b/configure.ac @@ -75,6 +75,7 @@ AC_PATH_PROG(XGETTEXT,xgettext) AC_PATH_PROG(HEXDUMP,hexdump) AC_PATH_TOOL(READELF, readelf) AC_PATH_TOOL(CPPFILT, c++filt) +AC_PATH_TOOL(OBJCOPY, objcopy) AC_ARG_VAR(PYTHONPATH, Augments the default search path for python module files) @@ -1060,6 +1061,7 @@ AC_SUBST(MINIUPNPC_LIBS) AC_CONFIG_FILES([Makefile src/Makefile share/setup.nsi share/qt/Info.plist src/test/buildenv.py]) AC_CONFIG_FILES([qa/pull-tester/run-bitcoind-for-test.sh],[chmod +x qa/pull-tester/run-bitcoind-for-test.sh]) AC_CONFIG_FILES([qa/pull-tester/tests_config.py],[chmod +x qa/pull-tester/tests_config.py]) +AC_CONFIG_FILES([contrib/devtools/split-debug.sh],[chmod +x contrib/devtools/split-debug.sh]) AC_CONFIG_LINKS([qa/pull-tester/rpc-tests.py:qa/pull-tester/rpc-tests.py]) dnl boost's m4 checks do something really nasty: they export these vars. As a diff --git a/contrib/devtools/split-debug.sh.in b/contrib/devtools/split-debug.sh.in new file mode 100644 index 0000000000000..deda49cc54104 --- /dev/null +++ b/contrib/devtools/split-debug.sh.in @@ -0,0 +1,10 @@ +#!/bin/sh + +if [ $# -ne 3 ]; + then echo "usage: $0 " +fi + +@OBJCOPY@ --enable-deterministic-archives -p --only-keep-debug $1 $3 +@OBJCOPY@ --enable-deterministic-archives -p --strip-debug $1 $2 +@STRIP@ --enable-deterministic-archives -p -s $2 +@OBJCOPY@ --enable-deterministic-archives -p --add-gnu-debuglink=$3 $2 diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index cd289b2f6e4c8..fb629578d65f0 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -7,7 +7,17 @@ architectures: - "amd64" packages: - "curl" -- "g++-multilib" +- "g++-aarch64-linux-gnu" +- "g++-4.8-aarch64-linux-gnu" +- "gcc-4.8-aarch64-linux-gnu" +- "binutils-aarch64-linux-gnu" +- "g++-arm-linux-gnueabihf" +- "g++-4.8-arm-linux-gnueabihf" +- "gcc-4.8-arm-linux-gnueabihf" +- "binutils-arm-linux-gnueabihf" +- "g++-4.8-multilib" +- "gcc-4.8-multilib" +- "binutils-gold" - "git-core" - "pkg-config" - "autoconf" @@ -15,7 +25,6 @@ packages: - "automake" - "faketime" - "bsdmainutils" -- "binutils-gold" - "ca-certificates" - "python" remotes: @@ -23,11 +32,18 @@ remotes: "dir": "bitcoin" files: [] script: | + + #unlock sudo + echo "ubuntu" | sudo -S true + + sudo mkdir -p /usr/include/i386-linux-gnu/ + sudo ln -s /usr/include/x86_64-linux-gnu/asm /usr/include/i386-linux-gnu/asm + WRAP_DIR=$HOME/wrapped - HOSTS="i686-pc-linux-gnu x86_64-unknown-linux-gnu" + HOSTS="i686-pc-linux-gnu x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu" CONFIGFLAGS="--enable-glibc-back-compat --enable-reduce-exports --disable-bench --disable-gui-tests" FAKETIME_HOST_PROGS="" - FAKETIME_PROGS="date ar ranlib nm strip objcopy" + FAKETIME_PROGS="date ar ranlib nm" HOST_CFLAGS="-O2 -g" HOST_CXXFLAGS="-O2 -g" HOST_LDFLAGS=-static-libstdc++ @@ -111,14 +127,24 @@ script: | CONFIG_SITE=${BASEPREFIX}/${i}/share/config.site ./configure --prefix=/ --disable-ccache --disable-maintainer-mode --disable-dependency-tracking ${CONFIGFLAGS} CFLAGS="${HOST_CFLAGS}" CXXFLAGS="${HOST_CXXFLAGS}" LDFLAGS="${HOST_LDFLAGS}" make ${MAKEOPTS} make ${MAKEOPTS} -C src check-security - make ${MAKEOPTS} -C src check-symbols + + #TODO: This is a quick hack that disables symbol checking for arm. + # Instead, we should investigate why these are popping up. + # For aarch64, we'll need to bump up the min GLIBC version, as the abi + # support wasn't introduced until 2.17. + case $i in + aarch64-*) : ;; + arm-*) : ;; + *) make ${MAKEOPTS} -C src check-symbols ;; + esac + make install DESTDIR=${INSTALLPATH} cd installed find . -name "lib*.la" -delete find . -name "lib*.a" -delete rm -rf ${DISTNAME}/lib/pkgconfig - find ${DISTNAME}/bin -type f -executable -exec objcopy --only-keep-debug {} {}.dbg \; -exec strip -s {} \; -exec objcopy --add-gnu-debuglink={}.dbg {} \; - find ${DISTNAME}/lib -type f -exec objcopy --only-keep-debug {} {}.dbg \; -exec strip -s {} \; -exec objcopy --add-gnu-debuglink={}.dbg {} \; + find ${DISTNAME}/bin -type f -executable -exec ../contrib/devtools/split-debug.sh {} {} {}.dbg \; + find ${DISTNAME}/lib -type f -exec ../contrib/devtools/split-debug.sh {} {} {}.dbg \; find ${DISTNAME} -not -name "*.dbg" | sort | tar --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-${i}.tar.gz find ${DISTNAME} -name "*.dbg" | sort | tar --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-${i}-debug.tar.gz cd ../../ @@ -126,8 +152,3 @@ script: | done mkdir -p $OUTDIR/src mv $SOURCEDIST $OUTDIR/src - mv ${OUTDIR}/${DISTNAME}-x86_64-*-debug.tar.gz ${OUTDIR}/${DISTNAME}-linux64-debug.tar.gz - mv ${OUTDIR}/${DISTNAME}-i686-*-debug.tar.gz ${OUTDIR}/${DISTNAME}-linux32-debug.tar.gz - mv ${OUTDIR}/${DISTNAME}-x86_64-*.tar.gz ${OUTDIR}/${DISTNAME}-linux64.tar.gz - mv ${OUTDIR}/${DISTNAME}-i686-*.tar.gz ${OUTDIR}/${DISTNAME}-linux32.tar.gz - diff --git a/depends/packages/bdb.mk b/depends/packages/bdb.mk index 200d57314ea0d..6c9876c2c7c7c 100644 --- a/depends/packages/bdb.mk +++ b/depends/packages/bdb.mk @@ -14,7 +14,8 @@ endef define $(package)_preprocess_cmds sed -i.old 's/__atomic_compare_exchange/__atomic_compare_exchange_db/' dbinc/atomic.h && \ - sed -i.old 's/atomic_init/atomic_init_db/' dbinc/atomic.h mp/mp_region.c mp/mp_mvcc.c mp/mp_fget.c mutex/mut_method.c mutex/mut_tas.c + sed -i.old 's/atomic_init/atomic_init_db/' dbinc/atomic.h mp/mp_region.c mp/mp_mvcc.c mp/mp_fget.c mutex/mut_method.c mutex/mut_tas.c && \ + cp -f $(BASEDIR)/config.guess $(BASEDIR)/config.sub dist endef define $(package)_config_cmds From 60ab9b200654ef0914459711cf2b22be16be3dc2 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 10 Jun 2016 15:19:51 +0200 Subject: [PATCH 0458/1802] Squashed 'src/univalue/' changes from 2740c4f..f32df99 f32df99 Merge branch '2016_04_unicode' into bitcoin 280b191 Merge remote-tracking branch 'jgarzik/master' into bitcoin c9a716c Handle UTF-8 bed8dd9 Version 1.0.2. 5e7985a Merge pull request #14 from laanwj/2015_11_escape_plan git-subtree-dir: src/univalue git-subtree-split: f32df99e96d99ab49e5eeda16cac93747d388245 --- Makefile.am | 9 ++- configure.ac | 6 +- lib/univalue_read.cpp | 37 +++++------- lib/univalue_utffilter.h | 119 +++++++++++++++++++++++++++++++++++++++ lib/univalue_write.cpp | 11 +--- test/fail38.json | 1 + test/fail39.json | 1 + test/fail40.json | 1 + test/fail41.json | 1 + test/round2.json | 1 + test/unitester.cpp | 31 ++++++++++ 11 files changed, 181 insertions(+), 37 deletions(-) create mode 100644 lib/univalue_utffilter.h create mode 100644 test/fail38.json create mode 100644 test/fail39.json create mode 100644 test/fail40.json create mode 100644 test/fail41.json create mode 100644 test/round2.json diff --git a/Makefile.am b/Makefile.am index 34fe9e3f13dbc..6c1ec81e63fb7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,7 +3,7 @@ ACLOCAL_AMFLAGS = -I build-aux/m4 .INTERMEDIATE: $(GENBIN) include_HEADERS = include/univalue.h -noinst_HEADERS = lib/univalue_escapes.h +noinst_HEADERS = lib/univalue_escapes.h lib/univalue_utffilter.h lib_LTLIBRARIES = libunivalue.la @@ -73,6 +73,10 @@ TEST_FILES = \ $(TEST_DATA_DIR)/fail35.json \ $(TEST_DATA_DIR)/fail36.json \ $(TEST_DATA_DIR)/fail37.json \ + $(TEST_DATA_DIR)/fail38.json \ + $(TEST_DATA_DIR)/fail39.json \ + $(TEST_DATA_DIR)/fail40.json \ + $(TEST_DATA_DIR)/fail41.json \ $(TEST_DATA_DIR)/fail3.json \ $(TEST_DATA_DIR)/fail4.json \ $(TEST_DATA_DIR)/fail5.json \ @@ -83,6 +87,7 @@ TEST_FILES = \ $(TEST_DATA_DIR)/pass1.json \ $(TEST_DATA_DIR)/pass2.json \ $(TEST_DATA_DIR)/pass3.json \ - $(TEST_DATA_DIR)/round1.json + $(TEST_DATA_DIR)/round1.json \ + $(TEST_DATA_DIR)/round2.json EXTRA_DIST=$(TEST_FILES) $(GEN_SRCS) diff --git a/configure.ac b/configure.ac index 0515b632bdf9a..93d3ba945d143 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ m4_define([libunivalue_major_version], [1]) m4_define([libunivalue_minor_version], [1]) -m4_define([libunivalue_micro_version], [1]) -m4_define([libunivalue_interface_age], [1]) +m4_define([libunivalue_micro_version], [2]) +m4_define([libunivalue_interface_age], [2]) # If you need a modifier for the version number. # Normally empty, but can be used to make "fixup" releases. m4_define([libunivalue_extraversion], []) @@ -14,7 +14,7 @@ m4_define([libunivalue_age], [m4_eval(libunivalue_binary_age - libunivalue_inter m4_define([libunivalue_version], [libunivalue_major_version().libunivalue_minor_version().libunivalue_micro_version()libunivalue_extraversion()]) -AC_INIT([univalue], [1.0.1], +AC_INIT([univalue], [1.0.2], [http://github.com/jgarzik/univalue/]) dnl make the compilation flags quiet unless V=1 is used diff --git a/lib/univalue_read.cpp b/lib/univalue_read.cpp index c7516b9628169..95bac6958d0fa 100644 --- a/lib/univalue_read.cpp +++ b/lib/univalue_read.cpp @@ -6,6 +6,7 @@ #include #include #include "univalue.h" +#include "univalue_utffilter.h" using namespace std; @@ -174,41 +175,31 @@ enum jtokentype getJsonToken(string& tokenVal, unsigned int& consumed, raw++; // skip " string valStr; + JSONUTF8StringFilter writer(valStr); while (*raw) { - if (*raw < 0x20) + if ((unsigned char)*raw < 0x20) return JTOK_ERR; else if (*raw == '\\') { raw++; // skip backslash switch (*raw) { - case '"': valStr += "\""; break; - case '\\': valStr += "\\"; break; - case '/': valStr += "/"; break; - case 'b': valStr += "\b"; break; - case 'f': valStr += "\f"; break; - case 'n': valStr += "\n"; break; - case 'r': valStr += "\r"; break; - case 't': valStr += "\t"; break; + case '"': writer.push_back('\"'); break; + case '\\': writer.push_back('\\'); break; + case '/': writer.push_back('/'); break; + case 'b': writer.push_back('\b'); break; + case 'f': writer.push_back('\f'); break; + case 'n': writer.push_back('\n'); break; + case 'r': writer.push_back('\r'); break; + case 't': writer.push_back('\t'); break; case 'u': { unsigned int codepoint; if (hatoui(raw + 1, raw + 1 + 4, codepoint) != raw + 1 + 4) return JTOK_ERR; - - if (codepoint <= 0x7f) - valStr.push_back((char)codepoint); - else if (codepoint <= 0x7FF) { - valStr.push_back((char)(0xC0 | (codepoint >> 6))); - valStr.push_back((char)(0x80 | (codepoint & 0x3F))); - } else if (codepoint <= 0xFFFF) { - valStr.push_back((char)(0xE0 | (codepoint >> 12))); - valStr.push_back((char)(0x80 | ((codepoint >> 6) & 0x3F))); - valStr.push_back((char)(0x80 | (codepoint & 0x3F))); - } - + writer.push_back_u(codepoint); raw += 4; break; } @@ -226,11 +217,13 @@ enum jtokentype getJsonToken(string& tokenVal, unsigned int& consumed, } else { - valStr += *raw; + writer.push_back(*raw); raw++; } } + if (!writer.finalize()) + return JTOK_ERR; tokenVal = valStr; consumed = (raw - rawStart); return JTOK_STRING; diff --git a/lib/univalue_utffilter.h b/lib/univalue_utffilter.h new file mode 100644 index 0000000000000..0e330dce9cd04 --- /dev/null +++ b/lib/univalue_utffilter.h @@ -0,0 +1,119 @@ +// Copyright 2016 Wladimir J. van der Laan +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#ifndef UNIVALUE_UTFFILTER_H +#define UNIVALUE_UTFFILTER_H + +#include + +/** + * Filter that generates and validates UTF-8, as well as collates UTF-16 + * surrogate pairs as specified in RFC4627. + */ +class JSONUTF8StringFilter +{ +public: + JSONUTF8StringFilter(std::string &s): + str(s), is_valid(true), codepoint(0), state(0), surpair(0) + { + } + // Write single 8-bit char (may be part of UTF-8 sequence) + void push_back(unsigned char ch) + { + if (state == 0) { + if (ch < 0x80) // 7-bit ASCII, fast direct pass-through + str.push_back(ch); + else if (ch < 0xc0) // Mid-sequence character, invalid in this state + is_valid = false; + else if (ch < 0xe0) { // Start of 2-byte sequence + codepoint = (ch & 0x1f) << 6; + state = 6; + } else if (ch < 0xf0) { // Start of 3-byte sequence + codepoint = (ch & 0x0f) << 12; + state = 12; + } else if (ch < 0xf8) { // Start of 4-byte sequence + codepoint = (ch & 0x07) << 18; + state = 18; + } else // Reserved, invalid + is_valid = false; + } else { + if ((ch & 0xc0) != 0x80) // Not a continuation, invalid + is_valid = false; + state -= 6; + codepoint |= (ch & 0x3f) << state; + if (state == 0) + push_back_u(codepoint); + } + } + // Write codepoint directly, possibly collating surrogate pairs + void push_back_u(unsigned int codepoint) + { + if (state) // Only accept full codepoints in open state + is_valid = false; + if (codepoint >= 0xD800 && codepoint < 0xDC00) { // First half of surrogate pair + if (surpair) // Two subsequent surrogate pair openers - fail + is_valid = false; + else + surpair = codepoint; + } else if (codepoint >= 0xDC00 && codepoint < 0xE000) { // Second half of surrogate pair + if (surpair) { // Open surrogate pair, expect second half + // Compute code point from UTF-16 surrogate pair + append_codepoint(0x10000 | ((surpair - 0xD800)<<10) | (codepoint - 0xDC00)); + surpair = 0; + } else // Second half doesn't follow a first half - fail + is_valid = false; + } else { + if (surpair) // First half of surrogate pair not followed by second - fail + is_valid = false; + else + append_codepoint(codepoint); + } + } + // Check that we're in a state where the string can be ended + // No open sequences, no open surrogate pairs, etc + bool finalize() + { + if (state || surpair) + is_valid = false; + return is_valid; + } +private: + std::string &str; + bool is_valid; + // Current UTF-8 decoding state + unsigned int codepoint; + int state; // Top bit to be filled in for next UTF-8 byte, or 0 + + // Keep track of the following state to handle the following section of + // RFC4627: + // + // To escape an extended character that is not in the Basic Multilingual + // Plane, the character is represented as a twelve-character sequence, + // encoding the UTF-16 surrogate pair. So, for example, a string + // containing only the G clef character (U+1D11E) may be represented as + // "\uD834\uDD1E". + // + // Two subsequent \u.... may have to be replaced with one actual codepoint. + unsigned int surpair; // First half of open UTF-16 surrogate pair, or 0 + + void append_codepoint(unsigned int codepoint) + { + if (codepoint <= 0x7f) + str.push_back((char)codepoint); + else if (codepoint <= 0x7FF) { + str.push_back((char)(0xC0 | (codepoint >> 6))); + str.push_back((char)(0x80 | (codepoint & 0x3F))); + } else if (codepoint <= 0xFFFF) { + str.push_back((char)(0xE0 | (codepoint >> 12))); + str.push_back((char)(0x80 | ((codepoint >> 6) & 0x3F))); + str.push_back((char)(0x80 | (codepoint & 0x3F))); + } else if (codepoint <= 0x1FFFFF) { + str.push_back((char)(0xF0 | (codepoint >> 18))); + str.push_back((char)(0x80 | ((codepoint >> 12) & 0x3F))); + str.push_back((char)(0x80 | ((codepoint >> 6) & 0x3F))); + str.push_back((char)(0x80 | (codepoint & 0x3F))); + } + } +}; + +#endif diff --git a/lib/univalue_write.cpp b/lib/univalue_write.cpp index ceb4cc9166cd2..cfbdad3284ed5 100644 --- a/lib/univalue_write.cpp +++ b/lib/univalue_write.cpp @@ -8,8 +8,6 @@ #include "univalue.h" #include "univalue_escapes.h" -// TODO: Using UTF8 - using namespace std; static string json_escape(const string& inS) @@ -23,15 +21,8 @@ static string json_escape(const string& inS) if (escStr) outS += escStr; - - else if (ch < 0x80) + else outS += ch; - - else { // TODO handle UTF-8 properly - char tmpesc[16]; - sprintf(tmpesc, "\\u%04x", ch); - outS += tmpesc; - } } return outS; diff --git a/test/fail38.json b/test/fail38.json new file mode 100644 index 0000000000000..b245e2e46cad5 --- /dev/null +++ b/test/fail38.json @@ -0,0 +1 @@ +["\ud834"] diff --git a/test/fail39.json b/test/fail39.json new file mode 100644 index 0000000000000..7c9e263f27de5 --- /dev/null +++ b/test/fail39.json @@ -0,0 +1 @@ +["\udd61"] diff --git a/test/fail40.json b/test/fail40.json new file mode 100644 index 0000000000000..664dc9e245f65 --- /dev/null +++ b/test/fail40.json @@ -0,0 +1 @@ +[""] \ No newline at end of file diff --git a/test/fail41.json b/test/fail41.json new file mode 100644 index 0000000000000..0de342a2b5fdf --- /dev/null +++ b/test/fail41.json @@ -0,0 +1 @@ +[""] \ No newline at end of file diff --git a/test/round2.json b/test/round2.json new file mode 100644 index 0000000000000..b766cccc68899 --- /dev/null +++ b/test/round2.json @@ -0,0 +1 @@ +["a§■𐎒𝅘𝅥𝅯"] diff --git a/test/unitester.cpp b/test/unitester.cpp index 5a052fe92c85b..05f3842cd1eb6 100644 --- a/test/unitester.cpp +++ b/test/unitester.cpp @@ -22,6 +22,7 @@ string srcdir(JSON_TEST_SRC); static bool test_failed = false; #define d_assert(expr) { if (!(expr)) { test_failed = true; fprintf(stderr, "%s failed\n", filename.c_str()); } } +#define f_assert(expr) { if (!(expr)) { test_failed = true; fprintf(stderr, "%s failed\n", __func__); } } static std::string rtrim(std::string s) { @@ -108,6 +109,10 @@ static const char *filenames[] = { "fail35.json", "fail36.json", "fail37.json", + "fail38.json", // invalid unicode: only first half of surrogate pair + "fail39.json", // invalid unicode: only second half of surrogate pair + "fail40.json", // invalid unicode: broken UTF-8 + "fail41.json", // invalid unicode: unfinished UTF-8 "fail3.json", "fail4.json", // extra comma "fail5.json", @@ -119,14 +124,40 @@ static const char *filenames[] = { "pass2.json", "pass3.json", "round1.json", // round-trip test + "round2.json", // unicode }; +// Test \u handling +void unescape_unicode_test() +{ + UniValue val; + bool testResult; + // Escaped ASCII (quote) + testResult = val.read("[\"\\u0022\"]"); + f_assert(testResult); + f_assert(val[0].get_str() == "\""); + // Escaped Basic Plane character, two-byte UTF-8 + testResult = val.read("[\"\\u0191\"]"); + f_assert(testResult); + f_assert(val[0].get_str() == "\xc6\x91"); + // Escaped Basic Plane character, three-byte UTF-8 + testResult = val.read("[\"\\u2191\"]"); + f_assert(testResult); + f_assert(val[0].get_str() == "\xe2\x86\x91"); + // Escaped Supplementary Plane character U+1d161 + testResult = val.read("[\"\\ud834\\udd61\"]"); + f_assert(testResult); + f_assert(val[0].get_str() == "\xf0\x9d\x85\xa1"); +} + int main (int argc, char *argv[]) { for (unsigned int fidx = 0; fidx < ARRAY_SIZE(filenames); fidx++) { runtest_file(filenames[fidx]); } + unescape_unicode_test(); + return test_failed ? 1 : 0; } From a406fcb6cacdc49ce11fc6147df58c0c827a7a06 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 28 Apr 2016 15:17:41 +0200 Subject: [PATCH 0459/1802] test: add ensure_ascii setting to AuthServiceProxy Add a setting ensure_ascii to AuthServiceProxy. This setting, defaulting to True (backwards compatible), is passed through to json.dumps. If set to False, non-ASCII characters >0x80 are not escaped. This is useful for testing server input processing, as well as slightly more bandwidth friendly in case of heavy unicode usage. --- qa/rpc-tests/test_framework/authproxy.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/qa/rpc-tests/test_framework/authproxy.py b/qa/rpc-tests/test_framework/authproxy.py index 95b2be658cffe..d095a56ce75e3 100644 --- a/qa/rpc-tests/test_framework/authproxy.py +++ b/qa/rpc-tests/test_framework/authproxy.py @@ -67,9 +67,11 @@ def EncodeDecimal(o): class AuthServiceProxy(object): __id_count = 0 - def __init__(self, service_url, service_name=None, timeout=HTTP_TIMEOUT, connection=None): + # ensure_ascii: escape unicode as \uXXXX, passed to json.dumps + def __init__(self, service_url, service_name=None, timeout=HTTP_TIMEOUT, connection=None, ensure_ascii=True): self.__service_url = service_url self._service_name = service_name + self.ensure_ascii = ensure_ascii # can be toggled on the fly by tests self.__url = urlparse.urlparse(service_url) if self.__url.port is None: port = 80 @@ -134,12 +136,12 @@ def __call__(self, *args): AuthServiceProxy.__id_count += 1 log.debug("-%s-> %s %s"%(AuthServiceProxy.__id_count, self._service_name, - json.dumps(args, default=EncodeDecimal))) + json.dumps(args, default=EncodeDecimal, ensure_ascii=self.ensure_ascii))) postdata = json.dumps({'version': '1.1', 'method': self._service_name, 'params': args, - 'id': AuthServiceProxy.__id_count}, default=EncodeDecimal) - response = self._request('POST', self.__url.path, postdata) + 'id': AuthServiceProxy.__id_count}, default=EncodeDecimal, ensure_ascii=self.ensure_ascii) + response = self._request('POST', self.__url.path, postdata.encode('utf-8')) if response['error'] is not None: raise JSONRPCException(response['error']) elif 'result' not in response: @@ -149,9 +151,9 @@ def __call__(self, *args): return response['result'] def _batch(self, rpc_call_list): - postdata = json.dumps(list(rpc_call_list), default=EncodeDecimal) + postdata = json.dumps(list(rpc_call_list), default=EncodeDecimal, ensure_ascii=self.ensure_ascii) log.debug("--> "+postdata) - return self._request('POST', self.__url.path, postdata) + return self._request('POST', self.__url.path, postdata.encode('utf-8')) def _get_response(self): http_response = self.__conn.getresponse() @@ -167,7 +169,7 @@ def _get_response(self): responsedata = http_response.read().decode('utf8') response = json.loads(responsedata, parse_float=decimal.Decimal) if "error" in response and response["error"] is None: - log.debug("<-%s- %s"%(response["id"], json.dumps(response["result"], default=EncodeDecimal))) + log.debug("<-%s- %s"%(response["id"], json.dumps(response["result"], default=EncodeDecimal, ensure_ascii=self.ensure_ascii))) else: log.debug("<-- "+responsedata) return response From 6bbb4ef39989ff75167da48faec581b55ba51240 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 28 Apr 2016 15:18:01 +0200 Subject: [PATCH 0460/1802] test: test utf-8 for labels in wallet --- qa/rpc-tests/wallet.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py index 9dda712f4ff08..ba84f0d5686dc 100755 --- a/qa/rpc-tests/wallet.py +++ b/qa/rpc-tests/wallet.py @@ -314,6 +314,20 @@ def run_test (self): balance_nodes = [self.nodes[i].getbalance() for i in range(3)] block_count = self.nodes[0].getblockcount() + # Check modes: + # - True: unicode escaped as \u.... + # - False: unicode directly as UTF-8 + for mode in [True, False]: + self.nodes[0].ensure_ascii = mode + # unicode check: Basic Multilingual Plane, Supplementary Plane respectively + for s in [u'рыба', u'𝅘𝅥𝅯']: + addr = self.nodes[0].getaccountaddress(s) + label = self.nodes[0].getaccount(addr) + assert_equal(label, s) + assert(s in self.nodes[0].listaccounts().keys()) + self.nodes[0].ensure_ascii = True # restore to default + + # maintenance tests maintenance = [ '-rescan', '-reindex', From 7982fce64c61c53d1e2e8cc6a8724f878701796d Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sat, 16 Apr 2016 15:21:47 +0200 Subject: [PATCH 0461/1802] doc: Mention full UTF-8 support in release notes --- doc/release-notes.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/release-notes.md b/doc/release-notes.md index 7d44b8cda934c..0d457714d5856 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -43,6 +43,11 @@ RPC low-level changes 32-bit and 64-bit platforms, and the txids were missing in the hashed data. This has been fixed, but this means that the output will be different than from previous versions. +- Full UTF-8 support in the RPC API. Non-ASCII characters in, for example, + wallet labels have always been malformed because they weren't taken into account + properly in JSON RPC processing. This is no longer the case. This also affects + the GUI debug console. + C++11 and Python 3 ------------------- From 657fc19d6535b33748dafcf63cc0248c6fa0ee7a Mon Sep 17 00:00:00 2001 From: instagibbs Date: Fri, 10 Jun 2016 10:09:06 -0400 Subject: [PATCH 0462/1802] rename mapAddrCount to mapNetGroupNodes --- src/net.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 173eba57c8669..c29dc3032a3fd 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -911,11 +911,11 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) { uint64_t naMostConnections; unsigned int nMostConnections = 0; int64_t nMostConnectionsTime = 0; - std::map > mapAddrCounts; + std::map > mapNetGroupNodes; BOOST_FOREACH(const NodeEvictionCandidate &node, vEvictionCandidates) { - mapAddrCounts[node.nKeyedNetGroup].push_back(node); - int64_t grouptime = mapAddrCounts[node.nKeyedNetGroup][0].nTimeConnected; - size_t groupsize = mapAddrCounts[node.nKeyedNetGroup].size(); + mapNetGroupNodes[node.nKeyedNetGroup].push_back(node); + int64_t grouptime = mapNetGroupNodes[node.nKeyedNetGroup][0].nTimeConnected; + size_t groupsize = mapNetGroupNodes[node.nKeyedNetGroup].size(); if (groupsize > nMostConnections || (groupsize == nMostConnections && grouptime > nMostConnectionsTime)) { nMostConnections = groupsize; @@ -925,7 +925,7 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) { } // Reduce to the network group with the most connections - vEvictionCandidates = std::move(mapAddrCounts[naMostConnections]); + vEvictionCandidates = std::move(mapNetGroupNodes[naMostConnections]); // Do not disconnect peers if there is only one unprotected connection from their network group. // This step excessively favors netgroup diversity, and should be removed once more protective criteria are established. From 1b0bcc5f9573406bff1c3ffaf73826b0142d23cc Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 10 Jun 2016 16:07:14 +0200 Subject: [PATCH 0463/1802] Track orphan by prev COutPoint rather than prev hash --- src/main.cpp | 58 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 6d006e8789db1..17867c869cd5b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -88,12 +88,21 @@ CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE; CTxMemPool mempool(::minRelayTxFee); FeeFilterRounder filterRounder(::minRelayTxFee); +struct IteratorComparator +{ + template + bool operator()(const I& a, const I& b) + { + return &(*a) < &(*b); + } +}; + struct COrphanTx { CTransaction tx; NodeId fromPeer; }; map mapOrphanTransactions GUARDED_BY(cs_main); -map > mapOrphanTransactionsByPrev GUARDED_BY(cs_main); +map::iterator, IteratorComparator>> mapOrphanTransactionsByPrev GUARDED_BY(cs_main); void EraseOrphansFor(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main); /** @@ -632,31 +641,33 @@ bool AddOrphanTx(const CTransaction& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(c return false; } - mapOrphanTransactions[hash].tx = tx; - mapOrphanTransactions[hash].fromPeer = peer; - BOOST_FOREACH(const CTxIn& txin, tx.vin) - mapOrphanTransactionsByPrev[txin.prevout.hash].insert(hash); + auto ret = mapOrphanTransactions.emplace(hash, COrphanTx{tx, peer}); + assert(ret.second); + BOOST_FOREACH(const CTxIn& txin, tx.vin) { + mapOrphanTransactionsByPrev[txin.prevout].insert(ret.first); + } - LogPrint("mempool", "stored orphan tx %s (mapsz %u prevsz %u)\n", hash.ToString(), + LogPrint("mempool", "stored orphan tx %s (mapsz %u outsz %u)\n", hash.ToString(), mapOrphanTransactions.size(), mapOrphanTransactionsByPrev.size()); return true; } -void static EraseOrphanTx(uint256 hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) +int static EraseOrphanTx(uint256 hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { map::iterator it = mapOrphanTransactions.find(hash); if (it == mapOrphanTransactions.end()) - return; + return 0; BOOST_FOREACH(const CTxIn& txin, it->second.tx.vin) { - map >::iterator itPrev = mapOrphanTransactionsByPrev.find(txin.prevout.hash); + auto itPrev = mapOrphanTransactionsByPrev.find(txin.prevout); if (itPrev == mapOrphanTransactionsByPrev.end()) continue; - itPrev->second.erase(hash); + itPrev->second.erase(it); if (itPrev->second.empty()) mapOrphanTransactionsByPrev.erase(itPrev); } mapOrphanTransactions.erase(it); + return 1; } void EraseOrphansFor(NodeId peer) @@ -668,8 +679,7 @@ void EraseOrphansFor(NodeId peer) map::iterator maybeErase = iter++; // increment to avoid iterator becoming invalid if (maybeErase->second.fromPeer == peer) { - EraseOrphanTx(maybeErase->second.tx.GetHash()); - ++nErased; + nErased += EraseOrphanTx(maybeErase->second.tx.GetHash()); } } if (nErased > 0) LogPrint("mempool", "Erased %d orphan tx from peer %d\n", nErased, peer); @@ -5019,7 +5029,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, return true; } - vector vWorkQueue; + deque vWorkQueue; vector vEraseQueue; CTransaction tx; vRecv >> tx; @@ -5038,7 +5048,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, if (!AlreadyHave(inv) && AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs)) { mempool.check(pcoinsTip); RelayTransaction(tx); - vWorkQueue.push_back(inv.hash); + for (unsigned int i = 0; i < tx.vout.size(); i++) { + vWorkQueue.emplace_back(inv.hash, i); + } LogPrint("mempool", "AcceptToMemoryPool: peer=%d: accepted %s (poolsz %u txn, %u kB)\n", pfrom->id, @@ -5047,18 +5059,18 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // Recursively process any orphan transactions that depended on this one set setMisbehaving; - for (unsigned int i = 0; i < vWorkQueue.size(); i++) - { - map >::iterator itByPrev = mapOrphanTransactionsByPrev.find(vWorkQueue[i]); + while (!vWorkQueue.empty()) { + auto itByPrev = mapOrphanTransactionsByPrev.find(vWorkQueue.front()); + vWorkQueue.pop_front(); if (itByPrev == mapOrphanTransactionsByPrev.end()) continue; - for (set::iterator mi = itByPrev->second.begin(); + for (auto mi = itByPrev->second.begin(); mi != itByPrev->second.end(); ++mi) { - const uint256& orphanHash = *mi; - const CTransaction& orphanTx = mapOrphanTransactions[orphanHash].tx; - NodeId fromPeer = mapOrphanTransactions[orphanHash].fromPeer; + const CTransaction& orphanTx = (*mi)->second.tx; + const uint256& orphanHash = orphanTx.GetHash(); + NodeId fromPeer = (*mi)->second.fromPeer; bool fMissingInputs2 = false; // Use a dummy CValidationState so someone can't setup nodes to counter-DoS based on orphan // resolution (that is, feeding people an invalid transaction based on LegitTxX in order to get @@ -5071,7 +5083,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, if (AcceptToMemoryPool(mempool, stateDummy, orphanTx, true, &fMissingInputs2)) { LogPrint("mempool", " accepted orphan tx %s\n", orphanHash.ToString()); RelayTransaction(orphanTx); - vWorkQueue.push_back(orphanHash); + for (unsigned int i = 0; i < orphanTx.vout.size(); i++) { + vWorkQueue.emplace_back(orphanHash, i); + } vEraseQueue.push_back(orphanHash); } else if (!fMissingInputs2) From db0ffe80a0919653f058ab0f1fc735f46bb902f3 Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Fri, 10 Jun 2016 20:41:49 +0000 Subject: [PATCH 0464/1802] This eliminates the primary leak that causes the orphan map to always grow to its maximum size. This does not go so far as to attempt to connect orphans made connectable by a new block. Keeping the orphan map less full helps improve the reliability of relaying chains of transactions. --- src/main.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 17867c869cd5b..c80a4ac922c83 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2345,6 +2345,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin CCheckQueueControl control(fScriptChecks && nScriptCheckThreads ? &scriptcheckqueue : NULL); + std::vector vOrphanErase; std::vector prevheights; CAmount nFees = 0; int nInputs = 0; @@ -2377,6 +2378,17 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin prevheights[j] = view.AccessCoins(tx.vin[j].prevout.hash)->nHeight; } + // Which orphan pool entries must we evict? + for (size_t j = 0; j < tx.vin.size(); j++) { + auto itByPrev = mapOrphanTransactionsByPrev.find(tx.vin[j].prevout); + if (itByPrev == mapOrphanTransactionsByPrev.end()) continue; + for (auto mi = itByPrev->second.begin(); mi != itByPrev->second.end(); ++mi) { + const CTransaction& orphanTx = (*mi)->second.tx; + const uint256& orphanHash = orphanTx.GetHash(); + vOrphanErase.push_back(orphanHash); + } + } + if (!SequenceLocks(tx, nLockTimeFlags, &prevheights, *pindex)) { return state.DoS(100, error("%s: contains a non-BIP68-final transaction", __func__), REJECT_INVALID, "bad-txns-nonfinal"); @@ -2464,6 +2476,15 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin GetMainSignals().UpdatedTransaction(hashPrevBestCoinBase); hashPrevBestCoinBase = block.vtx[0].GetHash(); + // Erase orphan transactions include or precluded by this block + if (vOrphanErase.size()) { + int nErased = 0; + BOOST_FOREACH(uint256 &orphanHash, vOrphanErase) { + nErased += EraseOrphanTx(orphanHash); + } + LogPrint("mempool", "Erased %d orphan tx included or conflicted by block\n", nErased); + } + int64_t nTime6 = GetTimeMicros(); nTimeCallbacks += nTime6 - nTime5; LogPrint("bench", " - Callbacks: %.2fms [%.2fs]\n", 0.001 * (nTime6 - nTime5), nTimeCallbacks * 0.000001); From fa61756842d78beeac8e7cffa88767fa3f710510 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 12 Jun 2016 14:10:55 +0200 Subject: [PATCH 0465/1802] [gitian] set correct PATH for wrappers --- contrib/gitian-descriptors/gitian-linux.yml | 6 ++++-- contrib/gitian-descriptors/gitian-osx.yml | 6 ++++-- contrib/gitian-descriptors/gitian-win.yml | 6 ++++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index cd289b2f6e4c8..28b7e6d351847 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -68,11 +68,11 @@ script: | done } - export PATH=${WRAP_DIR}:${PATH} - # Faketime for depends so intermediate results are comparable + export PATH_orig=${PATH} create_global_faketime_wrappers "2000-01-01 12:00:00" create_per-host_faketime_wrappers "2000-01-01 12:00:00" + export PATH=${WRAP_DIR}:${PATH} cd bitcoin BASEPREFIX=`pwd`/depends @@ -82,8 +82,10 @@ script: | done # Faketime for binaries + export PATH=${PATH_orig} create_global_faketime_wrappers "${REFERENCE_DATETIME}" create_per-host_faketime_wrappers "${REFERENCE_DATETIME}" + export PATH=${WRAP_DIR}:${PATH} # Create the release tarball using (arbitrarily) the first host ./autogen.sh diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml index 8436cd612a57d..536fcfb105d53 100644 --- a/contrib/gitian-descriptors/gitian-osx.yml +++ b/contrib/gitian-descriptors/gitian-osx.yml @@ -77,11 +77,11 @@ script: | done } - export PATH=${WRAP_DIR}:${PATH} - # Faketime for depends so intermediate results are comparable + export PATH_orig=${PATH} create_global_faketime_wrappers "2000-01-01 12:00:00" create_per-host_faketime_wrappers "2000-01-01 12:00:00" + export PATH=${WRAP_DIR}:${PATH} cd bitcoin BASEPREFIX=`pwd`/depends @@ -95,8 +95,10 @@ script: | done # Faketime for binaries + export PATH=${PATH_orig} create_global_faketime_wrappers "${REFERENCE_DATETIME}" create_per-host_faketime_wrappers "${REFERENCE_DATETIME}" + export PATH=${WRAP_DIR}:${PATH} # Create the release tarball using (arbitrarily) the first host ./autogen.sh diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml index 1d3a876dfb559..32b57b3160bd3 100644 --- a/contrib/gitian-descriptors/gitian-win.yml +++ b/contrib/gitian-descriptors/gitian-win.yml @@ -94,12 +94,12 @@ script: | done } - export PATH=${WRAP_DIR}:${PATH} - # Faketime for depends so intermediate results are comparable + export PATH_orig=${PATH} create_global_faketime_wrappers "2000-01-01 12:00:00" create_per-host_faketime_wrappers "2000-01-01 12:00:00" create_per-host_linker_wrapper "2000-01-01 12:00:00" + export PATH=${WRAP_DIR}:${PATH} cd bitcoin BASEPREFIX=`pwd`/depends @@ -109,9 +109,11 @@ script: | done # Faketime for binaries + export PATH=${PATH_orig} create_global_faketime_wrappers "${REFERENCE_DATETIME}" create_per-host_faketime_wrappers "${REFERENCE_DATETIME}" create_per-host_linker_wrapper "${REFERENCE_DATETIME}" + export PATH=${WRAP_DIR}:${PATH} # Create the release tarball using (arbitrarily) the first host ./autogen.sh From b0938a00203a32cd932c78bc2782d113d2d78f06 Mon Sep 17 00:00:00 2001 From: fanquake Date: Sun, 12 Jun 2016 20:33:20 +0800 Subject: [PATCH 0466/1802] [trivial][doc] Use Debian 8.5 in the gitian-build guide --- doc/gitian-building.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/gitian-building.md b/doc/gitian-building.md index 791f209bb1373..7796a5fc9c151 100644 --- a/doc/gitian-building.md +++ b/doc/gitian-building.md @@ -1,7 +1,7 @@ Gitian building ================ -*Setup instructions for a Gitian build of Bitcoin using a Debian VM or physical system.* +*Setup instructions for a Gitian build of Bitcoin Core using a Debian VM or physical system.* Gitian is the deterministic build process that is used to build the Bitcoin Core executables. It provides a way to be reasonably sure that the @@ -26,7 +26,7 @@ Table of Contents - [Installing Gitian](#installing-gitian) - [Setting up the Gitian image](#setting-up-the-gitian-image) - [Getting and building the inputs](#getting-and-building-the-inputs) -- [Building Bitcoin](#building-bitcoin) +- [Building Bitcoin Core](#building-bitcoin-core) - [Building an alternative repository](#building-an-alternative-repository) - [Signing externally](#signing-externally) - [Uploading signatures](#uploading-signatures) @@ -95,11 +95,11 @@ After creating the VM, we need to configure it. - Click `Ok` twice to save. -Get the [Debian 8.x net installer](http://cdimage.debian.org/debian-cd/8.4.0/amd64/iso-cd/debian-8.4.0-amd64-netinst.iso) (a more recent minor version should also work, see also [Debian Network installation](https://www.debian.org/CD/netinst/)). +Get the [Debian 8.x net installer](http://cdimage.debian.org/debian-cd/8.5.0/amd64/iso-cd/debian-8.5.0-amd64-netinst.iso) (a more recent minor version should also work, see also [Debian Network installation](https://www.debian.org/CD/netinst/)). This DVD image can be validated using a SHA256 hashing tool, for example on Unixy OSes by entering the following in a terminal: - echo "7a6b418e6a4ee3ca75dda04d79ed96c9e2c33bb0c703ca7e40c6374ab4590748 debian-8.4.0-amd64-netinst.iso" | sha256sum -c + echo "ad4e8c27c561ad8248d5ebc1d36eb172f884057bfeb2c22ead823f59fa8c3dff debian-8.5.0-amd64-netinst.iso" | sha256sum -c # (must return OK) Then start the VM. On the first launch you will be asked for a CD or DVD image. Choose the downloaded iso. @@ -342,10 +342,10 @@ manual intervention. Also optionally follow the next step: 'Seed the Gitian sour and offline git repositories' which will fetch the remaining files required for building offline. -Building Bitcoin +Building Bitcoin Core ---------------- -To build Bitcoin (for Linux, OS X and Windows) just follow the steps under 'perform +To build Bitcoin Core (for Linux, OS X and Windows) just follow the steps under 'perform Gitian builds' in [doc/release-process.md](release-process.md#perform-gitian-builds) in the bitcoin repository. This may take some time as it will build all the dependencies needed for each descriptor. From 01a99046de63dac4dbf1ddce9fc711ff1f05049a Mon Sep 17 00:00:00 2001 From: fanquake Date: Mon, 13 Jun 2016 19:28:39 +0800 Subject: [PATCH 0467/1802] [trivial] Ignore split-debug.sh --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index a8722aa593ac3..ce40019dc314f 100644 --- a/.gitignore +++ b/.gitignore @@ -114,3 +114,4 @@ share/BitcoindComparisonTool.jar /doc/doxygen/ libbitcoinconsensus.pc +contrib/devtools/split-debug.sh From 0e209f9bf940ec2f6215885cf30deaa7355086e9 Mon Sep 17 00:00:00 2001 From: fanquake Date: Mon, 13 Jun 2016 19:33:02 +0800 Subject: [PATCH 0468/1802] [trivial] Sync ax_pthread with upstream draft --- build-aux/m4/ax_pthread.m4 | 550 ++++++++++++++++++------------------- 1 file changed, 275 insertions(+), 275 deletions(-) diff --git a/build-aux/m4/ax_pthread.m4 b/build-aux/m4/ax_pthread.m4 index d218d1af73817..4c4051ea376f7 100644 --- a/build-aux/m4/ax_pthread.m4 +++ b/build-aux/m4/ax_pthread.m4 @@ -82,7 +82,7 @@ # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. -#serial 22 +#serial 23 AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) AC_DEFUN([AX_PTHREAD], [ @@ -100,22 +100,22 @@ ax_pthread_ok=no # etcetera environment variables, and if threads linking works using # them: if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then - ax_pthread_save_CC="$CC" - ax_pthread_save_CFLAGS="$CFLAGS" - ax_pthread_save_LIBS="$LIBS" - AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"]) - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - LIBS="$PTHREAD_LIBS $LIBS" - AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS]) - AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes]) - AC_MSG_RESULT([$ax_pthread_ok]) - if test "x$ax_pthread_ok" = "xno"; then - PTHREAD_LIBS="" - PTHREAD_CFLAGS="" - fi - CC="$ax_pthread_save_CC" - CFLAGS="$ax_pthread_save_CFLAGS" - LIBS="$ax_pthread_save_LIBS" + ax_pthread_save_CC="$CC" + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"]) + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS]) + AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes]) + AC_MSG_RESULT([$ax_pthread_ok]) + if test "x$ax_pthread_ok" = "xno"; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + CC="$ax_pthread_save_CC" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" fi # We must check for the threads library under a number of different @@ -152,50 +152,50 @@ ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread -- case $host_os in - freebsd*) + freebsd*) - # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) - # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) + # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) + # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) - ax_pthread_flags="-kthread lthread $ax_pthread_flags" - ;; + ax_pthread_flags="-kthread lthread $ax_pthread_flags" + ;; - hpux*) + hpux*) - # From the cc(1) man page: "[-mt] Sets various -D flags to enable - # multi-threading and also sets -lpthread." + # From the cc(1) man page: "[-mt] Sets various -D flags to enable + # multi-threading and also sets -lpthread." - ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" - ;; + ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" + ;; - openedition*) + openedition*) - # IBM z/OS requires a feature-test macro to be defined in order to - # enable POSIX threads at all, so give the user a hint if this is - # not set. (We don't define these ourselves, as they can affect - # other portions of the system API in unpredictable ways.) + # IBM z/OS requires a feature-test macro to be defined in order to + # enable POSIX threads at all, so give the user a hint if this is + # not set. (We don't define these ourselves, as they can affect + # other portions of the system API in unpredictable ways.) - AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING], - [ -# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) - AX_PTHREAD_ZOS_MISSING -# endif - ], - [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])]) - ;; + AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING], + [ +# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) + AX_PTHREAD_ZOS_MISSING +# endif + ], + [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])]) + ;; - solaris*) + solaris*) - # On Solaris (at least, for some versions), libc contains stubbed - # (non-functional) versions of the pthreads routines, so link-based - # tests will erroneously succeed. (N.B.: The stubs are missing - # pthread_cleanup_push, or rather a function called by this macro, - # so we could check for that, but who knows whether they'll stub - # that too in a future libc.) So we'll check first for the - # standard Solaris way of linking pthreads (-mt -lpthread). + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (N.B.: The stubs are missing + # pthread_cleanup_push, or rather a function called by this macro, + # so we could check for that, but who knows whether they'll stub + # that too in a future libc.) So we'll check first for the + # standard Solaris way of linking pthreads (-mt -lpthread). - ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags" - ;; + ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags" + ;; esac # GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) @@ -208,17 +208,17 @@ AS_IF([test "x$GCC" = "xyes"], # correctly enabled case $host_os in - darwin* | hpux* | linux* | osf* | solaris*) - ax_pthread_check_macro="_REENTRANT" - ;; + darwin* | hpux* | linux* | osf* | solaris*) + ax_pthread_check_macro="_REENTRANT" + ;; - aix* | freebsd*) - ax_pthread_check_macro="_THREAD_SAFE" - ;; + aix*) + ax_pthread_check_macro="_THREAD_SAFE" + ;; - *) - ax_pthread_check_macro="--" - ;; + *) + ax_pthread_check_macro="--" + ;; esac AS_IF([test "x$ax_pthread_check_macro" = "x--"], [ax_pthread_check_cond=0], @@ -231,13 +231,13 @@ AC_CACHE_CHECK([whether $CC is Clang], [ax_cv_PTHREAD_CLANG=no # Note that Autoconf sets GCC=yes for Clang as well as GCC if test "x$GCC" = "xyes"; then - AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG], - [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ -# if defined(__clang__) && defined(__llvm__) - AX_PTHREAD_CC_IS_CLANG -# endif - ], - [ax_cv_PTHREAD_CLANG=yes]) + AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG], + [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ +# if defined(__clang__) && defined(__llvm__) + AX_PTHREAD_CC_IS_CLANG +# endif + ], + [ax_cv_PTHREAD_CLANG=yes]) fi ]) ax_pthread_clang="$ax_cv_PTHREAD_CLANG" @@ -249,222 +249,222 @@ ax_pthread_clang_warning=no if test "x$ax_pthread_clang" = "xyes"; then - # Clang takes -pthread; it has never supported any other flag - - # (Note 1: This will need to be revisited if a system that Clang - # supports has POSIX threads in a separate library. This tends not - # to be the way of modern systems, but it's conceivable.) - - # (Note 2: On some systems, notably Darwin, -pthread is not needed - # to get POSIX threads support; the API is always present and - # active. We could reasonably leave PTHREAD_CFLAGS empty. But - # -pthread does define _REENTRANT, and while the Darwin headers - # ignore this macro, third-party headers might not.) - - PTHREAD_CFLAGS="-pthread" - PTHREAD_LIBS= - - ax_pthread_ok=yes - - # However, older versions of Clang make a point of warning the user - # that, in an invocation where only linking and no compilation is - # taking place, the -pthread option has no effect ("argument unused - # during compilation"). They expect -pthread to be passed in only - # when source code is being compiled. - # - # Problem is, this is at odds with the way Automake and most other - # C build frameworks function, which is that the same flags used in - # compilation (CFLAGS) are also used in linking. Many systems - # supported by AX_PTHREAD require exactly this for POSIX threads - # support, and in fact it is often not straightforward to specify a - # flag that is used only in the compilation phase and not in - # linking. Such a scenario is extremely rare in practice. - # - # Even though use of the -pthread flag in linking would only print - # a warning, this can be a nuisance for well-run software projects - # that build with -Werror. So if the active version of Clang has - # this misfeature, we search for an option to squash it. - - AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread], - [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG], - [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown - # Create an alternate version of $ac_link that compiles and - # links in two steps (.c -> .o, .o -> exe) instead of one - # (.c -> exe), because the warning occurs only in the second - # step - ax_pthread_save_ac_link="$ac_link" - ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' - ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` - ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" - ax_pthread_save_CFLAGS="$CFLAGS" - for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do - AS_IF([test "x$ax_pthread_try" = "xunknown"], [break]) - CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" - ac_link="$ax_pthread_save_ac_link" - AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], - [ac_link="$ax_pthread_2step_ac_link" - AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], - [break]) - ]) - done - ac_link="$ax_pthread_save_ac_link" - CFLAGS="$ax_pthread_save_CFLAGS" - AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no]) - ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" - ]) - - case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in - no | unknown) ;; - *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; - esac + # Clang takes -pthread; it has never supported any other flag + + # (Note 1: This will need to be revisited if a system that Clang + # supports has POSIX threads in a separate library. This tends not + # to be the way of modern systems, but it's conceivable.) + + # (Note 2: On some systems, notably Darwin, -pthread is not needed + # to get POSIX threads support; the API is always present and + # active. We could reasonably leave PTHREAD_CFLAGS empty. But + # -pthread does define _REENTRANT, and while the Darwin headers + # ignore this macro, third-party headers might not.) + + PTHREAD_CFLAGS="-pthread" + PTHREAD_LIBS= + + ax_pthread_ok=yes + + # However, older versions of Clang make a point of warning the user + # that, in an invocation where only linking and no compilation is + # taking place, the -pthread option has no effect ("argument unused + # during compilation"). They expect -pthread to be passed in only + # when source code is being compiled. + # + # Problem is, this is at odds with the way Automake and most other + # C build frameworks function, which is that the same flags used in + # compilation (CFLAGS) are also used in linking. Many systems + # supported by AX_PTHREAD require exactly this for POSIX threads + # support, and in fact it is often not straightforward to specify a + # flag that is used only in the compilation phase and not in + # linking. Such a scenario is extremely rare in practice. + # + # Even though use of the -pthread flag in linking would only print + # a warning, this can be a nuisance for well-run software projects + # that build with -Werror. So if the active version of Clang has + # this misfeature, we search for an option to squash it. + + AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread], + [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG], + [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown + # Create an alternate version of $ac_link that compiles and + # links in two steps (.c -> .o, .o -> exe) instead of one + # (.c -> exe), because the warning occurs only in the second + # step + ax_pthread_save_ac_link="$ac_link" + ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' + ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` + ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" + ax_pthread_save_CFLAGS="$CFLAGS" + for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do + AS_IF([test "x$ax_pthread_try" = "xunknown"], [break]) + CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" + ac_link="$ax_pthread_save_ac_link" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], + [ac_link="$ax_pthread_2step_ac_link" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], + [break]) + ]) + done + ac_link="$ax_pthread_save_ac_link" + CFLAGS="$ax_pthread_save_CFLAGS" + AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no]) + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" + ]) + + case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in + no | unknown) ;; + *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; + esac fi # $ax_pthread_clang = yes if test "x$ax_pthread_ok" = "xno"; then for ax_pthread_try_flag in $ax_pthread_flags; do - case $ax_pthread_try_flag in - none) - AC_MSG_CHECKING([whether pthreads work without any flags]) - ;; - - -mt,pthread) - AC_MSG_CHECKING([whether pthreads work with -mt -lpthread]) - PTHREAD_CFLAGS="-mt" - PTHREAD_LIBS="-lpthread" - ;; - - -*) - AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag]) - PTHREAD_CFLAGS="$ax_pthread_try_flag" - ;; - - pthread-config) - AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) - AS_IF([test "x$ax_pthread_config" = "xno"], [continue]) - PTHREAD_CFLAGS="`pthread-config --cflags`" - PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" - ;; - - *) - AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag]) - PTHREAD_LIBS="-l$ax_pthread_try_flag" - ;; - esac - - ax_pthread_save_CFLAGS="$CFLAGS" - ax_pthread_save_LIBS="$LIBS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - LIBS="$PTHREAD_LIBS $LIBS" - - # Check for various functions. We must include pthread.h, - # since some functions may be macros. (On the Sequent, we - # need a special flag -Kthread to make this header compile.) - # We check for pthread_join because it is in -lpthread on IRIX - # while pthread_create is in libc. We check for pthread_attr_init - # due to DEC craziness with -lpthreads. We check for - # pthread_cleanup_push because it is one of the few pthread - # functions on Solaris that doesn't have a non-functional libc stub. - # We try pthread_create on general principles. - - AC_LINK_IFELSE([AC_LANG_PROGRAM([#include -# if $ax_pthread_check_cond -# error "$ax_pthread_check_macro must be defined" -# endif - static void routine(void *a) { a = 0; } - static void *start_routine(void *a) { return a; }], - [pthread_t th; pthread_attr_t attr; - pthread_create(&th, 0, start_routine, 0); - pthread_join(th, 0); - pthread_attr_init(&attr); - pthread_cleanup_push(routine, 0); - pthread_cleanup_pop(0) /* ; */])], - [ax_pthread_ok=yes], - []) - - CFLAGS="$ax_pthread_save_CFLAGS" - LIBS="$ax_pthread_save_LIBS" - - AC_MSG_RESULT([$ax_pthread_ok]) - AS_IF([test "x$ax_pthread_ok" = "xyes"], [break]) - - PTHREAD_LIBS="" - PTHREAD_CFLAGS="" + case $ax_pthread_try_flag in + none) + AC_MSG_CHECKING([whether pthreads work without any flags]) + ;; + + -mt,pthread) + AC_MSG_CHECKING([whether pthreads work with -mt -lpthread]) + PTHREAD_CFLAGS="-mt" + PTHREAD_LIBS="-lpthread" + ;; + + -*) + AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag]) + PTHREAD_CFLAGS="$ax_pthread_try_flag" + ;; + + pthread-config) + AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) + AS_IF([test "x$ax_pthread_config" = "xno"], [continue]) + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag]) + PTHREAD_LIBS="-l$ax_pthread_try_flag" + ;; + esac + + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include +# if $ax_pthread_check_cond +# error "$ax_pthread_check_macro must be defined" +# endif + static void routine(void *a) { a = 0; } + static void *start_routine(void *a) { return a; }], + [pthread_t th; pthread_attr_t attr; + pthread_create(&th, 0, start_routine, 0); + pthread_join(th, 0); + pthread_attr_init(&attr); + pthread_cleanup_push(routine, 0); + pthread_cleanup_pop(0) /* ; */])], + [ax_pthread_ok=yes], + []) + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + AC_MSG_RESULT([$ax_pthread_ok]) + AS_IF([test "x$ax_pthread_ok" = "xyes"], [break]) + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$ax_pthread_ok" = "xyes"; then - ax_pthread_save_CFLAGS="$CFLAGS" - ax_pthread_save_LIBS="$LIBS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - LIBS="$PTHREAD_LIBS $LIBS" - - # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. - AC_CACHE_CHECK([for joinable pthread attribute], - [ax_cv_PTHREAD_JOINABLE_ATTR], - [ax_cv_PTHREAD_JOINABLE_ATTR=unknown - for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do - AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], - [int attr = $ax_pthread_attr; return attr /* ; */])], - [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break], - []) - done - ]) - AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ - test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ - test "x$ax_pthread_joinable_attr_defined" != "xyes"], - [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], - [$ax_cv_PTHREAD_JOINABLE_ATTR], - [Define to necessary symbol if this constant - uses a non-standard name on your system.]) - ax_pthread_joinable_attr_defined=yes - ]) - - AC_CACHE_CHECK([whether more special flags are required for pthreads], - [ax_cv_PTHREAD_SPECIAL_FLAGS], - [ax_cv_PTHREAD_SPECIAL_FLAGS=no - case $host_os in - solaris*) - ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" - ;; - esac - ]) - AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ - test "x$ax_pthread_special_flags_added" != "xyes"], - [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" - ax_pthread_special_flags_added=yes]) - - AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], - [ax_cv_PTHREAD_PRIO_INHERIT], - [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], - [[int i = PTHREAD_PRIO_INHERIT;]])], - [ax_cv_PTHREAD_PRIO_INHERIT=yes], - [ax_cv_PTHREAD_PRIO_INHERIT=no]) - ]) - AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ - test "x$ax_pthread_prio_inherit_defined" != "xyes"], - [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.]) - ax_pthread_prio_inherit_defined=yes - ]) - - CFLAGS="$ax_pthread_save_CFLAGS" - LIBS="$ax_pthread_save_LIBS" - - # More AIX lossage: compile with *_r variant - if test "x$GCC" != "xyes"; then - case $host_os in - aix*) - AS_CASE(["x/$CC"], - [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], - [#handle absolute path differently from PATH based program lookup - AS_CASE(["x$CC"], - [x/*], - [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], - [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) - ;; - esac - fi + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + AC_CACHE_CHECK([for joinable pthread attribute], + [ax_cv_PTHREAD_JOINABLE_ATTR], + [ax_cv_PTHREAD_JOINABLE_ATTR=unknown + for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], + [int attr = $ax_pthread_attr; return attr /* ; */])], + [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break], + []) + done + ]) + AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ + test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ + test "x$ax_pthread_joinable_attr_defined" != "xyes"], + [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], + [$ax_cv_PTHREAD_JOINABLE_ATTR], + [Define to necessary symbol if this constant + uses a non-standard name on your system.]) + ax_pthread_joinable_attr_defined=yes + ]) + + AC_CACHE_CHECK([whether more special flags are required for pthreads], + [ax_cv_PTHREAD_SPECIAL_FLAGS], + [ax_cv_PTHREAD_SPECIAL_FLAGS=no + case $host_os in + solaris*) + ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" + ;; + esac + ]) + AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ + test "x$ax_pthread_special_flags_added" != "xyes"], + [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" + ax_pthread_special_flags_added=yes]) + + AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], + [ax_cv_PTHREAD_PRIO_INHERIT], + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[int i = PTHREAD_PRIO_INHERIT;]])], + [ax_cv_PTHREAD_PRIO_INHERIT=yes], + [ax_cv_PTHREAD_PRIO_INHERIT=no]) + ]) + AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ + test "x$ax_pthread_prio_inherit_defined" != "xyes"], + [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.]) + ax_pthread_prio_inherit_defined=yes + ]) + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + # More AIX lossage: compile with *_r variant + if test "x$GCC" != "xyes"; then + case $host_os in + aix*) + AS_CASE(["x/$CC"], + [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], + [#handle absolute path differently from PATH based program lookup + AS_CASE(["x$CC"], + [x/*], + [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], + [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) + ;; + esac + fi fi test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" @@ -475,11 +475,11 @@ AC_SUBST([PTHREAD_CC]) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test "x$ax_pthread_ok" = "xyes"; then - ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) - : + ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) + : else - ax_pthread_ok=no - $2 + ax_pthread_ok=no + $2 fi AC_LANG_POP ])dnl AX_PTHREAD From 1c2a1bac0ad6901868c1a4003c7cbddcdf46a29b Mon Sep 17 00:00:00 2001 From: Francesco 'makevoid' Canessa Date: Thu, 3 Mar 2016 10:54:31 +0000 Subject: [PATCH 0469/1802] Add address label to request payment QR Code (QT) In the Receive 'Tab' of the QT wallet, when 'Show'ing a previously requested payment, add a label underneath the QR Code showing the bitcoin address where the funds will go to. This way the user can be sure that the QR code scanner app the user using is reading the correct bitcoin address, preventing funds to be stolen. Includes fix for HiDPI screens by @jonasschnelli. --- src/qt/forms/receiverequestdialog.ui | 2 +- src/qt/guiconstants.h | 2 +- src/qt/receiverequestdialog.cpp | 22 +++++++++++++++++----- src/qt/receiverequestdialog.h | 1 + 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/qt/forms/receiverequestdialog.ui b/src/qt/forms/receiverequestdialog.ui index 1e484dd9a0f59..4163f4189c5e9 100644 --- a/src/qt/forms/receiverequestdialog.ui +++ b/src/qt/forms/receiverequestdialog.ui @@ -22,7 +22,7 @@ 300 - 300 + 320 diff --git a/src/qt/guiconstants.h b/src/qt/guiconstants.h index 4b2c10dd48e43..bab9923d20d49 100644 --- a/src/qt/guiconstants.h +++ b/src/qt/guiconstants.h @@ -43,7 +43,7 @@ static const int TOOLTIP_WRAP_THRESHOLD = 80; static const int MAX_URI_LENGTH = 255; /* QRCodeDialog -- size of exported QR Code image */ -#define EXPORT_IMAGE_SIZE 256 +#define QR_IMAGE_SIZE 300 /* Number of frames in spinner animation */ #define SPINNER_FRAMES 36 diff --git a/src/qt/receiverequestdialog.cpp b/src/qt/receiverequestdialog.cpp index a1e9156eeae4e..b13ea3df709bb 100644 --- a/src/qt/receiverequestdialog.cpp +++ b/src/qt/receiverequestdialog.cpp @@ -45,7 +45,7 @@ QImage QRImageWidget::exportImage() { if(!pixmap()) return QImage(); - return pixmap()->toImage().scaled(EXPORT_IMAGE_SIZE, EXPORT_IMAGE_SIZE); + return pixmap()->toImage(); } void QRImageWidget::mousePressEvent(QMouseEvent *event) @@ -166,20 +166,32 @@ void ReceiveRequestDialog::update() ui->lblQRCode->setText(tr("Error encoding URI into QR Code.")); return; } - QImage myImage = QImage(code->width + 8, code->width + 8, QImage::Format_RGB32); - myImage.fill(0xffffff); + QImage qrImage = QImage(code->width + 8, code->width + 8, QImage::Format_RGB32); + qrImage.fill(0xffffff); unsigned char *p = code->data; for (int y = 0; y < code->width; y++) { for (int x = 0; x < code->width; x++) { - myImage.setPixel(x + 4, y + 4, ((*p & 1) ? 0x0 : 0xffffff)); + qrImage.setPixel(x + 4, y + 4, ((*p & 1) ? 0x0 : 0xffffff)); p++; } } QRcode_free(code); - ui->lblQRCode->setPixmap(QPixmap::fromImage(myImage).scaled(300, 300)); + QImage qrAddrImage = QImage(QR_IMAGE_SIZE, QR_IMAGE_SIZE+20, QImage::Format_RGB32); + qrAddrImage.fill(0xffffff); + QPainter painter(&qrAddrImage); + painter.drawImage(0, 0, qrImage.scaled(QR_IMAGE_SIZE, QR_IMAGE_SIZE)); + QFont font = GUIUtil::fixedPitchFont(); + font.setPixelSize(12); + painter.setFont(font); + QRect paddedRect = qrAddrImage.rect(); + paddedRect.setHeight(QR_IMAGE_SIZE+12); + painter.drawText(paddedRect, Qt::AlignBottom|Qt::AlignCenter, info.address); + painter.end(); + + ui->lblQRCode->setPixmap(QPixmap::fromImage(qrAddrImage)); ui->btnSaveAs->setEnabled(true); } } diff --git a/src/qt/receiverequestdialog.h b/src/qt/receiverequestdialog.h index 4cab4caff1ace..676745a858f6c 100644 --- a/src/qt/receiverequestdialog.h +++ b/src/qt/receiverequestdialog.h @@ -10,6 +10,7 @@ #include #include #include +#include class OptionsModel; From 3764dec36c815267174951a4c64e17c07ee6302f Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 26 Mar 2016 18:58:00 +0100 Subject: [PATCH 0470/1802] Keep addrman's nService bits consistent with outbound observations --- src/addrman.cpp | 18 ++++++++++++++++++ src/addrman.h | 11 +++++++++++ src/main.cpp | 4 ++++ 3 files changed, 33 insertions(+) diff --git a/src/addrman.cpp b/src/addrman.cpp index 00f6fe99e001c..d1e98d8ac0904 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -502,6 +502,24 @@ void CAddrMan::Connected_(const CService& addr, int64_t nTime) info.nTime = nTime; } +void CAddrMan::SetServices_(const CService& addr, uint64_t nServices) +{ + CAddrInfo* pinfo = Find(addr); + + // if not found, bail out + if (!pinfo) + return; + + CAddrInfo& info = *pinfo; + + // check whether we are talking about the exact same CService (including same port) + if (info != addr) + return; + + // update info + info.nServices = nServices; +} + int CAddrMan::RandomInt(int nMax){ return GetRandInt(nMax); } diff --git a/src/addrman.h b/src/addrman.h index c5923e94171c6..7e36e2228f39e 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -256,6 +256,9 @@ class CAddrMan //! Mark an entry as currently-connected-to. void Connected_(const CService &addr, int64_t nTime); + //! Update an entry's service bits. + void SetServices_(const CService &addr, uint64_t nServices); + public: /** * serialized format: @@ -589,6 +592,14 @@ class CAddrMan } } + void SetServices(const CService &addr, uint64_t nServices) + { + LOCK(cs); + Check(); + SetServices_(addr, nServices); + Check(); + } + }; #endif // BITCOIN_ADDRMAN_H diff --git a/src/main.cpp b/src/main.cpp index 6092e7a12e991..ac89945bf2638 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4612,6 +4612,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, CAddress addrFrom; uint64_t nNonce = 1; vRecv >> pfrom->nVersion >> pfrom->nServices >> nTime >> addrMe; + if (!pfrom->fInbound) + { + addrman.SetServices(pfrom->addr, pfrom->nServices); + } if (pfrom->nVersion < MIN_PEER_PROTO_VERSION) { // disconnect from peers older than this proto version From fc83f181530fb566726e5f3f4197fc5586d77fd8 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 26 Mar 2016 19:09:22 +0100 Subject: [PATCH 0471/1802] Verify that outbound connections have expected services --- src/main.cpp | 9 +++++++++ src/net.cpp | 5 +++++ src/net.h | 1 + 3 files changed, 15 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index ac89945bf2638..7818056d2142d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4616,6 +4616,15 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, { addrman.SetServices(pfrom->addr, pfrom->nServices); } + if (pfrom->nServicesExpected & ~pfrom->nServices) + { + LogPrint("net", "peer=%d does not offer the expected services (%08x offered, %08x expected); disconnecting\n", pfrom->id, pfrom->nServices, pfrom->nServicesExpected); + pfrom->PushMessage(NetMsgType::REJECT, strCommand, REJECT_NONSTANDARD, + strprintf("Expected to offer services %08x", pfrom->nServicesExpected)); + pfrom->fDisconnect = true; + return false; + } + if (pfrom->nVersion < MIN_PEER_PROTO_VERSION) { // disconnect from peers older than this proto version diff --git a/src/net.cpp b/src/net.cpp index 173eba57c8669..a0c2bd5091ce1 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -71,6 +71,9 @@ namespace { const static std::string NET_MESSAGE_COMMAND_OTHER = "*other*"; +/** Services this node implementation cares about */ +static const uint64_t nRelevantServices = NODE_NETWORK; + // // Global state variables // @@ -409,6 +412,7 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure vNodes.push_back(pnode); } + pnode->nServicesExpected = addrConnect.nServices & nRelevantServices; pnode->nTimeConnected = GetTime(); return pnode; @@ -2325,6 +2329,7 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa filterInventoryKnown(50000, 0.000001) { nServices = 0; + nServicesExpected = 0; hSocket = hSocketIn; nRecvVersion = INIT_PROTO_VERSION; nLastSend = 0; diff --git a/src/net.h b/src/net.h index 5c1f7e3e89cbc..445d25bf821bd 100644 --- a/src/net.h +++ b/src/net.h @@ -317,6 +317,7 @@ class CNode public: // socket uint64_t nServices; + uint64_t nServicesExpected; SOCKET hSocket; CDataStream ssSend; size_t nSendSize; // total size of all vSendMsg entries From 5e7ab16d29ac66a5a5753dd4f59b6fb12e60654e Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 26 Mar 2016 13:31:25 +0100 Subject: [PATCH 0472/1802] Only store and connect to NODE_NETWORK nodes --- src/main.cpp | 3 +++ src/net.cpp | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 7818056d2142d..bcaf095ab3141 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4785,6 +4785,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, { boost::this_thread::interruption_point(); + if (!(addr.nServices & NODE_NETWORK)) + continue; + if (addr.nTime <= 100000000 || addr.nTime > nNow + 10 * 60) addr.nTime = nNow - 5 * 24 * 60 * 60; pfrom->AddAddressKnown(addr); diff --git a/src/net.cpp b/src/net.cpp index a0c2bd5091ce1..395e1fe423bda 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1596,6 +1596,10 @@ void ThreadOpenConnections() if (IsLimited(addr)) continue; + // only connect to full nodes + if (!(addr.nServices & NODE_NETWORK)) + continue; + // only consider very recently tried nodes after 30 failed attempts if (nANow - addr.nLastTry < 600 && nTries < 30) continue; From 15bf863219abe968ebe9e59fed4806c9fd07a58b Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 25 May 2016 17:18:37 +0200 Subject: [PATCH 0473/1802] Don't require services in -addnode --- src/net.cpp | 15 ++++--- src/protocol.cpp | 2 +- src/protocol.h | 2 +- src/test/DoS_tests.cpp | 8 ++-- src/test/addrman_tests.cpp | 92 +++++++++++++++++++------------------- src/test/net_tests.cpp | 8 ++-- 6 files changed, 64 insertions(+), 63 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 395e1fe423bda..80ba7fce2288a 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -162,7 +162,7 @@ static std::vector convertSeed6(const std::vector &vSeedsIn { struct in6_addr ip; memcpy(&ip, i->addr, sizeof(ip)); - CAddress addr(CService(ip, i->port)); + CAddress addr(CService(ip, i->port), NODE_NETWORK); addr.nTime = GetTime() - GetRand(nOneWeek) - nOneWeek; vSeedsOut.push_back(addr); } @@ -179,9 +179,8 @@ CAddress GetLocalAddress(const CNetAddr *paddrPeer) CService addr; if (GetLocal(addr, paddrPeer)) { - ret = CAddress(addr); + ret = CAddress(addr, nLocalServices); } - ret.nServices = nLocalServices; ret.nTime = GetAdjustedTime(); return ret; } @@ -465,7 +464,7 @@ void CNode::PushVersion() int nBestHeight = GetNodeSignals().GetHeight().get_value_or(0); int64_t nTime = (fInbound ? GetAdjustedTime() : GetTime()); - CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0))); + CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0), addr.nServices)); CAddress addrMe = GetLocalAddress(&addr); GetRandBytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce)); if (fLogIPs) @@ -1441,7 +1440,7 @@ void ThreadDNSAddressSeed() } else { std::vector vIPs; std::vector vAdd; - uint64_t requiredServiceBits = NODE_NETWORK; + uint64_t requiredServiceBits = nRelevantServices; if (LookupHost(seed.getHost(requiredServiceBits).c_str(), vIPs, 0, true)) { BOOST_FOREACH(const CNetAddr& ip, vIPs) @@ -1524,7 +1523,7 @@ void ThreadOpenConnections() ProcessOneShot(); BOOST_FOREACH(const std::string& strAddr, mapMultiArgs["-connect"]) { - CAddress addr; + CAddress addr(CService(), 0); OpenNetworkConnection(addr, false, NULL, strAddr.c_str()); for (int i = 0; i < 10 && i < nLoop; i++) { @@ -1674,7 +1673,9 @@ void ThreadOpenAddedConnections() BOOST_FOREACH(std::vector& vserv, lservAddressesToAdd) { CSemaphoreGrant grant(*semOutbound); - OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), false, &grant); + /* We want -addnode to work even for nodes that don't provide all + * wanted services, so pass in nServices=0 to CAddress. */ + OpenNetworkConnection(CAddress(vserv[i % vserv.size()], 0), false, &grant); MilliSleep(500); } MilliSleep(120000); // Retry every 2 minutes diff --git a/src/protocol.cpp b/src/protocol.cpp index 8c4bd057254a3..a46051b84f2e3 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -141,7 +141,7 @@ CAddress::CAddress(CService ipIn, uint64_t nServicesIn) : CService(ipIn) void CAddress::Init() { - nServices = NODE_NETWORK; + nServices = 0; nTime = 100000000; } diff --git a/src/protocol.h b/src/protocol.h index 1b049e52af8a6..c3f819aaee882 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -251,7 +251,7 @@ class CAddress : public CService { public: CAddress(); - explicit CAddress(CService ipIn, uint64_t nServicesIn = NODE_NETWORK); + explicit CAddress(CService ipIn, uint64_t nServicesIn); void Init(); diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index 95342498fa782..dc019d6cf5746 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -45,7 +45,7 @@ BOOST_FIXTURE_TEST_SUITE(DoS_tests, TestingSetup) BOOST_AUTO_TEST_CASE(DoS_banning) { CNode::ClearBanned(); - CAddress addr1(ip(0xa0b0c001)); + CAddress addr1(ip(0xa0b0c001), 0); CNode dummyNode1(INVALID_SOCKET, addr1, "", true); dummyNode1.nVersion = 1; Misbehaving(dummyNode1.GetId(), 100); // Should get banned @@ -53,7 +53,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning) BOOST_CHECK(CNode::IsBanned(addr1)); BOOST_CHECK(!CNode::IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned - CAddress addr2(ip(0xa0b0c002)); + CAddress addr2(ip(0xa0b0c002), 0); CNode dummyNode2(INVALID_SOCKET, addr2, "", true); dummyNode2.nVersion = 1; Misbehaving(dummyNode2.GetId(), 50); @@ -69,7 +69,7 @@ BOOST_AUTO_TEST_CASE(DoS_banscore) { CNode::ClearBanned(); mapArgs["-banscore"] = "111"; // because 11 is my favorite number - CAddress addr1(ip(0xa0b0c001)); + CAddress addr1(ip(0xa0b0c001), 0); CNode dummyNode1(INVALID_SOCKET, addr1, "", true); dummyNode1.nVersion = 1; Misbehaving(dummyNode1.GetId(), 100); @@ -90,7 +90,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) int64_t nStartTime = GetTime(); SetMockTime(nStartTime); // Overrides future calls to GetTime() - CAddress addr(ip(0xa0b0c001)); + CAddress addr(ip(0xa0b0c001), 0); CNode dummyNode(INVALID_SOCKET, addr, "", true); dummyNode.nVersion = 1; diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp index 767b653e47734..93c3eba7fe27d 100644 --- a/src/test/addrman_tests.cpp +++ b/src/test/addrman_tests.cpp @@ -68,7 +68,7 @@ BOOST_AUTO_TEST_CASE(addrman_simple) // Test 2: Does Addrman::Add work as expected. CService addr1 = CService("250.1.1.1", 8333); - addrman.Add(CAddress(addr1), source); + addrman.Add(CAddress(addr1, 0), source); BOOST_CHECK(addrman.size() == 1); CAddrInfo addr_ret1 = addrman.Select(); BOOST_CHECK(addr_ret1.ToString() == "250.1.1.1:8333"); @@ -76,14 +76,14 @@ BOOST_AUTO_TEST_CASE(addrman_simple) // Test 3: Does IP address deduplication work correctly. // Expected dup IP should not be added. CService addr1_dup = CService("250.1.1.1", 8333); - addrman.Add(CAddress(addr1_dup), source); + addrman.Add(CAddress(addr1_dup, 0), source); BOOST_CHECK(addrman.size() == 1); // Test 5: New table has one addr and we add a diff addr we should // have two addrs. CService addr2 = CService("250.1.1.2", 8333); - addrman.Add(CAddress(addr2), source); + addrman.Add(CAddress(addr2, 0), source); BOOST_CHECK(addrman.size() == 2); // Test 6: AddrMan::Clear() should empty the new table. @@ -106,18 +106,18 @@ BOOST_AUTO_TEST_CASE(addrman_ports) // Test 7; Addr with same IP but diff port does not replace existing addr. CService addr1 = CService("250.1.1.1", 8333); - addrman.Add(CAddress(addr1), source); + addrman.Add(CAddress(addr1, 0), source); BOOST_CHECK(addrman.size() == 1); CService addr1_port = CService("250.1.1.1", 8334); - addrman.Add(CAddress(addr1_port), source); + addrman.Add(CAddress(addr1_port, 0), source); BOOST_CHECK(addrman.size() == 1); CAddrInfo addr_ret2 = addrman.Select(); BOOST_CHECK(addr_ret2.ToString() == "250.1.1.1:8333"); // Test 8: Add same IP but diff port to tried table, it doesn't get added. // Perhaps this is not ideal behavior but it is the current behavior. - addrman.Good(CAddress(addr1_port)); + addrman.Good(CAddress(addr1_port, 0)); BOOST_CHECK(addrman.size() == 1); bool newOnly = true; CAddrInfo addr_ret3 = addrman.Select(newOnly); @@ -136,7 +136,7 @@ BOOST_AUTO_TEST_CASE(addrman_select) // Test 9: Select from new with 1 addr in new. CService addr1 = CService("250.1.1.1", 8333); - addrman.Add(CAddress(addr1), source); + addrman.Add(CAddress(addr1, 0), source); BOOST_CHECK(addrman.size() == 1); bool newOnly = true; @@ -144,7 +144,7 @@ BOOST_AUTO_TEST_CASE(addrman_select) BOOST_CHECK(addr_ret1.ToString() == "250.1.1.1:8333"); // Test 10: move addr to tried, select from new expected nothing returned. - addrman.Good(CAddress(addr1)); + addrman.Good(CAddress(addr1, 0)); BOOST_CHECK(addrman.size() == 1); CAddrInfo addr_ret2 = addrman.Select(newOnly); BOOST_CHECK(addr_ret2.ToString() == "[::]:0"); @@ -160,21 +160,21 @@ BOOST_AUTO_TEST_CASE(addrman_select) CService addr3 = CService("250.3.2.2", 9999); CService addr4 = CService("250.3.3.3", 9999); - addrman.Add(CAddress(addr2), CService("250.3.1.1", 8333)); - addrman.Add(CAddress(addr3), CService("250.3.1.1", 8333)); - addrman.Add(CAddress(addr4), CService("250.4.1.1", 8333)); + addrman.Add(CAddress(addr2, 0), CService("250.3.1.1", 8333)); + addrman.Add(CAddress(addr3, 0), CService("250.3.1.1", 8333)); + addrman.Add(CAddress(addr4, 0), CService("250.4.1.1", 8333)); // Add three addresses to tried table. CService addr5 = CService("250.4.4.4", 8333); CService addr6 = CService("250.4.5.5", 7777); CService addr7 = CService("250.4.6.6", 8333); - addrman.Add(CAddress(addr5), CService("250.3.1.1", 8333)); - addrman.Good(CAddress(addr5)); - addrman.Add(CAddress(addr6), CService("250.3.1.1", 8333)); - addrman.Good(CAddress(addr6)); - addrman.Add(CAddress(addr7), CService("250.1.1.3", 8333)); - addrman.Good(CAddress(addr7)); + addrman.Add(CAddress(addr5, 0), CService("250.3.1.1", 8333)); + addrman.Good(CAddress(addr5, 0)); + addrman.Add(CAddress(addr6, 0), CService("250.3.1.1", 8333)); + addrman.Good(CAddress(addr6, 0)); + addrman.Add(CAddress(addr7, 0), CService("250.1.1.3", 8333)); + addrman.Good(CAddress(addr7, 0)); // Test 11: 6 addrs + 1 addr from last test = 7. BOOST_CHECK(addrman.size() == 7); @@ -199,7 +199,7 @@ BOOST_AUTO_TEST_CASE(addrman_new_collisions) for (unsigned int i = 1; i < 18; i++) { CService addr = CService("250.1.1." + boost::to_string(i)); - addrman.Add(CAddress(addr), source); + addrman.Add(CAddress(addr, 0), source); //Test 13: No collision in new table yet. BOOST_CHECK(addrman.size() == i); @@ -207,11 +207,11 @@ BOOST_AUTO_TEST_CASE(addrman_new_collisions) //Test 14: new table collision! CService addr1 = CService("250.1.1.18"); - addrman.Add(CAddress(addr1), source); + addrman.Add(CAddress(addr1, 0), source); BOOST_CHECK(addrman.size() == 17); CService addr2 = CService("250.1.1.19"); - addrman.Add(CAddress(addr2), source); + addrman.Add(CAddress(addr2, 0), source); BOOST_CHECK(addrman.size() == 18); } @@ -228,8 +228,8 @@ BOOST_AUTO_TEST_CASE(addrman_tried_collisions) for (unsigned int i = 1; i < 80; i++) { CService addr = CService("250.1.1." + boost::to_string(i)); - addrman.Add(CAddress(addr), source); - addrman.Good(CAddress(addr)); + addrman.Add(CAddress(addr, 0), source); + addrman.Good(CAddress(addr, 0)); //Test 15: No collision in tried table yet. BOOST_TEST_MESSAGE(addrman.size()); @@ -238,11 +238,11 @@ BOOST_AUTO_TEST_CASE(addrman_tried_collisions) //Test 16: tried table collision! CService addr1 = CService("250.1.1.80"); - addrman.Add(CAddress(addr1), source); + addrman.Add(CAddress(addr1, 0), source); BOOST_CHECK(addrman.size() == 79); CService addr2 = CService("250.1.1.81"); - addrman.Add(CAddress(addr2), source); + addrman.Add(CAddress(addr2, 0), source); BOOST_CHECK(addrman.size() == 80); } @@ -255,9 +255,9 @@ BOOST_AUTO_TEST_CASE(addrman_find) BOOST_CHECK(addrman.size() == 0); - CAddress addr1 = CAddress(CService("250.1.2.1", 8333)); - CAddress addr2 = CAddress(CService("250.1.2.1", 9999)); - CAddress addr3 = CAddress(CService("251.255.2.1", 8333)); + CAddress addr1 = CAddress(CService("250.1.2.1", 8333), 0); + CAddress addr2 = CAddress(CService("250.1.2.1", 9999), 0); + CAddress addr3 = CAddress(CService("251.255.2.1", 8333), 0); CNetAddr source1 = CNetAddr("250.1.2.1"); CNetAddr source2 = CNetAddr("250.1.2.2"); @@ -294,7 +294,7 @@ BOOST_AUTO_TEST_CASE(addrman_create) BOOST_CHECK(addrman.size() == 0); - CAddress addr1 = CAddress(CService("250.1.2.1", 8333)); + CAddress addr1 = CAddress(CService("250.1.2.1", 8333), 0); CNetAddr source1 = CNetAddr("250.1.2.1"); int nId; @@ -317,7 +317,7 @@ BOOST_AUTO_TEST_CASE(addrman_delete) BOOST_CHECK(addrman.size() == 0); - CAddress addr1 = CAddress(CService("250.1.2.1", 8333)); + CAddress addr1 = CAddress(CService("250.1.2.1", 8333), 0); CNetAddr source1 = CNetAddr("250.1.2.1"); int nId; @@ -344,15 +344,15 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr) vector vAddr1 = addrman.GetAddr(); BOOST_CHECK(vAddr1.size() == 0); - CAddress addr1 = CAddress(CService("250.250.2.1", 8333)); + CAddress addr1 = CAddress(CService("250.250.2.1", 8333), 0); addr1.nTime = GetAdjustedTime(); // Set time so isTerrible = false - CAddress addr2 = CAddress(CService("250.251.2.2", 9999)); + CAddress addr2 = CAddress(CService("250.251.2.2", 9999), 0); addr2.nTime = GetAdjustedTime(); - CAddress addr3 = CAddress(CService("251.252.2.3", 8333)); + CAddress addr3 = CAddress(CService("251.252.2.3", 8333), 0); addr3.nTime = GetAdjustedTime(); - CAddress addr4 = CAddress(CService("252.253.3.4", 8333)); + CAddress addr4 = CAddress(CService("252.253.3.4", 8333), 0); addr4.nTime = GetAdjustedTime(); - CAddress addr5 = CAddress(CService("252.254.4.5", 8333)); + CAddress addr5 = CAddress(CService("252.254.4.5", 8333), 0); addr5.nTime = GetAdjustedTime(); CNetAddr source1 = CNetAddr("250.1.2.1"); CNetAddr source2 = CNetAddr("250.2.3.3"); @@ -368,8 +368,8 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr) BOOST_CHECK(addrman.GetAddr().size() == 1); // Test 24: Ensure GetAddr works with new and tried addresses. - addrman.Good(CAddress(addr1)); - addrman.Good(CAddress(addr2)); + addrman.Good(CAddress(addr1, 0)); + addrman.Good(CAddress(addr2, 0)); BOOST_CHECK(addrman.GetAddr().size() == 1); // Test 25: Ensure GetAddr still returns 23% when addrman has many addrs. @@ -378,7 +378,7 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr) int octet2 = (i / 256) % 256; int octet3 = (i / (256 * 2)) % 256; string strAddr = boost::to_string(octet1) + "." + boost::to_string(octet2) + "." + boost::to_string(octet3) + ".23"; - CAddress addr = CAddress(CService(strAddr)); + CAddress addr = CAddress(CService(strAddr), 0); // Ensure that for all addrs in addrman, isTerrible == false. addr.nTime = GetAdjustedTime(); @@ -403,8 +403,8 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket) // Set addrman addr placement to be deterministic. addrman.MakeDeterministic(); - CAddress addr1 = CAddress(CService("250.1.1.1", 8333)); - CAddress addr2 = CAddress(CService("250.1.1.1", 9999)); + CAddress addr1 = CAddress(CService("250.1.1.1", 8333), 0); + CAddress addr2 = CAddress(CService("250.1.1.1", 9999), 0); CNetAddr source1 = CNetAddr("250.1.1.1"); @@ -431,7 +431,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket) set buckets; for (int i = 0; i < 255; i++) { CAddrInfo infoi = CAddrInfo( - CAddress(CService("250.1.1." + boost::to_string(i))), + CAddress(CService("250.1.1." + boost::to_string(i)), 0), CNetAddr("250.1.1." + boost::to_string(i))); int bucket = infoi.GetTriedBucket(nKey1); buckets.insert(bucket); @@ -443,7 +443,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket) buckets.clear(); for (int j = 0; j < 255; j++) { CAddrInfo infoj = CAddrInfo( - CAddress(CService("250." + boost::to_string(j) + ".1.1")), + CAddress(CService("250." + boost::to_string(j) + ".1.1"), 0), CNetAddr("250." + boost::to_string(j) + ".1.1")); int bucket = infoj.GetTriedBucket(nKey1); buckets.insert(bucket); @@ -460,8 +460,8 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket) // Set addrman addr placement to be deterministic. addrman.MakeDeterministic(); - CAddress addr1 = CAddress(CService("250.1.2.1", 8333)); - CAddress addr2 = CAddress(CService("250.1.2.1", 9999)); + CAddress addr1 = CAddress(CService("250.1.2.1", 8333), 0); + CAddress addr2 = CAddress(CService("250.1.2.1", 9999), 0); CNetAddr source1 = CNetAddr("250.1.2.1"); @@ -484,7 +484,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket) set buckets; for (int i = 0; i < 255; i++) { CAddrInfo infoi = CAddrInfo( - CAddress(CService("250.1.1." + boost::to_string(i))), + CAddress(CService("250.1.1." + boost::to_string(i)), 0), CNetAddr("250.1.1." + boost::to_string(i))); int bucket = infoi.GetNewBucket(nKey1); buckets.insert(bucket); @@ -497,7 +497,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket) for (int j = 0; j < 4 * 255; j++) { CAddrInfo infoj = CAddrInfo(CAddress( CService( - boost::to_string(250 + (j / 255)) + "." + boost::to_string(j % 256) + ".1.1")), + boost::to_string(250 + (j / 255)) + "." + boost::to_string(j % 256) + ".1.1"), 0), CNetAddr("251.4.1.1")); int bucket = infoj.GetNewBucket(nKey1); buckets.insert(bucket); @@ -509,7 +509,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket) buckets.clear(); for (int p = 0; p < 255; p++) { CAddrInfo infoj = CAddrInfo( - CAddress(CService("250.1.1.1")), + CAddress(CService("250.1.1.1"), 0), CNetAddr("250." + boost::to_string(p) + ".1.1")); int bucket = infoj.GetNewBucket(nKey1); buckets.insert(bucket); diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index b38d61f330354..b3d848fcb1ecb 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -51,7 +51,7 @@ class CAddrManCorrupted : public CAddrManSerializationMock int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30); s << nUBuckets; - CAddress addr = CAddress(CService("252.1.1.1", 7777)); + CAddress addr = CAddress(CService("252.1.1.1", 7777), 0); CAddrInfo info = CAddrInfo(addr, CNetAddr("252.2.2.2")); s << info; } @@ -79,9 +79,9 @@ BOOST_AUTO_TEST_CASE(caddrdb_read) CService addr3 = CService("250.7.3.3", 9999); // Add three addresses to new table. - addrmanUncorrupted.Add(CAddress(addr1), CService("252.5.1.1", 8333)); - addrmanUncorrupted.Add(CAddress(addr2), CService("252.5.1.1", 8333)); - addrmanUncorrupted.Add(CAddress(addr3), CService("252.5.1.1", 8333)); + addrmanUncorrupted.Add(CAddress(addr1, 0), CService("252.5.1.1", 8333)); + addrmanUncorrupted.Add(CAddress(addr2, 0), CService("252.5.1.1", 8333)); + addrmanUncorrupted.Add(CAddress(addr3, 0), CService("252.5.1.1", 8333)); // Test that the de-serialization does not throw an exception. CDataStream ssPeers1 = AddrmanToStream(addrmanUncorrupted); From ee06e04369c37da21e048fda849cce2a1f066f84 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 8 Jun 2016 19:12:22 +0200 Subject: [PATCH 0474/1802] Introduce enum ServiceFlags for service flags --- src/addrman.cpp | 4 +- src/addrman.h | 4 +- src/init.cpp | 4 +- src/main.cpp | 4 +- src/net.cpp | 24 +++++----- src/net.h | 8 ++-- src/protocol.cpp | 4 +- src/protocol.h | 12 +++-- src/test/DoS_tests.cpp | 8 ++-- src/test/addrman_tests.cpp | 92 +++++++++++++++++++------------------- src/test/net_tests.cpp | 8 ++-- 11 files changed, 89 insertions(+), 83 deletions(-) diff --git a/src/addrman.cpp b/src/addrman.cpp index d1e98d8ac0904..cebb1c8e5e708 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -263,7 +263,7 @@ bool CAddrMan::Add_(const CAddress& addr, const CNetAddr& source, int64_t nTimeP pinfo->nTime = std::max((int64_t)0, addr.nTime - nTimePenalty); // add services - pinfo->nServices |= addr.nServices; + pinfo->nServices = ServiceFlags(pinfo->nServices | addr.nServices); // do not update if no new information is present if (!addr.nTime || (pinfo->nTime && addr.nTime <= pinfo->nTime)) @@ -502,7 +502,7 @@ void CAddrMan::Connected_(const CService& addr, int64_t nTime) info.nTime = nTime; } -void CAddrMan::SetServices_(const CService& addr, uint64_t nServices) +void CAddrMan::SetServices_(const CService& addr, ServiceFlags nServices) { CAddrInfo* pinfo = Find(addr); diff --git a/src/addrman.h b/src/addrman.h index 7e36e2228f39e..1caf540758797 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -257,7 +257,7 @@ class CAddrMan void Connected_(const CService &addr, int64_t nTime); //! Update an entry's service bits. - void SetServices_(const CService &addr, uint64_t nServices); + void SetServices_(const CService &addr, ServiceFlags nServices); public: /** @@ -592,7 +592,7 @@ class CAddrMan } } - void SetServices(const CService &addr, uint64_t nServices) + void SetServices(const CService &addr, ServiceFlags nServices) { LOCK(cs); Check(); diff --git a/src/init.cpp b/src/init.cpp index ec4ce6b6da7b6..c2ba9ae44babe 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -950,7 +950,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) SetMockTime(GetArg("-mocktime", 0)); // SetMockTime(0) is a no-op if (GetBoolArg("-peerbloomfilters", DEFAULT_PEERBLOOMFILTERS)) - nLocalServices |= NODE_BLOOM; + nLocalServices = ServiceFlags(nLocalServices | NODE_BLOOM); nMaxTipAge = GetArg("-maxtipage", DEFAULT_MAX_TIP_AGE); @@ -1361,7 +1361,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // after any wallet rescanning has taken place. if (fPruneMode) { LogPrintf("Unsetting NODE_NETWORK on prune mode\n"); - nLocalServices &= ~NODE_NETWORK; + nLocalServices = ServiceFlags(nLocalServices & ~NODE_NETWORK); if (!fReindex) { uiInterface.InitMessage(_("Pruning blockstore...")); PruneAndFlush(); diff --git a/src/main.cpp b/src/main.cpp index bcaf095ab3141..c1569545b4e9f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4611,7 +4611,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, CAddress addrMe; CAddress addrFrom; uint64_t nNonce = 1; - vRecv >> pfrom->nVersion >> pfrom->nServices >> nTime >> addrMe; + uint64_t nServiceInt; + vRecv >> pfrom->nVersion >> nServiceInt >> nTime >> addrMe; + pfrom->nServices = ServiceFlags(nServiceInt); if (!pfrom->fInbound) { addrman.SetServices(pfrom->addr, pfrom->nServices); diff --git a/src/net.cpp b/src/net.cpp index 80ba7fce2288a..4661974d21561 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -72,14 +72,14 @@ namespace { const static std::string NET_MESSAGE_COMMAND_OTHER = "*other*"; /** Services this node implementation cares about */ -static const uint64_t nRelevantServices = NODE_NETWORK; +static const ServiceFlags nRelevantServices = NODE_NETWORK; // // Global state variables // bool fDiscover = true; bool fListen = true; -uint64_t nLocalServices = NODE_NETWORK; +ServiceFlags nLocalServices = NODE_NETWORK; bool fRelayTxes = true; CCriticalSection cs_mapLocalHost; std::map mapLocalHost; @@ -175,7 +175,7 @@ static std::vector convertSeed6(const std::vector &vSeedsIn // one by discovery. CAddress GetLocalAddress(const CNetAddr *paddrPeer) { - CAddress ret(CService("0.0.0.0",GetListenPort()),0); + CAddress ret(CService("0.0.0.0",GetListenPort()), NODE_NONE); CService addr; if (GetLocal(addr, paddrPeer)) { @@ -411,7 +411,7 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure vNodes.push_back(pnode); } - pnode->nServicesExpected = addrConnect.nServices & nRelevantServices; + pnode->nServicesExpected = ServiceFlags(addrConnect.nServices & nRelevantServices); pnode->nTimeConnected = GetTime(); return pnode; @@ -464,14 +464,14 @@ void CNode::PushVersion() int nBestHeight = GetNodeSignals().GetHeight().get_value_or(0); int64_t nTime = (fInbound ? GetAdjustedTime() : GetTime()); - CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0), addr.nServices)); + CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0", 0), addr.nServices)); CAddress addrMe = GetLocalAddress(&addr); GetRandBytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce)); if (fLogIPs) LogPrint("net", "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), addrYou.ToString(), id); else LogPrint("net", "send version message: version %d, blocks=%d, us=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), id); - PushMessage(NetMsgType::VERSION, PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe, + PushMessage(NetMsgType::VERSION, PROTOCOL_VERSION, (uint64_t)nLocalServices, nTime, addrYou, addrMe, nLocalHostNonce, strSubVersion, nBestHeight, ::fRelayTxes); } @@ -1440,7 +1440,7 @@ void ThreadDNSAddressSeed() } else { std::vector vIPs; std::vector vAdd; - uint64_t requiredServiceBits = nRelevantServices; + ServiceFlags requiredServiceBits = nRelevantServices; if (LookupHost(seed.getHost(requiredServiceBits).c_str(), vIPs, 0, true)) { BOOST_FOREACH(const CNetAddr& ip, vIPs) @@ -1523,7 +1523,7 @@ void ThreadOpenConnections() ProcessOneShot(); BOOST_FOREACH(const std::string& strAddr, mapMultiArgs["-connect"]) { - CAddress addr(CService(), 0); + CAddress addr(CService(), NODE_NONE); OpenNetworkConnection(addr, false, NULL, strAddr.c_str()); for (int i = 0; i < 10 && i < nLoop; i++) { @@ -1674,8 +1674,8 @@ void ThreadOpenAddedConnections() { CSemaphoreGrant grant(*semOutbound); /* We want -addnode to work even for nodes that don't provide all - * wanted services, so pass in nServices=0 to CAddress. */ - OpenNetworkConnection(CAddress(vserv[i % vserv.size()], 0), false, &grant); + * wanted services, so pass in nServices=NODE_NONE to CAddress. */ + OpenNetworkConnection(CAddress(vserv[i % vserv.size()], NODE_NONE), false, &grant); MilliSleep(500); } MilliSleep(120000); // Retry every 2 minutes @@ -2333,8 +2333,8 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa addrKnown(5000, 0.001), filterInventoryKnown(50000, 0.000001) { - nServices = 0; - nServicesExpected = 0; + nServices = NODE_NONE; + nServicesExpected = NODE_NONE; hSocket = hSocketIn; nRecvVersion = INIT_PROTO_VERSION; nLastSend = 0; diff --git a/src/net.h b/src/net.h index 445d25bf821bd..f5fb8faae2c42 100644 --- a/src/net.h +++ b/src/net.h @@ -152,7 +152,7 @@ CAddress GetLocalAddress(const CNetAddr *paddrPeer = NULL); extern bool fDiscover; extern bool fListen; -extern uint64_t nLocalServices; +extern ServiceFlags nLocalServices; extern bool fRelayTxes; extern uint64_t nLocalHostNonce; extern CAddrMan addrman; @@ -186,7 +186,7 @@ class CNodeStats { public: NodeId nodeid; - uint64_t nServices; + ServiceFlags nServices; bool fRelayTxes; int64_t nLastSend; int64_t nLastRecv; @@ -316,8 +316,8 @@ class CNode { public: // socket - uint64_t nServices; - uint64_t nServicesExpected; + ServiceFlags nServices; + ServiceFlags nServicesExpected; SOCKET hSocket; CDataStream ssSend; size_t nSendSize; // total size of all vSendMsg entries diff --git a/src/protocol.cpp b/src/protocol.cpp index a46051b84f2e3..422ef6f636512 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -133,7 +133,7 @@ CAddress::CAddress() : CService() Init(); } -CAddress::CAddress(CService ipIn, uint64_t nServicesIn) : CService(ipIn) +CAddress::CAddress(CService ipIn, ServiceFlags nServicesIn) : CService(ipIn) { Init(); nServices = nServicesIn; @@ -141,7 +141,7 @@ CAddress::CAddress(CService ipIn, uint64_t nServicesIn) : CService(ipIn) void CAddress::Init() { - nServices = 0; + nServices = NODE_NONE; nTime = 100000000; } diff --git a/src/protocol.h b/src/protocol.h index c3f819aaee882..ab0a5817839b8 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -223,7 +223,9 @@ extern const char *FEEFILTER; const std::vector &getAllNetMessageTypes(); /** nServices flags */ -enum { +enum ServiceFlags : uint64_t { + // Nothing + NODE_NONE = 0, // NODE_NETWORK means that the node is capable of serving the block chain. It is currently // set by all Bitcoin Core nodes, and is unset by SPV clients or other peers that just want // network services but don't provide them. @@ -251,7 +253,7 @@ class CAddress : public CService { public: CAddress(); - explicit CAddress(CService ipIn, uint64_t nServicesIn); + explicit CAddress(CService ipIn, ServiceFlags nServicesIn); void Init(); @@ -267,13 +269,15 @@ class CAddress : public CService if ((nType & SER_DISK) || (nVersion >= CADDR_TIME_VERSION && !(nType & SER_GETHASH))) READWRITE(nTime); - READWRITE(nServices); + uint64_t nServicesInt = nServices; + READWRITE(nServicesInt); + nServices = (ServiceFlags)nServicesInt; READWRITE(*(CService*)this); } // TODO: make private (improves encapsulation) public: - uint64_t nServices; + ServiceFlags nServices; // disk and network only unsigned int nTime; diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index dc019d6cf5746..4a373fc60b653 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -45,7 +45,7 @@ BOOST_FIXTURE_TEST_SUITE(DoS_tests, TestingSetup) BOOST_AUTO_TEST_CASE(DoS_banning) { CNode::ClearBanned(); - CAddress addr1(ip(0xa0b0c001), 0); + CAddress addr1(ip(0xa0b0c001), NODE_NONE); CNode dummyNode1(INVALID_SOCKET, addr1, "", true); dummyNode1.nVersion = 1; Misbehaving(dummyNode1.GetId(), 100); // Should get banned @@ -53,7 +53,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning) BOOST_CHECK(CNode::IsBanned(addr1)); BOOST_CHECK(!CNode::IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned - CAddress addr2(ip(0xa0b0c002), 0); + CAddress addr2(ip(0xa0b0c002), NODE_NONE); CNode dummyNode2(INVALID_SOCKET, addr2, "", true); dummyNode2.nVersion = 1; Misbehaving(dummyNode2.GetId(), 50); @@ -69,7 +69,7 @@ BOOST_AUTO_TEST_CASE(DoS_banscore) { CNode::ClearBanned(); mapArgs["-banscore"] = "111"; // because 11 is my favorite number - CAddress addr1(ip(0xa0b0c001), 0); + CAddress addr1(ip(0xa0b0c001), NODE_NONE); CNode dummyNode1(INVALID_SOCKET, addr1, "", true); dummyNode1.nVersion = 1; Misbehaving(dummyNode1.GetId(), 100); @@ -90,7 +90,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) int64_t nStartTime = GetTime(); SetMockTime(nStartTime); // Overrides future calls to GetTime() - CAddress addr(ip(0xa0b0c001), 0); + CAddress addr(ip(0xa0b0c001), NODE_NONE); CNode dummyNode(INVALID_SOCKET, addr, "", true); dummyNode.nVersion = 1; diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp index 93c3eba7fe27d..b6cec24b5752a 100644 --- a/src/test/addrman_tests.cpp +++ b/src/test/addrman_tests.cpp @@ -68,7 +68,7 @@ BOOST_AUTO_TEST_CASE(addrman_simple) // Test 2: Does Addrman::Add work as expected. CService addr1 = CService("250.1.1.1", 8333); - addrman.Add(CAddress(addr1, 0), source); + addrman.Add(CAddress(addr1, NODE_NONE), source); BOOST_CHECK(addrman.size() == 1); CAddrInfo addr_ret1 = addrman.Select(); BOOST_CHECK(addr_ret1.ToString() == "250.1.1.1:8333"); @@ -76,14 +76,14 @@ BOOST_AUTO_TEST_CASE(addrman_simple) // Test 3: Does IP address deduplication work correctly. // Expected dup IP should not be added. CService addr1_dup = CService("250.1.1.1", 8333); - addrman.Add(CAddress(addr1_dup, 0), source); + addrman.Add(CAddress(addr1_dup, NODE_NONE), source); BOOST_CHECK(addrman.size() == 1); // Test 5: New table has one addr and we add a diff addr we should // have two addrs. CService addr2 = CService("250.1.1.2", 8333); - addrman.Add(CAddress(addr2, 0), source); + addrman.Add(CAddress(addr2, NODE_NONE), source); BOOST_CHECK(addrman.size() == 2); // Test 6: AddrMan::Clear() should empty the new table. @@ -106,18 +106,18 @@ BOOST_AUTO_TEST_CASE(addrman_ports) // Test 7; Addr with same IP but diff port does not replace existing addr. CService addr1 = CService("250.1.1.1", 8333); - addrman.Add(CAddress(addr1, 0), source); + addrman.Add(CAddress(addr1, NODE_NONE), source); BOOST_CHECK(addrman.size() == 1); CService addr1_port = CService("250.1.1.1", 8334); - addrman.Add(CAddress(addr1_port, 0), source); + addrman.Add(CAddress(addr1_port, NODE_NONE), source); BOOST_CHECK(addrman.size() == 1); CAddrInfo addr_ret2 = addrman.Select(); BOOST_CHECK(addr_ret2.ToString() == "250.1.1.1:8333"); // Test 8: Add same IP but diff port to tried table, it doesn't get added. // Perhaps this is not ideal behavior but it is the current behavior. - addrman.Good(CAddress(addr1_port, 0)); + addrman.Good(CAddress(addr1_port, NODE_NONE)); BOOST_CHECK(addrman.size() == 1); bool newOnly = true; CAddrInfo addr_ret3 = addrman.Select(newOnly); @@ -136,7 +136,7 @@ BOOST_AUTO_TEST_CASE(addrman_select) // Test 9: Select from new with 1 addr in new. CService addr1 = CService("250.1.1.1", 8333); - addrman.Add(CAddress(addr1, 0), source); + addrman.Add(CAddress(addr1, NODE_NONE), source); BOOST_CHECK(addrman.size() == 1); bool newOnly = true; @@ -144,7 +144,7 @@ BOOST_AUTO_TEST_CASE(addrman_select) BOOST_CHECK(addr_ret1.ToString() == "250.1.1.1:8333"); // Test 10: move addr to tried, select from new expected nothing returned. - addrman.Good(CAddress(addr1, 0)); + addrman.Good(CAddress(addr1, NODE_NONE)); BOOST_CHECK(addrman.size() == 1); CAddrInfo addr_ret2 = addrman.Select(newOnly); BOOST_CHECK(addr_ret2.ToString() == "[::]:0"); @@ -160,21 +160,21 @@ BOOST_AUTO_TEST_CASE(addrman_select) CService addr3 = CService("250.3.2.2", 9999); CService addr4 = CService("250.3.3.3", 9999); - addrman.Add(CAddress(addr2, 0), CService("250.3.1.1", 8333)); - addrman.Add(CAddress(addr3, 0), CService("250.3.1.1", 8333)); - addrman.Add(CAddress(addr4, 0), CService("250.4.1.1", 8333)); + addrman.Add(CAddress(addr2, NODE_NONE), CService("250.3.1.1", 8333)); + addrman.Add(CAddress(addr3, NODE_NONE), CService("250.3.1.1", 8333)); + addrman.Add(CAddress(addr4, NODE_NONE), CService("250.4.1.1", 8333)); // Add three addresses to tried table. CService addr5 = CService("250.4.4.4", 8333); CService addr6 = CService("250.4.5.5", 7777); CService addr7 = CService("250.4.6.6", 8333); - addrman.Add(CAddress(addr5, 0), CService("250.3.1.1", 8333)); - addrman.Good(CAddress(addr5, 0)); - addrman.Add(CAddress(addr6, 0), CService("250.3.1.1", 8333)); - addrman.Good(CAddress(addr6, 0)); - addrman.Add(CAddress(addr7, 0), CService("250.1.1.3", 8333)); - addrman.Good(CAddress(addr7, 0)); + addrman.Add(CAddress(addr5, NODE_NONE), CService("250.3.1.1", 8333)); + addrman.Good(CAddress(addr5, NODE_NONE)); + addrman.Add(CAddress(addr6, NODE_NONE), CService("250.3.1.1", 8333)); + addrman.Good(CAddress(addr6, NODE_NONE)); + addrman.Add(CAddress(addr7, NODE_NONE), CService("250.1.1.3", 8333)); + addrman.Good(CAddress(addr7, NODE_NONE)); // Test 11: 6 addrs + 1 addr from last test = 7. BOOST_CHECK(addrman.size() == 7); @@ -199,7 +199,7 @@ BOOST_AUTO_TEST_CASE(addrman_new_collisions) for (unsigned int i = 1; i < 18; i++) { CService addr = CService("250.1.1." + boost::to_string(i)); - addrman.Add(CAddress(addr, 0), source); + addrman.Add(CAddress(addr, NODE_NONE), source); //Test 13: No collision in new table yet. BOOST_CHECK(addrman.size() == i); @@ -207,11 +207,11 @@ BOOST_AUTO_TEST_CASE(addrman_new_collisions) //Test 14: new table collision! CService addr1 = CService("250.1.1.18"); - addrman.Add(CAddress(addr1, 0), source); + addrman.Add(CAddress(addr1, NODE_NONE), source); BOOST_CHECK(addrman.size() == 17); CService addr2 = CService("250.1.1.19"); - addrman.Add(CAddress(addr2, 0), source); + addrman.Add(CAddress(addr2, NODE_NONE), source); BOOST_CHECK(addrman.size() == 18); } @@ -228,8 +228,8 @@ BOOST_AUTO_TEST_CASE(addrman_tried_collisions) for (unsigned int i = 1; i < 80; i++) { CService addr = CService("250.1.1." + boost::to_string(i)); - addrman.Add(CAddress(addr, 0), source); - addrman.Good(CAddress(addr, 0)); + addrman.Add(CAddress(addr, NODE_NONE), source); + addrman.Good(CAddress(addr, NODE_NONE)); //Test 15: No collision in tried table yet. BOOST_TEST_MESSAGE(addrman.size()); @@ -238,11 +238,11 @@ BOOST_AUTO_TEST_CASE(addrman_tried_collisions) //Test 16: tried table collision! CService addr1 = CService("250.1.1.80"); - addrman.Add(CAddress(addr1, 0), source); + addrman.Add(CAddress(addr1, NODE_NONE), source); BOOST_CHECK(addrman.size() == 79); CService addr2 = CService("250.1.1.81"); - addrman.Add(CAddress(addr2, 0), source); + addrman.Add(CAddress(addr2, NODE_NONE), source); BOOST_CHECK(addrman.size() == 80); } @@ -255,9 +255,9 @@ BOOST_AUTO_TEST_CASE(addrman_find) BOOST_CHECK(addrman.size() == 0); - CAddress addr1 = CAddress(CService("250.1.2.1", 8333), 0); - CAddress addr2 = CAddress(CService("250.1.2.1", 9999), 0); - CAddress addr3 = CAddress(CService("251.255.2.1", 8333), 0); + CAddress addr1 = CAddress(CService("250.1.2.1", 8333), NODE_NONE); + CAddress addr2 = CAddress(CService("250.1.2.1", 9999), NODE_NONE); + CAddress addr3 = CAddress(CService("251.255.2.1", 8333), NODE_NONE); CNetAddr source1 = CNetAddr("250.1.2.1"); CNetAddr source2 = CNetAddr("250.1.2.2"); @@ -294,7 +294,7 @@ BOOST_AUTO_TEST_CASE(addrman_create) BOOST_CHECK(addrman.size() == 0); - CAddress addr1 = CAddress(CService("250.1.2.1", 8333), 0); + CAddress addr1 = CAddress(CService("250.1.2.1", 8333), NODE_NONE); CNetAddr source1 = CNetAddr("250.1.2.1"); int nId; @@ -317,7 +317,7 @@ BOOST_AUTO_TEST_CASE(addrman_delete) BOOST_CHECK(addrman.size() == 0); - CAddress addr1 = CAddress(CService("250.1.2.1", 8333), 0); + CAddress addr1 = CAddress(CService("250.1.2.1", 8333), NODE_NONE); CNetAddr source1 = CNetAddr("250.1.2.1"); int nId; @@ -344,15 +344,15 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr) vector vAddr1 = addrman.GetAddr(); BOOST_CHECK(vAddr1.size() == 0); - CAddress addr1 = CAddress(CService("250.250.2.1", 8333), 0); + CAddress addr1 = CAddress(CService("250.250.2.1", 8333), NODE_NONE); addr1.nTime = GetAdjustedTime(); // Set time so isTerrible = false - CAddress addr2 = CAddress(CService("250.251.2.2", 9999), 0); + CAddress addr2 = CAddress(CService("250.251.2.2", 9999), NODE_NONE); addr2.nTime = GetAdjustedTime(); - CAddress addr3 = CAddress(CService("251.252.2.3", 8333), 0); + CAddress addr3 = CAddress(CService("251.252.2.3", 8333), NODE_NONE); addr3.nTime = GetAdjustedTime(); - CAddress addr4 = CAddress(CService("252.253.3.4", 8333), 0); + CAddress addr4 = CAddress(CService("252.253.3.4", 8333), NODE_NONE); addr4.nTime = GetAdjustedTime(); - CAddress addr5 = CAddress(CService("252.254.4.5", 8333), 0); + CAddress addr5 = CAddress(CService("252.254.4.5", 8333), NODE_NONE); addr5.nTime = GetAdjustedTime(); CNetAddr source1 = CNetAddr("250.1.2.1"); CNetAddr source2 = CNetAddr("250.2.3.3"); @@ -368,8 +368,8 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr) BOOST_CHECK(addrman.GetAddr().size() == 1); // Test 24: Ensure GetAddr works with new and tried addresses. - addrman.Good(CAddress(addr1, 0)); - addrman.Good(CAddress(addr2, 0)); + addrman.Good(CAddress(addr1, NODE_NONE)); + addrman.Good(CAddress(addr2, NODE_NONE)); BOOST_CHECK(addrman.GetAddr().size() == 1); // Test 25: Ensure GetAddr still returns 23% when addrman has many addrs. @@ -378,7 +378,7 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr) int octet2 = (i / 256) % 256; int octet3 = (i / (256 * 2)) % 256; string strAddr = boost::to_string(octet1) + "." + boost::to_string(octet2) + "." + boost::to_string(octet3) + ".23"; - CAddress addr = CAddress(CService(strAddr), 0); + CAddress addr = CAddress(CService(strAddr), NODE_NONE); // Ensure that for all addrs in addrman, isTerrible == false. addr.nTime = GetAdjustedTime(); @@ -403,8 +403,8 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket) // Set addrman addr placement to be deterministic. addrman.MakeDeterministic(); - CAddress addr1 = CAddress(CService("250.1.1.1", 8333), 0); - CAddress addr2 = CAddress(CService("250.1.1.1", 9999), 0); + CAddress addr1 = CAddress(CService("250.1.1.1", 8333), NODE_NONE); + CAddress addr2 = CAddress(CService("250.1.1.1", 9999), NODE_NONE); CNetAddr source1 = CNetAddr("250.1.1.1"); @@ -431,7 +431,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket) set buckets; for (int i = 0; i < 255; i++) { CAddrInfo infoi = CAddrInfo( - CAddress(CService("250.1.1." + boost::to_string(i)), 0), + CAddress(CService("250.1.1." + boost::to_string(i)), NODE_NONE), CNetAddr("250.1.1." + boost::to_string(i))); int bucket = infoi.GetTriedBucket(nKey1); buckets.insert(bucket); @@ -443,7 +443,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket) buckets.clear(); for (int j = 0; j < 255; j++) { CAddrInfo infoj = CAddrInfo( - CAddress(CService("250." + boost::to_string(j) + ".1.1"), 0), + CAddress(CService("250." + boost::to_string(j) + ".1.1"), NODE_NONE), CNetAddr("250." + boost::to_string(j) + ".1.1")); int bucket = infoj.GetTriedBucket(nKey1); buckets.insert(bucket); @@ -460,8 +460,8 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket) // Set addrman addr placement to be deterministic. addrman.MakeDeterministic(); - CAddress addr1 = CAddress(CService("250.1.2.1", 8333), 0); - CAddress addr2 = CAddress(CService("250.1.2.1", 9999), 0); + CAddress addr1 = CAddress(CService("250.1.2.1", 8333), NODE_NONE); + CAddress addr2 = CAddress(CService("250.1.2.1", 9999), NODE_NONE); CNetAddr source1 = CNetAddr("250.1.2.1"); @@ -484,7 +484,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket) set buckets; for (int i = 0; i < 255; i++) { CAddrInfo infoi = CAddrInfo( - CAddress(CService("250.1.1." + boost::to_string(i)), 0), + CAddress(CService("250.1.1." + boost::to_string(i)), NODE_NONE), CNetAddr("250.1.1." + boost::to_string(i))); int bucket = infoi.GetNewBucket(nKey1); buckets.insert(bucket); @@ -497,7 +497,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket) for (int j = 0; j < 4 * 255; j++) { CAddrInfo infoj = CAddrInfo(CAddress( CService( - boost::to_string(250 + (j / 255)) + "." + boost::to_string(j % 256) + ".1.1"), 0), + boost::to_string(250 + (j / 255)) + "." + boost::to_string(j % 256) + ".1.1"), NODE_NONE), CNetAddr("251.4.1.1")); int bucket = infoj.GetNewBucket(nKey1); buckets.insert(bucket); @@ -509,7 +509,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket) buckets.clear(); for (int p = 0; p < 255; p++) { CAddrInfo infoj = CAddrInfo( - CAddress(CService("250.1.1.1"), 0), + CAddress(CService("250.1.1.1"), NODE_NONE), CNetAddr("250." + boost::to_string(p) + ".1.1")); int bucket = infoj.GetNewBucket(nKey1); buckets.insert(bucket); diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index b3d848fcb1ecb..d005d6a1633e9 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -51,7 +51,7 @@ class CAddrManCorrupted : public CAddrManSerializationMock int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30); s << nUBuckets; - CAddress addr = CAddress(CService("252.1.1.1", 7777), 0); + CAddress addr = CAddress(CService("252.1.1.1", 7777), NODE_NONE); CAddrInfo info = CAddrInfo(addr, CNetAddr("252.2.2.2")); s << info; } @@ -79,9 +79,9 @@ BOOST_AUTO_TEST_CASE(caddrdb_read) CService addr3 = CService("250.7.3.3", 9999); // Add three addresses to new table. - addrmanUncorrupted.Add(CAddress(addr1, 0), CService("252.5.1.1", 8333)); - addrmanUncorrupted.Add(CAddress(addr2, 0), CService("252.5.1.1", 8333)); - addrmanUncorrupted.Add(CAddress(addr3, 0), CService("252.5.1.1", 8333)); + addrmanUncorrupted.Add(CAddress(addr1, NODE_NONE), CService("252.5.1.1", 8333)); + addrmanUncorrupted.Add(CAddress(addr2, NODE_NONE), CService("252.5.1.1", 8333)); + addrmanUncorrupted.Add(CAddress(addr3, NODE_NONE), CService("252.5.1.1", 8333)); // Test that the de-serialization does not throw an exception. CDataStream ssPeers1 = AddrmanToStream(addrmanUncorrupted); From ecd7fd37c888f8ebc64cf3d92272975b37ae54ca Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 13 Jun 2016 16:01:21 +0200 Subject: [PATCH 0475/1802] Introduce REQUIRED_SERVICES constant --- src/main.cpp | 2 +- src/net.cpp | 2 +- src/net.h | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index c1569545b4e9f..62012bf56709f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4787,7 +4787,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, { boost::this_thread::interruption_point(); - if (!(addr.nServices & NODE_NETWORK)) + if ((addr.nServices & REQUIRED_SERVICES) != REQUIRED_SERVICES) continue; if (addr.nTime <= 100000000 || addr.nTime > nNow + 10 * 60) diff --git a/src/net.cpp b/src/net.cpp index 4661974d21561..a390eca776f52 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1596,7 +1596,7 @@ void ThreadOpenConnections() continue; // only connect to full nodes - if (!(addr.nServices & NODE_NETWORK)) + if ((addr.nServices & REQUIRED_SERVICES) != REQUIRED_SERVICES) continue; // only consider very recently tried nodes after 30 failed attempts diff --git a/src/net.h b/src/net.h index f5fb8faae2c42..2aaca4888fde9 100644 --- a/src/net.h +++ b/src/net.h @@ -72,6 +72,8 @@ static const bool DEFAULT_FORCEDNSSEED = false; static const size_t DEFAULT_MAXRECEIVEBUFFER = 5 * 1000; static const size_t DEFAULT_MAXSENDBUFFER = 1 * 1000; +static const ServiceFlags REQUIRED_SERVICES = NODE_NETWORK; + // NOTE: When adjusting this, update rpcnet:setban's help ("24h") static const unsigned int DEFAULT_MISBEHAVING_BANTIME = 60 * 60 * 24; // Default 24-hour ban From fa26c420bfb7dbad6781f31f222a66ef52f2ae45 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 13 Jun 2016 19:36:01 +0200 Subject: [PATCH 0476/1802] [qa] util: Move check_fee_amount out of wallet.py --- qa/rpc-tests/test_framework/util.py | 9 +++++++++ qa/rpc-tests/wallet.py | 7 +------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index fc66ef287d715..782df52d62af9 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -477,6 +477,15 @@ def random_transaction(nodes, amount, min_fee, fee_increment, fee_variants): return (txid, signresult["hex"], fee) +def assert_fee_amount(fee, tx_size, fee_per_kB): + """Assert the fee was in range""" + target_fee = tx_size * fee_per_kB / 1000 + if fee < target_fee: + raise AssertionError("Fee of %s BTC too low! (Should be %s BTC)"%(str(fee), str(target_fee))) + # allow the wallet's estimation to be at most 2 bytes off + if fee > (tx_size + 2) * fee_per_kB / 1000: + raise AssertionError("Fee of %s BTC too high! (Should be %s BTC)"%(str(fee), str(target_fee))) + def assert_equal(thing1, thing2): if thing1 != thing2: raise AssertionError("%s != %s"%(str(thing1),str(thing2))) diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py index 9dda712f4ff08..0b7eb52f07fd5 100755 --- a/qa/rpc-tests/wallet.py +++ b/qa/rpc-tests/wallet.py @@ -11,12 +11,7 @@ class WalletTest (BitcoinTestFramework): def check_fee_amount(self, curr_balance, balance_with_fee, fee_per_byte, tx_size): """Return curr_balance after asserting the fee was in range""" fee = balance_with_fee - curr_balance - target_fee = fee_per_byte * tx_size - if fee < target_fee: - raise AssertionError("Fee of %s BTC too low! (Should be %s BTC)"%(str(fee), str(target_fee))) - # allow the node's estimation to be at most 2 bytes off - if fee > fee_per_byte * (tx_size + 2): - raise AssertionError("Fee of %s BTC too high! (Should be %s BTC)"%(str(fee), str(target_fee))) + assert_fee_amount(fee, tx_size, fee_per_byte * 1000) return curr_balance def __init__(self): From fae1d063fc8a54067a8527d249d8801a00feef03 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 13 Jun 2016 19:52:01 +0200 Subject: [PATCH 0477/1802] [qa] fundrawtransaction: Fix race, assert amounts --- qa/rpc-tests/fundrawtransaction.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py index 998f822afe81d..228574e671803 100755 --- a/qa/rpc-tests/fundrawtransaction.py +++ b/qa/rpc-tests/fundrawtransaction.py @@ -58,7 +58,6 @@ def run_test(self): self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.0) self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 5.0) - self.sync_all() self.nodes[0].generate(1) self.sync_all() @@ -552,7 +551,6 @@ def run_test(self): self.nodes[1].walletpassphrase("test", 100) signedTx = self.nodes[1].signrawtransaction(fundedTx['hex']) txId = self.nodes[1].sendrawtransaction(signedTx['hex']) - self.sync_all() self.nodes[1].generate(1) self.sync_all() @@ -572,7 +570,6 @@ def run_test(self): for i in range(0,20): self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.01) - self.sync_all() self.nodes[0].generate(1) self.sync_all() @@ -603,7 +600,6 @@ def run_test(self): for i in range(0,20): self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.01) - self.sync_all() self.nodes[0].generate(1) self.sync_all() @@ -677,6 +673,15 @@ def run_test(self): signedtx = self.nodes[0].signrawtransaction(signedtx["hex"]) assert(signedtx["complete"]) self.nodes[0].sendrawtransaction(signedtx["hex"]) + self.nodes[0].generate(1) + self.sync_all() + + ####################### + # Test 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[2].getnewaddress() : 1} @@ -684,8 +689,9 @@ def run_test(self): result = self.nodes[3].fundrawtransaction(rawtx) # uses min_relay_tx_fee (set by settxfee) result2 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2*min_relay_tx_fee}) result3 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 10*min_relay_tx_fee}) - assert_equal(result['fee']*2, result2['fee']) - assert_equal(result['fee']*10, result3['fee']) + 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) if __name__ == '__main__': RawTransactionsTest().main() From 1111b80df84aa7bc72fbddcc7bafde43f0835d90 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 28 May 2016 15:32:30 +0200 Subject: [PATCH 0478/1802] Rework addnode behaviour * Use CNode::addeName to track whether a connection to a name is already open * A new connection to a previously-connected by-name addednode is only opened when the previous one closes (even if the name starts resolving to something else) * At most one connection is opened per addednode (even if the name resolves to multiple) * Unify the code between ThreadOpenAddedNodeConnections and getaddednodeinfo * Information about open connections is always returned, and the dns argument becomes a dummy * An IP address and inbound/outbound is only reported for the (at most 1) open connection --- src/net.cpp | 107 ++++++++++++++++++++++++++---------------------- src/net.h | 10 +++++ src/rpc/net.cpp | 95 ++++++++++-------------------------------- 3 files changed, 91 insertions(+), 121 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index a390eca776f52..4d27db7604d0b 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1616,68 +1616,79 @@ void ThreadOpenConnections() } } -void ThreadOpenAddedConnections() +std::vector GetAddedNodeInfo() { + std::vector ret; + + std::list lAddresses(0); { LOCK(cs_vAddedNodes); - vAddedNodes = mapMultiArgs["-addnode"]; + ret.reserve(vAddedNodes.size()); + BOOST_FOREACH(const std::string& strAddNode, vAddedNodes) + lAddresses.push_back(strAddNode); } - if (HaveNameProxy()) { - while(true) { - std::list lAddresses(0); - { - LOCK(cs_vAddedNodes); - BOOST_FOREACH(const std::string& strAddNode, vAddedNodes) - lAddresses.push_back(strAddNode); + + // Build a map of all already connected addresses (by IP:port and by name) to inbound/outbound and resolved CService + std::map mapConnected; + std::map> mapConnectedByName; + { + LOCK(cs_vNodes); + for (const CNode* pnode : vNodes) { + if (pnode->addr.IsValid()) { + mapConnected[pnode->addr] = pnode->fInbound; } - BOOST_FOREACH(const std::string& strAddNode, lAddresses) { - CAddress addr; - CSemaphoreGrant grant(*semOutbound); - OpenNetworkConnection(addr, false, &grant, strAddNode.c_str()); - MilliSleep(500); + if (!pnode->addrName.empty()) { + mapConnectedByName[pnode->addrName] = std::make_pair(pnode->fInbound, static_cast(pnode->addr)); } - MilliSleep(120000); // Retry every 2 minutes } } + BOOST_FOREACH(const std::string& strAddNode, lAddresses) { + CService service(strAddNode, Params().GetDefaultPort()); + if (service.IsValid()) { + // strAddNode is an IP:port + auto it = mapConnected.find(service); + if (it != mapConnected.end()) { + ret.push_back(AddedNodeInfo{strAddNode, service, true, it->second}); + } else { + ret.push_back(AddedNodeInfo{strAddNode, CService(), false, false}); + } + } else { + // strAddNode is a name + auto it = mapConnectedByName.find(strAddNode); + if (it != mapConnectedByName.end()) { + ret.push_back(AddedNodeInfo{strAddNode, it->second.second, true, it->second.first}); + } else { + ret.push_back(AddedNodeInfo{strAddNode, CService(), false, false}); + } + } + } + + return ret; +} + +void ThreadOpenAddedConnections() +{ + { + LOCK(cs_vAddedNodes); + vAddedNodes = mapMultiArgs["-addnode"]; + } + for (unsigned int i = 0; true; i++) { - std::list lAddresses(0); - { - LOCK(cs_vAddedNodes); - BOOST_FOREACH(const std::string& strAddNode, vAddedNodes) - lAddresses.push_back(strAddNode); + std::vector vInfo = GetAddedNodeInfo(); + for (const AddedNodeInfo& info : vInfo) { + if (!info.fConnected) { + CSemaphoreGrant grant(*semOutbound); + // If strAddedNode is an IP/port, decode it immediately, so + // OpenNetworkConnection can detect existing connections to that IP/port. + CService service(info.strAddedNode, Params().GetDefaultPort()); + OpenNetworkConnection(CAddress(service, NODE_NONE), false, &grant, info.strAddedNode.c_str(), false); + MilliSleep(500); + } } - std::list > lservAddressesToAdd(0); - BOOST_FOREACH(const std::string& strAddNode, lAddresses) { - std::vector vservNode(0); - if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0)) - lservAddressesToAdd.push_back(vservNode); - } - // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry - // (keeping in mind that addnode entries can have many IPs if fNameLookup) - { - LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) - for (std::list >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++) - BOOST_FOREACH(const CService& addrNode, *(it)) - if (pnode->addr == addrNode) - { - it = lservAddressesToAdd.erase(it); - it--; - break; - } - } - BOOST_FOREACH(std::vector& vserv, lservAddressesToAdd) - { - CSemaphoreGrant grant(*semOutbound); - /* We want -addnode to work even for nodes that don't provide all - * wanted services, so pass in nServices=NODE_NONE to CAddress. */ - OpenNetworkConnection(CAddress(vserv[i % vserv.size()], NODE_NONE), false, &grant); - MilliSleep(500); - } MilliSleep(120000); // Retry every 2 minutes } } diff --git a/src/net.h b/src/net.h index 2aaca4888fde9..54a86d88dc887 100644 --- a/src/net.h +++ b/src/net.h @@ -818,4 +818,14 @@ class CBanDB /** Return a timestamp in the future (in microseconds) for exponentially distributed events. */ int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds); +struct AddedNodeInfo +{ + std::string strAddedNode; + CService resolvedAddress; + bool fConnected; + bool fInbound; +}; + +std::vector GetAddedNodeInfo(); + #endif // BITCOIN_NET_H diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index cae964e46df1e..b85c7b2e1aaa5 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -271,25 +271,22 @@ UniValue getaddednodeinfo(const UniValue& params, bool fHelp) { if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( - "getaddednodeinfo dns ( \"node\" )\n" + "getaddednodeinfo dummy ( \"node\" )\n" "\nReturns information about the given added node, or all added nodes\n" "(note that onetry addnodes are not listed here)\n" - "If dns is false, only a list of added nodes will be provided,\n" - "otherwise connected information will also be available.\n" "\nArguments:\n" - "1. dns (boolean, required) If false, only a list of added nodes will be provided, otherwise connected information will also be available.\n" + "1. dummy (boolean, required) Kept for historical purposes but ignored\n" "2. \"node\" (string, optional) If provided, return information about this specific node, otherwise all nodes are returned.\n" "\nResult:\n" "[\n" " {\n" - " \"addednode\" : \"192.168.0.201\", (string) The node ip address\n" + " \"addednode\" : \"192.168.0.201\", (string) The node ip address or name (as provided to addnode)\n" " \"connected\" : true|false, (boolean) If connected\n" - " \"addresses\" : [\n" + " \"addresses\" : [ (list of objects) Only when connected = true\n" " {\n" - " \"address\" : \"192.168.0.201:8333\", (string) The bitcoin server host and port\n" + " \"address\" : \"192.168.0.201:8333\", (string) The bitcoin server IP and port we're connected to\n" " \"connected\" : \"outbound\" (string) connection, inbound or outbound\n" " }\n" - " ,...\n" " ]\n" " }\n" " ,...\n" @@ -300,83 +297,35 @@ UniValue getaddednodeinfo(const UniValue& params, bool fHelp) + HelpExampleRpc("getaddednodeinfo", "true, \"192.168.0.201\"") ); - bool fDns = params[0].get_bool(); + std::vector vInfo = GetAddedNodeInfo(); - list laddedNodes(0); - if (params.size() == 1) - { - LOCK(cs_vAddedNodes); - BOOST_FOREACH(const std::string& strAddNode, vAddedNodes) - laddedNodes.push_back(strAddNode); - } - else - { - string strNode = params[1].get_str(); - LOCK(cs_vAddedNodes); - BOOST_FOREACH(const std::string& strAddNode, vAddedNodes) { - if (strAddNode == strNode) - { - laddedNodes.push_back(strAddNode); + if (params.size() == 2) { + bool found = false; + for (const AddedNodeInfo& info : vInfo) { + if (info.strAddedNode == params[1].get_str()) { + vInfo.assign(1, info); + found = true; break; } } - if (laddedNodes.size() == 0) + if (!found) { throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added."); - } - - UniValue ret(UniValue::VARR); - if (!fDns) - { - BOOST_FOREACH (const std::string& strAddNode, laddedNodes) { - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("addednode", strAddNode)); - ret.push_back(obj); } - return ret; } - list > > laddedAddreses(0); - BOOST_FOREACH(const std::string& strAddNode, laddedNodes) { - vector vservNode(0); - if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0)) - laddedAddreses.push_back(make_pair(strAddNode, vservNode)); - else - { - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("addednode", strAddNode)); - obj.push_back(Pair("connected", false)); - UniValue addresses(UniValue::VARR); - obj.push_back(Pair("addresses", addresses)); - ret.push_back(obj); - } - } + UniValue ret(UniValue::VARR); - LOCK(cs_vNodes); - for (list > >::iterator it = laddedAddreses.begin(); it != laddedAddreses.end(); it++) - { + for (const AddedNodeInfo& info : vInfo) { UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("addednode", it->first)); - + obj.push_back(Pair("addednode", info.strAddedNode)); + obj.push_back(Pair("connected", info.fConnected)); UniValue addresses(UniValue::VARR); - bool fConnected = false; - BOOST_FOREACH(const CService& addrNode, it->second) { - bool fFound = false; - UniValue node(UniValue::VOBJ); - node.push_back(Pair("address", addrNode.ToString())); - BOOST_FOREACH(CNode* pnode, vNodes) { - if (pnode->addr == addrNode) - { - fFound = true; - fConnected = true; - node.push_back(Pair("connected", pnode->fInbound ? "inbound" : "outbound")); - break; - } - } - if (!fFound) - node.push_back(Pair("connected", "false")); - addresses.push_back(node); + if (info.fConnected) { + UniValue address(UniValue::VOBJ); + address.push_back(Pair("address", info.resolvedAddress.ToString())); + address.push_back(Pair("connected", info.fInbound ? "inbound" : "outbound")); + addresses.push_back(address); } - obj.push_back(Pair("connected", fConnected)); obj.push_back(Pair("addresses", addresses)); ret.push_back(obj); } From f9f5cfc50637f2cd1540923caf337e2651ec1625 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 28 May 2016 16:22:02 +0200 Subject: [PATCH 0479/1802] Prevent duplicate connections where one is by name and another by ip --- src/net.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/net.cpp b/src/net.cpp index 4d27db7604d0b..30a6bc896db22 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -400,6 +400,26 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure return NULL; } + if (pszDest && addrConnect.IsValid()) { + // It is possible that we already have a connection to the IP/port pszDest resolved to. + // In that case, drop the connection that was just created, and return the existing CNode instead. + // Also store the name we used to connect in that CNode, so that future FindNode() calls to that + // name catch this early. + CNode* pnode = FindNode((CService)addrConnect); + if (pnode) + { + pnode->AddRef(); + { + LOCK(cs_vNodes); + if (pnode->addrName.empty()) { + pnode->addrName = std::string(pszDest); + } + } + CloseSocket(hSocket); + return pnode; + } + } + addrman.Attempt(addrConnect, fCountFailure); // Add node From 1a5a4e648873c4cd88b936648ebf2858393e5510 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 28 May 2016 16:44:08 +0200 Subject: [PATCH 0480/1802] Randomize name lookup result in ConnectSocketByName --- src/netbase.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/netbase.cpp b/src/netbase.cpp index 572ae70871d40..e2a516986c116 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -621,10 +621,10 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest proxyType nameProxy; GetNameProxy(nameProxy); - CService addrResolved; - if (Lookup(strDest.c_str(), addrResolved, port, fNameLookup && !HaveNameProxy())) { - if (addrResolved.IsValid()) { - addr = addrResolved; + std::vector addrResolved; + if (Lookup(strDest.c_str(), addrResolved, port, fNameLookup && !HaveNameProxy(), 256)) { + if (addrResolved.size() > 0) { + addr = addrResolved[GetRand(addrResolved.size())]; return ConnectSocket(addr, hSocketRet, nTimeout); } } From afcd77e17936f7ec9bbf7b47f55a211eccc08364 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Mon, 13 Jun 2016 16:27:41 +0200 Subject: [PATCH 0481/1802] Detect -usehd mismatches when wallet.dat already exists --- src/wallet/wallet.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 1c212d01476dd..a4ffdfdb5299e 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3236,6 +3236,13 @@ bool CWallet::InitLoadWallet() walletInstance->SetBestChain(chainActive.GetLocator()); } + else if (mapArgs.count("-usehd")) { + bool useHD = GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET); + if (!walletInstance->hdChain.masterKeyID.IsNull() && !useHD) + return InitError(strprintf(_("Error loading %s: You can't disable HD on a already existing HD wallet"), walletFile)); + if (walletInstance->hdChain.masterKeyID.IsNull() && useHD) + return InitError(strprintf(_("Error loading %s: You can't enable HD on a already existing non-HD wallet"), walletFile)); + } LogPrintf(" wallet %15dms\n", GetTimeMillis() - nStart); From ab8be98fdb25b678a8cd7e89adf06d1b1f6bdd62 Mon Sep 17 00:00:00 2001 From: BtcDrak Date: Tue, 14 Jun 2016 12:26:59 +0100 Subject: [PATCH 0482/1802] Remove bad chain alert partition check As per meeting 2016-03-31 https://bitcoincore.org/en/meetings/2016/03/31/#bad-chain-alerts The partition checker was producing huge number of false-positives and was disabled in 0.12.1 on the understanding it would either be fixed in 0.13 or removed entirely from master if not. --- src/Makefile.test.include | 1 - src/init.cpp | 6 --- src/main.cpp | 62 ------------------------------ src/main.h | 2 - src/test/alert_tests.cpp | 79 --------------------------------------- 5 files changed, 150 deletions(-) delete mode 100644 src/test/alert_tests.cpp diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 41d811fb5400f..0b6f306f83e81 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -38,7 +38,6 @@ BITCOIN_TESTS =\ test/arith_uint256_tests.cpp \ test/scriptnum10.h \ test/addrman_tests.cpp \ - test/alert_tests.cpp \ test/amount_tests.cpp \ test/allocator_tests.cpp \ test/base32_tests.cpp \ diff --git a/src/init.cpp b/src/init.cpp index c2ba9ae44babe..323d1cedcf2e4 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1416,12 +1416,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) StartNode(threadGroup, scheduler); - // Monitor the chain, and alert if we get blocks much quicker or slower than expected - int64_t nPowTargetSpacing = Params().GetConsensus().nPowTargetSpacing; - CScheduler::Function f = boost::bind(&PartitionCheck, &IsInitialBlockDownload, - boost::ref(cs_main), boost::cref(pindexBestHeader), nPowTargetSpacing); - scheduler.scheduleEvery(f, nPowTargetSpacing); - // ********************************************************* Step 12: finished SetRPCWarmupFinished(); diff --git a/src/main.cpp b/src/main.cpp index 62012bf56709f..91da3f47a5905 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2118,68 +2118,6 @@ void ThreadScriptCheck() { scriptcheckqueue.Thread(); } -// -// Called periodically asynchronously; alerts if it smells like -// we're being fed a bad chain (blocks being generated much -// too slowly or too quickly). -// -void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const CBlockIndex *const &bestHeader, - int64_t nPowTargetSpacing) -{ - if (bestHeader == NULL || initialDownloadCheck()) return; - - static int64_t lastAlertTime = 0; - int64_t now = GetAdjustedTime(); - if (lastAlertTime > now-60*60*24) return; // Alert at most once per day - - const int SPAN_HOURS=4; - const int SPAN_SECONDS=SPAN_HOURS*60*60; - int BLOCKS_EXPECTED = SPAN_SECONDS / nPowTargetSpacing; - - boost::math::poisson_distribution poisson(BLOCKS_EXPECTED); - - std::string strWarning; - int64_t startTime = GetAdjustedTime()-SPAN_SECONDS; - - LOCK(cs); - const CBlockIndex* i = bestHeader; - int nBlocks = 0; - while (i->GetBlockTime() >= startTime) { - ++nBlocks; - i = i->pprev; - if (i == NULL) return; // Ran out of chain, we must not be fully sync'ed - } - - // How likely is it to find that many by chance? - double p = boost::math::pdf(poisson, nBlocks); - - LogPrint("partitioncheck", "%s: Found %d blocks in the last %d hours\n", __func__, nBlocks, SPAN_HOURS); - LogPrint("partitioncheck", "%s: likelihood: %g\n", __func__, p); - - // Aim for one false-positive about every fifty years of normal running: - const int FIFTY_YEARS = 50*365*24*60*60; - double alertThreshold = 1.0 / (FIFTY_YEARS / SPAN_SECONDS); - - if (p <= alertThreshold && nBlocks < BLOCKS_EXPECTED) - { - // Many fewer blocks than expected: alert! - strWarning = strprintf(_("WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)"), - nBlocks, SPAN_HOURS, BLOCKS_EXPECTED); - } - else if (p <= alertThreshold && nBlocks > BLOCKS_EXPECTED) - { - // Many more blocks than expected: alert! - strWarning = strprintf(_("WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)"), - nBlocks, SPAN_HOURS, BLOCKS_EXPECTED); - } - if (!strWarning.empty()) - { - strMiscWarning = strWarning; - AlertNotify(strWarning); - lastAlertTime = now; - } -} - // Protected by cs_main VersionBitsCache versionbitscache; diff --git a/src/main.h b/src/main.h index 9b99ae7c870be..05f7d4d9204a0 100644 --- a/src/main.h +++ b/src/main.h @@ -242,8 +242,6 @@ bool ProcessMessages(CNode* pfrom); bool SendMessages(CNode* pto); /** Run an instance of the script checking thread */ void ThreadScriptCheck(); -/** Try to detect Partition (network isolation) attacks against us */ -void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const CBlockIndex *const &bestHeader, int64_t nPowTargetSpacing); /** Check whether we are doing an initial block download (synchronizing from disk or network) */ bool IsInitialBlockDownload(); /** Format a string that describes several potential problems detected by the core. diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp deleted file mode 100644 index 70f1f12273a82..0000000000000 --- a/src/test/alert_tests.cpp +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) 2013-2015 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -// Unit tests for alert system - -#include "chainparams.h" -#include "main.h" // For PartitionCheck - -#include "test/testutil.h" -#include "test/test_bitcoin.h" - -#include - -BOOST_FIXTURE_TEST_SUITE(Alert_tests, TestingSetup) - - -static bool falseFunc() { return false; } - -BOOST_AUTO_TEST_CASE(PartitionAlert) -{ - // Test PartitionCheck - CCriticalSection csDummy; - CBlockIndex indexDummy[100]; - CChainParams& params = Params(CBaseChainParams::MAIN); - int64_t nPowTargetSpacing = params.GetConsensus().nPowTargetSpacing; - - // Generate fake blockchain timestamps relative to - // an arbitrary time: - int64_t now = 1427379054; - SetMockTime(now); - for (int i = 0; i < 100; i++) - { - indexDummy[i].phashBlock = NULL; - if (i == 0) indexDummy[i].pprev = NULL; - else indexDummy[i].pprev = &indexDummy[i-1]; - indexDummy[i].nHeight = i; - indexDummy[i].nTime = now - (100-i)*nPowTargetSpacing; - // Other members don't matter, the partition check code doesn't - // use them - } - - strMiscWarning = ""; - - // Test 1: chain with blocks every nPowTargetSpacing seconds, - // as normal, no worries: - PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); - BOOST_CHECK_MESSAGE(strMiscWarning.empty(), strMiscWarning); - - // Test 2: go 3.5 hours without a block, expect a warning: - now += 3*60*60+30*60; - SetMockTime(now); - PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); - BOOST_CHECK(!strMiscWarning.empty()); - BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning); - strMiscWarning = ""; - - // Test 3: test the "partition alerts only go off once per day" - // code: - now += 60*10; - SetMockTime(now); - PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); - BOOST_CHECK(strMiscWarning.empty()); - - // Test 4: get 2.5 times as many blocks as expected: - now += 60*60*24; // Pretend it is a day later - SetMockTime(now); - int64_t quickSpacing = nPowTargetSpacing*2/5; - for (int i = 0; i < 100; i++) // Tweak chain timestamps: - indexDummy[i].nTime = now - (100-i)*quickSpacing; - PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); - BOOST_CHECK(!strMiscWarning.empty()); - BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning); - strMiscWarning = ""; - - SetMockTime(0); -} - -BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file From d80efec3273dfdb88a434474be644cc5c788b617 Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Wed, 15 Jun 2016 00:11:39 -0400 Subject: [PATCH 0483/1802] Update petertodd's testnet seed New seed with servicebit filtering support. --- src/chainparams.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 0005115671122..442bc61023826 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -207,7 +207,7 @@ class CTestNetParams : public CChainParams { vSeeds.clear(); // nodes with support for servicebits filtering should be at the top vSeeds.push_back(CDNSSeedData("testnetbitcoin.jonasschnelli.ch", "testnet-seed.bitcoin.jonasschnelli.ch", true)); - vSeeds.push_back(CDNSSeedData("bitcoin.petertodd.org", "testnet-seed.bitcoin.petertodd.org")); + vSeeds.push_back(CDNSSeedData("petertodd.org", "seed.tbtc.petertodd.org", true)); vSeeds.push_back(CDNSSeedData("bluematt.me", "testnet-seed.bluematt.me")); vSeeds.push_back(CDNSSeedData("bitcoin.schildbach.de", "testnet-seed.bitcoin.schildbach.de")); From 11cc143895e730002749f0881c4c95635fa54bd5 Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Sat, 11 Jun 2016 00:26:16 +0000 Subject: [PATCH 0484/1802] Adds an expiration time for orphan tx. This prevents higher order orphans and other junk from holding positions in the orphan map. Parents delayed twenty minutes are more are unlikely to ever arrive. The freed space will improve the orphan matching success rate for other transactions. --- src/main.cpp | 23 ++++++++++++++++++++++- src/main.h | 4 ++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index c80a4ac922c83..44d96d614e278 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -100,6 +100,7 @@ struct IteratorComparator struct COrphanTx { CTransaction tx; NodeId fromPeer; + int64_t nTimeExpire; }; map mapOrphanTransactions GUARDED_BY(cs_main); map::iterator, IteratorComparator>> mapOrphanTransactionsByPrev GUARDED_BY(cs_main); @@ -641,7 +642,7 @@ bool AddOrphanTx(const CTransaction& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(c return false; } - auto ret = mapOrphanTransactions.emplace(hash, COrphanTx{tx, peer}); + auto ret = mapOrphanTransactions.emplace(hash, COrphanTx{tx, peer, GetTime() + ORPHAN_TX_EXPIRE_TIME}); assert(ret.second); BOOST_FOREACH(const CTxIn& txin, tx.vin) { mapOrphanTransactionsByPrev[txin.prevout].insert(ret.first); @@ -689,6 +690,26 @@ void EraseOrphansFor(NodeId peer) unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { unsigned int nEvicted = 0; + static int64_t nNextSweep; + int64_t nNow = GetTime(); + if (nNextSweep <= nNow) { + // Sweep out expired orphan pool entries: + int nErased = 0; + int64_t nMinExpTime = nNow + ORPHAN_TX_EXPIRE_TIME - ORPHAN_TX_EXPIRE_INTERVAL; + map::iterator iter = mapOrphanTransactions.begin(); + while (iter != mapOrphanTransactions.end()) + { + map::iterator maybeErase = iter++; + if (maybeErase->second.nTimeExpire <= nNow) { + nErased += EraseOrphanTx(maybeErase->second.tx.GetHash()); + } else { + nMinExpTime = std::min(maybeErase->second.nTimeExpire, nMinExpTime); + } + } + // Sweep again 5 minutes after the next entry that expires in order to batch the linear scan. + nNextSweep = nMinExpTime + ORPHAN_TX_EXPIRE_INTERVAL; + if (nErased > 0) LogPrint("mempool", "Erased %d orphan tx due to expiration\n", nErased); + } while (mapOrphanTransactions.size() > nMaxOrphans) { // Evict a random orphan: diff --git a/src/main.h b/src/main.h index 9b99ae7c870be..191aafe043546 100644 --- a/src/main.h +++ b/src/main.h @@ -56,6 +56,10 @@ static const CAmount HIGH_TX_FEE_PER_KB = 0.01 * COIN; static const CAmount HIGH_MAX_TX_FEE = 100 * HIGH_TX_FEE_PER_KB; /** Default for -maxorphantx, maximum number of orphan transactions kept in memory */ static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS = 100; +/** Expiration time for orphan transactions in seconds */ +static const int64_t ORPHAN_TX_EXPIRE_TIME = 20 * 60; +/** Minimum time between orphan transactions expire time checks in seconds */ +static const int64_t ORPHAN_TX_EXPIRE_INTERVAL = 5 * 60; /** Default for -limitancestorcount, max number of in-mempool ancestors */ static const unsigned int DEFAULT_ANCESTOR_LIMIT = 25; /** Default for -limitancestorsize, maximum kilobytes of tx + all in-mempool ancestors */ From 8c99d1b525562ab3b733e9d7ef770882646bad5c Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Mon, 13 Jun 2016 17:27:44 +0000 Subject: [PATCH 0485/1802] Treat orphans as implicit inv for parents, discard when parents rejected. An orphan whos parents were rejected is never going to connect, so there is little utility in keeping it. Orphans also helpfully tell us what we're missing, so go ahead and treat it as INVed. --- src/main.cpp | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 44d96d614e278..6a2290bc05e24 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5156,13 +5156,29 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } else if (fMissingInputs) { - AddOrphanTx(tx, pfrom->GetId()); + bool fRejectedParents = false; // It may be the case that the orphans parents have all been rejected + BOOST_FOREACH(const CTxIn& txin, tx.vin) { + if (recentRejects->contains(txin.prevout.hash)) { + fRejectedParents = true; + break; + } + } + if (!fRejectedParents) { + BOOST_FOREACH(const CTxIn& txin, tx.vin) { + CInv inv(MSG_TX, txin.prevout.hash); + pfrom->AddInventoryKnown(inv); + if (!AlreadyHave(inv)) pfrom->AskFor(inv); + } + AddOrphanTx(tx, pfrom->GetId()); - // DoS prevention: do not allow mapOrphanTransactions to grow unbounded - unsigned int nMaxOrphanTx = (unsigned int)std::max((int64_t)0, GetArg("-maxorphantx", DEFAULT_MAX_ORPHAN_TRANSACTIONS)); - unsigned int nEvicted = LimitOrphanTxSize(nMaxOrphanTx); - if (nEvicted > 0) - LogPrint("mempool", "mapOrphan overflow, removed %u tx\n", nEvicted); + // DoS prevention: do not allow mapOrphanTransactions to grow unbounded + unsigned int nMaxOrphanTx = (unsigned int)std::max((int64_t)0, GetArg("-maxorphantx", DEFAULT_MAX_ORPHAN_TRANSACTIONS)); + unsigned int nEvicted = LimitOrphanTxSize(nMaxOrphanTx); + if (nEvicted > 0) + LogPrint("mempool", "mapOrphan overflow, removed %u tx\n", nEvicted); + } else { + LogPrint("mempool", "not keeping orphan with rejected parents %s\n",tx.GetHash().ToString()); + } } else { assert(recentRejects); recentRejects->insert(tx.GetHash()); From 54326a6808a7026eef9d3a26f91f93b77f00a793 Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Sat, 11 Jun 2016 00:28:48 +0000 Subject: [PATCH 0486/1802] Increase maximum orphan size to 100,000 bytes. Although this increases node memory usage in the worst case by perhaps 30MB, the current behavior causes severe issues with dependent tx relay. --- src/main.cpp | 6 +++--- src/test/DoS_tests.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 6a2290bc05e24..d4ab32744f022 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -633,10 +633,10 @@ bool AddOrphanTx(const CTransaction& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(c // large transaction with a missing parent then we assume // it will rebroadcast it later, after the parent transaction(s) // have been mined or received. - // 10,000 orphans, each of which is at most 5,000 bytes big is - // at most 500 megabytes of orphans: + // 100 orphans, each of which is at most 99,999 bytes big is + // at most 10 megabytes of orphans and somewhat more byprev index (in the worst case): unsigned int sz = tx.GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION); - if (sz > 5000) + if (sz >= MAX_STANDARD_TX_SIZE) { LogPrint("mempool", "ignoring large orphan tx (size: %u, hash: %s)\n", sz, hash.ToString()); return false; diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index 95342498fa782..818128d186c11 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -162,7 +162,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) tx.vout.resize(1); tx.vout[0].nValue = 1*CENT; tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID()); - tx.vin.resize(500); + tx.vin.resize(2777); for (unsigned int j = 0; j < tx.vin.size(); j++) { tx.vin[j].prevout.n = j; From bc0a895d810107132651c8178e95a981b9f3ff74 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 15 Jun 2016 19:31:28 +0200 Subject: [PATCH 0487/1802] Do not set extra flags for unfiltered DNS seed results --- src/chainparams.cpp | 8 -------- src/chainparams.h | 4 +--- src/net.cpp | 14 +++++++++++++- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 0005115671122..8c27a578bb948 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -16,14 +16,6 @@ #include "chainparamsseeds.h" -std::string CDNSSeedData::getHost(uint64_t requiredServiceBits) const { - //use default host for non-filter-capable seeds or if we use the default service bits (NODE_NETWORK) - if (!supportsServiceBitsFiltering || requiredServiceBits == NODE_NETWORK) - return host; - - return strprintf("x%x.%s", requiredServiceBits, host); -} - static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesisOutputScript, uint32_t nTime, uint32_t nNonce, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward) { CMutableTransaction txNew; diff --git a/src/chainparams.h b/src/chainparams.h index 7168daaf4347c..638893e9ad9b4 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -13,11 +13,9 @@ #include -class CDNSSeedData { -public: +struct CDNSSeedData { std::string name, host; bool supportsServiceBitsFiltering; - std::string getHost(uint64_t requiredServiceBits) const; CDNSSeedData(const std::string &strName, const std::string &strHost, bool supportsServiceBitsFilteringIn = false) : name(strName), host(strHost), supportsServiceBitsFiltering(supportsServiceBitsFilteringIn) {} }; diff --git a/src/net.cpp b/src/net.cpp index a390eca776f52..5e791291c7529 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1415,6 +1415,18 @@ void MapPort(bool) +static std::string GetDNSHost(const CDNSSeedData& data, ServiceFlags* requiredServiceBits) +{ + //use default host for non-filter-capable seeds or if we use the default service bits (NODE_NETWORK) + if (!data.supportsServiceBitsFiltering || *requiredServiceBits == NODE_NETWORK) { + *requiredServiceBits = NODE_NETWORK; + return data.host; + } + + return strprintf("x%x.%s", *requiredServiceBits, data.host); +} + + void ThreadDNSAddressSeed() { // goal: only query DNS seeds if address need is acute @@ -1441,7 +1453,7 @@ void ThreadDNSAddressSeed() std::vector vIPs; std::vector vAdd; ServiceFlags requiredServiceBits = nRelevantServices; - if (LookupHost(seed.getHost(requiredServiceBits).c_str(), vIPs, 0, true)) + if (LookupHost(GetDNSHost(seed, &requiredServiceBits).c_str(), vIPs, 0, true)) { BOOST_FOREACH(const CNetAddr& ip, vIPs) { From 5d0ca81f7422b7eac0a5129c6fbccad77e36b85d Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Sun, 22 May 2016 05:55:15 +0000 Subject: [PATCH 0488/1802] Add recently accepted blocks and txn to AttemptToEvictConnection. This protects any not-already-protected peers who were the most recent four to relay transactions and most recent four to send blocks to us. --- src/main.cpp | 16 +++++++++++----- src/main.h | 2 +- src/net.cpp | 48 ++++++++++++++++++++++++++++++++++++++++++++---- src/net.h | 5 +++++ 4 files changed, 61 insertions(+), 10 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 6d006e8789db1..24ae61b74de2d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3449,8 +3449,9 @@ static bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state } /** Store block on disk. If dbp is non-NULL, the file is known to already reside on disk */ -static bool AcceptBlock(const CBlock& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const CDiskBlockPos* dbp) +static bool AcceptBlock(const CBlock& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const CDiskBlockPos* dbp, bool* fNewBlock) { + if (fNewBlock) *fNewBlock = false; AssertLockHeld(cs_main); CBlockIndex *pindexDummy = NULL; @@ -3479,6 +3480,7 @@ static bool AcceptBlock(const CBlock& block, CValidationState& state, const CCha if (!fHasMoreWork) return true; // Don't process less-work chains if (fTooFarAhead) return true; // Block height is too high } + if (fNewBlock) *fNewBlock = true; if ((!CheckBlock(block, state, chainparams.GetConsensus(), GetAdjustedTime())) || !ContextualCheckBlock(block, state, pindex->pprev)) { if (state.IsInvalid() && !state.CorruptionPossible()) { @@ -3526,7 +3528,7 @@ static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned } -bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, const CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp) +bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp) { { LOCK(cs_main); @@ -3535,9 +3537,11 @@ bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, c // Store to disk CBlockIndex *pindex = NULL; - bool ret = AcceptBlock(*pblock, state, chainparams, &pindex, fRequested, dbp); + bool fNewBlock = false; + bool ret = AcceptBlock(*pblock, state, chainparams, &pindex, fRequested, dbp, &fNewBlock); if (pindex && pfrom) { mapBlockSource[pindex->GetBlockHash()] = pfrom->GetId(); + if (fNewBlock) pfrom->nLastBlockTime = GetTime(); } CheckBlockIndex(chainparams.GetConsensus()); if (!ret) @@ -4107,7 +4111,7 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB if (mapBlockIndex.count(hash) == 0 || (mapBlockIndex[hash]->nStatus & BLOCK_HAVE_DATA) == 0) { LOCK(cs_main); CValidationState state; - if (AcceptBlock(block, state, chainparams, NULL, true, dbp)) + if (AcceptBlock(block, state, chainparams, NULL, true, dbp, NULL)) nLoaded++; if (state.IsError()) break; @@ -4140,7 +4144,7 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB head.ToString()); LOCK(cs_main); CValidationState dummy; - if (AcceptBlock(block, dummy, chainparams, NULL, true, &it->second)) + if (AcceptBlock(block, dummy, chainparams, NULL, true, &it->second, NULL)) { nLoaded++; queue.push_back(block.GetHash()); @@ -5040,6 +5044,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, RelayTransaction(tx); vWorkQueue.push_back(inv.hash); + pfrom->nLastTXTime = GetTime(); + LogPrint("mempool", "AcceptToMemoryPool: peer=%d: accepted %s (poolsz %u txn, %u kB)\n", pfrom->id, tx.GetHash().ToString(), diff --git a/src/main.h b/src/main.h index 9b99ae7c870be..e2bfdfdf6ee36 100644 --- a/src/main.h +++ b/src/main.h @@ -215,7 +215,7 @@ void UnregisterNodeSignals(CNodeSignals& nodeSignals); * @param[out] dbp The already known disk position of pblock, or NULL if not yet stored. * @return True if state.IsValid() */ -bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, const CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp); +bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp); /** Check whether enough disk space is available for an incoming block */ bool CheckDiskSpace(uint64_t nAdditionalBytes = 0); /** Open a block file (blk?????.dat) */ diff --git a/src/net.cpp b/src/net.cpp index 173eba57c8669..ec547e8c998eb 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -838,6 +838,11 @@ struct NodeEvictionCandidate NodeId id; int64_t nTimeConnected; int64_t nMinPingUsecTime; + int64_t nLastBlockTime; + int64_t nLastTXTime; + bool fNetworkNode; + bool fRelayTxes; + bool fBloomFilter; CAddress addr; uint64_t nKeyedNetGroup; }; @@ -854,7 +859,24 @@ static bool ReverseCompareNodeTimeConnected(const NodeEvictionCandidate &a, cons static bool CompareNetGroupKeyed(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b) { return a.nKeyedNetGroup < b.nKeyedNetGroup; -}; +} + +static bool CompareNodeBlockTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b) +{ + // There is a fall-through here because it is common for a node to have many peers which have not yet relayed a block. + if (a.nLastBlockTime != b.nLastBlockTime) return a.nLastBlockTime < b.nLastBlockTime; + if (a.fNetworkNode != b.fNetworkNode) return b.fNetworkNode; + return a.nTimeConnected > b.nTimeConnected; +} + +static bool CompareNodeTXTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b) +{ + // There is a fall-through here because it is common for a node to have more than a few peers that have not yet relayed txn. + if (a.nLastTXTime != b.nLastTXTime) return a.nLastTXTime < b.nLastTXTime; + if (a.fRelayTxes != b.fRelayTxes) return b.fRelayTxes; + if (a.fBloomFilter != b.fBloomFilter) return a.fBloomFilter; + return a.nTimeConnected > b.nTimeConnected; +} /** Try to find a connection to evict when the node is full. * Extreme care must be taken to avoid opening the node to attacker @@ -864,7 +886,7 @@ static bool CompareNetGroupKeyed(const NodeEvictionCandidate &a, const NodeEvict * to forge. In order to partition a node the attacker must be * simultaneously better at all of them than honest peers. */ -static bool AttemptToEvictConnection(bool fPreferNewConnection) { +static bool AttemptToEvictConnection() { std::vector vEvictionCandidates; { LOCK(cs_vNodes); @@ -876,7 +898,9 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) { continue; if (node->fDisconnect) continue; - NodeEvictionCandidate candidate = {node->id, node->nTimeConnected, node->nMinPingUsecTime, node->addr, node->nKeyedNetGroup}; + NodeEvictionCandidate candidate = {node->id, node->nTimeConnected, node->nMinPingUsecTime, + node->nLastBlockTime, node->nLastTXTime, node->fNetworkNode, + node->fRelayTxes, node->pfilter != NULL, node->addr, node->nKeyedNetGroup}; vEvictionCandidates.push_back(candidate); } } @@ -899,6 +923,20 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) { if (vEvictionCandidates.empty()) return false; + // Protect 4 nodes that most recently sent us transactions. + // An attacker cannot manipulate this metric without performing useful work. + std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), CompareNodeTXTime); + vEvictionCandidates.erase(vEvictionCandidates.end() - std::min(4, static_cast(vEvictionCandidates.size())), vEvictionCandidates.end()); + + if (vEvictionCandidates.empty()) return false; + + // Protect 4 nodes that most recently sent us blocks. + // An attacker cannot manipulate this metric without performing useful work. + std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), CompareNodeBlockTime); + vEvictionCandidates.erase(vEvictionCandidates.end() - std::min(4, static_cast(vEvictionCandidates.size())), vEvictionCandidates.end()); + + if (vEvictionCandidates.empty()) return false; + // Protect the half of the remaining nodes which have been connected the longest. // This replicates the non-eviction implicit behavior, and precludes attacks that start later. std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), ReverseCompareNodeTimeConnected); @@ -999,7 +1037,7 @@ static void AcceptConnection(const ListenSocket& hListenSocket) { if (nInbound >= nMaxInbound) { - if (!AttemptToEvictConnection(whitelisted)) { + if (!AttemptToEvictConnection()) { // No connection to evict, disconnect the new connection LogPrint("net", "failed to find an eviction candidate - connection dropped (full)\n"); CloseSocket(hSocket); @@ -2358,6 +2396,8 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa fSentAddr = false; pfilter = new CBloomFilter(); timeLastMempoolReq = 0; + nLastBlockTime = 0; + nLastTXTime = 0; nPingNonceSent = 0; nPingUsecStart = 0; nPingUsecTime = 0; diff --git a/src/net.h b/src/net.h index 5c1f7e3e89cbc..2f96c58e305d4 100644 --- a/src/net.h +++ b/src/net.h @@ -416,6 +416,11 @@ class CNode // Last time a "MEMPOOL" request was serviced. std::atomic timeLastMempoolReq; + + // Block and TXN accept times + std::atomic nLastBlockTime; + std::atomic nLastTXTime; + // Ping time measurement: // The pong reply we're expecting, or 0 if no pong expected. uint64_t nPingNonceSent; From 6ee7f05622c32431a9815a96b31a6a65a821fdcc Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Fri, 10 Jun 2016 03:02:01 +0000 Subject: [PATCH 0489/1802] Allow disconnecting a netgroup with only one member in eviction. With the latest additions there are enough protective measures that we can take the training wheels off. --- src/net.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index ec547e8c998eb..89eb55ae94f1b 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -965,13 +965,6 @@ static bool AttemptToEvictConnection() { // Reduce to the network group with the most connections vEvictionCandidates = std::move(mapAddrCounts[naMostConnections]); - // Do not disconnect peers if there is only one unprotected connection from their network group. - // This step excessively favors netgroup diversity, and should be removed once more protective criteria are established. - if (vEvictionCandidates.size() <= 1) - // unless we prefer the new connection (for whitelisted peers) - if (!fPreferNewConnection) - return false; - // Disconnect from the network group with the most connections NodeId evicted = vEvictionCandidates.front().id; LOCK(cs_vNodes); From fa58e5ee93b8ab7a5a71cd232d829233ee7f2f56 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 16 Jun 2016 10:10:03 +0200 Subject: [PATCH 0490/1802] [doc] Add website links to about dialog --- src/init.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/init.cpp b/src/init.cpp index c2ba9ae44babe..b572bfc32720a 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -479,11 +479,20 @@ std::string HelpMessage(HelpMessageMode mode) std::string LicenseInfo() { + const std::string URL_SOURCE_CODE = ""; + const std::string URL_WEBSITE = ""; // todo: remove urls from translations on next change return CopyrightHolders(strprintf(_("Copyright (C) %i-%i"), 2009, COPYRIGHT_YEAR) + " ") + "\n" + "\n" + - _("This is experimental software.") + "\n" + + strprintf(_("Please contribute if you find %s useful. " + "Visit %s for further information about the software."), + PACKAGE_NAME, URL_WEBSITE) + + "\n" + + strprintf(_("The source code is available from %s."), + URL_SOURCE_CODE) + "\n" + + "\n" + + _("This is experimental software.") + "\n" + _("Distributed under the MIT software license, see the accompanying file COPYING or .") + "\n" + "\n" + _("This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.") + From c82a4e9a63a28fc8c482c7c8e5b7bfcc51a6805a Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Sat, 20 Feb 2016 21:02:44 -0500 Subject: [PATCH 0491/1802] Use ancestor-feerate based transaction selection for mining Includes changes by Pieter Wuille --- src/miner.cpp | 206 +++++++++++++++++++++++++++++++++++++++++++++++++- src/miner.h | 118 +++++++++++++++++++++++++++++ 2 files changed, 323 insertions(+), 1 deletion(-) diff --git a/src/miner.cpp b/src/miner.cpp index 99eb0a2ebd0f7..989ad11a2614d 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -25,6 +25,7 @@ #include "utilmoneystr.h" #include "validationinterface.h" +#include #include #include #include @@ -134,7 +135,7 @@ CBlockTemplate* BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn) : pblock->GetBlockTime(); addPriorityTxs(); - addScoreTxs(); + addPackageTxs(); nLastBlockTx = nBlockTx; nLastBlockSize = nBlockSize; @@ -177,7 +178,38 @@ bool BlockAssembler::isStillDependent(CTxMemPool::txiter iter) return false; } +void BlockAssembler::onlyUnconfirmed(CTxMemPool::setEntries& testSet) +{ + for (CTxMemPool::setEntries::iterator iit = testSet.begin(); iit != testSet.end(); ) { + // Only test txs not already in the block + if (inBlock.count(*iit)) { + testSet.erase(iit++); + } + else { + iit++; + } + } +} + +bool BlockAssembler::TestPackage(uint64_t packageSize, unsigned int packageSigOps) +{ + if (nBlockSize + packageSize >= nBlockMaxSize) + return false; + if (nBlockSigOps + packageSigOps >= MAX_BLOCK_SIGOPS) + return false; + return true; +} +// Block size and sigops have already been tested. Check that all transactions +// are final. +bool BlockAssembler::TestPackageFinality(const CTxMemPool::setEntries& package) +{ + BOOST_FOREACH (const CTxMemPool::txiter it, package) { + if (!IsFinalTx(it->GetTx(), nHeight, nLockTimeCutoff)) + return false; + } + return true; +} bool BlockAssembler::TestForBlock(CTxMemPool::txiter iter) { @@ -297,6 +329,178 @@ void BlockAssembler::addScoreTxs() } } +void BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& alreadyAdded, + indexed_modified_transaction_set &mapModifiedTx) +{ + BOOST_FOREACH(const CTxMemPool::txiter it, alreadyAdded) { + CTxMemPool::setEntries descendants; + mempool.CalculateDescendants(it, descendants); + // Insert all descendants (not yet in block) into the modified set + BOOST_FOREACH(CTxMemPool::txiter desc, descendants) { + if (alreadyAdded.count(desc)) + continue; + modtxiter mit = mapModifiedTx.find(desc); + if (mit == mapModifiedTx.end()) { + CTxMemPoolModifiedEntry modEntry(desc); + modEntry.nSizeWithAncestors -= it->GetTxSize(); + modEntry.nModFeesWithAncestors -= it->GetModifiedFee(); + modEntry.nSigOpCountWithAncestors -= it->GetSigOpCount(); + mapModifiedTx.insert(modEntry); + } else { + mapModifiedTx.modify(mit, update_for_parent_inclusion(it)); + } + } + } +} + +// Skip entries in mapTx that are already in a block or are present +// in mapModifiedTx (which implies that the mapTx ancestor state is +// stale due to ancestor inclusion in the block) +// Also skip transactions that we've already failed to add. This can happen if +// we consider a transaction in mapModifiedTx and it fails: we can then +// potentially consider it again while walking mapTx. It's currently +// guaranteed to fail again, but as a belt-and-suspenders check we put it in +// failedTx and avoid re-evaluation, since the re-evaluation would be using +// cached size/sigops/fee values that are not actually correct. +bool BlockAssembler::SkipMapTxEntry(CTxMemPool::txiter it, indexed_modified_transaction_set &mapModifiedTx, CTxMemPool::setEntries &failedTx) +{ + assert (it != mempool.mapTx.end()); + if (mapModifiedTx.count(it) || inBlock.count(it) || failedTx.count(it)) + return true; + return false; +} + +void BlockAssembler::SortForBlock(const CTxMemPool::setEntries& package, CTxMemPool::txiter entry, std::vector& sortedEntries) +{ + // Sort package by ancestor count + // If a transaction A depends on transaction B, then A's ancestor count + // must be greater than B's. So this is sufficient to validly order the + // transactions for block inclusion. + sortedEntries.clear(); + sortedEntries.insert(sortedEntries.begin(), package.begin(), package.end()); + std::sort(sortedEntries.begin(), sortedEntries.end(), CompareTxIterByAncestorCount()); +} + +// This transaction selection algorithm orders the mempool based +// on feerate of a transaction including all unconfirmed ancestors. +// Since we don't remove transactions from the mempool as we select them +// for block inclusion, we need an alternate method of updating the feerate +// of a transaction with its not-yet-selected ancestors as we go. +// This is accomplished by walking the in-mempool descendants of selected +// transactions and storing a temporary modified state in mapModifiedTxs. +// Each time through the loop, we compare the best transaction in +// mapModifiedTxs with the next transaction in the mempool to decide what +// transaction package to work on next. +void BlockAssembler::addPackageTxs() +{ + // mapModifiedTx will store sorted packages after they are modified + // because some of their txs are already in the block + indexed_modified_transaction_set mapModifiedTx; + // Keep track of entries that failed inclusion, to avoid duplicate work + CTxMemPool::setEntries failedTx; + + // Start by adding all descendants of previously added txs to mapModifiedTx + // and modifying them for their already included ancestors + UpdatePackagesForAdded(inBlock, mapModifiedTx); + + CTxMemPool::indexed_transaction_set::index::type::iterator mi = mempool.mapTx.get().begin(); + CTxMemPool::txiter iter; + while (mi != mempool.mapTx.get().end() || !mapModifiedTx.empty()) + { + // First try to find a new transaction in mapTx to evaluate. + if (mi != mempool.mapTx.get().end() && + SkipMapTxEntry(mempool.mapTx.project<0>(mi), mapModifiedTx, failedTx)) { + ++mi; + continue; + } + + // Now that mi is not stale, determine which transaction to evaluate: + // the next entry from mapTx, or the best from mapModifiedTx? + bool fUsingModified = false; + + modtxscoreiter modit = mapModifiedTx.get().begin(); + if (mi == mempool.mapTx.get().end()) { + // We're out of entries in mapTx; use the entry from mapModifiedTx + iter = modit->iter; + fUsingModified = true; + } else { + // Try to compare the mapTx entry to the mapModifiedTx entry + iter = mempool.mapTx.project<0>(mi); + if (modit != mapModifiedTx.get().end() && + CompareModifiedEntry()(*modit, CTxMemPoolModifiedEntry(iter))) { + // The best entry in mapModifiedTx has higher score + // than the one from mapTx. + // Switch which transaction (package) to consider + iter = modit->iter; + fUsingModified = true; + } else { + // Either no entry in mapModifiedTx, or it's worse than mapTx. + // Increment mi for the next loop iteration. + ++mi; + } + } + + // We skip mapTx entries that are inBlock, and mapModifiedTx shouldn't + // contain anything that is inBlock. + assert(!inBlock.count(iter)); + + uint64_t packageSize = iter->GetSizeWithAncestors(); + CAmount packageFees = iter->GetModFeesWithAncestors(); + unsigned int packageSigOps = iter->GetSigOpCountWithAncestors(); + if (fUsingModified) { + packageSize = modit->nSizeWithAncestors; + packageFees = modit->nModFeesWithAncestors; + packageSigOps = modit->nSigOpCountWithAncestors; + } + + if (packageFees < ::minRelayTxFee.GetFee(packageSize) && nBlockSize >= nBlockMinSize) { + // Everything else we might consider has a lower fee rate + return; + } + + if (!TestPackage(packageSize, packageSigOps)) { + if (fUsingModified) { + // Since we always look at the best entry in mapModifiedTx, + // we must erase failed entries so that we can consider the + // next best entry on the next loop iteration + mapModifiedTx.get().erase(modit); + failedTx.insert(iter); + } + continue; + } + + CTxMemPool::setEntries ancestors; + uint64_t nNoLimit = std::numeric_limits::max(); + std::string dummy; + mempool.CalculateMemPoolAncestors(*iter, ancestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy, false); + + onlyUnconfirmed(ancestors); + ancestors.insert(iter); + + // Test if all tx's are Final + if (!TestPackageFinality(ancestors)) { + if (fUsingModified) { + mapModifiedTx.get().erase(modit); + failedTx.insert(iter); + } + continue; + } + + // Package can be added. Sort the entries in a valid order. + vector sortedEntries; + SortForBlock(ancestors, iter, sortedEntries); + + for (size_t i=0; i #include +#include "boost/multi_index_container.hpp" +#include "boost/multi_index/ordered_index.hpp" class CBlockIndex; class CChainParams; @@ -29,6 +31,104 @@ struct CBlockTemplate std::vector vTxSigOps; }; +// Container for tracking updates to ancestor feerate as we include (parent) +// transactions in a block +struct CTxMemPoolModifiedEntry { + CTxMemPoolModifiedEntry(CTxMemPool::txiter entry) + { + iter = entry; + nSizeWithAncestors = entry->GetSizeWithAncestors(); + nModFeesWithAncestors = entry->GetModFeesWithAncestors(); + nSigOpCountWithAncestors = entry->GetSigOpCountWithAncestors(); + } + + CTxMemPool::txiter iter; + uint64_t nSizeWithAncestors; + CAmount nModFeesWithAncestors; + unsigned int nSigOpCountWithAncestors; +}; + +/** Comparator for CTxMemPool::txiter objects. + * It simply compares the internal memory address of the CTxMemPoolEntry object + * pointed to. This means it has no meaning, and is only useful for using them + * as key in other indexes. + */ +struct CompareCTxMemPoolIter { + bool operator()(const CTxMemPool::txiter& a, const CTxMemPool::txiter& b) const + { + return &(*a) < &(*b); + } +}; + +struct modifiedentry_iter { + typedef CTxMemPool::txiter result_type; + result_type operator() (const CTxMemPoolModifiedEntry &entry) const + { + return entry.iter; + } +}; + +// This matches the calculation in CompareTxMemPoolEntryByAncestorFee, +// except operating on CTxMemPoolModifiedEntry. +// TODO: refactor to avoid duplication of this logic. +struct CompareModifiedEntry { + bool operator()(const CTxMemPoolModifiedEntry &a, const CTxMemPoolModifiedEntry &b) + { + double f1 = (double)a.nModFeesWithAncestors * b.nSizeWithAncestors; + double f2 = (double)b.nModFeesWithAncestors * a.nSizeWithAncestors; + if (f1 == f2) { + return CTxMemPool::CompareIteratorByHash()(a.iter, b.iter); + } + return f1 > f2; + } +}; + +// A comparator that sorts transactions based on number of ancestors. +// This is sufficient to sort an ancestor package in an order that is valid +// to appear in a block. +struct CompareTxIterByAncestorCount { + bool operator()(const CTxMemPool::txiter &a, const CTxMemPool::txiter &b) + { + if (a->GetCountWithAncestors() != b->GetCountWithAncestors()) + return a->GetCountWithAncestors() < b->GetCountWithAncestors(); + return CTxMemPool::CompareIteratorByHash()(a, b); + } +}; + +typedef boost::multi_index_container< + CTxMemPoolModifiedEntry, + boost::multi_index::indexed_by< + boost::multi_index::ordered_unique< + modifiedentry_iter, + CompareCTxMemPoolIter + >, + // sorted by modified ancestor fee rate + boost::multi_index::ordered_non_unique< + // Reuse same tag from CTxMemPool's similar index + boost::multi_index::tag, + boost::multi_index::identity, + CompareModifiedEntry + > + > +> indexed_modified_transaction_set; + +typedef indexed_modified_transaction_set::nth_index<0>::type::iterator modtxiter; +typedef indexed_modified_transaction_set::index::type::iterator modtxscoreiter; + +struct update_for_parent_inclusion +{ + update_for_parent_inclusion(CTxMemPool::txiter it) : iter(it) {} + + void operator() (CTxMemPoolModifiedEntry &e) + { + e.nModFeesWithAncestors -= iter->GetFee(); + e.nSizeWithAncestors -= iter->GetTxSize(); + e.nSigOpCountWithAncestors -= iter->GetSigOpCount(); + } + + CTxMemPool::txiter iter; +}; + /** Generate a new block, without valid proof-of-work */ class BlockAssembler { @@ -74,12 +174,30 @@ class BlockAssembler void addScoreTxs(); /** Add transactions based on tx "priority" */ void addPriorityTxs(); + /** Add transactions based on feerate including unconfirmed ancestors */ + void addPackageTxs(); // helper function for addScoreTxs and addPriorityTxs /** Test if tx will still "fit" in the block */ bool TestForBlock(CTxMemPool::txiter iter); /** Test if tx still has unconfirmed parents not yet in block */ bool isStillDependent(CTxMemPool::txiter iter); + + // helper functions for addPackageTxs() + /** Remove confirmed (inBlock) entries from given set */ + void onlyUnconfirmed(CTxMemPool::setEntries& testSet); + /** Test if a new package would "fit" in the block */ + bool TestPackage(uint64_t packageSize, unsigned int packageSigOps); + /** Test if a set of transactions are all final */ + bool TestPackageFinality(const CTxMemPool::setEntries& package); + /** Return true if given transaction from mapTx has already been evaluated, + * or if the transaction's cached data in mapTx is incorrect. */ + bool SkipMapTxEntry(CTxMemPool::txiter it, indexed_modified_transaction_set &mapModifiedTx, CTxMemPool::setEntries &failedTx); + /** Sort the package in an order that is valid to appear in a block */ + void SortForBlock(const CTxMemPool::setEntries& package, CTxMemPool::txiter entry, std::vector& sortedEntries); + /** Add descendants of given transactions to mapModifiedTx with ancestor + * state updated assuming given transactions are inBlock. */ + void UpdatePackagesForAdded(const CTxMemPool::setEntries& alreadyAdded, indexed_modified_transaction_set &mapModifiedTx); }; /** Modify the extranonce in a block */ From 29fac19c93fabfed4163ee9ffa85f9188c9ee6ac Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Sat, 20 Feb 2016 20:58:23 -0500 Subject: [PATCH 0492/1802] Add unit tests for ancestor feerate mining --- src/test/miner_tests.cpp | 109 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 3fb7967881bec..ca8d6d2e05baa 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -71,6 +71,113 @@ bool TestSequenceLocks(const CTransaction &tx, int flags) return CheckSequenceLocks(tx, flags); } +// Test suite for ancestor feerate transaction selection. +// Implemented as an additional function, rather than a separate test case, +// to allow reusing the blockchain created in CreateNewBlock_validity. +// Note that this test assumes blockprioritysize is 0. +void TestPackageSelection(const CChainParams& chainparams, CScript scriptPubKey, std::vector& txFirst) +{ + // Test the ancestor feerate transaction selection. + TestMemPoolEntryHelper entry; + + // Test that a medium fee transaction will be selected after a higher fee + // rate package with a low fee rate parent. + CMutableTransaction tx; + tx.vin.resize(1); + tx.vin[0].scriptSig = CScript() << OP_1; + tx.vin[0].prevout.hash = txFirst[0]->GetHash(); + tx.vin[0].prevout.n = 0; + tx.vout.resize(1); + tx.vout[0].nValue = 5000000000LL - 1000; + // This tx has a low fee: 1000 satoshis + uint256 hashParentTx = tx.GetHash(); // save this txid for later use + mempool.addUnchecked(hashParentTx, entry.Fee(1000).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); + + // This tx has a medium fee: 10000 satoshis + tx.vin[0].prevout.hash = txFirst[1]->GetHash(); + tx.vout[0].nValue = 5000000000LL - 10000; + uint256 hashMediumFeeTx = tx.GetHash(); + mempool.addUnchecked(hashMediumFeeTx, entry.Fee(10000).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); + + // This tx has a high fee, but depends on the first transaction + tx.vin[0].prevout.hash = hashParentTx; + tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 50k satoshi fee + uint256 hashHighFeeTx = tx.GetHash(); + mempool.addUnchecked(hashHighFeeTx, entry.Fee(50000).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); + + CBlockTemplate *pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey); + BOOST_CHECK(pblocktemplate->block.vtx[1].GetHash() == hashParentTx); + BOOST_CHECK(pblocktemplate->block.vtx[2].GetHash() == hashHighFeeTx); + BOOST_CHECK(pblocktemplate->block.vtx[3].GetHash() == hashMediumFeeTx); + + // Test that a package below the min relay fee doesn't get included + tx.vin[0].prevout.hash = hashHighFeeTx; + tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 0 fee + uint256 hashFreeTx = tx.GetHash(); + mempool.addUnchecked(hashFreeTx, entry.Fee(0).FromTx(tx)); + size_t freeTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); + + // Calculate a fee on child transaction that will put the package just + // below the min relay fee (assuming 1 child tx of the same size). + CAmount feeToUse = minRelayTxFee.GetFee(2*freeTxSize) - 1; + + tx.vin[0].prevout.hash = hashFreeTx; + tx.vout[0].nValue = 5000000000LL - 1000 - 50000 - feeToUse; + uint256 hashLowFeeTx = tx.GetHash(); + mempool.addUnchecked(hashLowFeeTx, entry.Fee(feeToUse).FromTx(tx)); + pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey); + // Verify that the free tx and the low fee tx didn't get selected + for (size_t i=0; iblock.vtx.size(); ++i) { + BOOST_CHECK(pblocktemplate->block.vtx[i].GetHash() != hashFreeTx); + BOOST_CHECK(pblocktemplate->block.vtx[i].GetHash() != hashLowFeeTx); + } + + // Test that packages above the min relay fee do get included, even if one + // of the transactions is below the min relay fee + // Remove the low fee transaction and replace with a higher fee transaction + std::list dummy; + mempool.removeRecursive(tx, dummy); + tx.vout[0].nValue -= 2; // Now we should be just over the min relay fee + hashLowFeeTx = tx.GetHash(); + mempool.addUnchecked(hashLowFeeTx, entry.Fee(feeToUse+2).FromTx(tx)); + pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey); + BOOST_CHECK(pblocktemplate->block.vtx[4].GetHash() == hashFreeTx); + BOOST_CHECK(pblocktemplate->block.vtx[5].GetHash() == hashLowFeeTx); + + // Test that transaction selection properly updates ancestor fee + // calculations as ancestor transactions get included in a block. + // Add a 0-fee transaction that has 2 outputs. + tx.vin[0].prevout.hash = txFirst[2]->GetHash(); + tx.vout.resize(2); + tx.vout[0].nValue = 5000000000LL - 100000000; + tx.vout[1].nValue = 100000000; // 1BTC output + uint256 hashFreeTx2 = tx.GetHash(); + mempool.addUnchecked(hashFreeTx2, entry.Fee(0).SpendsCoinbase(true).FromTx(tx)); + + // This tx can't be mined by itself + tx.vin[0].prevout.hash = hashFreeTx2; + tx.vout.resize(1); + feeToUse = minRelayTxFee.GetFee(freeTxSize); + tx.vout[0].nValue = 5000000000LL - 100000000 - feeToUse; + uint256 hashLowFeeTx2 = tx.GetHash(); + mempool.addUnchecked(hashLowFeeTx2, entry.Fee(feeToUse).SpendsCoinbase(false).FromTx(tx)); + pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey); + + // Verify that this tx isn't selected. + for (size_t i=0; iblock.vtx.size(); ++i) { + BOOST_CHECK(pblocktemplate->block.vtx[i].GetHash() != hashFreeTx2); + BOOST_CHECK(pblocktemplate->block.vtx[i].GetHash() != hashLowFeeTx2); + } + + // This tx will be mineable, and should cause hashLowFeeTx2 to be selected + // as well. + tx.vin[0].prevout.n = 1; + tx.vout[0].nValue = 100000000 - 10000; // 10k satoshi fee + mempool.addUnchecked(tx.GetHash(), entry.Fee(10000).FromTx(tx)); + pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey); + BOOST_CHECK(pblocktemplate->block.vtx[8].GetHash() == hashLowFeeTx2); +} + // NOTE: These tests rely on CreateNewBlock doing its own self-validation! BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) { @@ -385,6 +492,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) SetMockTime(0); mempool.clear(); + TestPackageSelection(chainparams, scriptPubKey, txFirst); + BOOST_FOREACH(CTransaction *_tx, txFirst) delete _tx; From f25209a3e1e6488d4d44de15b0f113d2302e9aee Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 9 Jun 2016 12:30:38 -0400 Subject: [PATCH 0493/1802] depends: bump OSX toolchain clang: 3.7.1 cctools: 877.8 ld64: 253.9 --- depends/hosts/darwin.mk | 4 ++-- depends/packages/native_cctools.mk | 20 +++++++++++--------- depends/packages/qt.mk | 1 + 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/depends/hosts/darwin.mk b/depends/hosts/darwin.mk index dbe6d00795e00..985649619ffec 100644 --- a/depends/hosts/darwin.mk +++ b/depends/hosts/darwin.mk @@ -1,7 +1,7 @@ OSX_MIN_VERSION=10.7 -OSX_SDK_VERSION=10.9 +OSX_SDK_VERSION=10.11 OSX_SDK=$(SDK_PATH)/MacOSX$(OSX_SDK_VERSION).sdk -LD64_VERSION=241.9 +LD64_VERSION=253.9 darwin_CC=clang -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION) darwin_CXX=clang++ -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION) -stdlib=libc++ diff --git a/depends/packages/native_cctools.mk b/depends/packages/native_cctools.mk index b5603a8d48c60..797480c25eb2f 100644 --- a/depends/packages/native_cctools.mk +++ b/depends/packages/native_cctools.mk @@ -1,14 +1,14 @@ package=native_cctools -$(package)_version=ee31ae567931c426136c94aad457c7b51d844beb +$(package)_version=807d6fd1be5d2224872e381870c0a75387fe05e6 $(package)_download_path=https://github.com/theuni/cctools-port/archive $(package)_file_name=$($(package)_version).tar.gz -$(package)_sha256_hash=ef107e6ab1b3994cb22e14f4f5c59ea0c0b5a988e6b21d42ed9616b018bbcbf9 +$(package)_sha256_hash=a09c9ba4684670a0375e42d9d67e7f12c1f62581a27f28f7c825d6d7032ccc6a $(package)_build_subdir=cctools -$(package)_clang_version=3.3 +$(package)_clang_version=3.7.1 $(package)_clang_download_path=http://llvm.org/releases/$($(package)_clang_version) -$(package)_clang_download_file=clang+llvm-$($(package)_clang_version)-amd64-Ubuntu-12.04.2.tar.gz -$(package)_clang_file_name=clang-llvm-$($(package)_clang_version)-amd64-Ubuntu-12.04.2.tar.gz -$(package)_clang_sha256_hash=60d8f69f032d62ef61bf527857ebb933741ec3352d4d328c5516aa520662dab7 +$(package)_clang_download_file=clang+llvm-$($(package)_clang_version)-x86_64-linux-gnu-ubuntu-14.04.tar.xz +$(package)_clang_file_name=clang-llvm-$($(package)_clang_version)-x86_64-linux-gnu-ubuntu-14.04.tar.xz +$(package)_clang_sha256_hash=99b28a6b48e793705228a390471991386daa33a9717cd9ca007fcdde69608fd9 $(package)_extra_sources=$($(package)_clang_file_name) define $(package)_fetch_cmds @@ -23,6 +23,7 @@ define $(package)_extract_cmds $(build_SHA256SUM) -c $($(package)_extract_dir)/.$($(package)_file_name).hash && \ mkdir -p toolchain/bin toolchain/lib/clang/3.5/include && \ tar --strip-components=1 -C toolchain -xf $($(package)_source_dir)/$($(package)_clang_file_name) && \ + rm -f toolchain/lib/libc++abi.so* && \ echo "#!/bin/sh" > toolchain/bin/$(host)-dsymutil && \ echo "exit 0" >> toolchain/bin/$(host)-dsymutil && \ chmod +x toolchain/bin/$(host)-dsymutil && \ @@ -30,7 +31,7 @@ define $(package)_extract_cmds endef define $(package)_set_vars -$(package)_config_opts=--target=$(host) --disable-libuuid +$(package)_config_opts=--target=$(host) --disable-lto-support $(package)_ldflags+=-Wl,-rpath=\\$$$$$$$$\$$$$$$$$ORIGIN/../lib $(package)_cc=$($(package)_extract_dir)/toolchain/bin/clang $(package)_cxx=$($(package)_extract_dir)/toolchain/bin/clang++ @@ -53,10 +54,11 @@ define $(package)_stage_cmds cd $($(package)_extract_dir)/toolchain && \ mkdir -p $($(package)_staging_prefix_dir)/lib/clang/$($(package)_clang_version)/include && \ mkdir -p $($(package)_staging_prefix_dir)/bin $($(package)_staging_prefix_dir)/include && \ - cp -P bin/clang bin/clang++ $($(package)_staging_prefix_dir)/bin/ &&\ + cp bin/clang $($(package)_staging_prefix_dir)/bin/ &&\ + cp -P bin/clang++ $($(package)_staging_prefix_dir)/bin/ &&\ cp lib/libLTO.so $($(package)_staging_prefix_dir)/lib/ && \ cp -rf lib/clang/$($(package)_clang_version)/include/* $($(package)_staging_prefix_dir)/lib/clang/$($(package)_clang_version)/include/ && \ - cp bin/$(host)-dsymutil $($(package)_staging_prefix_dir)/bin && \ + cp bin/llvm-dsymutil $($(package)_staging_prefix_dir)/bin/$(host)-dsymutil && \ if `test -d include/c++/`; then cp -rf include/c++/ $($(package)_staging_prefix_dir)/include/; fi && \ if `test -d lib/c++/`; then cp -rf lib/c++/ $($(package)_staging_prefix_dir)/lib/; fi endef diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index c1fc8e3058e9e..a8d3439965449 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -124,6 +124,7 @@ define $(package)_preprocess_cmds sed -i.old "s/src_plugins.depends = src_sql src_xml src_network/src_plugins.depends = src_xml src_network/" qtbase/src/src.pro && \ sed -i.old "s|X11/extensions/XIproto.h|X11/X.h|" qtbase/src/plugins/platforms/xcb/qxcbxsettings.cpp && \ sed -i.old 's/if \[ "$$$$XPLATFORM_MAC" = "yes" \]; then xspecvals=$$$$(macSDKify/if \[ "$$$$BUILD_ON_MAC" = "yes" \]; then xspecvals=$$$$(macSDKify/' qtbase/configure && \ + sed -i.old 's/CGEventCreateMouseEvent(0, kCGEventMouseMoved, pos, 0)/CGEventCreateMouseEvent(0, kCGEventMouseMoved, pos, kCGMouseButtonLeft)/' qtbase/src/plugins/platforms/cocoa/qcocoacursor.mm && \ 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/ &&\ From f6eb4e2b62d9c01ae32cf5a742dd86a594849343 Mon Sep 17 00:00:00 2001 From: fanquake Date: Sat, 14 May 2016 16:38:44 +0800 Subject: [PATCH 0494/1802] [depends] OpenSSL 1.0.1k - update config_opts --- depends/packages/openssl.mk | 39 ++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/depends/packages/openssl.mk b/depends/packages/openssl.mk index c6452820a2de8..5ee9f17a63235 100644 --- a/depends/packages/openssl.mk +++ b/depends/packages/openssl.mk @@ -6,9 +6,42 @@ $(package)_sha256_hash=8f9faeaebad088e772f4ef5e38252d472be4d878c6b3a2718c10a4fce define $(package)_set_vars $(package)_config_env=AR="$($(package)_ar)" RANLIB="$($(package)_ranlib)" CC="$($(package)_cc)" -$(package)_config_opts=--prefix=$(host_prefix) --openssldir=$(host_prefix)/etc/openssl no-zlib no-shared no-dso -$(package)_config_opts+=no-krb5 no-camellia no-capieng no-cast no-cms no-dtls1 no-gost no-gmp no-heartbeats no-idea no-jpake no-md2 -$(package)_config_opts+=no-mdc2 no-rc5 no-rdrand no-rfc3779 no-rsax no-sctp no-seed no-sha0 no-static_engine no-whirlpool no-rc2 no-rc4 no-ssl2 no-ssl3 +$(package)_config_opts=--prefix=$(host_prefix) --openssldir=$(host_prefix)/etc/openssl +$(package)_config_opts+=no-camellia +$(package)_config_opts+=no-capieng +$(package)_config_opts+=no-cast +$(package)_config_opts+=no-comp +$(package)_config_opts+=no-dso +$(package)_config_opts+=no-dtls1 +$(package)_config_opts+=no-ec_nistp_64_gcc_128 +$(package)_config_opts+=no-gost +$(package)_config_opts+=no-gmp +$(package)_config_opts+=no-heartbeats +$(package)_config_opts+=no-idea +$(package)_config_opts+=no-jpake +$(package)_config_opts+=no-krb5 +$(package)_config_opts+=no-libunbound +$(package)_config_opts+=no-md2 +$(package)_config_opts+=no-mdc2 +$(package)_config_opts+=no-rc4 +$(package)_config_opts+=no-rc5 +$(package)_config_opts+=no-rdrand +$(package)_config_opts+=no-rfc3779 +$(package)_config_opts+=no-rsax +$(package)_config_opts+=no-sctp +$(package)_config_opts+=no-seed +$(package)_config_opts+=no-sha0 +$(package)_config_opts+=no-shared +$(package)_config_opts+=no-ssl-trace +$(package)_config_opts+=no-ssl2 +$(package)_config_opts+=no-ssl3 +$(package)_config_opts+=no-static_engine +$(package)_config_opts+=no-store +$(package)_config_opts+=no-unit-test +$(package)_config_opts+=no-weak-ssl-ciphers +$(package)_config_opts+=no-whirlpool +$(package)_config_opts+=no-zlib +$(package)_config_opts+=no-zlib-dynamic $(package)_config_opts+=$($(package)_cflags) $($(package)_cppflags) $(package)_config_opts_linux=-fPIC -Wa,--noexecstack $(package)_config_opts_x86_64_linux=linux-x86_64 From faa91b12f774d7f459e47f440b7e9fe173d72bb0 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Tue, 7 Jun 2016 11:22:21 +0200 Subject: [PATCH 0495/1802] [wallet] tests: Don't use floating point --- src/wallet/test/wallet_tests.cpp | 46 +++++++++++++++++--------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 387b223589340..0a4f06ba88175 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -27,7 +27,7 @@ typedef set > CoinSet; BOOST_FIXTURE_TEST_SUITE(wallet_tests, WalletTestingSetup) -static CWallet wallet; +static const CWallet wallet; static vector vCoins; static void add_coin(const CAmount& nValue, int nAge = 6*24, bool fIsFromMe = false, int nInput=0) @@ -188,11 +188,11 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) // empty the wallet and start again, now with fractions of a cent, to test small change avoidance empty_wallet(); - add_coin(0.1*MIN_CHANGE); - add_coin(0.2*MIN_CHANGE); - add_coin(0.3*MIN_CHANGE); - add_coin(0.4*MIN_CHANGE); - add_coin(0.5*MIN_CHANGE); + add_coin(MIN_CHANGE * 1 / 10); + add_coin(MIN_CHANGE * 2 / 10); + add_coin(MIN_CHANGE * 3 / 10); + add_coin(MIN_CHANGE * 4 / 10); + add_coin(MIN_CHANGE * 5 / 10); // try making 1 * MIN_CHANGE from the 1.5 * MIN_CHANGE // we'll get change smaller than MIN_CHANGE whatever happens, so can expect MIN_CHANGE exactly @@ -207,8 +207,8 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) BOOST_CHECK_EQUAL(nValueRet, 1 * MIN_CHANGE); // we should get the exact amount // if we add more small coins: - add_coin(0.6*MIN_CHANGE); - add_coin(0.7*MIN_CHANGE); + add_coin(MIN_CHANGE * 6 / 10); + add_coin(MIN_CHANGE * 7 / 10); // and try again to make 1.0 * MIN_CHANGE BOOST_CHECK( wallet.SelectCoinsMinConf(1 * MIN_CHANGE, 1, 1, vCoins, setCoinsRet, nValueRet)); @@ -229,9 +229,9 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) // sometimes it will fail, and so we use the next biggest coin: empty_wallet(); - add_coin(0.5 * MIN_CHANGE); - add_coin(0.6 * MIN_CHANGE); - add_coin(0.7 * MIN_CHANGE); + add_coin(MIN_CHANGE * 5 / 10); + add_coin(MIN_CHANGE * 6 / 10); + add_coin(MIN_CHANGE * 7 / 10); add_coin(1111 * MIN_CHANGE); BOOST_CHECK( wallet.SelectCoinsMinConf(1 * MIN_CHANGE, 1, 1, vCoins, setCoinsRet, nValueRet)); BOOST_CHECK_EQUAL(nValueRet, 1111 * MIN_CHANGE); // we get the bigger coin @@ -239,9 +239,9 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) // but sometimes it's possible, and we use an exact subset (0.4 + 0.6 = 1.0) empty_wallet(); - add_coin(0.4 * MIN_CHANGE); - add_coin(0.6 * MIN_CHANGE); - add_coin(0.8 * MIN_CHANGE); + add_coin(MIN_CHANGE * 4 / 10); + add_coin(MIN_CHANGE * 6 / 10); + add_coin(MIN_CHANGE * 8 / 10); add_coin(1111 * MIN_CHANGE); BOOST_CHECK( wallet.SelectCoinsMinConf(MIN_CHANGE, 1, 1, vCoins, setCoinsRet, nValueRet)); BOOST_CHECK_EQUAL(nValueRet, MIN_CHANGE); // we should get the exact amount @@ -249,17 +249,17 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) // test avoiding small change empty_wallet(); - add_coin(0.05 * MIN_CHANGE); - add_coin(1 * MIN_CHANGE); - add_coin(100 * MIN_CHANGE); + add_coin(MIN_CHANGE * 5 / 100); + add_coin(MIN_CHANGE * 1); + add_coin(MIN_CHANGE * 100); // trying to make 100.01 from these three coins - BOOST_CHECK( wallet.SelectCoinsMinConf(100.01 * MIN_CHANGE, 1, 1, vCoins, setCoinsRet, nValueRet)); - BOOST_CHECK_EQUAL(nValueRet, 101.05 * MIN_CHANGE); // we should get all coins + BOOST_CHECK(wallet.SelectCoinsMinConf(MIN_CHANGE * 10001 / 100, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK_EQUAL(nValueRet, MIN_CHANGE * 10105 / 100); // we should get all coins BOOST_CHECK_EQUAL(setCoinsRet.size(), 3U); // but if we try to make 99.9, we should take the bigger of the two small coins to avoid small change - BOOST_CHECK( wallet.SelectCoinsMinConf(99.9 * MIN_CHANGE, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK(wallet.SelectCoinsMinConf(MIN_CHANGE * 9990 / 100, 1, 1, vCoins, setCoinsRet, nValueRet)); BOOST_CHECK_EQUAL(nValueRet, 101 * MIN_CHANGE); BOOST_CHECK_EQUAL(setCoinsRet.size(), 2U); @@ -310,7 +310,11 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) // add 75 cents in small change. not enough to make 90 cents, // then try making 90 cents. there are multiple competing "smallest bigger" coins, // one of which should be picked at random - add_coin( 5*CENT); add_coin(10*CENT); add_coin(15*CENT); add_coin(20*CENT); add_coin(25*CENT); + add_coin(5 * CENT); + add_coin(10 * CENT); + add_coin(15 * CENT); + add_coin(20 * CENT); + add_coin(25 * CENT); fails = 0; for (int i = 0; i < RANDOM_REPEATS; i++) From facb6c0bf8a6ef7081d763d9f33b446276a36635 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 22 May 2016 11:37:42 +0200 Subject: [PATCH 0496/1802] [qa] mininode: fail on send_message instead of silent return --- qa/rpc-tests/test_framework/mininode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index c0b59f38579d7..6612b99b84234 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -1315,7 +1315,7 @@ def got_data(self): def send_message(self, message, pushbuf=False): if self.state != "connected" and not pushbuf: - return + raise IOError('Not connected, no pushbuf') self.show_debug_msg("Send %s" % repr(message)) command = message.command data = message.serialize() From fa8ce3b670dd9376d2c13722670b9cc8012011ca Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sat, 16 Apr 2016 19:11:39 +0200 Subject: [PATCH 0497/1802] [qa] assert 'changePosition out of bounds' --- qa/rpc-tests/fundrawtransaction.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py index 228574e671803..3dfb9e4024f2a 100755 --- a/qa/rpc-tests/fundrawtransaction.py +++ b/qa/rpc-tests/fundrawtransaction.py @@ -247,6 +247,12 @@ def run_test(self): assert_equal(utx['txid'], dec_tx['vin'][0]['txid']) change = self.nodes[2].getnewaddress() + try: + rawtxfund = self.nodes[2].fundrawtransaction(rawtx, {'changeAddress': change, 'changePosition': 2}) + except JSONRPCException as e: + assert('changePosition out of bounds' == e.error['message']) + else: + assert(False) rawtxfund = self.nodes[2].fundrawtransaction(rawtx, {'changeAddress': change, 'changePosition': 0}) dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) out = dec_tx['vout'][0]; From fa324653ab7a44a89d6a692ce8f953ded8501e17 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sat, 16 Apr 2016 18:36:39 +0200 Subject: [PATCH 0498/1802] [qa] fundrawtransaction: Create get_unspent() --- qa/rpc-tests/fundrawtransaction.py | 93 ++++++------------------------ 1 file changed, 19 insertions(+), 74 deletions(-) diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py index 3dfb9e4024f2a..eeb8476634fcb 100755 --- a/qa/rpc-tests/fundrawtransaction.py +++ b/qa/rpc-tests/fundrawtransaction.py @@ -6,7 +6,14 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * -# Create one-input, one-output, no-fee transaction: + +def get_unspent(listunspent, amount): + for utx in listunspent: + if utx['amount'] == amount: + return utx + raise AssertionError('Could not find unspent with amount={}'.format(amount)) + + class RawTransactionsTest(BitcoinTestFramework): def __init__(self): @@ -71,7 +78,7 @@ def run_test(self): rawtxfund = self.nodes[2].fundrawtransaction(rawtx) fee = rawtxfund['fee'] dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) - assert(len(dec_tx['vin']) > 0) #test if we have enought inputs + assert(len(dec_tx['vin']) > 0) #test that we have enough inputs ############################## # simple test with two coins # @@ -123,14 +130,7 @@ def run_test(self): ######################################################################### # test a fundrawtransaction with a VIN greater than the required amount # ######################################################################### - utx = False - listunspent = self.nodes[2].listunspent() - for aUtx in listunspent: - if aUtx['amount'] == 5.0: - utx = aUtx - break - - assert(utx!=False) + utx = get_unspent(self.nodes[2].listunspent(), 5) inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}] outputs = { self.nodes[0].getnewaddress() : 1.0 } @@ -151,14 +151,7 @@ def run_test(self): ##################################################################### # test a fundrawtransaction with which will not get a change output # ##################################################################### - utx = False - listunspent = self.nodes[2].listunspent() - for aUtx in listunspent: - if aUtx['amount'] == 5.0: - utx = aUtx - break - - assert(utx!=False) + utx = get_unspent(self.nodes[2].listunspent(), 5) inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}] outputs = { self.nodes[0].getnewaddress() : Decimal(5.0) - fee - feeTolerance } @@ -180,14 +173,7 @@ def run_test(self): #################################################### # test a fundrawtransaction with an invalid option # #################################################### - utx = False - listunspent = self.nodes[2].listunspent() - for aUtx in listunspent: - if aUtx['amount'] == 5.0: - utx = aUtx - break - - assert_equal(utx!=False, True) + utx = get_unspent(self.nodes[2].listunspent(), 5) inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ] outputs = { self.nodes[0].getnewaddress() : Decimal(4.0) } @@ -205,14 +191,7 @@ def run_test(self): ############################################################ # test a fundrawtransaction with an invalid change address # ############################################################ - utx = False - listunspent = self.nodes[2].listunspent() - for aUtx in listunspent: - if aUtx['amount'] == 5.0: - utx = aUtx - break - - assert_equal(utx!=False, True) + utx = get_unspent(self.nodes[2].listunspent(), 5) inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ] outputs = { self.nodes[0].getnewaddress() : Decimal(4.0) } @@ -227,18 +206,10 @@ def run_test(self): assert("changeAddress must be a valid bitcoin address" in e.error['message']) - ############################################################ # test a fundrawtransaction with a provided change address # ############################################################ - utx = False - listunspent = self.nodes[2].listunspent() - for aUtx in listunspent: - if aUtx['amount'] == 5.0: - utx = aUtx - break - - assert_equal(utx!=False, True) + utx = get_unspent(self.nodes[2].listunspent(), 5) inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ] outputs = { self.nodes[0].getnewaddress() : Decimal(4.0) } @@ -259,18 +230,10 @@ def run_test(self): assert_equal(change, out['scriptPubKey']['addresses'][0]) - ######################################################################### # test a fundrawtransaction with a VIN smaller than the required amount # ######################################################################### - utx = False - listunspent = self.nodes[2].listunspent() - for aUtx in listunspent: - if aUtx['amount'] == 1.0: - utx = aUtx - break - - assert(utx!=False) + utx = get_unspent(self.nodes[2].listunspent(), 1) inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}] outputs = { self.nodes[0].getnewaddress() : 1.0 } @@ -305,17 +268,8 @@ def run_test(self): ########################################### # test a fundrawtransaction with two VINs # ########################################### - utx = False - utx2 = False - listunspent = self.nodes[2].listunspent() - for aUtx in listunspent: - if aUtx['amount'] == 1.0: - utx = aUtx - if aUtx['amount'] == 5.0: - utx2 = aUtx - - - assert(utx!=False) + utx = get_unspent(self.nodes[2].listunspent(), 1) + utx2 = get_unspent(self.nodes[2].listunspent(), 5) inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']},{'txid' : utx2['txid'], 'vout' : utx2['vout']} ] outputs = { self.nodes[0].getnewaddress() : 6.0 } @@ -347,17 +301,8 @@ def run_test(self): ######################################################### # test a fundrawtransaction with two VINs and two vOUTs # ######################################################### - utx = False - utx2 = False - listunspent = self.nodes[2].listunspent() - for aUtx in listunspent: - if aUtx['amount'] == 1.0: - utx = aUtx - if aUtx['amount'] == 5.0: - utx2 = aUtx - - - assert(utx!=False) + utx = get_unspent(self.nodes[2].listunspent(), 1) + utx2 = get_unspent(self.nodes[2].listunspent(), 5) inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']},{'txid' : utx2['txid'], 'vout' : utx2['vout']} ] outputs = { self.nodes[0].getnewaddress() : 6.0, self.nodes[0].getnewaddress() : 1.0 } From fa3b3792522681207b3619edec5f3175be6fc841 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 9 May 2016 21:29:18 +0200 Subject: [PATCH 0499/1802] [qa] pull-tester: Fix assertion and check for run_parallel --- qa/pull-tester/rpc-tests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index 57a576f1c7bf0..98823085034af 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -191,7 +191,7 @@ def runtests(): if coverage: flags.append(coverage.flag) - if len(test_list) > 1: + if len(test_list) > 1 and run_parallel > 1: # Populate cache subprocess.check_output([RPC_TESTS_DIR + 'create_cache.py'] + flags) @@ -251,7 +251,7 @@ def get_next(self): stdout=subprocess.PIPE, stderr=subprocess.PIPE))) if not self.jobs: - raise IndexError('%s from empty list' % __name__) + raise IndexError('pop from empty list') while True: # Return first proc that finishes time.sleep(.5) From 6194d9a501901f9fa7b20d2a4c34b31357a6441d Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 16 Jun 2016 11:29:44 +0200 Subject: [PATCH 0500/1802] Fix bitcoin_qt.m4 and fix-xcb-include-order.patch --- .travis.yml | 2 +- build-aux/m4/bitcoin_qt.m4 | 2 + contrib/devtools/symbol-check.py | 1 + contrib/gitian-descriptors/gitian-osx.yml | 4 +- depends/packages/qt.mk | 84 ++++++++++--------- .../patches/qt/fix-xcb-include-order.patch | 28 ++++--- depends/patches/qt/fix_qt_pkgconfig.patch | 11 +++ 7 files changed, 77 insertions(+), 55 deletions(-) create mode 100644 depends/patches/qt/fix_qt_pkgconfig.patch diff --git a/.travis.yml b/.travis.yml index 64227ac2a883b..a6c51753b6727 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,7 +39,7 @@ env: # No wallet - HOST=x86_64-unknown-linux-gnu PACKAGES=" openjdk-7-jre-headless python3" DEP_OPTS="NO_WALLET=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" # Cross-Mac - - HOST=x86_64-apple-darwin11 PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev" BITCOIN_CONFIG="--enable-reduce-exports" OSX_SDK=10.9 GOAL="deploy" + - HOST=x86_64-apple-darwin11 PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev" BITCOIN_CONFIG="--enable-reduce-exports" OSX_SDK=10.11 GOAL="deploy" before_install: - export PATH=$(echo $PATH | tr ':' "\n" | sed '/\/opt\/python/d' | tr "\n" ":" | sed "s|::|:|g") diff --git a/build-aux/m4/bitcoin_qt.m4 b/build-aux/m4/bitcoin_qt.m4 index efffa4887d611..210df3c025d0b 100644 --- a/build-aux/m4/bitcoin_qt.m4 +++ b/build-aux/m4/bitcoin_qt.m4 @@ -342,6 +342,8 @@ AC_DEFUN([_BITCOIN_QT_FIND_STATIC_PLUGINS],[ elif test x$TARGET_OS = xdarwin; then PKG_CHECK_MODULES([QTPRINT], [Qt5PrintSupport], [QT_LIBS="$QTPRINT_LIBS $QT_LIBS"]) fi + else + QT_LIBS="-lQt5PlatformSupport $QT_LIBS" fi ]) else diff --git a/contrib/devtools/symbol-check.py b/contrib/devtools/symbol-check.py index e26c0fbb94455..037b34212151e 100755 --- a/contrib/devtools/symbol-check.py +++ b/contrib/devtools/symbol-check.py @@ -68,6 +68,7 @@ b'libxcb.so.1', # part of X11 b'libfontconfig.so.1', # font support b'libfreetype.so.6', # font parsing +b'libdbus-1.so.3', # inter process communication (notification system) b'libdl.so.2' # programming interface to dynamic linker } diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml index 536fcfb105d53..991976d59eaa0 100644 --- a/contrib/gitian-descriptors/gitian-osx.yml +++ b/contrib/gitian-descriptors/gitian-osx.yml @@ -31,7 +31,7 @@ remotes: - "url": "https://github.com/bitcoin/bitcoin.git" "dir": "bitcoin" files: -- "MacOSX10.9.sdk.tar.gz" +- "MacOSX10.11.sdk.tar.gz" script: | WRAP_DIR=$HOME/wrapped HOSTS="x86_64-apple-darwin11" @@ -87,7 +87,7 @@ script: | BASEPREFIX=`pwd`/depends mkdir -p ${BASEPREFIX}/SDKs - tar -C ${BASEPREFIX}/SDKs -xf ${BUILD_DIR}/MacOSX10.9.sdk.tar.gz + tar -C ${BASEPREFIX}/SDKs -xf ${BUILD_DIR}/MacOSX10.11.sdk.tar.gz # Build dependencies for each host for i in $HOSTS; do diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index a8d3439965449..c452823a9552e 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -1,20 +1,21 @@ PACKAGE=qt -$(package)_version=5.5.0 -$(package)_download_path=http://download.qt.io/official_releases/qt/5.5/$($(package)_version)/submodules +$(package)_version=5.6.1 +$(package)_download_path=http://download.qt.io/official_releases/qt/5.6/$($(package)_version)/submodules $(package)_suffix=opensource-src-$($(package)_version).tar.gz $(package)_file_name=qtbase-$($(package)_suffix) -$(package)_sha256_hash=7e82b1318f88e56a2a9376e069aa608d4fd96b48cb0e1b880ae658b0a1af0561 +$(package)_sha256_hash=0ac67cf8d66d52b995f96c31c4b48117a1afb3db99eaa93e20ccd8f7f55f7fde $(package)_dependencies=openssl $(package)_linux_dependencies=freetype fontconfig dbus libxcb libX11 xproto libXext $(package)_build_subdir=qtbase $(package)_qt_libs=corelib network widgets gui plugins testlib -$(package)_patches=mac-qmake.conf fix-xcb-include-order.patch mingw-uuidof.patch pidlist_absolute.patch +$(package)_patches=mac-qmake.conf mingw-uuidof.patch pidlist_absolute.patch fix-xcb-include-order.patch fix_qt_pkgconfig.patch $(package)_qttranslations_file_name=qttranslations-$($(package)_suffix) -$(package)_qttranslations_sha256_hash=c4bd6db6e426965c6f8824c54e81f68bbd61e2bae1bcadc328c6e81c45902a0d +$(package)_qttranslations_sha256_hash=dcc1534d247babca1840cb6d0a000671801a341ea352d0535474f86adadaf028 + $(package)_qttools_file_name=qttools-$($(package)_suffix) -$(package)_qttools_sha256_hash=d9e06bd19ecc86afba5e95d45a906d1bc1ad579aa70001e36143c1aaf695bdd6 +$(package)_qttools_sha256_hash=e0f845de28c31230dfa428f0190ccb3b91d1fc02481b1f064698ae4ef8376aa1 $(package)_extra_sources = $($(package)_qttranslations_file_name) $(package)_extra_sources += $($(package)_qttools_file_name) @@ -22,21 +23,33 @@ $(package)_extra_sources += $($(package)_qttools_file_name) define $(package)_set_vars $(package)_config_opts_release = -release $(package)_config_opts_debug = -debug -$(package)_config_opts += -opensource -confirm-license +$(package)_config_opts += -bindir $(build_prefix)/bin +$(package)_config_opts += -c++11 +$(package)_config_opts += -confirm-license +$(package)_config_opts += -hostprefix $(build_prefix) +$(package)_config_opts += -no-alsa $(package)_config_opts += -no-audio-backend +$(package)_config_opts += -no-cups +$(package)_config_opts += -no-egl +$(package)_config_opts += -no-eglfs +$(package)_config_opts += -no-feature-style-windowsmobile +$(package)_config_opts += -no-feature-style-windowsce +$(package)_config_opts += -no-freetype +$(package)_config_opts += -no-gif $(package)_config_opts += -no-glib +$(package)_config_opts += -no-gstreamer $(package)_config_opts += -no-icu -$(package)_config_opts += -no-cups $(package)_config_opts += -no-iconv -$(package)_config_opts += -no-gif -$(package)_config_opts += -no-freetype +$(package)_config_opts += -no-kms +$(package)_config_opts += -no-linuxfb +$(package)_config_opts += -no-libudev +$(package)_config_opts += -no-mitshm +$(package)_config_opts += -no-mtdev $(package)_config_opts += -no-nis -$(package)_config_opts += -pch +$(package)_config_opts += -no-pulseaudio +$(package)_config_opts += -no-openvg +$(package)_config_opts += -no-reduce-relocations $(package)_config_opts += -no-qml-debug -$(package)_config_opts += -nomake examples -$(package)_config_opts += -nomake tests -$(package)_config_opts += -no-feature-style-windowsmobile -$(package)_config_opts += -no-feature-style-windowsce $(package)_config_opts += -no-sql-db2 $(package)_config_opts += -no-sql-ibase $(package)_config_opts += -no-sql-oci @@ -46,36 +59,25 @@ $(package)_config_opts += -no-sql-odbc $(package)_config_opts += -no-sql-psql $(package)_config_opts += -no-sql-sqlite $(package)_config_opts += -no-sql-sqlite2 -$(package)_config_opts += -prefix $(host_prefix) -$(package)_config_opts += -hostprefix $(build_prefix) -$(package)_config_opts += -bindir $(build_prefix)/bin -$(package)_config_opts += -c++11 +$(package)_config_opts += -no-use-gold-linker +$(package)_config_opts += -no-xinput2 +$(package)_config_opts += -no-xrender +$(package)_config_opts += -nomake examples +$(package)_config_opts += -nomake tests +$(package)_config_opts += -opensource $(package)_config_opts += -openssl-linked -$(package)_config_opts += -v -$(package)_config_opts += -static -$(package)_config_opts += -silent +$(package)_config_opts += -optimized-qmake +$(package)_config_opts += -pch $(package)_config_opts += -pkg-config +$(package)_config_opts += -prefix $(host_prefix) $(package)_config_opts += -qt-libpng $(package)_config_opts += -qt-libjpeg -$(package)_config_opts += -qt-zlib $(package)_config_opts += -qt-pcre -$(package)_config_opts += -no-pulseaudio -$(package)_config_opts += -no-openvg -$(package)_config_opts += -no-xrender -$(package)_config_opts += -no-alsa -$(package)_config_opts += -no-mtdev -$(package)_config_opts += -no-gstreamer -$(package)_config_opts += -no-mitshm -$(package)_config_opts += -no-kms -$(package)_config_opts += -no-reduce-relocations -$(package)_config_opts += -no-egl -$(package)_config_opts += -no-eglfs -$(package)_config_opts += -no-linuxfb -$(package)_config_opts += -no-xinput2 -$(package)_config_opts += -no-libudev -$(package)_config_opts += -no-use-gold-linker +$(package)_config_opts += -qt-zlib $(package)_config_opts += -reduce-exports -$(package)_config_opts += -optimized-qmake +$(package)_config_opts += -static +$(package)_config_opts += -silent +$(package)_config_opts += -v ifneq ($(build_os),darwin) $(package)_config_opts_darwin = -xplatform macx-clang-linux @@ -119,6 +121,7 @@ define $(package)_extract_cmds tar --strip-components=1 -xf $($(package)_source_dir)/$($(package)_qttools_file_name) -C qttools endef + define $(package)_preprocess_cmds sed -i.old "s|updateqm.commands = \$$$$\$$$$LRELEASE|updateqm.commands = $($(package)_extract_dir)/qttools/bin/lrelease|" qttranslations/translations/translations.pro && \ sed -i.old "s/src_plugins.depends = src_sql src_xml src_network/src_plugins.depends = src_xml src_network/" qtbase/src/src.pro && \ @@ -130,9 +133,10 @@ define $(package)_preprocess_cmds 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 && \ - patch -p1 < $($(package)_patch_dir)/fix-xcb-include-order.patch && \ patch -p1 < $($(package)_patch_dir)/mingw-uuidof.patch && \ patch -p1 < $($(package)_patch_dir)/pidlist_absolute.patch && \ + patch -p1 < $($(package)_patch_dir)/fix-xcb-include-order.patch && \ + patch -p1 < $($(package)_patch_dir)/fix_qt_pkgconfig.patch && \ echo "QMAKE_CFLAGS += $($(package)_cflags) $($(package)_cppflags)" >> qtbase/mkspecs/common/gcc-base.conf && \ echo "QMAKE_CXXFLAGS += $($(package)_cxxflags) $($(package)_cppflags)" >> qtbase/mkspecs/common/gcc-base.conf && \ echo "QMAKE_LFLAGS += $($(package)_ldflags)" >> qtbase/mkspecs/common/gcc-base.conf && \ diff --git a/depends/patches/qt/fix-xcb-include-order.patch b/depends/patches/qt/fix-xcb-include-order.patch index ae469ea94bff0..c7dbebedce831 100644 --- a/depends/patches/qt/fix-xcb-include-order.patch +++ b/depends/patches/qt/fix-xcb-include-order.patch @@ -1,15 +1,15 @@ --- old/qtbase/src/plugins/platforms/xcb/xcb_qpa_lib.pro 2015-03-17 02:06:42.705930685 +0000 +++ new/qtbase/src/plugins/platforms/xcb/xcb_qpa_lib.pro 2015-03-17 02:08:41.281926351 +0000 -@@ -94,8 +94,6 @@ - +@@ -74,8 +74,6 @@ + DEFINES += $$QMAKE_DEFINES_XCB LIBS += $$QMAKE_LIBS_XCB -QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_XCB -QMAKE_CFLAGS += $$QMAKE_CFLAGS_XCB - + CONFIG += qpa/genericunixfontdatabase - -@@ -104,7 +102,8 @@ + +@@ -87,7 +85,8 @@ contains(QT_CONFIG, xcb-qt) { DEFINES += XCB_USE_RENDER XCB_DIR = ../../../3rdparty/xcb @@ -18,28 +18,32 @@ + QMAKE_CXXFLAGS += -I$$XCB_DIR/include -I$$XCB_DIR/sysinclude $$QMAKE_CFLAGS_XCB LIBS += -lxcb -L$$OUT_PWD/xcb-static -lxcb-static } else { - LIBS += -lxcb -lxcb-image -lxcb-icccm -lxcb-sync -lxcb-xfixes -lxcb-shm -lxcb-randr -lxcb-shape -lxcb-keysyms + LIBS += -lxcb -lxcb-image -lxcb-icccm -lxcb-sync -lxcb-xfixes -lxcb-shm -lxcb-randr -lxcb-shape -lxcb-keysyms -lxcb-xinerama --- old/qtbase/src/plugins/platforms/xcb/xcb-static/xcb-static.pro 2015-03-17 02:07:04.641929383 +0000 +++ new/qtbase/src/plugins/platforms/xcb/xcb-static/xcb-static.pro 2015-03-17 02:10:15.485922059 +0000 -@@ -8,7 +8,8 @@ - +@@ -9,7 +9,8 @@ + XCB_DIR = ../../../../3rdparty/xcb - + -INCLUDEPATH += $$XCB_DIR/include $$XCB_DIR/include/xcb $$XCB_DIR/sysinclude +QMAKE_CFLAGS += -I$$XCB_DIR/include -I$$XCB_DIR/include/xcb -I$$XCB_DIR/sysinclude +QMAKE_CXXFLAGS += -I$$XCB_DIR/include -I$$XCB_DIR/include/xcb -I$$XCB_DIR/sysinclude - + QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_XCB QMAKE_CFLAGS += $$QMAKE_CFLAGS_XCB --- old/qtbase/src/plugins/platforms/xcb/xcb-plugin.pro 2015-07-24 16:02:59.530038830 -0400 +++ new/qtbase/src/plugins/platforms/xcb/xcb-plugin.pro 2015-07-24 16:01:22.106037459 -0400 -@@ -11,3 +11,9 @@ +@@ -6,6 +6,13 @@ qxcbmain.cpp OTHER_FILES += xcb.json README - + +contains(QT_CONFIG, xcb-qt) { + DEFINES += XCB_USE_RENDER + XCB_DIR = ../../../3rdparty/xcb + QMAKE_CFLAGS += -I$$XCB_DIR/include -I$$XCB_DIR/sysinclude $$QMAKE_CFLAGS_XCB + QMAKE_CXXFLAGS += -I$$XCB_DIR/include -I$$XCB_DIR/sysinclude $$QMAKE_CFLAGS_XCB +} ++ + PLUGIN_TYPE = platforms + PLUGIN_CLASS_NAME = QXcbIntegrationPlugin + !equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = - diff --git a/depends/patches/qt/fix_qt_pkgconfig.patch b/depends/patches/qt/fix_qt_pkgconfig.patch new file mode 100644 index 0000000000000..3772db4f8b804 --- /dev/null +++ b/depends/patches/qt/fix_qt_pkgconfig.patch @@ -0,0 +1,11 @@ +--- old/qtbase/mkspecs/features/qt_module.prf 2016-03-17 02:06:42.705930685 +0000 ++++ new/qtbase/mkspecs/features/qt_module.prf 2016-03-17 02:06:42.705930685 +0000 +@@ -244,7 +244,7 @@ + load(qt_targets) + + # this builds on top of qt_common +-!internal_module:!lib_bundle:if(unix|mingw) { ++unix|mingw { + CONFIG += create_pc + QMAKE_PKGCONFIG_DESTDIR = pkgconfig + host_build: \ From 9e3ec74fac76f93bedaca882cc7053cc46199a61 Mon Sep 17 00:00:00 2001 From: Nathaniel Mahieu Date: Tue, 14 Jun 2016 17:49:09 -0500 Subject: [PATCH 0501/1802] Clarify documentation for running a tor node Previous wording suggested that no additional setup was required for a tor hidden service to be created. --- doc/tor.md | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/doc/tor.md b/doc/tor.md index 43e922718b7dd..79f1563021094 100644 --- a/doc/tor.md +++ b/doc/tor.md @@ -95,12 +95,22 @@ Starting with Tor version 0.2.7.1 it is possible, through Tor's control socket API, to create and destroy 'ephemeral' hidden services programmatically. Bitcoin Core has been updated to make use of this. -This means that if Tor is running (and proper authorization is available), -Bitcoin Core automatically creates a hidden service to listen on, without -manual configuration. This will positively affect the number of available -.onion nodes. +This means that if Tor is running (and proper authentication has been configured), +Bitcoin Core automatically creates a hidden service to listen on. This will positively +affect the number of available .onion nodes. This new feature is enabled by default if Bitcoin Core is listening, and a connection to Tor can be made. It can be configured with the `-listenonion`, `-torcontrol` and `-torpassword` settings. To show verbose debugging information, pass `-debug=tor`. + +Connecting to Tor's control socket API requires one of two authentication methods to be +configured. For cookie authentication the user running bitcoind must have write access +to the `CookieAuthFile` specified in Tor configuration. In some cases this is +preconfigured and the creation of a hidden service is automatic. If permission problems +are seen with `-debug=tor` they can be resolved by adding both the user running tor and +the user running bitcoind to the same group and setting permissions appropriately. On +Debian-based systems the user running bitcoind can be added to the debian-tor group, +which has the appropriate permissions. An alternative authentication method is the use +of the `-torpassword` flag and a `hash-password` which can be enabled and specified in +Tor configuration. \ No newline at end of file From 59d063d07660d6e8d53ed8aa1eb8b0747ea6767c Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Sat, 18 Jun 2016 13:51:45 +0200 Subject: [PATCH 0502/1802] Use runtime linking of QT libdbus, use custom/temp. SDK URL --- .travis.yml | 2 +- contrib/devtools/symbol-check.py | 1 - depends/packages/qt.mk | 3 ++- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index a6c51753b6727..af9c476dc1d99 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,7 +22,7 @@ env: - CCACHE_TEMPDIR=/tmp/.ccache-temp - CCACHE_COMPRESS=1 - BASE_OUTDIR=$TRAVIS_BUILD_DIR/out - - SDK_URL=https://bitcoincore.org/depends-sources/sdks + - SDK_URL=https://bitcoin.jonasschnelli.ch/sdks - PYTHON_DEBUG=1 - WINEDEBUG=fixme-all matrix: diff --git a/contrib/devtools/symbol-check.py b/contrib/devtools/symbol-check.py index 037b34212151e..e26c0fbb94455 100755 --- a/contrib/devtools/symbol-check.py +++ b/contrib/devtools/symbol-check.py @@ -68,7 +68,6 @@ b'libxcb.so.1', # part of X11 b'libfontconfig.so.1', # font support b'libfreetype.so.6', # font parsing -b'libdbus-1.so.3', # inter process communication (notification system) b'libdl.so.2' # programming interface to dynamic linker } diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index c452823a9552e..d41d0b9ea5b15 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -5,7 +5,7 @@ $(package)_suffix=opensource-src-$($(package)_version).tar.gz $(package)_file_name=qtbase-$($(package)_suffix) $(package)_sha256_hash=0ac67cf8d66d52b995f96c31c4b48117a1afb3db99eaa93e20ccd8f7f55f7fde $(package)_dependencies=openssl -$(package)_linux_dependencies=freetype fontconfig dbus libxcb libX11 xproto libXext +$(package)_linux_dependencies=freetype fontconfig libxcb libX11 xproto libXext $(package)_build_subdir=qtbase $(package)_qt_libs=corelib network widgets gui plugins testlib $(package)_patches=mac-qmake.conf mingw-uuidof.patch pidlist_absolute.patch fix-xcb-include-order.patch fix_qt_pkgconfig.patch @@ -26,6 +26,7 @@ $(package)_config_opts_debug = -debug $(package)_config_opts += -bindir $(build_prefix)/bin $(package)_config_opts += -c++11 $(package)_config_opts += -confirm-license +$(package)_config_opts += -dbus-runtime $(package)_config_opts += -hostprefix $(build_prefix) $(package)_config_opts += -no-alsa $(package)_config_opts += -no-audio-backend From ad0752e41f7804fd1d0e639c51e927ed4f430e09 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 18 Jun 2016 18:16:36 +0200 Subject: [PATCH 0503/1802] Stop trimming when mapTx is empty --- src/txmempool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 205ffd6379351..18c54b08bc2d3 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -1075,7 +1075,7 @@ void CTxMemPool::TrimToSize(size_t sizelimit, std::vector* pvNoSpendsRe unsigned nTxnRemoved = 0; CFeeRate maxFeeRateRemoved(0); - while (DynamicMemoryUsage() > sizelimit) { + while (!mapTx.empty() && DynamicMemoryUsage() > sizelimit) { indexed_transaction_set::index::type::iterator it = mapTx.get().begin(); // We set the new mempool min fee to the feerate of the removed set, plus the From 3775ff9ea7e92cc1e6a0cdbb15999913d93c87e7 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 18 Jun 2016 19:15:03 +0200 Subject: [PATCH 0504/1802] Enable mempool consistency checks in unit tests --- src/test/test_bitcoin.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index c68320ba8b8e6..3dc59ddd08e76 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -55,6 +55,7 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha pathTemp = GetTempPath() / strprintf("test_bitcoin_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000))); boost::filesystem::create_directories(pathTemp); mapArgs["-datadir"] = pathTemp.string(); + mempool.setSanityCheck(1.0); pblocktree = new CBlockTreeDB(1 << 20, true); pcoinsdbview = new CCoinsViewDB(1 << 23, true); pcoinsTip = new CCoinsViewCache(pcoinsdbview); From 9fce0629b437441cb09c14055ee810b8ee6b7978 Mon Sep 17 00:00:00 2001 From: Daniel Kraft Date: Sat, 18 Jun 2016 19:38:28 +0200 Subject: [PATCH 0505/1802] [c++11] Use std::unique_ptr for block creation. CreateNewBlock returns a pointer for which the caller takes ownership. Use std::unique_ptr to make this explicit and simplify handling of these objects in getblocktemplate. --- src/miner.cpp | 7 ++++--- src/miner.h | 2 +- src/rpc/mining.cpp | 10 +++------- src/test/miner_tests.cpp | 15 ++++----------- src/test/test_bitcoin.cpp | 5 +++-- 5 files changed, 15 insertions(+), 24 deletions(-) diff --git a/src/miner.cpp b/src/miner.cpp index 989ad11a2614d..d38ccedf554e3 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -29,6 +29,7 @@ #include #include #include +#include using namespace std; @@ -102,14 +103,14 @@ void BlockAssembler::resetBlock() blockFinished = false; } -CBlockTemplate* BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn) +std::unique_ptr BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn) { resetBlock(); pblocktemplate.reset(new CBlockTemplate()); if(!pblocktemplate.get()) - return NULL; + return nullptr; pblock = &pblocktemplate->block; // pointer for convenience // Add dummy coinbase tx as first transaction @@ -164,7 +165,7 @@ CBlockTemplate* BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn) throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, FormatStateMessage(state))); } - return pblocktemplate.release(); + return std::move(pblocktemplate); } bool BlockAssembler::isStillDependent(CTxMemPool::txiter iter) diff --git a/src/miner.h b/src/miner.h index a9fea85304aa6..54c680b5ffd9d 100644 --- a/src/miner.h +++ b/src/miner.h @@ -160,7 +160,7 @@ class BlockAssembler public: BlockAssembler(const CChainParams& chainparams); /** Construct a new block template with coinbase to scriptPubKeyIn */ - CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn); + std::unique_ptr CreateNewBlock(const CScript& scriptPubKeyIn); private: // utility functions diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 94eeea91f39f2..162f4a0721e3b 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -22,6 +22,7 @@ #include "utilstrencodings.h" #include "validationinterface.h" +#include #include #include @@ -508,12 +509,12 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) // Update block static CBlockIndex* pindexPrev; static int64_t nStart; - static CBlockTemplate* pblocktemplate; + static std::unique_ptr pblocktemplate; if (pindexPrev != chainActive.Tip() || (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5)) { // Clear pindexPrev so future calls make a new block, despite any failures from here on - pindexPrev = NULL; + pindexPrev = nullptr; // Store the pindexBest used before CreateNewBlock, to avoid races nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); @@ -521,11 +522,6 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) nStart = GetTime(); // Create new block - if(pblocktemplate) - { - delete pblocktemplate; - pblocktemplate = NULL; - } CScript scriptDummy = CScript() << OP_TRUE; pblocktemplate = BlockAssembler(Params()).CreateNewBlock(scriptDummy); if (!pblocktemplate) diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index ca8d6d2e05baa..7b087763d09d4 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -18,6 +18,8 @@ #include "test/test_bitcoin.h" +#include + #include BOOST_FIXTURE_TEST_SUITE(miner_tests, TestingSetup) @@ -105,7 +107,7 @@ void TestPackageSelection(const CChainParams& chainparams, CScript scriptPubKey, uint256 hashHighFeeTx = tx.GetHash(); mempool.addUnchecked(hashHighFeeTx, entry.Fee(50000).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); - CBlockTemplate *pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey); + std::unique_ptr pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey); BOOST_CHECK(pblocktemplate->block.vtx[1].GetHash() == hashParentTx); BOOST_CHECK(pblocktemplate->block.vtx[2].GetHash() == hashHighFeeTx); BOOST_CHECK(pblocktemplate->block.vtx[3].GetHash() == hashMediumFeeTx); @@ -183,7 +185,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) { const CChainParams& chainparams = Params(CBaseChainParams::MAIN); CScript scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG; - CBlockTemplate *pblocktemplate; + std::unique_ptr pblocktemplate; CMutableTransaction tx,tx2; CScript script; uint256 hash; @@ -225,11 +227,9 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) BOOST_CHECK(state.IsValid()); pblock->hashPrevBlock = pblock->GetHash(); } - delete pblocktemplate; // Just to make sure we can still make simple blocks BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey)); - delete pblocktemplate; const CAmount BLOCKSUBSIDY = 50*COIN; const CAmount LOWFEE = CENT; @@ -268,7 +268,6 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vin[0].prevout.hash = hash; } BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey)); - delete pblocktemplate; mempool.clear(); // block size > limit @@ -289,7 +288,6 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vin[0].prevout.hash = hash; } BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey)); - delete pblocktemplate; mempool.clear(); // orphan in mempool, template creation fails @@ -313,7 +311,6 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) hash = tx.GetHash(); mempool.addUnchecked(hash, entry.Fee(HIGHERFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey)); - delete pblocktemplate; mempool.clear(); // coinbase in mempool, template creation fails @@ -371,7 +368,6 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) chainActive.SetTip(next); } BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey)); - delete pblocktemplate; // Extend to a 210000-long block chain. while (chainActive.Tip()->nHeight < 210000) { CBlockIndex* prev = chainActive.Tip(); @@ -384,7 +380,6 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) chainActive.SetTip(next); } BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey)); - delete pblocktemplate; // Delete the dummy blocks again. while (chainActive.Tip()->nHeight > nHeight) { CBlockIndex* del = chainActive.Tip(); @@ -477,7 +472,6 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) // but relative locked txs will if inconsistently added to mempool. // For now these will still generate a valid template until BIP68 soft fork BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 3); - delete pblocktemplate; // However if we advance height by 1 and time by 512, all of them should be mined for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++) chainActive.Tip()->GetAncestor(chainActive.Tip()->nHeight - i)->nTime += 512; //Trick the MedianTimePast @@ -486,7 +480,6 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey)); BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 5); - delete pblocktemplate; chainActive.Tip()->nHeight--; SetMockTime(0); diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index c68320ba8b8e6..98b02a1f6fc07 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -22,6 +22,8 @@ #include "test/testutil.h" +#include + #include #include #include @@ -98,7 +100,7 @@ CBlock TestChain100Setup::CreateAndProcessBlock(const std::vector& txns, const CScript& scriptPubKey) { const CChainParams& chainparams = Params(); - CBlockTemplate *pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey); + std::unique_ptr pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey); CBlock& block = pblocktemplate->block; // Replace mempool-selected txns with just coinbase plus passed-in txns: @@ -115,7 +117,6 @@ TestChain100Setup::CreateAndProcessBlock(const std::vector& ProcessNewBlock(state, chainparams, NULL, &block, true, NULL); CBlock result = block; - delete pblocktemplate; return result; } From 1e9aab0dbfcb844458b5f221a9af0141bba6280f Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Sat, 18 Jun 2016 20:53:17 -0400 Subject: [PATCH 0506/1802] Remove sipa's old revoked key from verify-commits Now that the trusted root is past all commits signed by that key we don't need it in the trusted-keys list, nor do we need to whitelist those commits in allow-revsig-commits --- contrib/verify-commits/allow-revsig-commits | 2 -- contrib/verify-commits/trusted-keys | 1 - 2 files changed, 3 deletions(-) diff --git a/contrib/verify-commits/allow-revsig-commits b/contrib/verify-commits/allow-revsig-commits index 31aeb8f3d38bb..e69de29bb2d1d 100644 --- a/contrib/verify-commits/allow-revsig-commits +++ b/contrib/verify-commits/allow-revsig-commits @@ -1,2 +0,0 @@ -586a29253dabec3ca0f1ccba9091daabd16b8411 -eddaba7b5692288087a926da5733e86b47274e4e diff --git a/contrib/verify-commits/trusted-keys b/contrib/verify-commits/trusted-keys index 9c36d58cd2a30..75242c2a9760b 100644 --- a/contrib/verify-commits/trusted-keys +++ b/contrib/verify-commits/trusted-keys @@ -1,5 +1,4 @@ 71A3B16735405025D447E8F274810B012346C9A6 -1F4410F6A89268CE3197A84C57896D2FF8F0B657 3F1888C6DCA92A6499C4911FDBA1A67379A1A931 32EE5C4C3FA15CCADB46ABE529D4BCB6416F53EC FE09B823E6D83A3BC7983EAA2D7F2372E50FE137 From 96806c39f4ef395975c0cd7d654dcb71c4790be2 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 18 Jun 2016 18:16:36 +0200 Subject: [PATCH 0507/1802] Stop trimming when mapTx is empty --- src/txmempool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 205ffd6379351..18c54b08bc2d3 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -1075,7 +1075,7 @@ void CTxMemPool::TrimToSize(size_t sizelimit, std::vector* pvNoSpendsRe unsigned nTxnRemoved = 0; CFeeRate maxFeeRateRemoved(0); - while (DynamicMemoryUsage() > sizelimit) { + while (!mapTx.empty() && DynamicMemoryUsage() > sizelimit) { indexed_transaction_set::index::type::iterator it = mapTx.get().begin(); // We set the new mempool min fee to the feerate of the removed set, plus the From 7c29ec94490a2fb0b5f9aec56c89d0a9a58eec79 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sun, 10 Apr 2016 18:52:32 -0700 Subject: [PATCH 0508/1802] If AcceptBlockHeader returns true, pindex will be set. Assert this instead of checking (and then dref'ing later anyway) to make sure no one thinks they can change that postcondition of AcceptBlockHeader.. --- src/main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index bdb3457f8eeb7..378d2c70227e3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5218,10 +5218,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } } - if (pindexLast) - UpdateBlockAvailability(pfrom->GetId(), pindexLast->GetBlockHash()); + assert(pindexLast); + UpdateBlockAvailability(pfrom->GetId(), pindexLast->GetBlockHash()); - if (nCount == MAX_HEADERS_RESULTS && pindexLast && hasNewHeaders) { + if (nCount == MAX_HEADERS_RESULTS && hasNewHeaders) { // Headers message had its maximum size; the peer may have more headers. // TODO: optimize: if pindexLast is an ancestor of chainActive.Tip or pindexBestHeader, continue // from there instead. From cbda71cf04ef6f2abe6eaa56c3140a6f5cff4feb Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Wed, 8 Jun 2016 16:12:52 -0700 Subject: [PATCH 0509/1802] Move context-required checks from CheckBlockHeader to Contextual... --- src/main.cpp | 28 ++++++++++++++-------------- src/main.h | 6 +++--- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 378d2c70227e3..7d267bef7d984 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2241,7 +2241,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin int64_t nTimeStart = GetTimeMicros(); // Check it again in case a previous version let a bad block in - if (!CheckBlock(block, state, chainparams.GetConsensus(), GetAdjustedTime(), !fJustCheck, !fJustCheck)) + if (!CheckBlock(block, state, chainparams.GetConsensus(), !fJustCheck, !fJustCheck)) return error("%s: Consensus::CheckBlock: %s", __func__, FormatStateMessage(state)); // verify that the view's current state corresponds to the previous block @@ -3258,20 +3258,16 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne return true; } -bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, int64_t nAdjustedTime, bool fCheckPOW) +bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW) { // Check proof of work matches claimed amount if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits, consensusParams)) return state.DoS(50, false, REJECT_INVALID, "high-hash", false, "proof of work failed"); - // Check timestamp - if (block.GetBlockTime() > nAdjustedTime + 2 * 60 * 60) - return state.Invalid(false, REJECT_INVALID, "time-too-new", "block timestamp too far in the future"); - return true; } -bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::Params& consensusParams, int64_t nAdjustedTime, bool fCheckPOW, bool fCheckMerkleRoot) +bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW, bool fCheckMerkleRoot) { // These are checks that are independent of context. @@ -3280,7 +3276,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P // Check that the header is valid (particularly PoW). This is mostly // redundant with the call in AcceptBlockHeader. - if (!CheckBlockHeader(block, state, consensusParams, nAdjustedTime, fCheckPOW)) + if (!CheckBlockHeader(block, state, consensusParams, fCheckPOW)) return false; // Check the merkle root. @@ -3346,7 +3342,7 @@ static bool CheckIndexAgainstCheckpoint(const CBlockIndex* pindexPrev, CValidati return true; } -bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex * const pindexPrev) +bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex * const pindexPrev, int64_t nAdjustedTime) { // Check proof of work if (block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams)) @@ -3356,6 +3352,10 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast()) return state.Invalid(false, REJECT_INVALID, "time-too-old", "block's timestamp is too early"); + // Check timestamp + if (block.GetBlockTime() > nAdjustedTime + 2 * 60 * 60) + return state.Invalid(false, REJECT_INVALID, "time-too-new", "block timestamp too far in the future"); + // Reject outdated version blocks when 95% (75% on testnet) of the network has upgraded: for (int32_t version = 2; version < 5; ++version) // check for version 2, 3 and 4 upgrades if (block.nVersion < version && IsSuperMajority(version, pindexPrev, consensusParams.nMajorityRejectBlockOutdated, consensusParams)) @@ -3420,7 +3420,7 @@ static bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state return true; } - if (!CheckBlockHeader(block, state, chainparams.GetConsensus(), GetAdjustedTime())) + if (!CheckBlockHeader(block, state, chainparams.GetConsensus())) return error("%s: Consensus::CheckBlockHeader: %s, %s", __func__, hash.ToString(), FormatStateMessage(state)); // Get prev block index @@ -3436,7 +3436,7 @@ static bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state if (fCheckpointsEnabled && !CheckIndexAgainstCheckpoint(pindexPrev, state, chainparams, hash)) return error("%s: CheckIndexAgainstCheckpoint(): %s", __func__, state.GetRejectReason().c_str()); - if (!ContextualCheckBlockHeader(block, state, chainparams.GetConsensus(), pindexPrev)) + if (!ContextualCheckBlockHeader(block, state, chainparams.GetConsensus(), pindexPrev, GetAdjustedTime())) return error("%s: Consensus::ContextualCheckBlockHeader: %s, %s", __func__, hash.ToString(), FormatStateMessage(state)); } if (pindex == NULL) @@ -3569,9 +3569,9 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, indexDummy.nHeight = pindexPrev->nHeight + 1; // NOTE: CheckBlockHeader is called by CheckBlock - if (!ContextualCheckBlockHeader(block, state, chainparams.GetConsensus(), pindexPrev)) + if (!ContextualCheckBlockHeader(block, state, chainparams.GetConsensus(), pindexPrev, GetAdjustedTime())) return error("%s: Consensus::ContextualCheckBlockHeader: %s", __func__, FormatStateMessage(state)); - if (!CheckBlock(block, state, chainparams.GetConsensus(), GetAdjustedTime(), fCheckPOW, fCheckMerkleRoot)) + if (!CheckBlock(block, state, chainparams.GetConsensus(), fCheckPOW, fCheckMerkleRoot)) return error("%s: Consensus::CheckBlock: %s", __func__, FormatStateMessage(state)); if (!ContextualCheckBlock(block, state, pindexPrev)) return error("%s: Consensus::ContextualCheckBlock: %s", __func__, FormatStateMessage(state)); @@ -3916,7 +3916,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus())) return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); // check level 1: verify block validity - if (nCheckLevel >= 1 && !CheckBlock(block, state, chainparams.GetConsensus(), GetAdjustedTime())) + if (nCheckLevel >= 1 && !CheckBlock(block, state, chainparams.GetConsensus())) return error("%s: *** found bad block at %d, hash=%s (%s)\n", __func__, pindex->nHeight, pindex->GetBlockHash().ToString(), FormatStateMessage(state)); // check level 2: verify undo validity diff --git a/src/main.h b/src/main.h index e2bfdfdf6ee36..56e81ec29cd7a 100644 --- a/src/main.h +++ b/src/main.h @@ -425,13 +425,13 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus /** Functions for validating blocks and updating the block tree */ /** Context-independent validity checks */ -bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, int64_t nAdjustedTime, bool fCheckPOW = true); -bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::Params& consensusParams, int64_t nAdjustedTime, bool fCheckPOW = true, bool fCheckMerkleRoot = true); +bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW = true); +bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW = true, bool fCheckMerkleRoot = true); /** Context-dependent validity checks. * By "context", we mean only the previous block headers, but not the UTXO * set; UTXO-related validity checks are done in ConnectBlock(). */ -bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex* pindexPrev); +bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex* pindexPrev, int64_t nAdjustedTime); bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex *pindexPrev); /** Apply the effects of this block (with given index) on the UTXO set represented by coins. From 5249daca5a8c4ebdc6c9a3090af0e1bdddcfba1b Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Wed, 18 May 2016 13:11:42 -0700 Subject: [PATCH 0510/1802] Add COMPACTSIZE wrapper similar to VARINT for serialization --- src/serialize.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/serialize.h b/src/serialize.h index 5c2db9d332ce3..378ed39074ea3 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -373,6 +373,7 @@ I ReadVarInt(Stream& is) #define FLATDATA(obj) REF(CFlatData((char*)&(obj), (char*)&(obj) + sizeof(obj))) #define VARINT(obj) REF(WrapVarInt(REF(obj))) +#define COMPACTSIZE(obj) REF(CCompactSize(REF(obj))) #define LIMITED_STRING(obj,n) REF(LimitedString< n >(REF(obj))) /** @@ -443,6 +444,28 @@ class CVarInt } }; +class CCompactSize +{ +protected: + uint64_t &n; +public: + CCompactSize(uint64_t& nIn) : n(nIn) { } + + unsigned int GetSerializeSize(int, int) const { + return GetSizeOfCompactSize(n); + } + + template + void Serialize(Stream &s, int, int) const { + WriteCompactSize(s, n); + } + + template + void Unserialize(Stream& s, int, int) { + n = ReadCompactSize(s); + } +}; + template class LimitedString { From 85ad31ede7bc338079c8ae643542fde7ad83ce55 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 15 Apr 2016 12:23:57 -0700 Subject: [PATCH 0511/1802] Add partial-block block encodings API --- src/Makefile.am | 2 + src/blockencodings.cpp | 158 +++++++++++++++++++++++++++++++ src/blockencodings.h | 205 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 365 insertions(+) create mode 100644 src/blockencodings.cpp create mode 100644 src/blockencodings.h diff --git a/src/Makefile.am b/src/Makefile.am index 3df8e267bb335..e3eaacdb4c983 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -74,6 +74,7 @@ BITCOIN_CORE_H = \ addrman.h \ base58.h \ bloom.h \ + blockencodings.h \ chain.h \ chainparams.h \ chainparamsbase.h \ @@ -163,6 +164,7 @@ libbitcoin_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_server_a_SOURCES = \ addrman.cpp \ bloom.cpp \ + blockencodings.cpp \ chain.cpp \ checkpoints.cpp \ httprpc.cpp \ diff --git a/src/blockencodings.cpp b/src/blockencodings.cpp new file mode 100644 index 0000000000000..c6b79f4201c55 --- /dev/null +++ b/src/blockencodings.cpp @@ -0,0 +1,158 @@ +// Copyright (c) 2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "blockencodings.h" +#include "consensus/consensus.h" +#include "consensus/validation.h" +#include "chainparams.h" +#include "hash.h" +#include "random.h" +#include "streams.h" +#include "txmempool.h" +#include "main.h" + +#include + +#define MIN_TRANSACTION_SIZE (::GetSerializeSize(CTransaction(), SER_NETWORK, PROTOCOL_VERSION)) + +CBlockHeaderAndShortTxIDs::CBlockHeaderAndShortTxIDs(const CBlock& block) : + nonce(GetRand(std::numeric_limits::max())), + shorttxids(block.vtx.size() - 1), prefilledtxn(1), header(block) { + FillShortTxIDSelector(); + //TODO: Use our mempool prior to block acceptance to predictively fill more than just the coinbase + prefilledtxn[0] = {0, block.vtx[0]}; + for (size_t i = 1; i < block.vtx.size(); i++) { + const CTransaction& tx = block.vtx[i]; + shorttxids[i - 1] = GetShortID(tx.GetHash()); + } +} + +void CBlockHeaderAndShortTxIDs::FillShortTxIDSelector() const { + CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); + stream << header << nonce; + CSHA256 hasher; + hasher.Write((unsigned char*)&(*stream.begin()), stream.end() - stream.begin()); + uint256 shorttxidhash; + hasher.Finalize(shorttxidhash.begin()); + shorttxidk0 = shorttxidhash.GetUint64(0); + shorttxidk1 = shorttxidhash.GetUint64(1); +} + +uint64_t CBlockHeaderAndShortTxIDs::GetShortID(const uint256& txhash) const { + static_assert(SHORTTXIDS_LENGTH == 6, "shorttxids calculation assumes 6-byte shorttxids"); + return SipHashUint256(shorttxidk0, shorttxidk1, txhash) & 0xffffffffffffL; +} + + + +ReadStatus PartiallyDownloadedBlock::InitData(const CBlockHeaderAndShortTxIDs& cmpctblock) { + if (cmpctblock.header.IsNull() || (cmpctblock.shorttxids.empty() && cmpctblock.prefilledtxn.empty())) + return READ_STATUS_INVALID; + if (cmpctblock.shorttxids.size() + cmpctblock.prefilledtxn.size() > MAX_BLOCK_SIZE / MIN_TRANSACTION_SIZE) + return READ_STATUS_INVALID; + + assert(header.IsNull() && txn_available.empty()); + header = cmpctblock.header; + txn_available.resize(cmpctblock.BlockTxCount()); + + int32_t lastprefilledindex = -1; + for (size_t i = 0; i < cmpctblock.prefilledtxn.size(); i++) { + if (cmpctblock.prefilledtxn[i].tx.IsNull()) + return READ_STATUS_INVALID; + + lastprefilledindex += cmpctblock.prefilledtxn[i].index + 1; //index is a uint16_t, so cant overflow here + if (lastprefilledindex > std::numeric_limits::max()) + return READ_STATUS_INVALID; + if ((uint32_t)lastprefilledindex > cmpctblock.shorttxids.size() + i) { + // If we are inserting a tx at an index greater than our full list of shorttxids + // plus the number of prefilled txn we've inserted, then we have txn for which we + // have neither a prefilled txn or a shorttxid! + return READ_STATUS_INVALID; + } + txn_available[lastprefilledindex] = std::make_shared(cmpctblock.prefilledtxn[i].tx); + } + + // Calculate map of txids -> positions and check mempool to see what we have (or dont) + // Because well-formed cmpctblock messages will have a (relatively) uniform distribution + // of short IDs, any highly-uneven distribution of elements can be safely treated as a + // READ_STATUS_FAILED. + std::unordered_map shorttxids(cmpctblock.shorttxids.size()); + uint16_t index_offset = 0; + for (size_t i = 0; i < cmpctblock.shorttxids.size(); i++) { + while (txn_available[i + index_offset]) + index_offset++; + shorttxids[cmpctblock.shorttxids[i]] = i + index_offset; + // Bucket selection is a simple Binomial distribution. If we assume blocks of + // 10,000 transactions, allowing up to 12 elements per bucket should only fail + // once every ~1.3 million blocks and once every 74,000 blocks in a worst-case + // 16,000-transaction block. + if (shorttxids.bucket_size(shorttxids.bucket(cmpctblock.shorttxids[i])) > 12) + return READ_STATUS_FAILED; + } + // TODO: in the shortid-collision case, we should instead request both transactions + // which collided. Falling back to full-block-request here is overkill. + if (shorttxids.size() != cmpctblock.shorttxids.size()) + return READ_STATUS_FAILED; // Short ID collision + + std::vector have_txn(txn_available.size()); + LOCK(pool->cs); + for (CTxMemPool::txiter it = pool->mapTx.begin(); it != pool->mapTx.end(); it++) { + std::unordered_map::iterator idit = shorttxids.find(cmpctblock.GetShortID(it->GetTx().GetHash())); + if (idit != shorttxids.end()) { + if (!have_txn[idit->second]) { + txn_available[idit->second] = it->GetSharedTx(); + have_txn[idit->second] = true; + } else { + // If we find two mempool txn that match the short id, just request it. + // This should be rare enough that the extra bandwidth doesn't matter, + // but eating a round-trip due to FillBlock failure would be annoying + txn_available[idit->second].reset(); + } + } + // Though ideally we'd continue scanning for the two-txn-match-shortid case, + // the performance win of an early exit here is too good to pass up and worth + // the extra risk. + if (mempool_count == shorttxids.size()) + break; + } + + return READ_STATUS_OK; +} + +bool PartiallyDownloadedBlock::IsTxAvailable(size_t index) const { + assert(!header.IsNull()); + assert(index < txn_available.size()); + return txn_available[index] ? true : false; +} + +ReadStatus PartiallyDownloadedBlock::FillBlock(CBlock& block, const std::vector& vtx_missing) const { + assert(!header.IsNull()); + block = header; + block.vtx.resize(txn_available.size()); + + size_t tx_missing_offset = 0; + for (size_t i = 0; i < txn_available.size(); i++) { + if (!txn_available[i]) { + if (vtx_missing.size() <= tx_missing_offset) + return READ_STATUS_INVALID; + block.vtx[i] = vtx_missing[tx_missing_offset++]; + } else + block.vtx[i] = *txn_available[i]; + } + if (vtx_missing.size() != tx_missing_offset) + return READ_STATUS_INVALID; + + CValidationState state; + if (!CheckBlock(block, state, Params().GetConsensus())) { + // TODO: We really want to just check merkle tree manually here, + // but that is expensive, and CheckBlock caches a block's + // "checked-status" (in the CBlock?). CBlock should be able to + // check its own merkle root and cache that check. + if (state.CorruptionPossible()) + return READ_STATUS_FAILED; // Possible Short ID collision + return READ_STATUS_INVALID; + } + + return READ_STATUS_OK; +} diff --git a/src/blockencodings.h b/src/blockencodings.h new file mode 100644 index 0000000000000..adc60c85d0ecf --- /dev/null +++ b/src/blockencodings.h @@ -0,0 +1,205 @@ +// Copyright (c) 2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_BLOCK_ENCODINGS_H +#define BITCOIN_BLOCK_ENCODINGS_H + +#include "primitives/block.h" + +#include + +class CTxMemPool; + +// Dumb helper to handle CTransaction compression at serialize-time +struct TransactionCompressor { +private: + CTransaction& tx; +public: + TransactionCompressor(CTransaction& txIn) : tx(txIn) {} + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + READWRITE(tx); //TODO: Compress tx encoding + } +}; + +class BlockTransactionsRequest { +public: + // A BlockTransactionsRequest message + uint256 blockhash; + std::vector indexes; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + READWRITE(blockhash); + uint64_t indexes_size = (uint64_t)indexes.size(); + READWRITE(COMPACTSIZE(indexes_size)); + if (ser_action.ForRead()) { + size_t i = 0; + while (indexes.size() < indexes_size) { + indexes.resize(std::min((uint64_t)(1000 + indexes.size()), indexes_size)); + for (; i < indexes.size(); i++) { + uint64_t index = 0; + READWRITE(COMPACTSIZE(index)); + if (index > std::numeric_limits::max()) + throw std::ios_base::failure("index overflowed 16 bits"); + indexes[i] = index; + } + } + + uint16_t offset = 0; + for (size_t i = 0; i < indexes.size(); i++) { + if (uint64_t(indexes[i]) + uint64_t(offset) > std::numeric_limits::max()) + throw std::ios_base::failure("indexes overflowed 16 bits"); + indexes[i] = indexes[i] + offset; + offset = indexes[i] + 1; + } + } else { + for (size_t i = 0; i < indexes.size(); i++) { + uint64_t index = indexes[i] - (i == 0 ? 0 : (indexes[i - 1] + 1)); + READWRITE(COMPACTSIZE(index)); + } + } + } +}; + +class BlockTransactions { +public: + // A BlockTransactions message + uint256 blockhash; + std::vector txn; + + BlockTransactions() {} + BlockTransactions(const BlockTransactionsRequest& req) : + blockhash(req.blockhash), txn(req.indexes.size()) {} + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + READWRITE(blockhash); + uint64_t txn_size = (uint64_t)txn.size(); + READWRITE(COMPACTSIZE(txn_size)); + if (ser_action.ForRead()) { + size_t i = 0; + while (txn.size() < txn_size) { + txn.resize(std::min((uint64_t)(1000 + txn.size()), txn_size)); + for (; i < txn.size(); i++) + READWRITE(REF(TransactionCompressor(txn[i]))); + } + } else { + for (size_t i = 0; i < txn.size(); i++) + READWRITE(REF(TransactionCompressor(txn[i]))); + } + } +}; + +// Dumb serialization/storage-helper for CBlockHeaderAndShortTxIDs and PartiallyDownlaodedBlock +struct PrefilledTransaction { + // Used as an offset since last prefilled tx in CBlockHeaderAndShortTxIDs, + // as a proper transaction-in-block-index in PartiallyDownloadedBlock + uint16_t index; + CTransaction tx; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + uint64_t idx = index; + READWRITE(COMPACTSIZE(idx)); + if (idx > std::numeric_limits::max()) + throw std::ios_base::failure("index overflowed 16-bits"); + index = idx; + READWRITE(REF(TransactionCompressor(tx))); + } +}; + +typedef enum ReadStatus_t +{ + READ_STATUS_OK, + READ_STATUS_INVALID, // Invalid object, peer is sending bogus crap + READ_STATUS_FAILED, // Failed to process object +} ReadStatus; + +class CBlockHeaderAndShortTxIDs { +private: + mutable uint64_t shorttxidk0, shorttxidk1; + uint64_t nonce; + + void FillShortTxIDSelector() const; + + friend class PartiallyDownloadedBlock; + + static const int SHORTTXIDS_LENGTH = 6; +protected: + std::vector shorttxids; + std::vector prefilledtxn; + +public: + CBlockHeader header; + + // Dummy for deserialization + CBlockHeaderAndShortTxIDs() {} + + CBlockHeaderAndShortTxIDs(const CBlock& block); + + uint64_t GetShortID(const uint256& txhash) const; + + size_t BlockTxCount() const { return shorttxids.size() + prefilledtxn.size(); } + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + READWRITE(header); + READWRITE(nonce); + + uint64_t shorttxids_size = (uint64_t)shorttxids.size(); + READWRITE(COMPACTSIZE(shorttxids_size)); + if (ser_action.ForRead()) { + size_t i = 0; + while (shorttxids.size() < shorttxids_size) { + shorttxids.resize(std::min((uint64_t)(1000 + shorttxids.size()), shorttxids_size)); + for (; i < shorttxids.size(); i++) { + uint32_t lsb = 0; uint16_t msb = 0; + READWRITE(lsb); + READWRITE(msb); + shorttxids[i] = (uint64_t(msb) << 32) | uint64_t(lsb); + static_assert(SHORTTXIDS_LENGTH == 6, "shorttxids serialization assumes 6-byte shorttxids"); + } + } + } else { + for (size_t i = 0; i < shorttxids.size(); i++) { + uint32_t lsb = shorttxids[i] & 0xffffffff; + uint16_t msb = (shorttxids[i] >> 32) & 0xffff; + READWRITE(lsb); + READWRITE(msb); + } + } + + READWRITE(prefilledtxn); + + if (ser_action.ForRead()) + FillShortTxIDSelector(); + } +}; + +class PartiallyDownloadedBlock { +protected: + std::vector > txn_available; + CTxMemPool* pool; +public: + CBlockHeader header; + PartiallyDownloadedBlock(CTxMemPool* poolIn) : pool(poolIn) {} + + ReadStatus InitData(const CBlockHeaderAndShortTxIDs& cmpctblock); + bool IsTxAvailable(size_t index) const; + ReadStatus FillBlock(CBlock& block, const std::vector& vtx_missing) const; +}; + +#endif From f4f8f14adc79f71eb3cfd3a8d6dbfe9878d1e3f6 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 25 Apr 2016 17:04:13 -0700 Subject: [PATCH 0512/1802] Add TestMemPoolEntryHelper::FromTx version for CTransaction --- src/test/test_bitcoin.cpp | 6 +++++- src/test/test_bitcoin.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index c68320ba8b8e6..199670918830f 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -126,7 +126,11 @@ TestChain100Setup::~TestChain100Setup() CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(CMutableTransaction &tx, CTxMemPool *pool) { CTransaction txn(tx); - bool hasNoDependencies = pool ? pool->HasNoInputsOf(tx) : hadNoDependencies; + return FromTx(txn, pool); +} + +CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(CTransaction &txn, CTxMemPool *pool) { + bool hasNoDependencies = pool ? pool->HasNoInputsOf(txn) : hadNoDependencies; // Hack to assume either its completely dependent on other mempool txs or not at all CAmount inChainValue = hasNoDependencies ? txn.GetValueOut() : 0; diff --git a/src/test/test_bitcoin.h b/src/test/test_bitcoin.h index 57f66f6c6d0dc..78b87e7109b7d 100644 --- a/src/test/test_bitcoin.h +++ b/src/test/test_bitcoin.h @@ -78,6 +78,7 @@ struct TestMemPoolEntryHelper hadNoDependencies(false), spendsCoinbase(false), sigOpCount(1) { } CTxMemPoolEntry FromTx(CMutableTransaction &tx, CTxMemPool *pool = NULL); + CTxMemPoolEntry FromTx(CTransaction &tx, CTxMemPool *pool = NULL); // Change the default value TestMemPoolEntryHelper &Fee(CAmount _fee) { nFee = _fee; return *this; } From e3b2222144a0def7fa61822bdd11fb7e6bdc70ec Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 25 Apr 2016 15:51:08 -0700 Subject: [PATCH 0513/1802] Add some blockencodings tests --- src/Makefile.test.include | 1 + src/test/blockencodings_tests.cpp | 315 ++++++++++++++++++++++++++++++ 2 files changed, 316 insertions(+) create mode 100644 src/test/blockencodings_tests.cpp diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 41d811fb5400f..c8918eb53f82f 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -45,6 +45,7 @@ BITCOIN_TESTS =\ test/base58_tests.cpp \ test/base64_tests.cpp \ test/bip32_tests.cpp \ + test/blockencodings_tests.cpp \ test/bloom_tests.cpp \ test/Checkpoints_tests.cpp \ test/coins_tests.cpp \ diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp new file mode 100644 index 0000000000000..3884bf3fe37c3 --- /dev/null +++ b/src/test/blockencodings_tests.cpp @@ -0,0 +1,315 @@ +// Copyright (c) 2011-2015 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 "blockencodings.h" +#include "consensus/merkle.h" +#include "chainparams.h" +#include "random.h" + +#include "test/test_bitcoin.h" + +#include + +struct RegtestingSetup : public TestingSetup { + RegtestingSetup() : TestingSetup(CBaseChainParams::REGTEST) {} +}; + +BOOST_FIXTURE_TEST_SUITE(blockencodings_tests, RegtestingSetup) + +static CBlock BuildBlockTestCase() { + CBlock block; + CMutableTransaction tx; + tx.vin.resize(1); + tx.vin[0].scriptSig.resize(10); + tx.vout.resize(1); + tx.vout[0].nValue = 42; + + block.vtx.resize(3); + block.vtx[0] = tx; + block.nVersion = 42; + block.hashPrevBlock = GetRandHash(); + block.nBits = 0x207fffff; + + tx.vin[0].prevout.hash = GetRandHash(); + tx.vin[0].prevout.n = 0; + block.vtx[1] = tx; + + tx.vin.resize(10); + for (size_t i = 0; i < tx.vin.size(); i++) { + tx.vin[i].prevout.hash = GetRandHash(); + tx.vin[i].prevout.n = 0; + } + block.vtx[2] = tx; + + bool mutated; + block.hashMerkleRoot = BlockMerkleRoot(block, &mutated); + assert(!mutated); + while (!CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus())) ++block.nNonce; + return block; +} + +// Number of shared use_counts we expect for a tx we havent touched +// == 2 (mempool + our copy from the GetSharedTx call) +#define SHARED_TX_OFFSET 2 + +BOOST_AUTO_TEST_CASE(SimpleRoundTripTest) +{ + CTxMemPool pool(CFeeRate(0)); + TestMemPoolEntryHelper entry; + CBlock block(BuildBlockTestCase()); + + pool.addUnchecked(block.vtx[2].GetHash(), entry.FromTx(block.vtx[2])); + BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2].GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0); + + // Do a simple ShortTxIDs RT + { + CBlockHeaderAndShortTxIDs shortIDs(block); + + CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); + stream << shortIDs; + + CBlockHeaderAndShortTxIDs shortIDs2; + stream >> shortIDs2; + + PartiallyDownloadedBlock partialBlock(&pool); + BOOST_CHECK(partialBlock.InitData(shortIDs2) == READ_STATUS_OK); + BOOST_CHECK( partialBlock.IsTxAvailable(0)); + BOOST_CHECK(!partialBlock.IsTxAvailable(1)); + BOOST_CHECK( partialBlock.IsTxAvailable(2)); + + BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2].GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1); + + std::list removed; + pool.removeRecursive(block.vtx[2], removed); + BOOST_CHECK_EQUAL(removed.size(), 1); + + CBlock block2; + std::vector vtx_missing; + BOOST_CHECK(partialBlock.FillBlock(block2, vtx_missing) == READ_STATUS_INVALID); // No transactions + + vtx_missing.push_back(block.vtx[2]); // Wrong transaction + partialBlock.FillBlock(block2, vtx_missing); // Current implementation doesn't check txn here, but don't require that + bool mutated; + BOOST_CHECK(block.hashMerkleRoot != BlockMerkleRoot(block2, &mutated)); + + vtx_missing[0] = block.vtx[1]; + CBlock block3; + BOOST_CHECK(partialBlock.FillBlock(block3, vtx_missing) == READ_STATUS_OK); + BOOST_CHECK_EQUAL(block.GetHash().ToString(), block3.GetHash().ToString()); + BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block3, &mutated).ToString()); + BOOST_CHECK(!mutated); + } +} + +class TestHeaderAndShortIDs { + // Utility to encode custom CBlockHeaderAndShortTxIDs +public: + CBlockHeader header; + uint64_t nonce; + std::vector shorttxids; + std::vector prefilledtxn; + + TestHeaderAndShortIDs(const CBlockHeaderAndShortTxIDs& orig) { + CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); + stream << orig; + stream >> *this; + } + TestHeaderAndShortIDs(const CBlock& block) : + TestHeaderAndShortIDs(CBlockHeaderAndShortTxIDs(block)) {} + + uint64_t GetShortID(const uint256& txhash) const { + CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); + stream << *this; + CBlockHeaderAndShortTxIDs base; + stream >> base; + return base.GetShortID(txhash); + } + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + READWRITE(header); + READWRITE(nonce); + size_t shorttxids_size = shorttxids.size(); + READWRITE(VARINT(shorttxids_size)); + shorttxids.resize(shorttxids_size); + for (size_t i = 0; i < shorttxids.size(); i++) { + uint32_t lsb = shorttxids[i] & 0xffffffff; + uint16_t msb = (shorttxids[i] >> 32) & 0xffff; + READWRITE(lsb); + READWRITE(msb); + shorttxids[i] = (uint64_t(msb) << 32) | uint64_t(lsb); + } + READWRITE(prefilledtxn); + } +}; + +BOOST_AUTO_TEST_CASE(NonCoinbasePreforwardRTTest) +{ + CTxMemPool pool(CFeeRate(0)); + TestMemPoolEntryHelper entry; + CBlock block(BuildBlockTestCase()); + + pool.addUnchecked(block.vtx[2].GetHash(), entry.FromTx(block.vtx[2])); + BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2].GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0); + + // Test with pre-forwarding tx 1, but not coinbase + { + TestHeaderAndShortIDs shortIDs(block); + shortIDs.prefilledtxn.resize(1); + shortIDs.prefilledtxn[0] = {1, block.vtx[1]}; + shortIDs.shorttxids.resize(2); + shortIDs.shorttxids[0] = shortIDs.GetShortID(block.vtx[0].GetHash()); + shortIDs.shorttxids[1] = shortIDs.GetShortID(block.vtx[2].GetHash()); + + CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); + stream << shortIDs; + + CBlockHeaderAndShortTxIDs shortIDs2; + stream >> shortIDs2; + + PartiallyDownloadedBlock partialBlock(&pool); + BOOST_CHECK(partialBlock.InitData(shortIDs2) == READ_STATUS_OK); + BOOST_CHECK(!partialBlock.IsTxAvailable(0)); + BOOST_CHECK( partialBlock.IsTxAvailable(1)); + BOOST_CHECK( partialBlock.IsTxAvailable(2)); + + BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2].GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1); + + CBlock block2; + std::vector vtx_missing; + BOOST_CHECK(partialBlock.FillBlock(block2, vtx_missing) == READ_STATUS_INVALID); // No transactions + + vtx_missing.push_back(block.vtx[1]); // Wrong transaction + partialBlock.FillBlock(block2, vtx_missing); // Current implementation doesn't check txn here, but don't require that + bool mutated; + BOOST_CHECK(block.hashMerkleRoot != BlockMerkleRoot(block2, &mutated)); + + vtx_missing[0] = block.vtx[0]; + CBlock block3; + BOOST_CHECK(partialBlock.FillBlock(block3, vtx_missing) == READ_STATUS_OK); + BOOST_CHECK_EQUAL(block.GetHash().ToString(), block3.GetHash().ToString()); + BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block3, &mutated).ToString()); + BOOST_CHECK(!mutated); + + BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2].GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1); + } + BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2].GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0); +} + +BOOST_AUTO_TEST_CASE(SufficientPreforwardRTTest) +{ + CTxMemPool pool(CFeeRate(0)); + TestMemPoolEntryHelper entry; + CBlock block(BuildBlockTestCase()); + + pool.addUnchecked(block.vtx[1].GetHash(), entry.FromTx(block.vtx[1])); + BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[1].GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0); + + // Test with pre-forwarding coinbase + tx 2 with tx 1 in mempool + { + TestHeaderAndShortIDs shortIDs(block); + shortIDs.prefilledtxn.resize(2); + shortIDs.prefilledtxn[0] = {0, block.vtx[0]}; + shortIDs.prefilledtxn[1] = {1, block.vtx[2]}; // id == 1 as it is 1 after index 1 + shortIDs.shorttxids.resize(1); + shortIDs.shorttxids[0] = shortIDs.GetShortID(block.vtx[1].GetHash()); + + CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); + stream << shortIDs; + + CBlockHeaderAndShortTxIDs shortIDs2; + stream >> shortIDs2; + + PartiallyDownloadedBlock partialBlock(&pool); + BOOST_CHECK(partialBlock.InitData(shortIDs2) == READ_STATUS_OK); + BOOST_CHECK( partialBlock.IsTxAvailable(0)); + BOOST_CHECK( partialBlock.IsTxAvailable(1)); + BOOST_CHECK( partialBlock.IsTxAvailable(2)); + + BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[1].GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1); + + CBlock block2; + std::vector vtx_missing; + BOOST_CHECK(partialBlock.FillBlock(block2, vtx_missing) == READ_STATUS_OK); + BOOST_CHECK_EQUAL(block.GetHash().ToString(), block2.GetHash().ToString()); + bool mutated; + BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block2, &mutated).ToString()); + BOOST_CHECK(!mutated); + + BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[1].GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1); + } + BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[1].GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0); +} + +BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest) +{ + CTxMemPool pool(CFeeRate(0)); + CMutableTransaction coinbase; + coinbase.vin.resize(1); + coinbase.vin[0].scriptSig.resize(10); + coinbase.vout.resize(1); + coinbase.vout[0].nValue = 42; + + CBlock block; + block.vtx.resize(1); + block.vtx[0] = coinbase; + block.nVersion = 42; + block.hashPrevBlock = GetRandHash(); + block.nBits = 0x207fffff; + + bool mutated; + block.hashMerkleRoot = BlockMerkleRoot(block, &mutated); + assert(!mutated); + while (!CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus())) ++block.nNonce; + + // Test simple header round-trip with only coinbase + { + CBlockHeaderAndShortTxIDs shortIDs(block); + + CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); + stream << shortIDs; + + CBlockHeaderAndShortTxIDs shortIDs2; + stream >> shortIDs2; + + PartiallyDownloadedBlock partialBlock(&pool); + BOOST_CHECK(partialBlock.InitData(shortIDs2) == READ_STATUS_OK); + BOOST_CHECK(partialBlock.IsTxAvailable(0)); + + CBlock block2; + std::vector vtx_missing; + BOOST_CHECK(partialBlock.FillBlock(block2, vtx_missing) == READ_STATUS_OK); + BOOST_CHECK_EQUAL(block.GetHash().ToString(), block2.GetHash().ToString()); + bool mutated; + BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block2, &mutated).ToString()); + BOOST_CHECK(!mutated); + } +} + +BOOST_AUTO_TEST_CASE(TransactionsRequestSerializationTest) { + BlockTransactionsRequest req1; + req1.blockhash = GetRandHash(); + req1.indexes.resize(4); + req1.indexes[0] = 0; + req1.indexes[1] = 1; + req1.indexes[2] = 3; + req1.indexes[3] = 4; + + CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); + stream << req1; + + BlockTransactionsRequest req2; + stream >> req2; + + BOOST_CHECK_EQUAL(req1.blockhash.ToString(), req2.blockhash.ToString()); + BOOST_CHECK_EQUAL(req1.indexes.size(), req2.indexes.size()); + BOOST_CHECK_EQUAL(req1.indexes[0], req2.indexes[0]); + BOOST_CHECK_EQUAL(req1.indexes[1], req2.indexes[1]); + BOOST_CHECK_EQUAL(req1.indexes[2], req2.indexes[2]); + BOOST_CHECK_EQUAL(req1.indexes[3], req2.indexes[3]); +} + +BOOST_AUTO_TEST_SUITE_END() From 00c40784fe737ca67122fdec6538c450d2a516f3 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 6 Jun 2016 01:26:52 -0700 Subject: [PATCH 0514/1802] Add protocol messages for short-ids blocks --- src/protocol.cpp | 13 +++++++++++-- src/protocol.h | 31 +++++++++++++++++++++++++++++-- src/version.h | 5 ++++- 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/src/protocol.cpp b/src/protocol.cpp index 422ef6f636512..2f90fb764cfbc 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -35,6 +35,10 @@ const char *FILTERCLEAR="filterclear"; const char *REJECT="reject"; const char *SENDHEADERS="sendheaders"; const char *FEEFILTER="feefilter"; +const char *SENDCMPCT="sendcmpct"; +const char *CMPCTBLOCK="cmpctblock"; +const char *GETBLOCKTXN="getblocktxn"; +const char *BLOCKTXN="blocktxn"; }; static const char* ppszTypeName[] = @@ -42,7 +46,8 @@ static const char* ppszTypeName[] = "ERROR", // Should never occur NetMsgType::TX, NetMsgType::BLOCK, - "filtered block" // Should never occur + "filtered block", // Should never occur + "compact block" // Should never occur }; /** All known message types. Keep this in the same order as the list of @@ -70,7 +75,11 @@ const static std::string allNetMessageTypes[] = { NetMsgType::FILTERCLEAR, NetMsgType::REJECT, NetMsgType::SENDHEADERS, - NetMsgType::FEEFILTER + NetMsgType::FEEFILTER, + NetMsgType::SENDCMPCT, + NetMsgType::CMPCTBLOCK, + NetMsgType::GETBLOCKTXN, + NetMsgType::BLOCKTXN, }; const static std::vector allNetMessageTypesVec(allNetMessageTypes, allNetMessageTypes+ARRAYLEN(allNetMessageTypes)); diff --git a/src/protocol.h b/src/protocol.h index ab0a5817839b8..a72813e959c64 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -217,6 +217,32 @@ extern const char *SENDHEADERS; * @since protocol version 70013 as described by BIP133 */ extern const char *FEEFILTER; +/** + * Contains a 1-byte bool and 8-byte LE version number. + * Indicates that a node is willing to provide blocks via "cmpctblock" messages. + * May indicate that a node prefers to receive new block announcements via a + * "cmpctblock" message rather than an "inv", depending on message contents. + * @since protocol version 70014 as described by BIP 152 + */ +extern const char *SENDCMPCT; +/** + * Contains a CBlockHeaderAndShortTxIDs object - providing a header and + * list of "short txids". + * @since protocol version 70014 as described by BIP 152 + */ +extern const char *CMPCTBLOCK; +/** + * Contains a BlockTransactionsRequest + * Peer should respond with "blocktxn" message. + * @since protocol version 70014 as described by BIP 152 + */ +extern const char *GETBLOCKTXN; +/** + * Contains a BlockTransactions. + * Sent in response to a "getblocktxn" message. + * @since protocol version 70014 as described by BIP 152 + */ +extern const char *BLOCKTXN; }; /* Get a vector of all valid message types (see above) */ @@ -315,9 +341,10 @@ class CInv enum { MSG_TX = 1, MSG_BLOCK, - // Nodes may always request a MSG_FILTERED_BLOCK in a getdata, however, - // MSG_FILTERED_BLOCK should not appear in any invs except as a part of getdata. + // Nodes may always request a MSG_FILTERED_BLOCK/MSG_CMPCT_BLOCK in a getdata, however, + // MSG_FILTERED_BLOCK/MSG_CMPCT_BLOCK should not appear in any invs except as a part of getdata. MSG_FILTERED_BLOCK, + MSG_CMPCT_BLOCK, }; #endif // BITCOIN_PROTOCOL_H diff --git a/src/version.h b/src/version.h index 0e1d8a63ced6e..68ccd6d378323 100644 --- a/src/version.h +++ b/src/version.h @@ -9,7 +9,7 @@ * network protocol versioning */ -static const int PROTOCOL_VERSION = 70013; +static const int PROTOCOL_VERSION = 70014; //! initial proto version, to be increased after version/verack negotiation static const int INIT_PROTO_VERSION = 209; @@ -39,4 +39,7 @@ static const int SENDHEADERS_VERSION = 70012; //! "feefilter" tells peers to filter invs to you by fee starts with this version static const int FEEFILTER_VERSION = 70013; +//! shord-id-based block download starts with this version +static const int SHORT_IDS_BLOCKS_VERSION = 70014; + #endif // BITCOIN_VERSION_H From 9c837d5468063917009aef8569ce6ce9ddd340d2 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 11 Apr 2016 01:00:17 -0700 Subject: [PATCH 0515/1802] Add sender-side protocol implementation for CMPCTBLOCK stuff --- src/main.cpp | 110 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 95 insertions(+), 15 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 7d267bef7d984..911c0a648b999 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -274,6 +274,10 @@ struct CNodeState { bool fPreferredDownload; //! Whether this peer wants invs or headers (when possible) for block announcements. bool fPreferHeaders; + //! Whether this peer wants invs or cmpctblocks (when possible) for block announcements. + bool fPreferHeaderAndIDs; + //! Whether this peer will send us cmpctblocks if we request them + bool fProvidesHeaderAndIDs; CNodeState() { fCurrentlyConnected = false; @@ -290,6 +294,8 @@ struct CNodeState { nBlocksInFlightValidHeaders = 0; fPreferredDownload = false; fPreferHeaders = false; + fPreferHeaderAndIDs = false; + fProvidesHeaderAndIDs = false; } }; @@ -4454,7 +4460,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam boost::this_thread::interruption_point(); it++; - if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK) + if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || inv.type == MSG_CMPCT_BLOCK) { bool send = false; BlockMap::iterator mi = mapBlockIndex.find(inv.hash); @@ -4496,7 +4502,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam assert(!"cannot load block from disk"); if (inv.type == MSG_BLOCK) pfrom->PushMessage(NetMsgType::BLOCK, block); - else // MSG_FILTERED_BLOCK) + else if (inv.type == MSG_FILTERED_BLOCK) { LOCK(pfrom->cs_filter); if (pfrom->pfilter) @@ -4516,6 +4522,18 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam // else // no response } + else if (inv.type == MSG_CMPCT_BLOCK) + { + // If a peer is asking for old blocks, we're almost guaranteed + // they wont have a useful mempool to match against a compact block, + // and we dont feel like constructing the object for them, so + // instead we respond with the full, non-compact block. + if (mi->second->nHeight >= chainActive.Height() - 10) { + CBlockHeaderAndShortTxIDs cmpctblock(block); + pfrom->PushMessage(NetMsgType::CMPCTBLOCK, cmpctblock); + } else + pfrom->PushMessage(NetMsgType::BLOCK, block); + } // Trigger the peer node to send a getblocks request for the next batch of inventory if (inv.hash == pfrom->hashContinue) @@ -4839,6 +4857,18 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, State(pfrom->GetId())->fPreferHeaders = true; } + else if (strCommand == NetMsgType::SENDCMPCT) + { + bool fAnnounceUsingCMPCTBLOCK = false; + uint64_t nCMPCTBLOCKVersion = 1; + vRecv >> fAnnounceUsingCMPCTBLOCK >> nCMPCTBLOCKVersion; + if (nCMPCTBLOCKVersion == 1) { + LOCK(cs_main); + State(pfrom->GetId())->fProvidesHeaderAndIDs = true; + State(pfrom->GetId())->fPreferHeaderAndIDs = fAnnounceUsingCMPCTBLOCK; + } + } + else if (strCommand == NetMsgType::INV) { @@ -4982,6 +5012,39 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } + else if (strCommand == NetMsgType::GETBLOCKTXN) + { + BlockTransactionsRequest req; + vRecv >> req; + + BlockMap::iterator it = mapBlockIndex.find(req.blockhash); + if (it == mapBlockIndex.end() || !(it->second->nStatus & BLOCK_HAVE_DATA)) { + Misbehaving(pfrom->GetId(), 100); + LogPrintf("Peer %d sent us a getblocktxn for a block we don't have", pfrom->id); + return true; + } + + if (it->second->nHeight < chainActive.Height() - 10) { + LogPrint("net", "Peer %d sent us a getblocktxn for a block > 10 deep", pfrom->id); + return true; + } + + CBlock block; + assert(ReadBlockFromDisk(block, it->second, chainparams.GetConsensus())); + + BlockTransactions resp(req); + for (size_t i = 0; i < req.indexes.size(); i++) { + if (req.indexes[i] >= block.vtx.size()) { + Misbehaving(pfrom->GetId(), 100); + LogPrintf("Peer %d sent us a getblocktxn with out-of-bounds tx indices", pfrom->id); + return true; + } + resp.txn[i] = block.vtx[req.indexes[i]]; + } + pfrom->PushMessage(NetMsgType::BLOCKTXN, resp); + } + + else if (strCommand == NetMsgType::GETHEADERS) { CBlockLocator locator; @@ -5824,7 +5887,9 @@ bool SendMessages(CNode* pto) // add all to the inv queue. LOCK(pto->cs_inventory); vector vHeaders; - bool fRevertToInv = (!state.fPreferHeaders || pto->vBlockHashesToAnnounce.size() > MAX_BLOCKS_TO_ANNOUNCE); + bool fRevertToInv = ((!state.fPreferHeaders && + (!state.fPreferHeaderAndIDs || pto->vBlockHashesToAnnounce.size() > 1)) || + pto->vBlockHashesToAnnounce.size() > MAX_BLOCKS_TO_ANNOUNCE); CBlockIndex *pBestIndex = NULL; // last header queued for delivery ProcessBlockAvailability(pto->id); // ensure pindexBestKnownBlock is up-to-date @@ -5876,6 +5941,33 @@ bool SendMessages(CNode* pto) } } } + if (!fRevertToInv && !vHeaders.empty()) { + if (vHeaders.size() == 1 && state.fPreferHeaderAndIDs) { + // We only send up to 1 block as header-and-ids, as otherwise + // probably means we're doing an initial-ish-sync or they're slow + LogPrint("net", "%s sending header-and-ids %s to peer %d\n", __func__, + vHeaders.front().GetHash().ToString(), pto->id); + //TODO: Shouldn't need to reload block from disk, but requires refactor + CBlock block; + assert(ReadBlockFromDisk(block, pBestIndex, consensusParams)); + CBlockHeaderAndShortTxIDs cmpctblock(block); + pto->PushMessage(NetMsgType::CMPCTBLOCK, cmpctblock); + state.pindexBestHeaderSent = pBestIndex; + } else if (state.fPreferHeaders) { + if (vHeaders.size() > 1) { + LogPrint("net", "%s: %u headers, range (%s, %s), to peer=%d\n", __func__, + vHeaders.size(), + vHeaders.front().GetHash().ToString(), + vHeaders.back().GetHash().ToString(), pto->id); + } else { + LogPrint("net", "%s: sending header %s to peer=%d\n", __func__, + vHeaders.front().GetHash().ToString(), pto->id); + } + pto->PushMessage(NetMsgType::HEADERS, vHeaders); + state.pindexBestHeaderSent = pBestIndex; + } else + fRevertToInv = true; + } if (fRevertToInv) { // If falling back to using an inv, just try to inv the tip. // The last entry in vBlockHashesToAnnounce was our tip at some point @@ -5901,18 +5993,6 @@ bool SendMessages(CNode* pto) pto->id, hashToAnnounce.ToString()); } } - } else if (!vHeaders.empty()) { - if (vHeaders.size() > 1) { - LogPrint("net", "%s: %u headers, range (%s, %s), to peer=%d\n", __func__, - vHeaders.size(), - vHeaders.front().GetHash().ToString(), - vHeaders.back().GetHash().ToString(), pto->id); - } else { - LogPrint("net", "%s: sending header %s to peer=%d\n", __func__, - vHeaders.front().GetHash().ToString(), pto->id); - } - pto->PushMessage(NetMsgType::HEADERS, vHeaders); - state.pindexBestHeaderSent = pBestIndex; } pto->vBlockHashesToAnnounce.clear(); } From 7734479a012be173b788e48ef1b99852437fe23c Mon Sep 17 00:00:00 2001 From: Will Binns Date: Sun, 19 Jun 2016 14:15:58 -0600 Subject: [PATCH 0516/1802] readme: Omit phrasing; 'new' This commit removes the word "new" in reference to describing Bitcoin, as it has been around for over seven years, now. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8e816e7a43fa4..3c41649c1b8d9 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ https://bitcoincore.org What is Bitcoin? ---------------- -Bitcoin is an experimental new digital currency that enables instant payments to +Bitcoin is an experimental digital currency that enables instant payments to anyone, anywhere in the world. Bitcoin uses peer-to-peer technology to operate with no central authority: managing transactions and issuing money are carried out collectively by the network. Bitcoin Core is the name of open source From d25cd3ec4e8961c5f36c29a65395f52d0db294c5 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 14 Apr 2016 17:45:49 -0700 Subject: [PATCH 0517/1802] Add receiver-side protocol implementation for CMPCTBLOCK stuff --- src/main.cpp | 215 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 207 insertions(+), 8 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 911c0a648b999..26b215f94cc54 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,6 +7,7 @@ #include "addrman.h" #include "arith_uint256.h" +#include "blockencodings.h" #include "chainparams.h" #include "checkpoints.h" #include "checkqueue.h" @@ -197,8 +198,9 @@ namespace { /** Blocks that are in flight, and that are in the queue to be downloaded. Protected by cs_main. */ struct QueuedBlock { uint256 hash; - CBlockIndex* pindex; //!< Optional. - bool fValidatedHeaders; //!< Whether this block has validated headers at the time of request. + CBlockIndex* pindex; //!< Optional. + bool fValidatedHeaders; //!< Whether this block has validated headers at the time of request. + std::unique_ptr partialBlock; //!< Optional, used for CMPCTBLOCK downloads }; map::iterator> > mapBlocksInFlight; @@ -364,6 +366,7 @@ void FinalizeNode(NodeId nodeid) { // Requires cs_main. // Returns a bool indicating whether we requested this block. +// Also used if a block was /not/ received and timed out or started with another peer bool MarkBlockAsReceived(const uint256& hash) { map::iterator> >::iterator itInFlight = mapBlocksInFlight.find(hash); if (itInFlight != mapBlocksInFlight.end()) { @@ -387,17 +390,26 @@ bool MarkBlockAsReceived(const uint256& hash) { } // Requires cs_main. -void MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, const Consensus::Params& consensusParams, CBlockIndex *pindex = NULL) { +// returns false, still setting pit, if the block was already in flight from the same peer +// pit will only be valid as long as the same cs_main lock is being held +bool MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, const Consensus::Params& consensusParams, CBlockIndex *pindex = NULL, list::iterator **pit = NULL) { CNodeState *state = State(nodeid); assert(state != NULL); + // Short-circuit most stuff in case its from the same node + map::iterator> >::iterator itInFlight = mapBlocksInFlight.find(hash); + if (itInFlight != mapBlocksInFlight.end() && itInFlight->second.first == nodeid) { + *pit = &itInFlight->second.second; + return false; + } + // Make sure it's not listed somewhere already. MarkBlockAsReceived(hash); - QueuedBlock newentry = {hash, pindex, pindex != NULL}; - list::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(), newentry); + list::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(), + {hash, pindex, pindex != NULL, std::unique_ptr(pit ? new PartiallyDownloadedBlock(&mempool) : NULL)}); state->nBlocksInFlight++; - state->nBlocksInFlightValidHeaders += newentry.fValidatedHeaders; + state->nBlocksInFlightValidHeaders += it->fValidatedHeaders; if (state->nBlocksInFlight == 1) { // We're starting a block download (batch) from this peer. state->nDownloadingSince = GetTimeMicros(); @@ -405,7 +417,10 @@ void MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, const Consensus::Pa if (state->nBlocksInFlightValidHeaders == 1 && pindex != NULL) { nPeersWithValidatedDownloads++; } - mapBlocksInFlight[hash] = std::make_pair(nodeid, it); + itInFlight = mapBlocksInFlight.insert(std::make_pair(hash, std::make_pair(nodeid, it))).first; + if (pit) + *pit = &itInFlight->second.second; + return true; } /** Check whether the last unknown block a peer advertised is not yet known. */ @@ -4783,6 +4798,16 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // nodes) pfrom->PushMessage(NetMsgType::SENDHEADERS); } + if (pfrom->nVersion >= SHORT_IDS_BLOCKS_VERSION) { + // Tell our peer we are willing to provide version-1 cmpctblocks + // However, we do not request new block announcements using + // cmpctblock messages. + // We send this to non-NODE NETWORK peers as well, because + // they may wish to request compact blocks from us + bool fAnnounceUsingCMPCTBLOCK = false; + uint64_t nCMPCTBLOCKVersion = 1; + pfrom->PushMessage(NetMsgType::SENDCMPCT, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion); + } } @@ -4915,7 +4940,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, CNodeState *nodestate = State(pfrom->GetId()); if (CanDirectFetch(chainparams.GetConsensus()) && nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) { - vToFetch.push_back(inv); + if (nodestate->fProvidesHeaderAndIDs) + vToFetch.push_back(CInv(MSG_CMPCT_BLOCK, inv.hash)); + else + vToFetch.push_back(inv); // Mark block as in flight already, even though the actual "getdata" message only goes out // later (within the same cs_main lock, though). MarkBlockAsInFlight(pfrom->GetId(), inv.hash, chainparams.GetConsensus()); @@ -5232,6 +5260,174 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } + else if (strCommand == NetMsgType::CMPCTBLOCK && !fImporting && !fReindex) // Ignore blocks received while importing + { + CBlockHeaderAndShortTxIDs cmpctblock; + vRecv >> cmpctblock; + + LOCK(cs_main); + + if (mapBlockIndex.find(cmpctblock.header.hashPrevBlock) == mapBlockIndex.end()) { + // Doesn't connect (or is genesis), instead of DoSing in AcceptBlockHeader, request deeper headers + if (!IsInitialBlockDownload()) + pfrom->PushMessage(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), uint256()); + return true; + } + + CBlockIndex *pindex = NULL; + CValidationState state; + if (!AcceptBlockHeader(cmpctblock.header, state, chainparams, &pindex)) { + int nDoS; + if (state.IsInvalid(nDoS)) { + if (nDoS > 0) + Misbehaving(pfrom->GetId(), nDoS); + LogPrintf("Peer %d sent us invalid header via cmpctblock\n", pfrom->id); + return true; + } + } + + // If AcceptBlockHeader returned true, it set pindex + assert(pindex); + UpdateBlockAvailability(pfrom->GetId(), pindex->GetBlockHash()); + + std::map::iterator> >::iterator blockInFlightIt = mapBlocksInFlight.find(pindex->GetBlockHash()); + bool fAlreadyInFlight = blockInFlightIt != mapBlocksInFlight.end(); + + if (pindex->nStatus & BLOCK_HAVE_DATA) // Nothing to do here + return true; + + if (pindex->nChainWork <= chainActive.Tip()->nChainWork || // We know something better + pindex->nTx != 0) { // We had this block at some point, but pruned it + if (fAlreadyInFlight) { + // We requested this block for some reason, but our mempool will probably be useless + // so we just grab the block via normal getdata + std::vector vInv(1); + vInv[0] = CInv(MSG_BLOCK, cmpctblock.header.GetHash()); + pfrom->PushMessage(NetMsgType::GETDATA, vInv); + return true; + } + } + + // If we're not close to tip yet, give up and let parallel block fetch work its magic + if (!fAlreadyInFlight && !CanDirectFetch(chainparams.GetConsensus())) + return true; + + CNodeState *nodestate = State(pfrom->GetId()); + + // We want to be a bit conservative just to be extra careful about DoS + // possibilities in compact block processing... + if (pindex->nHeight <= chainActive.Height() + 2) { + if ((!fAlreadyInFlight && nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) || + (fAlreadyInFlight && blockInFlightIt->second.first == pfrom->GetId())) { + list::iterator *queuedBlockIt = NULL; + if (!MarkBlockAsInFlight(pfrom->GetId(), pindex->GetBlockHash(), chainparams.GetConsensus(), pindex, &queuedBlockIt)) { + if (!(*queuedBlockIt)->partialBlock) + (*queuedBlockIt)->partialBlock.reset(new PartiallyDownloadedBlock(&mempool)); + else { + // The block was already in flight using compact blocks from the same peer + LogPrint("net", "Peer sent us compact block we were already syncing!\n"); + return true; + } + } + + PartiallyDownloadedBlock& partialBlock = *(*queuedBlockIt)->partialBlock; + ReadStatus status = partialBlock.InitData(cmpctblock); + if (status == READ_STATUS_INVALID) { + MarkBlockAsReceived(pindex->GetBlockHash()); // Reset in-flight state in case of whitelist + Misbehaving(pfrom->GetId(), 100); + LogPrintf("Peer %d sent us invalid compact block\n", pfrom->id); + return true; + } else if (status == READ_STATUS_FAILED) { + // Duplicate txindexes, the block is now in-flight, so just request it + std::vector vInv(1); + vInv[0] = CInv(MSG_BLOCK, cmpctblock.header.GetHash()); + pfrom->PushMessage(NetMsgType::GETDATA, vInv); + return true; + } + + BlockTransactionsRequest req; + for (size_t i = 0; i < cmpctblock.BlockTxCount(); i++) { + if (!partialBlock.IsTxAvailable(i)) + req.indexes.push_back(i); + } + if (req.indexes.empty()) { + // Dirty hack to jump to BLOCKTXN code (TODO: move message handling into their own functions) + BlockTransactions txn; + txn.blockhash = cmpctblock.header.GetHash(); + CDataStream blockTxnMsg(SER_NETWORK, PROTOCOL_VERSION); + blockTxnMsg << txn; + return ProcessMessage(pfrom, NetMsgType::BLOCKTXN, blockTxnMsg, nTimeReceived, chainparams); + } else { + req.blockhash = pindex->GetBlockHash(); + pfrom->PushMessage(NetMsgType::GETBLOCKTXN, req); + } + } + } else { + if (fAlreadyInFlight) { + // We requested this block, but its far into the future, so our + // mempool will probably be useless - request the block normally + std::vector vInv(1); + vInv[0] = CInv(MSG_BLOCK, cmpctblock.header.GetHash()); + pfrom->PushMessage(NetMsgType::GETDATA, vInv); + return true; + } else { + // If this was an announce-cmpctblock, we want the same treatment as a header message + // Dirty hack to process as if it were just a headers message (TODO: move message handling into their own functions) + std::vector headers; + headers.push_back(cmpctblock.header); + CDataStream vHeadersMsg(SER_NETWORK, PROTOCOL_VERSION); + vHeadersMsg << headers; + return ProcessMessage(pfrom, NetMsgType::HEADERS, vHeadersMsg, nTimeReceived, chainparams); + } + } + + CheckBlockIndex(chainparams.GetConsensus()); + } + + else if (strCommand == NetMsgType::BLOCKTXN && !fImporting && !fReindex) // Ignore blocks received while importing + { + BlockTransactions resp; + vRecv >> resp; + + LOCK(cs_main); + + map::iterator> >::iterator it = mapBlocksInFlight.find(resp.blockhash); + if (it == mapBlocksInFlight.end() || !it->second.second->partialBlock || + it->second.first != pfrom->GetId()) { + LogPrint("net", "Peer %d sent us block transactions for block we weren't expecting\n", pfrom->id); + return true; + } + + PartiallyDownloadedBlock& partialBlock = *it->second.second->partialBlock; + CBlock block; + ReadStatus status = partialBlock.FillBlock(block, resp.txn); + if (status == READ_STATUS_INVALID) { + MarkBlockAsReceived(resp.blockhash); // Reset in-flight state in case of whitelist + Misbehaving(pfrom->GetId(), 100); + LogPrintf("Peer %d sent us invalid compact block/non-matching block transactions\n", pfrom->id); + return true; + } else if (status == READ_STATUS_FAILED) { + // Might have collided, fall back to getdata now :( + std::vector invs; + invs.push_back(CInv(MSG_BLOCK, resp.blockhash)); + pfrom->PushMessage(NetMsgType::GETDATA, invs); + } else { + CValidationState state; + ProcessNewBlock(state, chainparams, pfrom, &block, false, NULL); + int nDoS; + if (state.IsInvalid(nDoS)) { + assert (state.GetRejectCode() < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes + pfrom->PushMessage(NetMsgType::REJECT, strCommand, (unsigned char)state.GetRejectCode(), + state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), block.GetHash()); + if (nDoS > 0) { + LOCK(cs_main); + Misbehaving(pfrom->GetId(), nDoS); + } + } + } + } + + else if (strCommand == NetMsgType::HEADERS && !fImporting && !fReindex) // Ignore headers received while importing { std::vector headers; @@ -5334,6 +5530,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, pindexLast->GetBlockHash().ToString(), pindexLast->nHeight); } if (vGetData.size() > 0) { + if (nodestate->fProvidesHeaderAndIDs && vGetData.size() == 1 && mapBlocksInFlight.size() == 1 && pindexLast->pprev->IsValid(BLOCK_VALID_CHAIN)) { + vGetData[0] = CInv(MSG_CMPCT_BLOCK, vGetData[0].hash); + } pfrom->PushMessage(NetMsgType::GETDATA, vGetData); } } From 927f8eede0c9e0ab9cc2b5e43e39cfe3e1340dd6 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 6 May 2016 11:50:24 -0700 Subject: [PATCH 0518/1802] Add ability to fetch CNode by NodeId --- src/net.cpp | 10 ++++++++++ src/net.h | 5 +++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 4eca3d75ccae4..336163a89624d 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -368,6 +368,16 @@ CNode* FindNode(const CService& addr) return NULL; } +//TODO: This is used in only one place in main, and should be removed +CNode* FindNode(const NodeId nodeid) +{ + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + if (pnode->GetId() == nodeid) + return (pnode); + return NULL; +} + CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure) { if (pszDest == NULL) { diff --git a/src/net.h b/src/net.h index 67b95fe0e4a25..aa9b2c11a3c22 100644 --- a/src/net.h +++ b/src/net.h @@ -80,12 +80,15 @@ static const unsigned int DEFAULT_MISBEHAVING_BANTIME = 60 * 60 * 24; // Defaul unsigned int ReceiveFloodSize(); unsigned int SendBufferSize(); +typedef int NodeId; + void AddOneShot(const std::string& strDest); void AddressCurrentlyConnected(const CService& addr); CNode* FindNode(const CNetAddr& ip); CNode* FindNode(const CSubNet& subNet); CNode* FindNode(const std::string& addrName); CNode* FindNode(const CService& ip); +CNode* FindNode(const NodeId id); //TODO: Remove this bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false); void MapPort(bool fUseUPnP); unsigned short GetListenPort(); @@ -94,8 +97,6 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler); bool StopNode(); void SocketSendData(CNode *pnode); -typedef int NodeId; - struct CombinerAll { typedef bool result_type; From 2f34a2e476ae9d0585c67e275d238e44119c56cf Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 6 May 2016 18:33:46 -0400 Subject: [PATCH 0519/1802] Get our "best three" peers to announce blocks using cmpctblocks --- src/main.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 26b215f94cc54..60a33f9c2f97e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -204,6 +204,9 @@ namespace { }; map::iterator> > mapBlocksInFlight; + /** Stack of nodes which we have set to announce using compact blocks */ + list lNodesAnnouncingHeaderAndIDs; + /** Number of preferable block download peers. */ int nPreferredDownload = 0; @@ -456,6 +459,28 @@ void UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) { } } +void MaybeSetPeerAsAnnouncingHeaderAndIDs(const CNodeState* nodestate, CNode* pfrom) { + if (nodestate->fProvidesHeaderAndIDs) { + BOOST_FOREACH(const NodeId nodeid, lNodesAnnouncingHeaderAndIDs) + if (nodeid == pfrom->GetId()) + return; + bool fAnnounceUsingCMPCTBLOCK = false; + uint64_t nCMPCTBLOCKVersion = 1; + if (lNodesAnnouncingHeaderAndIDs.size() >= 3) { + // As per BIP152, we only get 3 of our peers to announce + // blocks using compact encodings. + CNode* pnodeStop = FindNode(lNodesAnnouncingHeaderAndIDs.front()); + if (pnodeStop) { + pnodeStop->PushMessage(NetMsgType::SENDCMPCT, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion); + lNodesAnnouncingHeaderAndIDs.pop_front(); + } + } + fAnnounceUsingCMPCTBLOCK = true; + pfrom->PushMessage(NetMsgType::SENDCMPCT, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion); + lNodesAnnouncingHeaderAndIDs.push_back(pfrom->GetId()); + } +} + // Requires cs_main bool CanDirectFetch(const Consensus::Params &consensusParams) { @@ -5531,6 +5556,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } if (vGetData.size() > 0) { if (nodestate->fProvidesHeaderAndIDs && vGetData.size() == 1 && mapBlocksInFlight.size() == 1 && pindexLast->pprev->IsValid(BLOCK_VALID_CHAIN)) { + // We seem to be rather well-synced, so it appears pfrom was the first to provide us + // with this block! Let's get them to announce using compact blocks in the future. + MaybeSetPeerAsAnnouncingHeaderAndIDs(nodestate, pfrom); + // In any case, we want to download using a compact block, not a regular one vGetData[0] = CInv(MSG_CMPCT_BLOCK, vGetData[0].hash); } pfrom->PushMessage(NetMsgType::GETDATA, vGetData); From 56ba5167272bc5afa8629ad93f16ed5135490bf5 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Wed, 8 Jun 2016 15:43:50 -0700 Subject: [PATCH 0520/1802] Add reconstruction debug logging --- src/blockencodings.cpp | 16 +++++++++++++++- src/blockencodings.h | 1 + 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/blockencodings.cpp b/src/blockencodings.cpp index c6b79f4201c55..204de45c29fe7 100644 --- a/src/blockencodings.cpp +++ b/src/blockencodings.cpp @@ -11,6 +11,7 @@ #include "streams.h" #include "txmempool.h" #include "main.h" +#include "util.h" #include @@ -72,6 +73,7 @@ ReadStatus PartiallyDownloadedBlock::InitData(const CBlockHeaderAndShortTxIDs& c } txn_available[lastprefilledindex] = std::make_shared(cmpctblock.prefilledtxn[i].tx); } + prefilled_count = cmpctblock.prefilledtxn.size(); // Calculate map of txids -> positions and check mempool to see what we have (or dont) // Because well-formed cmpctblock messages will have a (relatively) uniform distribution @@ -103,11 +105,15 @@ ReadStatus PartiallyDownloadedBlock::InitData(const CBlockHeaderAndShortTxIDs& c if (!have_txn[idit->second]) { txn_available[idit->second] = it->GetSharedTx(); have_txn[idit->second] = true; + mempool_count++; } else { // If we find two mempool txn that match the short id, just request it. // This should be rare enough that the extra bandwidth doesn't matter, // but eating a round-trip due to FillBlock failure would be annoying - txn_available[idit->second].reset(); + if (txn_available[idit->second]) { + txn_available[idit->second].reset(); + mempool_count--; + } } } // Though ideally we'd continue scanning for the two-txn-match-shortid case, @@ -117,6 +123,8 @@ ReadStatus PartiallyDownloadedBlock::InitData(const CBlockHeaderAndShortTxIDs& c break; } + LogPrint("cmpctblock", "Initialized PartiallyDownloadedBlock for block %s using a cmpctblock of size %lu\n", cmpctblock.header.GetHash().ToString(), cmpctblock.GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION)); + return READ_STATUS_OK; } @@ -154,5 +162,11 @@ ReadStatus PartiallyDownloadedBlock::FillBlock(CBlock& block, const std::vector< return READ_STATUS_INVALID; } + LogPrint("cmpctblock", "Successfully reconstructed block %s with %lu txn prefilled, %lu txn from mempool and %lu txn requested\n", header.GetHash().ToString(), prefilled_count, mempool_count, vtx_missing.size()); + if (vtx_missing.size() < 5) { + for(const CTransaction& tx : vtx_missing) + LogPrint("cmpctblock", "Reconstructed block %s required tx %s\n", header.GetHash().ToString(), tx.GetHash().ToString()); + } + return READ_STATUS_OK; } diff --git a/src/blockencodings.h b/src/blockencodings.h index adc60c85d0ecf..b980e9e28660f 100644 --- a/src/blockencodings.h +++ b/src/blockencodings.h @@ -192,6 +192,7 @@ class CBlockHeaderAndShortTxIDs { class PartiallyDownloadedBlock { protected: std::vector > txn_available; + size_t prefilled_count = 0, mempool_count = 0; CTxMemPool* pool; public: CBlockHeader header; From 678ee9793f6279c07b57c22c3cce983ab1e069d0 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 6 Jun 2016 01:15:21 -0700 Subject: [PATCH 0521/1802] Add BIP 152 to implemented BIPs list --- doc/bips.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/bips.md b/doc/bips.md index 1ec03d2fb1dd2..62bde20d944f4 100644 --- a/doc/bips.md +++ b/doc/bips.md @@ -26,3 +26,4 @@ BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.13.0**): * [`BIP 125`](https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki): Opt-in full replace-by-fee signaling honoured in mempool and mining as of **v0.12.0** ([PR 6871](https://github.com/bitcoin/bitcoin/pull/6871)). * [`BIP 130`](https://github.com/bitcoin/bips/blob/master/bip-0130.mediawiki): direct headers announcement is negotiated with peer versions `>=70012` as of **v0.12.0** ([PR 6494](https://github.com/bitcoin/bitcoin/pull/6494)). * [`BIP 133`](https://github.com/bitcoin/bips/blob/master/bip-0133.mediawiki): feefilter messages are respected and sent for peer versions `>=70013` as of **v0.13.0** ([PR 7542](https://github.com/bitcoin/bitcoin/pull/7542)). +* [`BIP 152`](https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki): Compact block transfer and related optimizations are used as of **v0.13.0** ([PR 8068](https://github.com/bitcoin/bitcoin/pull/8068)). From 811902649d6aaddd886cb39b83aa69adf7b441bd Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 14 Jun 2016 23:59:03 -0700 Subject: [PATCH 0522/1802] Provide a flat list of txid/terators to txn in CTxMemPool --- src/txmempool.cpp | 14 +++++++++++++- src/txmempool.h | 5 +++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 18c54b08bc2d3..ead28546de56a 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -438,6 +438,9 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, totalTxSize += entry.GetTxSize(); minerPolicyEstimator->processTransaction(entry, fCurrentEstimate); + vTxHashes.emplace_back(hash, newit); + newit->vTxHashesIdx = vTxHashes.size() - 1; + return true; } @@ -447,6 +450,15 @@ void CTxMemPool::removeUnchecked(txiter it) BOOST_FOREACH(const CTxIn& txin, it->GetTx().vin) mapNextTx.erase(txin.prevout); + if (vTxHashes.size() > 1) { + vTxHashes[it->vTxHashesIdx] = std::move(vTxHashes.back()); + vTxHashes[it->vTxHashesIdx].second->vTxHashesIdx = it->vTxHashesIdx; + vTxHashes.pop_back(); + if (vTxHashes.size() * 2 < vTxHashes.capacity()) + vTxHashes.shrink_to_fit(); + } else + vTxHashes.clear(); + totalTxSize -= it->GetTxSize(); cachedInnerUsage -= it->DynamicMemoryUsage(); cachedInnerUsage -= memusage::DynamicUsage(mapLinks[it].parents) + memusage::DynamicUsage(mapLinks[it].children); @@ -965,7 +977,7 @@ bool CCoinsViewMemPool::HaveCoins(const uint256 &txid) const { size_t CTxMemPool::DynamicMemoryUsage() const { LOCK(cs); // Estimate the overhead of mapTx to be 15 pointers + an allocation, as no exact formula for boost::multi_index_contained is implemented. - return memusage::MallocUsage(sizeof(CTxMemPoolEntry) + 15 * sizeof(void*)) * mapTx.size() + memusage::DynamicUsage(mapNextTx) + memusage::DynamicUsage(mapDeltas) + memusage::DynamicUsage(mapLinks) + cachedInnerUsage; + return memusage::MallocUsage(sizeof(CTxMemPoolEntry) + 15 * sizeof(void*)) * mapTx.size() + memusage::DynamicUsage(mapNextTx) + memusage::DynamicUsage(mapDeltas) + memusage::DynamicUsage(mapLinks) + memusage::DynamicUsage(vTxHashes) + cachedInnerUsage; } void CTxMemPool::RemoveStaged(setEntries &stage, bool updateDescendants) { diff --git a/src/txmempool.h b/src/txmempool.h index f0e9b2e2c6975..d6d0d72ff5874 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -150,6 +150,8 @@ class CTxMemPoolEntry uint64_t GetSizeWithAncestors() const { return nSizeWithAncestors; } CAmount GetModFeesWithAncestors() const { return nModFeesWithAncestors; } unsigned int GetSigOpCountWithAncestors() const { return nSigOpCountWithAncestors; } + + mutable size_t vTxHashesIdx; //!< Index in mempool's vTxHashes }; // Helpers for modifying CTxMemPool::mapTx, which is a boost multi_index. @@ -457,7 +459,10 @@ class CTxMemPool mutable CCriticalSection cs; indexed_transaction_set mapTx; + typedef indexed_transaction_set::nth_index<0>::type::iterator txiter; + std::vector > vTxHashes; //!< All tx hashes/entries in mapTx, in random order + struct CompareIteratorByHash { bool operator()(const txiter &a, const txiter &b) const { return a->GetTx().GetHash() < b->GetTx().GetHash(); From 0d4cb48ef1b916679d9fad9f247a297c85c7fedf Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sun, 19 Jun 2016 01:31:52 -0700 Subject: [PATCH 0523/1802] Use vTxHashes to optimize InitData significantly --- src/blockencodings.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/blockencodings.cpp b/src/blockencodings.cpp index 204de45c29fe7..9a0805e40050d 100644 --- a/src/blockencodings.cpp +++ b/src/blockencodings.cpp @@ -99,11 +99,13 @@ ReadStatus PartiallyDownloadedBlock::InitData(const CBlockHeaderAndShortTxIDs& c std::vector have_txn(txn_available.size()); LOCK(pool->cs); - for (CTxMemPool::txiter it = pool->mapTx.begin(); it != pool->mapTx.end(); it++) { - std::unordered_map::iterator idit = shorttxids.find(cmpctblock.GetShortID(it->GetTx().GetHash())); + const std::vector >& vTxHashes = pool->vTxHashes; + for (size_t i = 0; i < vTxHashes.size(); i++) { + uint64_t shortid = cmpctblock.GetShortID(vTxHashes[i].first); + std::unordered_map::iterator idit = shorttxids.find(shortid); if (idit != shorttxids.end()) { if (!have_txn[idit->second]) { - txn_available[idit->second] = it->GetSharedTx(); + txn_available[idit->second] = vTxHashes[i].second->GetSharedTx(); have_txn[idit->second] = true; mempool_count++; } else { From ccd06b94f69c3e7758c35ac4bcd36d0e9450e158 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 18 Jun 2016 01:36:23 +0200 Subject: [PATCH 0524/1802] Elaborate bucket size math --- src/blockencodings.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/blockencodings.cpp b/src/blockencodings.cpp index 9a0805e40050d..7fd6a9cf52d81 100644 --- a/src/blockencodings.cpp +++ b/src/blockencodings.cpp @@ -85,10 +85,16 @@ ReadStatus PartiallyDownloadedBlock::InitData(const CBlockHeaderAndShortTxIDs& c while (txn_available[i + index_offset]) index_offset++; shorttxids[cmpctblock.shorttxids[i]] = i + index_offset; - // Bucket selection is a simple Binomial distribution. If we assume blocks of - // 10,000 transactions, allowing up to 12 elements per bucket should only fail - // once every ~1.3 million blocks and once every 74,000 blocks in a worst-case - // 16,000-transaction block. + // To determine the chance that the number of entries in a bucket exceeds N, + // we use the fact that the number of elements in a single bucket is + // binomially distributed (with n = the number of shorttxids S, and p = + // 1 / the number of buckets), that in the worst case the number of buckets is + // equal to S (due to std::unordered_map having a default load factor of 1.0), + // and that the chance for any bucket to exceed N elements is at most + // buckets * (the chance that any given bucket is above N elements). + // Thus: P(max_elements_per_bucket > N) <= S * (1 - cdf(binomial(n=S,p=1/S), N)). + // If we assume blocks of up to 16000, allowing 12 elements per bucket should + // only fail once per ~1 million block transfers (per peer and connection). if (shorttxids.bucket_size(shorttxids.bucket(cmpctblock.shorttxids[i])) > 12) return READ_STATUS_FAILED; } From 2759597bc8617039a7ffa6210f4d49a985a20093 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Mon, 20 Jun 2016 10:17:01 +0200 Subject: [PATCH 0525/1802] Only pass -lQt5PlatformSupport if >=Qt5.6 --- build-aux/m4/bitcoin_qt.m4 | 4 +++- src/qt/bitcoin.cpp | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/build-aux/m4/bitcoin_qt.m4 b/build-aux/m4/bitcoin_qt.m4 index 210df3c025d0b..74d910267462e 100644 --- a/build-aux/m4/bitcoin_qt.m4 +++ b/build-aux/m4/bitcoin_qt.m4 @@ -343,7 +343,9 @@ AC_DEFUN([_BITCOIN_QT_FIND_STATIC_PLUGINS],[ PKG_CHECK_MODULES([QTPRINT], [Qt5PrintSupport], [QT_LIBS="$QTPRINT_LIBS $QT_LIBS"]) fi else - QT_LIBS="-lQt5PlatformSupport $QT_LIBS" + if ${PKG_CONFIG} --exists "Qt5Core >= 5.6" 2>/dev/null; then + QT_LIBS="-lQt5PlatformSupport $QT_LIBS" + fi fi ]) else diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 6218ab6ab0542..64b5c83d72a00 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -533,6 +533,9 @@ int main(int argc, char *argv[]) // Generate high-dpi pixmaps QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); #endif +#if QT_VERSION >= 0x050600 + QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); +#endif #ifdef Q_OS_MAC QApplication::setAttribute(Qt::AA_DontShowIconsInMenus); #endif From fa58f94ff7f097260ebee791008dab368c7ac318 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 20 Jun 2016 11:21:00 +0200 Subject: [PATCH 0526/1802] [qa] pull-tester: Start longest test first --- qa/pull-tester/rpc-tests.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index 98823085034af..6c0ed4510f103 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -101,6 +101,8 @@ #Tests testScripts = [ + # longest test should go first, to favor running tests in parallel + 'p2p-fullblocktest.py', 'walletbackup.py', 'bip68-112-113-p2p.py', 'wallet.py', @@ -125,7 +127,6 @@ 'nodehandling.py', 'reindex.py', 'decodescript.py', - 'p2p-fullblocktest.py', 'blockchain.py', 'disablewallet.py', 'sendheaders.py', From e5a680dc6a69cc5c35f2debeba15d4886fa4f789 Mon Sep 17 00:00:00 2001 From: fanquake Date: Sun, 12 Jun 2016 12:59:02 +0800 Subject: [PATCH 0527/1802] [Doc] Update OS X build notes for 10.11 SDK --- doc/{README_osx.txt => README_osx.md} | 28 +++++++++++++-------------- doc/build-osx.md | 8 +++++--- doc/release-process.md | 16 +++++---------- 3 files changed, 24 insertions(+), 28 deletions(-) rename doc/{README_osx.txt => README_osx.md} (81%) diff --git a/doc/README_osx.txt b/doc/README_osx.md similarity index 81% rename from doc/README_osx.txt rename to doc/README_osx.md index c13efaa145c83..aed3cd97e1ecd 100644 --- a/doc/README_osx.txt +++ b/doc/README_osx.md @@ -1,21 +1,19 @@ Deterministic OS X Dmg Notes. Working OS X DMGs are created in Linux by combining a recent clang, -the Apple's binutils (ld, ar, etc), and DMG authoring tools. +the Apple binutils (ld, ar, etc) and DMG authoring tools. Apple uses clang extensively for development and has upstreamed the necessary functionality so that a vanilla clang can take advantage. It supports the use of -F, -target, -mmacosx-version-min, and --sysroot, which are all necessary -when building for OS X. A pre-compiled version of 3.2 is used because it was not -available in the Precise repositories at the time this work was started. In the -future, it can be switched to use system packages instead. +when building for OS X. Apple's version of binutils (called cctools) contains lots of functionality missing in the FSF's binutils. In addition to extra linker options for frameworks and sysroots, several other tools are needed as well such as install_name_tool, lipo, and nmedit. These do not build under linux, so they have been patched to do so. The work here was used as a starting point: -https://github.com/mingwandroid/toolchain4 +[mingwandroid/toolchain4](https://github.com/mingwandroid/toolchain4). In order to build a working toolchain, the following source packages are needed from Apple: cctools, dyld, and ld64. @@ -29,16 +27,19 @@ originally done in toolchain4. To complicate things further, all builds must target an Apple SDK. These SDKs are free to download, but not redistributable. -To obtain it, register for a developer account, then download the Xcode 6.1.1 dmg: -https://developer.apple.com/devcenter/download.action?path=/Developer_Tools/xcode_6.1.1/xcode_6.1.1.dmg +To obtain it, register for a developer account, then download the [Xcode 7.3.1 dmg](https://developer.apple.com/devcenter/download.action?path=/Developer_Tools/Xcode_7.3.1/Xcode_7.3.1.dmg). This file is several gigabytes in size, but only a single directory inside is -needed: Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk +needed: +``` +Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk +``` Unfortunately, the usual linux tools (7zip, hpmount, loopback mount) are incapable of opening this file. To create a tarball suitable for Gitian input, mount the dmg in OS X, then create it with: - $ tar -C /Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ -czf MacOSX10.9.sdk.tar.gz MacOSX10.9.sdk - +``` + $ tar -C /Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ -czf MacOSX10.11.sdk.tar.gz MacOSX10.11.sdk +``` The Gitian descriptors build 2 sets of files: Linux tools, then Apple binaries which are created using these tools. The build process has been designed to @@ -48,15 +49,14 @@ fully deterministic and may be freely redistributed. genisoimage is used to create the initial DMG. It is not deterministic as-is, so it has been patched. A system genisoimage will work fine, but it will not be deterministic because the file-order will change between invocations. -The patch can be seen here: -https://raw.githubusercontent.com/theuni/osx-cross-depends/master/patches/cdrtools/genisoimage.diff +The patch can be seen here: [theuni/osx-cross-depends](https://raw.githubusercontent.com/theuni/osx-cross-depends/master/patches/cdrtools/genisoimage.diff). No effort was made to fix this cleanly, so it likely leaks memory badly. But it's only used for a single invocation, so that's no real concern. genisoimage cannot compress DMGs, so afterwards, the 'dmg' tool from the libdmg-hfsplus project is used to compress it. There are several bugs in this tool and its maintainer has seemingly abandoned the project. It has been forked -and is available (with fixes) here: https://github.com/theuni/libdmg-hfsplus . +and is available (with fixes) here: [theuni/libdmg-hfsplus](https://github.com/theuni/libdmg-hfsplus). The 'dmg' tool has the ability to create DMGs from scratch as well, but this functionality is broken. Only the compression feature is currently used. @@ -77,6 +77,6 @@ build process to remain somewhat deterministic. Here's how it works: that have been previously (deterministically) built in order to create a final dmg. - The Apple keyholder uses this unsigned app to create a detached signature, - using the script that is also included there. + using the script that is also included there. Detached signatures are available from this [repository](https://github.com/bitcoin-core/bitcoin-detached-sigs). - Builders feed the unsigned app + detached signature back into Gitian. It uses the pre-built tools to recombine the pieces into a deterministic dmg. diff --git a/doc/build-osx.md b/doc/build-osx.md index 89d7816c9a42b..c9eb4225abb5c 100644 --- a/doc/build-osx.md +++ b/doc/build-osx.md @@ -5,11 +5,13 @@ The built-in one is located in `/Applications/Utilities/Terminal.app`. Preparation ----------- -Download and install [Xcode](https://developer.apple.com/xcode/download). +Install the OS X command line tools: -Once installed, run `xcode-select --install` to install the OS X command line tools. +`xcode-select --install` -Install [Homebrew](http://brew.sh). +When the popup appears, click `Install`. + +Then install [Homebrew](http://brew.sh). Dependencies ---------------------- diff --git a/doc/release-process.md b/doc/release-process.md index 3bfcc38177bb2..f5d0d836d1ae9 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -3,7 +3,7 @@ Release Process Before every release candidate: -* Update translations (ping wumpus on IRC) see [translation_process.md](https://github.com/bitcoin/bitcoin/blob/master/doc/translation_process.md#syncing-with-transifex) +* Update translations (ping wumpus on IRC) see [translation_process.md](https://github.com/bitcoin/bitcoin/blob/master/doc/translation_process.md#synchronising-translations). Before every minor and major release: @@ -13,7 +13,7 @@ Before every minor and major release: Before every major release: -* Update hardcoded [seeds](/contrib/seeds/README.md), see [this pull request](https://github.com/bitcoin/bitcoin/pull/7415) for an example. +* Update hardcoded [seeds](/contrib/seeds/README.md), see [this pull request](https://github.com/bitcoin/bitcoin/pull/7415) for an example. ### First time / New builders @@ -75,7 +75,7 @@ Ensure your gitian.sigs are up-to-date if you wish to gverify your builds agains git pull popd -Ensure gitian-builder is up-to-date to take advantage of new caching features (`e9741525c` or later is recommended). +Ensure gitian-builder is up-to-date: pushd ./gitian-builder git pull @@ -89,13 +89,7 @@ Ensure gitian-builder is up-to-date to take advantage of new caching features (` wget -P inputs http://downloads.sourceforge.net/project/osslsigncode/osslsigncode/osslsigncode-1.7.1.tar.gz popd -Register and download the Apple SDK: see [OS X readme](README_osx.txt) for details. - -https://developer.apple.com/devcenter/download.action?path=/Developer_Tools/xcode_6.1.1/xcode_6.1.1.dmg - -Using a Mac, create a tarball for the 10.9 SDK and copy it to the inputs directory: - - tar -C /Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ -czf MacOSX10.9.sdk.tar.gz MacOSX10.9.sdk +Create the OS X SDK tarball, see the [OS X readme](README_osx.md) for details, and copy it into the inputs directory. ### Optional: Seed the Gitian sources cache and offline git repositories @@ -239,7 +233,7 @@ transmission-show -m Insert the magnet URI into the announcement sent to mailing lists. This permits people without access to `bitcoin.org` to download the binary distribution. Also put it into the `optional_magnetlink:` slot in the YAML file for -bitcoin.org (see below for bitcoin.org update instructions). +bitcoin.org (see below for bitcoin.org update instructions). - Update bitcoin.org version From fa6ad56948d1163ec7e3a7cd49d7e9d99787e27a Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 20 Jun 2016 14:57:39 +0200 Subject: [PATCH 0528/1802] [travis] Update SDK_URL --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index af9c476dc1d99..a6c51753b6727 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,7 +22,7 @@ env: - CCACHE_TEMPDIR=/tmp/.ccache-temp - CCACHE_COMPRESS=1 - BASE_OUTDIR=$TRAVIS_BUILD_DIR/out - - SDK_URL=https://bitcoin.jonasschnelli.ch/sdks + - SDK_URL=https://bitcoincore.org/depends-sources/sdks - PYTHON_DEBUG=1 - WINEDEBUG=fixme-all matrix: From bf9c70b1008e1eada462955a6420e79a7d2a8352 Mon Sep 17 00:00:00 2001 From: TheLazieR Yip Date: Tue, 21 Jun 2016 00:46:59 +0700 Subject: [PATCH 0529/1802] Fix LogPrint to LogPrintf Printing Log without category defined should use LogPrintf Github-Pull: #8230 Meta: PR should have been based on master in the first place --- src/qt/winshutdownmonitor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/winshutdownmonitor.cpp b/src/qt/winshutdownmonitor.cpp index 1bc4f779597bf..a11da50588262 100644 --- a/src/qt/winshutdownmonitor.cpp +++ b/src/qt/winshutdownmonitor.cpp @@ -27,7 +27,7 @@ bool WinShutdownMonitor::nativeEventFilter(const QByteArray &eventType, void *pM // Warn only once as this is performance-critical static bool warned = false; if (!warned) { - LogPrint("%s: OpenSSL RAND_event() failed to seed OpenSSL PRNG with enough data.\n", __func__); + LogPrintf("%s: OpenSSL RAND_event() failed to seed OpenSSL PRNG with enough data.\n", __func__); warned = true; } } From b3e1348c46573630e5899b53f77236fd51f78d13 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 21 Jun 2016 10:54:57 +0200 Subject: [PATCH 0530/1802] [Qt] fix a bug where the SplashScreen will not be hidden during startup --- src/qt/splashscreen.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index b46321fa866f1..e36d86fdddaa0 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -141,6 +141,11 @@ SplashScreen::~SplashScreen() void SplashScreen::slotFinish(QWidget *mainWin) { Q_UNUSED(mainWin); + + /* If the window is minimized, hide() will be ignored. */ + /* Make sure we de-minimize the splashscreen window before hiding */ + if (isMinimized()) + showNormal(); hide(); } From b7bf037121f0a46ee9f7a31e3c0b78f118dadba2 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 21 Jun 2016 14:10:53 +0200 Subject: [PATCH 0531/1802] doc: Mention ARM executables in release process Mention ARM executables in the release process documentation (these were introduced in #8188). As well as that Linux tarballs have changed name to contain an architecture tuple, instead of `linux32`/`linux64`. Also mention that `-debug` files should not be uploaded (these were introduced in #8167). --- doc/release-process.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/doc/release-process.md b/doc/release-process.md index 3bfcc38177bb2..0263bdf693a34 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -210,8 +210,10 @@ sha256sum * > SHA256SUMS The list of files should be: ``` -bitcoin-${VERSION}-linux32.tar.gz -bitcoin-${VERSION}-linux64.tar.gz +bitcoin-${VERSION}-aarch64-linux-gnu.tar.gz +bitcoin-${VERSION}-arm-linux-gnueabihf.tar.gz +bitcoin-${VERSION}-i686-pc-linux-gnu.tar.gz +bitcoin-${VERSION}-x86_64-linux-gnu.tar.gz bitcoin-${VERSION}-osx64.tar.gz bitcoin-${VERSION}-osx.dmg bitcoin-${VERSION}.tar.gz @@ -220,6 +222,11 @@ bitcoin-${VERSION}-win32.zip bitcoin-${VERSION}-win64-setup.exe bitcoin-${VERSION}-win64.zip ``` +The `*-debug*` files generated by the gitian build contain debug symbols +for troubleshooting by developers. It is assumed that anyone that is interested +in debugging can run gitian to generate the files for themselves. To avoid +end-user confusion about which file to pick, as well as save storage +space *do not upload these to the bitcoin.org server, nor put them in the torrent*. - GPG-sign it, delete the unsigned file: ``` From 05f64c9940478f3d40104a5083a1b850f0358879 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 21 Jun 2016 14:33:13 +0200 Subject: [PATCH 0532/1802] doc: Mention Linux ARM builds in release notes --- doc/release-notes.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/doc/release-notes.md b/doc/release-notes.md index 6cc05989dbd6e..df3c265dcdbd2 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -61,6 +61,26 @@ When cross-compiling for a target that doesn't have C++11 libraries, configure w For running the functional tests in `qa/rpc-tests`, Python3.4 or higher is now required. +Linux ARM builds +------------------ + +Due to popular request, Linux ARM builds have been added to the uploaded +executables. + +The following extra files can be found in the download directory or torrent: + +- `bitcoin-${VERSION}-arm-linux-gnueabihf.tar.gz`: Linux binaries for the most + common 32-bit ARM architecture. +- `bitcoin-${VERSION}-aarch64-linux-gnu.tar.gz`: Linux binaries for the most + common 64-bit ARM architecture. + +ARM builds are still experimental. If you have problems on a certain device or +Linux distribution combination please report them on the bug tracker, it may be +possible to resolve them. + +Note that Android is not considered ARM Linux in this context. The executables +are not expected to work out of the box on Android. + 0.13.0 Change log ================= From 4cbe05bf205ceeb23d1d47360693c8235b497ed5 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 21 Jun 2016 13:23:39 +0000 Subject: [PATCH 0533/1802] qt: Periodic transifex update Pulls in the following new languages: - `af` Afrikaans - `es_419` Spanish (Latin America) - `es_AR` Spanish (Argentina) - `es_CO` Spanish (Colombia) - `fil` Filipino - `it_IT` Italian (Italy) - `ro` Romanian - `sr@latin` Serbian (Latin) - `ta` Tamil - `uz@Latn` Uzbek (Latin) - `zh_HK` Chinese (Hong Kong) --- src/Makefile.qt.include | 11 + src/qt/bitcoin_locale.qrc | 11 + src/qt/bitcoinstrings.cpp | 10 + src/qt/locale/bitcoin_af.ts | 509 ++++++ src/qt/locale/bitcoin_af_ZA.ts | 26 +- src/qt/locale/bitcoin_ar.ts | 152 +- src/qt/locale/bitcoin_bg.ts | 10 +- src/qt/locale/bitcoin_ca.ts | 80 +- src/qt/locale/bitcoin_ca@valencia.ts | 8 - src/qt/locale/bitcoin_ca_ES.ts | 76 +- src/qt/locale/bitcoin_cs.ts | 376 ++++- src/qt/locale/bitcoin_cs_CZ.ts | 24 + src/qt/locale/bitcoin_da.ts | 74 +- src/qt/locale/bitcoin_de.ts | 106 +- src/qt/locale/bitcoin_el_GR.ts | 13 +- src/qt/locale/bitcoin_en.ts | 2176 ++++---------------------- src/qt/locale/bitcoin_en_GB.ts | 66 +- src/qt/locale/bitcoin_eo.ts | 42 +- src/qt/locale/bitcoin_es.ts | 242 ++- src/qt/locale/bitcoin_es_419.ts | 173 ++ src/qt/locale/bitcoin_es_AR.ts | 373 +++++ src/qt/locale/bitcoin_es_CL.ts | 120 +- src/qt/locale/bitcoin_es_CO.ts | 542 +++++++ src/qt/locale/bitcoin_es_DO.ts | 4 - src/qt/locale/bitcoin_es_MX.ts | 100 +- src/qt/locale/bitcoin_et.ts | 4 - src/qt/locale/bitcoin_fa.ts | 4 - src/qt/locale/bitcoin_fi.ts | 92 +- src/qt/locale/bitcoin_fil.ts | 157 ++ src/qt/locale/bitcoin_fr.ts | 60 +- src/qt/locale/bitcoin_fr_FR.ts | 1662 +++++++++++++++++++- src/qt/locale/bitcoin_gl.ts | 4 - src/qt/locale/bitcoin_he.ts | 16 +- src/qt/locale/bitcoin_hr.ts | 4 - src/qt/locale/bitcoin_hu.ts | 8 +- src/qt/locale/bitcoin_id_ID.ts | 302 +++- src/qt/locale/bitcoin_it.ts | 18 +- src/qt/locale/bitcoin_it_IT.ts | 325 ++++ src/qt/locale/bitcoin_ja.ts | 64 +- src/qt/locale/bitcoin_ka.ts | 4 - src/qt/locale/bitcoin_ko_KR.ts | 1336 ++++++++++++++-- src/qt/locale/bitcoin_la.ts | 4 - src/qt/locale/bitcoin_lt.ts | 24 +- src/qt/locale/bitcoin_lv_LV.ts | 4 - src/qt/locale/bitcoin_nb.ts | 12 - src/qt/locale/bitcoin_nl.ts | 68 +- src/qt/locale/bitcoin_pam.ts | 4 - src/qt/locale/bitcoin_pl.ts | 221 ++- src/qt/locale/bitcoin_pt_BR.ts | 174 +- src/qt/locale/bitcoin_pt_PT.ts | 894 +++++++++-- src/qt/locale/bitcoin_ro.ts | 169 ++ src/qt/locale/bitcoin_ro_RO.ts | 138 +- src/qt/locale/bitcoin_ru.ts | 36 +- src/qt/locale/bitcoin_ru_RU.ts | 52 + src/qt/locale/bitcoin_sk.ts | 287 +++- src/qt/locale/bitcoin_sl_SI.ts | 20 +- src/qt/locale/bitcoin_sq.ts | 8 + src/qt/locale/bitcoin_sr@latin.ts | 653 ++++++++ src/qt/locale/bitcoin_sv.ts | 64 +- src/qt/locale/bitcoin_ta.ts | 1029 ++++++++++++ src/qt/locale/bitcoin_th_TH.ts | 182 ++- src/qt/locale/bitcoin_tr.ts | 72 +- src/qt/locale/bitcoin_tr_TR.ts | 8 + src/qt/locale/bitcoin_uk.ts | 16 +- src/qt/locale/bitcoin_uz@Cyrl.ts | 4 - src/qt/locale/bitcoin_uz@Latn.ts | 169 ++ src/qt/locale/bitcoin_zh_CN.ts | 80 +- src/qt/locale/bitcoin_zh_HK.ts | 521 ++++++ src/qt/locale/bitcoin_zh_TW.ts | 178 ++- 69 files changed, 11761 insertions(+), 2714 deletions(-) create mode 100644 src/qt/locale/bitcoin_af.ts create mode 100644 src/qt/locale/bitcoin_es_419.ts create mode 100644 src/qt/locale/bitcoin_es_AR.ts create mode 100644 src/qt/locale/bitcoin_es_CO.ts create mode 100644 src/qt/locale/bitcoin_fil.ts create mode 100644 src/qt/locale/bitcoin_it_IT.ts create mode 100644 src/qt/locale/bitcoin_ro.ts create mode 100644 src/qt/locale/bitcoin_sr@latin.ts create mode 100644 src/qt/locale/bitcoin_ta.ts create mode 100644 src/qt/locale/bitcoin_uz@Latn.ts create mode 100644 src/qt/locale/bitcoin_zh_HK.ts diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 9381cca9f256c..dc775a3568d78 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -3,6 +3,7 @@ EXTRA_LIBRARIES += qt/libbitcoinqt.a # bitcoin qt core # QT_TS = \ + qt/locale/bitcoin_af.ts \ qt/locale/bitcoin_af_ZA.ts \ qt/locale/bitcoin_ar.ts \ qt/locale/bitcoin_be_BY.ts \ @@ -22,7 +23,10 @@ QT_TS = \ qt/locale/bitcoin_en_GB.ts \ qt/locale/bitcoin_en.ts \ qt/locale/bitcoin_eo.ts \ + qt/locale/bitcoin_es_419.ts \ + qt/locale/bitcoin_es_AR.ts \ qt/locale/bitcoin_es_CL.ts \ + qt/locale/bitcoin_es_CO.ts \ qt/locale/bitcoin_es_DO.ts \ qt/locale/bitcoin_es_ES.ts \ qt/locale/bitcoin_es_MX.ts \ @@ -33,6 +37,7 @@ QT_TS = \ qt/locale/bitcoin_eu_ES.ts \ qt/locale/bitcoin_fa_IR.ts \ qt/locale/bitcoin_fa.ts \ + qt/locale/bitcoin_fil.ts \ qt/locale/bitcoin_fi.ts \ qt/locale/bitcoin_fr_CA.ts \ qt/locale/bitcoin_fr_FR.ts \ @@ -43,6 +48,7 @@ QT_TS = \ qt/locale/bitcoin_hr.ts \ qt/locale/bitcoin_hu.ts \ qt/locale/bitcoin_id_ID.ts \ + qt/locale/bitcoin_it_IT.ts \ qt/locale/bitcoin_it.ts \ qt/locale/bitcoin_ja.ts \ qt/locale/bitcoin_ka.ts \ @@ -62,22 +68,27 @@ QT_TS = \ qt/locale/bitcoin_pt_BR.ts \ qt/locale/bitcoin_pt_PT.ts \ qt/locale/bitcoin_ro_RO.ts \ + qt/locale/bitcoin_ro.ts \ qt/locale/bitcoin_ru_RU.ts \ qt/locale/bitcoin_ru.ts \ qt/locale/bitcoin_sk.ts \ qt/locale/bitcoin_sl_SI.ts \ qt/locale/bitcoin_sq.ts \ + qt/locale/bitcoin_sr@latin.ts \ qt/locale/bitcoin_sr.ts \ qt/locale/bitcoin_sv.ts \ + qt/locale/bitcoin_ta.ts \ qt/locale/bitcoin_th_TH.ts \ qt/locale/bitcoin_tr_TR.ts \ qt/locale/bitcoin_tr.ts \ qt/locale/bitcoin_uk.ts \ qt/locale/bitcoin_ur_PK.ts \ qt/locale/bitcoin_uz@Cyrl.ts \ + qt/locale/bitcoin_uz@Latn.ts \ qt/locale/bitcoin_vi.ts \ qt/locale/bitcoin_vi_VN.ts \ qt/locale/bitcoin_zh_CN.ts \ + qt/locale/bitcoin_zh_HK.ts \ qt/locale/bitcoin_zh.ts \ qt/locale/bitcoin_zh_TW.ts diff --git a/src/qt/bitcoin_locale.qrc b/src/qt/bitcoin_locale.qrc index a8a0253b078ff..1acda7f28caaf 100644 --- a/src/qt/bitcoin_locale.qrc +++ b/src/qt/bitcoin_locale.qrc @@ -1,5 +1,6 @@ + locale/bitcoin_af.qm locale/bitcoin_af_ZA.qm locale/bitcoin_ar.qm locale/bitcoin_be_BY.qm @@ -19,7 +20,10 @@ locale/bitcoin_en_GB.qm locale/bitcoin_en.qm locale/bitcoin_eo.qm + locale/bitcoin_es_419.qm + locale/bitcoin_es_AR.qm locale/bitcoin_es_CL.qm + locale/bitcoin_es_CO.qm locale/bitcoin_es_DO.qm locale/bitcoin_es_ES.qm locale/bitcoin_es_MX.qm @@ -30,6 +34,7 @@ locale/bitcoin_eu_ES.qm locale/bitcoin_fa_IR.qm locale/bitcoin_fa.qm + locale/bitcoin_fil.qm locale/bitcoin_fi.qm locale/bitcoin_fr_CA.qm locale/bitcoin_fr_FR.qm @@ -40,6 +45,7 @@ locale/bitcoin_hr.qm locale/bitcoin_hu.qm locale/bitcoin_id_ID.qm + locale/bitcoin_it_IT.qm locale/bitcoin_it.qm locale/bitcoin_ja.qm locale/bitcoin_ka.qm @@ -59,22 +65,27 @@ locale/bitcoin_pt_BR.qm locale/bitcoin_pt_PT.qm locale/bitcoin_ro_RO.qm + locale/bitcoin_ro.qm locale/bitcoin_ru_RU.qm locale/bitcoin_ru.qm locale/bitcoin_sk.qm locale/bitcoin_sl_SI.qm locale/bitcoin_sq.qm + locale/bitcoin_sr@latin.qm locale/bitcoin_sr.qm locale/bitcoin_sv.qm + locale/bitcoin_ta.qm locale/bitcoin_th_TH.qm locale/bitcoin_tr_TR.qm locale/bitcoin_tr.qm locale/bitcoin_uk.qm locale/bitcoin_ur_PK.qm locale/bitcoin_uz@Cyrl.qm + locale/bitcoin_uz@Latn.qm locale/bitcoin_vi.qm locale/bitcoin_vi_VN.qm locale/bitcoin_zh_CN.qm + locale/bitcoin_zh_HK.qm locale/bitcoin_zh.qm locale/bitcoin_zh_TW.qm diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp index 9e53f19591070..ce8753fc7ddc6 100644 --- a/src/qt/bitcoinstrings.cpp +++ b/src/qt/bitcoinstrings.cpp @@ -60,6 +60,8 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" QT_TRANSLATE_NOOP("bitcoin-core", "" "Do not keep transactions in the mempool longer than hours (default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "" +"Error loading %s: You can't enable HD on a already existing non-HD wallet"), +QT_TRANSLATE_NOOP("bitcoin-core", "" "Error reading %s! All keys read correctly, but transaction data or address " "book entries might be missing or incorrect."), QT_TRANSLATE_NOOP("bitcoin-core", "" @@ -114,6 +116,9 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" "Please check that your computer's date and time are correct! If your clock " "is wrong, %s will not work properly."), QT_TRANSLATE_NOOP("bitcoin-core", "" +"Please contribute if you find %s useful. Visit %s for further information " +"about the software."), +QT_TRANSLATE_NOOP("bitcoin-core", "" "Prune configured below the minimum of %d MiB. Please use a higher number."), QT_TRANSLATE_NOOP("bitcoin-core", "" "Prune: last wallet synchronisation goes beyond pruned data. You need to -" @@ -168,6 +173,9 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" QT_TRANSLATE_NOOP("bitcoin-core", "" "Use UPnP to map the listening port (default: 1 when listening and no -proxy)"), QT_TRANSLATE_NOOP("bitcoin-core", "" +"Use hierarchical deterministic key generation (HD) after bip32. Only has " +"effect during wallet creation/first start"), +QT_TRANSLATE_NOOP("bitcoin-core", "" "Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: " "%s)"), QT_TRANSLATE_NOOP("bitcoin-core", "" @@ -243,6 +251,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Error initializing wallet database environmen QT_TRANSLATE_NOOP("bitcoin-core", "Error loading %s"), 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 %s: You can't disable HD on a already existing HD wallet"), QT_TRANSLATE_NOOP("bitcoin-core", "Error loading block database"), QT_TRANSLATE_NOOP("bitcoin-core", "Error opening block database"), QT_TRANSLATE_NOOP("bitcoin-core", "Error reading from database, shutting down."), @@ -317,6 +326,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Specify pid file (default: %s)"), QT_TRANSLATE_NOOP("bitcoin-core", "Specify wallet file (within data directory)"), QT_TRANSLATE_NOOP("bitcoin-core", "Specify your own public address"), QT_TRANSLATE_NOOP("bitcoin-core", "Spend unconfirmed change when sending transactions (default: %u)"), +QT_TRANSLATE_NOOP("bitcoin-core", "The source code is available from %s."), QT_TRANSLATE_NOOP("bitcoin-core", "The transaction amount is too small to pay the fee"), QT_TRANSLATE_NOOP("bitcoin-core", "This is experimental software."), QT_TRANSLATE_NOOP("bitcoin-core", "Threshold for disconnecting misbehaving peers (default: %u)"), diff --git a/src/qt/locale/bitcoin_af.ts b/src/qt/locale/bitcoin_af.ts new file mode 100644 index 0000000000000..492c7bccd4e1b --- /dev/null +++ b/src/qt/locale/bitcoin_af.ts @@ -0,0 +1,509 @@ + + + AddressBookPage + + Right-click to edit address or label + Regs-kliek om die adres of etiket te verander + + + Create a new address + Skep 'n nuwe adres + + + &New + &Nuut + + + Copy the currently selected address to the system clipboard + Dupliseer die geselekteerde adres na die sisteem se geheuebord + + + &Copy + &Dupliseer + + + &Copy Address + &Dupliseer Adres + + + Delete the currently selected address from the list + Verwyder die adres wat u gekies het van die lys + + + Export the data in the current tab to a file + Voer die inligting op hierdie bladsy uit na 'n leer + + + &Export + &Voer uit + + + &Delete + &Vee uit + + + Choose the address to send coins to + Kies die adres waarheen u munte wil stuur + + + Choose the address to receive coins with + Kies die adres wat die munte moet ontvang + + + Sending addresses + Stuurders adresse + + + Receiving addresses + Ontvanger adresse + + + These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. + Hierdie is die adresse vanwaar u Bitcoin betalings stuur. U moet altyd die bedrag en die adres van die ontvanger nagaan voordat u enige munte stuur. + + + These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. + Hierdie is die adresse waar u Bitcoins sal ontvang. Ons beveel aan dat u 'n nuwe adres kies vir elke transaksie + + + &Edit + &Verander + + + Export Address List + Voer adreslys uit + + + Comma separated file (*.csv) + Comma separated file (*.csv) + + + Exporting Failed + Uitvoer was onsuksesvol + + + There was an error trying to save the address list to %1. Please try again. + Die adreslys kon nie in %1 gestoor word nie. Probeer asseblief weer. + + + + AddressTableModel + + Address + Adres + + + (no label) + (geen etiket) + + + + AskPassphraseDialog + + Passphrase Dialog + Wagwoord Dialoog + + + Enter passphrase + Tik u wagwoord in + + + New passphrase + Nuwe wagwoord + + + Repeat new passphrase + Herhaal nuwe wagwoord + + + Encrypt wallet + Kodifiseer beursie + + + This operation needs your wallet passphrase to unlock the wallet. + U het u beursie se wagwoord nodig om toegang tot u beursie te verkry. + + + Unlock wallet + Sluit beursie oop + + + This operation needs your wallet passphrase to decrypt the wallet. + U het u beursie se wagwoord nodig om u beursie se kode te ontsyfer. + + + Decrypt wallet + Ontsleutel beursie + + + Change passphrase + Verander wagwoord + + + Confirm wallet encryption + Bevestig dat die beursie gekodifiseer is + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! + Waarskuwing: Indien u die beursie kodifiseer en u vergeet u wagwoord <b>VERLOOR U AL U BITCOINS</b>! + + + Are you sure you wish to encrypt your wallet? + Is u seker dat u die beursie wil kodifiseer? + + + Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. + Bitcoin Kern gaan nou toemaak om die kodifikasie af te handel. Onthou dat die kodifikasie van u beursie nie altyd u munte kan beskerm teen diefstal deur kwaadwillige sagteware op u rekenaar nie. + + + 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. + BELANGRIK: Alle vorige kopieë en rugsteun-weergawes wat u tevore van die gemaak het, moet vervang word met die jongste weergawe van u nuutste gekodifiseerde beursie. Alle vorige weergawes en rugsteun-kopieë van u beursie sal nutteloos raak die oomblik wat u die nuut-gekodifiseerde beursie begin gebruik. + + + Warning: The Caps Lock key is on! + WAARSKUWING: Outomatiese Kapitalisering is aktief op u sleutelbord! + + + Wallet encrypted + Beursie gekodifiseer + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. + Tik die nuwe wagwoord vir u beursie.<br/>Gerbuik asseblief 'n wagwoord met <b>tien of meer lukrake karakters</b>, of <b>agt of meer woorde</b>. + + + Enter the old passphrase and new passphrase to the wallet. + Tik die ou en die nuwe wagwoorde vir die beursie. + + + Wallet encryption failed + Kodifikasie was onsuksesvol + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Weens 'n interne fout het kodifikasie het nie geslaag nie. U beursie is nie gekodifiseer nie + + + The supplied passphrases do not match. + Die wagwoorde stem nie ooreen nie. + + + Wallet unlock failed + Die beursie is nie oopgesluit nie + + + The passphrase entered for the wallet decryption was incorrect. + U het die verkeerde wagwoord ingetik. + + + + BanTableModel + + Banned Until + Verban tot + + + + BitcoinGUI + + Synchronizing with network... + Netwerk-sinkronisasie... + + + &Overview + &Oorsig + + + Node + Node + + + Show general overview of wallet + Vertoon 'n algemene oorsig van die beursie + + + &Transactions + &Transaksies + + + Quit application + Stop en verlaat die applikasie + + + &Options... + &Opsies + + + &Encrypt Wallet... + &Kodifiseer Beursie + + + &Backup Wallet... + &Rugsteun-kopie van Beursie + + + &Change Passphrase... + &Verander Wagwoord + + + &Sending addresses... + &Versending adresse... + + + &Receiving addresses... + &Ontvanger adresse + + + Open &URI... + Oop & URI... + + + Bitcoin Core client + Bitcoin Kern klient + + + Importing blocks from disk... + Besig om blokke vanaf die hardeskyf in te voer... + + + Reindexing blocks on disk... + Besig met herindeksering van blokke op hardeskyf... + + + Send coins to a Bitcoin address + Stuur munte na 'n Bitcoin adres + + + Backup wallet to another location + Maak 'n rugsteun-kopié van beursie na 'n ander stoorplek + + + Change the passphrase used for wallet encryption + Verander die wagwoord wat ek vir kodifikasie van my beursie gebruik + + + Bitcoin + Bitcoin + + + Wallet + Beursie + + + &Send + &Stuur + + + &Receive + &Ontvang + + + Show information about Bitcoin Core + Vertoon inligting oor Bitcoin Kern + + + Show or hide the main Window + Wys of versteek die hoofbladsy + + + Encrypt the private keys that belong to your wallet + Kodifiseer die private sleutes wat aan jou beursie gekoppel is. + + + Sign messages with your Bitcoin addresses to prove you own them + Onderteken boodskappe met u Bitcoin adresse om u eienaarskap te bewys + + + Verify messages to ensure they were signed with specified Bitcoin addresses + Verifieër boodskappe om seker te maak dat dit met die gespesifiseerde Bitcoin adresse + + + &Help + &Help + + + Bitcoin Core + Bitcoin Kern + + + Request payments (generates QR codes and bitcoin: URIs) + Versoek betalings (genereer QR-kodes en bitcoin: URI's) + + + &About Bitcoin Core + &Omtrent Bitcoin Kern + + + Modify configuration options for Bitcoin Core + Verander konfigurasie-opsies vir Bitcoin Kern + + + Show the list of used sending addresses and labels + Vertoon die lys van gebruikte versendingsadresse en etikette + + + Show the list of used receiving addresses and labels + Vertoon die lys van gebruikte ontvangers-adresse en etikette + + + Open a bitcoin: URI or payment request + Skep 'n bitcoin: URI of betalingsversoek + + + + ClientModel + + + CoinControlDialog + + (no label) + (geen etiket) + + + + EditAddressDialog + + + FreespaceChecker + + + HelpMessageDialog + + Bitcoin Core + Bitcoin Kern + + + Reset all settings changes made over the GUI + Herstel al my veranderinge aan die stellings terug na die verstek-opsies + + + + Intro + + Bitcoin Core + Bitcoin Kern + + + + OpenURIDialog + + + OptionsDialog + + + OverviewPage + + + PaymentServer + + + PeerTableModel + + + QObject + + + QRImageWidget + + + RPCConsole + + + ReceiveCoinsDialog + + + ReceiveRequestDialog + + Address + Adres + + + + RecentRequestsTableModel + + (no label) + (geen etiket) + + + + SendCoinsDialog + + (no label) + (geen etiket) + + + + SendCoinsEntry + + + ShutdownWindow + + + SignVerifyMessageDialog + + + SplashScreen + + Bitcoin Core + Bitcoin Kern + + + + TrafficGraphWidget + + + TransactionDesc + + + TransactionDescDialog + + + TransactionTableModel + + + TransactionView + + Exporting Failed + Uitvoer was onsuksesvol + + + Comma separated file (*.csv) + Comma separated file (*.csv) + + + Address + Adres + + + + UnitDisplayStatusBarControl + + + WalletFrame + + + WalletModel + + + WalletView + + &Export + &Voer uit + + + Export the data in the current tab to a file + Voer die inligting op hierdie bladsy uit na 'n leer + + + + bitcoin-core + + WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) + WAARSKUWING: toets die status van u netwerk, %d blokke ontvang in die laaste %d ure (%d verwag) + + + Do not keep transactions in the mempool longer than <n> hours (default: %u) + Moenie transaksies vir langer as <n> ure in die geheuepoel hou nie (verstek: %u) + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_af_ZA.ts b/src/qt/locale/bitcoin_af_ZA.ts index d77aa77f8e6f8..12ac21eb80dcf 100644 --- a/src/qt/locale/bitcoin_af_ZA.ts +++ b/src/qt/locale/bitcoin_af_ZA.ts @@ -31,17 +31,21 @@ AskPassphraseDialog + + Passphrase Dialog + Wagfrase Dialoog + Enter passphrase - Tik Wagwoord in + Tik wagfrase in New passphrase - Nuwe wagwoord + Nuwe wagfrase Repeat new passphrase - Herhaal nuwe wagwoord + Herhaal nuwe wagfrase Encrypt wallet @@ -65,7 +69,7 @@ Change passphrase - Verander wagwoord + Verander wagfrase Confirm wallet encryption @@ -75,6 +79,10 @@ Wallet encrypted Die beursie is nou bewaak + + Enter the old passphrase and new passphrase to the wallet. + Tik in die ou wagfrase en die nuwe wagfrase vir die beursie. + Wallet encryption failed Die beursie kon nie bewaak word nie @@ -85,7 +93,7 @@ The supplied passphrases do not match. - Die wagwoord stem nie ooreen nie + Die wagfrase stem nie ooreen nie Wallet unlock failed @@ -93,13 +101,17 @@ The passphrase entered for the wallet decryption was incorrect. - Die wagwoord wat ingetik was om die beursie oop te sluit, was verkeerd. + Die wagfrase wat ingetik was om die beursie oop te sluit, was verkeerd. Wallet decryption failed Beursie dekripsie het misluk - + + Wallet passphrase was successfully changed. + Die beursie se wagfrase verandering was suksesvol. + + BanTableModel diff --git a/src/qt/locale/bitcoin_ar.ts b/src/qt/locale/bitcoin_ar.ts index 88ce05bbd5dbc..1e74564ed3ead 100644 --- a/src/qt/locale/bitcoin_ar.ts +++ b/src/qt/locale/bitcoin_ar.ts @@ -222,7 +222,15 @@ BanTableModel - + + IP/Netmask + عنوان البروتوكول/قناع + + + Banned Until + محظور حتى + + BitcoinGUI @@ -325,6 +333,10 @@ &Debug window &نافذة المعالجة + + Open debugging and diagnostic console + إفتح وحدة التصحيح و التشخيص + &Verify message... &التحقق من الرسالة... @@ -361,6 +373,14 @@ Encrypt the private keys that belong to your wallet تشفير المفتاح الخاص بمحفظتك + + Sign messages with your Bitcoin addresses to prove you own them + وقَع الرسائل بواسطة ال: Bitcoin الخاص بك لإثبات امتلاكك لهم + + + Verify messages to ensure they were signed with specified Bitcoin addresses + تحقق من الرسائل للتأكد من أنَها وُقعت برسائل Bitcoin محدَدة + &File &ملف @@ -381,14 +401,58 @@ Bitcoin Core جوهر البيت كوين + + Request payments (generates QR codes and bitcoin: URIs) + أطلب دفعات (يولد كودات الرمز المربع وبيت كوين: العناوين المعطاة) + &About Bitcoin Core حول bitcoin core + + Modify configuration options for Bitcoin Core + تغيير خيارات الإعداد لأساس Bitcoin + + + Show the list of used sending addresses and labels + عرض قائمة عناوين الإرسال المستخدمة والملصقات + + + Show the list of used receiving addresses and labels + عرض قائمة عناوين الإستقبال المستخدمة والملصقات + + + Open a bitcoin: URI or payment request + فتح URI : Bitcoin أو طلب دفع + + + &Command-line options + &خيارات سطر الأوامر + + + No block source available... + لا يوجد أي مصدر الكتلة + + + Processed %n block(s) of transaction history. + لم يتم معالجة أي كتلة سجل المعاملاتتم معالجة كتلة واحدة سجل المعاملاتتم معالجة كتلتين سجل المعاملاتتم معالجة %n كتل سجل المعاملاتتم معالجة %n كتلة سجل المعاملاتتم معالجة %n كتلة سجل المعاملات + + + %n hour(s) + 0 ساعة%n ساعة%n ساعتين%n ساعات%n ساعة%n ساعات + %1 and %2 %1 و %2 + + Last received block was generated %1 ago. + تم توليد الكتلة المستقبلة الأخيرة منذ %1. + + + Transactions after this will not yet be visible. + المعاملات بعد ذلك لن تكون مريئة بعد. + Error خطأ @@ -463,6 +527,14 @@ Amount المبلغ + + Received with label + مستقبل مع ملصق + + + Received with address + مستقبل مع عنوان + Date التاريخ @@ -531,6 +603,14 @@ medium-high متوسط-مرتفع + + medium + متوسط + + + low-medium + متوسط-منخفض + low منخفض @@ -547,6 +627,10 @@ none لا شيء + + This label turns red if the transaction size is greater than 1000 bytes. + هذا الملصق يصبح أخمرا إذا كان حجم المعاملة أكبر من 1000 بايت. + yes نعم @@ -555,6 +639,18 @@ no لا + + This means a fee of at least %1 per kB is required. + هذا يعني أن من المطلوب أن يكون الرسم ألى الأقل %1 لكل كيلوبايت. + + + Can vary +/- 1 byte per input. + يمكن أن يتفاوت بـ 1 بايت لكل مساهمة. + + + Transactions with higher priority are more likely to get included into a block. + المعاملات التي لديها أولوية أعلى على الأرجح سيتم إنضمامها في الكتلة. + (no label) (لا وصف) @@ -598,6 +694,10 @@ The entered address "%1" is already in the address book. هدا العنوان "%1" موجود مسبقا في دفتر العناوين + + The entered address "%1" is not a valid Bitcoin address. + العنوان المدخل "%1" ليس عنوان بيت كوين صحيح. + Could not unlock wallet. يمكن فتح المحفظة. @@ -617,6 +717,14 @@ name الاسم + + Directory already exists. Add %1 if you intend to create a new directory here. + الدليل موجوج بالفعل. أضف %1 لو نويت إنشاء دليل جديد هنا. + + + Path already exists, and is not a directory. + المسار موجود بالفعل، وهو ليس دليلاً. + Cannot create data directory here. لا يمكن انشاء دليل بيانات هنا . @@ -636,11 +744,39 @@ About Bitcoin Core عن جوهر البيت كوين + + Command-line options + خيارات سطر الأوامر + Usage: المستخدم - + + command-line options + خيارات سطر الأوامر + + + UI Options: + خيارات واجهة المستخدم + + + Choose data directory on startup (default: %u) + اختر دليل البيانات عند بدء التشغير (افتراضي: %u) + + + Set SSL root certificates for payment request (default: -system-) + أضع شهادة بروتوكول الشبقة الأمنية لطلب المدفوع (افتراضي: -نظام-) + + + Show splash screen on startup (default: %u) + أظهر شاشة البداية عند بدء التشغيل (افتراضي: %u) + + + Reset all settings changes made over the GUI + إعادة تعيين كل الإعدادات تم تغييرها من خلال الواجهة الرسومية + + Intro @@ -1793,14 +1929,26 @@ Invalid -proxy address: '%s' عنوان البروكسي غير صحيح : '%s' + + Make the wallet broadcast transactions + إنتاج معاملات بث المحفظة + Insufficient funds اموال غير كافية + + Loading block index... + تحميل مؤشر الكتلة + Loading wallet... تحميل المحفظه + + Cannot downgrade wallet + لا يمكن تخفيض قيمة المحفظة + Cannot write default address لايمكن كتابة العنوان الافتراضي diff --git a/src/qt/locale/bitcoin_bg.ts b/src/qt/locale/bitcoin_bg.ts index ecd10e5461716..54bf8136a60b4 100644 --- a/src/qt/locale/bitcoin_bg.ts +++ b/src/qt/locale/bitcoin_bg.ts @@ -214,7 +214,11 @@ BanTableModel - + + Banned Until + Със забранен достъп до + + BitcoinGUI @@ -1229,10 +1233,6 @@ General Основни - - Using OpenSSL version - Използване на OpenSSL версия - Using BerkeleyDB version Използване на база данни BerkeleyDB diff --git a/src/qt/locale/bitcoin_ca.ts b/src/qt/locale/bitcoin_ca.ts index 38e770f182242..8bc9281f1daaa 100644 --- a/src/qt/locale/bitcoin_ca.ts +++ b/src/qt/locale/bitcoin_ca.ts @@ -1115,6 +1115,22 @@ Shows, if the supplied default SOCKS5 proxy is used to reach peers via this network type. Mostra si el proxy SOCKS5 per defecte proporcionat s'utilitza per arribar als iguals mitjançant aquest tipus de xarxa. + + IPv4 + IPv4 + + + IPv6 + IPv6 + + + Tor + Tor + + + Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services. + Conectar a la red de Bitcoin a través de un proxy SOCKS5 per als serveis ocults de Tor + Use separate SOCKS5 proxy to reach peers via Tor hidden services: Utilitza un proxy SOCKS4 apart per a arribar als iguals a través de serveis ocults de Tor: @@ -1457,10 +1473,6 @@ General General - - Using OpenSSL version - Utilitzant OpenSSL versió - Using BerkeleyDB version Utilitzant BerkeleyDB versió @@ -1489,6 +1501,18 @@ Current number of blocks Nombre de blocs actuals + + Memory Pool + Reserva de memòria + + + Current number of transactions + Nombre actual de transaccions + + + Memory usage + Us de memoria + Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. Obre el fitxer de registre de depuració del Bitcoin Core del directori de dades actual. Pot portar uns quants segons per a fitxers de registre grans. @@ -2748,6 +2772,10 @@ Copy transaction ID Copiar ID de transacció + + Copy raw transaction + Copia la transacció crua + Edit label Editar etiqueta @@ -2895,22 +2923,62 @@ Accept command line and JSON-RPC commands Accepta la línia d'ordres i ordres JSON-RPC + + If <category> is not supplied or if <category> = 1, output all debugging information. + Si no es proporciona <category> o si <category> = 1, treu a la sortida tota la informació de depuració. + Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s) Comissions totals màximes (en %s) per utilitzar en una única transacció de moneder; definir-ne una massa baixa pot interrompre les transaccions més grans (per defecte: %s) + + Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. + Comproveu que la data i hora de l'ordinador són correctes! Si el vostre rellotge no té l'hora correcta, el Bitcoin Core no funcionarà adequadament. + + + Prune configured below the minimum of %d MiB. Please use a higher number. + Poda configurada per sota el mínim de %d MiB. Utilitzeu un nombre superior. + + + Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node) + Poda: la darrera sincronització del moneder va més enllà de les dades podades. Cal que activeu -reindex (baixeu tota la cadena de blocs de nou en cas de node podat) + + + Reduce storage requirements by pruning (deleting) old blocks. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, >%u = target size in MiB to use for block files) + Reduïu els requisits d'emmagatzematge podant (suprimint) els blocs antics. Aquest mode és incompatible amb -txindex i -rescan. Avís: la reversió d'aquest paràmetre implica haver de tornar a baixar la cadena de blocs sencera. (per defecte: 0 = inhabilita la poda de blocs, >%u = mida objectiu en MiB per utilitzar en els fitxers de blocs) + + + Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again. + Els rescanejos no són possible en el mode de poda. Caldrà que utilitzeu -reindex, que tornarà a baixar la cadena de blocs sencera. + + + Error: A fatal internal error occurred, see debug.log for details + Error: s'ha produït un error intern fatal. Vegeu debug.log per a més detalls + Fee (in %s/kB) to add to transactions you send (default: %s) Comissió (en %s/kB) per afegir a les transaccions que envieu (per defecte: %s) + + Pruning blockstore... + S'està podant la cadena de blocs... + Run in the background as a daemon and accept commands Executa en segon pla com a programa dimoni i accepta ordres + + Unable to start HTTP server. See debug log for details. + No s'ha pogut iniciar el servidor HTTP. Vegeu debug.log per a més detalls. + Accept connections from outside (default: 1 if no -proxy or -connect) Accepta connexions de fora (per defecte: 1 si no -proxy o -connect) + + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. + -fallbackfee és molt elevat. Aquesta és la comissió de transacció que podeu pagar quan les estimacions de comissions no estan disponibles. + Bind to given address and always listen on it. Use [host]:port notation for IPv6 Vincula a una adreça específica i sempre escolta-hi. Utilitza la notació [host]:port per IPv6 @@ -3079,10 +3147,6 @@ Wallet options: Opcions de moneder: - - Warning: This version is obsolete; upgrade required! - Avís: aquesta versió és obsoleta; cal actualitzar-la! - You need to rebuild the database using -reindex to change -txindex Cal que reconstruïu la base de dades fent servir -reindex per canviar -txindex diff --git a/src/qt/locale/bitcoin_ca@valencia.ts b/src/qt/locale/bitcoin_ca@valencia.ts index 2c41ec78d4061..e5744fcbbf9b4 100644 --- a/src/qt/locale/bitcoin_ca@valencia.ts +++ b/src/qt/locale/bitcoin_ca@valencia.ts @@ -1413,10 +1413,6 @@ General General - - Using OpenSSL version - Utilitzant OpenSSL versió - Using BerkeleyDB version Utilitzant BerkeleyDB versió @@ -2959,10 +2955,6 @@ Wallet options: Opcions de moneder: - - Warning: This version is obsolete; upgrade required! - Avís: esta versió és obsoleta; cal actualitzar-la! - You need to rebuild the database using -reindex to change -txindex Cal que reconstruïu la base de dades fent servir -reindex per canviar -txindex diff --git a/src/qt/locale/bitcoin_ca_ES.ts b/src/qt/locale/bitcoin_ca_ES.ts index e6a932ebeeaed..2c238bb44f34a 100644 --- a/src/qt/locale/bitcoin_ca_ES.ts +++ b/src/qt/locale/bitcoin_ca_ES.ts @@ -1115,6 +1115,22 @@ Shows, if the supplied default SOCKS5 proxy is used to reach peers via this network type. Mostra si el proxy SOCKS5 per defecte proporcionat s'utilitza per arribar als iguals mitjançant aquest tipus de xarxa. + + IPv4 + IPv4 + + + IPv6 + IPv6 + + + Tor + Tor + + + Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services. + Conectar a la red de Bitcoin a través de un proxy SOCKS5 per als serveis ocults de Tor + Use separate SOCKS5 proxy to reach peers via Tor hidden services: Utilitza un proxy SOCKS4 apart per a arribar als iguals a través de serveis ocults de Tor: @@ -1457,10 +1473,6 @@ General General - - Using OpenSSL version - Utilitzant OpenSSL versió - Using BerkeleyDB version Utilitzant BerkeleyDB versió @@ -1489,6 +1501,18 @@ Current number of blocks Nombre de blocs actuals + + Memory Pool + Reserva de memòria + + + Current number of transactions + Nombre actual de transaccions + + + Memory usage + Us de memoria + Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. Obre el fitxer de registre de depuració del Bitcoin Core del directori de dades actual. Pot portar uns quants segons per a fitxers de registre grans. @@ -2748,6 +2772,10 @@ Copy transaction ID Copiar ID de transacció + + Copy raw transaction + Copia la transacció crua + Edit label Editar etiqueta @@ -2895,18 +2923,54 @@ Accept command line and JSON-RPC commands Accepta la línia d'ordres i ordres JSON-RPC + + If <category> is not supplied or if <category> = 1, output all debugging information. + Si no es proporciona <category> o si <category> = 1, treu a la sortida tota la informació de depuració. + Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s) Comissions totals màximes (en %s) per utilitzar en una única transacció de moneder; definir-ne una massa baixa pot interrompre les transaccions més grans (per defecte: %s) + + Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. + Comproveu que la data i hora de l'ordinador són correctes! Si el vostre rellotge no té l'hora correcta, el Bitcoin Core no funcionarà adequadament. + + + Prune configured below the minimum of %d MiB. Please use a higher number. + Poda configurada per sota el mínim de %d MiB. Utilitzeu un nombre superior. + + + Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node) + Poda: la darrera sincronització del moneder va més enllà de les dades podades. Cal que activeu -reindex (baixeu tota la cadena de blocs de nou en cas de node podat) + + + Reduce storage requirements by pruning (deleting) old blocks. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, >%u = target size in MiB to use for block files) + Reduïu els requisits d'emmagatzematge podant (suprimint) els blocs antics. Aquest mode és incompatible amb -txindex i -rescan. Avís: la reversió d'aquest paràmetre implica haver de tornar a baixar la cadena de blocs sencera. (per defecte: 0 = inhabilita la poda de blocs, >%u = mida objectiu en MiB per utilitzar en els fitxers de blocs) + + + Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again. + Els rescanejos no són possible en el mode de poda. Caldrà que utilitzeu -reindex, que tornarà a baixar la cadena de blocs sencera. + + + Error: A fatal internal error occurred, see debug.log for details + Error: s'ha produït un error intern fatal. Vegeu debug.log per a més detalls + Fee (in %s/kB) to add to transactions you send (default: %s) Comissió (en %s/kB) per afegir a les transaccions que envieu (per defecte: %s) + + Pruning blockstore... + S'està podant la cadena de blocs... + Run in the background as a daemon and accept commands Executa en segon pla com a programa dimoni i accepta ordres + + Unable to start HTTP server. See debug log for details. + No s'ha pogut iniciar el servidor HTTP. Vegeu debug.log per a més detalls. + Accept connections from outside (default: 1 if no -proxy or -connect) Accepta connexions de fora (per defecte: 1 si no -proxy o -connect) @@ -3079,10 +3143,6 @@ Wallet options: Opcions de moneder: - - Warning: This version is obsolete; upgrade required! - Avís: aquesta versió és obsoleta; cal actualitzar-la! - You need to rebuild the database using -reindex to change -txindex Cal que reconstruïu la base de dades fent servir -reindex per canviar -txindex diff --git a/src/qt/locale/bitcoin_cs.ts b/src/qt/locale/bitcoin_cs.ts index ef1903edd168e..d3ff5c1f57d64 100644 --- a/src/qt/locale/bitcoin_cs.ts +++ b/src/qt/locale/bitcoin_cs.ts @@ -3,7 +3,7 @@ AddressBookPage Right-click to edit address or label - Pravým tlačítkem myši začneš upravovat označení adresy + Pravým tlačítkem myši můžeš upravit označení adresy Create a new address @@ -71,7 +71,7 @@ These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Tohle jsou tvé Bitcoinové adresy pro příjem plateb. Je doporučené používat pokaždé novou adresu pro každou transakci. + Tohle jsou tvé Bitcoinové adresy pro příjem plateb. Nezapomeň si pro každou transakci vždy vygenerovat novou adresu. Copy &Label @@ -83,11 +83,11 @@ Export Address List - Exportuj seznam adres + Export seznamu adres Comma separated file (*.csv) - CSV formát (*.csv) + Formát CSV (*.csv) Exporting Failed @@ -343,7 +343,7 @@ &Send - &Pošli + P&ošli &Receive @@ -383,7 +383,7 @@ &Help - Ná&pověda + Nápověd&a Tabs toolbar @@ -419,7 +419,7 @@ &Command-line options - Ar&gumenty z příkazové řádky + Ar&gumenty příkazové řádky Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options @@ -467,7 +467,7 @@ Transactions after this will not yet be visible. - Následné transakce ještě nebudou vidět. + Novější transakce zatím nejsou vidět. Error @@ -806,11 +806,11 @@ The entered address "%1" is already in the address book. - Zadaná adresa "%1" už v adresáři je. + Zadaná adresa „%1“ už v adresáři je. The entered address "%1" is not a valid Bitcoin address. - Zadaná adresa "%1" není platná Bitcoinová adresa. + Zadaná adresa „%1“ není platná Bitcoinová adresa. Could not unlock wallet. @@ -864,7 +864,7 @@ Command-line options - Argumenty z příkazové řádky + Argumenty příkazové řádky Usage: @@ -874,7 +874,35 @@ command-line options možnosti příkazové řádky - + + UI Options: + Možnosti UI: + + + Choose data directory on startup (default: %u) + Zvolit při startu adresář pro data (výchozí: %u) + + + Set language, for example "de_DE" (default: system locale) + Nastavit jazyk, například „de_DE“ (výchozí: systémové nastavení) + + + Start minimized + Nastartovat minimalizovaně + + + Set SSL root certificates for payment request (default: -system-) + Nastavit kořenové SSL certifikáty pro platební požadavky (výchozí: -system-) + + + Show splash screen on startup (default: %u) + Zobrazit startovací obrazovku (výchozí: %u) + + + Reset all settings changes made over the GUI + Resetovat všechna nastavení provedené v GUI + + Intro @@ -989,7 +1017,7 @@ 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 |. - URL třetích stran (např. block exploreru), které se zobrazí v kontextovém menu v záložce Transakce. %s v URL se nahradí hashem transakce. Více URL odděl svislítkem |. + URL třetích stran (např. block exploreru), která se zobrazí v kontextovém menu v záložce Transakce. %s v URL se nahradí hashem transakce. Více URL odděl svislítkem |. Third party transaction URLs @@ -997,7 +1025,7 @@ Active command-line options that override above options: - Aktivní argumenty z příkazové řádky, které přetloukly tato nastavení: + Aktivní argumenty z příkazové řádky, které mají přednost před nastavením výše: Reset all client options to default. @@ -1029,7 +1057,7 @@ Expert - Odborník + Pokročilá nastavení Enable coin &control features @@ -1071,6 +1099,30 @@ Port of the proxy (e.g. 9050) Port proxy (např. 9050) + + Used for reaching peers via: + Použije se k připojování k protějškům přes: + + + Shows, if the supplied default SOCKS5 proxy is used to reach peers via this network type. + Ukazuje, jestli se zadaná výchozí SOCKS5 proxy používá k připojování k peerům v rámci tohoto typu sítě. + + + IPv4 + IPv4 + + + IPv6 + IPv6 + + + Tor + Tor + + + Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services. + Připojí se do Bitcoinové sítě přes SOCKS5 proxy vyhrazenou pro skryté služby v Tor síti. + Use separate SOCKS5 proxy to reach peers via Tor hidden services: Použít samostatnou SOCKS5 proxy ke spojení s protějšky přes skryté služby v Toru: @@ -1101,7 +1153,7 @@ &Unit to show amounts in: - J&ednotka pro částky: + Je&dnotka pro částky: Choose the default subdivision unit to show in the interface and when sending coins. @@ -1113,7 +1165,7 @@ &OK - &Budiž + &Použít &Cancel @@ -1141,7 +1193,7 @@ This change would require a client restart. - Tahle změna bude chtít restartovat klienta. + Tato změna vyžaduje restart aplikace. The supplied proxy address is invalid. @@ -1188,7 +1240,7 @@ Balances - Stavy účtů + Stav účtů Total: @@ -1413,10 +1465,6 @@ General Obecné - - Using OpenSSL version - Používaná verze OpenSSL - Using BerkeleyDB version Používaná verze BerkeleyDB @@ -1445,6 +1493,10 @@ Current number of blocks Aktuální počet bloků + + Memory usage + Využití paměti + Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. Otevři soubor s ladicími záznamy Bitcoin Core z aktuálního datového adresáře. U velkých logů to může pár vteřin zabrat. @@ -1549,6 +1601,34 @@ Clear console Vyčistit konzoli + + &Disconnect Node + &Odpojit uzel + + + Ban Node for + Uvalit na uzel klatbu na + + + 1 &hour + 1 &hodinu + + + 1 &day + 1 &den + + + 1 &week + 1 &týden + + + 1 &year + 1 &rok + + + &Unban Node + &Zbavit uzel klatby + Welcome to the Bitcoin Core RPC console. Vítej v RPC konzoli Bitcoin Core. @@ -1577,6 +1657,10 @@ %1 GB %1 GB + + (node id: %1) + (id uzlu: %1) + via %1 via %1 @@ -1630,7 +1714,7 @@ 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. - Volitelná zpráva, která se připojí k platebnímu požadavku a která se zobrazí, když se požadavek otevře. Poznámka: Tahle zpráva se neposílá s platbou po Bitcoinové síti. + Volitelná zpráva, která se připojí k platebnímu požadavku a která se zobrazí, když se požadavek otevře. Poznámka: tahle zpráva se neposílá s platbou po Bitcoinové síti. An optional label to associate with the new receiving address. @@ -1638,7 +1722,7 @@ Use this form to request payments. All fields are <b>optional</b>. - Tímto formulář můžeš požadovat platby. Všechna pole jsou <b>volitelná</b>. + Tímto formulářem můžeš požadovat platby. Všechna pole jsou <b>volitelná</b>. An optional amount to request. Leave this empty or zero to not request a specific amount. @@ -1931,7 +2015,7 @@ S&end - P&ošli + Pošl&i Confirm send coins @@ -1969,6 +2053,10 @@ Copy change Kopíruj drobné + + Total Amount %1 + Celková částka %1 + or nebo @@ -2001,6 +2089,10 @@ Payment request expired. Platební požadavek vypršel. + + Pay only the required fee of %1 + Zaplatit pouze vyžadovaný poplatek %1 + Estimated to begin confirmation within %n block(s). Potvrzování by podle odhadu mělo začít během %n bloku.Potvrzování by podle odhadu mělo začít během %n bloků.Potvrzování by podle odhadu mělo začít během %n bloků. @@ -2090,7 +2182,7 @@ S&ubtract fee from amount - &Odečíst poplatek od částky + Od&ečíst poplatek od částky Message: @@ -2176,7 +2268,7 @@ Copy the current signature to the system clipboard - Zkopíruj aktuálně vybraný podpis do systémové schránky + Zkopíruj tento podpis do schránky Sign the message to prove you own this Bitcoin address @@ -2220,7 +2312,7 @@ Click "Sign Message" to generate signature - Kliknutím na "Podepiš zprávu" vygeneruješ podpis + Kliknutím na „Podepiš zprávu“ vygeneruješ podpis The entered address is invalid. @@ -2248,7 +2340,7 @@ Message signed. - Zpráv podepsána. + Zpráva podepsána. The signature could not be decoded. @@ -2405,7 +2497,7 @@ 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. - Vygenerované mince musí čekat %1 bloků, než mohou být utraceny. Když jsi vygeneroval tenhle blok, tak byl rozposlán do sítě, aby byl přidán do řetězce bloků. Pokud se mu nepodaří dostat se do řetězce, změní se na "neakceptovaný" a nepůjde utratit. To se občas může stát, pokud jiný uzel vygeneruje blok zhruba ve stejném okamžiku jako ty. + Vygenerované mince musí čekat %1 bloků, než mohou být utraceny. Když jsi vygeneroval tenhle blok, tak byl rozposlán do sítě, aby byl přidán do řetězce bloků. Pokud se mu nepodaří dostat se do řetězce, změní se na „neakceptovaný“ a nepůjde utratit. To se občas může stát, pokud jiný uzel vygeneruje blok zhruba ve stejném okamžiku jako ty. Debug information @@ -2467,7 +2559,7 @@ Immature (%1 confirmations, will be available after %2) - Nedozráno (%1 potvrzení, bude k dispozici za %2) + Nedozráno (%1 potvrzení, dozraje při %2 potvrzeních) Open for %n more block(s) @@ -2636,6 +2728,10 @@ Copy transaction ID Kopíruj ID transakce + + Copy raw transaction + Kopíruj surovou transakci + Edit label Uprav označení @@ -2670,7 +2766,7 @@ Comma separated file (*.csv) - CSV formát (*.csv) + Formát CSV (*.csv) Confirmed @@ -2783,14 +2879,66 @@ Accept command line and JSON-RPC commands Akceptovat příkazy z příkazové řádky a přes JSON-RPC + + If <category> is not supplied or if <category> = 1, output all debugging information. + Pokud není <category> zadána nebo je <category> = 1, bude tisknout veškeré ladicí informace. + + + Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. + Prosím zkontrolujte nastavení času na svém počítači. Pokud čas a datum není nastaven správně, Bitcoin Core nebude fungovat! + + + Prune configured below the minimum of %d MiB. Please use a higher number. + Prořezávání je nastaveno pod minimum %d MiB. Použij, prosím, nějaké vyšší číslo. + + + Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node) + Prořezávání: poslední synchronizace peněženky proběhla před už prořezanými daty. Je třeba provést -reindex (tedy v případě prořezávacího režimu stáhnout znovu celý řetězec bloků) + + + Reduce storage requirements by pruning (deleting) old blocks. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, >%u = target size in MiB to use for block files) + Omezit nároky na úložný prostor prořezáváním (mazáním) starých bloků. Tento režim není slučitelný s -txindex ani -rescan. Upozornění: opětovná změna tohoto nastavení bude vyžadovat nové stažení celého řetězce bloků. (výchozí: 0 = bloky neprořezávat, >%u = cílová velikost souborů s bloky, v MiB) + + + Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again. + V prořezávacím režimu není možné přeskenovávat řetězec bloků. Musíš provést -reindex, což znovu stáhne celý řetězec bloků. + + + Error: A fatal internal error occurred, see debug.log for details + Chyba: Přihodila se závažná vnitřní chyba, podrobnosti viz v debug.log + + + Fee (in %s/kB) to add to transactions you send (default: %s) + Poplatek (v %s/kB), který se přidá ke každé odeslané transakci (výchozí: %s) + + + Pruning blockstore... + Prořezávám úložiště bloků... + Run in the background as a daemon and accept commands - Běžet na pozadí jako démon a akceptovat příkazy + Běžet na pozadí jako démon a přijímat příkazy + + + Unable to start HTTP server. See debug log for details. + Nemohu spustit HTTP server. Detaily viz v debug.log. Accept connections from outside (default: 1 if no -proxy or -connect) Přijímat spojení zvenčí (výchozí: 1, pokud není zadáno -proxy nebo -connect) + + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. + -fallbackfee je nastaveno velmi vysoko! Toto je transakční poplatek, který bys platil, pokud nebude k dispozici odhad poplatků. + + + A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s) + Sazba poplatku (v %s/kB), která se použije, pokud nebude k dispozici dostatek dat pro automatický odhad poplatku (výchozí: %s) + + + Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d) + Přijímat přeposílané transakce obdržené od vždy vítaných protějšků, i když transakce nepřeposíláme (výchozí: %d) + Bind to given address and always listen on it. Use [host]:port notation for IPv6 Poslouchat na zadané adrese. Pro zápis IPv6 adresy použij notaci [adresa]:port @@ -2807,10 +2955,18 @@ Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) Spustit příkaz, když se objeví transakce týkající se peněženky (%s se v příkazu nahradí za TxID) + + Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) + Vynutit přeposílání transakcí od vždy vítaných protějšků (tj. těch na bílé listině), i když porušují místní zásady pro přeposílání (výchozí: %d) + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) Nastavení počtu vláken pro verifikaci skriptů (%u až %d, 0 = automaticky, <0 = nechat daný počet jader volný, výchozí: %d) + + 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 + Databáze bloků obsahuje blok, který vypadá jako z budoucnosti, což může být kvůli špatně nastavenému datu a času na tvém počítači. Nech databázi bloků přestavět pouze v případě, že si jsi jistý, že máš na počítači správný datum a čas + This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Tohle je testovací verze – používej ji jen na vlastní riziko, ale rozhodně ji nepoužívej k těžbě nebo pro obchodní aplikace @@ -2819,6 +2975,14 @@ Unable to bind to %s on this computer. Bitcoin Core is probably already running. Nedaří se mi připojit na %s na tomhle počítači. Bitcoin Core už pravděpodobně jednou běží. + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + Nepodporovaný argument -whitelistalwaysrelay se ignoruje, použij -whitelistrelay a/nebo -whitelistforcerelay. + + + Use UPnP to map the listening port (default: 1 when listening and no -proxy) + Použít UPnP k namapování naslouchacího portu (výchozí: 1, pokud naslouchá a nepoužívá -proxy) + WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) UPOZORNĚNÍ: vygenerováno nezvykle mnoho bloků – přijato %d bloků jen za posledních %d hodin (očekáváno %d) @@ -2837,16 +3001,24 @@ Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Upozornění: soubor wallet.dat je poškozený, data jsou však zachráněna! Původní soubor wallet.dat je uložený jako wallet.{timestamp}.bak v %s. Pokud je stav tvého účtu nebo transakce nesprávné, zřejmě bys měl obnovit zálohu. + Upozornění: soubor wallet.dat je poškozený, data jsou však zachráněna! Původní soubor wallet.dat je uložený jako wallet.{timestamp}.bak v %s. Pokud jsou stav tvého účtu nebo transakce nesprávné, zřejmě bys měl obnovit zálohu. Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. - Umístit na bílou listinu protějšky připojující se z dané podsítě či IP adresy. Lze zadat i vícekrát. + Vždy vítat protějšky připojující se z dané podsítě či IP adresy. Lze zadat i vícekrát. + + + -maxmempool must be at least %d MB + -maxmempool musí být alespoň %d MB <category> can be: <category> může být: + + Append comment to the user agent string + Připojit komentář k typu klienta + Block creation options: Možnosti vytváření bloku: @@ -2911,6 +3083,22 @@ Invalid -onion address: '%s' Neplatná -onion adresa: '%s' + + Invalid amount for -fallbackfee=<amount>: '%s' + Neplatná částka pro -fallbackfee=<částka>: '%s' + + + Keep the transaction memory pool below <n> megabytes (default: %u) + Udržovat zasobník transakcí menší než <n> megabajtů (výchozí: %u) + + + Location of the auth cookie (default: data dir) + Místo pro autentizační cookie (výchozí: adresář pro data) + + + Minimum bytes per sigop in transactions we relay and mine (default: %u) + Minimální počet bajtů na každý sigop v transakcích, které přeposíláme a těžíme (výchozí: %u) + Not enough file descriptors available. Je nedostatek deskriptorů souborů. @@ -2919,6 +3107,10 @@ Only connect to nodes in network <net> (ipv4, ipv6 or onion) Připojovat se pouze k uzlům v <net> síti (ipv4, ipv6 nebo onion) + + Print version and exit + Vypsat verzi a skončit + Prune cannot be configured with a negative value. Prořezávání nemůže být zkonfigurováno s negativní hodnotou. @@ -2939,10 +3131,26 @@ Specify wallet file (within data directory) Udej název souboru s peněženkou (v rámci datového adresáře) + + Unsupported argument -benchmark ignored, use -debug=bench. + Nepodporovaný argument -benchmark se ignoruje, použij -debug=bench. + + + Unsupported argument -debugnet ignored, use -debug=net. + Nepodporovaný argument -debugnet se ignoruje, použij -debug=net. + + + Unsupported argument -tor found, use -onion. + Argument -tor již není podporovaný, použij -onion. + Use UPnP to map the listening port (default: %u) Použít UPnP k namapování naslouchacího portu (výchozí: %u) + + User Agent comment (%s) contains unsafe characters. + Komentář u typu klienta (%s) obsahuje riskantní znaky. + Verifying blocks... Ověřuji bloky... @@ -2959,10 +3167,6 @@ Wallet options: Možnosti peněženky: - - Warning: This version is obsolete; upgrade required! - Upozornění: tahle verze je zastaralá, měl bys ji aktualizovat! - You need to rebuild the database using -reindex to change -txindex Je třeba přestavět databázi použitím -reindex, aby bylo možné změnit -txindex @@ -2973,7 +3177,7 @@ Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6 - Obsadit zadanou adresu a protějšky, které se na ní připojí, umístit na bílou listinu. Pro zápis IPv6 adresy použij notaci [adresa]:port + Obsadit zadanou adresu a vždy vítat protějšky, které se na ni připojí. Pro zápis IPv6 adresy použij notaci [adresa]:port Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces) @@ -2999,6 +3203,10 @@ Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message) Spustit příkaz, když přijde relevantní upozornění nebo když dojde k opravdu dlouhému rozštěpení řetezce bloků (%s se v příkazu nahradí zprávou) + + Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s) + Poplatky (v %s/kB) menší než tato hodnota jsou považovány za nulové pro účely přeposílání, těžení a vytváření transakcí (výchozí: %s) + If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u) Pokud paytxfee není nastaveno, platit dostatečný poplatek na to, aby začaly být transakce potvrzovány v průměru během n bloků (výchozí: %u) @@ -3037,7 +3245,7 @@ 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 - Na protějšky na bílé listině se nevztahuje DoS klatba a jejich transakce jsou vždy přeposílány, i když už třeba jsou v mempoolu, což je užitečné např. pro bránu + Na vždy vítané protějšky se nevztahuje DoS klatba a jejich transakce jsou vždy přeposílány, i když už třeba jsou v transakčním zásobníku, což je užitečné např. pro bránu You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain @@ -3055,6 +3263,14 @@ Activating best chain... Aktivuji nejlepší řetězec... + + Attempt to recover private keys from a corrupt wallet.dat on startup + Pokusit se při startu zachránit soukromé klíče z poškozeného souboru wallet.dat + + + Automatically create Tor hidden service (default: %d) + Automaticky v Toru vytvářet skryté služby (výchozí: %d) + Cannot resolve -whitebind address: '%s' Nemohu přeložit -whitebind adresu: '%s' @@ -3075,6 +3291,10 @@ Error reading from database, shutting down. Chyba při čtení z databáze, ukončuji se. + + Imports blocks from external blk000??.dat file on startup + Importovat při startu bloky z externího souboru blk000??.dat + Information Informace @@ -3127,6 +3347,14 @@ Receive and display P2P network alerts (default: %u) Přijímat a zobrazovat poplachy z P2P sítě (výchozí: %u) + + Reducing -maxconnections from %d to %d, because of system limitations. + Omezuji -maxconnections z %d na %d kvůli systémovým omezením. + + + Rescan the block chain for missing wallet transactions on startup + Přeskenovat při startu řetězec bloků na chybějící transakce tvé pěněženky + Send trace/debug info to console instead of debug.log file Posílat stopovací/ladicí informace do konzole místo do souboru debug.log @@ -3155,6 +3383,14 @@ This is experimental software. Tohle je experimentální program. + + Tor control port password (default: empty) + Heslo ovládacího portu Toru (výchozí: prázdné) + + + Tor control port to use if onion listening enabled (default: %s) + Ovládací port Toru, je-li zapnuté onion naslouchání (výchozí: %s) + Transaction amount too small Částka v transakci je příliš malá @@ -3175,6 +3411,10 @@ Unable to bind to %s on this computer (bind returned error %s) Nedaří se mi připojit na %s na tomhle počítači (operace bind vrátila chybu %s) + + Upgrade wallet to latest format on startup + Převést při startu peněženku na nejnovější formát + Username for JSON-RPC connections Uživatelské jméno pro JSON-RPC spojení @@ -3187,10 +3427,18 @@ Warning Upozornění + + Whether to operate in a blocks only mode (default: %u) + Zda fungovat v čistě blokovém režimu (výchozí: %u) + Zapping all transactions from wallet... Vymazat všechny transakce z peněženky... + + ZeroMQ notification options: + Možnosti ZeroMQ oznámení: + wallet.dat corrupt, salvage failed Soubor wallet.dat je poškozen, jeho záchrana se nezdařila @@ -3223,6 +3471,26 @@ (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) (1 = ukládat transakční metadata, např. majitele účtu a informace o platebním požadavku, 2 = mazat transakční metadata) + + -maxtxfee is set very high! Fees this large could be paid on a single transaction. + -maxtxfee je nastaveno velmi vysoko! Takto vysoký poplatek může být zaplacen v jednotlivé transakci. + + + -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + -paytxfee je nastaveno velmi vysoko! Toto je transakční poplatek, který zaplatíš za každou poslanou transakci. + + + Do not keep transactions in the mempool longer than <n> hours (default: %u) + Nedržet transakce v zásobníku déle než <n> hodin (výchozí: %u) + + + Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Nastala chyba při čtení souboru wallet.dat! Všechny klíče se přečetly správně, ale data o transakcích nebo záznamy v adresáři mohou chybět či být nesprávné. + + + Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) + Poplatky (v %s/kB) menší než tato hodnota jsou považovány za nulové pro účely vytváření transakcí (výchozí: %s) + How thorough the block verification of -checkblocks is (0-4, default: %u) Jak moc důkladná má být verifikace bloků -checkblocks (0-4, výchozí: %u) @@ -3239,10 +3507,30 @@ Output debugging information (default: %u, supplying <category> is optional) Tisknout ladicí informace (výchozí: %u, zadání <category> je volitelné) + + Support filtering of blocks and transaction with bloom filters (default: %u) + Umožnit filtrování bloků a transakcí pomocí Bloomova filtru (výchozí: %u) + + + Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments. + Celková délka síťového identifikačního řetězce (%i) překročila svůj horní limit (%i). Omez počet nebo velikost voleb uacomment. + + + Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d) + Pokusit se udržet odchozí provoz pod stanovenou hodnotou (v MiB za 24 hodin), 0 = bez omezení (výchozí: %d) + + + Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported. + Byl použit nepodporovaný argument -socks. Nastavení verze SOCKS už není možné, podporovány jsou pouze SOCKS5 proxy. + Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s) Použít samostatnou SOCKS5 proxy ke spojení s protějšky přes skryté služby v Toru (výchozí: %s) + + Username and hashed password for JSON-RPC connections. The field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A canonical python script is included in share/rpcuser. This option can be specified multiple times + Uživatelské jméno a zahašované heslo pro JSON-RPC spojení. Pole <userpw> má formát: <UŽIVATELSKÉ_JMÉNO>:<SŮL>$<HAŠ>. Pomocný pythonní skript je přiložen v share/rpcuser. Tuto volbu lze použít i vícekrát + (default: %s) (výchozí: %s) @@ -3327,10 +3615,6 @@ Specify connection timeout in milliseconds (minimum: 1, default: %d) Zadej časový limit spojení v milivteřinách (minimum: 1, výchozí: %d) - - Specify pid file (default: %s) - PID soubor (výchozí: %s) - Spend unconfirmed change when sending transactions (default: %u) Utrácet i ještě nepotvrzené drobné při posílání transakcí (výchozí: %u) diff --git a/src/qt/locale/bitcoin_cs_CZ.ts b/src/qt/locale/bitcoin_cs_CZ.ts index cc0c791154a90..34d7b4b4a1644 100644 --- a/src/qt/locale/bitcoin_cs_CZ.ts +++ b/src/qt/locale/bitcoin_cs_CZ.ts @@ -1,6 +1,10 @@ AddressBookPage + + Right-click to edit address or label + Pravým klikem editujte adresu nebo popisek + Create a new address Vytvořit novou adresu @@ -9,6 +13,18 @@ Copy the currently selected address to the system clipboard Kopírovat aktuálně vybrané adresy do schránky + + Delete the currently selected address from the list + Odstraní aktuálně vybrané adresy ze seznamu + + + Export the data in the current tab to a file + Exportovat aktuální pohled do souboru + + + &Export + &Exportovat + &Delete &Odstranit @@ -622,6 +638,14 @@ WalletView + + &Export + &Exportovat + + + Export the data in the current tab to a file + Exportovat aktuální pohled do souboru + bitcoin-core diff --git a/src/qt/locale/bitcoin_da.ts b/src/qt/locale/bitcoin_da.ts index aa2724a1e81ca..7d11825a618a7 100644 --- a/src/qt/locale/bitcoin_da.ts +++ b/src/qt/locale/bitcoin_da.ts @@ -1017,7 +1017,7 @@ 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. - Minimér i stedet for at lukke applikationen, når vinduet lukkes. Når denne indstilling er slået til, vil applikationen først blive lukket, når Afslut vælges i menuen. + Minimér i stedet for at lukke applikationen, når vinduet lukkes. Når denne indstilling er aktiveret, vil applikationen først blive lukket, når Afslut vælges i menuen. The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. @@ -1069,7 +1069,7 @@ Enable coin &control features - Slå egenskaber for &coin-styring til + Aktivér egenskaber for &coin-styring 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. @@ -1473,10 +1473,6 @@ General Generelt - - Using OpenSSL version - Anvender OpenSSL-version - Using BerkeleyDB version Bruger BerkeleyDB version @@ -2979,6 +2975,18 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Acceptér forbindelser udefra (standard: 1 hvis hverken -proxy eller -connect) + + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. + -fallbackfee er sat meget højt! Dette er transaktionsgebyret, du eventuelt betaler, hvis gebyrestimater ikke er tilgængelige. + + + A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s) + En gebyrsats (i %s/kB), som vil blive brugt, hvis gebyrestimering har utilstrækkelig data (standard: %s) + + + Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d) + Acceptér videresendte transaktioner, der modtages fra hvidlistede knuder, selv når transaktioner ikke videresendes (standard: %d) + Bind to given address and always listen on it. Use [host]:port notation for IPv6 Tildel til den givne adresse og lyt altid på den. Brug [vært]:port-notation for IPv6 @@ -2995,6 +3003,10 @@ Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) Udfør kommando, når en transaktion i tegnebogen ændres (%s i kommandoen erstattes med TxID) + + Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) + Gennemtving videresendelse af transaktioner fra hvidlistede knuder, selv om de overtræder lokal videresendelsespolitik (standard: %d) + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) Sæt antallet af scriptverificeringstråde (%u til %d, 0 = auto, <0 = efterlad det antal kernet fri, standard: %d) @@ -3011,6 +3023,10 @@ Unable to bind to %s on this computer. Bitcoin Core is probably already running. Ikke i stand til at tildele til %s på denne computer. Bitcoin Core kører sansynligvis allerede. + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + Argument -whitelistalwaysrelay understøttes ikke og ignoreres; brug -whitelistrelay og/eller -whitelistforcerelay. + Use UPnP to map the listening port (default: 1 when listening and no -proxy) Brug UPnP for at konfigurere den lyttende port (standard: 1 under lytning og ingen -proxy) @@ -3027,6 +3043,10 @@ Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Advarsel: Netværket ser ikke ud til at være fuldt ud enige! Enkelte minere ser ud til at opleve problemer. + + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + Advarsel: Ukendte blokversioner bliver minet! Det er muligt, at ukendte regler er i brug + Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Advarsel: Vi ser ikke ud til at være fuldt ud enige med andre knuder! Du kan være nødt til at opgradere, eller andre knuder kan være nødt til at opgradere. @@ -3047,6 +3067,10 @@ <category> can be: <kategori> kan være: + + Append comment to the user agent string + Føj kommentar til brugeragentstrengen + Block creation options: Blokoprettelsestilvalg: @@ -3091,6 +3115,10 @@ Enable publish raw transaction in <address> Aktivér offentliggørelse af rå transaktion i <address> + + Enable transaction replacement in the memory pool (default: %u) + Aktivér transaktionserstatning i hukommelsespuljen (standard: %u) + Error initializing block database Klargøring af blokdatabase mislykkedes @@ -3127,10 +3155,22 @@ Invalid -onion address: '%s' Ugyldig -onion adresse: "%s" + + Invalid amount for -fallbackfee=<amount>: '%s' + Ugyldigt beløb for -fallbackfee=<beløb>: "%s" + Keep the transaction memory pool below <n> megabytes (default: %u) Hold hukommelsespuljen med transaktioner under <n> megabyte (standard: %u) + + Location of the auth cookie (default: data dir) + Placering for autentificerings-cookie (standard: datamappe) + + + Minimum bytes per sigop in transactions we relay and mine (default: %u) + Minimum bytes pr. sigop i transaktioner, vi videresender og miner (standard: %u) + Not enough file descriptors available. For få tilgængelige fildeskriptorer. @@ -3139,6 +3179,10 @@ Only connect to nodes in network <net> (ipv4, ipv6 or onion) Tilslut kun til knuder i netværk <net> (IPv4, IPv6 eller Onion) + + Print version and exit + Udskriv version og afslut + Prune cannot be configured with a negative value. Beskæring kan ikke opsættes med en negativ værdi. @@ -3195,10 +3239,6 @@ Wallet options: Tilvalg for tegnebog: - - Warning: This version is obsolete; upgrade required! - Advarsel: Denne version er forældet; opgradering påkrævet! - You need to rebuild the database using -reindex to change -txindex Du er nødt til at genopbygge databasen ved hjælp af -reindex for at ændre -txindex @@ -3257,7 +3297,7 @@ Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u) - Brug tilfældige akkreditiver for hver proxy-forbindelse. Dette tillader strømisolation med Tor (standard: %u) + Brug tilfældige akkreditiver for hver proxy-forbindelse. Dette aktiverer strømisolation med Tor (standard: %u) Set maximum size of high-priority/low-fee transactions in bytes (default: %d) @@ -3277,7 +3317,7 @@ 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 - Andre knuder på hvidliste kan ikke DoS-bandlyses, og deres transaktioner videresendes altid, selv hvis de allerede er i mempool'en. Brugbart til fx et adgangspunkt + Andre knuder på hvidliste kan ikke DoS-bandlyses, og deres transaktioner videresendes altid, selv hvis de allerede er i hukommelsespuljen. Brugbart til fx et adgangspunkt You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain @@ -3295,10 +3335,6 @@ Activating best chain... Aktiverer bedste kæde… - - Always relay transactions received from whitelisted peers (default: %d) - Videresend altid transaktioner, der modtages fra hvidlistede knuder (standard: %d) - Attempt to recover private keys from a corrupt wallet.dat on startup Forsøg at genskabe private nøgler fra en ødelagt wallet.dat under opstart @@ -3425,7 +3461,7 @@ Tor control port to use if onion listening enabled (default: %s) - Tor kontrolport, der skal bruges, hvis onion-lytning er slået til (standard: %s) + Tor kontrolport, der skal bruges, hvis onion-lytning er aktiveret (standard: %s) Transaction amount too small @@ -3463,6 +3499,10 @@ Warning Advarsel + + Warning: unknown new rules activated (versionbit %i) + Advarsel: Ukendte nye regler aktiveret (versionsbit %i) + Whether to operate in a blocks only mode (default: %u) Hvorvidt der skal arbejdes i kun-blokke-tilstand (standard: %u) diff --git a/src/qt/locale/bitcoin_de.ts b/src/qt/locale/bitcoin_de.ts index 84de80aff50d3..947a471acd1dc 100644 --- a/src/qt/locale/bitcoin_de.ts +++ b/src/qt/locale/bitcoin_de.ts @@ -892,7 +892,7 @@ Set language, for example "de_DE" (default: system locale) - Sprache einstellen, zum Beispiel "de_DE" (default: system locale) + Sprache einstellen, zum Beispiel "de_DE" (Standard: Systemgebietsschema) Start minimized @@ -1473,10 +1473,6 @@ General Allgemein - - Using OpenSSL version - Verwendete OpenSSL-Version - Using BerkeleyDB version Verwendete BerkeleyDB-Version @@ -2927,6 +2923,10 @@ Accept command line and JSON-RPC commands Kommandozeilen- und JSON-RPC-Befehle annehmen + + If <category> is not supplied or if <category> = 1, output all debugging information. + Wenn <category> nicht angegeben wird oder <category>=1, jegliche Debugginginformationen ausgeben. + Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s) Maximale Gesamtgebühr (in %s) in einer Börsentransaktion; wird dies zu niedrig gesetzten können große Transaktionen abgebrochen werden (Standard: %s) @@ -2935,10 +2935,22 @@ Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. Bitte korrigieren Sie die Datums- und Uhrzeiteinstellungen Ihres Computers, da Bitcoin Core ansonsten nicht ordnungsgemäß funktionieren wird. + + Prune configured below the minimum of %d MiB. Please use a higher number. + Kürzungsmodus wurde kleiner als das Minimum in Höhe von %d MiB konfiguriert. Bitte verwenden Sie einen größeren Wert. + + + Reduce storage requirements by pruning (deleting) old blocks. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, >%u = target size in MiB to use for block files) + Speicherplatzanforderung durch kürzen (löschen) alter Blöcke reduzieren. Dieser Modus ist nicht mit -txindex und -rescan kompatibel. Warnung: Die Umkehr dieser Einstellung erfordert das erneute Herunterladen der gesamten Blockkette. (Standard: 0 = deaktiviert das Kürzen von Blöcken, >%u = Zielgröße in MiB, die für Blockdateien verwendet werden darf) + Error: A fatal internal error occurred, see debug.log for details Fehler: Ein schwerer interner Fehler ist aufgetreten, siehe debug.log für Details. + + Fee (in %s/kB) to add to transactions you send (default: %s) + Gebühr (in %s/kB), die von Ihnen gesendeten Transaktionen hinzugefügt wird (Standard: %s) + Pruning blockstore... Kürze Blockspeicher... @@ -2955,6 +2967,14 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Eingehende Verbindungen annehmen (Standard: 1, wenn nicht -proxy oder -connect) + + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. + -fallbackfee ist sehr hoch eingestellt! Das ist die Transaktionsgebühr, welche du zahlen müsstest, wenn die Gebührenschätzungen nicht verfügbar sind. + + + A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s) + Eine Transaktionsgebühr (in %s/kB) wird genutzt, wenn für die Gebührenschützung zu wenig Daten vorliegen (Standardwert: %s) + Bind to given address and always listen on it. Use [host]:port notation for IPv6 An die angegebene Adresse binden und immer abhören. Für IPv6 "[Host]:Port"-Notation verwenden @@ -2971,10 +2991,18 @@ Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) Befehl ausführen wenn sich eine Wallet-Transaktion verändert (%s im Befehl wird durch die Transaktions-ID ersetzt) + + Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) + Leite Transaktionen von Peers auf der Positivliste auf jeden Fall weiter, auch wenn sie die lokale Weiterleitungsregeln verletzen (Standardeinstellung: %d) + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) Maximale Anzahl an Skript-Verifizierungs-Threads festlegen (%u bis %d, 0 = automatisch, <0 = so viele Kerne frei lassen, Standard: %d) + + 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 + 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. + This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Dies ist eine Vorab-Testversion - Verwendung auf eigene Gefahr - nicht für Mining- oder Handelsanwendungen nutzen! @@ -2983,6 +3011,14 @@ Unable to bind to %s on this computer. Bitcoin Core is probably already running. Kann auf diesem Computer nicht an %s binden, da Bitcoin Core wahrscheinlich bereits gestartet wurde. + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + Das Argument -whitelistalwaysrelay wird nicht unterstützt und deswegen ignoriert. Benutze -whitelistrelay und/oder -whitelistforcerelay. + + + Use UPnP to map the listening port (default: 1 when listening and no -proxy) + UPnP verwenden, um eine Portweiterleitung einzurichten (Standard: 1, wenn abgehört wird und -proxy nicht gesetzt ist) + WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) Warnung: Es wurde eine ungewöhnlich hohe Anzahl Blöcke erzeugt, %d Blöcke wurden in den letzten %d Stunden empfangen (%d wurden erwartet). @@ -2995,6 +3031,10 @@ Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Warnung: Das Netzwerk scheint nicht vollständig übereinzustimmen! Einige Miner scheinen Probleme zu haben. + + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + Warnung: Unbekannte Blockversion wird durch Mining erzeugt! Es ist möglich, dass unbekannte Regeln in Kraft sind. + Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Warnung: Wir scheinen nicht vollständig mit unseren Gegenstellen übereinzustimmen! Sie oder die anderen Knoten müssen unter Umständen Ihre Client-Software aktualisieren. @@ -3015,6 +3055,10 @@ <category> can be: <category> kann sein: + + Append comment to the user agent string + Hänge ein Kommentar zur User Agent-Zeichenkette an + Block creation options: Blockerzeugungsoptionen: @@ -3055,6 +3099,10 @@ Enable publish raw block in <address> Aktiviere das Veröffentlichen des Raw-Blocks in <address> + + Enable publish raw transaction in <address> + Aktiviere das Veröffentlichen der Roh-Transaktion in <address> + Error initializing block database Fehler beim Initialisieren der Blockdatenbank @@ -3091,6 +3139,18 @@ Invalid -onion address: '%s' Ungültige "-onion"-Adresse: '%s' + + Invalid amount for -fallbackfee=<amount>: '%s' + Ungültiger Betrag für -fallbackfee=<amount>: '%s' + + + Keep the transaction memory pool below <n> megabytes (default: %u) + Halten Sie den Transaktionsspeicherpool unter <n> Megabytes (Voreinstellung: %u) + + + Location of the auth cookie (default: data dir) + Dateiort für das Auth-Cookie (Standard: Datenverzeichnis) + Not enough file descriptors available. Nicht genügend Datei-Deskriptoren verfügbar. @@ -3099,6 +3159,10 @@ Only connect to nodes in network <net> (ipv4, ipv6 or onion) Nur zu Knoten des Netzwerktyps <net> verbinden (ipv4, ipv6 oder onion) + + Print version and exit + Gibt die Versionsnummer aus und beendet das Programm + Prune cannot be configured with a negative value. Kürzungsmodus kann nicht mit einem negativen Wert konfiguriert werden. @@ -3135,6 +3199,10 @@ Use UPnP to map the listening port (default: %u) UPnP verwenden, um eine Portweiterleitung einzurichten (Standard: %u) + + User Agent comment (%s) contains unsafe characters. + Der User Agent Kommentar (%s) enthält unsichere Zeichen. + Verifying blocks... Verifiziere Blöcke... @@ -3151,10 +3219,6 @@ Wallet options: Wallet-Optionen: - - Warning: This version is obsolete; upgrade required! - Warnung: Diese Version is veraltet, Aktualisierung erforderlich! - You need to rebuild the database using -reindex to change -txindex Sie müssen die Datenbank mit Hilfe von -reindex neu aufbauen, um -txindex zu verändern @@ -3191,6 +3255,10 @@ Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message) Befehl ausführen wenn ein relevanter Alarm empfangen wird oder wir einen wirklich langen Fork entdecken (%s im Befehl wird durch die Nachricht ersetzt) + + Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s) + Niedrigere Gebühren (in %s/Kb) als diese werden bei der Transaktionserstellung als gebührenfrei angesehen (Standard: %s) + If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u) Wenn -paytxfee nicht festgelegt wurde Gebühren einschließen, so dass mit der Bestätigung von Transaktionen im Schnitt innerhalb von n Blöcken begonnen wird (Standard: %u) @@ -3331,6 +3399,10 @@ Receive and display P2P network alerts (default: %u) P2P-Netzwerk-Alarme empfangen und anzeigen (Standard: %u) + + Reducing -maxconnections from %d to %d, because of system limitations. + Reduziere -maxconnections von %d zu %d, aufgrund von Systemlimitierungen. + Rescan the block chain for missing wallet transactions on startup Blockkette beim Starten erneut nach fehlenden Wallet-Transaktionen durchsuchen @@ -3407,6 +3479,10 @@ Warning Warnung + + Warning: unknown new rules activated (versionbit %i) + Warnung: Unbekannte neue Regeln aktiviert (Versionsbit %i) + Whether to operate in a blocks only mode (default: %u) Legt fest ob nur Blöcke Modus aktiv sein soll (Standard: %u) @@ -3467,6 +3543,10 @@ Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. Lesen von wallet.dat fehlgeschlagen! Alle Schlüssel wurden korrekt gelesen, Transaktionsdaten bzw. Adressbucheinträge fehlen aber möglicherweise oder sind inkorrekt. + + Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) + Niedrigere Gebühren (in %s/Kb) als diese werden bei der Transaktionserstellung als gebührenfrei angesehen (Standard: %s) + How thorough the block verification of -checkblocks is (0-4, default: %u) Legt fest, wie gründlich die Blockverifikation von -checkblocks ist (0-4, Standard: %u) @@ -3483,6 +3563,10 @@ Output debugging information (default: %u, supplying <category> is optional) Debugginginformationen ausgeben (Standard: %u, <category> anzugeben ist optional) + + Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments. + Gesamtlänge des Netzwerkversionstrings (%i) erreicht die maximale Länge (%i). Reduzieren Sie die Nummer oder die Größe von uacomments. + Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d) Versucht ausgehenden Datenverkehr unter dem gegebenen Wert zu halten (in MiB pro 24h), 0 = kein Limit (default: %d) @@ -3495,6 +3579,10 @@ Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s) Separaten SOCKS5-Proxy verwenden, um Gegenstellen über versteckte Tor-Dienste zu erreichen (Standard: %s) + + Username and hashed password for JSON-RPC connections. The field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A canonical python script is included in share/rpcuser. This option can be specified multiple times + Benutzername und gehashtes Passwort für JSON-RPC Verbindungen. Das Feld <userpw> kommt im Format: <USERNAME>:<SALT>$<HASH>. Ein kanonisches Pythonskript ist in share/rpcuser inbegriffen. Diese Option kann mehrere Male spezifiziert werden + (default: %s) (Standard: %s) diff --git a/src/qt/locale/bitcoin_el_GR.ts b/src/qt/locale/bitcoin_el_GR.ts index 90c27c43943ac..b5fb22f9739bf 100644 --- a/src/qt/locale/bitcoin_el_GR.ts +++ b/src/qt/locale/bitcoin_el_GR.ts @@ -168,6 +168,11 @@ Are you sure you wish to encrypt your wallet? Είστε σίγουροι ότι θέλετε να κρυπτογραφήσετε το πορτοφόλι σας; + + Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. + Το Bitcoin Core θα κλεισει τώρα για να τελειώσει την διαδικασία κρυπτογράφησης. Θυμήσου ότι κρυπτογραφώντας το πορτοφόλι σου δεν μπορείς να προστατέψεις πλήρως τα bitcoins σου από κλοπή στην περίπτωση που μολυνθεί ο υπολογιστής σου με κακόβουλο λογισμικό. + + 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. ΣΗΜΑΝΤΙΚΟ: Τα προηγούμενα αντίγραφα ασφαλείας που έχετε κάνει από το αρχείο του πορτοφόλιου σας θα πρέπει να αντικατασταθουν με το νέο που δημιουργείται, κρυπτογραφημένο αρχείο πορτοφόλιου. Για λόγους ασφαλείας, τα προηγούμενα αντίγραφα ασφαλείας του μη κρυπτογραφημένου αρχείου πορτοφόλιου θα καταστουν άχρηστα μόλις αρχίσετε να χρησιμοποιείτε το νέο κρυπτογραφημένο πορτοφόλι. @@ -184,6 +189,10 @@ Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. Εισάγετε τον νέο κωδικό πρόσβασης στον πορτοφόλι <br/> Παρακαλώ χρησιμοποιείστε ένα κωδικό με <b> 10 ή περισσότερους τυχαίους χαρακτήρες</b> ή <b> οχτώ ή παραπάνω λέξεις</b>. + + Enter the old passphrase and new passphrase to the wallet. + Πληκτρολόγησε τον παλιό και τον νέο κωδικό στο πορτοφολι. + Wallet encryption failed Η κρυπτογραφηση του πορτοφολιού απέτυχε @@ -1324,10 +1333,6 @@ General Γενικά - - Using OpenSSL version - Χρησιμοποιηση της OpenSSL εκδοσης - Using BerkeleyDB version Χρήση BerkeleyDB έκδοσης diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts index b90221f2c2535..f122273a35216 100644 --- a/src/qt/locale/bitcoin_en.ts +++ b/src/qt/locale/bitcoin_en.ts @@ -34,12 +34,7 @@ - - &Copy Address - &Copy Address - - - + Delete the currently selected address from the list Delete the currently selected address from the list @@ -58,89 +53,6 @@ &Delete &Delete - - - Choose the address to send coins to - - - - - Choose the address to receive coins with - - - - - C&hoose - - - - - Sending addresses - - - - - Receiving addresses - - - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - - - - - Copy &Label - Copy &Label - - - - &Edit - &Edit - - - - Export Address List - - - - - Comma separated file (*.csv) - Comma separated file (*.csv) - - - - Exporting Failed - - - - - There was an error trying to save the address list to %1. Please try again. - - - - - AddressTableModel - - - Label - Label - - - - Address - Address - - - - (no label) - (no label) - AskPassphraseDialog @@ -164,124 +76,6 @@ Repeat new passphrase Repeat new passphrase - - - Encrypt wallet - Encrypt wallet - - - - This operation needs your wallet passphrase to unlock the wallet. - This operation needs your wallet passphrase to unlock the wallet. - - - - Unlock wallet - Unlock wallet - - - - This operation needs your wallet passphrase to decrypt the wallet. - This operation needs your wallet passphrase to decrypt the wallet. - - - - Decrypt wallet - Decrypt wallet - - - - Change passphrase - Change passphrase - - - - Confirm wallet encryption - Confirm wallet encryption - - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - - - - Are you sure you wish to encrypt your wallet? - Are you sure you wish to encrypt your wallet? - - - - 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. - 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. - - - - - Warning: The Caps Lock key is on! - Warning: The Caps Lock key is on! - - - - - Wallet encrypted - Wallet encrypted - - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - - - - - Enter the old passphrase and new passphrase to the wallet. - - - - - %1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - - - - - - - - Wallet encryption failed - Wallet encryption failed - - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - - - - - The supplied passphrases do not match. - The supplied passphrases do not match. - - - - Wallet unlock failed - Wallet unlock failed - - - - - - The passphrase entered for the wallet decryption was incorrect. - The passphrase entered for the wallet decryption was incorrect. - - - - Wallet decryption failed - Wallet decryption failed - - - - Wallet passphrase was successfully changed. - Wallet passphrase was successfully changed. - BanTableModel @@ -795,396 +589,173 @@ Priority + + + EditAddressDialog - - Copy address - Copy address + + Edit Address + Edit Address - - Copy label - Copy label + + &Label + &Label - - - Copy amount - Copy amount + + The label associated with this address list entry + - - Copy transaction ID - Copy transaction ID + + The address associated with this address list entry. This can only be modified for sending addresses. + - - Lock unspent - + + &Address + &Address + + + FreespaceChecker - - Unlock unspent - + + A new data directory will be created. + A new data directory will be created. - Copy quantity - + name + name - Copy fee - + Directory already exists. Add %1 if you intend to create a new directory here. + Directory already exists. Add %1 if you intend to create a new directory here. - - Copy after fee - + + Path already exists, and is not a directory. + Path already exists, and is not a directory. - - Copy bytes - + + Cannot create data directory here. + Cannot create data directory here. + + + HelpMessageDialog - - Copy priority - + + version + version - - Copy dust + + + (%1-bit) - - Copy change + + About %1 - - highest + + Command-line options - higher - + Usage: + Usage: - high - + command-line options + command-line options - - medium-high + + UI Options: - - medium + + Choose data directory on startup (default: %u) - low-medium + Set language, for example "de_DE" (default: system locale) - low + Start minimized - lower + Set SSL root certificates for payment request (default: -system-) - lowest - - - - - (%1 locked) + Show splash screen on startup (default: %u) - - none + + Reset all settings changed in the GUI + + + Intro - - This label turns red if the transaction size is greater than 1000 bytes. - + + Welcome + Welcome - - This label turns red if the priority is smaller than "medium". + + Welcome to %1. - - Can vary +/- %1 satoshi(s) per input. + + As this is the first time the program is launched, you can choose where %1 will store its data. - - yes + + %1 will download and store a copy of the Bitcoin block chain. At least %2GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - - no - + + Use the default data directory + Use the default data directory - - - This means a fee of at least %1 per kB is required. - + + Use a custom data directory: + Use a custom data directory: - - Can vary +/- 1 byte per input. + + Error: Specified data directory "%1" cannot be created. - - Transactions with higher priority are more likely to get included into a block. - - - - - This label turns red if any recipient receives an amount smaller than the current dust threshold. - - - - - - (no label) - (no label) - - - - change from %1 (%2) - - - - - (change) - - - - - EditAddressDialog - - - Edit Address - Edit Address - - - - &Label - &Label - - - - The label associated with this address list entry - - - - - The address associated with this address list entry. This can only be modified for sending addresses. - - - - - &Address - &Address - - - - New receiving address - New receiving address - - - - New sending address - New sending address - - - - Edit receiving address - Edit receiving address - - - - Edit sending address - Edit sending address - - - - The entered address "%1" is already in the address book. - The entered address "%1" is already in the address book. - - - - The entered address "%1" is not a valid Bitcoin address. - The entered address "%1" is not a valid Bitcoin address. - - - - Could not unlock wallet. - Could not unlock wallet. - - - - New key generation failed. - New key generation failed. - - - - FreespaceChecker - - - A new data directory will be created. - A new data directory will be created. - - - - name - name - - - - Directory already exists. Add %1 if you intend to create a new directory here. - Directory already exists. Add %1 if you intend to create a new directory here. - - - - Path already exists, and is not a directory. - Path already exists, and is not a directory. - - - - Cannot create data directory here. - Cannot create data directory here. - - - - HelpMessageDialog - - - version - version - - - - - (%1-bit) - - - - - About %1 - - - - - Command-line options - - - - - Usage: - Usage: - - - - command-line options - command-line options - - - - UI Options: - - - - - Choose data directory on startup (default: %u) - - - - - Set language, for example "de_DE" (default: system locale) - - - - - Start minimized - - - - - Set SSL root certificates for payment request (default: -system-) - - - - - Show splash screen on startup (default: %u) - - - - - Reset all settings changed in the GUI - - - - - Intro - - - Welcome - Welcome - - - - Welcome to %1. - - - - - As this is the first time the program is launched, you can choose where %1 will store its data. - - - - - %1 will download and store a copy of the Bitcoin block chain. At least %2GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - - - - - Use the default data directory - Use the default data directory - - - - Use a custom data directory: - Use a custom data directory: - - - - Error: Specified data directory "%1" cannot be created. - - - - - Error - Error + + Error + Error @@ -1225,11 +796,6 @@ Select payment request file - - - Select payment request file to open - - OptionsDialog @@ -1627,218 +1193,69 @@ - PaymentServer + PeerTableModel - - - - URI handling - URI handling + + User Agent + - - Invalid payment address %1 + + Node/Service - - - - - - - Payment request rejected + + Ping Time + + + QObject - - Payment request network doesn't match client network. - + + Amount + Amount - - Payment request is not initialized. + + Enter a Bitcoin address (e.g. %1) - - Requested payment amount of %1 is too small (considered dust). + + %1 d - - - - - - - Payment request error + + %1 h - - Cannot start bitcoin: click-to-pay handler + + %1 m - - Payment request fetch URL is invalid: %1 + + + %1 s - - URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. + + None - - Payment request file handling - + + N/A + N/A - - Payment request file cannot be read! This can be caused by an invalid payment request file. - - - - - Payment request expired. - - - - - Unverified payment requests to custom payment scripts are unsupported. - - - - - - Invalid payment request. - - - - - Refund from %1 - - - - - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - - - - - Error communicating with %1: %2 - - - - - Payment request cannot be parsed! - - - - - Bad response from server %1 - - - - - Payment acknowledged - - - - - Network request error - - - - - PeerTableModel - - - User Agent - - - - - Node/Service - - - - - Ping Time - - - - - QObject - - - Amount - Amount - - - - Enter a Bitcoin address (e.g. %1) - - - - - %1 d - - - - - %1 h - - - - - %1 m - - - - - - %1 s - - - - - None - - - - - N/A - N/A - - - - %1 ms - - - - - QRImageWidget - - - &Save Image... - - - - - &Copy Image - - - - - Save QR Code - Save QR Code - - - - PNG Image (*.png) + + %1 ms @@ -2338,21 +1755,6 @@ Remove - - - Copy label - Copy label - - - - Copy message - - - - - Copy amount - Copy amount - ReceiveRequestDialog @@ -2376,95 +1778,11 @@ &Save Image... - - - Request payment to %1 - - - - - Payment information - - - - - URI - - - - - Address - Address - - - - Amount - Amount - - - - Label - Label - - - - Message - Message - - - - Resulting URI too long, try to reduce the text for label / message. - Resulting URI too long, try to reduce the text for label / message. - - - - Error encoding URI into QR Code. - Error encoding URI into QR Code. - - - - RecentRequestsTableModel - - - Date - Date - - - - Label - Label - - - - Message - Message - - - - (no amount requested) - - - - - Requested - - - - - (no label) - (no label) - - - - (no message) - - SendCoinsDialog - Send Coins Send Coins @@ -2650,190 +1968,39 @@ S&end S&end + + + SendCoinsEntry - - Confirm send coins - Confirm send coins - - - - - - - %1 to %2 - - - - - Copy quantity - - - - - Copy amount - Copy amount - - - - Copy fee - - - - - Copy after fee - - - - - Copy bytes - - - - - Copy priority - - - - - Copy change - - - - - Total Amount %1 - - - - - or - - - - - The amount to pay must be larger than 0. - The amount to pay must be larger than 0. + + + + A&mount: + A&mount: - - The amount exceeds your balance. - The amount exceeds your balance. + + Pay &To: + Pay &To: - - The total exceeds your balance when the %1 transaction fee is included. - The total exceeds your balance when the %1 transaction fee is included. + + &Label: + &Label: - - Transaction creation failed! + + Choose previously used address - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. + + This is a normal payment. - - A fee higher than %1 is considered an absurdly high fee. - - - - - Payment request expired. - - - - - Pay only the required fee of %1 - - - - - Estimated to begin confirmation within %n block(s). - - Estimated to begin confirmation within %n block. - Estimated to begin confirmation within %n blocks. - - - - - The recipient address is not valid. Please recheck. - - - - - Duplicate address found: addresses should only be used once each. - - - - - Warning: Invalid Bitcoin address - - - - - (no label) - (no label) - - - - Warning: Unknown change address - - - - - Copy dust - - - - - Are you sure you want to send? - - - - - added as transaction fee - - - - - SendCoinsEntry - - - - - A&mount: - A&mount: - - - - Pay &To: - Pay &To: - - - - Enter a label for this address to add it to your address book - Enter a label for this address to add it to your address book - - - - &Label: - &Label: - - - - Choose previously used address - - - - - This is a normal payment. - - - - - The Bitcoin address to send the payment to + + The Bitcoin address to send the payment to @@ -2842,950 +2009,230 @@ Alt+A - - Paste address from clipboard - Paste address from clipboard - - - - Alt+P - Alt+P - - - - - - Remove this entry - - - - - 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. - - - - - S&ubtract fee from amount - - - - - Message: - - - - - This is an unauthenticated payment request. - - - - - This is an authenticated payment request. - - - - - Enter a label for this address to add it to the list of used addresses - - - - - 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. - - - - - - Pay To: - - - - - - Memo: - - - - - SendConfirmationDialog - - - - Yes - - - - - ShutdownWindow - - - %1 is shutting down... - - - - - Do not shut down the computer until this window disappears. - - - - - SignVerifyMessageDialog - - - Signatures - Sign / Verify a Message - Signatures - Sign / Verify a Message - - - - &Sign Message - &Sign Message - - - - 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. - - - - - The Bitcoin address to sign the message with - - - - - - Choose previously used address - - - - - - Alt+A - Alt+A - - - - Paste address from clipboard - Paste address from clipboard - - - - Alt+P - Alt+P - - - - Enter the message you want to sign here - Enter the message you want to sign here - - - - Signature - Signature - - - - Copy the current signature to the system clipboard - Copy the current signature to the system clipboard - - - - Sign the message to prove you own this Bitcoin address - Sign the message to prove you own this Bitcoin address - - - - Sign &Message - Sign &Message - - - - Reset all sign message fields - Reset all sign message fields - - - - - Clear &All - Clear &All - - - - &Verify Message - &Verify Message - - - - 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! - - - - - The Bitcoin address the message was signed with - - - - - Verify the message to ensure it was signed with the specified Bitcoin address - Verify the message to ensure it was signed with the specified Bitcoin address - - - - Verify &Message - Verify &Message - - - - Reset all verify message fields - Reset all verify message fields - - - - Click "Sign Message" to generate signature - Click "Sign Message" to generate signature - - - - - The entered address is invalid. - The entered address is invalid. - - - - - - - Please check the address and try again. - Please check the address and try again. - - - - - The entered address does not refer to a key. - The entered address does not refer to a key. - - - - Wallet unlock was cancelled. - Wallet unlock was cancelled. - - - - Private key for the entered address is not available. - Private key for the entered address is not available. - - - - Message signing failed. - Message signing failed. - - - - Message signed. - Message signed. - - - - The signature could not be decoded. - The signature could not be decoded. - - - - - Please check the signature and try again. - Please check the signature and try again. - - - - The signature did not match the message digest. - The signature did not match the message digest. - - - - Message verification failed. - Message verification failed. - - - - Message verified. - Message verified. - - - - SplashScreen - - - [testnet] - [testnet] - - - - TrafficGraphWidget - - - KB/s - - - - - TransactionDesc - - - Open until %1 - Open until %1 - - - - %1/offline - %1/offline - - - - 0/unconfirmed, %1 - - - - - in memory pool - - - - - not in memory pool - - - - - abandoned - - - - - %1/unconfirmed - %1/unconfirmed - - - - %1 confirmations - %1 confirmations - - - - Status - Status - - - - , broadcast through %n node(s) - - , broadcast through %n node - , broadcast through %n nodes - - - - - Date - Date - - - - Source - Source - - - - Generated - Generated - - - - - - From - From - - - - - - To - To - - - - own address - own address - - - - - watch-only - - - - - label - label - - - - - - - - Credit - Credit - - - - matures in %n more block(s) - - matures in %n more block - matures in %n more blocks - - - - - not accepted - not accepted - - - - - - Debit - Debit - - - - Total debit - - - - - Total credit - - - - - Transaction fee - Transaction fee - - - - Net amount - Net amount - - - - - Message - Message - - - - Comment - Comment - - - - Transaction ID - Transaction ID - - - - Output index - - - - - Merchant - - - - - 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. - - - - - Debug information - Debug information - - - - Transaction - Transaction - - - - Inputs - Inputs - - - - Amount - Amount - - - - - true - true - - - - - false - false - - - - , has not been successfully broadcast yet - , has not been successfully broadcast yet - - - - Open for %n more block(s) - - Open for %n more block - Open for %n more blocks - - - - - conflicted with a transaction with %1 confirmations - - - - - unknown - unknown - - - - TransactionDescDialog - - - This pane shows a detailed description of the transaction - This pane shows a detailed description of the transaction - - - - Details for %1 - - - - - TransactionTableModel - - - Date - Date - - - - Type - Type - - - - Immature (%1 confirmations, will be available after %2) - - - - - Open for %n more block(s) - - Open for %n more block - Open for %n more blocks - - - - - Open until %1 - Open until %1 - - - - Confirmed (%1 confirmations) - Confirmed (%1 confirmations) - - - - This block was not received by any other nodes and will probably not be accepted! - This block was not received by any other nodes and will probably not be accepted! - - - - Generated but not accepted - Generated but not accepted - - - - Offline - - - - - Label - Label - - - - Unconfirmed - - - - - Abandoned - - - - - Confirming (%1 of %2 recommended confirmations) - - - - - Conflicted - - - - - Received with - Received with - - - - Received from - Received from - - - - Sent to - Sent to - - - - Payment to yourself - Payment to yourself - - - - Mined - Mined - - - - watch-only - - - - - (n/a) - (n/a) - - - - (no label) - (no label) - - - - Transaction status. Hover over this field to show number of confirmations. - Transaction status. Hover over this field to show number of confirmations. - - - - Date and time that the transaction was received. - Date and time that the transaction was received. - - - - Type of transaction. - Type of transaction. - - - - Whether or not a watch-only address is involved in this transaction. - - - - - User-defined intent/purpose of the transaction. - - - - - Amount removed from or added to balance. - Amount removed from or added to balance. - - - - TransactionView - - - - All - All - - - - Today - Today - - - - This week - This week - - - - This month - This month + + Paste address from clipboard + Paste address from clipboard - - Last month - Last month + + Alt+P + Alt+P - - This year - This year + + + + Remove this entry + - - Range... - Range... + + 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. + - - Received with - Received with + + S&ubtract fee from amount + - - Sent to - Sent to + + Message: + - - To yourself - To yourself + + This is an unauthenticated payment request. + - - Mined - Mined + + This is an authenticated payment request. + - - Other - Other + + Enter a label for this address to add it to the list of used addresses + - - Enter address or label to search - Enter address or label to search + + 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. + - - Min amount - Min amount + + + Pay To: + - - Abandon transaction + + + Memo: + + + ShutdownWindow - - Copy address - Copy address + + %1 is shutting down... + - Copy label - Copy label + Do not shut down the computer until this window disappears. + + + + SignVerifyMessageDialog - - Copy amount - Copy amount + + Signatures - Sign / Verify a Message + Signatures - Sign / Verify a Message - - Copy transaction ID - Copy transaction ID + + &Sign Message + &Sign Message - - Copy raw transaction + + 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. - - Copy full transaction details + + The Bitcoin address to sign the message with - - Edit label - Edit label + + + Choose previously used address + - - Show transaction details - Show transaction details + + + Alt+A + Alt+A - - Export Transaction History - + + Paste address from clipboard + Paste address from clipboard - - Watch-only - + + Alt+P + Alt+P - - Exporting Failed - + + Enter the message you want to sign here + Enter the message you want to sign here - - There was an error trying to save the transaction history to %1. - + + Signature + Signature - - Exporting Successful - + + Copy the current signature to the system clipboard + Copy the current signature to the system clipboard - - The transaction history was successfully saved to %1. - + + Sign the message to prove you own this Bitcoin address + Sign the message to prove you own this Bitcoin address - - Comma separated file (*.csv) - Comma separated file (*.csv) + + Sign &Message + Sign &Message - - Confirmed - Confirmed + + Reset all sign message fields + Reset all sign message fields - Date - Date + + Clear &All + Clear &All - - Type - Type + + &Verify Message + &Verify Message - - Label - Label + + 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! + - - Address - Address + + The Bitcoin address the message was signed with + - - ID - ID + + Verify the message to ensure it was signed with the specified Bitcoin address + Verify the message to ensure it was signed with the specified Bitcoin address - - Range: - Range: + + Verify &Message + Verify &Message - - to - to + + Reset all verify message fields + Reset all verify message fields - UnitDisplayStatusBarControl + SplashScreen - - Unit to show amounts in. Click to select another unit. - + + [testnet] + [testnet] - WalletFrame + TrafficGraphWidget - - No wallet has been loaded. + + KB/s - WalletModel + TransactionDescDialog - - Send Coins - Send Coins + + This pane shows a detailed description of the transaction + This pane shows a detailed description of the transaction - WalletView - - - &Export - &Export - - - - Export the data in the current tab to a file - Export the data in the current tab to a file - - - - Backup Wallet - Backup Wallet - - - - Wallet Data (*.dat) - Wallet Data (*.dat) - - - - Backup Failed - Backup Failed - - - - There was an error trying to save the wallet data to %1. - - + UnitDisplayStatusBarControl - - The wallet data was successfully saved to %1. + + Unit to show amounts in. Click to select another unit. - - - Backup Successful - Backup Successful - bitcoin-core - + Options: Options: @@ -3795,27 +2242,27 @@ Specify data directory - + Connect to a node to retrieve peer addresses, and disconnect Connect to a node to retrieve peer addresses, and disconnect - + Specify your own public address Specify your own public address - + Accept command line and JSON-RPC commands Accept command line and JSON-RPC commands - + If <category> is not supplied or if <category> = 1, output all debugging information. - + Prune configured below the minimum of %d MiB. Please use a higher number. @@ -3835,7 +2282,7 @@ - + Error: A fatal internal error occurred, see debug.log for details @@ -3855,17 +2302,17 @@ Run in the background as a daemon and accept commands - + Unable to start HTTP server. See debug log for details. - + Accept connections from outside (default: 1 if no -proxy or -connect) Accept connections from outside (default: 1 if no -proxy or -connect) - + Bitcoin Core Bitcoin Core @@ -3911,6 +2358,11 @@ + Error loading %s: You can't enable HD on a already existing non-HD wallet + + + + Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect. @@ -3939,6 +2391,11 @@ Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly. + + + Please contribute if you find %s useful. Visit %s for further information about the software. + + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) @@ -3960,7 +2417,12 @@ - + + Use hierarchical deterministic key generation (HD) after bip32. Only has effect during wallet creation/first start + + + + WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) @@ -4114,6 +2576,11 @@ Error loading %s: Wallet requires newer version of %s + + + Error loading %s: You can't disable HD on a already existing HD wallet + + Error loading block database @@ -4240,7 +2707,12 @@ Specify wallet file (within data directory) - + + The source code is available from %s. + + + + Unable to bind to %s on this computer. %s is probably already running. @@ -4300,7 +2772,7 @@ - + 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 @@ -4325,7 +2797,7 @@ - + Error: Listening for incoming connections failed (listen returned error %s) @@ -4355,7 +2827,7 @@ - + Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect) @@ -4380,7 +2852,7 @@ - + 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 @@ -4410,7 +2882,7 @@ - + Error reading from database, shutting down. @@ -4490,7 +2962,7 @@ Signing transaction failed - + The transaction amount is too small to pay the fee @@ -4570,27 +3042,27 @@ - + Password for JSON-RPC connections Password for JSON-RPC connections - + Execute command when the best block changes (%s in cmd is replaced by block hash) Execute command when the best block changes (%s in cmd is replaced by block hash) - + Allow DNS lookups for -addnode, -seednode and -connect Allow DNS lookups for -addnode, -seednode and -connect - + Loading addresses... Loading addresses... - + (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) @@ -4610,7 +3082,7 @@ - + Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) @@ -4635,7 +3107,7 @@ - + Support filtering of blocks and transaction with bloom filters (default: %u) @@ -4660,7 +3132,7 @@ - + Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s) @@ -4690,7 +3162,7 @@ - + How many blocks to check at startup (default: %u, 0 = all) @@ -4785,7 +3257,7 @@ - + Threshold for disconnecting misbehaving peers (default: %u) @@ -4795,7 +3267,7 @@ Unknown network specified in -onlynet: '%s' - + Insufficient funds Insufficient funds @@ -4805,17 +3277,17 @@ Loading block index... - + Add a node to connect to and attempt to keep the connection open Add a node to connect to and attempt to keep the connection open - + Loading wallet... Loading wallet... - + Cannot downgrade wallet Cannot downgrade wallet @@ -4825,17 +3297,17 @@ Cannot write default address - + Rescanning... Rescanning... - + Done loading Done loading - + Error Error diff --git a/src/qt/locale/bitcoin_en_GB.ts b/src/qt/locale/bitcoin_en_GB.ts index bf912d295e96f..b9c0c82814a54 100644 --- a/src/qt/locale/bitcoin_en_GB.ts +++ b/src/qt/locale/bitcoin_en_GB.ts @@ -908,7 +908,7 @@ Reset all settings changes made over the GUI - Reset all settings changes made over the GUI + Reset all setting changes made via the GUI @@ -1473,10 +1473,6 @@ General General - - Using OpenSSL version - Using OpenSSL version - Using BerkeleyDB version Using BerkeleyDB version @@ -2979,6 +2975,18 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Accept connections from outside (default: 1 if no -proxy or -connect) + + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. + + + A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s) + A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s) + + + Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d) + Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d) + Bind to given address and always listen on it. Use [host]:port notation for IPv6 Bind to given address and always listen on it. Use [host]:port notation for IPv6 @@ -2995,6 +3003,10 @@ Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) + Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) @@ -3011,6 +3023,10 @@ Unable to bind to %s on this computer. Bitcoin Core is probably already running. Unable to bind to %s on this computer. Bitcoin Core is probably already running. + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + Use UPnP to map the listening port (default: 1 when listening and no -proxy) Use UPnP to map the listening port (default: 1 when listening and no -proxy) @@ -3027,6 +3043,10 @@ Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. + + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. @@ -3047,6 +3067,10 @@ <category> can be: <category> can be: + + Append comment to the user agent string + Append comment to the user agent string + Block creation options: Block creation options: @@ -3091,6 +3115,10 @@ Enable publish raw transaction in <address> Enable publish raw transaction in <address> + + Enable transaction replacement in the memory pool (default: %u) + Enable transaction replacement in the memory pool (default: %u) + Error initializing block database Error initialising block database @@ -3127,10 +3155,22 @@ Invalid -onion address: '%s' Invalid -onion address: '%s' + + Invalid amount for -fallbackfee=<amount>: '%s' + Invalid amount for -fallbackfee=<amount>: '%s' + Keep the transaction memory pool below <n> megabytes (default: %u) Keep the transaction memory pool below <n> megabytes (default: %u) + + Location of the auth cookie (default: data dir) + Location of the auth cookie (default: data dir) + + + Minimum bytes per sigop in transactions we relay and mine (default: %u) + Minimum bytes per sigop in transactions we relay and mine (default: %u) + Not enough file descriptors available. Not enough file descriptors available. @@ -3139,6 +3179,10 @@ Only connect to nodes in network <net> (ipv4, ipv6 or onion) Only connect to nodes in network <net> (ipv4, ipv6 or onion) + + Print version and exit + Print version and exit + Prune cannot be configured with a negative value. Prune cannot be configured with a negative value. @@ -3195,10 +3239,6 @@ Wallet options: Wallet options: - - Warning: This version is obsolete; upgrade required! - Warning: This version is obsolete; upgrade required! - You need to rebuild the database using -reindex to change -txindex You need to rebuild the database using -reindex to change -txindex @@ -3295,10 +3335,6 @@ Activating best chain... Activating best chain... - - Always relay transactions received from whitelisted peers (default: %d) - Always relay transactions received from whitelisted peers (default: %d) - Attempt to recover private keys from a corrupt wallet.dat on startup Attempt to recover private keys from a corrupt wallet.dat on startup @@ -3463,6 +3499,10 @@ Warning Warning + + Warning: unknown new rules activated (versionbit %i) + Warning: unknown new rules activated (versionbit %i) + Whether to operate in a blocks only mode (default: %u) Whether to operate in a blocks only mode (default: %u) diff --git a/src/qt/locale/bitcoin_eo.ts b/src/qt/locale/bitcoin_eo.ts index ab8dd65f81673..2095db34bf32e 100644 --- a/src/qt/locale/bitcoin_eo.ts +++ b/src/qt/locale/bitcoin_eo.ts @@ -179,6 +179,10 @@ Wallet encrypted La monujo estas ĉifrita + + Enter the old passphrase and new passphrase to the wallet. + Tajpu la malnovan pasvorton kaj la novan pasvorton por la monujo. + Wallet encryption failed Ĉifrado de la monujo fiaskis @@ -409,6 +413,10 @@ No block source available... Neniu fonto de blokoj trovebla... + + %n hour(s) + %n horo%n horoj + %n day(s) %n tago%n tagoj @@ -479,6 +487,12 @@ Label: %1 Etikedo: %1 + + + + Address: %1 + + Adreso: %1 @@ -812,6 +826,10 @@ command-line options komandliniaj agordaĵoj + + UI Options: + Uzantinterfaco ebloj: + Intro @@ -847,6 +865,10 @@ Error Eraro + + %n GB of free space available + %n gigabajto de libera loko disponeble%n gigabajtoj de libera loko disponebla. + OpenURIDialog @@ -1098,6 +1120,10 @@ PeerTableModel + + User Agent + Uzanto Agento + QObject @@ -1167,10 +1193,6 @@ General Ĝenerala - - Using OpenSSL version - uzas OpenSSL-version - Startup time Horo de lanĉo @@ -1203,10 +1225,22 @@ Sent Sendita + + &Peers + &Samuloj + + + Banned peers + Malpermesita samuloj. + Version Versio + + User Agent + Uzanto Agento + Services Servoj diff --git a/src/qt/locale/bitcoin_es.ts b/src/qt/locale/bitcoin_es.ts index 936074210a53d..5322634c5db98 100644 --- a/src/qt/locale/bitcoin_es.ts +++ b/src/qt/locale/bitcoin_es.ts @@ -882,6 +882,10 @@ command-line options opciones de la consola de comandos + + UI Options: + Opciones de interfaz de usuario: + Choose data directory on startup (default: %u) Elegir directorio de datos al iniciar (predeterminado: %u) @@ -898,7 +902,11 @@ Set SSL root certificates for payment request (default: -system-) Establecer los certificados raíz SSL para solicitudes de pago (predeterminado: -system-) - + + Reset all settings changes made over the GUI + Resetear los cambios de configuracion hechos por el GUI + + Intro @@ -1095,6 +1103,14 @@ Port of the proxy (e.g. 9050) Puerto del servidor proxy (ej. 9050) + + Used for reaching peers via: + Usado para alcanzar compañeros via: + + + Shows, if the supplied default SOCKS5 proxy is used to reach peers via this network type. + Muestra si el proxy SOCKS5 predeterminado es utilizado para llegar a los pares a traves de este tipo de red. + IPv4 IPv4 @@ -1107,6 +1123,10 @@ Tor Tor + + Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services. + Conectar a la red Bitcoin mediante un proxy SOCKS5 por separado para los servicios ocultos de Tor. + Use separate SOCKS5 proxy to reach peers via Tor hidden services: Usar distintos proxys SOCKS5 para comunicarse vía Tor de forma anónima: @@ -1449,10 +1469,6 @@ General General - - Using OpenSSL version - Utilizando la versión de OpenSSL - Using BerkeleyDB version Utilizando la versión de BerkeleyDB @@ -1481,6 +1497,18 @@ Current number of blocks Número actual de bloques + + Memory Pool + Piscina de Memoria + + + Current number of transactions + Número actual de transacciones + + + Memory usage + Uso de memoria + Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. Abre el archivo de registro de depuración de Bitcoin desde el directorio de datos actual. Esto puede tardar unos segundos para ficheros de registro de gran tamaño. @@ -1505,6 +1533,10 @@ Select a peer to view detailed information. Seleccionar un par para ver su información detallada. + + Whitelisted + En la lista blanca + Direction Dirección @@ -1553,6 +1585,14 @@ Ping Time Ping + + The duration of a currently outstanding ping. + La duración de un ping actualmente en proceso. + + + Ping Wait + Espera de Ping + Time Offset Desplazamiento de tiempo @@ -1605,6 +1645,10 @@ &Disconnect Node Nodo &Desconectado + + Ban Node for + Prohibir Nodo para + 1 &hour 1 &hora @@ -1621,6 +1665,10 @@ 1 &year 1 &año + + &Unban Node + &Desbanear Nodo + Welcome to the Bitcoin Core RPC console. Bienvenido a la consola RPC de Bitcoin Core. @@ -2720,6 +2768,10 @@ Copy transaction ID Copiar identificador de transacción + + Copy raw transaction + Copiar traducción en crudo + Edit label Editar etiqueta @@ -2869,6 +2921,34 @@ Aceptar comandos consola y JSON-RPC + + If <category> is not supplied or if <category> = 1, output all debugging information. + Si <category> no es proporcionado o si <category> =1, muestra toda la información de depuración. + + + Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s) + Máximas comisiones totales (en %s) para utilizar en una sola transacción de la cartera; establecer esto demasiado bajo puede abortar grandes transacciones (predeterminado: %s) + + + Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. + Por favor, mira si la fecha y la hora en tu computador son correctas! Si tu hara es errónea Bitcoin Core no funcionará correctamente. + + + Prune configured below the minimum of %d MiB. Please use a higher number. + La Poda se ha configurado por debajo del minimo de %d MiB. Por favor utiliza un valor mas alto. + + + Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node) + Poda: la ultima sincronizacion de la cartera sobrepasa los datos podados. Necesitas reindexar con -reindex (o descargar la cadena de bloques de nuevo en el caso de un nodo podado) + + + Reduce storage requirements by pruning (deleting) old blocks. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, >%u = target size in MiB to use for block files) + Reduce los requisitos de almacenaje podando (eliminando) los bloques viejos. Este modo es incompatible con -txindex y -rescan. Advertencia: Revertir este ajuste requiere volver a descargar la cadena de bloques al completo. (predeterminado: 0 = deshabilitar la poda de bloques, >%u = objetivo de tamaño en MiB para usar para los archivos de bloques) + + + Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again. + Nos es posible re-escanear en modo podado.Necesitas utilizar -reindex el cual descargara la cadena de bloques al completo de nuevo. + Error: A fatal internal error occurred, see debug.log for details Un error interno fatal ocurrió, ver debug.log para detalles @@ -2894,6 +2974,18 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Aceptar conexiones desde el exterior (predeterminado: 1 si no -proxy o -connect) + + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. + -fallbackfee tiene un ajuste muy alto! Esta es la comisión de transacción que pagarás cuando las estimaciones de comisiones no estén disponibles. + + + A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s) + Una comision (en %s/kB) que sera usada cuando las estimacion de comision no disponga de suficientes datos (predeterminado: %s) + + + Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d) + Aceptar transacciones retransmitidas recibidas desde nodos en la lista blanca incluso cuando no estés retransmitiendo transacciones (predeterminado: %d) + Bind to given address and always listen on it. Use [host]:port notation for IPv6 Vincular a la dirección dada y escuchar siempre en ella. Utilice la notación [host]:port para IPv6 @@ -2910,10 +3002,18 @@ Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) Ejecutar comando cuando una transacción del monedero cambia (%s en cmd se remplazará por TxID) + + Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) + Fuerza la retransmisión de transacciones desde nodos en la lista blanca incluso si violan la política de retransmisiones local (predeterminado: %d) + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) Establecer el número de hilos (threads) de verificación de scripts (entre %u y %d, 0 = automático, <0 = dejar libres ese número de núcleos; predeterminado: %d) + + 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 + La base de datos de bloques contiene un bloque que parece ser del futuro. Esto puede ser porque la fecha y hora de tu ordenador están mal ajustados. Reconstruye la base de datos de bloques solo si estas seguro de que la fecha y hora de tu ordenador estan ajustados correctamente. + This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Esta es una versión de pre-prueba - utilícela bajo su propio riesgo. No la utilice para usos comerciales o de minería. @@ -2922,6 +3022,14 @@ Unable to bind to %s on this computer. Bitcoin Core is probably already running. No se ha podido acceder a %s en esta máquina. Probablemente ya se está ejecutando Bitcoin Core. + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + El argumento no soportado -whitelistalwaysrelay ha sido ignorado, utiliza -whitelistrelay y/o -whitelistforcerelay. + + + Use UPnP to map the listening port (default: 1 when listening and no -proxy) + Utiliza UPnP para asignar el puerto de escucha (predeterminado: 1 cuando esta escuchando sin -proxy) + WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) ADVERTENCIA: anormalmente alto número de bloques generado, %d bloques recibidos en las últimas horas %d (%d espera) @@ -2934,6 +3042,10 @@ Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Atención: ¡Parece que la red no está totalmente de acuerdo! Algunos mineros están presentando inconvenientes. + + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + Advertencia: Se están minando versiones de bloques desconocidas! Es posible que normas desconocidas estén activas + Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Atención: ¡Parece que no estamos completamente de acuerdo con nuestros pares! Podría necesitar una actualización, u otros nodos podrían necesitarla. @@ -2954,6 +3066,10 @@ <category> can be: <category> puede ser: + + Append comment to the user agent string + Adjunta un comentario a la linea de agente de usuario + Block creation options: Opciones de creación de bloques: @@ -2982,6 +3098,26 @@ Do you want to rebuild the block database now? ¿Quieres reconstruir la base de datos de bloques ahora? + + Enable publish hash block in <address> + Activar publicar bloque .hash en <.Address> + + + Enable publish hash transaction in <address> + Activar publicar transacción .hash en <.Address> + + + Enable publish raw block in <address> + Habilita la publicacion de bloques en bruto en <direccion> + + + Enable publish raw transaction in <address> + Habilitar publicar transacción en rama en <dirección> + + + Enable transaction replacement in the memory pool (default: %u) + Habilita el reemplazamiento de transacciones en la piscina de memoria (predeterminado: %u) + Error initializing block database Error al inicializar la base de datos de bloques @@ -3018,6 +3154,22 @@ Invalid -onion address: '%s' Dirección -onion inválida: '%s' + + Invalid amount for -fallbackfee=<amount>: '%s' + Cantidad inválida para -fallbackfee=<amount>: '%s' + + + Keep the transaction memory pool below <n> megabytes (default: %u) + Mantener la memoria de transacciones por debajo de <n> megabytes (predeterminado: %u) + + + Location of the auth cookie (default: data dir) + Ubicación de la cookie de autenticación (default: data dir) + + + Minimum bytes per sigop in transactions we relay and mine (default: %u) + Mínimo de bytes por sigop en transacciones que retransmitimos y minamos (predeterminado: %u) + Not enough file descriptors available. No hay suficientes descriptores de archivo disponibles. @@ -3026,6 +3178,10 @@ Only connect to nodes in network <net> (ipv4, ipv6 or onion) Sólo conectar a nodos en redes <net> (ipv4, ipv6 o onion) + + Print version and exit + Imprimir versión y salir + Prune cannot be configured with a negative value. Pode no se puede configurar con un valor negativo. @@ -3046,10 +3202,26 @@ Specify wallet file (within data directory) Especificar archivo de monedero (dentro del directorio de datos) + + Unsupported argument -benchmark ignored, use -debug=bench. + El argumento -benchmark no es soportado y ha sido ignorado, utiliza -debug=bench + + + Unsupported argument -debugnet ignored, use -debug=net. + Parámetros no compatibles -debugnet ignorados , use -debug = red. + + + Unsupported argument -tor found, use -onion. + Parámetros no compatibles -tor encontrados, use -onion . + Use UPnP to map the listening port (default: %u) Usar UPnP para asignar el puerto de escucha (predeterminado:: %u) + + User Agent comment (%s) contains unsafe characters. + El comentario del Agente de Usuario (%s) contiene caracteres inseguros. + Verifying blocks... Verificando bloques... @@ -3066,10 +3238,6 @@ Wallet options: Opciones de monedero: - - Warning: This version is obsolete; upgrade required! - Peligro: Esta versión es obsoleta; actualización requerida! - You need to rebuild the database using -reindex to change -txindex Usted necesita reconstruir la base de datos utilizando -reindex para cambiar -txindex @@ -3106,6 +3274,10 @@ Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message) Ejecutar un comando cuando se reciba una alerta importante o cuando veamos un fork demasiado largo (%s en cmd se reemplazará por el mensaje) + + Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s) + Las comisiones (en %s/kB) mas pequeñas que esto se consideran como cero comisión para la retransmisión, minería y creación de la transacción (predeterminado: %s) + If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u) Si el pago de comisión no está establecido, incluir la cuota suficiente para que las transacciones comiencen la confirmación en una media de n bloques ( por defecto :%u) @@ -3246,6 +3418,10 @@ Receive and display P2P network alerts (default: %u) Recibir y mostrar alertas de red P2P (default: %u) + + Reducing -maxconnections from %d to %d, because of system limitations. + Reduciendo -maxconnections de %d a %d, debido a limitaciones del sistema. + Rescan the block chain for missing wallet transactions on startup Rescanea la cadena de bloques para transacciones perdidas de la cartera @@ -3278,6 +3454,14 @@ This is experimental software. Este software es experimental. + + Tor control port password (default: empty) + Contraseña del puerto de control de Tor (predeterminado: vacio) + + + Tor control port to use if onion listening enabled (default: %s) + Puerto de control de Tor a utilizar si la escucha de onion esta activada (predeterminado: %s) + Transaction amount too small Cantidad de la transacción demasiado pequeña @@ -3315,10 +3499,22 @@ Warning Aviso + + Warning: unknown new rules activated (versionbit %i) + Advertencia: nuevas reglas desconocidas activadas (versionbit %i) + + + Whether to operate in a blocks only mode (default: %u) + Si se debe o no operar en un modo de solo bloques (predeterminado: %u) + Zapping all transactions from wallet... Eliminando todas las transacciones del monedero... + + ZeroMQ notification options: + Opciones de notificación ZeroQM: + wallet.dat corrupt, salvage failed wallet.dat corrupto. Ha fallado la recuperación. @@ -3353,6 +3549,26 @@ (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) + + -maxtxfee is set very high! Fees this large could be paid on a single transaction. + -maxtxfee tiene un ajuste muy elevado! Las comisiones así de grandes podrían ser pagadas en una única transaccion. + + + -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + -paytxfee tiene un ajuste muy elevado! Esta es la comisión de transacción que pagaras si envías una transaccion. + + + Do not keep transactions in the mempool longer than <n> hours (default: %u) + No mantener transacciones en la memoria mas de <n> horas (predeterminado: %u) + + + Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Error al leer wallet.dat! Todas las llaves se leyeron correctamente, pero los datos de transacciones o la libreta de direcciones pueden faltar o ser incorrectos. + + + Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) + Las comisiones (en %s/kB) menores que esto son consideradas de cero comision para la creacion de transacciones (predeterminado: %s) + How thorough the block verification of -checkblocks is (0-4, default: %u) Nivel de rigor en la verificación de bloques de -checkblocks (0-4; predeterminado: %u) @@ -3369,10 +3585,18 @@ Output debugging information (default: %u, supplying <category> is optional) Mostrar depuración (por defecto: %u, proporcionar <category> es opcional) + + Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported. + Error: Unsupported argumento -socks encontrados. SOCKS versión ajuste ya no es posible, sólo SOCKS5 proxies son compatibles. + Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s) Usar distintos proxys SOCKS5 para comunicarse vía Tor de forma anónima (Por defecto: %s) + + Username and hashed password for JSON-RPC connections. The field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A canonical python script is included in share/rpcuser. This option can be specified multiple times + Nombre de usuario y hash de la contraseña para las conexiones JSON-RPC. El campo <userpw> tiene el formato: <USERNAME>:<SALT>$<HASH>. Se incluye un script python convencional en share/rpcuser. Esta opción puede ser especificada multiples veces + (default: %s) (predeterminado: %s) diff --git a/src/qt/locale/bitcoin_es_419.ts b/src/qt/locale/bitcoin_es_419.ts new file mode 100644 index 0000000000000..b76915662c114 --- /dev/null +++ b/src/qt/locale/bitcoin_es_419.ts @@ -0,0 +1,173 @@ + + + AddressBookPage + + Right-click to edit address or label + Haga clic para editar la dirección o etiqueta + + + Create a new address + Crear una nueva dirección + + + &New + &New + + + Copy the currently selected address to the system clipboard + Copia la dirección seleccionada al portapapeles del sistema + + + Choose the address to send coins to + Seleccione la Direccion a la que enviara dinero + + + Choose the address to receive coins with + Seleccione la direccion de la que recibira dinero + + + Export Address List + Exportar Lista de Direcciones + + + + AddressTableModel + + Address + Direccion + + + + AskPassphraseDialog + + Decrypt wallet + Desencriptar Monedero + + + Confirm wallet encryption + Confirmar Encriptacion de Monedero + + + Warning: The Caps Lock key is on! + Advertencia: La Tecla Caps Lock esta habilitada! + + + Wallet encrypted + Monedero ha sido encriptado + + + Wallet encryption failed + La encriptacion del monedero ha fallado + + + + BanTableModel + + + BitcoinGUI + + + ClientModel + + + CoinControlDialog + + + EditAddressDialog + + + FreespaceChecker + + + HelpMessageDialog + + + Intro + + + OpenURIDialog + + + OptionsDialog + + + OverviewPage + + + PaymentServer + + + PeerTableModel + + + QObject + + + QRImageWidget + + + RPCConsole + + + ReceiveCoinsDialog + + + ReceiveRequestDialog + + Address + Direccion + + + + RecentRequestsTableModel + + + SendCoinsDialog + + + SendCoinsEntry + + + ShutdownWindow + + + SignVerifyMessageDialog + + + SplashScreen + + + TrafficGraphWidget + + + TransactionDesc + + + TransactionDescDialog + + + TransactionTableModel + + + TransactionView + + Address + Direccion + + + + UnitDisplayStatusBarControl + + + WalletFrame + + + WalletModel + + + WalletView + + + bitcoin-core + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_es_AR.ts b/src/qt/locale/bitcoin_es_AR.ts new file mode 100644 index 0000000000000..fb9ac895be830 --- /dev/null +++ b/src/qt/locale/bitcoin_es_AR.ts @@ -0,0 +1,373 @@ + + + AddressBookPage + + Right-click to edit address or label + Hacé click para editar la dirección o etiqueta + + + Create a new address + Crear una nueva dirección + + + &New + &Nuevo + + + Copy the currently selected address to the system clipboard + Copiá la dirección que seleccionaste al portapapeles + + + &Copy + &Copiar + + + C&lose + C&lose + + + &Copy Address + &Copiar Dirección + + + Delete the currently selected address from the list + Borrar de la lista la dirección seleccionada + + + Export the data in the current tab to a file + Exportar los datos de la pestaña actual a un archivo + + + &Export + &Exportar + + + &Delete + &Borrar + + + Choose the address to send coins to + Elegir la dirección a donde enviar las monedas (coins) + + + Choose the address to receive coins with + Elegí la dirección donde recibir las monedas + + + C&hoose + E&legir + + + Sending addresses + Direcciones de envío + + + Receiving addresses + Direcciones de recepción + + + These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. + Estas son tus direcciones Bitcoin para enviar pagos. Siempre chequeá el monto y la dirección de recepción antes de mandar monedas. + + + These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. + Estas son tus direcciones para recibir pagos. Te recomendamos que uses una dirección de recibir para cada transacción. + + + Copy &Label + Copiar &Etiqueta + + + &Edit + &Editar + + + Export Address List + Exportar lista de direcciones + + + Comma separated file (*.csv) + Archivo separado por coma (*.csv) + + + Exporting Failed + Falló la exportación + + + There was an error trying to save the address list to %1. Please try again. + Hubo un error al tratar de guardar la lista de direcciones a %1. Por favor tratá de nuevo. + + + + AddressTableModel + + Label + Etiqueta + + + Address + Dirección + + + (no label) + (sin etiqueta) + + + + AskPassphraseDialog + + Passphrase Dialog + Diálogo de Frase de Contraseña + + + Enter passphrase + Ingresar la Frase de Contraseña + + + New passphrase + Nueva Frase de Contraseña + + + Repeat new passphrase + Repetí la nueva Frase de Contraseña + + + Encrypt wallet + Encriptar la billetera + + + This operation needs your wallet passphrase to unlock the wallet. + Esta operación necesita tu frase de contraseña para desbloquear tu billetera. + + + Unlock wallet + Desbloquear la billetera + + + This operation needs your wallet passphrase to decrypt the wallet. + Esta operación necesita tu Frase de Contraseña de billetera para desencriptar la billetera. + + + Decrypt wallet + Desencriptar la billetera + + + Change passphrase + Cambiar la Frase de Contraseña + + + Confirm wallet encryption + Confirmá la encriptación de la billetera + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! + Atención: Si encriptás tu billetera y perdés tu frase de contraseña, vas a <b>PERDER TODOS TUS BITCOINS</b>! + + + Are you sure you wish to encrypt your wallet? + ¿Estás seguro que querés encriptar tu billetera? + + + Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. + Bitcoin Core ahora se va a cerrar para terminar el proceso de encriptación. Acordate que encriptar tu billetera no te protege completamente de que algún malware que pueda infectar tu computadora te robe tus bitcoins. + + + 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. + IMPORTANTE: Todos los backups que hayas hecho de tu billetera tendrían que ser reemplazados por el archivo encriptado de billetera que generaste. Por razones de seguridad, los backups anteriores del archivo de billetera no encriptado se inutilizan en el momento en que empezás a usar la nueva billetera encriptada + + + Warning: The Caps Lock key is on! + Atención: Tenés puestas las mayúsculas! + + + Wallet encrypted + Billetera encriptada + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. + Ingresá una nueva frase de contraseña para la billetera.<br/>Por favor, fijate de usar una frase de contraseña de <b>diez o más caracteres aleatorios</b>, o de <b>ocho o más palabras</b>. + + + Enter the old passphrase and new passphrase to the wallet. + Ingresá la frase de contraseña vieja y la nueva para la billetera. + + + Wallet encryption failed + Falló la encriptación de la billetera + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Falló la encriptación de la billetera por un error interno. Tu billetera no está encriptada. + + + The supplied passphrases do not match. + Las frases de contraseña no son iguales. + + + Wallet unlock failed + Falló el desbloqueo de la billetera + + + The passphrase entered for the wallet decryption was incorrect. + La frase de contraseña que ingresaste para desencriptar la billetera es incorrecta. + + + Wallet decryption failed + Falló la desencriptación de la billetera + + + + BanTableModel + + + BitcoinGUI + + + ClientModel + + + CoinControlDialog + + (no label) + (sin etiqueta) + + + + EditAddressDialog + + + FreespaceChecker + + + HelpMessageDialog + + + Intro + + + OpenURIDialog + + + OptionsDialog + + + OverviewPage + + + PaymentServer + + + PeerTableModel + + + QObject + + + QRImageWidget + + + RPCConsole + + + ReceiveCoinsDialog + + + ReceiveRequestDialog + + Address + Dirección + + + Label + Etiqueta + + + + RecentRequestsTableModel + + Label + Etiqueta + + + (no label) + (sin etiqueta) + + + + SendCoinsDialog + + (no label) + (sin etiqueta) + + + + SendCoinsEntry + + + ShutdownWindow + + + SignVerifyMessageDialog + + + SplashScreen + + + TrafficGraphWidget + + + TransactionDesc + + + TransactionDescDialog + + + TransactionTableModel + + Label + Etiqueta + + + + TransactionView + + Exporting Failed + Falló la exportación + + + Comma separated file (*.csv) + Archivo separado por coma (*.csv) + + + Label + Etiqueta + + + Address + Dirección + + + + UnitDisplayStatusBarControl + + + WalletFrame + + + WalletModel + + + WalletView + + &Export + &Exportar + + + Export the data in the current tab to a file + Exportar los datos de la pestaña actual a un archivo + + + + bitcoin-core + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_es_CL.ts b/src/qt/locale/bitcoin_es_CL.ts index e6d48a29f07f9..742dee29d0374 100644 --- a/src/qt/locale/bitcoin_es_CL.ts +++ b/src/qt/locale/bitcoin_es_CL.ts @@ -7,7 +7,7 @@ Create a new address - Crea una nueva direCrea una nueva direccióncción + Crea una nueva dirección &New @@ -45,6 +45,22 @@ &Delete &Borrar + + Choose the address to send coins to + Selecciona la direccion para enviar coins + + + Choose the address to receive coins with + Selecciona la dirección para recibir coins + + + Sending addresses + Dirección de envio + + + Receiving addresses + Dirección para recibir + Copy &Label Copia &etiqueta @@ -53,10 +69,18 @@ &Edit &Editar + + Export Address List + Exportar lista de direcciones + Comma separated file (*.csv) Archivos separados por coma (*.csv) + + Exporting Failed + Exportado fallo + AddressTableModel @@ -225,6 +249,14 @@ &Change Passphrase... &Cambiar la contraseña... + + &Sending addresses... + Mandando direcciones + + + &Receiving addresses... + Recibiendo direcciones + Open &URI... Abrir y url... @@ -257,6 +289,10 @@ Open debugging and diagnostic console Abre consola de depuración y diagnóstico + + &Verify message... + Verificar mensaje.... + Bitcoin Bitcoin @@ -273,6 +309,10 @@ &Receive y recibir + + Show information about Bitcoin Core + Mostrar informacion sobre Bitcoin Core + &Show / Hide &Mostrar/Ocultar @@ -301,6 +341,18 @@ Bitcoin Core bitcoin core + + Request payments (generates QR codes and bitcoin: URIs) + Pide pagos (genera codigos QR and bitcoin: URls) + + + &About Bitcoin Core + &Sobre Bitcoin Core + + + Modify configuration options for Bitcoin Core + Modifica las opciones para BitCoin Core + %1 and %2 %1 y %2 @@ -359,6 +411,11 @@ Priority: prioridad: + + Fee: + comisión: + + Amount Cantidad @@ -367,6 +424,10 @@ Date Fecha + + Confirmations + Confirmaciones + Confirmed Confirmado @@ -387,10 +448,26 @@ Copy amount Copiar Cantidad + + Copy quantity + copiar cantidad + + + Copy fee + copiar comision + + + Copy bytes + copiar bytes + medium medio + + low + bajo + yes si @@ -468,6 +545,10 @@ version versión + + Command-line options + opciones de linea de comando + Usage: Uso: @@ -793,10 +874,23 @@ Priority: prioridad: + + Fee: + comisión: + + Transaction Fee: Comisión transacción: + + normal + normal + + + fast + rapido + Send to multiple recipients at once Enviar a múltiples destinatarios @@ -825,10 +919,22 @@ Confirm send coins Confirmar el envio de monedas + + Copy quantity + copiar cantidad + Copy amount Copiar Cantidad + + Copy fee + copiar comision + + + Copy bytes + copiar bytes + The amount to pay must be larger than 0. La cantidad por pagar tiene que ser mayor 0. @@ -1113,10 +1219,18 @@ Generated but not accepted Generado pero no acceptado + + Offline + fuera de linea + Label Etiqueta + + Unconfirmed + no confirmado + Received with Recibido con @@ -1236,6 +1350,10 @@ Show transaction details Mostrar detalles de la transacción + + Exporting Failed + Exportado fallo + Comma separated file (*.csv) Archivos separados por coma (*.csv) diff --git a/src/qt/locale/bitcoin_es_CO.ts b/src/qt/locale/bitcoin_es_CO.ts new file mode 100644 index 0000000000000..ea0664636d2d6 --- /dev/null +++ b/src/qt/locale/bitcoin_es_CO.ts @@ -0,0 +1,542 @@ + + + AddressBookPage + + Right-click to edit address or label + Click derecho para editar la dirección o etiqueta + + + Create a new address + Crear una nueva dirección + + + &New + &Nuevo + + + Copy the currently selected address to the system clipboard + Copiar la dirección actualmente seleccionada al sistema de portapapeles + + + &Copy + &Copiar + + + C&lose + C&errar + + + &Copy Address + &Copiar dirección + + + Delete the currently selected address from the list + Borrar la dirección actualmente seleccionada de la lista + + + &Export + &Exportar + + + &Delete + &Borrar + + + Choose the address to send coins to + Escoje la dirección para enviar monedas a + + + Choose the address to receive coins with + Escoje la dirección para recibir monedas con + + + C&hoose + E&scojer + + + Sending addresses + Enviando direcciones + + + Receiving addresses + Recibiendo direcciones + + + These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. + +Estas son las direcciones de Bitcoin para enviar pagos . Siempre verifique la cantidad y la dirección de recepción antes de enviar monedas. + + + These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. + Estas son las direcciones de Bitcoin para recibir los pagos . Se recomienda el uso de una nueva dirección de recepción para cada transacción. + + + Copy &Label + Copiar &Etiqueta + + + &Edit + &Editar + + + Export Address List + Exportar lista de direcciones + + + Comma separated file (*.csv) + Coma(,) archivo separado (*.csv) + + + Exporting Failed + Exportación Fallida + + + There was an error trying to save the address list to %1. Please try again. + Hubo un error intentando guardar la lista de direcciones a %1 Inténtelo otravez + + + + AddressTableModel + + Label + Etiqueta + + + Address + Dirección + + + (no label) + (ninguna dirección) + + + + AskPassphraseDialog + + Passphrase Dialog + Diálogo de contraseña + + + Enter passphrase + Poner contraseña + + + New passphrase + Nueva contraseña + + + Repeat new passphrase + Repetir nueva contraseña + + + Encrypt wallet + Billetera Encriptada + + + This operation needs your wallet passphrase to unlock the wallet. + Esta operación necesita tu contraseña de la billetera para desbloquear la billetera + + + Unlock wallet + Billetera Desbloqueada + + + This operation needs your wallet passphrase to decrypt the wallet. + Esta operación necesita tu contraseña de la billetera para desencriptar la billetera. + + + Decrypt wallet + Billetera Desencriptada + + + Change passphrase + Cambiar contraseña + + + Confirm wallet encryption + Confirmar encriptación de la billetera + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! + Precaución: Si tú has encriptado tu billetera y has perdido tu contraseña, usted <b>PERDERÁ TODOS TUS BITCOINS</b> + + + Are you sure you wish to encrypt your wallet? + Estas seguro de que deseas encriptar tu billetera? + + + Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. + Bitcoin Core se cerrará ahora para finalizar el proceso de encriptación. Recuerda que encriptando tu billetera no protegera por completo tus bitcoins desde robos por malware que infectan tu computadora. + + + 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. + IMPORTANTE : Cualquier copias de seguridad anteriores que han hecho de su archivo cartera debe ser reemplazado por el archivo de la carpeta recién generado , encriptado . Por razones de seguridad , las copias de seguridad anteriores del archivo cartera sin cifrar se vuelven inútiles , tan pronto como empiece a utilizar el nuevo , carpeta cifrada . + + + Warning: The Caps Lock key is on! + Ojo: El bloqueo de MAYUSCULAS esta activado! + + + Wallet encrypted + Billetera encriptada + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. + Poner la nueva contraseña a la billetera.<br/>Por favor usa una contraseña de <b>diez o más palabras aleatorias</b>, o <b>nueve o más letras</b>. + + + Enter the old passphrase and new passphrase to the wallet. + Poner la antigua contraseña y nueva contraseña a la billetera. + + + Wallet encryption failed + Encriptación de la billetera fallida + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Encriptación de la billetera fallida por un error interno. Tu billetera no ha sido encriptada. + + + Wallet unlock failed + Falló el desbloqueo de la billetera + + + The passphrase entered for the wallet decryption was incorrect. + La contraseña tecleada de la desencriptación de la billetera ha sido incorrecta. + + + Wallet decryption failed + Encriptación de la billetera fallida + + + Wallet passphrase was successfully changed. + La contraseña de la billetera a sido cambiada exitosamente. + + + + BanTableModel + + + BitcoinGUI + + Synchronizing with network... + Sincronizando con la red... + + + Node + Nodo + + + Show general overview of wallet + Mostrar vista general de la billetera + + + &Transactions + &Transacciones + + + E&xit + S&alir + + + Quit application + Salir de la aplicación + + + About &Qt + Acerca de &Qt + + + Show information about Qt + Mostrar información sobre Qt + + + &Options... + &Opciones + + + &Encrypt Wallet... + &Billetera Encriptada + + + &Backup Wallet... + &Billetera Copia de seguridad... + + + &Change Passphrase... + &Cambiar contraseña... + + + &Sending addresses... + &Enviando Direcciones... + + + &Receiving addresses... + &Recibiendo Direcciones... + + + Open &URI... + Abrir &URL... + + + Bitcoin Core client + Bitcoin Core cliente + + + Importing blocks from disk... + Importando bloques desde el disco... + + + Send coins to a Bitcoin address + Enviando monedas a una dirección de Bitcoin + + + Change the passphrase used for wallet encryption + Cambiar la contraseña usando la encriptación de la billetera + + + &Debug window + &Ventana desarrollador + + + Open debugging and diagnostic console + Abrir consola de diagnóstico y desarrollo + + + &Verify message... + &Verificar Mensaje... + + + Bitcoin + Bitcoin + + + Wallet + Billetera + + + &Send + &Enviar + + + &Receive + &Recibir + + + Show information about Bitcoin Core + Mostrar información sobre Bitcoin Core + + + &Show / Hide + &Mostrar / Ocultar + + + Show or hide the main Window + Mostrar u ocultar la Ventana Principal + + + &File + &Archivo + + + &Settings + &Configuraciones + + + &Help + &Ayuda + + + Bitcoin Core + Bitcoin Core + + + Error + Error + + + + ClientModel + + + CoinControlDialog + + (no label) + (ninguna dirección) + + + + EditAddressDialog + + + FreespaceChecker + + + HelpMessageDialog + + Bitcoin Core + Bitcoin Core + + + + Intro + + Bitcoin Core + Bitcoin Core + + + Error + Error + + + + OpenURIDialog + + + OptionsDialog + + + OverviewPage + + + PaymentServer + + + PeerTableModel + + + QObject + + + QRImageWidget + + + RPCConsole + + + ReceiveCoinsDialog + + + ReceiveRequestDialog + + Address + Dirección + + + Label + Etiqueta + + + + RecentRequestsTableModel + + Label + Etiqueta + + + (no label) + (ninguna dirección) + + + + SendCoinsDialog + + (no label) + (ninguna dirección) + + + + SendCoinsEntry + + + ShutdownWindow + + + SignVerifyMessageDialog + + + SplashScreen + + Bitcoin Core + Bitcoin Core + + + + TrafficGraphWidget + + + TransactionDesc + + + TransactionDescDialog + + + TransactionTableModel + + Label + Etiqueta + + + + TransactionView + + Exporting Failed + Exportación Fallida + + + Comma separated file (*.csv) + Coma(,) archivo separado (*.csv) + + + Label + Etiqueta + + + Address + Dirección + + + + UnitDisplayStatusBarControl + + + WalletFrame + + + WalletModel + + + WalletView + + &Export + &Exportar + + + + bitcoin-core + + Insufficient funds + Fondos Insuficientes + + + Loading wallet... + Cargando billetera... + + + Cannot write default address + No se puede escribir la dirección por defecto + + + Rescanning... + Reescaneando + + + Done loading + Listo Cargando + + + Error + Error + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_es_DO.ts b/src/qt/locale/bitcoin_es_DO.ts index 0463c0f6e1cdc..b4841ca9b8682 100644 --- a/src/qt/locale/bitcoin_es_DO.ts +++ b/src/qt/locale/bitcoin_es_DO.ts @@ -1075,10 +1075,6 @@ General General - - Using OpenSSL version - Utilizando la versión OpenSSL - Startup time Hora de inicio diff --git a/src/qt/locale/bitcoin_es_MX.ts b/src/qt/locale/bitcoin_es_MX.ts index fa2b3c0623be3..b0dfa4ab7c54c 100644 --- a/src/qt/locale/bitcoin_es_MX.ts +++ b/src/qt/locale/bitcoin_es_MX.ts @@ -1,6 +1,10 @@ AddressBookPage + + Right-click to edit address or label + Click derecho para editar tu dirección o etiqueta + Create a new address Crear una dirección nueva @@ -345,6 +349,10 @@ &About Bitcoin Core Acerca de Bitcoin Core + + Modify configuration options for Bitcoin Core + Modificar las opciones de configuración de Bitcoin Core + &Command-line options opciones de la &Linea de comandos @@ -353,6 +361,18 @@ Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options Mostrar mensaje de ayuda del nucleo de Bitcoin para optener una lista con los posibles comandos de Bitcoin + + Error + Error + + + Warning + Aviso + + + Information + Información + Up to date Actualizado al dia @@ -383,6 +403,10 @@ CoinControlDialog + + Quantity: + Cantidad + Bytes: Bytes: @@ -399,6 +423,14 @@ Fee: Cuota: + + After Fee: + Después de los cargos por comisión. + + + Change: + Cambio + Amount Monto @@ -427,6 +459,10 @@ Copy amount Copiar monto + + Copy transaction ID + Copiar identificación de la transacción. + Copy quantity Copiar cantidad @@ -451,11 +487,31 @@ Copy change Copiar cambio + + low + Bajo + + + none + Ninguno + + + yes + si + + + no + no + (no label) (sin etiqueta) - + + (change) + cambio + + EditAddressDialog @@ -501,6 +557,10 @@ FreespaceChecker + + name + nombre + HelpMessageDialog @@ -539,6 +599,10 @@ Bitcoin Core nucleo Bitcoin + + Error + Error + OpenURIDialog @@ -557,6 +621,10 @@ W&allet Cartera + + none + Ninguno + OverviewPage @@ -675,6 +743,10 @@ Send Coins Enviar monedas + + Quantity: + Cantidad + Bytes: Bytes: @@ -691,6 +763,14 @@ Fee: Cuota: + + After Fee: + Después de los cargos por comisión. + + + Change: + Cambio + fast rápido @@ -1062,6 +1142,10 @@ Copy amount copiar monto + + Copy transaction ID + Copiar identificación de la transacción. + Edit label Editar capa @@ -1177,6 +1261,14 @@ Wallet options: Opciones de cartera: + + Information + Información + + + Warning + Aviso + Loading addresses... Cargando direcciones... @@ -1193,5 +1285,9 @@ Done loading Carga completa - + + Error + Error + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_et.ts b/src/qt/locale/bitcoin_et.ts index 945e4cfa5812c..089f01035d89d 100644 --- a/src/qt/locale/bitcoin_et.ts +++ b/src/qt/locale/bitcoin_et.ts @@ -829,10 +829,6 @@ General Üldine - - Using OpenSSL version - Kasutan OpenSSL versiooni - Startup time Käivitamise hetk diff --git a/src/qt/locale/bitcoin_fa.ts b/src/qt/locale/bitcoin_fa.ts index 7ab3b77da3032..02c216765ce83 100644 --- a/src/qt/locale/bitcoin_fa.ts +++ b/src/qt/locale/bitcoin_fa.ts @@ -999,10 +999,6 @@ Debug window پنجرهٔ اشکالزدایی - - Using OpenSSL version - نسخهٔ OpenSSL استفاده شده - Startup time زمان آغاز به کار diff --git a/src/qt/locale/bitcoin_fi.ts b/src/qt/locale/bitcoin_fi.ts index 57987b26ec21b..0fb6aebb9fe9a 100644 --- a/src/qt/locale/bitcoin_fi.ts +++ b/src/qt/locale/bitcoin_fi.ts @@ -1473,10 +1473,6 @@ General Yleinen - - Using OpenSSL version - Käytössä oleva OpenSSL-versio - Using BerkeleyDB version Käyttää BerkeleyDB-versiota @@ -2001,6 +1997,10 @@ Custom: Muokattu: + + (Smart fee not initialized yet. This usually takes a few blocks...) + (Älykästä rahansiirtokulua ei ole vielä alustettu. Tähän kuluu yleensä aikaa muutaman lohkon verran...) + Confirmation time: Vahvistusaika: @@ -2907,10 +2907,38 @@ If <category> is not supplied or if <category> = 1, output all debugging information. Jos <category> on toimittamatta tai jos <category> = 1, tulosta kaikki debug-tieto. + + Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. + Tarkistathan että tietokoneesi päivämäärä ja kellonaika ovat oikeassa! Jos kellosi on väärässä, Bitcoin Core ei toimi oikein. + + + Prune configured below the minimum of %d MiB. Please use a higher number. + Karsinta konfiguroitu alle minimin %d MiB. Käytä surempaa numeroa. + + + Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node) + Karsinta: viime lompakon synkronisointi menee karsitun datan taakse. Sinun tarvitsee ajaa -reindex (lataa koko lohkoketju uudelleen tapauksessa jossa karsiva noodi) + + + Reduce storage requirements by pruning (deleting) old blocks. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, >%u = target size in MiB to use for block files) + Vähennä levytilan tarvetta karsimalla (poistamalla) vanhoja lohkoja. Tämä tila ei ole yhteensopiva -txindex ja -rescan -parametrien kanssa. Varoitus: Tämän asetuksen peruutus vaatii koko lohkoketjun uudelleenlataamisen. (oletus: 0 = poista karsinta käytöstä, >%u = kohdekoko muodossa MiB jota käytetään lohkotiedostoille) + + + Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again. + Uudelleenskannaukset eivät ole mahdollisia karsivassa tilassa. Sinun täytyy käyttää -reindex joka lataa koko lohkoketjun uudelleen. + Error: A fatal internal error occurred, see debug.log for details Virhe: Kriittinen sisäinen virhe kohdattiin, katso debug.log lisätietoja varten + + Fee (in %s/kB) to add to transactions you send (default: %s) + Kulu (muodossa %s/kB) joka lisätään rahansiirtoihin joita lähetät (oletus: %s) + + + Pruning blockstore... + Karsitaan lohkovarastoa... + Run in the background as a daemon and accept commands Aja taustalla daemonina ja hyväksy komennot @@ -2923,6 +2951,10 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Hyväksy yhteyksiä ulkopuolelta (vakioasetus: 1 jos -proxy tai -connect ei määritelty) + + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. + -fallbackfee on asetettu erittäin suureksi! Tämä on rahansiirtokulu jonka voit maksaa kun arvioitu rahansirtokulu ei ole saatavilla. + Bind to given address and always listen on it. Use [host]:port notation for IPv6 Kytkeydy annettuun osoitteeseen ja pidä linja aina auki. Käytä [host]:portin merkintätapaa IPv6:lle. @@ -2967,6 +2999,10 @@ Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. Varoitus: wallet.dat -lompakkotiedosto on korruptoitunut, tiedot pelastettu. Alkuperäinen wallet.dat -lompakkotiedosto on tallennettu wallet.{timestamp}.bak kansioon %s; jos balanssisi tai siirtohistoria on virheellinen, sinun tulisi palauttaa lompakkotiedosto varmuuskopiosta. + + Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. + Salli vertaisten yhdistää annetusta verkkomaskista tai IP-osoitteesta. Voidaan määrittää useampia kertoja. + -maxmempool must be at least %d MB -maxmempool on oltava vähintään %d MB @@ -3087,18 +3123,22 @@ Wallet options: Lompakon valinnat: - - Warning: This version is obsolete; upgrade required! - Varoitus: Tämä versio on vanhentunut; päivittämistä vaaditaan! - You need to rebuild the database using -reindex to change -txindex Sinun tulee uudelleenrakentaa tietokanta käyttäen -reindex vaihtaen -txindex + + 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 + Salli JSON-RPC-yhteydet määritetystä lähteestä. Kelvolliset arvot <ip> ovat yksittäinen IP (esim. 1.2.3.4), verkko/verkkomaski (esim. 1.2.3.4/255.255.255.0) tai verkko/luokaton reititys (esim. 1.2.3.4/24). Tätä valintatapaa voidaan käyttää useita kertoja + Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. Ei voida lukita data-hakemistoa %s. Bitcoin Core on luultavasti jo käynnissä. + + Discover own IP addresses (default: 1 when listening and no -externalip or -proxy) + Paljasta omat IP-osoitteet (oletus: 1 kun kuunnellaan ja -externalip tai -proxy ei ole käytössä) + Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message) Aja komento kun olennainen hälytys vastaanotetaan tai nähdään todella pitkä haara (%s komennossa korvataan viestillä) @@ -3163,6 +3203,10 @@ Invalid amount for -mintxfee=<amount>: '%s' Virheellinen määrä -mintxfee=<amount>: '%s' + + Keep at most <n> unconnectable transactions in memory (default: %u) + Pidä enimmillään <n> yhdistämiskelvotonta rahansiirtoa muistissa (oletus: %u) + Node relay options: Välityssolmukohdan asetukset: @@ -3283,10 +3327,22 @@ Error loading wallet.dat: Wallet corrupted Virhe ladattaessa wallet.dat-tiedostoa: Lompakko vioittunut + + -maxtxfee is set very high! Fees this large could be paid on a single transaction. + -maxtxfee on asetettu erittäin suureksi! Tämänkokoisia kuluja saatetaan maksaa yhdessä rahansiirrossa. + + + -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + -paytxfee on asetettu erittäin suureksi! Tämä on rahansiirtokulu, jonka maksat, mikäli lähetät rahansiirron. + Do not keep transactions in the mempool longer than <n> hours (default: %u) Älä pidä rahansiirtoja muistivarannoissa kauemmin kuin <n> tuntia (oletus: %u) + + Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Virhe lukiessa wallet.dat-tiedostoa! Kaikki avaimet luettiin onnistuneesti, mutta rahansiirtotiedot tai osoitekirjan sisältö saattavat olla muuttuneita tai vääriä. + How thorough the block verification of -checkblocks is (0-4, default: %u) Kuinka läpikäyvä lohkojen -checkblocks -todennus on (0-4, oletus: %u) @@ -3299,6 +3355,10 @@ (default: %s) (oletus: %s) + + Always query for peer addresses via DNS lookup (default: %u) + Pyydä vertaisten osoitteita aina DNS-kyselyjen avulla (oletus: %u) + Error loading wallet.dat Virhe ladattaessa wallet.dat-tiedostoa @@ -3327,6 +3387,10 @@ Listen for connections on <port> (default: %u or testnet: %u) Kuuntele yhteyksiä portissa <port> (oletus: %u tai testnet: %u) + + Maintain at most <n> connections to peers (default: %u) + Ylläpidä enimmillään <n> yhteyttä vertaisiin (oletus: %u) + Make the wallet broadcast transactions Aseta lompakko kuuluttamaan rahansiirtoja @@ -3339,6 +3403,10 @@ Maximum per-connection send buffer, <n>*1000 bytes (default: %u) Maksimi yhteyttä kohden käytettävä lähetyspuskurin koko, <n>*1000 tavua (oletus: %u) + + Prepend debug output with timestamp (default: %u) + Lisää debug-tietojen alkuun aikaleimat (oletus: %u) + Relay and mine data carrier transactions (default: %u) Välitä ja louhi dataa kantavia rahansiirtoja (oletus: %u) @@ -3363,6 +3431,10 @@ Specify configuration file (default: %s) Määritä asetustiedosto (oletus: %s) + + Specify connection timeout in milliseconds (minimum: 1, default: %d) + Määritä yhteyden aikakatkaisu millisekunneissa (minimi: 1, oletus: %d) + Specify pid file (default: %s) Määritä pid-tiedosto (oletus: %s) @@ -3371,6 +3443,10 @@ Spend unconfirmed change when sending transactions (default: %u) Käytä vahvistamattomia vaihtorahoja lähetettäessä rahansiirtoja (oletus: %u) + + Threshold for disconnecting misbehaving peers (default: %u) + Aikaväli sopimattomien vertaisten yhteyksien katkaisuun (oletus: %u) + Unknown network specified in -onlynet: '%s' Tuntematon verkko -onlynet parametrina: '%s' diff --git a/src/qt/locale/bitcoin_fil.ts b/src/qt/locale/bitcoin_fil.ts new file mode 100644 index 0000000000000..fba823837112b --- /dev/null +++ b/src/qt/locale/bitcoin_fil.ts @@ -0,0 +1,157 @@ + + + AddressBookPage + + Create a new address + Gumawa ng bagong address + + + Copy the currently selected address to the system clipboard + Kopyahin ang napiling tahanan sa clipboard + + + &Copy + Kumopya + + + C&lose + Isarado + + + &Copy Address + Tumulad ng kinatatahanan + + + Delete the currently selected address from the list + Alisin ang napiling address sa pagpipilian + + + Choose the address to send coins to + Pumili ng pagpapadalahang address + + + Choose the address to receive coins with + Piliin ang address ng nagpadala + + + C&hoose + Piliin + + + Sending addresses + Address pagpapadala + + + Receiving addresses + Address bilang pagtanggap + + + + AddressTableModel + + + AskPassphraseDialog + + + BanTableModel + + + BitcoinGUI + + + ClientModel + + + CoinControlDialog + + + EditAddressDialog + + + FreespaceChecker + + + HelpMessageDialog + + + Intro + + + OpenURIDialog + + + OptionsDialog + + + OverviewPage + + + PaymentServer + + + PeerTableModel + + + QObject + + + QRImageWidget + + + RPCConsole + + + ReceiveCoinsDialog + + + ReceiveRequestDialog + + + RecentRequestsTableModel + + + SendCoinsDialog + + + SendCoinsEntry + + + ShutdownWindow + + + SignVerifyMessageDialog + + + SplashScreen + + + TrafficGraphWidget + + + TransactionDesc + + + TransactionDescDialog + + + TransactionTableModel + + + TransactionView + + + UnitDisplayStatusBarControl + + + WalletFrame + + + WalletModel + + + WalletView + + + bitcoin-core + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_fr.ts b/src/qt/locale/bitcoin_fr.ts index a0b9feb9adfa0..65808c77406b7 100644 --- a/src/qt/locale/bitcoin_fr.ts +++ b/src/qt/locale/bitcoin_fr.ts @@ -1244,7 +1244,7 @@ Mined balance that has not yet matured - Le solde généré n'est pas encore mûr + Le solde miné n'est pas encore mûr Balances @@ -1473,10 +1473,6 @@ General Général - - Using OpenSSL version - Version d'OpenSSL utilisée - Using BerkeleyDB version Version BerkeleyDB utilisée @@ -2979,6 +2975,18 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Accepter les connexions entrantes (par défaut : 1 si aucun -proxy ou -connect ) + + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. + La valeur -fallbackfee est très élevée ! Elle représente les frais de transaction que vous pourriez acquitter si aucune estimation de frais n'est proposée. + + + A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s) + Un taux de frais (en %s/Ko) qui sera utilisé si l'estimation de frais ne possède pas suffisamment de données (par défaut : %s) + + + Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d) + Accepter les transactions relayées reçues de pairs de la liste blanche même si le nœud ne relaie pas les transactions (par défaut : %d) + Bind to given address and always listen on it. Use [host]:port notation for IPv6 Se lier à l'adresse donnée et toujours l'écouter. Utilisez la notation [host]:port pour l'IPv6 @@ -3011,6 +3019,10 @@ Unable to bind to %s on this computer. Bitcoin Core is probably already running. Impossible de se lier à %s sur cet ordinateur. Bitcoin Core fonctionne probablement déjà. + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + Argument non pris charge -whitelistalwaysrelay ignoré, utiliser -whitelistrelay et/ou -whitelistforcerelay. + Use UPnP to map the listening port (default: 1 when listening and no -proxy) Utiliser l'UPnP pour mapper le port d'écoute (par défaut : 1 lors de l'écoute et pas de mandataire -proxy) @@ -3027,6 +3039,10 @@ Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Avertissement : le réseau ne semble pas totalement d'accord ! Quelques mineurs semblent éprouver des difficultés. + + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + Avertissement : des versions de blocs inconnues sont minées ! Il est possible que des règles inconnues soient en vigeur + Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Avertissement : nous ne semblons pas être en accord complet avec nos pairs ! Vous pourriez avoir besoin d'effectuer une mise à niveau, ou d'autres nœuds du réseau pourraient avoir besoin d'effectuer une mise à niveau. @@ -3047,6 +3063,10 @@ <category> can be: <category> peut être : + + Append comment to the user agent string + Ajouter un commentaire à la chaîne d'agent utilisateur + Block creation options: Options de création de bloc : @@ -3127,10 +3147,22 @@ Invalid -onion address: '%s' Adresse -onion invalide : « %s » + + Invalid amount for -fallbackfee=<amount>: '%s' + Montant invalide pour -fallbackfee=<amount> : « %s » + Keep the transaction memory pool below <n> megabytes (default: %u) Garder la réserve de mémoire transactionnelle sous <n> mégaoctets (par défaut : %u) + + Location of the auth cookie (default: data dir) + Emplacement du fichier témoin auth (par défaut : data dir) + + + Minimum bytes per sigop in transactions we relay and mine (default: %u) + Octets minimaux par sigop dans les transactions que nous relayons et minons (par défaut : %u) + Not enough file descriptors available. Pas assez de descripteurs de fichiers proposés. @@ -3139,6 +3171,10 @@ Only connect to nodes in network <net> (ipv4, ipv6 or onion) Seulement se connecter aux nœuds du réseau <net> (IPv4, IPv6 ou oignon) + + Print version and exit + Imprimer la version et quitter + Prune cannot be configured with a negative value. L'élagage ne peut pas être configuré avec une valeur négative. @@ -3195,10 +3231,6 @@ Wallet options: Options du portefeuille : - - Warning: This version is obsolete; upgrade required! - Avertissement : cette version est obsolète. Une mise à niveau est exigée ! - You need to rebuild the database using -reindex to change -txindex Vous devez reconstruire la base de données en utilisant -reindex afin de modifier -txindex @@ -3295,10 +3327,6 @@ Activating best chain... Activation de la meilleure chaîne... - - Always relay transactions received from whitelisted peers (default: %d) - Toujours relayer les transactions reçues des pairs de la liste blanche (par défaut : %d) - Attempt to recover private keys from a corrupt wallet.dat on startup Tenter de récupérer les clefs privées d'un wallet.dat corrompu lors du démarrage @@ -3381,7 +3409,7 @@ Receive and display P2P network alerts (default: %u) - Recevoir et afficher les alertes du réseau poste à poste (%u par défaut) + Recevoir et afficher les alertes du réseau poste à poste (par défaut : %u) Reducing -maxconnections from %d to %d, because of system limitations. @@ -3463,6 +3491,10 @@ Warning Avertissement + + Warning: unknown new rules activated (versionbit %i) + Avertissement : nouvelles règles inconnues activées (bit de version %i) + Whether to operate in a blocks only mode (default: %u) Faut-il fonctionner en mode blocs seulement (par défaut : %u) diff --git a/src/qt/locale/bitcoin_fr_FR.ts b/src/qt/locale/bitcoin_fr_FR.ts index df63243353931..9a2ac551c63eb 100644 --- a/src/qt/locale/bitcoin_fr_FR.ts +++ b/src/qt/locale/bitcoin_fr_FR.ts @@ -1,27 +1,104 @@ AddressBookPage + + Right-click to edit address or label + Double cliquez afin de modifier l'adresse ou l'étiquette + Create a new address Créer une nouvelle adresse + + &New + &Nouveau + Copy the currently selected address to the system clipboard Copier l'adresse surlignée dans votre presse-papiers + + &Copy + &Copie + + + C&lose + F&ermer + + + &Copy Address + &Adresse de copie + + + Delete the currently selected address from the list + Supprimer l'adresse sélectionnée de la liste + Export the data in the current tab to a file Exporter les données de l'onglet courant vers un fichier + + &Export + &Exporter... + &Delete &Supprimer + + Choose the address to send coins to + Choisissez une adresse où envoyer les bitcoins + + + Choose the address to receive coins with + Choisissez une adresse où recevoir les bitcoins + + + C&hoose + C&oisir + + + Sending addresses + Adresses d'envoi + + + Receiving addresses + Adresses de réception + + + These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. + Voici vos adresses Bitcoin qui vous permettent d'envoyer des paiements. Vérifiez toujours le montant et l'adresse de réception avant d'envoyer des pièces. + + + These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. + Voici vos adresses Bitcoin qui vous permettent de recevoir des paiements. Il est recommandé d'utiliser une nouvelle adresse de réception pour chaque transaction + + + Copy &Label + Copier &Étiquette + + + &Edit + &Éditer + + + Export Address List + Exporter la liste d'adresses + Comma separated file (*.csv) Valeurs séparées par des virgules (*.csv) - + + Exporting Failed + Échec de l'export + + + There was an error trying to save the address list to %1. Please try again. + Il y a eu une erreur durant la tentative de sauvegarde de la liste d’adresse vers %1. +Réessayez. + + AddressTableModel @@ -39,6 +116,10 @@ AskPassphraseDialog + + Passphrase Dialog + Dialogue mot de passe + Enter passphrase Entrez la phrase de passe @@ -79,10 +160,30 @@ Confirm wallet encryption Confirmer le chiffrement du porte-monnaie + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! + Attention: Si vous cryptez votre portefeuille et que vous perdez votre mot de passe vous <b> PERDREZ TOUS VOS BITCOINS</b>! + + + Are you sure you wish to encrypt your wallet? + Êtes-vous sûr de de vouloir crypter votre portefeuille ? + + + Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. + Bitcoin Core fermera maintenant pour finir le processus de chiffrement. Rappelez-vous que crypter votre portefeuille ne protége pas totalement vos bitcoins d'être volé par un malware ayant infecté votre ordinateur. + + + Warning: The Caps Lock key is on! + Attention : La touche majuscule est enfoncé. + Wallet encrypted Porte-monnaie chiffré + + Enter the old passphrase and new passphrase to the wallet. + Entrez l'ancien mot de passe et le nouveau mot de passe pour le portefeuille + Wallet encryption failed Le chiffrement du porte-monnaie a échoué @@ -107,12 +208,28 @@ Wallet decryption failed Le décryptage du porte-monnaie a échoué - + + Wallet passphrase was successfully changed. + Le changement du mot de passe du portefeuille à été effectué avec succès. + + BanTableModel - + + IP/Netmask + IP/Masque de sous réseau + + + Banned Until + Banni jusque + + BitcoinGUI + + Sign &message... + Signer &message... + Synchronizing with network... Synchronisation avec le réseau... @@ -121,6 +238,10 @@ &Overview &Vue d'ensemble + + Node + Nœud + Show general overview of wallet Affiche une vue d'ensemble du porte-monnaie @@ -153,6 +274,46 @@ &Options... &Options... + + &Encrypt Wallet... + &Chiffrer le portefeuille + + + &Backup Wallet... + &Sauvegarder le portefeuille + + + &Change Passphrase... + &Modifier le mot de passe + + + &Sending addresses... + &Adresses d'envoi + + + &Receiving addresses... + &Adresses de réception + + + Open &URI... + Ouvrir &URI + + + Bitcoin Core client + Client Bitcoin Core + + + Importing blocks from disk... + Importer les blocs depuis le disque... + + + Reindexing blocks on disk... + Réindexer les blocs sur le disque... + + + Send coins to a Bitcoin address + Envoyer des pièces à une adresse Bitcoin + Backup wallet to another location Sauvegarder le porte-monnaie à un autre emplacement @@ -161,14 +322,54 @@ Change the passphrase used for wallet encryption Modifier la phrase de passe utilisée pour le cryptage du porte-monnaie + + &Debug window + &Fenêtre de débogage + + + Open debugging and diagnostic console + Ouvrir la console de débogage et de diagnostic + + + &Verify message... + &Vérification du message + Bitcoin Bitcoin + + Wallet + Portefeuille + &Send &Envoyer + + &Receive + &Réception + + + Show information about Bitcoin Core + Montrer les informations à propos de Bitcoin Core + + + &Show / Hide + &Montrer / Cacher + + + Show or hide the main Window + Montrer ou cacher la fenêtre principale + + + Encrypt the private keys that belong to your wallet + Crypter les clé privées qui appartiennent votre portefeuille + + + Sign messages with your Bitcoin addresses to prove you own them + Signer vos messages avec vos adresses Bitcoin pour prouver que vous les détenez + &File &Fichier @@ -185,6 +386,86 @@ Tabs toolbar Barre d'outils des onglets + + Bitcoin Core + Bitcoin Core + + + Request payments (generates QR codes and bitcoin: URIs) + Demander des paiements (générer QR codes et bitcoin: URIs) + + + &About Bitcoin Core + &À propos de Bitcoin + + + Modify configuration options for Bitcoin Core + Modifier les options de configuration de Bitcoin Core + + + Show the list of used sending addresses and labels + Montrer la liste des adresses d'envois utilisées et les étiquettes + + + Open a bitcoin: URI or payment request + Ouvrir un bitcoin: URI ou demande de paiement + + + &Command-line options + &Options de ligne de commande + + + %n active connection(s) to Bitcoin network + %n connexion active au réseau Bitcoin%n connexions actives au réseau Bitcoin + + + No block source available... + Aucun bloc source disponible + + + %n hour(s) + %n heure%n heures + + + %n day(s) + %n jour%n jours + + + %n week(s) + %n semaine%n semaines + + + %1 and %2 + %1 et %2 + + + %n year(s) + %n an%n années + + + %1 behind + en retard de %1 + + + Last received block was generated %1 ago. + Le dernier bloc reçu a été généré %1. + + + Transactions after this will not yet be visible. + Les transactions ne seront plus visible après ceci. + + + Error + Erreur + + + Warning + Attention + + + Information + Information + Up to date À jour @@ -193,6 +474,36 @@ Catching up... Rattrapage... + + Date: %1 + + Date: %1 + + + + Amount: %1 + + Montant:%1 + + + + Type: %1 + + Type: %1 + + + + Label: %1 + + Étiquette: %1 + + + + Address: %1 + + Adresse: %1 + + Sent transaction Transaction envoyée @@ -212,25 +523,89 @@ ClientModel - + + Network Alert + Alerte réseau + + CoinControlDialog + + Coin Selection + Sélection de pièce + + + Quantity: + Quantité: + + + Bytes: + Octets: + Amount: Montant : + + Priority: + Priorité: + + + Fee: + Frais: + + + Dust: + Poussière: + + + After Fee: + Après frais: + + + Change: + Change: + + + (un)select all + (dé)sélectionné tout: + + + Tree mode + Mode arbre + + + List mode + Mode list + Amount Montant + + Received with label + Reçu avec : + + + Received with address + Reçue avec l'adresse + Date Date + + Confirmations + Confirmations + Confirmed Confirmée + + Priority + Priorité + Copy address Copier l'adresse @@ -243,11 +618,131 @@ Copy amount Copier le montant + + Copy transaction ID + Copie ID transaction + + + Lock unspent + Verrouiller les non dépensés + + + Unlock unspent + Déverrouiller les non dépensés + + + Copy quantity + Copier la quantité + + + Copy fee + Copier les frais + + + Copy after fee + Copier après les frais + + + Copy bytes + Copier les octets + + + Copy priority + Copier la priorité + + + Copy dust + Copier la poussière + + + Copy change + Copier changement + + + highest + le plus élevé + + + higher + plus haute + + + high + haut + + + medium-high + moyen-élevé + + + medium + moyen + + + low-medium + bas-moyen + + + low + bas + + + lower + inférieur + + + lowest + le plus bas + + + (%1 locked) + (%1 verrouillé) + + + none + aucun + + + This label turns red if the transaction size is greater than 1000 bytes. + Cette étiquette devient rouge si la taille de la transaction est plus grande que 1000 octets + + + This label turns red if the priority is smaller than "medium". + Cette étiquette devient rouge si la priorité est plus petite que "moyen" + + + Can vary +/- %1 satoshi(s) per input. + Peut varier de +/- %1 satoshi(s) par entrée. + + + yes + oui + + + no + non + + + This means a fee of at least %1 per kB is required. + Cela signifie que des frais d'au moins %1 par kO sont requis. + + + Can vary +/- 1 byte per input. + Peut varier de +/- 1 octet par entrée. + (no label) (aucune étiquette) - + + change from %1 (%2) + changement de %1 (%2) + + + (change) + (changement) + + EditAddressDialog @@ -282,6 +777,10 @@ The entered address "%1" is already in the address book. L'adresse fournie « %1 » est déjà présente dans le carnet d'adresses. + + The entered address "%1" is not a valid Bitcoin address. + L'adresse entrée "%1" n'est pas une adresse Bitcoin valide. + Could not unlock wallet. Impossible de déverrouiller le porte-monnaie. @@ -293,26 +792,174 @@ FreespaceChecker - - - HelpMessageDialog - Usage: - Utilisation : + A new data directory will be created. + Un nouveau répertoire de données sera créé. + + + name + nom + + + Path already exists, and is not a directory. + Le chemin existe déjà et ce n'est pas un répertoire. + + + Cannot create data directory here. + Impossible de créer un répertoire ici. + + + + HelpMessageDialog + + Bitcoin Core + Bitcoin Core + + + version + version + + + (%1-bit) + (%1-bit) + + + About Bitcoin Core + À propos de Bitcoin Core + + + Command-line options + Options de ligne de commande + + + Usage: + Utilisation : + + + command-line options + Options de ligne de commande + + + UI Options: + Options interface graphique: + + + Start minimized + Démarrer sous forme minimisée - Intro - - + Intro + + Welcome + Bienvenue + + + Welcome to Bitcoin Core. + Bienvenue sur Bitcoin Core. + + + Use the default data directory + Utiliser le répertoire par défaut + + + Use a custom data directory: + Utiliser votre propre répertoire + + + Bitcoin Core + Bitcoin Core + + + Error: Specified data directory "%1" cannot be created. + Erreur: Le répertoire de données "%1" n'a pas pu être créé. + + + Error + Erreur + + + %n GB of free space available + %n GO d'espace libre disponible%n GO d'espace libre disponible + + + (of %n GB needed) + (%n GB nécessaire)(%n GB nécessaire) + + + OpenURIDialog - + + Open URI + Ouvrir URI + + + Open payment request from URI or file + Ouvrir une demande de paiement depuis une URI ou un fichier + + + URI: + URI: + + + Select payment request file + Sélectionner un fichier de demande de paiement + + + Select payment request file to open + Sélectionnez le fichier de demande de paiement à ouvrir + + OptionsDialog Options Options + + &Main + &Principal + + + Size of &database cache + Taille du cache de la base de données. + + + MB + MO + + + Accept connections from outside + Accepter les connexions venant de l'extérieur + + + Allow incoming connections + Autoriser les connexions entrantes + + + IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + Adresse IP du proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + + Reset all client options to default. + Réinitialiser toutes les options du client par défaut. + + + &Reset Options + &Options de réinitialisation + + + &Network + &Réseau + + + Automatically start Bitcoin Core after logging in to the system. + Démarrer automatiquement Bitcoin Core après s'être connecté au système. + + + Expert + Expert + Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled. Ouvrir le port du client Bitcoin automatiquement sur le routeur. Cela ne fonctionne que si votre routeur supporte l'UPnP et si la fonctionnalité est activée. @@ -321,6 +968,38 @@ Map port using &UPnP Ouvrir le port avec l'&UPnP + + Proxy &IP: + Proxy &IP: + + + &Port: + &Port: + + + Port of the proxy (e.g. 9050) + Port du proxy (e.g. 9050) + + + Used for reaching peers via: + Utilisé pour contacter des pairs via: + + + IPv4 + IPv4 + + + IPv6 + IPv6 + + + Tor + Tor + + + &Window + &Fenêtre + &Minimize to the tray instead of the taskbar &Minimiser dans la barre système au lieu de la barre des tâches @@ -329,37 +1008,429 @@ M&inimize on close Mi&nimiser lors de la fermeture - + + &Display + &Afficher + + + User Interface &language: + Interface utilisateur &langage: + + + &OK + &OK + + + &Cancel + &Annuler + + + default + defaut + + + none + aucun + + + Confirm options reset + Confirmer les options de réinitialisation + + + Client restart required to activate changes. + Redémarrage du client nécessaire pour activer les changements. + + + This change would require a client restart. + Ce changement nécessiterait un redémarrage du client. + + + The supplied proxy address is invalid. + L'adresse du proxy est invalide. + + OverviewPage Form Formulaire + + Watch-only: + Regarder seulement: + + + Available: + Disponible: + + + Pending: + En attente: + + + Immature: + Immature: + + + Balances + Balances + + + Total: + Total: + + + Your current total balance + Votre balance totale courante + + + Spendable: + Dépensable: + + + Recent transactions + Transactions récentes + PaymentServer - + + Invalid payment address %1 + Adresse de paiement invalide %1 + + + Payment request rejected + Requête de paiement rejetée + + + Payment request is not initialized. + La demande de paiement n'a pas été initialisée. + + + Payment request error + Erreur lors de la requête de paiement + + + Payment request expired. + Demande de paiement expirée. + + + Invalid payment request. + Demande de paiement invalide. + + + Refund from %1 + Remboursement de %1 + + + Bad response from server %1 + Mauvaise réponse du serveur %1 + + + Network request error + Erreur de demande de réseau + + PeerTableModel - + + User Agent + Agent Utilisateur + + + Node/Service + Nœud/Service + + + Ping Time + Temps du ping + + QObject Amount Montant - + + Enter a Bitcoin address (e.g. %1) + Entrer une adresse Bitcoin (e.g. %1) + + + %1 d + %1 j + + + %1 h + %1 h + + + %1 m + %1 m + + + %1 s + %1 s + + + None + Aucun + + + N/A + N/A + + + %1 ms + %1 ms + + QRImageWidget - + + &Save Image... + &Sauvegarder image + + + &Copy Image + &Copier image + + + Save QR Code + Sauvegarder QR code + + + PNG Image (*.png) + Image PNG (*.png) + + RPCConsole + + Client name + Nom du client + + + N/A + N/A + + + Client version + Version du client + + + &Information + &Information + + + Debug window + Fenêtre de débogage + + + General + Général + + + Using BerkeleyDB version + Version BerkeleyDButilisée + + + Startup time + Le temps de démarrage + + + Network + Réseau + Name Nom - + + Number of connections + Nombre de connexions + + + Block chain + Chaîne de bloc + + + Current number of blocks + Nombre courant de blocs + + + Memory Pool + Mémoire du pool + + + Current number of transactions + Nombre courant de transactions + + + Memory usage + Usage de la mémoire + + + Received + Reçu + + + Sent + Envoyé + + + &Peers + &Pairs + + + Banned peers + Pairs bannis + + + Whitelisted + Autorisé par la liste + + + Direction + Direction + + + Version + Version + + + Starting Block + Bloc de départ + + + Synced Blocks + Blocs Synchronisés + + + User Agent + Agent Utilisateur + + + Services + Services + + + Ban Score + Score de ban + + + Connection Time + Temps de connexion + + + Last Send + Dernier envoyé + + + Last Receive + Dernier reçu + + + Ping Time + Temps du ping + + + Ping Wait + Attente du ping + + + &Open + &Ouvert + + + &Console + &Console + + + &Network Traffic + &Trafic réseau + + + &Clear + &Nettoyer + + + Totals + Totaux + + + In: + Entrée: + + + Out: + Sortie: + + + Build date + Date de création + + + Debug log file + Fichier du journal de débogage + + + Clear console + Nettoyer la console + + + 1 &hour + 1 &heure + + + 1 &day + 1 &jour + + + 1 &week + 1 &semaine + + + 1 &year + 1 &an + + + %1 B + %1 O + + + %1 KB + %1 KO + + + %1 MB + %1 MO + + + %1 GB + %1 GO + + + via %1 + via %1 + + + never + jamais + + + Yes + Oui + + + No + Non + + + Unknown + Inconnu + + ReceiveCoinsDialog @@ -374,20 +1445,72 @@ &Message: Message : + + Clear all fields of the form. + Nettoyer tous les champs du formulaire. + + + Clear + Nettoyer + + + Requested payments history + Historique des demandes de paiements. + + + &Request payment + &Demande de paiement + + + Show + Montrer + + + Remove + Retirer + Copy label Copier l'étiquette + + Copy message + Copier message + Copy amount Copier le montant - - - ReceiveRequestDialog + + + ReceiveRequestDialog + + QR Code + QR Code + + + Copy &URI + Copier &URI + + + Copy &Address + Copier &Adresse + + + &Save Image... + &Sauvegarder image + + + Request payment to %1 + Demande de paiement à %1 + + + Payment information + Informations de paiement + - QR Code - QR Code + URI + URI Address @@ -428,25 +1551,113 @@ (no label) (aucune étiquette) - + + (no message) + (pas de message) + + + (no amount) + (pas de montant) + + SendCoinsDialog Send Coins Envoyer des pièces + + Inputs... + Sorties... + + + automatically selected + Automatiquement sélectionné + Insufficient funds! Fonds insuffisants + + Quantity: + Quantité: + + + Bytes: + Octets: + Amount: Montant : + + Priority: + Priorité: + + + Fee: + Frais: + + + After Fee: + Après frais: + + + Change: + Change: + + + Transaction Fee: + Frais de transaction + + + Choose... + Choisir... + + + per kilobyte + par kilo octet + + + Hide + Cacher + + + total at least + Au total au moins + + + Recommended: + Recommandé: + + + Confirmation time: + Temps de confirmation: + + + normal + normal + + + fast + rapide + Send to multiple recipients at once Envoyer des pièces à plusieurs destinataires à la fois + + Clear all fields of the form. + Nettoyer tous les champs du formulaire. + + + Dust: + Poussière: + + + Clear &All + Nettoyer &Tout + Balance: Solde : @@ -459,19 +1670,87 @@ Confirm send coins Confirmer l'envoi des pièces + + %1 to %2 + %1 à %2 + + + Copy quantity + Copier la quantité + Copy amount Copier le montant + + Copy fee + Copier les frais + + + Copy after fee + Copier après les frais + + + Copy bytes + Copier les octets + + + Copy priority + Copier la priorité + + + Copy change + Copier changement + + + Total Amount %1 + Montant Total %1 + + + or + ou + The amount to pay must be larger than 0. Le montant à payer doit être supérieur à 0. + + The amount exceeds your balance. + Le montant excède votre balance. + + + Transaction creation failed! + Échec de la création de la transaction + + + Payment request expired. + Demande de paiement expirée. + + + Pay only the required fee of %1 + Payer seulement les frais obligatoire de %1 + + + Warning: Invalid Bitcoin address + Attention: Adresse Bitcoin Invalide + (no label) (aucune étiquette) - + + Copy dust + Copier la poussière + + + Are you sure you want to send? + Êtes-vous sûr de vouloir envoyer ? + + + added as transaction fee + Ajoute en tant que frais de transaction + + SendCoinsEntry @@ -490,6 +1769,14 @@ &Label: &Étiquette : + + Choose previously used address + Choisir une adresse précédemment utilisée + + + This is a normal payment. + C'est un paiement normal. + Alt+A Alt+A @@ -502,6 +1789,10 @@ Alt+P Alt+P + + Remove this entry + Retirer cette entrée + Message: Message : @@ -510,7 +1801,11 @@ Pay To: Payer à : - + + Memo: + Memo: + + ShutdownWindow @@ -520,6 +1815,10 @@ &Sign Message &Signer le message + + Choose previously used address + Choisir une adresse précédemment utilisée + Alt+A Alt+A @@ -536,13 +1835,65 @@ Enter the message you want to sign here Entrez ici le message que vous désirez signer + + Signature + Signature + + + Copy the current signature to the system clipboard + Copier l'adresse courante dans le presse papier + Sign &Message &Signer le message - + + Clear &All + Nettoyer &Tout + + + &Verify Message + &Vérifier message + + + Verify &Message + Vérifier &Message + + + The entered address is invalid. + L'adresse entrée est invalide. + + + Please check the address and try again. + Vérifiez l'adresse et réessayer. + + + Message signed. + Message signé. + + + Please check the signature and try again. + Vérifiez la signature et réessayer. + + + Message verification failed. + Vérification du message échouée. + + + Message verified. + Message vérifié. + + SplashScreen + + Bitcoin Core + Bitcoin Core + + + The Bitcoin Core developers + Les développeurs de Bitcoin Core + [testnet] [testnet] @@ -550,7 +1901,11 @@ TrafficGraphWidget - + + KB/s + KO/s + + TransactionDesc @@ -573,30 +1928,110 @@ Date Date + + Source + Source + Generated Généré + + From + De + + + To + Á + + + own address + Votre adresse + + + watch-only + Lecture uniquement + + + label + Étiquette + Credit Crédit + + not accepted + Pas accepté + Debit Débit + + Total debit + Débit total + + + Total credit + Crédit total + + + Transaction fee + Frais de transaction + + + Net amount + Montant net + Message Message + + Comment + Commentaire + + + Transaction ID + ID de transaction + + + Merchant + Marchant + + + Debug information + Information de débogage + + + Transaction + Transaction + + + Inputs + Entrées + Amount Montant + + true + vrai + + + false + faux + , has not been successfully broadcast yet , n'a pas encore été diffusée avec succès + + Open for %n more block(s) + Ouvert pour %n bloc de plusOuvert pour %n blocs de plus + unknown inconnue @@ -623,6 +2058,10 @@ Type Type + + Open for %n more block(s) + Ouvert pour %n bloc de plusOuvert pour %n blocs de plus + Open until %1 Ouvert jusqu'à %1 @@ -639,10 +2078,18 @@ Generated but not accepted Généré mais pas accepté + + Offline + Hors ligne + Label Étiquette + + Unconfirmed + Non Confirmé + Received with Reçues avec @@ -663,6 +2110,10 @@ Mined Extraction + + watch-only + Lecture uniquement + (n/a) (indisponible) @@ -754,10 +2205,30 @@ Copy amount Copier le montant + + Copy transaction ID + Copie ID transaction + Edit label Éditer l'étiquette + + Show transaction details + Afficher les détails de la transaction + + + Export Transaction History + Exporter l'historique des transactions + + + Exporting Failed + Échec de l'export + + + Exporting Successful + Export réalisé avec sucés + Comma separated file (*.csv) Valeurs séparées par des virgules (*.csv) @@ -800,7 +2271,11 @@ WalletFrame - + + No wallet has been loaded. + Aucun portefeuille a été chargé. + + WalletModel @@ -810,6 +2285,10 @@ WalletView + + &Export + &Exporter... + Export the data in the current tab to a file Exporter les données de l'onglet courant vers un fichier @@ -826,7 +2305,11 @@ Backup Failed La sauvegarde a échoué - + + Backup Successful + Sauvegarde réussie + + bitcoin-core @@ -837,6 +2320,10 @@ Specify data directory Spécifier le répertoire de données + + Specify your own public address + Spécifier votre adresse publique + Accept command line and JSON-RPC commands Accepter les commandes de JSON-RPC et de la ligne de commande @@ -845,14 +2332,95 @@ Run in the background as a daemon and accept commands Fonctionner en arrière-plan en tant que démon et accepter les commandes + + <category> can be: + <category> peut être: + + + Block creation options: + Options de création de bloc: + + + Connection options: + Options de connexion: + + + Debugging/Testing options: + Options de débogage/test + + + Importing... + +Importation ... + + + Verifying blocks... + Vérifications des blocs... + + + Verifying wallet... + Vérification du portefeuille... + + + Wallet options: + Options du portefeuille: + + + (default: %u) + (défaut: %u) + + + Connect through SOCKS5 proxy + Connecté au travers du proxy SOCKS5 + + + Information + Information + + + Node relay options: + Options du relais de nœud: + + + RPC server options: + Options de serveur RPC: + Send trace/debug info to console instead of debug.log file Envoyer les informations de débogage/trace à la console au lieu du fichier debug.log + + Signing transaction failed + Transaction signée échouée + + + This is experimental software. + C'est un logiciel expérimental. + + + Transaction amount too small + Montant de la transaction trop bas + + + Transaction amounts must be positive + Les montants de la transaction doivent être positif + + + Transaction too large for fee policy + Montant de la transaction trop élevé pour la politique de frais + + + Transaction too large + Transaction trop grande + Username for JSON-RPC connections Nom d'utilisateur pour les connexions JSON-RPC + + Warning + Attention + Password for JSON-RPC connections Mot de passe pour les connexions JSON-RPC @@ -869,10 +2437,26 @@ Error loading wallet.dat: Wallet corrupted Erreur lors du chargement de wallet.dat : porte-monnaie corrompu + + (default: %s) + (défaut: %s) + Error loading wallet.dat Erreur lors du chargement de wallet.dat + + Generate coins (default: %u) + Générer des pièces (défaut: %u) + + + Invalid -proxy address: '%s' + Adresse -proxy invalide: '%s' + + + Specify pid file (default: %s) + Spécifier le pid du fichier (défaut: %s) + Insufficient funds Fonds insuffisants @@ -885,6 +2469,14 @@ Loading wallet... Chargement du porte-monnaie... + + Cannot downgrade wallet + Vous ne pouvez pas rétrograder votre portefeuille + + + Cannot write default address + Impossible d'écrire l'adresse par défaut + Rescanning... Nouvelle analyse... @@ -893,5 +2485,9 @@ Done loading Chargement terminé - + + Error + Erreur + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_gl.ts b/src/qt/locale/bitcoin_gl.ts index 96d4adeba9df8..50b081d20562a 100644 --- a/src/qt/locale/bitcoin_gl.ts +++ b/src/qt/locale/bitcoin_gl.ts @@ -983,10 +983,6 @@ Debug window Ventana de Depuración - - Using OpenSSL version - Usar versión OpenSSL - Startup time Tempo de arranque diff --git a/src/qt/locale/bitcoin_he.ts b/src/qt/locale/bitcoin_he.ts index 926d20620694e..d937e211b0f1a 100644 --- a/src/qt/locale/bitcoin_he.ts +++ b/src/qt/locale/bitcoin_he.ts @@ -1,6 +1,10 @@ AddressBookPage + + Right-click to edit address or label + לחץ משק ימני כדי לערוך כתובת או חברה + Create a new address יצירת כתובת חדשה @@ -163,6 +167,10 @@ Are you sure you wish to encrypt your wallet? האם אכן להצפין את הארנק? + + Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. + ליבת ביטקוין תיסגר עכשיו כדי לסיים את תליך ההצפנה. זכור כי הצפנה אינה יכולה להגן עלייך באופן מלא מגניבה שמקורה בתוכנות זדוניות המצויות במחשב שלך. + 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. לתשומת לבך: כל גיבוי קודם שביצעת לארנק שלך יש להחליף בקובץ הארנק המוצפן שזה עתה נוצר. מטעמי אבטחה, גיבויים קודמים של קובץ הארנק הבלתי-מוצפן יהפכו לחסרי תועלת עם התחלת השימוש בארנק החדש המוצפן. @@ -179,6 +187,10 @@ Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. נא להזין את מילת הצופן החדשה לארנק.<br/>כדאי להשתמש במילת צופן המורכבת מ<b>עשרה תווים אקראיים ומעלה</b>, או <b>שמונה מילים ומעלה</b>. + + Enter the old passphrase and new passphrase to the wallet. + הכנס את מילת הצופן הישנה ומילת צופן חדשה לארנק שלך. + Wallet encryption failed הצפנת הארנק נכשלה @@ -1259,10 +1271,6 @@ General כללי - - Using OpenSSL version - שימוש ב־OpenSSL גרסה - Using BerkeleyDB version שימוש ב־BerkeleyDB גרסה diff --git a/src/qt/locale/bitcoin_hr.ts b/src/qt/locale/bitcoin_hr.ts index 413dc21857344..f9d744aa3ec37 100644 --- a/src/qt/locale/bitcoin_hr.ts +++ b/src/qt/locale/bitcoin_hr.ts @@ -1017,10 +1017,6 @@ Debug window Konzola za dijagnostiku - - Using OpenSSL version - OpenSSL verzija u upotrebi - Network Mreža diff --git a/src/qt/locale/bitcoin_hu.ts b/src/qt/locale/bitcoin_hu.ts index ab4517ccfabb0..839ee883bd356 100644 --- a/src/qt/locale/bitcoin_hu.ts +++ b/src/qt/locale/bitcoin_hu.ts @@ -963,6 +963,10 @@ The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. Itt beállíthatod a kezelőfelület nyelvét. A beállítás a Bitcoin újraindítása után lép érvénybe. + + Third party transaction URLs + Harmadik fél tranzakció URL-ek + Reset all client options to default. Minden kliensbeállítás alapértelmezettre állítása. @@ -1257,10 +1261,6 @@ General Általános - - Using OpenSSL version - Használt OpenSSL verzió - Using BerkeleyDB version Használt BerkeleyDB verzió diff --git a/src/qt/locale/bitcoin_id_ID.ts b/src/qt/locale/bitcoin_id_ID.ts index 1b626fbf239dc..e1ec7ae7fa24a 100644 --- a/src/qt/locale/bitcoin_id_ID.ts +++ b/src/qt/locale/bitcoin_id_ID.ts @@ -59,19 +59,19 @@ Sending addresses - Alamat-alamat mengirim + Alamat pengirim Receiving addresses - Alamat-alamat menerima + Alamat penerima These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Alamat-alamat Anda supaya mengirim pembayaran. Periksalah jumlah dan alamat penerima setiap kali Anda mengirim Bitcoin. + Alamat-alamat Anda untuk mengirim pembayaran. Periksalah jumlah dan alamat penerima setiap kali Anda mengirim Bitcoin. These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Alamat-alamat Anda supaya menerima pembayaran. Dianjurkan agar Anda menggunakan alamat menerima yang baru untuk setiap transaksi. + Alamat-alamat Anda untuk menerima pembayaran. Dianjurkan agar Anda menggunakan alamat yang baru untuk setiap transaksi. Copy &Label @@ -93,7 +93,11 @@ Exporting Failed Proses Ekspor Gagal - + + There was an error trying to save the address list to %1. Please try again. + Terjadi kesalahan saat menyimpan daftar alamat ke %1. Silakan coba lagi. + + AddressTableModel @@ -133,7 +137,7 @@ This operation needs your wallet passphrase to unlock the wallet. - Operasi ini memerlukan kata kunci dompet Anda untuk membuka dompet ini. + Operasi ini memerlukan kata kunci dompet Anda untuk membuka dompet. Unlock wallet @@ -141,7 +145,7 @@ This operation needs your wallet passphrase to decrypt the wallet. - Operasi ini memerlukan kata kunci dompet Anda untuk mendekripsi dompet ini. + Operasi ini memerlukan kata kunci dompet Anda untuk mendekripsi dompet. Decrypt wallet @@ -157,11 +161,19 @@ Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Perhatian: Jika anda mengenkripsi dompet anda dan lupa kata kuncinya, anda pasti <b>KEHILANGAN SELURUH BITCOIN ANDA</B>! + Perhatian: Jika anda mengenkripsi dompet anda dan lupa kata kuncinya, anda akan <b>KEHILANGAN SELURUH BITCOIN ANDA</b>! Are you sure you wish to encrypt your wallet? - Apakah kamu yakin ingin mengenkripsi dompet anda? + Apakah Anda yakin ingin mengenkripsi dompet Anda? + + + Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. + Bitcoin Core akan ditutup untuk menyelesaikan proses enkripsi. Mohon diingat bahwa mengenkripsi dompet Anda tidak akan sepenuhnya melindungi bitcoin Anda dari virus atau malware yang menginfeksi komputer Anda. + + + 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. + PENTING: Setiap back up yang sudah Anda buat sebaiknya diganti dengan data dompet Anda yang baru dan terenkripsi. Untuk alasan keamanan, data back up tidak terenkripsi yang sudah Anda buat sebelumnya tidak akan dapat digunakan setelah Anda mulai menggunakan dompet yang baru dan terenkripsi. Warning: The Caps Lock key is on! @@ -171,6 +183,14 @@ Wallet encrypted Dompet terenkripsi + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. + Masukkan kata kunci untuk dompet Anda.<br/>Mohon gunakan kata kunci <b>yang terdiri dari 10 karakter acak</b>, atau <b>delapan atau beberapa kata lagi</b>. + + + Enter the old passphrase and new passphrase to the wallet. + Masukkan kata kunci lama dan kata kunci baru dompet Anda. + Wallet encryption failed Enkripsi dompet gagal @@ -197,12 +217,20 @@ Wallet passphrase was successfully changed. - Kata kunci untuk dompet berubah berhasil. + Kata kunci dompet Anda berhasil diubah. BanTableModel - + + IP/Netmask + IP/Netmask + + + Banned Until + Di banned sampai + + BitcoinGUI @@ -223,7 +251,7 @@ Show general overview of wallet - Tampilkan kilasan umum dari dompet + Tampilkan gambaran umum dompet Anda &Transactions @@ -231,7 +259,7 @@ Browse transaction history - Jelajah sejarah transaksi + Lihat riwayat transaksi E&xit @@ -267,11 +295,11 @@ &Sending addresses... - Alamat-alamat &Mengirim + &Alamat-alamat untuk mengirim... &Receiving addresses... - Alamat-alamat &Menerima + &Alamat-alamat untuk menerima... Open &URI... @@ -279,15 +307,15 @@ Bitcoin Core client - Client Bitcoin Inti + Klien Bitcoin Core Importing blocks from disk... - Blok-blok sedang di-impor dari disk + Mengimpor blok dari disk... Reindexing blocks on disk... - Mengindex ulang block di harddisk... + Mengindex ulang blok di dalam disk... Send coins to a Bitcoin address @@ -331,11 +359,11 @@ Show information about Bitcoin Core - Tampilkan informasi tentang Bitcoin Inti + Tampilkan informasi tentang Bitcoin Core &Show / Hide - &Sunjukkan / Menyembungi + &Tampilkan / Sembunyikan Show or hide the main Window @@ -343,15 +371,15 @@ Encrypt the private keys that belong to your wallet - Mengenkripsi kunci-kunci pribadi yang dipunyai dompetmu + Enkripsi private key yang dimiliki dompet Anda Sign messages with your Bitcoin addresses to prove you own them - Tandalah pesanan dengan alamat-alamat Bitcoin Anda supaya membuktikan pesanan itu dikirim oleh Anda + Tanda tangani sebuah pesan menggunakan alamat Bitcoin Anda untuk membuktikan bahwa Anda adalah pemilik alamat tersebut Verify messages to ensure they were signed with specified Bitcoin addresses - Periksakan pesan-pesan supaya menjaminkan ditandatangani oleh alamat Bitcoin yang terperinci + Verifikasi pesan untuk memastikan bahwa pesan tersebut ditanda tangani oleh suatu alamat Bitcoin tertentu &File @@ -375,12 +403,16 @@ Request payments (generates QR codes and bitcoin: URIs) - Permintaan pembayaran (membangkitkan kode QR dan bitcoin: URIs) + Permintaan pembayaran (membuat kode QR dan bitcoin: URIs) &About Bitcoin Core &Mengenai Bitcoin Core + + Modify configuration options for Bitcoin Core + Modifikasi pengaturan konfigurasi untuk Bitcoin Core + Show the list of used sending addresses and labels Tampilkan daftar alamat dan label yang terkirim @@ -395,20 +427,24 @@ &Command-line options - &pilihan Perintah-baris + &pilihan Command-line Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Tampilkan pesan bantuan Bitcoin Core untuk memberikan daftar pilihan perintah-baris yang memungkinkan dalam aplikasi Bitcoin + Tampilkan pesan bantuan Bitcoin Core untuk mendapatkan daftar pilihan Command-line %n active connection(s) to Bitcoin network - %n hubungan aktif ke jaringan Bitcoin + %n koneksi aktif ke jaringan Bitcoin No block source available... Sumber blok tidak tersedia... + + Processed %n block(s) of transaction history. + %n blok dari riwayat transaksi diproses. + %n hour(s) %n jam @@ -435,15 +471,15 @@ Last received block was generated %1 ago. - Blok terakhir dibuat %1 lalu. + Blok terakhir yang diterima %1 lalu. Transactions after this will not yet be visible. - Transaksi setelah ini tidak akan ditampilkan + Transaksi setelah ini belum akan terlihat. Error - Gagal + Terjadi sebuah kesalahan Warning @@ -531,7 +567,7 @@ Amount: - Nilai: + Jumlah: Priority: @@ -541,13 +577,17 @@ Fee: Biaya: + + Dust: + Dust: + After Fee: Dengan Biaya: Change: - Uang Kembali: + Kembalian: (un)select all @@ -555,7 +595,7 @@ Tree mode - mode pohon + Tree mode List mode @@ -563,7 +603,15 @@ Amount - Nilai + Jumlah + + + Received with label + Diterima dengan label + + + Received with address + Diterima dengan alamat Date @@ -571,7 +619,7 @@ Confirmations - Konfirmasi-konfirmasi + Konfirmasi Confirmed @@ -591,19 +639,19 @@ Copy amount - Salin nilai + Salin jumlah Copy transaction ID - Menyalinkan ID transaksi + Salin ID transaksi Lock unspent - Kunci terpakai. + Kunci unspent. Unlock unspent - Membuka kunci terpakai + Buka unspent Copy quantity @@ -625,9 +673,13 @@ Copy priority Salin prioritas + + Copy dust + Salin dust + Copy change - Salin uang kembali + Salin kembalian highest @@ -673,6 +725,22 @@ none tidak satupun + + This label turns red if the transaction size is greater than 1000 bytes. + Label ini akan menjadi merah apabila ukuran transaksi melebihi 1000 bytes. + + + This label turns red if the priority is smaller than "medium". + Label ini akan menjadi merah apabila prioritasnya lebih kecil dari "sedang" + + + This label turns red if any recipient receives an amount smaller than %1. + Label ini akan menjadi merah apabila penerima menerima jumlah yang lebih kecil dari %1. + + + Can vary +/- %1 satoshi(s) per input. + Dapat beragam +/- %1 satoshi per input. + yes ya @@ -683,15 +751,15 @@ This means a fee of at least %1 per kB is required. - Berarti perlu biaya lebih dari %1 untuk setiap kB. + Perlu biaya lebih dari %1 untuk setiap kB. Can vary +/- 1 byte per input. - Boleh berbeda +/- 1 byte setiap masukan. + Dapat beragam +/- 1 byte per input. Transactions with higher priority are more likely to get included into a block. - Makin penting transaksinya, makin kemungkinan akan termasuk dalam blok. + Transaksi dengan prioritas lebih tinggi akan lebih cepat dimasukkan kedalam blok. (no label) @@ -699,11 +767,11 @@ change from %1 (%2) - uang kembali dari %1 (%2) + kembalian dari %1 (%2) (change) - (uang kembali) + (kembalian) @@ -718,11 +786,11 @@ The label associated with this address list entry - Label yang terkait dengan daftar alamat yang dimasukkan ini + Label yang terkait dengan daftar alamat The address associated with this address list entry. This can only be modified for sending addresses. - Alamat yang terkait dengan entri buku alamat ini. Hanya dapat diubah untuk alamat pengirim. + Alamat yang terkait dengan daftar alamat. Hanya dapat diubah untuk alamat pengirim. &Address @@ -773,15 +841,15 @@ Directory already exists. Add %1 if you intend to create a new directory here. - Direktori masih ada. Tambahlah %1 kalau ingin membuat direktori baru disini. + Direktori masih ada. Tambahlah %1 apabila Anda ingin membuat direktori baru disini. Path already exists, and is not a directory. - Masih ada Path, dan path itu bukan direktori. + Sudah ada path, dan itu bukan direktori. Cannot create data directory here. - Tidak busa membuat direktori untuk data disini. + Tidak bisa membuat direktori data disini. @@ -794,13 +862,17 @@ version versi + + (%1-bit) + (%1-bit) + About Bitcoin Core Mengenai Bitcoin Core Command-line options - pilihan Perintah-baris + Pilihan Command-line Usage: @@ -808,9 +880,37 @@ command-line options - pilihan perintah-baris + pilihan command-line - + + UI Options: + Pilihan UI: + + + Choose data directory on startup (default: %u) + Pilih direktori data saat memulai (default: %u) + + + Set language, for example "de_DE" (default: system locale) + Pilih bahasa, contoh "id_ID" (default: system locale) + + + Start minimized + Start minimized + + + Set SSL root certificates for payment request (default: -system-) + Pilih sertifikat root SSL untuk permintaan pembayaran {default: -system-) + + + Show splash screen on startup (default: %u) + Tampilkan layar kilat saat memulai (default: %u) + + + Reset all settings changes made over the GUI + Reset semua pengaturan yang dibuat dari GUI + + Intro @@ -821,27 +921,43 @@ Welcome to Bitcoin Core. Selamat Datang ke Bitcoin Core + + As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. + Ini adalah pertama kali program ini dijalankan, Anda dapat memilih dimana Bitcoin Core menyimpan data. + + + Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. + Bitcoin Core akan mengunduh dan menyimpan salinan dari block chain Bitcoin. Setidaknya %1GB data akan disimpan di direktori ini, dan akan terus bertambah. Dompet Anda juga akan disimpan di direktori ini. + Use the default data directory - Menggunakan direktori untuk data yang biasa. + Gunakan direktori data default. Use a custom data directory: - Menggunakan direktori data yang dipilih Anda: + Gunakan direktori pilihan Anda: Bitcoin Core Bitcoin Core + + Error: Specified data directory "%1" cannot be created. + Kesalahan: Direktori data "%1" tidak dapat dibuat. + Error - Gagal + Kesalahan %n GB of free space available - %n GB dari ruang yang tersedia + %n GB ruang kosong tersedia. - + + (of %n GB needed) + (dari %n GB yang dibutuhkan) + + OpenURIDialog @@ -850,7 +966,7 @@ Open payment request from URI or file - Buka permintaan pembayaran dari URI atau arsip + Buka permintaan pembayaran dari URI atau data URI: @@ -858,11 +974,11 @@ Select payment request file - Pilihlah arsip permintaan pembayaran + Pilih data permintaan pembayaran Select payment request file to open - Pilihlah arsip permintaan pembayaran yang Anda ingin membuka + Pilih data permintaan pembayaran yang akan dibuka @@ -875,25 +991,53 @@ &Main &Utama + + Size of &database cache + Ukuran cache &database + MB MB + + Number of script &verification threads + Jumlah script &verification threads + + + Accept connections from outside + Terima koneksi dari luar + + + Allow incoming connections + Perbolehkan koneksi masuk + IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) Alamat IP proxy (cth. IPv4: 127.0.0.1 / IPv6: ::1) + + 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. + Minimalisasi aplikasi ketika jendela ditutup. Ketika pilihan ini dipilih, aplikasi akan menutup seluruhnya jika anda memilih Keluar di menu yang tersedia. + + + The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. + Bahasa interface pengguna bisa diubah disini. Pengaturan ini akan memberikan efek setelah Bitcoin Core di-restart. + + + 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 |. + URL pihak ketika (misalnya sebuah block explorer) yang mumcul dalam tab transaksi sebagai konteks menu. %s dalam URL diganti dengan kode transaksi. URL dipisahkan dengan tanda vertikal |. + Third party transaction URLs - Transaksi URLs pihak ketiga + URL transaksi pihak ketiga Active command-line options that override above options: - pilihan perintah-baris aktif menimpa atas pilihan-pilihan: + Pilihan command-line yang aktif menimpa diatas opsi: Reset all client options to default. - Reset setiap pilihan untuk pilihan biasa + Kembalikan semua pengaturan ke awal. &Reset Options @@ -903,6 +1047,18 @@ &Network &Jaringan + + Automatically start Bitcoin Core after logging in to the system. + Buka Bitcoin Core secara otomatis setelah Anda log-in ke sistem Anda. + + + &Start Bitcoin Core on system login + &Mulai Bitcoin Core saat log-in sistem + + + (0 = auto, <0 = leave that many cores free) + (0 = auto, <0 = leave that many cores free) + W&allet D&ompet @@ -913,7 +1069,7 @@ Enable coin &control features - Nyalain cara &pengaturan koin + Perbolehkan fitur &pengaturan koin 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. @@ -931,6 +1087,10 @@ Map port using &UPnP Petakan port dengan &UPnP + + Connect to the Bitcoin network through a SOCKS5 proxy. + Hubungkan ke jaringan Bitcoin melalui SOCKS5 proxy. + Proxy &IP: IP Proxy: @@ -1197,10 +1357,6 @@ General Umum - - Using OpenSSL version - Menggunakan versi OpenSSL - Startup time Waktu nyala @@ -1595,6 +1751,10 @@ Clear all fields of the form. Hapus informasi dari form. + + Dust: + Dust: + Clear &All Hapus &Semua @@ -1691,6 +1851,10 @@ (no label) (tidak ada label) + + Copy dust + Salin dust + Are you sure you want to send? Apakah Anda yakin ingin kirim? diff --git a/src/qt/locale/bitcoin_it.ts b/src/qt/locale/bitcoin_it.ts index d510b1063b854..2f14c420146c6 100644 --- a/src/qt/locale/bitcoin_it.ts +++ b/src/qt/locale/bitcoin_it.ts @@ -949,6 +949,10 @@ Error Errore + + %n GB of free space available + GB di spazio libero disponibile%n GB di spazio disponibile + (of %n GB needed) (di %nGB richiesti)(%n GB richiesti) @@ -1470,10 +1474,6 @@ Per specificare più URL separarli con una barra verticale "|". General Generale - - Using OpenSSL version - Versione OpenSSL in uso - Using BerkeleyDB version Versione BerkeleyDB in uso @@ -2850,7 +2850,7 @@ Per specificare più URL separarli con una barra verticale "|". UnitDisplayStatusBarControl Unit to show amounts in. Click to select another unit. - Unità con cui visualizzare gli importi. Clicca per selezionare un altra unità. + Unità con cui visualizzare gli importi. Clicca per selezionare un'altra unità. @@ -3192,10 +3192,6 @@ Per specificare più URL separarli con una barra verticale "|". Wallet options: Opzioni portamonete: - - Warning: This version is obsolete; upgrade required! - Attenzione: questa versione è obsoleta. Aggiornamento necessario! - You need to rebuild the database using -reindex to change -txindex È necessario ricostruire il database usando -reindex per cambiare -txindex @@ -3292,10 +3288,6 @@ Per specificare più URL separarli con una barra verticale "|". Activating best chain... Attivazione della blockchain migliore... - - Always relay transactions received from whitelisted peers (default: %d) - Trasmetti sempre le transazioni ricevute da peers whitelisted (default: %d) - Attempt to recover private keys from a corrupt wallet.dat on startup Prova a recuperare le chiavi private da un wallet corrotto all'avvio diff --git a/src/qt/locale/bitcoin_it_IT.ts b/src/qt/locale/bitcoin_it_IT.ts new file mode 100644 index 0000000000000..46ad0e9339df0 --- /dev/null +++ b/src/qt/locale/bitcoin_it_IT.ts @@ -0,0 +1,325 @@ + + + AddressBookPage + + Right-click to edit address or label + Click destro per modificare indirizzo o etichetta + + + Create a new address + Crea un nuovo indirizzo + + + &New + nuovo + + + Copy the currently selected address to the system clipboard + copia l'indirizzo selezionato correntemente nella clipboard di sistema + + + &Copy + copia + + + C&lose + chiudi + + + &Copy Address + copia indirizzo + + + Delete the currently selected address from the list + Cancella l'indirizzo attualmente selezionato dalla lista. + + + Export the data in the current tab to a file + Esportare i dati nella scheda corrente in un file + + + &Export + Esporta + + + &Delete + Cancella + + + Choose the address to send coins to + Scegli l'indirizzo a cui inviare denaro + + + Choose the address to receive coins with + Scegli l'indirizzo con cui ricevere i coin + + + C&hoose + Scegli + + + Sending addresses + Indirizzi mittenti + + + Receiving addresses + Indirizzi destinatari + + + These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. + Questi sono gli indirizzi Bitcoin per l'invio di pagamenti. Controlla sempre la quantità e l'indirizzo di ricezione prima di inviare monete. + + + These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. + Questi sono i tuoi indirizzi Bitcoin per ricevere pagamenti. Si raccomanda di generare un nuovo indirizzo per ogni transazione + + + Copy &Label + copia etichetta + + + &Edit + Modifica + + + Export Address List + Esporta lista degli indirizzi + + + Comma separated file (*.csv) + Contenuto del file separato da virgole (*.csv) + + + Exporting Failed + Esportazione fallita + + + + AddressTableModel + + Label + Etichetta + + + Address + Indirizzo + + + (no label) + (nessuna etichetta) + + + + + AskPassphraseDialog + + Enter passphrase + Invia passphrase + + + New passphrase + Nuova passphrase + + + Repeat new passphrase + Ripeti nuova passphrase + + + Encrypt wallet + Cifra portagoflio + + + This operation needs your wallet passphrase to unlock the wallet. + Questa operazione richiede la passphrase del tuo portafoglio per sbloccare il portafoglio. + + + Unlock wallet + Sblocca portafoglio + + + Decrypt wallet + decifra portafoglio + + + Change passphrase + cambia passphrase + + + Confirm wallet encryption + conferma cifrazione del portagoglio + + + Wallet encrypted + portafoglio cifrato + + + Wallet unlock failed + sblocco portafoglio fallito + + + + BanTableModel + + Banned Until + bannato fino + + + + BitcoinGUI + + &Transactions + Transazioni + + + + ClientModel + + + CoinControlDialog + + (no label) + (nessuna etichetta) + + + + + EditAddressDialog + + + FreespaceChecker + + + HelpMessageDialog + + + Intro + + + OpenURIDialog + + + OptionsDialog + + + OverviewPage + + + PaymentServer + + + PeerTableModel + + + QObject + + + QRImageWidget + + + RPCConsole + + + ReceiveCoinsDialog + + + ReceiveRequestDialog + + Address + Indirizzo + + + Label + Etichetta + + + + RecentRequestsTableModel + + Label + Etichetta + + + (no label) + (nessuna etichetta) + + + + + SendCoinsDialog + + (no label) + (nessuna etichetta) + + + + + SendCoinsEntry + + + ShutdownWindow + + + SignVerifyMessageDialog + + + SplashScreen + + + TrafficGraphWidget + + + TransactionDesc + + + TransactionDescDialog + + + TransactionTableModel + + Label + Etichetta + + + + TransactionView + + Exporting Failed + Esportazione fallita + + + Comma separated file (*.csv) + Contenuto del file separato da virgole (*.csv) + + + Label + Etichetta + + + Address + Indirizzo + + + + UnitDisplayStatusBarControl + + + WalletFrame + + + WalletModel + + + WalletView + + &Export + Esporta + + + Export the data in the current tab to a file + Esportare i dati nella scheda corrente in un file + + + + bitcoin-core + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_ja.ts b/src/qt/locale/bitcoin_ja.ts index 4344fd0436323..06fd27fa161a5 100644 --- a/src/qt/locale/bitcoin_ja.ts +++ b/src/qt/locale/bitcoin_ja.ts @@ -1473,10 +1473,6 @@ General 一般 - - Using OpenSSL version - 使用中の OpenSSL のバージョン - Using BerkeleyDB version 使用中のBerkleyDBバージョン @@ -2979,6 +2975,18 @@ Accept connections from outside (default: 1 if no -proxy or -connect) 外部からの接続を許可 (初期値: -proxy または -connect を使用していない場合は1) + + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. + -fallbackfee が高すぎます!これは手数料の推定機能が利用できない場合に支払うトランザクション手数料です。 + + + A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s) + 十分なデータが蓄積されていない場合に手数料推定機能が利用する手数料レート (%s/kB) (デフォルト: %s) + + + Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d) + トランザクションの中継を行っていない場合でも、ホワイトリストのピアから受け取った中継トランザクションは受け取るようにする (デフォルト: %d) + Bind to given address and always listen on it. Use [host]:port notation for IPv6 指定のアドレスへバインドし、その上で常にリスンします。IPv6 は [ホスト名]:ポート番号 と表記します @@ -2995,6 +3003,10 @@ Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) ウォレットの取引を変更する際にコマンドを実行 (cmd の %s は TxID に置換される) + + Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) + ホワイトリストのピアから受け取ったトランザクションに関しては、たとえローカルの中継ポリシーに違反しているとしても中継を行うようにする (デフォルト: %d) + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) スクリプト検証スレッドを設定 (%uから%dの間, 0 = 自動, <0 = たくさんのコアを自由にしておく, 初期値: %d) @@ -3011,6 +3023,10 @@ Unable to bind to %s on this computer. Bitcoin Core is probably already running. このコンピュータの %s にバインドすることができません。おそらく Bitcoin Core は既に実行されています。 + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + サポートされていない引数 -whitelistalwaysrelay は無視されました。-whitelistrelay または -whitelistforcerelay を利用してください + Use UPnP to map the listening port (default: 1 when listening and no -proxy) リスン ポートの割当に UPnP を使用 (初期値: リスン中および-proxyが指定されていない場合は1) @@ -3027,6 +3043,10 @@ Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. 警告: ネットワークは完全に同意しないみたいです。マイナーは何かの問題を経験してるみたいなんです。 + + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + 警告: 未知のバージョンのブロックが採掘されました。未知のルールが導入された可能性があります + Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. 警告: ピアーと完全に同意しないみたいです!アップグレードは必要かもしれません、それとも他のノードはアップグレードは必要かもしれません。 @@ -3047,6 +3067,10 @@ <category> can be: <category>は以下の値を指定できます: + + Append comment to the user agent string + ユーザエージェント文字列にコメントを + Block creation options: ブロック作成オプション: @@ -3092,6 +3116,10 @@ Enable publish raw transaction in <address> <address> に対し、生トランザクションの公開を有効にする + + Enable transaction replacement in the memory pool (default: %u) + メモリプール内のトランザクションの置換を有効化する (デフォルト: %u) + Error initializing block database ブロック データベースの初期化中にエラー @@ -3128,10 +3156,22 @@ Invalid -onion address: '%s' 無効な -onion アドレス:'%s' + + Invalid amount for -fallbackfee=<amount>: '%s' + 不正な額 -fallbackfee=<amount>: '%s' + Keep the transaction memory pool below <n> megabytes (default: %u) トランザクションのメモリ・プールの総量を <n> メガバイト以下に維持する (初期値: %u) + + Location of the auth cookie (default: data dir) + 認証クッキーの場所 (デフォルト: ) + + + Minimum bytes per sigop in transactions we relay and mine (default: %u) + 中継や採掘を行ってもよい、sigopあたりの最小バイト数 (デフォルト: %u) + Not enough file descriptors available. 使用可能なファイルディスクリプタが不足しています。 @@ -3140,6 +3180,10 @@ Only connect to nodes in network <net> (ipv4, ipv6 or onion) <net> (ipv4, ipv6 または onion) ネットワーク内のノードだけに接続する + + Print version and exit + バージョンを表示し終了 + Prune cannot be configured with a negative value. 剪定値は負の値に設定できません。 @@ -3196,10 +3240,6 @@ Wallet options: ウォレットオプション: - - Warning: This version is obsolete; upgrade required! - 警告: このバージョンはサポートされません。アップグレードが必要です! - You need to rebuild the database using -reindex to change -txindex -txindex を変更するには -reindex を使用してデータベースを再構築する必要があります @@ -3296,10 +3336,6 @@ Activating best chain... 最優良のチェインを有効化しています... - - Always relay transactions received from whitelisted peers (default: %d) - ホワイトリストにあるピアから受け取ったトランザクションを常にリレーする (初期値: %d) - Attempt to recover private keys from a corrupt wallet.dat on startup 起動時に壊れた wallet.dat から秘密鍵を復旧することを試す @@ -3464,6 +3500,10 @@ Warning 警告 + + Warning: unknown new rules activated (versionbit %i) + 警告: 未知の新しいルールが有効化されました (バージョンビット %i) + Whether to operate in a blocks only mode (default: %u) ブロック限定モードにおいて動作を行うかどうか (初期値: %u) diff --git a/src/qt/locale/bitcoin_ka.ts b/src/qt/locale/bitcoin_ka.ts index 11c73ec76794b..1a072d1df116b 100644 --- a/src/qt/locale/bitcoin_ka.ts +++ b/src/qt/locale/bitcoin_ka.ts @@ -1111,10 +1111,6 @@ General საერთო - - Using OpenSSL version - OpenSSL-ის ვერსია - Startup time სტარტის დრო diff --git a/src/qt/locale/bitcoin_ko_KR.ts b/src/qt/locale/bitcoin_ko_KR.ts index ce48ce249fffc..34aeafcd5ca94 100644 --- a/src/qt/locale/bitcoin_ko_KR.ts +++ b/src/qt/locale/bitcoin_ko_KR.ts @@ -11,7 +11,7 @@ &New - 새 항목(N) + 새 항목(&N) Copy the currently selected address to the system clipboard @@ -19,11 +19,11 @@ &Copy - 복사 + 복사(&C) C&lose - 닫기 (L) + 닫기(&L) &Copy Address @@ -39,11 +39,11 @@ &Export - &내보내기 + 내보내기(&E) &Delete - &삭제 + 삭제(&D) Choose the address to send coins to @@ -55,7 +55,7 @@ C&hoose - 선택하기 (H) + 선택하기(&H) Sending addresses @@ -67,7 +67,7 @@ These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - 비트코인을 받는 계좌 주소입니다. 코인을 보내기 전에 잔고와 받는 주소를 항상 확인하세요. + 비트코인을 보내는 계좌 주소입니다. 코인을 보내기 전에 잔고와 받는 주소를 항상 확인하세요. These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. @@ -75,11 +75,11 @@ Copy &Label - 라벨 복사 + 라벨 복사(&L) &Edit - 편집& + 편집(&E) Export Address List @@ -167,6 +167,10 @@ Are you sure you wish to encrypt your wallet? 지갑 암호화를 허용하시겠습니까? + + Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. + 비트코인 코어는 암호화 과정을 마무리 하기 위해 종료됩니다. 당신의 지갑을 암호화하는 것이 여러분의 컴퓨터에 해를 끼치는 프로그램으로부터 여러분의 비트코인을 완전히 보호해주지는 못한다는 사실을 기억하십시오. + 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. 중요: 본인 지갑파일에서 만든 예전 백업들은 새로 생성한 암호화 된 지갑 파일로 교체됩니다. 보안상 이유로 이전에 암호화 하지 않은 지갑 파일 백업은 사용할 수 없게 되니 빠른 시일 내로 새로 암호화 된 지갑을 사용하시기 바랍니다. @@ -179,6 +183,10 @@ Wallet encrypted 지갑 암호화 완료 + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. + 지갑에 새로운 비밀문구를 입력하세요.<br/>비밀문구를 <b>열 개 이상의 무작위 글자</b> 혹은 <b>여덟개 이상의 단어로<b> 정하세요. + Enter the old passphrase and new passphrase to the wallet. 지갑의 기존 암호와 새로운 암호를 입력해주세요. @@ -189,7 +197,7 @@ Wallet encryption failed due to an internal error. Your wallet was not encrypted. - 지갑 암호화는 내부 에러로 인해 실패했습니다. 당신의 지갑은 암호화 되지 않았습니다. + 지갑 암호화는 내부 오류로 인해 실패했습니다. 당신의 지갑은 암호화 되지 않았습니다. The supplied passphrases do not match. @@ -214,12 +222,20 @@ BanTableModel - + + IP/Netmask + IP주소/넷마스크 + + + Banned Until + 다음과 같은 상황이 될 때까지 계정 정지됩니다. + + BitcoinGUI Sign &message... - 메시지 서명&... + 메시지 서명(&M)... Synchronizing with network... @@ -227,7 +243,7 @@ &Overview - &개요 + 개요(&O) Node @@ -239,7 +255,7 @@ &Transactions - &거래 + 거래(&T) Browse transaction history @@ -251,11 +267,11 @@ Quit application - 적용 중단 + 어플리케이션 종료 About &Qt - Qt 정보(&Q) + &Qt 정보 Show information about Qt @@ -263,31 +279,31 @@ &Options... - &옵션 + 옵션(&O) &Encrypt Wallet... - 지갑 암호화&... + 지갑 암호화(&E)... &Backup Wallet... - 지갑 백업&... + 지갑 백업(&B)... &Change Passphrase... - 암호문 변경&... + 암호문 변경(&C)... &Sending addresses... - &주소 보내는 중 + 보내는 주소(&S) &Receiving addresses... - & 주소 받는 중 + 받는 주소(&R) Open &URI... - URI&열기... + &URI 열기... Bitcoin Core client @@ -315,7 +331,7 @@ &Debug window - 디버그 창& + 디버그 창(&D) Open debugging and diagnostic console @@ -323,7 +339,7 @@ &Verify message... - 메시지 확인&... + 메시지 확인(&V)... Bitcoin @@ -367,15 +383,15 @@ &File - &파일 + 파일(&F) &Settings - &설정 + 설정(&S) &Help - &도움말 + 도움말(&H) Tabs toolbar @@ -391,7 +407,11 @@ &About Bitcoin Core - &비트코인 코어 소개 + 비트코인 코어 소개(&A) + + + Modify configuration options for Bitcoin Core + 비트코인 코어에 대한 설정을 수정합니다. Show the list of used sending addresses and labels @@ -407,16 +427,24 @@ &Command-line options - 명령어-라인 옵션 + 명령줄 옵션(&C) Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - 사용할 수 있는 비트코인 명령어 옵션 목록을 가져오기 위해 Bitcoin-Qt 도움말 메시지를 표시합니다. + 사용할 수 있는 비트코인 명령줄 옵션 목록을 가져오기 위해 Bitcoin-Qt 도움말 메시지를 표시합니다. + + + %n active connection(s) to Bitcoin network + 비트코인 네트워크에 %n개의 연결이 활성화되어 있습니다. No block source available... 사용 가능한 블록이 없습니다... + + Processed %n block(s) of transaction history. + %n 블럭 만큼의 거래 기록이 처리됨. + %n hour(s) %n시간 @@ -575,7 +603,15 @@ Amount - 거래량 + 거래액 + + + Received with label + 입금과 함께 수신된 라벨 + + + Received with address + 입금과 함께 수신된 주소 Date @@ -599,11 +635,11 @@ Copy label - 표 복사하기 + 라벨 복사하기 Copy amount - 거래량 복사 + 거래액 복사 Copy transaction ID @@ -637,6 +673,14 @@ Copy priority 우선도 복사 + + Copy dust + 더스트 복사 + + + Copy change + 잔돈 복사 + highest 아주 높음 @@ -681,6 +725,22 @@ none 없음 + + This label turns red if the transaction size is greater than 1000 bytes. + 이 라벨은 1000바이트 이상의 거래가 이루어지면 붉게 변합니다. + + + This label turns red if the priority is smaller than "medium". + 이 라벨은 우선순위가 "보통" 이하인 경우 붉게 변합니다. + + + This label turns red if any recipient receives an amount smaller than %1. + 이 라벨은 수령인이 받은 액수가 잔고의 %1보다 작으면 붉게 변합니다. + + + Can vary +/- %1 satoshi(s) per input. + 입력마다 +/- %1 사토시가 변할 수 있습니다. + yes @@ -691,7 +751,11 @@ This means a fee of at least %1 per kB is required. - 이 의미는 수수료가 최소한 %1 per 키로바이트 필요합니다 + 이 뜻은 최소한 1kB 당 %1의 수수료가 필요하다는 의미입니다. + + + Can vary +/- 1 byte per input. + 입력마다 +/- 1 바이트가 변할 수 있습니다. Transactions with higher priority are more likely to get included into a block. @@ -699,13 +763,17 @@ (no label) - (표 없음) + (라벨 없음) change from %1 (%2) ~로부터 변경 %1 (%2) - + + (change) + (잔돈) + + EditAddressDialog @@ -714,15 +782,19 @@ &Label - &표 + 라벨(&L) The label associated with this address list entry 현재 선택된 주소 필드의 제목입니다. + + The address associated with this address list entry. This can only be modified for sending addresses. + 본 주소록 입력은 주소와 연계되었습니다. 이것은 보내는 주소들에서만 변경될수 있습니다. + &Address - &주소 + 주소(&A) New receiving address @@ -754,7 +826,7 @@ New key generation failed. - 새로운 키 생성이 실패하였습니다 + 새로운 키 생성이 실패하였습니다. @@ -810,7 +882,35 @@ command-line options 명령줄 옵션 - + + UI Options: + UI 옵션: + + + Choose data directory on startup (default: %u) + 실행시 데이터 폴더 선택하기 (기본값: %u) + + + Set language, for example "de_DE" (default: system locale) + "ko_KR"와 같이 언어를 설정하십시오 (기본값: 시스템 로캘) + + + Start minimized + 최소화된 상태에서 시작 + + + Set SSL root certificates for payment request (default: -system-) + 지불 요청을 위한 SSL 루트 인증서 설정 (기본값: -system-) + + + Show splash screen on startup (default: %u) + 실행시 시작화면 보기 (기본값: %u) + + + Reset all settings changes made over the GUI + GUI를 통해 수정된 모든 설정을 초기화 + + Intro @@ -819,7 +919,7 @@ Welcome to Bitcoin Core. - 비트코인 코어에 오신것을 환영합니. + 비트코인 코어에 오신것을 환영합니다. As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. @@ -841,11 +941,23 @@ Bitcoin Core 비트코인 코어 + + Error: Specified data directory "%1" cannot be created. + 오류: "%1" 지정한 데이터 디렉토리를 생성할 수 없습니다. + Error 오류 - + + %n GB of free space available + %n GB 사용가능 + + + (of %n GB needed) + (%n GB가 필요) + + OpenURIDialog @@ -873,7 +985,7 @@ OptionsDialog Options - 선택들 + 환경설정 &Main @@ -881,7 +993,7 @@ Size of &database cache - 데이터베이스 캐시 크기 + 데이터베이스 캐시 크기(&D) MB @@ -889,7 +1001,7 @@ Number of script &verification threads - 스크립트 인증 쓰레드의 개수 + 스크립트 인증 쓰레드의 개수(&V) Accept connections from outside @@ -901,7 +1013,19 @@ IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) - 프록시 아이피 주소(예. IPv4:127.0.0.1 / IPv6: ::1) + 프록시 아이피 주소 (예. IPv4:127.0.0.1 / IPv6: ::1) + + + 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. + 창을 닫으면 종료 대신 트레이로 보내기. 이 옵션을 활성화하면 메뉴에서 종료를 선택한 후에만 어플리케이션이 종료됩니다. + + + The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. + 사용자 인터페이스 언어를 여기서 설정할 수 있습니다. 이 설정은 Bitcoin Core를 다시 시작할 때 적용됩니다. + + + 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 |. + 서드-파티 URLs (예. 블록 탐색기)는 거래 탭의 컨텍스트 메뉴에 나타납니다. URL의 %s는 트랜잭션 해시값으로 대체됩니다. 여러 URLs는 수직 바 | 에서 나누어 집니다. Third party transaction URLs @@ -909,7 +1033,7 @@ Active command-line options that override above options: - 명령어 라인 옵션을 활성화해서 옵션을 우회하시오 + 명령줄 옵션 활성화는 위의 옵션들을 대체합니다: Reset all client options to default. @@ -923,9 +1047,21 @@ &Network 네트워크(&N) + + Automatically start Bitcoin Core after logging in to the system. + 시스템 로그인 후 자동으로 Bitcoin Core를 실행합니다. + + + &Start Bitcoin Core on system login + 시스템 로그인 후 Bitcoin Core 시작(&S) + + + (0 = auto, <0 = leave that many cores free) + (0 = 자동, <0 = 지정된 코어 개수만큼 사용 안함) + W&allet - 지갑 + 지갑(&A) Expert @@ -933,19 +1069,23 @@ Enable coin &control features - 코인 상세 제어기능을 활성화합니다 - &C + 코인 상세 제어기능을 활성화합니다 (&C) + + + 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. + 검증되지 않은 잔돈 쓰기를 비활성화하면 트랜잭션이 적어도 1회 이상 검증되기 전까지 그 트랜잭션의 거스름돈은 사용할 수 없습니다. 이는 잔액 계산 방법에도 영향을 미칩니다. &Spend unconfirmed change - &확인되지 않은 돈을 쓰다 + 검증되지 않은 잔돈 쓰기 (&S) Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled. - 라우터의 비트코인 클라이언트 포트를 자동으로 엽니다. 라우터에서 UPnP를 지원하고 활성화 했을 경우에만 동작합니다. + 라우터에서 Bitcoin 클라이언트 포트를 자동적으로 엽니다. 라우터에서 UPnP를 지원하고 활성화 했을 경우에만 동작합니다. Map port using &UPnP - 사용중인 UPnP 포트 매핑(&U) + 사용중인 &UPnP 포트 매핑 Connect to the Bitcoin network through a SOCKS5 proxy. @@ -953,11 +1093,11 @@ &Connect through SOCKS5 proxy (default proxy): - SOCKS5 프록시를 거쳐 연결합니다 (기본값 프록시): + SOCKS5 프록시를 거쳐 연결합니다(&C) (기본 프록시): Proxy &IP: - 프록시 IP(&I): + 프록시 &IP: &Port: @@ -967,6 +1107,14 @@ Port of the proxy (e.g. 9050) 프록시의 포트번호입니다(예: 9050) + + Used for reaching peers via: + 피어에 연결하기 위해 사용된 방법: + + + Shows, if the supplied default SOCKS5 proxy is used to reach peers via this network type. + 이 SOCK5 프록시를 통과해 피어와 접속한 네트워크 유형이 표시됩니다. + IPv4 IPv4 @@ -979,6 +1127,14 @@ Tor Tor + + Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services. + Tor 서비스를 경유하여 비트코인 네트워크에 연결하기 위해 분리된 SOCKS5 프록시를 사용. + + + Use separate SOCKS5 proxy to reach peers via Tor hidden services: + Tor 서비스를 이용하여 피어에게 연결하기 위해 분리된 SOCKS5 프록시 사용 + &Window 창(&W) @@ -1039,6 +1195,10 @@ Client restart required to activate changes. 변경 사항을 적용하기 위해서는 프로그램이 종료 후 재시작되어야 합니다. + + Client will be shut down. Do you want to proceed? + 클라이언트가 종료됩니다, 계속 진행하시겠습니까? + This change would require a client restart. 이 변경 사항 적용을 위해 프로그램 재시작이 필요합니다. @@ -1056,7 +1216,7 @@ 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. - 표시한 정보가 오래된 것 같습니다. 비트코인 네트워크에 연결하고 난 다음에 지갑을 자동으로 동기화 하지만, 아직 과정이 끝나지는 않았습니다. + 표시된 정보가 오래된 것 같습니다. 비트코인 네트워크에 연결하고 난 다음에 지갑을 자동으로 동기화 하지만, 아직 과정이 끝나지는 않았습니다. Watch-only: @@ -1102,11 +1262,27 @@ Your current balance in watch-only addresses 모니터링 지갑의 현재 잔액 + + Spendable: + 사용가능: + Recent transactions 최근 거래 - + + Unconfirmed transactions to watch-only addresses + 모니터링 지갑의 검증되지 않은 트랜잭션 + + + Mined balance in watch-only addresses that has not yet matured + 모니터링 지갑의 채굴된 잔액 중 숙성되지 않은 것 + + + Current total balance in watch-only addresses + 모니터링 지갑의 현재 잔액 + + PaymentServer @@ -1117,13 +1293,25 @@ Invalid payment address %1 잘못된 지불 주소입니다 %1 + + Payment request rejected + 지불 요청이 거부됨 + + + Payment request network doesn't match client network. + 지급 요청 네트워크가 클라이언트 네트워크와 일치되지 않습니다. + + + Payment request is not initialized. + 지불 요청이 초기화 되지 않았습니다. + Requested payment amount of %1 is too small (considered dust). 요청한 금액 %1의 양이 너무 적습니다. (스팸성 거래로 간주) Payment request error - 지불 요청 애러 + 지불 요청 오류 Cannot start bitcoin: click-to-pay handler @@ -1133,21 +1321,45 @@ Payment request fetch URL is invalid: %1 대금 청구서의 URL이 올바르지 않습니다: %1 + + URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. + URI의 파싱에 문제가 발생했습니다. 잘못된 비트코인 주소나 URI 파라미터 구성에 오류가 존재할 수 있습니다. + Payment request file handling 지불이 파일 처리를 요청합니다 + + Payment request file cannot be read! This can be caused by an invalid payment request file. + 지불 요청 파일을 읽을 수 없습니다. 이것은 잘못된 지불 요청 파일에 의해 발생하는 오류일 수 있습니다. + + + Payment request expired. + 지불 요청이 만료됨. + Unverified payment requests to custom payment scripts are unsupported. 임의로 변경한 결제 스크립트 기반의 대금 청구서 양식은 검증되기 전까지는 지원되지 않습니다. + + Invalid payment request. + 잘못된 지불 요청. + Refund from %1 %1 으로부터의 환불 + + Payment request %1 is too large (%2 bytes, allowed %3 bytes). + 지불 요청 %1은 너무 큽니다 (%2 바이트, %3 바이트까지 허용됩니다). + Error communicating with %1: %2 - %1과 소통하는데 애러: %2 + %1과 소통하는데 오류: %2 + + + Payment request cannot be parsed! + 지불요청을 처리할 수 없습니다. Bad response from server %1 @@ -1159,22 +1371,38 @@ Network request error - 네트워크 요청 애러 + 네트워크 요청 오류 PeerTableModel - + + User Agent + 유저 에이전트 + + + Node/Service + 노드/서비스 + + + Ping Time + Ping 시간 + + QObject Amount - 거래량 + 거래액 Enter a Bitcoin address (e.g. %1) 비트코인 주소를 입력하기 (예. %1) + + %1 d + %1 일 + %1 h %1 시간 @@ -1187,6 +1415,10 @@ %1 s %1 초 + + None + 없음 + N/A 없음 @@ -1212,7 +1444,7 @@ PNG Image (*.png) - PNG 이미지(*.png) + PNG 이미지 (*.png) @@ -1231,7 +1463,7 @@ &Information - 정보 + 정보(&I) Debug window @@ -1241,13 +1473,9 @@ General 일반 - - Using OpenSSL version - 사용중인 OpenSSL 버전 - Using BerkeleyDB version - 사용중인 BerkeleyDB 버전 + 사용 중인 BerkeleyDB 버전 Startup time @@ -1273,6 +1501,22 @@ Current number of blocks 현재 블럭 수 + + Memory Pool + 메모리 풀 + + + Current number of transactions + 현재 트랜잭션 수 + + + Memory usage + 메모리 사용량 + + + Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. + 현재의 데이터폴더에서 비트코인 디버그 파일을 엽니다. 용량이 큰 로그 파일은 몇 초가 걸릴 수 있습니다. + Received 받음 @@ -1283,12 +1527,80 @@ &Peers - &피어 + 피어(&P) + + + Banned peers + 차단된 피어 + + + Select a peer to view detailed information. + 자세한 정보를 보려면 피어를 선택하세요. + + + Whitelisted + 화이트리스트에 포함 + + + Direction + 방향 Version 버전 + + Starting Block + 시작된 블록 + + + Synced Headers + 동기화된 헤더 + + + Synced Blocks + 동기화된 블록 + + + User Agent + 유저 에이전트 + + + Services + 서비스 + + + Ban Score + 밴 스코어 + + + Connection Time + 접속 시간 + + + Last Send + 마지막으로 보낸 시간 + + + Last Receive + 마지막으로 받은 시간 + + + Ping Time + Ping 시간 + + + The duration of a currently outstanding ping. + 현재 진행중인 PING에 걸린 시간. + + + Ping Wait + Ping 대기 + + + Time Offset + 시간 오프셋 + Last block time 최종 블럭 시각 @@ -1303,11 +1615,11 @@ &Network Traffic - &네트워크 트래픽 + 네트워크 트래픽(&N) &Clear - &지우기 + 지우기(&C) Totals @@ -1333,6 +1645,38 @@ Clear console 콘솔 초기화 + + &Disconnect Node + 끊긴 노드(&D) + + + Ban Node for + 추방된 노드: + + + 1 &hour + 1시간(&H) + + + 1 &day + 1일(&D) + + + 1 &week + 1주(&W) + + + 1 &year + 1년(&Y) + + + &Unban Node + 노드 추방 취소(&U) + + + Welcome to the Bitcoin Core RPC console. + 비트코인 RPC 콘솔에 오신걸 환영합니다 + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. 기록을 찾아보려면 위 아래 화살표 키를, 화면을 지우려면 <b>Ctrl-L</b>키를 사용하십시오. @@ -1357,20 +1701,52 @@ %1 GB %1 기가바이트 - + + (node id: %1) + (노드 ID: %1) + + + via %1 + %1 경유 + + + never + 없음 + + + Inbound + 인바운드 + + + Outbound + 아웃바운드 + + + Yes + + + + No + 아니오 + + + Unknown + 알수없음 + + ReceiveCoinsDialog &Amount: - &거래량: + 거래액(&A): &Label: - 라벨: + 라벨(&L): &Message: - &메시지: + 메시지(&M): Reuse one of the previously used receiving addresses. Reusing addresses has security and privacy issues. Do not use this unless re-generating a payment request made before. @@ -1378,7 +1754,11 @@ R&euse an existing receiving address (not recommended) - 현재의 수취용 주소를 재사용합니다만 권장하지는 않습니다. (R&) + 현재의 수취용 주소를 재사용하기(&E) (권장하지 않습니다) + + + 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. + 지불 요청에 첨부되는 선택가능한 메시지 입니다. 이 메세지는 요청이 열릴 때 표시될 것 입니다. 메모: 이 메시지는 비트코인 네트워크로 전송되지 않습니다. An optional label to associate with the new receiving address. @@ -1408,6 +1788,10 @@ &Request payment 지불 요청(&R) + + Show the selected request (does the same as double clicking an entry) + 선택된 요청을 표시하기 (더블 클릭으로 항목을 표시할 수 있습니다) + Show 보기 @@ -1422,7 +1806,7 @@ Copy label - 표 복사하기 + 라벨 복사하기 Copy message @@ -1430,7 +1814,7 @@ Copy amount - 거래량 복사 + 거래액 복사 @@ -1469,11 +1853,11 @@ Amount - 거래량 + 거래액 Label - + 라벨 Message @@ -1481,7 +1865,7 @@ Resulting URI too long, try to reduce the text for label / message. - URI 결과가 너무 길음, 표/메세지의 글을 줄이도록 하세요. + URI 결과가 너무 길음, 라벨/메세지의 글을 줄이도록 하세요. Error encoding URI into QR Code. @@ -1496,7 +1880,7 @@ Label - + 라벨 Message @@ -1504,7 +1888,7 @@ Amount - 거래량 + 거래액 (no label) @@ -1516,7 +1900,7 @@ (no amount) - (거래량 없음) + (거래액 없음) @@ -1551,7 +1935,7 @@ Amount: - 거래량: + 거래액: Priority: @@ -1569,6 +1953,10 @@ Change: 체인지: + + If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address. + 이 기능이 활성화되면 거스름돈 주소가 공란이거나 무효인 경우, 거스름돈은 새롭게 생성된 주소로 송금됩니다. + Custom change address 주소변경 @@ -1577,17 +1965,77 @@ Transaction Fee: 거래 수수료: + + Choose... + 선택 하기... + + + collapse fee-settings + 수수료 설정 접기 + + + per kilobyte + 킬로바이트 당 + + + If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte. + 사용자 정의 수수료가 1000사토시로 지정된 경우 트랜잭션의 크기가 250바이트 일 경우 1킬로바이트당 250사토시만 지불되지만 "최소 수수료"에선 1000사토시가 지불됩니다. 1킬로바이트가 넘는 트랜잭션인 경우 어떠한 경우에든 1킬로바이트 기준으로 지불됩니다. + + + Hide + 숨기기 + + + total at least + 최소 수수료 + + + Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process. + 블록의 용량보다 트랜잭션의 용량이 작은 경우에는 최소한의 수수료만으로도 충분합니다. 그러나 비트코인 네트워크의 처리량보다 더 많은 트랜잭션 요구는 영원히 검증이 안 될 수도 있습니다. + + + (read the tooltip) + (툴팁을 읽어보세요) + Recommended: 권장: + + Custom: + 사용자 정의: + + + (Smart fee not initialized yet. This usually takes a few blocks...) + (Smart fee가 아직 초기화되지 않았습니다. 블록 분석이 완료될 때 까지 기다려주십시오...) + + + Confirmation time: + 승인 시간: + + + normal + 일반 + + + fast + 빠름 + + + Send as zero-fee transaction if possible + 가능한 경우 수수료 없이 보내기 + + + (confirmation may take longer) + (거래 검증이 오래 걸릴 수 있습니다) + Send to multiple recipients at once 다수의 수령인들에게 한번에 보내기 Add &Recipient - 수령인 추가하기 + 수령인 추가하기(&R) Clear all fields of the form. @@ -1627,7 +2075,7 @@ Copy amount - 거래량 복사 + 거래액 복사 Copy fee @@ -1645,6 +2093,14 @@ Copy priority 우선도 복사 + + Copy change + 잔돈 복사 + + + Total Amount %1 + 총 액수 %1 + or 또는 @@ -1670,18 +2126,46 @@ 거래가 거부되었습니다. 몇몇 코인들이 지갑에서 이미 사용된 경우, 예를 들어 코인을 이미 사용한 wallet.dat를 복사해서 사용한 경우 지금 지갑에 기록이 안되있어 이런 일이 생길 수 있습니다. - Warning: Invalid Bitcoin address - 경고: 잘못된 비트코인주소입니다 + A fee higher than %1 is considered an absurdly high fee. + %1 보다 높은 수수료는 너무 높은 수수료 입니다. - (no label) - (표 없음) + Payment request expired. + 지불 요청이 만료됨. - Warning: Unknown change address - 경고: 알려지지 않은 주소변경입니다 + Pay only the required fee of %1 + 오직 %1 만의 수수료를 지불하기 - + + Estimated to begin confirmation within %n block(s). + %n 블록 안에 거래검증이 시작 될것으로 예상합니다. + + + The recipient address is not valid. Please recheck. + 수령인 주소가 정확하지 않습니다. 재확인 바랍니다 + + + Duplicate address found: addresses should only be used once each. + 두개 이상의 주소입니다: 한번에 하나의 주소에만 작업할 수 있습니다. + + + Warning: Invalid Bitcoin address + 경고: 잘못된 비트코인주소입니다 + + + (no label) + (라벨 없음) + + + Warning: Unknown change address + 경고: 알려지지 않은 주소변경입니다 + + + Copy dust + 더스트 복사 + + Are you sure you want to send? 정말로 보내시겠습니까? @@ -1694,19 +2178,19 @@ SendCoinsEntry A&mount: - 금액: + 금액(&M): Pay &To: - 지급&수신: + 송금할 대상(&T) : Enter a label for this address to add it to your address book - 당신의 주소록에 이 주소를 추가하기 위하여 표를 입역하세요 + 주소록에 추가하려면 라벨을 입력하세요 &Label: - 표: + 라벨(&L) Choose previously used address @@ -1714,7 +2198,11 @@ This is a normal payment. - 평균지급입니다 + 이것은 정상적인 지불입니다. + + + The Bitcoin address to send the payment to + 이 비트코인 주소로 송금됩니다 Alt+A @@ -1722,7 +2210,7 @@ Paste address from clipboard - 클립보드로 부터 주소를 붙이세요 + 클립보드로 부터 주소 붙여넣기 Alt+P @@ -1730,15 +2218,31 @@ Remove this entry - 항목을 지우시오 + 항목을 지웁니다 + + + 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. + 수수료가 송금되는 금액에서 공제됩니다. 수령자는 금액 필드에서 입력한 금액보다 적은 금액을 전송받게 됩니다. 받는 사람이 여러 명인 경우 수수료는 균등하게 나누어집니다. + + + S&ubtract fee from amount + 송금액에서 수수료 공제(&U) Message: 메시지: + + This is an unauthenticated payment request. + 인증 되지 않은 지급 요청입니다. + + + This is an authenticated payment request. + 인증 된 지급 요청 입니다. + Enter a label for this address to add it to the list of used addresses - 사용된 주소 목록에 새 주소를 추가하기 위해 제목을 입력합니다. + 사용된 주소 목록에 새 주소를 추가하기 위해 라벨 이름을 입력해 주세요. 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. @@ -1757,7 +2261,7 @@ ShutdownWindow Bitcoin Core is shutting down... - 비트코인코어가 닫아지고 있습니다 + Bitcoin Core이 종료 중입니다... Do not shut down the computer until this window disappears. @@ -1774,6 +2278,14 @@ &Sign Message 메시지 서명(&S) + + 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. + 여러분 자신을 증명하기 위해 주소를 첨가하고 서명할 수 있습니다. 피싱 공격으로 말미암아 여러분의 서명을 통해 속아 넘어가게 할 수 있으므로, 서명하지 않은 모든 모호한 요소를 주의하십시오. 조항들이 완전 무결한지 확인 후 동의하는 경우에만 서명하십시오. + + + The Bitcoin address to sign the message with + 메세지를 서명한 비트코인 주소 + Choose previously used address 이전에 사용한 주소를 선택하십시오 @@ -1784,7 +2296,7 @@ Paste address from clipboard - 클립보드로 부터 주소를 붙이세요 + 클립보드로 부터 주소를 복사하기 Alt+P @@ -1822,6 +2334,14 @@ &Verify Message 메시지 검증(&V) + + 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! + 메시지를 검증하기 위해 아래 칸에 각각 지갑 주소와 메시지, 전자서명을 입력하세요. (메시지 원본의 띄어쓰기, 들여쓰기, 행 나눔 등이 정확하게 입력되어야 하므로 원본을 복사해서 입력하세요) 이 기능은 메시지 검증이 주 목적이며, 네트워크 침입자에 의해 변조되지 않도록 전자서명 해독에 불필요한 시간을 소모하지 마세요. + + + The Bitcoin address the message was signed with + 메세지의 서명에 사용된 비트코인 주소 + Verify the message to ensure it was signed with the specified Bitcoin address 정확한 비트코인주소가 입력됬는지 메시지를 확인하시오 @@ -1935,6 +2455,10 @@ Status 상태 + + , broadcast through %n node(s) + %n 노드를 거쳐 전파합니다. + Date 날짜 @@ -1959,6 +2483,10 @@ own address 자신의 주소 + + watch-only + 모니터링 지갑 + label 라벨 @@ -1967,6 +2495,10 @@ Credit 예금 + + matures in %n more block(s) + %n개 블럭 후에 코인 숙성이 완료됩니다. + not accepted 허용되지 않는다 @@ -1975,13 +2507,21 @@ Debit 차변 + + Total debit + 총 출금액 + + + Total credit + 총 입금액 + Transaction fee 송금 수수료 Net amount - 총액 + 총 거래액 Message @@ -2017,7 +2557,7 @@ Amount - 거래량 + 거래액 true @@ -2031,6 +2571,10 @@ , has not been successfully broadcast yet . 아직 성공적으로 통보하지 않음 + + Open for %n more block(s) + %n 개의 추가 블록을 읽습니다. + unknown 알수없음 @@ -2061,13 +2605,17 @@ Immature (%1 confirmations, will be available after %2) 충분히 숙성되지 않은 상태 (%1 승인, %2 후에 사용 가능합니다) + + Open for %n more block(s) + %n 개의 추가 블록을 읽습니다. + Open until %1 %1 까지 열림 Confirmed (%1 confirmations) - 확인됨(%1 확인됨) + 확인됨 (%1 확인됨) This block was not received by any other nodes and will probably not be accepted! @@ -2083,7 +2631,7 @@ Label - + 라벨 Unconfirmed @@ -2117,13 +2665,17 @@ Mined 채굴 + + watch-only + 모니터링 지갑 + (n/a) (없음) Transaction status. Hover over this field to show number of confirmations. - 거래상황. 마우스를 올리면 승인횟수가 표시됩니다. + 거래상황. 마우스를 올리면 검증횟수가 표시됩니다. Date and time that the transaction was received. @@ -2133,6 +2685,14 @@ Type of transaction. 거래의 종류. + + Whether or not a watch-only address is involved in this transaction. + 이 트랜잭션에 모니터링 지갑를 포함할지의 여부입니다. + + + User-defined intent/purpose of the transaction. + 트랜잭션에 대한 사용자 정의 intent/purpose + Amount removed from or added to balance. 변경된 잔고. @@ -2194,7 +2754,7 @@ Min amount - 최소 거래량 + 최소 거래액 Copy address @@ -2202,19 +2762,23 @@ Copy label - 표 복사하기 + 라벨 복사하기 Copy amount - 거래량 복사 + 거래액 복사 Copy transaction ID 거래 아이디 복사 + + Copy raw transaction + 로우 트랜잭션 복사 + Edit label - 표 수정하기 + 라벨 수정하기 Show transaction details @@ -2234,7 +2798,7 @@ There was an error trying to save the transaction history to %1. - %1으로 거래 기록을 저장하는데 애러가 있었습니다. + %1으로 거래 기록을 저장하는데 오류가 있었습니다. Exporting Successful @@ -2262,7 +2826,7 @@ Label - + 라벨 Address @@ -2283,7 +2847,11 @@ UnitDisplayStatusBarControl - + + Unit to show amounts in. Click to select another unit. + 거래액을 표시하는 단위. 클릭해서 다른 단위를 선택할 수 있습니다. + + WalletFrame @@ -2302,7 +2870,7 @@ WalletView &Export - &내보내기 + 내보내기(&E) Export the data in the current tab to a file @@ -2355,30 +2923,130 @@ Accept command line and JSON-RPC commands 명령줄과 JSON-RPC 명령 수락 + + If <category> is not supplied or if <category> = 1, output all debugging information. + <category>가 제공되지 않거나 <category> = 1 인 경우, 모든 디버깅 정보를 출력 + + + Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s) + 하나의 지갑 트랜잭션에서의 총 수수료(%s)의 최대치; 너무 낮게 설정하면 큰 트랜잭션이 중지 됩니다 (기본값: %s) + + + Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. + 컴퓨터의 날짜와 시간이 올바른지 확인하십시오! 시간이 잘못되면 비트코인은 제대로 동작하지 않습니다. + + + Prune configured below the minimum of %d MiB. Please use a higher number. + 블록 축소가 최소치의 %d MiB 밑으로 설정되어 있습니다. 더 높은 값을 사용해 보세요. + + + Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node) + 블록 축소: 마지막 지갑 동기화 지점이 축소된 데이터보다 과거의 것 입니다. -reindex가 필요합니다 (정지된 노드의 경우 모든 블록체인을 재다운로드합니다) + + + Reduce storage requirements by pruning (deleting) old blocks. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, >%u = target size in MiB to use for block files) + 오래된 블록을 제거(축소)하여 디스크 용량을 줄입니다. 이 모드는 -txindex 와 -rescan 과 호환되지 않습니다. 경고: 이 모드를 취소하면 모든 블록체인을 다시 다운로드 받아야 합니다. (기본값:0 = 블록 축소 비활성화, >%u = 블록파일에 사용할 용량을 MiB단위로 지정) + + + Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again. + 블록 축소 모드에서는 재검색이 불가능 합니다. -reindex 명령을 사용해서 모든 블록체인을 다시 다운로드 해야 합니다. + + + Error: A fatal internal error occurred, see debug.log for details + 에러: 치명적인 내부 오류가 발생했습니다, 자세한 내용은 debug.log 를 확인해주세요. + + + Fee (in %s/kB) to add to transactions you send (default: %s) + 송금 거래시 추가되는 수수료 (%s/kB) (기본값: %s) + + + Pruning blockstore... + 블록 데이터를 축소 중입니다.. + Run in the background as a daemon and accept commands 데몬으로 백그라운드에서 실행하고 명령을 허용 + + Unable to start HTTP server. See debug log for details. + HTTP 서버를 시작할 수 없습니다. 자세한 사항은 디버그 로그를 확인 하세요. + Accept connections from outside (default: 1 if no -proxy or -connect) 외부 접속을 승인합니다 + + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. + -fallbackfee은 너무 높습니다! 이것은 수수료 예측을 이용할 수 없을 때 지불되는 트랜잭션 수수료입니다. + + + A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s) + 충분한 데이터가 축적되지 않은 상태에서의 수수료 추정 기능이 사용하는 수수료 비율(%s/kB) (기본값: %s) + + + Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d) + 트랜잭션의 중계를 하지 않더라도 화이트 리스트에 포함된 피어에서 받은 트랜잭션은 중계하기 (기본값: %d) + Bind to given address and always listen on it. Use [host]:port notation for IPv6 선택된 주소로 고정하며 항상 리슨(Listen)합니다. IPv6 프로토콜인 경우 [host]:port 방식의 명령어 표기법을 사용합니다. + + Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup + 시작시 모든 지갑 트랜잭션을 삭제하고 -rescan을 통하여 블록체인만 복구합니다. + + + Distributed under the MIT software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>. + MIT 소프트웨어 라이센스에 따라 배포됩니다. 동봉된 파일 혹은 <http://www.opensource.org/licenses/mit-license.php>를 참조하세요. + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) 지갑 거래가 바뀌면 명령을 실행합니다.(%s 안의 명령어가 TxID로 바뀝니다) + + Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) + 피어들이 로컬 중계 정책을 위반하더라도 화이트 리스트에 포함된 피어인경우 강제로 중계하기 (기본값: %d) + + + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) + 스크립트 인증 스레드의 갯수 설정 (%u-%d, 0 = 자동, <0 = 지정된 코어 개수만큼 사용 안함, 기본값: %d) + + + 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 + 블록 데이터베이스에 미래의 블록이 포함되어 있습니다. 이것은 사용자의 컴퓨터의 날짜와 시간이 올바르게 설정되어 있지 않을때 나타날 수 있습니다. 만약 사용자의 컴퓨터의 날짜와 시간이 올바르다고 확신할 때에만 블록 데이터 베이스의 재구성을 하십시오 + This is a pre-release test build - use at your own risk - do not use for mining or merchant applications 이 빌드 버전은 정식 출시 전 테스트의 목적이며, 예기치 않은 위험과 오류가 발생할 수 있습니다. 채굴과 상점용 소프트웨어로 사용하는 것을 권하지 않습니다. + + Unable to bind to %s on this computer. Bitcoin Core is probably already running. + 이 컴퓨터의 %s에 바인딩 할 수 없습니다. 아마도 비트코인이 실행중인 것 같습니다. + + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + 지원하지 않는 인수 -whitelistalwaysrelay 는 무시됩니다, -whitelistrelay 나 -whitelistforcerelay 를 사용해 주세요. + + + Use UPnP to map the listening port (default: 1 when listening and no -proxy) + 리슨(Listen) 포트를 할당하기 위해 UPnP 사용 (기본값: 열려있거나 -proxy 옵션을 사용하지 않을 시 1) + + + WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) + 경고: 비정상적으로 많은 블록이 생성되고 있습니다. %d 블록은 마지막 %d에 수신되었습니다 (%d 예측됨) + + + WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) + 경고: 네트워크 연결을 확인해 주세요. %d 블록은 마지막 %d에 수신되었습니다 (%d 예측됨) + Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. 경고 : 모든 네트워크가 동의해야 하나, 일부 채굴자들에게 문제가 있는 것으로 보입니다. + + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + 경고: 알려지지 않은 버전의 블록이 채굴되었습니다. 알려지지 않은 규칙이 적용되었을 가능성이 있습니다. + Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. 경고: 현재 비트코인 버전이 다른 네트워크 참여자들과 동일하지 않는 것 같습니다. 당신 또는 다른 참여자들이 동일한 비트코인 버전으로 업그레이드 할 필요가 있습니다. @@ -2387,6 +3055,22 @@ Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. 경고 : wallet.dat가 손상되어 데이터가 복구되었습니다. 원래의 wallet.dat 파일은 %s 후에 wallet.{timestamp}.bak 이름으로 저장됩니다. 잔액과 거래 내역이 정확하지 않다면 백업 파일로 부터 복원해야 합니다. + + Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. + 설정된 넷마스크 혹은 IP 주소로 화이트리스트에 포함된 피어에 접속합니다. 이 설정은 복수로 지정 할 수 있습니다. + + + -maxmempool must be at least %d MB + -maxmempool은 최소한 %d MB가 필요합니다 + + + <category> can be: + <category> 지정 가능: + + + Append comment to the user agent string + 사용자 에이전트 문자열에 코멘트 첨부 + Block creation options: 블록 생성 옵션: @@ -2415,6 +3099,26 @@ Do you want to rebuild the block database now? 블락 데이터베이스를 다시 생성하시겠습니까? + + Enable publish hash block in <address> + <address>에 대한 해시 블록 공개 활성화 + + + Enable publish hash transaction in <address> + <address>에 대한 해시 트랙잭션 공개 활성화 + + + Enable publish raw block in <address> + <address>에 대한 로우 블록 공개 활성화 + + + Enable publish raw transaction in <address> + <address>에 대한 로우 트랜잭션 공개 활성화 + + + Enable transaction replacement in the memory pool (default: %u) + 메모리 풀(pool) 내의 트랜잭션 치환(replacement) 활성화 (기본값: %u) + Error initializing block database 블록 데이터베이스를 초기화하는데 오류 @@ -2451,10 +3155,42 @@ Invalid -onion address: '%s' 잘못된 -onion 주소입니다: '%s' + + Invalid amount for -fallbackfee=<amount>: '%s' + 유효하지 않은 금액 -fallbackfee=<amount>: '%s' + + + Keep the transaction memory pool below <n> megabytes (default: %u) + 트랜잭션 메모리 풀의 용량을 <n>메가바이트 아래로 유지하기 (기본값: %u) + + + Location of the auth cookie (default: data dir) + 인증 쿠키의 위치 (기본값: data dir) + + + Minimum bytes per sigop in transactions we relay and mine (default: %u) + 중계 및 채굴을 할 때 트랜잭션에서의 sigop 당 데이터의 최소 크기 (기본값: %u) + Not enough file descriptors available. 사용 가능한 파일 디스크립터-File Descriptor-가 부족합니다. + + Only connect to nodes in network <net> (ipv4, ipv6 or onion) + 오직 <net> 네트워크로 로만 접속 (IPv4, IPv6 혹은 onion) + + + Print version and exit + 버전 출력후 종료 + + + Prune cannot be configured with a negative value. + 블록 축소는 음수로 설정할 수 없습니다. + + + Prune mode is incompatible with -txindex. + 블록 축소 모드는 -txindex와 호환되지 않습니다. + Set database cache size in megabytes (%d to %d, default: %d) 데이터베이스 케시 크기를 메가바이트로 설정(%d 부터 %d, 기본값: %d) @@ -2467,6 +3203,26 @@ Specify wallet file (within data directory) 데이터 폴더 안에 지갑 파일을 선택하세요. + + Unsupported argument -benchmark ignored, use -debug=bench. + 지원하지 않는 인수 -benchmark 은 무시됩니다, -debug=bench 형태로 사용하세요. + + + Unsupported argument -debugnet ignored, use -debug=net. + 지원하지 않는 인수 -debugnet 은 무시됩니다, -debug=net 형태로 사용하세요. + + + Unsupported argument -tor found, use -onion. + 지원하지 않는 인수 -tor를 찾았습니다. -onion를 사용해주세요. + + + Use UPnP to map the listening port (default: %u) + 리슨(Listen) 포트를 할당하기 위해 UPnP 사용 (기본값: %u) + + + User Agent comment (%s) contains unsafe characters. + 사용자 정의 코멘트 (%s)에 안전하지 못한 글자가 포함되어 있습니다. + Verifying blocks... 블록 검증중... @@ -2487,26 +3243,138 @@ You need to rebuild the database using -reindex to change -txindex -txindex를 바꾸기 위해서는 -reindex를 사용해서 데이터베이스를 재구성해야 합니다. + + 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 + 특정 소스에서의 JSON-RPC 연결 허가. 유효한 <ip> 같은 하나의 IP주소 (예 1.2.3.4), 네트워크/넷마스크 (예 1.2.3.4/255.255.255.0) 혹은 네트워크/CIDR (예 1.2.3.4/24). 이 옵션은 복수로 설정 할 수 있습니다. + + + Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6 + 선택된 주소로 고정하여 화이트리스트에 포함된 피어에 접속합니다. IPv6 프로토콜인 경우 [host]:port 방식의 명령어 표기법을 사용합니다. + + + Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces) + 선택된 주소로 고정하여 JSON-RPC 연결을 리슨(Listen)합니다. IPv6 프로토콜인 경우 [host]:port 방식의 명령어 표기법을 사용합니다. 이 옵션은 복수로 지정 할수 있습니다. (기본값: 모든 인터페이스에 고정) + Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. 데이터 디렉토리 %s에 락을 걸 수 없었습니다. 비트코인 코어가 이미 실행 중인 것으로 보입니다. + + Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) + umask 077 대신 시스템 기본 퍼미션으로 새 파일을 만듭니다 (지갑 기능이 비활성화 상태에서만 유효합니다) + + + Discover own IP addresses (default: 1 when listening and no -externalip or -proxy) + 자신의 주소를 탐색 (기본값: 열려있거나 -externalip 나 -proxy 옵션이 없으면 1) + + + Error: Listening for incoming connections failed (listen returned error %s) + 오류: 들어오는 연결을 리슨(Listen)하는데 실패했습니다 (오류 리턴 %s) + Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message) 이 사항과 관련있는 경고가 발생하거나 아주 긴 포크가 발생했을 때 명령어를 실행해 주세요. (cmd 명령어 목록에서 %s는 메시지로 대체됩니다) + + Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s) + 해당 금액(%s/kB) 보다 적은 수수료는 중계, 채굴, 트랜잭션 생성에서 수수료 면제로 간주됩니다 (기본값: %s) + + + If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u) + paytxfee가 설정되어 있지 않다면 평균 n 블록안에 승인이 이루어지도록 충분한 수수료가 포함됩니다 (기본값: %u) + + + Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions) + 유효하지 않은 금액 -maxtxfee=<amount>: '%s' (트랜잭션이 막히는 상황을 방지하게 위해 적어도 %s 의 중계 수수료를 지정해야 합니다) + + + Maximum size of data in data carrier transactions we relay and mine (default: %u) + 중계 및 채굴을 할 때 데이터 운송 트랜잭션에서 데이터의 최대 크기 (기본값: %u) + + + Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect) + DNS lookup를 통해 피어 주소에 대한 쿼리 보내기 (기본값: 1 -connect 예외) + + + Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u) + 인증정보를 프록시 연결마다 무작위로 합니다. 이는 Tor 스트림을 격리시킬 수 있습니다 (기본값: %u) + Set maximum size of high-priority/low-fee transactions in bytes (default: %d) 최대 크기를 최우선으로 설정 / 바이트당 최소 수수료로 거래(기본값: %d) + + Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) + 코인 생성에 대한 스레드 갯수 설정 (-1 = 모든 코어, 기본값: %d) + + + The transaction amount is too small to send after the fee has been deducted + 거래액이 수수료를 지불하기엔 너무 작습니다 + + + This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard. + 이 프로그램에는 OpenSSL 툴킷<https://www.openssl.org/> 사용 목적으로 개발한 OpenSSL 프로젝트를 포함하고 있으며, 암호화 프로그램은 Eric Young이, UPnP 프로그램은 Thomas Bernard가 작성했습니다. + + + 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 + 화이트리스트에 포함된 피어는 이미 메모리풀에 포함되어 있어도 DoS 추방이 되지 않으며 그들의 트랜잭션이 항상 중계됩니다, 이는 예를 들면 게이트웨이에서 유용합니다. + + + You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain + 축소 모드를 해제하고 데이터베이스를 재구성 하기 위해 -reindex를 사용해야 합니다. 이 명령은 모든 블록체인을 다시 다운로드 할 것 입니다. + + + (default: %u) + (기본값: %u) + + + Accept public REST requests (default: %u) + 공개 REST 요청을 허가 (기본값: %u) + + + Activating best chain... + 최적 블록 체인을 활성화하는중... + + + Attempt to recover private keys from a corrupt wallet.dat on startup + 시작시 망가진 wallet.dat에서 개인키 복원을 시도 + + + Automatically create Tor hidden service (default: %d) + Tor서비스를 자동적으로 생성 (기본값: %d) + Cannot resolve -whitebind address: '%s' -whitebind 주소를 확인할 수 없습니다: '%s' + + Connect through SOCKS5 proxy + SOCK5 프록시를 통해 연결 + + + Copyright (C) 2009-%i The Bitcoin Core Developers + Copyright (C) 2009-%i The Bitcoin Core Developers + + + Error loading wallet.dat: Wallet requires newer version of Bitcoin Core + wallet.dat 불러오기 오류: 최신 버전의 Bitcoin Core이 필요합니다. + + + Error reading from database, shutting down. + 블록 데이터베이스를 불러오는데 오류가 발생하였습니다, 종료됩니다. + + + Imports blocks from external blk000??.dat file on startup + 외부 blk000??.dat 파일에서 블록을 가져오기 + Information 정보 + + Initialization sanity check failed. Bitcoin Core is shutting down. + 무결성 확인 초기화가 실패했습니다. Bitcoin Core가 종료됩니다. + Invalid amount for -maxtxfee=<amount>: '%s' -maxtxfee=<amount>에 대한 양이 잘못되었습니다: '%s' @@ -2519,14 +3387,54 @@ Invalid amount for -mintxfee=<amount>: '%s' 최저 거래 수수료가 부족합니다. -mintxfee=<amount>: '%s' + + Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) + 유효하지 않은 금액 -paytxfee=<amount>: "%s" (최소 %s 이상이어야 됨) + + + Invalid netmask specified in -whitelist: '%s' + 유효하지 않은 넷마스크가 -whitelist: '%s" 를 통해 지정됨 + + + Keep at most <n> unconnectable transactions in memory (default: %u) + 최대 <n>개의 연결할 수 없는 트랜잭션을 메모리에 저장 (기본값: %u) + + + Need to specify a port with -whitebind: '%s' + -whitebind를 이용하여 포트를 지정해야 합니다: '%s" + + + Node relay options: + Node 중계 옵션: + RPC server options: RPC 서버 설정 + + Rebuild block chain index from current blk000??.dat files on startup + 현재의 blk000??.dat 파일들로부터 블록체인 색인을 재구성합니다. + + + Receive and display P2P network alerts (default: %u) + P2P 네트워크 알림을 수신후 표시합니다 (기본값: %u) + + + Reducing -maxconnections from %d to %d, because of system limitations. + 시스템 한계로 인하여 -maxconnections를 %d 에서 %d로 줄였습니다. + + + Rescan the block chain for missing wallet transactions on startup + 시작시 누락된 지갑 트랜잭션에 대해 블록 체인을 다시 검색 합니다 + Send trace/debug info to console instead of debug.log file 추적오류 정보를 degug.log 자료로 보내는 대신 콘솔로 보내기 + + Send transactions as zero-fee transactions if possible (default: %u) + 가능한 경우 수수료 없이 트랜잭션 보내기 (기본값: %u) + Show all debugging options (usage: --help -help-debug) 모든 디버그 설정 보기(설정: --help -help-debug) @@ -2539,30 +3447,70 @@ Signing transaction failed 거래를 서명하는것을 실패하였습니다. + + The transaction amount is too small to pay the fee + 거래액이 수수료를 지불하기엔 너무 작습니다 + + + This is experimental software. + 이 소프트웨어는 시험적입니다. + + + Tor control port password (default: empty) + Tor 관리 포트 암호 (기본값: 공란) + + + Tor control port to use if onion listening enabled (default: %s) + onion 열림이 활성화시 Tor 관리 포트 사용 (기본값: %s) + Transaction amount too small - 거래량이 너무 적습니다 + 거래액이 너무 적습니다 Transaction amounts must be positive - 거래량은 반드시 정수여야합니다. + 거래액은 반드시 정수여야합니다. + + + Transaction too large for fee policy + 수수료 정책에 비해 트랜잭션이 너무 큽니다 Transaction too large 너무 큰 거래 + + Upgrade wallet to latest format on startup + 시작시 지갑 포멧을 최신으로 업그레이드 합니다 + Username for JSON-RPC connections JSON-RPC 연결에 사용할 사용자 이름 + + Wallet needed to be rewritten: restart Bitcoin Core to complete + 지갑을 새로 써야 합니다: 완료하기 위하여 Bitcoin Core을 다시 시작하십시오. + Warning 경고 + + Warning: unknown new rules activated (versionbit %i) + 경고: 알려지지 않은 새로운 규칙이 활성화되었습니다. (버전비트 %i) + + + Whether to operate in a blocks only mode (default: %u) + 블록 전용 모드로 동작할지 여부 (기본값: %u) + Zapping all transactions from wallet... 지갑의 모든거래내역 건너뛰기... + + ZeroMQ notification options: + ZeroMQ 알림 옵션: + wallet.dat corrupt, salvage failed wallet.dat 파일이 손상되었고 복구가 실패하였습니다. @@ -2589,16 +3537,160 @@ Error loading wallet.dat: Wallet corrupted - wallet.dat 불러오기 에러: 지갑 오류 + wallet.dat 불러오기 오류: 지갑 오류 + + + (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) + (1 = 트랜잭션의 메타 데이터를 유지함 예. 계좌정보 와 지불 요구 정보, 2 = 트랜잭션 메타 데이터 파기) + + + -maxtxfee is set very high! Fees this large could be paid on a single transaction. + -maxtxfee값이 너무 큽니다! 하나의 트랜잭션에 너무 큰 수수료가 지불 됩니다. + + + -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + -paytxfee값이 너무 큽니다! 이 값은 송금할때 지불할 송금 수수료입니다. + + + Do not keep transactions in the mempool longer than <n> hours (default: %u) + 메모리 풀에 있는 트랜잭션 기록을 <n>시간 후 부터는 유지하지 않기 (기본값: %u) + + + Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + 경고 : wallet.dat 파일을 읽는 중 오류가 발생했습니다. 주소 키는 모두 정확하게 로딩되었으나 거래 데이터와 주소록 필드에서 누락이나 오류가 존재할 수 있습니다. + + + Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) + 해당 금액(%s/kB) 보다 적은 수수료는 수수료 면제로 간주됩니다.(기본값: %s) + + + How thorough the block verification of -checkblocks is (0-4, default: %u) + -checkblocks을 통한 블록 점검 (0-4, 기본값: %u) + + + Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u) + getrawtransaction를 RPC CALL를 통해 완전한 트랜잭션 인덱스 유지 (기본값: %u) + + + Number of seconds to keep misbehaving peers from reconnecting (default: %u) + 이상행동을 하는 네트워크 참여자들을 다시 연결시키는데 걸리는 시간 (기본값: %u) + + + Output debugging information (default: %u, supplying <category> is optional) + 디버그 정보 출력 (기본값: %u, <category> 제공은 선택입니다) + + + Support filtering of blocks and transaction with bloom filters (default: %u) + 블룸필터를 통해 블록과 트랜잭션 필터링 지원 (기본값: %u) + + + Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments. + 네트워크 버전 문자 (%i)의 길이가 최대길이 (%i)를 초과합니다. UA코멘트의 갯수나 길이를 줄이세요. + + + Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d) + 아웃바운드 트래픽을 설정된 목표치 이하로 유지하기 (24시간당 MiB기준), 0 = 무제한 (기본값: %d) + + + Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported. + 지원하지 않는 인수 -socks를 찾았습니다. 설정된 SOCKS의 버전은 더이상 사용할 수 없으며, SOCK5 프록시만을 지원합니다. + + + Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s) + Tor 서비스를 이용하여 피어에게 연결하기 위해 분리된 SOCKS5 프록시를 사용 (기본값: %s) + + + Username and hashed password for JSON-RPC connections. The field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A canonical python script is included in share/rpcuser. This option can be specified multiple times + JSON-RPC 연결시 사용자 이름과 해시화된 암호문. <userpw> 필드는 <USERNAME>:<SALT>$<HASH> 포멧으로 구성되어 있습니다. 전형적 파이썬 스크립트에선 share/rpcuser가 포함되어 있습니다. 이 옵션은 여러번 지정할 수 있습니다. + + + Always query for peer addresses via DNS lookup (default: %u) + DNS lookup을 통해 항상 피어주소에 대한 쿼리 보내기 (기본값: %u) Error loading wallet.dat - wallet.dat 불러오기 에러 + wallet.dat 불러오기 오류 + + + Generate coins (default: %u) + 코인 생성 (기본값: %u) + + + How many blocks to check at startup (default: %u, 0 = all) + 시작시 점검할 블록 갯수 (기본값: %u, 0 = 모두) + + + Include IP addresses in debug output (default: %u) + 디버그 출력에 IP주소 포함하기 (기본값: %u) Invalid -proxy address: '%s' 잘못된 -proxy 주소입니다: '%s' + + Listen for JSON-RPC connections on <port> (default: %u or testnet: %u) + JSON-RPC 연결을 <port>포트로 받기 (기본값: %u 혹은 테스트넷: %u) + + + Listen for connections on <port> (default: %u or testnet: %u) + <port>포트로 연결 받기 (기본값: %u 혹은 테스트넷: %u) + + + Maintain at most <n> connections to peers (default: %u) + 피어 연결수를 <n>개로 유지 (기본값: %u) + + + Make the wallet broadcast transactions + 지갑 브로드캐스트 트랜잭션을 만들기 + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: %u) + 접속별 최대 수신 버퍼. <n> × 1000바이트 (기본값: %u) + + + Maximum per-connection send buffer, <n>*1000 bytes (default: %u) + 접속별 최대 전송 버퍼. <n> × 1000바이트 (기본값: %u) + + + Prepend debug output with timestamp (default: %u) + 디버그 출력에 타임 스탬프 포함하기 (기본값: %u) + + + Relay and mine data carrier transactions (default: %u) + 데이터 운송 트랜잭션을 중계 및 채굴 (기본값: %u) + + + Relay non-P2SH multisig (default: %u) + 비 P2SH 다중서명을 중계 (기본값: %u) + + + Set key pool size to <n> (default: %u) + 키 풀 사이즈를 <n> 로 설정 (기본값: %u) + + + Set the number of threads to service RPC calls (default: %d) + 원격 프로시져 호출 서비스를 위한 쓰레드 개수를 설정 (기본값 : %d) + + + Specify configuration file (default: %s) + 설정파일 지정 (기본값: %s) + + + Specify connection timeout in milliseconds (minimum: 1, default: %d) + 밀리초 단위로 연결 제한시간을 설정 (최소값: 1, 기본값: %d) + + + Specify pid file (default: %s) + pid 파일 지정 (기본값: %s) + + + Spend unconfirmed change when sending transactions (default: %u) + 트랜잭션을 보낼 때 검증되지 않은 잔돈 쓰기 (기본값: %u) + + + Threshold for disconnecting misbehaving peers (default: %u) + 이상행동 네트워크 참여자의 연결을 차단시키기 위한 한계치 (기본값: %u) + Unknown network specified in -onlynet: '%s' -onlynet에 지정한 네트워크를 알 수 없습니다: '%s' diff --git a/src/qt/locale/bitcoin_la.ts b/src/qt/locale/bitcoin_la.ts index e3dcd505feaf9..b11027d1ee275 100644 --- a/src/qt/locale/bitcoin_la.ts +++ b/src/qt/locale/bitcoin_la.ts @@ -667,10 +667,6 @@ Debug window Fenestra Debug - - Using OpenSSL version - Utens OpenSSL versione - Startup time Tempus initiandi diff --git a/src/qt/locale/bitcoin_lt.ts b/src/qt/locale/bitcoin_lt.ts index b98976dfeaec2..873a6939b7a5c 100644 --- a/src/qt/locale/bitcoin_lt.ts +++ b/src/qt/locale/bitcoin_lt.ts @@ -33,6 +33,10 @@ Delete the currently selected address from the list Ištrinti pasirinktą adresą iš sąrašo + + Export the data in the current tab to a file + Eksportuoti informaciją iš dabartinės lentelės į failą + &Export &Eksportuoti @@ -45,6 +49,10 @@ Choose the address to send coins to Pasirinkite adresą kuriam siūsite monetas + + Choose the address to receive coins with + Pasirinkite adresą su kuriuo gauti monetas + C&hoose P&asirinkti @@ -57,6 +65,14 @@ Receiving addresses Gaunami adresai + + These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. + Tai yra jūsų Bitcoin adresai mokėjimų siuntimui. Visada patikrinkite siunčiamą sumą ir gavėjo adresą prieš siųsdami monetas. + + + These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. + Tai yra jūsų Bitcoin adresai mokėjimų gavimui. Rekomenduojame naudoti naujus gavimo adresus kiekvienai tranzakcijai. + Copy &Label Kopijuoti ž&ymę @@ -907,10 +923,6 @@ Debug window Derinimo langas - - Using OpenSSL version - Naudojama OpenSSL versija - Startup time Paleidimo laikas @@ -1690,6 +1702,10 @@ &Export &Eksportuoti + + Export the data in the current tab to a file + Eksportuoti informaciją iš dabartinės lentelės į failą + Backup Wallet Backup piniginę diff --git a/src/qt/locale/bitcoin_lv_LV.ts b/src/qt/locale/bitcoin_lv_LV.ts index e01d4c812c5fa..5a59184b0cef8 100644 --- a/src/qt/locale/bitcoin_lv_LV.ts +++ b/src/qt/locale/bitcoin_lv_LV.ts @@ -1079,10 +1079,6 @@ General Vispārējs - - Using OpenSSL version - Izmantotā OpenSSL versija - Startup time Sākuma laiks diff --git a/src/qt/locale/bitcoin_nb.ts b/src/qt/locale/bitcoin_nb.ts index 9236ac86fe12d..94e02f8900ed1 100644 --- a/src/qt/locale/bitcoin_nb.ts +++ b/src/qt/locale/bitcoin_nb.ts @@ -1473,10 +1473,6 @@ General Generelt - - Using OpenSSL version - Bruker OpenSSL versjon - Using BerkeleyDB version Bruker BerkeleyDB versjon @@ -3195,10 +3191,6 @@ Wallet options: Valg for lommebok: - - Warning: This version is obsolete; upgrade required! - Advarsel: Denne versjonen er utdatert; oppgradering er påkrevd! - You need to rebuild the database using -reindex to change -txindex Du må gjenoppbygge databasen med å bruke -reindex for å endre -txindex @@ -3295,10 +3287,6 @@ Activating best chain... Aktiverer beste kjede... - - Always relay transactions received from whitelisted peers (default: %d) - Alltid videresend transaksjoner mottatt fra hvitlistede noder (standardverdi: %d) - Attempt to recover private keys from a corrupt wallet.dat on startup Forsøk å berge private nøkler fra en korrupt wallet.dat ved oppstart diff --git a/src/qt/locale/bitcoin_nl.ts b/src/qt/locale/bitcoin_nl.ts index 8457a9ab50265..fe29959abf5ba 100644 --- a/src/qt/locale/bitcoin_nl.ts +++ b/src/qt/locale/bitcoin_nl.ts @@ -7,7 +7,7 @@ Create a new address - Maak een nieuw adres + Maak een nieuw adres aan &New @@ -169,7 +169,7 @@ Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Bitcoin Core zal nu afsluiten om het versleutelingsproces te voltooien. Hou er rekening mee dat versleuteling van je portemonnee je niet volledig beschermt tegen diefstal van jouw bitcoins door malware op je computer. + Bitcoin Core zal nu afsluiten om het versleutelingsproces te voltooien. Hou er rekening mee dat versleuteling van uw portemonnee u niet volledig beschermt tegen diefstal van jouw bitcoins door malware op je computer. 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. @@ -1473,10 +1473,6 @@ General Algemeen - - Using OpenSSL version - Gebruikt OpenSSL versie - Using BerkeleyDB version Gebruikt BerkeleyDB versie @@ -2979,6 +2975,18 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Accepteer verbindingen van buitenaf (standaard: 1 als geen -proxy of -connect is opgegeven) + + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. + -fallbackfee is zeer hoog ingesteld! Dit zijn de transactie kosten die u mogelijk betaald wanneer de schattingen niet beschikbaar zijn. + + + A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s) + Een transactietarief (in %s/kB) dat gebruikt wordt als de transactiekosten schatting niet genoeg data heeft. (normaal: %s) + + + Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d) + Accepteer doorgestuurde transacties ontvangen van goedgekeurde peers, ook wanneer je zelf geen transacties doorstuurt (standaard: %d) + Bind to given address and always listen on it. Use [host]:port notation for IPv6 Bind aan opgegeven adres en luister er altijd op. Gebruik [host]:port notatie voor IPv6 @@ -2995,6 +3003,10 @@ Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) Voer opdracht uit zodra een portemonneetransactie verandert (%s in cmd wordt vervangen door TxID) + + Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) + Forceer het doorsturen van transacties van goedgekeurde peers, zelfs wanneer deze niet voldoen aan de lokale doorstuur regels (standaard: %d) + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) Kies het aantal scriptverificatie processen (%u tot %d, 0 = auto, <0 = laat dit aantal kernen vrij, standaard: %d) @@ -3011,6 +3023,10 @@ Unable to bind to %s on this computer. Bitcoin Core is probably already running. Niet in staat om %s te verbinden op deze computer. Bitcoin Core draait waarschijnlijk al. + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + Niet ondersteund argument -whitelistalwaysrelay genegeerd, gebruik -whitelistrelay en/of -whitelistforcerelay. + Use UPnP to map the listening port (default: 1 when listening and no -proxy) Gebruik UPnP om de luisterende poort te mappen (standaard: 1 als er geluisterd worden en geen -proxy is meegegeven) @@ -3027,6 +3043,10 @@ Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Waarschuwing: Het lijkt erop dat het netwerk geen consensus kan vinden! Sommige delvers lijken problemen te ondervinden. + + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + Waarschuwing: Onbekende blok versies worden gemined! Er zijn mogelijk onbekende regels in werking getreden + Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Waarschuwing: Het lijkt erop dat we geen consensus kunnen vinden met onze peers! Mogelijk dient u te upgraden, of andere nodes moeten wellicht upgraden. @@ -3047,6 +3067,10 @@ <category> can be: <categorie> kan zijn: + + Append comment to the user agent string + Voeg commentaar toe aan de user agent string + Block creation options: Blokcreatie-opties: @@ -3091,6 +3115,10 @@ Enable publish raw transaction in <address> Sta toe ruwe transacties te publiceren in <adres> + + Enable transaction replacement in the memory pool (default: %u) + Transactie vervanging inschakelen in het geheugen (standaard: %u) + Error initializing block database Fout bij intialisatie blokkendatabase @@ -3127,10 +3155,22 @@ Invalid -onion address: '%s' Ongeldig -onion adres '%s' + + Invalid amount for -fallbackfee=<amount>: '%s' + Ongeldig bedrag voor -fallbackfee=<bedrag>: '%s' + Keep the transaction memory pool below <n> megabytes (default: %u) De transactiegeheugenpool moet onder de <n> megabytes blijven (standaard: %u) + + Location of the auth cookie (default: data dir) + Locatie van de auth cookie (standaard: data dir) + + + Minimum bytes per sigop in transactions we relay and mine (default: %u) + Minimum aantal bytes dat er per sigop in een transactie gerelayed en gemined worden (standaard: %u) + Not enough file descriptors available. Niet genoeg file descriptors beschikbaar. @@ -3139,6 +3179,10 @@ Only connect to nodes in network <net> (ipv4, ipv6 or onion) Verbind alleen met nodes in netwerk <net> (ipv4, ipv6 of onion) + + Print version and exit + Laat versie zien en sluit af + Prune cannot be configured with a negative value. Snoeien kan niet worden geconfigureerd met een negatieve waarde. @@ -3195,10 +3239,6 @@ Wallet options: Portemonnee instellingen: - - Warning: This version is obsolete; upgrade required! - Waarschuwing: Deze versie is verouderd; upgraden verplicht! - You need to rebuild the database using -reindex to change -txindex Om -txindex te kunnen veranderen dient u de database herbouwen met gebruik van -reindex. @@ -3295,10 +3335,6 @@ Activating best chain... Beste reeks activeren... - - Always relay transactions received from whitelisted peers (default: %d) - Geef transacties altijd door aan goedgekeurde peers (standaard: %d) - Attempt to recover private keys from a corrupt wallet.dat on startup Probeer privésleutels te herstellen van een corrupte wallet.dat bij opstarten @@ -3463,6 +3499,10 @@ Warning Waarschuwing + + Warning: unknown new rules activated (versionbit %i) + Waarschuwing: onbekende nieuwe regels geactiveerd (versionbit %i) + Whether to operate in a blocks only mode (default: %u) Om in alleen een blokmodus te opereren (standaard: %u) diff --git a/src/qt/locale/bitcoin_pam.ts b/src/qt/locale/bitcoin_pam.ts index 233918ff2ba59..c5a0b17e801fe 100644 --- a/src/qt/locale/bitcoin_pam.ts +++ b/src/qt/locale/bitcoin_pam.ts @@ -655,10 +655,6 @@ Debug window I-Debug ing awang - - Using OpenSSL version - Gagamit bersion na ning OpenSSL - Startup time Oras ning umpisa diff --git a/src/qt/locale/bitcoin_pl.ts b/src/qt/locale/bitcoin_pl.ts index 8a8c377480996..ffbacfd4929f4 100644 --- a/src/qt/locale/bitcoin_pl.ts +++ b/src/qt/locale/bitcoin_pl.ts @@ -87,11 +87,11 @@ Comma separated file (*.csv) - CSV (rozdzielany przecinkami) + Pliki (*.csv) rozdzielone przecinkami Exporting Failed - Błąd przy próbie eksportu + Błąd przy próbie eksportowania There was an error trying to save the address list to %1. Please try again. @@ -137,7 +137,7 @@ This operation needs your wallet passphrase to unlock the wallet. - Ta operacja wymaga hasła do portfela ażeby odblokować portfel. + Operacja wymaga hasła portfela, aby go odblokować. Unlock wallet @@ -145,7 +145,7 @@ This operation needs your wallet passphrase to decrypt the wallet. - Ta operacja wymaga hasła do portfela ażeby odszyfrować portfel. + Operacja wymaga hasła portfela, aby go odszyfrować. Decrypt wallet @@ -161,7 +161,7 @@ Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Uwaga: Jeśli zaszyfrujesz swój portfel i zgubisz hasło to <b>STRACISZ WSZYSTKIE SWOJE BITCOIN'Y</b>! + Uwaga: jeśli zaszyfrujesz swój portfel i zgubisz hasło <b>STRACISZ WSZYSTKIE SWOJE BITCOINY</b>! Are you sure you wish to encrypt your wallet? @@ -169,15 +169,15 @@ Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Program Bitcoin Core zamknie się, aby dokończyć proces szyfrowania. Pamiętaj, że szyfrowanie portfela nie zabezpiecza w pełni Twoich bitcoinów przed kradzieżą przez wirusy lub trojany mogące zainfekować Twój komputer. + Program Bitcoin Core zamknie się, aby dokończyć proces szyfrowania. Pamiętaj, że szyfrowanie portfela nie zabezpiecza w pełni twoich bitcoinów przed kradzieżą przez złośliwe oprogramowanie mogące zainfekować twój komputer. 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. - WAŻNE: Wszystkie wykonane wcześniej kopie pliku portfela powinny być zamienione na nowe, szyfrowane pliki. Z powodów bezpieczeństwa, poprzednie kopie nieszyfrowanych plików portfela staną się bezużyteczne jak tylko zaczniesz korzystać z nowego, szyfrowanego portfela. + WAŻNE: Wszystkie wcześniejsze kopie pliku portfela powinny być zamienione na nowe, szyfrowane pliki. Z powodów bezpieczeństwa, poprzednie kopie nieszyfrowanych plików portfela staną się bezużyteczne jak tylko zaczniesz korzystać z nowego, szyfrowanego portfela. Warning: The Caps Lock key is on! - Uwaga: Klawisz Caps Lock jest włączony! + Uwaga: klawisz Caps Lock jest włączony! Wallet encrypted @@ -185,7 +185,7 @@ Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Wprowadź nowe hasło do portfela.<br/>Proszę używać hasła złożonego z <b>10 lub więcej losowych znaków</b> lub <b>ośmiu lub więcej słów.</b> + Wprowadź nowe hasło do portfela.<br/>Proszę używać hasła złożonego z <b>10 lub więcej losowych znaków</b> albo <b>8 lub więcej słów.</b> Enter the old passphrase and new passphrase to the wallet. @@ -224,7 +224,7 @@ BanTableModel IP/Netmask - IP/Maska Sieci + IP / maska podsieci Banned Until @@ -307,7 +307,7 @@ Bitcoin Core client - Rdzeń klienta Bitcoin + Klient Rdzenia Bitcoina Importing blocks from disk... @@ -319,7 +319,7 @@ Send coins to a Bitcoin address - Wyślij monety na adres Bitcoin + Wyślij monety na adres bitcoinowy Backup wallet to another location @@ -359,7 +359,7 @@ Show information about Bitcoin Core - Pokaż informacje o Rdzeniu Bitcoin + Pokaż informacje o Rdzeniu Bitcoina &Show / Hide @@ -371,7 +371,7 @@ Encrypt the private keys that belong to your wallet - Szyfruj klucze prywatne, które są w Twoim portfelu + Szyfruj klucze prywatne, które są w twoim portfelu Sign messages with your Bitcoin addresses to prove you own them @@ -379,7 +379,7 @@ Verify messages to ensure they were signed with specified Bitcoin addresses - Zweryfikuj wiadomość, aby upewnić się, że została podpisana podanym adresem Bitcoin. + Zweryfikuj wiadomość, aby upewnić się, że została podpisana podanym adresem bitcoinowym. &File @@ -399,11 +399,11 @@ Bitcoin Core - Rdzeń Bitcoin + Rdzeń Bitcoina Request payments (generates QR codes and bitcoin: URIs) - Żądaj płatności (generuje kod QR oraz bitcoin URI) + Żądaj płatności (generuje kod QR oraz bitcoinowe URI) &About Bitcoin Core @@ -449,6 +449,10 @@ %n hour(s) %n godzin%n godzin%n godzin + + %n day(s) + dzień%n dni%n dni + %n week(s) %n tygodni%n tygodni%n tygodni @@ -491,7 +495,7 @@ Catching up... - Synchronizuję się... + Trwa synchronizacja… Date: %1 @@ -810,11 +814,11 @@ The entered address "%1" is already in the address book. - Wprowadzony adres "%1" już istnieje w książce adresowej. + Wprowadzony adres «%1» już istnieje w książce adresowej. The entered address "%1" is not a valid Bitcoin address. - Wprowadzony adres "%1" nie jest poprawnym adresem Bitcoin. + Wprowadzony adres «%1"» nie jest poprawnym adresem bitcoinowym. Could not unlock wallet. @@ -852,7 +856,7 @@ HelpMessageDialog Bitcoin Core - Rdzeń Bitcoin + Rdzeń Bitcoina version @@ -888,7 +892,7 @@ Set language, for example "de_DE" (default: system locale) - Wybierz język, na przykład "de_DE" (domyślnie: język systemowy) + Wybierz język, na przykład «de_DE» (domyślnie: język systemowy) Start minimized @@ -915,7 +919,7 @@ Welcome to Bitcoin Core. - Witam w Bitcoin Core + Witaj w Bitcoin Core As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. @@ -923,7 +927,7 @@ Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - Program pobierze i będzie przechowywał kopię łańcucha bloków Bitcoin. W wybranym katalogu musi być przynajmniej %1GB miejsca, a z czasem ilość danych będzie rosła. Portfel będzie przechowywany w tym samym katalogu. + Program pobierze i będzie przechowywał kopię łańcucha bloków bitcoinowych. W wybranym katalogu musi być przynajmniej %1 GB miejsca, a z czasem ilość danych będzie rosła. Portfel będzie przechowywany w tym samym katalogu. Use the default data directory @@ -935,11 +939,11 @@ Bitcoin Core - Rdzeń Bitcoin + Rdzeń Bitcoina Error: Specified data directory "%1" cannot be created. - Błąd: Określony folder danych "%1" nie mógł zostać utworzony. + Błąd: podany folder danych «%1» nie mógł zostać utworzony. Error @@ -1037,7 +1041,7 @@ &Reset Options - Z&resetuj Ustawienia + Z&resetuj ustawienia &Network @@ -1049,7 +1053,7 @@ &Start Bitcoin Core on system login - Uruchamiaj Bitcoin wraz z zalogowaniem do &systemu + Uruchamiaj Bitcoin Core wraz z zalogowaniem do &systemu (0 = auto, <0 = leave that many cores free) @@ -1093,7 +1097,7 @@ Proxy &IP: - Proxy &IP: + &IP proxy: &Port: @@ -1103,6 +1107,10 @@ Port of the proxy (e.g. 9050) Port proxy (np. 9050) + + Used for reaching peers via: + Użyto do połączenia z peerami przy pomocy: + Shows, if the supplied default SOCKS5 proxy is used to reach peers via this network type. Pokazuje, czy wspierane domyślnie proxy SOCKS5 jest używane do łączenia się z peerami w tej sieci @@ -1119,9 +1127,13 @@ Tor Tor + + Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services. + Połącz się z siecią Bitcoin przy pomocy oddzielnego SOCKS5 proxy dla sieci TOR + Use separate SOCKS5 proxy to reach peers via Tor hidden services: - Użyj oddzielnego prozy SOCKS5 aby osiągnąć węzły w ukrytych usługach Tor: + Użyj oddzielnego proxy SOCKS5 aby osiągnąć węzły w ukrytych usługach Tor: &Window @@ -1133,7 +1145,7 @@ &Minimize to the tray instead of the taskbar - &Minimalizuj do paska przy zegarku zamiast do paska zadań + &Minimalizuj do zasobnika systemowego zamiast do paska zadań M&inimize on close @@ -1145,7 +1157,7 @@ User Interface &language: - Język &Użytkownika: + Język &użytkownika: &Unit to show amounts in: @@ -1240,7 +1252,7 @@ Total: - Wynosi ogółem: + Ogółem: Your current total balance @@ -1385,7 +1397,7 @@ Enter a Bitcoin address (e.g. %1) - Wprowadź adres Bitcoin (np. %1) + Wprowadź adres bitcoinowy (np. %1) %1 d @@ -1428,7 +1440,7 @@ Save QR Code - Zapisz Kod QR + Zapisz kod QR PNG Image (*.png) @@ -1461,10 +1473,6 @@ General Ogólne - - Using OpenSSL version - Używana wersja OpenSSL - Using BerkeleyDB version Używana wersja BerkeleyDB @@ -1493,6 +1501,10 @@ Current number of blocks Aktualna liczba bloków + + Memory Pool + Memory Pool (obszar pamięci) + Current number of transactions Obecna liczba transakcji @@ -1629,10 +1641,30 @@ Clear console Wyczyść konsolę + + &Disconnect Node + Odłącz Nod + Ban Node for Blokuj węzeł na okres + + 1 &hour + 1 &godzina + + + 1 &day + 1 &dzień + + + 1 &week + 1 &tydzień + + + 1 &year + 1 &rok + &Unban Node Odblokuj węzeł @@ -2298,6 +2330,11 @@ &Verify Message &Zweryfikuj wiadomość + + 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! + Wpisz adres, wiadomość oraz sygnaturę (podpis) odbiorcy (upewnij się, że dokładnie skopiujesz wszystkie zakończenia linii, spacje, tabulacje itp.). Uważaj by nie dodać więcej do podpisu niż do samej podpisywanej wiadomości by uniknąć ataku man-in-the-middle. +Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadawca posiada klucz do adresu, natomiast nie potwierdza to, że poprawne wysłanie jakiejkolwiek transakcji! + The Bitcoin address the message was signed with Adres Bitcoin, którym została podpisana wiadomość @@ -2371,7 +2408,7 @@ SplashScreen Bitcoin Core - Rdzeń Bitcoin + Rdzeń Bitcoina The Bitcoin Core developers @@ -2838,11 +2875,11 @@ Backup Wallet - Kopia Zapasowa Portfela + Kopia zapasowa portfela Wallet Data (*.dat) - Dane Portfela (*.dat) + Dane portfela (*.dat) Backup Failed @@ -2858,7 +2895,7 @@ Backup Successful - Wykonano Kopię Zapasową + Wykonano kopię zapasową @@ -2883,6 +2920,18 @@ Accept command line and JSON-RPC commands Akceptuj linię poleceń oraz polecenia JSON-RPC + + If <category> is not supplied or if <category> = 1, output all debugging information. + Jeżeli <category> nie zostanie określona lub <category> = 1, wyświetl wszystkie informacje debugowania. + + + Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. + Proszę sprawdzić czy data i czas na Twoim komputerze są poprawne! Jeżeli ustawienia zegara będą złe, Bitcoin Core nie będzie działał prawidłowo. + + + Prune configured below the minimum of %d MiB. Please use a higher number. + Przycinanie skonfigurowano poniżej minimalnych %d MiB. Proszę użyć wyższej liczby. + Error: A fatal internal error occurred, see debug.log for details Błąd: Wystąpił fatalny błąd wewnętrzny, sprawdź szczegóły w debug.log @@ -2907,6 +2956,10 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Akceptuj połączenia z zewnątrz (domyślnie: 1 jeśli nie ustawiono -proxy lub -connect) + + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. + -fallbackfee ma ustawioną bardzo dużą wartość! Jest to prowizja za transakcje, którą możesz zapłacić gdy oszacowanie opłaty jest niemożliwe. + Bind to given address and always listen on it. Use [host]:port notation for IPv6 Skojarz z podanym adresem i nasłuchuj na nim. Użyj formatu [host]:port dla IPv6 @@ -2923,6 +2976,10 @@ Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) Wykonaj polecenie, kiedy transakcja portfela ulegnie zmianie (%s w poleceniu zostanie zastąpione przez TxID) + + Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) + Wymuś przekazywanie transakcji od osób z białej listy, nawet jeśli narusza to lokalną politykę przekazywania (default: %d) + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) Ustaw liczbę wątków skryptu weryfikacyjnego (%u do %d, 0 = auto, <0 = zostaw tyle rdzeni wolnych, domyślnie: %d) @@ -2935,6 +2992,14 @@ Unable to bind to %s on this computer. Bitcoin Core is probably already running. Nie można przywiązać z portem %s na tym komputerze. Bitcoin Core prawdopodobnie już działa. + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + Niewspierany argument -whitelistalwaysrelay zignorowany, użyj -whitelistrelay i/lub -whitelistforcerelay. + + + Use UPnP to map the listening port (default: 1 when listening and no -proxy) + Używaj UPnP do mapowania portu nasłuchu (domyślnie: 1 gdy nasłuchuje i brak -proxy) + WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) UWAGA: nienaturalnie duża liczba wygenerowanych bloków, %d bloków otrzymano w ostatnich %d godzinach (%d oczekiwanych) @@ -2959,6 +3024,10 @@ Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. Dodawaj do białej listy węzły łączące się z podanej maski sieciowej lub adresu IP. Może być określona kilka razy. + + -maxmempool must be at least %d MB + -maxmempool musi być przynajmniej %d MB + <category> can be: <category> mogą być: @@ -2991,6 +3060,10 @@ Do you want to rebuild the block database now? Czy chcesz teraz przebudować bazę bloków? + + Enable publish hash block in <address> + Włącz wyświetlanie hasha bloku w <address> + Error initializing block database Błąd inicjowania bazy danych bloków @@ -3027,6 +3100,14 @@ Invalid -onion address: '%s' Nieprawidłowy adres -onion: '%s' + + Invalid amount for -fallbackfee=<amount>: '%s' + Nieprawidłowa kwota dla -fallbackfee=<amount>: '%s' + + + Keep the transaction memory pool below <n> megabytes (default: %u) + Utrzymuj obszar pamięci dla transakcji poniżej <n> MB (default: %u) + Not enough file descriptors available. Brak wystarczającej liczby deskryptorów plików. @@ -3035,6 +3116,10 @@ Only connect to nodes in network <net> (ipv4, ipv6 or onion) Łącz z węzłami tylko w sieci <net> (ipv4, piv6 lub onion) + + Print version and exit + Wyświetl wersję i wyjdź + Prune cannot be configured with a negative value. Przycinanie nie może być skonfigurowane z negatywną wartością. @@ -3063,10 +3148,18 @@ Unsupported argument -debugnet ignored, use -debug=net. Niewspierany argument -debugnet zignorowany, użyj -debug=net. + + Unsupported argument -tor found, use -onion. + Znaleziono nieprawidłowy argument -tor, użyj -onion. + Use UPnP to map the listening port (default: %u) Użyj UPnP do przekazania portu nasłuchu (domyślnie : %u) + + User Agent comment (%s) contains unsafe characters. + Komentarz User Agent (%s) zawiera niebezpieczne znaki. + Verifying blocks... Weryfikacja bloków... @@ -3083,10 +3176,6 @@ Wallet options: Opcje portfela: - - Warning: This version is obsolete; upgrade required! - Uwaga: Ta wersja jest przestarzała, wymagana jest aktualizacja! - You need to rebuild the database using -reindex to change -txindex Musisz przebudować bazę używając parametru -reindex aby zmienić -txindex @@ -3171,10 +3260,6 @@ Activating best chain... Aktywuje najlepszy łańcuch - - Always relay transactions received from whitelisted peers (default: %d) - Zawsze przekazuj informacje o transakcjach otrzymanych od osób z białej listy (domyślnie: %d) - Attempt to recover private keys from a corrupt wallet.dat on startup Próbuj podczas uruchamiania programu odzyskać klucze prywatne z uszkodzonego pliku wallet.dat @@ -3259,6 +3344,10 @@ Receive and display P2P network alerts (default: %u) Odbieranie i wyświetlanie alertów sieci P2P (domyślnie: %u) + + Reducing -maxconnections from %d to %d, because of system limitations. + Zmniejszanie -maxconnections z %d do %d z powodu ograniczeń systemu. + Rescan the block chain for missing wallet transactions on startup Przeskanuj podczas ładowania programu łańcuch bloków w poszukiwaniu zaginionych transakcji portfela @@ -3335,6 +3424,10 @@ Zapping all transactions from wallet... Usuwam wszystkie transakcje z portfela... + + ZeroMQ notification options: + Opcje powiadomień ZeroMQ: + wallet.dat corrupt, salvage failed wallet.dat uszkodzony, odtworzenie się nie powiodło @@ -3367,14 +3460,26 @@ (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) (1 = zachowaj wysłane metadane np. właściciel konta i informacje o żądaniach płatności, 2 = porzuć wysłane metadane) + + -maxtxfee is set very high! Fees this large could be paid on a single transaction. + -matxfee jest ustawione bardzo wysokie! Tak wysokie opłaty mogą być zapłacone w jednej transakcji. + + + -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + -paytxfee ma ustawioną bardzo dużą wartość! Jest to prowizja za transakcje, którą płacisz, gdy wysyłasz monety. + Do not keep transactions in the mempool longer than <n> hours (default: %u) - Nie trzymaj w pamięci transakcji starszych niż <n> godzin (domyślnie: %u) + Nie trzymaj w pamięci transakcji starszych niż <n> godz. (domyślnie: %u) Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. Ostrzeżenie: błąd odczytu wallet.dat! Wszystkie klucze zostały odczytane, ale może brakować pewnych danych transakcji lub wpisów w książce adresowej lub mogą one być nieprawidłowe. + + Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) + Opłaty (w %s/Kb) mniejsze niż ta będą traktowane jako bez opłaty przy tworzeniu transakcji (domyślnie: %s) + How thorough the block verification of -checkblocks is (0-4, default: %u) Jak dokładna jest weryfikacja bloków przy -checkblocks (0-4, domyślnie: %u) @@ -3391,6 +3496,18 @@ Output debugging information (default: %u, supplying <category> is optional) Wypuść informacje debugowania (domyślnie: %u, podanie <category> jest opcjonalne) + + Support filtering of blocks and transaction with bloom filters (default: %u) + Wspieraj filtrowanie bloków i transakcji używając Filtrów Blooma (domyślnie: %u) + + + Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments. + Całkowita długość łańcucha wersji (%i) przekracza maksymalną dopuszczalną długość (%i). Zmniejsz ilość lub rozmiar parametru uacomment. + + + Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d) + Próbuje utrzymać ruch wychodzący poniżej zadanego (w MiB na dobę), 0 = bez limitu (domyślnie: %d) + Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported. Znaleziono niewspierany argument -socks. Wybieranie wersji SOCKS nie jest już możliwe, wsparcie programu obejmuje tylko proxy SOCKS5 diff --git a/src/qt/locale/bitcoin_pt_BR.ts b/src/qt/locale/bitcoin_pt_BR.ts index 5cea349fbc3f4..1b92395c79809 100644 --- a/src/qt/locale/bitcoin_pt_BR.ts +++ b/src/qt/locale/bitcoin_pt_BR.ts @@ -387,7 +387,7 @@ &Settings - &definições + &Definições &Help @@ -723,7 +723,7 @@ none - nenhum + Nenhum This label turns red if the transaction size is greater than 1000 bytes. @@ -1033,7 +1033,7 @@ Active command-line options that override above options: - Ativa as opções de linha de comando que sobrescreve as opções acima: + Opções de linha de comando ativas que sobrescreve as opções acima: Reset all client options to default. @@ -1185,7 +1185,7 @@ none - nenhum + Nenhum Confirm options reset @@ -1473,10 +1473,6 @@ General Geral - - Using OpenSSL version - Versão do OpenSSL - Using BerkeleyDB version Versão do BerkeleyDB @@ -1975,7 +1971,7 @@ collapse fee-settings - colapso Taxa de definições + Ocultar painel per kilobyte @@ -2340,7 +2336,7 @@ 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! - Coloque o endereço do destinatário, a mensagem (certifique-se de copiar toda a mensagem, incluindo quebras de linha, espaços, tabulações, etc.) e a assinatura embaixo para verificar a mensagem. Cuidado para não ler mais da assinatura do que está assinado na mensagem, para evitar ser enganado pelo ataque man-in-the-middle. Note que isso somente prova a propriedade de um endereço, e não o remetende de qualquer transação. + Coloque o endereço do autor, a mensagem (certifique-se de copiar toda a mensagem, incluindo quebras de linha, espaços, tabulações, etc.) e a assinatura embaixo para verificar a mensagem. Cuidado para não ler mais da assinatura do que está assinado na mensagem, para evitar ser enganado pelo ataque man-in-the-middle. Note que isso somente prova a propriedade de um endereço, e não o remetende de qualquer transação. The Bitcoin address the message was signed with @@ -2979,6 +2975,18 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Aceitar conexões externas (padrão: 1 se opções -proxy ou -connect não estiverem presentes) + + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. + -fallbackfee está muito alta! Essa é a taxa de transação que você vai pagar quando a taxa estimada não estiver disponível. + + + A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s) + A variação da taxa (em %s/kB) que será usada quando não houver dados suficientes para se estimar a taxa (default: %s) + + + Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d) + Aceita transações retransmitidas advindas de pares em lista branca, mesmo quando não estiver retransmitindo transações (padrão: %d) + Bind to given address and always listen on it. Use [host]:port notation for IPv6 Vincular ao endereço fornecido e sempre escutar nele. Use a notação [host]:port para IPv6 @@ -2995,6 +3003,10 @@ Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) Executa um comando quando uma transação da carteira mudar (%s no comando será substituído por TxID) + + Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) + Força a retransmissão de transações de pares da lista branca, mesmo quando violam a política local de retransmissão (default: %d) + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) Define o número de threads de verificação de script (%u a %d, 0 = automático, <0 = número de cores deixados livres, padrão: %d) @@ -3011,6 +3023,10 @@ Unable to bind to %s on this computer. Bitcoin Core is probably already running. Impossível ouvir em %s neste computador. Provavelmente o Bitcoin já está sendo executado. + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + Argumento não suportado -whitelistalwaysrelay foi ignorado, utilize -whitelistrelay e/ou -whitelistforcerelay. + Use UPnP to map the listening port (default: 1 when listening and no -proxy) Use UPnP para mapear a porta escutada (padrão: 1 quando escutando e sem -proxy) @@ -3027,6 +3043,10 @@ Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Atenção: A rede não parecem concordar plenamente! Alguns mineiros parecem estar enfrentando problemas. + + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + Aviso: Versões de bloco desconhecidas sendo mineradas! É possível que regras estranhas estejam ativas + Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Atenção: Nós não parecemos concordar plenamente com nossos colegas! Você pode precisar atualizar ou outros nós podem precisar atualizar. @@ -3047,6 +3067,10 @@ <category> can be: <category> pode ser: + + Append comment to the user agent string + Adiciona comentário ao user-agent do navegador + Block creation options: Opções de criação de blocos: @@ -3091,6 +3115,10 @@ Enable publish raw transaction in <address> Abilitar a publicação dos dados brutos da transação em <endereço> + + Enable transaction replacement in the memory pool (default: %u) + Habilita substituição de transação em memória (padrão: %u) + Error initializing block database Erro ao inicializar banco de dados de blocos @@ -3127,10 +3155,22 @@ Invalid -onion address: '%s' Endereço -onion inválido: '%s' + + Invalid amount for -fallbackfee=<amount>: '%s' + Valor inválido para -fallbackfee=<amount>: '%s' + Keep the transaction memory pool below <n> megabytes (default: %u) Mantenha a mempool de transações abaixo de <n> megabytes (padrão: %u) + + Location of the auth cookie (default: data dir) + Localização do cookie de autenticação (padrão: diretório de dados) + + + Minimum bytes per sigop in transactions we relay and mine (default: %u) + Número mínimo de bytes por sigop em transações que transmitimos e mineramos (default: %u) + Not enough file descriptors available. Decriptadores de arquivos disponíveis insuficientes. @@ -3139,6 +3179,10 @@ Only connect to nodes in network <net> (ipv4, ipv6 or onion) Somente conectar a clientes na rede <net> (ipv4, ipv6 ou onion) + + Print version and exit + Mostra a versão e sai + Prune cannot be configured with a negative value. O modo Prune não pode ser configurado com um valor negativo. @@ -3195,10 +3239,6 @@ Wallet options: Opções da carteira: - - Warning: This version is obsolete; upgrade required! - Atenção: Essa versão está obsoleta, atualização necessária! - You need to rebuild the database using -reindex to change -txindex Você precisa reconstruir o banco de dados utilizando -reindex @@ -3273,7 +3313,7 @@ This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard. - Esse produto inclui software desenvolvido pelo Open SSL Project para uso na OpenSSL Toolkit<https://www.openssl.org/> e software criptográfico escrito por Eric Young e software UPnP escrito por Thomas Bernard. + Esse produto inclui software desenvolvido pelo Open SSL Project para uso na OpenSSL Toolkit <https://www.openssl.org> e software criptográfico escrito por Eric Young e software UPnP escrito por Thomas Bernard. 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 @@ -3295,10 +3335,6 @@ Activating best chain... Ativando a melhor sequência... - - Always relay transactions received from whitelisted peers (default: %d) - Sempre transmitir transações recebidas de peers confiáveis (padrão: %d) - Attempt to recover private keys from a corrupt wallet.dat on startup Tentar recuperar na inicialização chaves privadas de um arquivo wallet.dat corrompido @@ -3383,6 +3419,14 @@ Receive and display P2P network alerts (default: %u) Receba e mostre P2P alerta de rede (padrão: %u) + + Reducing -maxconnections from %d to %d, because of system limitations. + Reduzindo -maxconnections de %d para %d, devido a limitações do sistema + + + Rescan the block chain for missing wallet transactions on startup + Re-escanear a block-chain por transações faltantes na carteira durante a inicialização + Send trace/debug info to console instead of debug.log file Mandar informação de trace/debug para o console em vez de para o arquivo debug.log @@ -3411,6 +3455,14 @@ This is experimental software. Este é um software experimental. + + Tor control port password (default: empty) + Senha da porta de controle do Tor (padrão: vazio) + + + Tor control port to use if onion listening enabled (default: %s) + Porta de controle a ser usada se o monitoramento onion estiver habilitado (padrão: %s) + Transaction amount too small Quantidade da transação muito pequena. @@ -3431,6 +3483,10 @@ Unable to bind to %s on this computer (bind returned error %s) Impossível se ligar a %s neste computador (bind retornou erro %s) + + Upgrade wallet to latest format on startup + Atualizar a carteira para o último formato na inicialização + Username for JSON-RPC connections Nome de usuário para conexões JSON-RPC @@ -3443,10 +3499,22 @@ Warning Atenção + + Warning: unknown new rules activated (versionbit %i) + Aviso: Novas regras estranhas foram ativadas (versionbit %i) + + + Whether to operate in a blocks only mode (default: %u) + Quando operar em modo de blocos somente (padrãp: %u) + Zapping all transactions from wallet... Aniquilando todas as transações da carteira... + + ZeroMQ notification options: + Opções de notificação ZeroMQ: + wallet.dat corrupt, salvage failed wallet.dat corrompido, recuperação falhou @@ -3475,14 +3543,70 @@ Error loading wallet.dat: Wallet corrupted Erro ao carregar wallet.dat: Carteira corrompida + + (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) + (1 = manter metadados tx e.g. informação do dono da conta e requisição de pagamente, 2 = descartar metadados tx) + + + -maxtxfee is set very high! Fees this large could be paid on a single transaction. + -maxtxfee é muito alto! Essa quantia poderia ser paga em uma única transação. + + + -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + -paytxfee é muito alto! Este é o valor da taxa de transação que você irá pagar se enviar a transação. + + + Do not keep transactions in the mempool longer than <n> hours (default: %u) + Não manter transações na mempool por mais que <n> horas (padrão: %u) + + + Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Erro ao ler o arquivo wallet.dat! Todas as chaves foram lidas corretamente, mas os dados de transações ou o livro de endereços podem estar faltando ou ser incorretos. + Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) Comissões (em %s/kB) menores serão consideradas como zero para criação de transação (padrão %s) + + How thorough the block verification of -checkblocks is (0-4, default: %u) + Quão completa a verificação de blocos do -checkblocks é (0-4, padrão: %u) + + + Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u) + Mantém um índice completo de transações, usado pela chamada rpc getrawtransaction (padrão: %u) + + + Number of seconds to keep misbehaving peers from reconnecting (default: %u) + Número de segundos para impedir que peers mal comportados reconectem (padrão %u) + + + Output debugging information (default: %u, supplying <category> is optional) + Informação de saída de debug (padrão: %u, definir <category> é opcional) + + + Support filtering of blocks and transaction with bloom filters (default: %u) + Suportar filtragem de blocos e transações com filtros bloom (padrão: %u) + + + Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments. + O tamanho total da string de versão da rede (%i) excede o tamanho máximo (%i). Reduza o numero ou tamanho de uacomments. + + + Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d) + Tenta manter tráfego fora dos limites dentro do alvo especificado (em MiB por 24h), 0 = sem limite (padrão: %d) + + + Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported. + Argumento inválido -socks encontrado. Definir a versão do SOCKS não é mais possível, somente proxys SOCK5 são suportados. + Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s) Use um proxy SOCKS5 separado para alcançar participantes da rede via serviços ocultos Tor (padrão: %s) + + Username and hashed password for JSON-RPC connections. The field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A canonical python script is included in share/rpcuser. This option can be specified multiple times + Nome de usuário e senha hash para conexões JSON-RPC. O campo <userpw> vem com o formato: <USERNAME>:<SALT>$<HASH>. Um script python canônico é incluído em share/rpcuser. Essa opção pode ser especificada múltiplas vezes. + (default: %s) (padrão: %s) @@ -3531,10 +3655,18 @@ Maximum per-connection receive buffer, <n>*1000 bytes (default: %u) Buffer máximo de recebimento por conexão, <n>*1000 bytes (padrão: %u) + + Maximum per-connection send buffer, <n>*1000 bytes (default: %u) + Buffer máximo de envio por conexão, <n>*1000 bytes (padrão: %u) + Prepend debug output with timestamp (default: %u) Adiciona timestamp como prefixo no debug (padrão: %u) + + Relay and mine data carrier transactions (default: %u) + Transações de dados de operadora (padrão: %u) + Relay non-P2SH multisig (default: %u) Retransmitir P2SH não multisig (padrão: %u) @@ -3567,6 +3699,10 @@ Spend unconfirmed change when sending transactions (default: %u) Gastar troco não confirmado quando enviar transações (padrão: %u) + + Threshold for disconnecting misbehaving peers (default: %u) + Limite para desconectar peers mal comportados (padrão: %u) + Unknown network specified in -onlynet: '%s' Rede desconhecida especificada em -onlynet: '%s' diff --git a/src/qt/locale/bitcoin_pt_PT.ts b/src/qt/locale/bitcoin_pt_PT.ts index ffed44a61c20c..362769138a842 100644 --- a/src/qt/locale/bitcoin_pt_PT.ts +++ b/src/qt/locale/bitcoin_pt_PT.ts @@ -3,7 +3,7 @@ AddressBookPage Right-click to edit address or label - Clique á direita para editar endereço ou rótulo + Clique com o botão direito para editar o endereço ou rótulo Create a new address @@ -31,11 +31,11 @@ Delete the currently selected address from the list - Apagar o endereço selecionado da lista + Eliminar o endereço selecionado da lista Export the data in the current tab to a file - Exportar os dados no separador actual para um ficheiro + Exportar os dados no separador atual para um ficheiro &Export @@ -43,15 +43,15 @@ &Delete - &Eliminar\ + &Eliminar Choose the address to send coins to - Escolha o endereço para o qual pretende enviar moedas + Escolha o endereço para enviar as moedas Choose the address to receive coins with - Escolha o endereço com o qual pretende receber moedas + Escolha o endereço para receber as moedas com C&hoose @@ -63,7 +63,7 @@ Receiving addresses - Endereços de depósito + Endereços de a receber These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. @@ -71,7 +71,7 @@ These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Estes são os seus endereços Bitcoin para receber pagamentos. É recomendado que utilize um endereço novo para cada transacção. + Estes são os seus endereços do Bitcoin para receber pagamentos. É recomendado que utilize um novo endereço para cada transação. Copy &Label @@ -91,7 +91,7 @@ Exporting Failed - A Exportação Falhou + Exportação Falhou There was an error trying to save the address list to %1. Please try again. @@ -102,7 +102,7 @@ AddressTableModel Label - Rótulo + Etiqueta Address @@ -110,26 +110,26 @@ (no label) - (sem rótulo) + (sem etiqueta) AskPassphraseDialog Passphrase Dialog - Diálogo de frase de segurança + Janela da frase de palavra-passe Enter passphrase - Insira a frase de segurança + Insira a frase de palavra-passe New passphrase - Nova frase de segurança + Nova frase de palavra-passe Repeat new passphrase - Repita a nova frase de segurança + Repita a nova frase de palavra-passe Encrypt wallet @@ -137,7 +137,7 @@ This operation needs your wallet passphrase to unlock the wallet. - A sua frase de segurança é necessária para desbloquear a carteira. + Esta operação precisa da sua frase de palavra-passe da carteira para desbloquear a mesma. Unlock wallet @@ -145,7 +145,7 @@ This operation needs your wallet passphrase to decrypt the wallet. - A sua frase de segurança é necessária para desencriptar a carteira. + Esta operação precisa da sua frase de palavra-passe da carteira para desencriptar a mesma. Decrypt wallet @@ -153,7 +153,7 @@ Change passphrase - Alterar frase de segurança + Alterar frase de palavra-passe Confirm wallet encryption @@ -161,7 +161,7 @@ Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Atenção: Se encriptar a carteira e perder a sua senha irá <b>PERDER TODOS OS SEUS BITCOINS</b>! + Aviso: se encriptar a sua carteira e perder a sua frase de de palavra-passe, irá <b>PERDER TODOS OS SEUS BITCOINS</b>! Are you sure you wish to encrypt your wallet? @@ -177,7 +177,7 @@ Warning: The Caps Lock key is on! - Atenção: A tecla Caps Lock está activa! + Atenção: a tecla Caps Lock está ativada! Wallet encrypted @@ -185,11 +185,11 @@ Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Escreva a nova frase de seguraça da sua carteira. <br/> Por favor, use uma frase de <b>10 ou mais caracteres aleatórios,</b> ou <b>oito ou mais palavras</b>. + Insira a nova frase de palavra-passe da sua carteira. <br/> Por favor, utilize uma frase de palavra-passe com <b>mais de 10 ou mais carateres aleatórios,</b> ou <b>oito ou mais palavras</b>. Enter the old passphrase and new passphrase to the wallet. - Escreva a antiga frase de segurança da carteira, seguida da nova. + Insira a frase de palavra-passe antiga e a nova frase de palavra-passe para carteira. Wallet encryption failed @@ -201,7 +201,7 @@ The supplied passphrases do not match. - As frases de segurança fornecidas não coincidem. + As frases de palavra-passe inseridas não coincidem. Wallet unlock failed @@ -209,7 +209,7 @@ The passphrase entered for the wallet decryption was incorrect. - A frase de segurança introduzida para a desencriptação da carteira estava incorreta. + A frase de palavra-passe inserida para a desencriptação da carteira estava incorreta. Wallet decryption failed @@ -217,12 +217,20 @@ Wallet passphrase was successfully changed. - A frase de segurança da carteira foi alterada com êxito. + A frase de palavra-passe da carteira foi alterada com sucesso. BanTableModel - + + IP/Netmask + IP/Máscara de Rede + + + Banned Until + Banido Até + + BitcoinGUI @@ -235,7 +243,7 @@ &Overview - Visã&o geral + &Sinopse Node @@ -243,7 +251,7 @@ Show general overview of wallet - Mostrar visão geral da carteira + Mostrar sinopse geral da carteira &Transactions @@ -251,7 +259,7 @@ Browse transaction history - Navegar pelo histórico de transações + Explorar histórico das transações E&xit @@ -283,15 +291,15 @@ &Change Passphrase... - Mudar &Palavra-passe... + Alterar &Frase de Palavra-passe... &Sending addresses... - A &enviar endereços... + A &enviar os endereços... &Receiving addresses... - A &receber endereços... + A &receber os endereços... Open &URI... @@ -299,15 +307,15 @@ Bitcoin Core client - Cliente Bitcoin Core + Cliente do Bitcoin Core Importing blocks from disk... - A importar blocos do disco... + A importar os blocos do disco... Reindexing blocks on disk... - A reindexar blocos no disco... + A reindexar os blocos no disco... Send coins to a Bitcoin address @@ -315,11 +323,11 @@ Backup wallet to another location - Faça uma cópia de segurança da carteira para outra localização + Efetue uma cópia de segurança da carteira para outra localização Change the passphrase used for wallet encryption - Mudar a frase de segurança utilizada na encriptação da carteira + Alterar a frase de palavra-passe utilizada na encriptação da carteira &Debug window @@ -351,7 +359,7 @@ Show information about Bitcoin Core - Mostrar informação sobre Bitcoin Core + Mostrar informação sobre o Bitcoin Core &Show / Hide @@ -359,7 +367,7 @@ Show or hide the main Window - Mostrar ou esconder a janela principal + Mostrar ou ocultar a janela principal Encrypt the private keys that belong to your wallet @@ -387,7 +395,7 @@ Tabs toolbar - Barra de separadores + Barra de ferramentas dos separadores Bitcoin Core @@ -395,7 +403,7 @@ Request payments (generates QR codes and bitcoin: URIs) - Solicitar pagamentos (gera códigos QR e URIs bitcoin:) + Solicitar pagamentos (gera códigos QR e bitcoin: URIs) &About Bitcoin Core @@ -403,7 +411,7 @@ Modify configuration options for Bitcoin Core - Modificar opções de configuração de Bitcoin Core + Modificar as opções de configuração do Bitcoin Core Show the list of used sending addresses and labels @@ -419,11 +427,11 @@ &Command-line options - &Opções da linha de &comandos + &Opções da linha de &comando Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Mostrar a mensagem de ajuda do Bitcoin Core para obter uma lista com possíveis opções de linha de comandos + Mostrar a mensagem de ajuda do Bitcoin Core para obter uma lista com possíveis opções de linha de comando do Bitcoin %n active connection(s) to Bitcoin network @@ -463,11 +471,11 @@ Last received block was generated %1 ago. - O último bloco recebido foi gerado %1 atrás. + O último bloco recebido foi gerado há %1. Transactions after this will not yet be visible. - Transações posteriores não serão visíveis por enquanto. + As transações depois de isto ainda não serão visíveis. Error @@ -498,7 +506,7 @@ Amount: %1 - Quantia: %1 + Valor: %1 @@ -510,7 +518,7 @@ Label: %1 - Rótulo: %1 + Etiqueta: %1 @@ -547,7 +555,7 @@ CoinControlDialog Coin Selection - Seleção de moeda + Seleção de Moeda Quantity: @@ -559,7 +567,7 @@ Amount: - Quantia: + Valor: Priority: @@ -575,7 +583,7 @@ After Fee: - Depois da Taxa: + Depois da taxa: Change: @@ -583,23 +591,23 @@ (un)select all - (des)seleccionar todos + (des)selecionar todos Tree mode - Modo árvore + Modo de árvore List mode - Modo lista + Modo de lista Amount - Quantia + Valor Received with label - Recebido com rótulo + Recebido com etiqueta Received with address @@ -611,7 +619,7 @@ Confirmations - Confirmados + Confirmações Confirmed @@ -627,23 +635,23 @@ Copy label - Copiar rótulo + Copiar etiqueta Copy amount - Copiar quantia + Copiar valor Copy transaction ID - Copiar ID da transação + Copiar id. da transação Lock unspent - Bloquear não gastos + Bloquear não gastas Unlock unspent - Desbloquear não gastos + Desbloquear não gastas Copy quantity @@ -655,7 +663,7 @@ Copy after fee - Copiar valor após taxa + Copiar depois da taxa Copy bytes @@ -687,7 +695,7 @@ medium-high - média-alta + média alta medium @@ -695,7 +703,7 @@ low-medium - média-baixa + média baixa low @@ -707,7 +715,7 @@ lowest - muito alta + muito baixa (%1 locked) @@ -719,15 +727,15 @@ This label turns red if the transaction size is greater than 1000 bytes. - Este rótulo fica vermelho se o tamanho da transacção exceder os 1000 bytes. + Esta etiqueta fica vermelha se o tamanho da transação exceder os 1000 bytes. This label turns red if the priority is smaller than "medium". - Esta legenda fica vermelha se a prioridade for menor que "média". + Esta etiqueta fica vermelha se a prioridade for menor que "média". This label turns red if any recipient receives an amount smaller than %1. - Este rótulo fica vermelho se algum recipiente receber uma quantia menor que %1. + Esta etiqueta fica vermelha se qualquer recipiente receber uma quantia menor que %1. Can vary +/- %1 satoshi(s) per input. @@ -755,7 +763,7 @@ (no label) - (sem rótulo) + (sem etiqueta) change from %1 (%2) @@ -774,15 +782,15 @@ &Label - &Rótulo + &Etiqueta The label associated with this address list entry - O rótulo associado com esta entrada no livro de endereços + A etiqueta associada com esta entrada da lista de endereços The address associated with this address list entry. This can only be modified for sending addresses. - O endereço associado com o esta entrada no livro de endereços. Isto só pode ser modificado para endereços de saída. + O endereço associado com o esta entrada da lista de endereços. Isto só pode ser modificado para os endereços de envio. &Address @@ -825,7 +833,7 @@ FreespaceChecker A new data directory will be created. - Uma nova pasta de dados será criada. + Irá ser criada uma nova diretoria de dados. name @@ -841,7 +849,7 @@ Cannot create data directory here. - Não pode ser criada uma pasta de dados aqui. + Não é possível criar aqui uma diretoria de dados. @@ -864,7 +872,7 @@ Command-line options - Opções de linha de comandos + Opções da linha de comando Usage: @@ -872,9 +880,37 @@ command-line options - opções da linha de comandos + opções da linha de comando - + + UI Options: + Opções da IU: + + + Choose data directory on startup (default: %u) + Escolha a diretoria dos dados no arranque (predefinição: %u) + + + Set language, for example "de_DE" (default: system locale) + Definir linguagem, por exemplo "pt_PT" (por defeito: linguagem do sistema) + + + Start minimized + Iniciar minimizado + + + Set SSL root certificates for payment request (default: -system-) + Configurar certificados SSL root para pedido de pagamento (default: -system-) + + + Show splash screen on startup (default: %u) + Mostrar o ecrã de abertura no arranque (predefinição: %u) + + + Reset all settings changes made over the GUI + Reiniciar as alterações das configurações efetuadas na GUI + + Intro @@ -887,19 +923,19 @@ As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - Sendo esta a primeira vez que o programa é iniciado, poderá escolher onde o Bitcoin Core irá guardar os seus dados. + Como esta é a primeira vez que o programa é iniciado, pode escolher onde guardar os seus dados do Bitcoin Core. Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - O Bitcoin Core vai transferir e armazenar uma cópia do "block chain" (cadeia de blocos). Pelo menos %1GB de dados serão armazenados nesta pasta, e vão crescer ao longo do tempo. A sua carteira também irá ser armazenada nesta pasta. + O Bitcoin Core irá transferir e guardar uma cópia da cadeia de bloco do Bitcoin. Pelo menos %1GB de dados serão guardados nesta diretoria, e estes irão crescer ao longo do tempo. A sua carteira também será guardada nesta diretoria. Use the default data directory - Utilizar a pasta de dados padrão + Utilizar a diretoria de dados predefinida Use a custom data directory: - Utilizar uma pasta de dados personalizada: + Utilizar uma diretoria de dados personalizada: Bitcoin Core @@ -907,7 +943,7 @@ Error: Specified data directory "%1" cannot be created. - Erro: Pasta de dados especificada como "%1, não pode ser criada. + Erro: não pode ser criada a diretoria de dados especificada como "%1. Error @@ -915,7 +951,7 @@ %n GB of free space available - %n GB de espaço livre disponível %n GB de espaço livre disponível + %n GB de espaço livre disponível%n GB de espaço livre disponível (of %n GB needed) @@ -969,11 +1005,11 @@ Accept connections from outside - Aceitar conceções externas + Aceitar ligações externas Allow incoming connections - Permitir conexão + Permitir ligação a receber IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) @@ -985,7 +1021,7 @@ The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - A linguagem da interface do utilizador pode ser definida aqui. Esta definição entrará em efeito após reiniciar o Bitcoin Core. + O idioma da da interface do utilizador pode ser definida aqui. Esta definição será aplicada depois de reiniciar o Bitcoin Core. 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 |. @@ -994,15 +1030,15 @@ Third party transaction URLs - URLs de transação de outrem + URLs de transação de terceiros Active command-line options that override above options: - Opções de linha de comandos ativas que se sobrepõem ás opções anteriores: + Ativar as opções da linha de comando que se sobrepõem às opções acima: Reset all client options to default. - Repor todas as opções do cliente. + Repor todas as opções de cliente para a predefinição. &Reset Options @@ -1014,15 +1050,15 @@ Automatically start Bitcoin Core after logging in to the system. - Começar o Bitcoin Core automaticamente ao iniciar sessão no sistema. + Iniciar automaticamente o Bitcoin Core depois de iniciar a sessão no sistema. &Start Bitcoin Core on system login - &Começar o Bitcoin Core ao iniciar o sistema + &Iniciar o Bitcoin Core ao iniciar a sessão no sistema (0 = auto, <0 = leave that many cores free) - (0 = auto, <0 = Deixar essa quantidade de núcleos livre) + (0 = automático, <0 = deixar essa quantidade de núcleos livre) W&allet @@ -1030,11 +1066,11 @@ Expert - Especialista + Especialistas Enable coin &control features - Ativar funcionalidades de controlo de transação. + Ativar as funcionalidades de controlo de moedas 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. @@ -1050,7 +1086,7 @@ Map port using &UPnP - Mapear porta usando &UPnP + Mapear porta, utilizando &UPnP Connect to the Bitcoin network through a SOCKS5 proxy. @@ -1072,6 +1108,34 @@ Port of the proxy (e.g. 9050) Porto do proxy (p.ex. 9050) + + Used for reaching peers via: + Usado para alcançar nós via: + + + Shows, if the supplied default SOCKS5 proxy is used to reach peers via this network type. + Mostra, caso o proxy SOCKS5 predefinido submetido seja usado para alcançar nós através deste tipo de rede. + + + IPv4 + IPv4 + + + IPv6 + IPv6 + + + Tor + Tor + + + Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services. + Ligar à rede Bitcoin através de um proxy SOCKS5 separado para utilizar os serviços ocultos do Tor. + + + Use separate SOCKS5 proxy to reach peers via Tor hidden services: + Utilizar um proxy SOCKS5 separado para alcançar nós via serviços ocultos do Tor: + &Window &Janela @@ -1102,11 +1166,11 @@ Choose the default subdivision unit to show in the interface and when sending coins. - Escolha a subdivisão unitária a ser mostrada por defeito na aplicação e ao enviar moedas. + Escolha a unidade da subdivisão predefinida para ser mostrada na interface e quando enviar as moedas. Whether to show coin control features or not. - Escolha para mostrar funcionalidades de Coin Control ou não. + Escolha se deve mostrar as funcionalidades de controlo de moedas ou não. &OK @@ -1118,7 +1182,7 @@ default - padrão + predefinição none @@ -1126,7 +1190,7 @@ Confirm options reset - Confirme a reposição de opções + Confirme a reposição das opções Client restart required to activate changes. @@ -1252,7 +1316,7 @@ Cannot start bitcoin: click-to-pay handler - Impossível iniciar o controlador de bitcoin: click-to-pay + Não é possível iniciar o Bitcoin: utilizador clique-para-pagar Payment request fetch URL is invalid: %1 @@ -1410,17 +1474,13 @@ General Geral - - Using OpenSSL version - Usando versão OpenSSL - Using BerkeleyDB version Versão BerkeleyDB em uso Startup time - Hora de inicialização + Hora de Arranque Network @@ -1442,6 +1502,22 @@ Current number of blocks Número actual de blocos + + Memory Pool + Banco de Memória + + + Current number of transactions + Número actual de transacções + + + Memory usage + Utilização de memória + + + Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. + Abrir o ficheiro de registo de depuração da pasta de dados actual. Isto pode demorar alguns segundos para ficheiros de registo grandes. + Received Recebido @@ -1452,12 +1528,20 @@ &Peers - &Conexção + &Conexão + + + Banned peers + Nós banidos Select a peer to view detailed information. Selecione uma conexação para ver informação em detalhe. + + Whitelisted + Permitido por si + Direction Direcção @@ -1466,6 +1550,18 @@ Version Versão + + Starting Block + Bloco Inicial + + + Synced Headers + Cabeçalhos Sincronizados + + + Synced Blocks + Blocos Sincronizados + User Agent Agente Usuário @@ -1480,7 +1576,7 @@ Connection Time - Tempo de Conexção + Tempo de Ligação Last Send @@ -1494,6 +1590,18 @@ Ping Time Tempo de Latência + + The duration of a currently outstanding ping. + A duração de um ping atualmente pendente. + + + Ping Wait + Espera do Ping + + + Time Offset + Fuso Horário + Last block time Data do último bloco @@ -1538,6 +1646,34 @@ Clear console Limpar consola + + &Disconnect Node + &Desligar Nó + + + Ban Node for + Banir Nó por + + + 1 &hour + 1 &hora + + + 1 &day + 1 &dia + + + 1 &week + 1 &semana + + + 1 &year + 1 &ano + + + &Unban Node + &Desbloquear Nó + Welcome to the Bitcoin Core RPC console. Bem-vindo à consola RPC do Bitcoin Core. @@ -1566,6 +1702,10 @@ %1 GB %1 GB + + (node id: %1) + (id nó: %1) + via %1 via %1 @@ -1582,6 +1722,14 @@ Outbound Saída + + Yes + Sim + + + No + Não + Unknown Desconhecido @@ -1764,7 +1912,7 @@ Coin Control Features - Funcionalidades de Coin Control: + Funcionalidades do Controlo de Moedas: Inputs... @@ -1820,7 +1968,7 @@ Choose... - Escolha... + Escolher... collapse fee-settings @@ -1950,6 +2098,10 @@ Copy change Copiar alteração + + Total Amount %1 + Quantia Total %1 + or ou @@ -1974,10 +2126,26 @@ The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. A transação foi rejeitada! Isto poderá acontecer se algumas das moedas na sua carteira já tiverem sido gastas, se por exemplo tiver usado uma cópia do ficheiro wallet.dat e as moedas tiverem sido gastas na cópia mas não tiverem sido marcadas como gastas aqui. + + A fee higher than %1 is considered an absurdly high fee. + Uma taxa superior a %1 é considerada muito alta. + Payment request expired. Pedido de pagamento expirou. + + Pay only the required fee of %1 + Pagar somente a taxa mínima de %1 + + + The recipient address is not valid. Please recheck. + O endereço de destino não é válido. Por favor, verifique novamente. + + + Duplicate address found: addresses should only be used once each. + Endereço duplicado encontrado: cada endereço só poderá ser usado uma vez. + Warning: Invalid Bitcoin address Aviso: Endereço Bitcoin inválido @@ -2023,7 +2191,7 @@ Choose previously used address - Escolher endereço usado previamente + Escolha o endereço utilizado anteriormente This is a normal payment. @@ -2049,10 +2217,26 @@ Remove this entry Remover esta entrada + + 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. + A taxa será deduzida ao montante enviado. O destinatário irá receber menos bitcoins do que as que introduziu no campo montante. Caso sejam seleccionados múltiplos destinatários, a taxa será repartida equitativamente. + + + S&ubtract fee from amount + S&ubtrair taxa ao montante + Message: Mensagem: + + This is an unauthenticated payment request. + Pedido de pagamento não autenticado. + + + This is an authenticated payment request. + Pedido de pagamento autenticado. + Enter a label for this address to add it to the list of used addresses Introduza um rótulo para este endereço para o adicionar à sua lista de endereços usados @@ -2091,13 +2275,17 @@ &Sign Message &Assinar Mensagem + + 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. + Pode assinar mensagens com os seus endereços para provar que são seus. Tenha atenção ao assinar mensagens ambíguas, pois ataques de phishing podem tentar enganá-lo de modo a assinar a sua identidade para os atacantes. Apenas assine declarações detalhadas com as quais concorde. + The Bitcoin address to sign the message with O endereço Bitcoin para designar a mensagem Choose previously used address - Escolher endereço usado previamente + Escolha o endereço utilizado anteriormente Alt+A @@ -2143,6 +2331,10 @@ &Verify Message &Verificar Mensagem + + 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! + Introduza o endereço de assinatura, mensagem (assegure-se que copia quebras de linha, espaços, tabulações, etc. exactamente) e assinatura abaixo para verificar a mensagem. Tenha atenção para não ler mais na assinatura do que o que estiver na mensagem assinada, para evitar ser enganado por um atacante que se encontre entre si e quem assinou a mensagem. + The Bitcoin address the message was signed with O endereço Bitcoin com que a mensagem foi designada @@ -2494,6 +2686,10 @@ Whether or not a watch-only address is involved in this transaction. Desde que um endereço de modo-verificação faça parte ou não desta transação + + User-defined intent/purpose of the transaction. + Motivo da transacção definido pelo utilizador. + Amount removed from or added to balance. Quantia retirada ou adicionada ao saldo. @@ -2573,6 +2769,10 @@ Copy transaction ID Copiar ID da Transação + + Copy raw transaction + Copiar dados brutos da transacção + Edit label Editar rótulo @@ -2653,7 +2853,7 @@ WalletFrame No wallet has been loaded. - Nenhuma carteira foi carregada. + Não foi carregada nenhuma carteira. @@ -2720,14 +2920,70 @@ Accept command line and JSON-RPC commands Aceitar comandos de linha de comandos e JSON-RPC + + If <category> is not supplied or if <category> = 1, output all debugging information. + Se <category> não é fornecida ou <category> = 1, imprimir toda a informação de depuração. + + + Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s) + Total máximo de taxas (em %s) a utilizar numa única transacção; definir este valor demasiado baixo pode abortar transacções grandes (padrão: %s) + + + Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. + Por favor verifique que a data e hora do seu computador estão correctas! Se o seu relógio não estiver certo o Bitcoin Core não irá funcionar correctamente. + + + Prune configured below the minimum of %d MiB. Please use a higher number. + Poda configurada abaixo do mínimo de %d MiB. Por favor, utilize um valor mais elevado. + + + Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node) + Suprimir: a última sincronização da carteira vai além dos dados suprimidos. O que precisa para -reindex (transferir novamente toda a cadeia de blocos, no caso de nó suprimido) + + + Reduce storage requirements by pruning (deleting) old blocks. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, >%u = target size in MiB to use for block files) + Reduza os requisitos de armazenamento podando (eliminando) blocos antigos. Este modo é incompatível com -txindex e -rescan. Aviso: Reverter esta opção requer um novo descarregamento da cadeia de blocos completa. (padrão: 0 = desactivar poda de blocos, >%u = tamanho desejado em MiB para utilizar em ficheiros de blocos) + + + Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again. + Reanálises não são possíveis no modo de suprimir. Para isso terá de utilizar -reindex que irá transferir novamente toda a cadeia de blocos. + + + Error: A fatal internal error occurred, see debug.log for details + Erro: Um erro fatal interno ocorreu, verificar debug.log para mais informação + + + Fee (in %s/kB) to add to transactions you send (default: %s) + Taxa (em %s/kB) a adicionar às transacções que envia (padrão: %s) + + + Pruning blockstore... + A podar a blockstore... + Run in the background as a daemon and accept commands Correr o processo em segundo plano e aceitar comandos + + Unable to start HTTP server. See debug log for details. + Não é possível iniciar o servidor HTTP. Verifique o debug.log para detalhes. + Accept connections from outside (default: 1 if no -proxy or -connect) Aceitar ligações externas (padrão: 1 sem -proxy ou -connect) + + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. + -fallbackfee está definida muito elevada! Esta é a taxa de transação pode poderá pagar quando as estimativas de taxas não estão disponíveis. + + + A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s) + Uma percentagem da taxa (em %s/kB) que será utilizada quando a estimativa da taxa tiver dados insuficientes (predefinição: %s) + + + Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d) + Aceitar as transações retransmitidas recebidas dos pares na lista branca, mesmo quando não retransmitir as transações (predefinição: %d) + Bind to given address and always listen on it. Use [host]:port notation for IPv6 Associar a endereço específico e escutar sempre nele. Use a notação [anfitrião]:porta para IPv6 @@ -2744,10 +3000,18 @@ Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) Executar comando quando uma das transações na carteira mudar (no comando, %s é substituído pelo ID da Transação) + + Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) + Forçar retransmissão das transações a partir dos pares da lista branca, mesmo que estes violem a política de retransmissão local (predefinição: %d) + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) Defina o número de processos de verificação (%u até %d, 0 = automático, <0 = ldisponibiliza esse número de núcleos livres, por defeito: %d) + + 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 + A base de dados de blocos contém um bloco que aparenta ser do futuro. Isto pode ser causado por uma data incorrecta definida no seu computador. Reconstrua apenas a base de dados de blocos caso tenha a certeza de que a data e hora do seu computador estão correctos. + This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Esta é uma versão de testes pré-lançamento - use à sua responsabilidade - não usar para minar ou aplicações comerciais @@ -2756,10 +3020,30 @@ Unable to bind to %s on this computer. Bitcoin Core is probably already running. Incapaz de vincular à porta %s neste computador. O Bitcoin Core provavelmente já está a correr. + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + Argumento não suportado -whitelistalwaysrelay ignorado, utilize -whitelistrelay e/ou -whitelistforcerelay. + + + Use UPnP to map the listening port (default: 1 when listening and no -proxy) + Utilizar UPnP para mapear a porta de escuta (predefinição: 1 quando escutar e sem -proxy) + + + WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) + AVISO: gerado um número anormalmente elevado de blocos, %d blocos recebidos nas últimas %d horas (%d esperados) + + + WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) + AVISO: verifique a sua conexão à rede, %d blocos recebidos nas últimas %d horas (%d esperados) + Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Aviso: A rede não parece estar completamente de acordo! Parece que alguns mineiros estão com dificuldades técnicas. + + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + Atenção: Versões desconhecidas de blocos estão a ser mineradas! É possível que regras desconhecias estão a ser efetuadas + Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Atenção: Parecemos não estar de acordo com os nossos pares! Poderá ter que atualizar o seu cliente, ou outros nós poderão ter que atualizar os seus clientes. @@ -2772,13 +3056,21 @@ Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. Ligações na lista branca conectam desde a seguinte netmask ou endereço IP. Posse ser especificado varias vezes. + + -maxmempool must be at least %d MB + - máximo do banco de memória deverá ser pelo menos %d MB + <category> can be: <categoria> pode ser: + + Append comment to the user agent string + Anexar um comentário para a entrada de agente do utilizador + Block creation options: - Opções de criação de bloco: + Opções da criação de bloco: Connect only to the specified node(s) @@ -2786,7 +3078,7 @@ Connection options: - Opcões de conexção: + Opções de ligação: Corrupted block database detected @@ -2794,16 +3086,36 @@ Debugging/Testing options: - Depuração/Opções teste: + Opções de Depuração/Teste: Do not load the wallet and disable wallet RPC calls - Não carregar a carteira e desativar chamadas RPC de carteira. + Não carregar a carteira e desativar as chamadas de RPC da carteira. Do you want to rebuild the block database now? Deseja reconstruir agora a base de dados de blocos. + + Enable publish hash block in <address> + Activar publicação do hash do bloco em <address> + + + Enable publish hash transaction in <address> + Activar publicação do hash da transacção em <address> + + + Enable publish raw block in <address> + Activar publicação de dados brutos do bloco em <address> + + + Enable publish raw transaction in <address> + Activar publicação de dados brutos da transacção em <address> + + + Enable transaction replacement in the memory pool (default: %u) + Ativar substituição da transação no banco de memória (predefinição: %u) + Error initializing block database Erro ao inicializar a cadeia de blocos @@ -2840,6 +3152,22 @@ Invalid -onion address: '%s' Endereço -onion inválido: '%s' + + Invalid amount for -fallbackfee=<amount>: '%s' + Valor inválido para -fallbackfee=<amount>: '%s' + + + Keep the transaction memory pool below <n> megabytes (default: %u) + Manter o banco de memória da transação abaixo de <n> megabytes (predefinição: %u) + + + Location of the auth cookie (default: data dir) + Localização de cookie de autorização (predefinição: diretoria de dados) + + + Minimum bytes per sigop in transactions we relay and mine (default: %u) + Mínimo de bytes por sigop nas transações que nós transmitimos e mine (predefinição: %u) + Not enough file descriptors available. Os descritores de ficheiros disponíveis são insuficientes. @@ -2848,6 +3176,18 @@ Only connect to nodes in network <net> (ipv4, ipv6 or onion) Somente conectar aos nodes na rede <net> (ipv4, ipv6 ou onion) + + Print version and exit + Imprimir versão e sair + + + Prune cannot be configured with a negative value. + Poda não pode ser configurada com um valor negativo. + + + Prune mode is incompatible with -txindex. + Modo poda é incompatível com -txindex. + Set database cache size in megabytes (%d to %d, default: %d) Definir o tamanho da cache de base de dados em megabytes (%d a %d, padrão: %d) @@ -2860,9 +3200,25 @@ Specify wallet file (within data directory) Especifique ficheiro de carteira (dentro da pasta de dados) + + Unsupported argument -benchmark ignored, use -debug=bench. + Argumento não suportado -benchmark ignorado, use -debug=bench. + + + Unsupported argument -debugnet ignored, use -debug=net. + Argumento não suportado -debugnet ignorado, use -debug=net. + + + Unsupported argument -tor found, use -onion. + Argumento não suportado -tor encontrado, use -onion. + Use UPnP to map the listening port (default: %u) - Use UPnP para mapear a porto de escuta (default: %u) + Utilizar UPnP para mapear a porta de escuta (predefinição: %u) + + + User Agent comment (%s) contains unsafe characters. + Comentário no User Agent (%s) contém caracteres inseguros. Verifying blocks... @@ -2880,10 +3236,6 @@ Wallet options: Opções da carteira: - - Warning: This version is obsolete; upgrade required! - Aviso: Esta versão está desatualizada; atualização necessária! - You need to rebuild the database using -reindex to change -txindex É necessário reconstruir as bases de dados usando -reindex para mudar o -txindex @@ -2904,34 +3256,122 @@ Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. Impossível trancar a pasta de dados %s. Provavelmente o Bitcoin Core já está a ser executado. + + Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) + Crie ficheiros novos com as permisões predefinidas do sistema, em vez de umask 077 (apenas eficaz caso a funcionalidade carteira esteja desactivada) + + + Discover own IP addresses (default: 1 when listening and no -externalip or -proxy) + Descobrir o próprio endereço IP (padrão: 1 ao escutar e sem -externalip ou -proxy) + + + Error: Listening for incoming connections failed (listen returned error %s) + Erro: A escuta de ligações de entrada falhou (escuta devolveu erro %s) + Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message) Executar comando quando um alerta relevante for recebido ou em caso de uma divisão longa da cadeia de blocos (no comando, %s é substituído pela mensagem) + + Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s) + Taxas (em %s/kB) abaixo deste valor são consideradas nulas para propagação, mineração e criação de transacções (padrão: %s) + + + If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u) + Caso o paytxfee não seja definido, inclua uma taxa suficiente para que as transacções comecem a ser confirmadas, em média, dentro de n blocos (padrão: %u) + + + Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions) + Montante inválido para -maxtxfee=<amount>: '%s' (deverá ser, no mínimo , a taxa mínima de propagação de %s, de modo a evitar transações bloqueadas) + + + Maximum size of data in data carrier transactions we relay and mine (default: %u) + Tamanho máximo dos dados em transacções que incluem dados que propagamos e mineramos (padrão: %u) + + + Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect) + Encontrar pares usando DNS lookup, caso o número de endereços seja reduzido (padrão: 1 excepto -connect) + + + Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u) + Usar credenciais aleatórias por cada ligação proxy. Permite que o Tor use stream isolation (padrão: %u) + Set maximum size of high-priority/low-fee transactions in bytes (default: %d) Definir tamanho máximo de transações com alta-prioridade/baixa-taxa em bytes (por defeito: %d) + + Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) + Definir o número threads para a geração de moedas, caso activo (-1 = todos os cores, padrão: %d) + + + The transaction amount is too small to send after the fee has been deducted + O montante da transacção é demasiado baixo após a dedução da taxa + + + This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard. + Este produto inclui software desenvolvido pelo OpenSSL Project para utilização no OpenSSL Toolkit <https://www.openssl.org/> e software criptográfico escrito por Eric Young e software UPnP escrito por Thomas Bernard. + + + 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 + Os pares enviados para a lista branca não podem ser DoS banidos e as suas transações são sempre retransmitidas, mesmo que já estejam no banco de memória, útil, por exemplo, para um acesso + + + You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain + É necessário reconstruir a base de dados, utilizando -reindex para voltar ao modo de suprimir. Isto irá transferir novamente a cadeia de blocos completa + (default: %u) - (por defeito: %u) + (predefinição: %u) + + + Accept public REST requests (default: %u) + Aceitar pedidos REST públicos (predefinição: %u) + + + Activating best chain... + A activar a melhor cadeia... + + + Attempt to recover private keys from a corrupt wallet.dat on startup + Tentar recuperar chaves privadas de um wallet.dat corrompido ao iniciar + + + Automatically create Tor hidden service (default: %d) + Criar automaticamente o serviço Tor oculto (predefinição: %d) Cannot resolve -whitebind address: '%s' Não foi possível resolver o endereço -whitebind: '%s' + + Connect through SOCKS5 proxy + Ligar através de um proxy SOCKS5 + Copyright (C) 2009-%i The Bitcoin Core Developers Copyright (C) 2009-%i Os Programadores do Bitcoin Core Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - Erro ao carregar wallet.dat: A Carteira requer uma versão mais recente do Bitcoin Core + Erro ao carregar wallet.dat: A carteira requer uma versão mais recente do Bitcoin Core + + + Error reading from database, shutting down. + Erro ao ler da base de dados, encerrando. + + + Imports blocks from external blk000??.dat file on startup + Importar blocos de um ficheiro blk000??.dat externo ao iniciar Information Informação + + Initialization sanity check failed. Bitcoin Core is shutting down. + Falha na prova real inicial. Bitcoin Core está a desligar. + Invalid amount for -maxtxfee=<amount>: '%s' Quantia inválida para -maxtxfee=<quantidade>: '%s' @@ -2944,10 +3384,58 @@ Invalid amount for -mintxfee=<amount>: '%s' Quantia inválida para -mintxfee=<quantidade>: '%s' + + Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) + Montante inválido para -paytxfee=<amount>: '%s' (deverá ser no mínimo %s) + + + Invalid netmask specified in -whitelist: '%s' + Máscara de rede inválida especificada em -whitelist: '%s' + + + Keep at most <n> unconnectable transactions in memory (default: %u) + Manter no máximo <n> transacções órfãs em memória (padrão: %u) + + + Need to specify a port with -whitebind: '%s' + Necessário especificar uma porta com -whitebind: '%s' + + + Node relay options: + Opções da transmissão de nós: + + + RPC server options: + Opções do servidor RPC: + + + Rebuild block chain index from current blk000??.dat files on startup + Reconstruir a cadeia de blocos a partir dos ficheiros blk000??.dat actuais ao iniciar + + + Receive and display P2P network alerts (default: %u) + Receber e mostrar alertas da rede P2P (padrão: %u) + + + Reducing -maxconnections from %d to %d, because of system limitations. + Reduzindo -maxconnections de %d para %d, devido a limitações no sistema. + + + Rescan the block chain for missing wallet transactions on startup + Procurar transacções em falta na cadeia de blocos ao iniciar + Send trace/debug info to console instead of debug.log file Enviar informação de rastreio/depuração para a consola e não para o ficheiro debug.log + + Send transactions as zero-fee transactions if possible (default: %u) + Enviar como uma transacção a custo zero se possível (padrão: %u) + + + Show all debugging options (usage: --help -help-debug) + Mostrar todas as opções de depuração (utilização: --help -help-debug) + Shrink debug.log file on client startup (default: 1 when no -debug) Encolher ficheiro debug.log ao iniciar o cliente (por defeito: 1 sem -debug definido) @@ -2956,6 +3444,22 @@ Signing transaction failed Falhou assinatura da transação + + The transaction amount is too small to pay the fee + O montante da transacção é demasiado baixo para pagar a taxa + + + This is experimental software. + Isto é software experimental. + + + Tor control port password (default: empty) + Palavra-passe da porta de controlo Tor (predefinição: vazio) + + + Tor control port to use if onion listening enabled (default: %s) + Porta de controlo Tor a utilizar se a escuta cebola estiver ativada (predefinição: %s) + Transaction amount too small Quantia da transação é muito baixa @@ -2964,10 +3468,22 @@ Transaction amounts must be positive Quantia da transação deverá ser positiva + + Transaction too large for fee policy + Transacção demasiado grande para a política de taxas + Transaction too large Transação grande demais + + Unable to bind to %s on this computer (bind returned error %s) + Incapaz de vincular à porta %s neste computador (vínculo retornou erro %s) + + + Upgrade wallet to latest format on startup + Actualizar carteira para o formato mais recente ao iniciar + Username for JSON-RPC connections Nome de utilizador para ligações JSON-RPC @@ -2980,10 +3496,22 @@ Warning Aviso + + Warning: unknown new rules activated (versionbit %i) + Aviso: ativadas novas regras desconhecidas (versionbit %i) + + + Whether to operate in a blocks only mode (default: %u) + Se operar apenas num modo de blocos (predefinição: %u) + Zapping all transactions from wallet... A limpar todas as transações da carteira... + + ZeroMQ notification options: + Opções de notificação ZeroMQ: + wallet.dat corrupt, salvage failed wallet.dat corrompido, recuperação falhou @@ -3006,27 +3534,107 @@ Loading addresses... - A carregar endereços... + A carregar os endereços... Error loading wallet.dat: Wallet corrupted Erro ao carregar wallet.dat: Carteira danificada + + (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) + (1 = guardar metadados da transacção ex: proprietário da conta e informação do pedido de pagamento, 2 = descartar metadados da transacção) + + + -maxtxfee is set very high! Fees this large could be paid on a single transaction. + -maxtxfee está definido com um valor muito alto! Taxas desta magnitude podem ser pagas numa única transacção. + + + -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + -paytxfee está definido com um valor muito alto! Esta é a taxa que irá pagar se enviar uma transacção. + + + Do not keep transactions in the mempool longer than <n> hours (default: %u) + Não guardar transações no banco de memória por mais de <n> horas (predefinição: %u) + + + Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Erro ao ler wallet.dat! Todas as chaves foram lidas correctamente, mas os dados das transacções ou do livro de endereços podem estar em falta ou incorrectos. + + + Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) + Taxas (em %s/kB) abaixo deste valor são consideradas nulas para a criação de transacções (padrão: %s) + + + How thorough the block verification of -checkblocks is (0-4, default: %u) + Minuciosidade da verificação de blocos para -checkblocks é (0-4, padrão: %u) + + + Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u) + Manter um índice de transacções completo, usado pela chamada RPC getrawtransaction (padrão: %u) + + + Number of seconds to keep misbehaving peers from reconnecting (default: %u) + Número de segundos a impedir que pares com comportamento indesejado se liguem de novo (padrão: %u) + + + Output debugging information (default: %u, supplying <category> is optional) + Informação de depuração (padrão: %u, fornecer uma <category> é opcional) + + + Support filtering of blocks and transaction with bloom filters (default: %u) + Suportar filtragem de blocos e transacções com fitros bloom (padrão: %u) + + + Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments. + Comprimento total da entrada da versão de rede (%i) excede o comprimento máximo (%i). Reduzir o número ou o tamanho de uacomments. + + + Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d) + Tenta manter o tráfego externo abaixo do limite especificado (em MiB por 24h), 0 = sem limite (padrão: %d) + + + Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported. + Encontrado um argumento não suportado -socks. Definir a versão do SOCKS já não é possível, apenas proxies SOCKS5 são suportados. + + + Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s) + Use um proxy SOCKS5 separado para alcançar pares via serviços ocultos do Tor (padrão: %s) + + + Username and hashed password for JSON-RPC connections. The field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A canonical python script is included in share/rpcuser. This option can be specified multiple times + Username e hash da password para ligações JSON-RPC. O campo <userpw> está no formato: <USERNAME>:<SALT>$<HASH>. Um script python está incluido em share/rpcuser. Esta opção pode ser especificada múltiplas vezes. + (default: %s) - (por defeito: %s) + (predefinição: %s) + + + Always query for peer addresses via DNS lookup (default: %u) + Utilizar sempre a consulta de DNS para endereços de pares (predefinição: %u) Error loading wallet.dat Erro ao carregar wallet.dat + + Generate coins (default: %u) + Gerar moedas (predefinição: %u) + + + How many blocks to check at startup (default: %u, 0 = all) + Quantos blocos para verificar no arranque (predefinição: %u, 0 = todos) + + + Include IP addresses in debug output (default: %u) + Incluir endereços de IP na informação de depuração (predefinição: %u) + Invalid -proxy address: '%s' Endereço -proxy inválido: '%s' Listen for JSON-RPC connections on <port> (default: %u or testnet: %u) - Escutar por ligações JSON-RPC na porta <port> (por defeito: %u ou rede de testes: %u) + Escutar por ligações JSON-RPC na porta <port> (predefinição: %u ou rede de testes: %u) Listen for connections on <port> (default: %u or testnet: %u) @@ -3036,6 +3644,10 @@ Maintain at most <n> connections to peers (default: %u) Manter no máximo <n> ligações a outros nós da rede (por defeito: %u) + + Make the wallet broadcast transactions + Colocar a carteira a transmitir transacções + Maximum per-connection receive buffer, <n>*1000 bytes (default: %u) Maximo armazenamento intermédio de recepção por ligação, <n>*1000 bytes (por defeito: %u) @@ -3048,9 +3660,17 @@ Prepend debug output with timestamp (default: %u) Adicionar data e hora à informação de depuração (por defeito: %u) + + Relay and mine data carrier transactions (default: %u) + Propagar e minerar transacções que incluem dados (padrão: %u) + + + Relay non-P2SH multisig (default: %u) + Propagar não P2SH multisig (predefinição: %u) + Set key pool size to <n> (default: %u) - Definir o tamanho da memória de chaves para <n> (por defeito: %u) + Definir tamanho do banco de memória da chave para <n> (predefinição: %u) Set minimum block size in bytes (default: %u) @@ -3068,6 +3688,18 @@ Specify connection timeout in milliseconds (minimum: 1, default: %d) Especificar tempo de espera da ligação em milissegundos (mínimo 1, por defeito: %d) + + Specify pid file (default: %s) + Especificar ficheiro pid (padrão: %s) + + + Spend unconfirmed change when sending transactions (default: %u) + Gastar troco não confirmado ao enviar transacções (padrão: %u) + + + Threshold for disconnecting misbehaving peers (default: %u) + Tolerância para desligar nós com comportamento indesejável (padrão: %u) + Unknown network specified in -onlynet: '%s' Rede desconhecida especificada em -onlynet: '%s' @@ -3090,7 +3722,7 @@ Loading block index... - A carregar índice de blocos... + A carregar o índice de blocos... Add a node to connect to and attempt to keep the connection open @@ -3098,7 +3730,7 @@ Loading wallet... - A carregar carteira... + A carregar a carteira... Cannot downgrade wallet @@ -3114,7 +3746,7 @@ Done loading - Carregamento completo + Carregamento concluído Error diff --git a/src/qt/locale/bitcoin_ro.ts b/src/qt/locale/bitcoin_ro.ts new file mode 100644 index 0000000000000..11ac69f0f2dd1 --- /dev/null +++ b/src/qt/locale/bitcoin_ro.ts @@ -0,0 +1,169 @@ + + + AddressBookPage + + Right-click to edit address or label + Click dreapta pentru a modifica adresa o eticheta + + + Create a new address + Crează o nouă adresă + + + &New + &Nou + + + Copy the currently selected address to the system clipboard + Copiază în notițe adresa selectată în prezent + + + &Copy + &Copiază + + + C&lose + Î&nchide + + + &Copy Address + &Copiază Adresa + + + Delete the currently selected address from the list + Șterge adresa curentă selectata din listă + + + Export the data in the current tab to a file + Exportă datele din tabul curent in fisier + + + &Export + &Exportă + + + Choose the address to send coins to + Indică adresa de expediere a monedelor + + + Choose the address to receive coins with + Indică adresa de a primi monedele + + + + AddressTableModel + + + AskPassphraseDialog + + + BanTableModel + + + BitcoinGUI + + + ClientModel + + + CoinControlDialog + + + EditAddressDialog + + + FreespaceChecker + + + HelpMessageDialog + + + Intro + + + OpenURIDialog + + + OptionsDialog + + + OverviewPage + + + PaymentServer + + + PeerTableModel + + + QObject + + + QRImageWidget + + + RPCConsole + + + ReceiveCoinsDialog + + + ReceiveRequestDialog + + + RecentRequestsTableModel + + + SendCoinsDialog + + + SendCoinsEntry + + + ShutdownWindow + + + SignVerifyMessageDialog + + + SplashScreen + + + TrafficGraphWidget + + + TransactionDesc + + + TransactionDescDialog + + + TransactionTableModel + + + TransactionView + + + UnitDisplayStatusBarControl + + + WalletFrame + + + WalletModel + + + WalletView + + &Export + &Exportă + + + Export the data in the current tab to a file + Exportă datele din tabul curent in fisier + + + + bitcoin-core + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_ro_RO.ts b/src/qt/locale/bitcoin_ro_RO.ts index 8bccf037a73c7..502052dffb296 100644 --- a/src/qt/locale/bitcoin_ro_RO.ts +++ b/src/qt/locale/bitcoin_ro_RO.ts @@ -27,7 +27,7 @@ &Copy Address - &Copiază adresa + &Copiază Adresa Delete the currently selected address from the list @@ -43,15 +43,15 @@ &Delete - Şterge + &Şterge Choose the address to send coins to - Alegeţi adresa unde vreţi să trimiteţi monezile + Alegeţi adresa unde vreţi să trimiteţi monedele Choose the address to receive coins with - Alegeţi adresa unde vreţi să primiţi monezile + Alegeţi adresa unde vreţi să primiţi monedele C&hoose @@ -67,7 +67,7 @@ These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Acestea sînt adresele dumneavoastră Bitcoin pentru efectuarea plăţilor. Verificaţi întotdeauna cantitatea şi adresa de primire înainte de a trimite monezi. + Acestea sînt adresele dumneavoastră Bitcoin pentru efectuarea plăţilor. Verificaţi întotdeauna cantitatea şi adresa de primire înainte de a trimite monede. These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. @@ -222,7 +222,15 @@ BanTableModel - + + IP/Netmask + IP/Netmask + + + Banned Until + Banat până la + + BitcoinGUI @@ -547,7 +555,7 @@ CoinControlDialog Coin Selection - Selectarea monezii + Selectarea monedei Quantity: @@ -874,7 +882,35 @@ command-line options Opţiuni linie de comandă - + + UI Options: + Opţiuni UI: + + + Choose data directory on startup (default: %u) + Alege dosarul de date la pornire (implicit: %u) + + + Set language, for example "de_DE" (default: system locale) + Setează limba, de exemplu: "ro_RO" (implicit: sistem local) + + + Start minimized + Porniţi minimizat + + + Set SSL root certificates for payment request (default: -system-) + Setare rădăcină certificat SSL pentru cerere de plată (implicit: -sistem- ) + + + Show splash screen on startup (default: %u) + Afişează ecran splash la pornire (implicit: %u) + + + Reset all settings changes made over the GUI + Resetează toate schimbările făcute în GUI + + Intro @@ -1011,6 +1047,10 @@ &Network Reţea + + Automatically start Bitcoin Core after logging in to the system. + Porneşte automat Bitcoin Core după logarea în sistem. + &Start Bitcoin Core on system login Porneşte Nucleul Bitcoin la pornirea sistemului @@ -1067,6 +1107,18 @@ Port of the proxy (e.g. 9050) Portul proxy (de exemplu: 9050) + + IPv4 + IPv4 + + + IPv6 + IPv6 + + + Tor + Tor + &Window &Fereastră @@ -1312,6 +1364,10 @@ User Agent Agent utilizator + + Node/Service + Nod/Serviciu + Ping Time Timp ping @@ -1401,10 +1457,6 @@ General General - - Using OpenSSL version - Foloseşte OpenSSL versiunea - Using BerkeleyDB version Foloseşte BerkeleyDB versiunea @@ -1433,6 +1485,14 @@ Current number of blocks Numărul curent de blocuri + + Current number of transactions + Numărul curent de tranzacţii + + + Memory usage + Memorie folosită + Received Recepţionat @@ -1449,6 +1509,10 @@ Select a peer to view detailed information. Selectaţi un partener pentru a vedea informaţiile detaliate. + + Whitelisted + Whitelisted + Direction Direcţie @@ -1457,6 +1521,18 @@ Version Versiune + + Starting Block + Bloc de început + + + Synced Headers + Headere Sincronizate + + + Synced Blocks + Blocuri Sincronizate + User Agent Agent utilizator @@ -1525,6 +1601,26 @@ Clear console Curăţă consola + + &Disconnect Node + &Deconectare nod + + + 1 &hour + 1 &oră + + + 1 &day + 1 &zi + + + 1 &week + 1 &săptămână + + + 1 &year + 1 &an + Welcome to the Bitcoin Core RPC console. Bun venit la consola Nucleului Bitcoin RPC. @@ -1569,6 +1665,14 @@ Outbound Ieşire + + Yes + Da + + + No + Nu + Unknown Necunoscut @@ -1917,6 +2021,10 @@ Copy change Copiază rest + + Total Amount %1 + Suma totală %1 + or sau @@ -1949,6 +2057,10 @@ The recipient address is not valid. Please recheck. Adresa destinatarului nu este validă, vă rugăm să o verificaţi. + + Duplicate address found: addresses should only be used once each. + Adresă duplicat găsită: fiecare adresă ar trebui folosită o singură dată. + Warning: Invalid Bitcoin address Atenţie: Adresa bitcoin nevalidă! @@ -2317,7 +2429,7 @@ 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. - Monezile generate trebuie să crească %1 blocuri înainte să poată fi cheltuite. Cînd aţi generat acest bloc, a fost transmis reţelei pentru a fi adaugat la lanţul de blocuri. Aceasta se poate întîmpla ocazional dacă alt nod generează un bloc la numai cîteva secunde de al dvs. + Monedele generate trebuie să crească %1 blocuri înainte să poată fi cheltuite. Cînd aţi generat acest bloc, a fost transmis reţelei pentru a fi adaugat la lanţul de blocuri. Aceasta se poate întîmpla ocazional dacă alt nod generează un bloc la numai cîteva secunde de al dvs. Debug information diff --git a/src/qt/locale/bitcoin_ru.ts b/src/qt/locale/bitcoin_ru.ts index 00dfd833abfa2..b4546a21578f4 100644 --- a/src/qt/locale/bitcoin_ru.ts +++ b/src/qt/locale/bitcoin_ru.ts @@ -1473,10 +1473,6 @@ General Общие - - Using OpenSSL version - Используется версия OpenSSL - Using BerkeleyDB version Используется версия BerkeleyDB @@ -2995,6 +2991,10 @@ Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) Выполнить команду, когда меняется транзакция в бумажнике (%s в команде заменяется на TxID) + + Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) + Всегда разрешать транзакции, полученные от участников из белого списка (по умолчанию: %d) + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) Задать число потоков проверки скрипта (от %u до %d, 0=авто, <0 = оставить столько ядер свободными, по умолчанию: %d) @@ -3027,6 +3027,10 @@ Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Внимание: похоже, в сети нет полного согласия! Некоторый майнеры, возможно, испытывают проблемы. + + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + Внимание: Получена неизвестная версия блока! Возможно неизвестные правила вступили в силу. + Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Внимание: мы не полностью согласны с подключенными участниками! Вам или другим участникам, возможно, следует обновиться. @@ -3047,6 +3051,10 @@ <category> can be: <category> может быть: + + Append comment to the user agent string + Добавить комментарий к строке пользовательского агента + Block creation options: Параметры создания блоков: @@ -3131,6 +3139,10 @@ Keep the transaction memory pool below <n> megabytes (default: %u) Сбрасывать транзакции из памяти на диск каждые <n> мегабайт (по умолчанию: %u) + + Location of the auth cookie (default: data dir) + Расположение куки входы(по умолчанию: data dir) + Not enough file descriptors available. Недостаточно файловых дескрипторов. @@ -3139,6 +3151,10 @@ Only connect to nodes in network <net> (ipv4, ipv6 or onion) Соединяться только по сети <net> (ipv4, ipv6 или onion) + + Print version and exit + Написать версию и выйти + Prune cannot be configured with a negative value. Удаление блоков не может использовать отрицательное значение. @@ -3195,10 +3211,6 @@ Wallet options: Настройки бумажника: - - Warning: This version is obsolete; upgrade required! - Внимание: эта версия устарела; требуется обновление! - You need to rebuild the database using -reindex to change -txindex Вам необходимо пересобрать базы данных с помощью -reindex, чтобы изменить -txindex @@ -3295,10 +3307,6 @@ Activating best chain... Активируется лучшая цепь... - - Always relay transactions received from whitelisted peers (default: %d) - Всегда транслировать транзакции, полученные из белого списка участников (по умолчанию: %d) - Attempt to recover private keys from a corrupt wallet.dat on startup Попытаться восстановить приватные ключи из повреждённого wallet.dat при запуске @@ -3463,6 +3471,10 @@ Warning Внимание + + Warning: unknown new rules activated (versionbit %i) + Внимание: неизвестные правила вступили в силу(versionbit %i) + Whether to operate in a blocks only mode (default: %u) Будет работать в режиме только блоков (по умолчанию: %u) diff --git a/src/qt/locale/bitcoin_ru_RU.ts b/src/qt/locale/bitcoin_ru_RU.ts index 53a1c1d8a40b9..41e467e496e82 100644 --- a/src/qt/locale/bitcoin_ru_RU.ts +++ b/src/qt/locale/bitcoin_ru_RU.ts @@ -1,6 +1,50 @@ AddressBookPage + + Create a new address + Создать новый адрес + + + &New + Новый + + + Copy the currently selected address to the system clipboard + Copy the currently selected address to the system clipboardый адрес в буфер + + + &Copy + Копировать + + + C&lose + Закрыть + + + &Copy Address + Копировать адрес + + + Delete the currently selected address from the list + Удалить выбранный адрес из списка + + + Export the data in the current tab to a file + Экспортировать данные текущей вкладки в файл + + + &Export + Экспортировать + + + &Delete + Удалить + + + C&hoose + Выбрать + AddressTableModel @@ -226,6 +270,14 @@ WalletView + + &Export + Экспорт + + + Export the data in the current tab to a file + Экспортировать данные текущей вкладки в файл + bitcoin-core diff --git a/src/qt/locale/bitcoin_sk.ts b/src/qt/locale/bitcoin_sk.ts index 8c779cbe98665..9addbdaa8a10e 100644 --- a/src/qt/locale/bitcoin_sk.ts +++ b/src/qt/locale/bitcoin_sk.ts @@ -63,7 +63,7 @@ Receiving addresses - Adresa prijatia + Prijímacia adresa These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. @@ -222,7 +222,15 @@ BanTableModel - + + IP/Netmask + IP/Maska stiete + + + Banned Until + Blokovaný do + + BitcoinGUI @@ -874,7 +882,35 @@ command-line options voľby príkazového riadku - + + UI Options: + Možnosti používateľského rozhrania: + + + Choose data directory on startup (default: %u) + Vyberte dátový priečinok pri štarte (predvolené: %u) + + + Set language, for example "de_DE" (default: system locale) + Nastavte jazyk, napríklad "de_DE" (predvolené: podľa systému) + + + Start minimized + Spustiť minimalizované + + + Set SSL root certificates for payment request (default: -system-) + Nastaviť SSL root certifikáty pre vyžiadanie platby (predvolené: -system-) + + + Show splash screen on startup (default: %u) + Zobraziť uvítaciu obrazovku pri štarte (predvolené: %u) + + + Reset all settings changes made over the GUI + Reštartovať všetky nastavenia urobené v používateľskom rozhraní. + + Intro @@ -1009,7 +1045,7 @@ &Network - Sieť + &Sieť Automatically start Bitcoin Core after logging in to the system. @@ -1025,7 +1061,7 @@ W&allet - Peňaženka + &Peňaženka Expert @@ -1071,13 +1107,37 @@ Port of the proxy (e.g. 9050) Port proxy (napr. 9050) + + Used for reaching peers via: + Použité pre získavanie peerov cez: + + + Shows, if the supplied default SOCKS5 proxy is used to reach peers via this network type. + Zobrazuje, či je poskytované predvolené SOCKS5 proxy používané pre získavanie peerov cez tento typ siete. + + + IPv4 + IPv4 + + + IPv6 + IPv6 + + + Tor + Tor + + + Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services. + Pripojiť k Bitcoinovej sieti cez separované SOCKS5 proxy pre skrytú službu Tor. + Use separate SOCKS5 proxy to reach peers via Tor hidden services: Použiť samostatný SOCKS5 proxy server na dosiahnutie počítačov cez skryté služby Tor: &Window - Okno + &Okno Show only a tray icon after minimizing the window. @@ -1093,7 +1153,7 @@ &Display - &Displej + &Zobrazenie User Interface &language: @@ -1413,10 +1473,6 @@ General Všeobecné - - Using OpenSSL version - Používa OpenSSL verziu - Using BerkeleyDB version Používa BerkeleyDB verziu @@ -1445,6 +1501,18 @@ Current number of blocks Aktuálny počet blokov + + Memory Pool + Pamäť Poolu + + + Current number of transactions + Aktuálny počet tranzakcií + + + Memory usage + Využitie pamäte + Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. Otvoriť Bitcoin log súbor pre ladenie z aktuálneho dátového adresára. Toto môže trvať niekoľko sekúnd pre veľké súbory. @@ -1461,10 +1529,18 @@ &Peers &Partneri + + Banned peers + Zablokované spojenia + Select a peer to view detailed information. Vyberte počítač pre zobrazenie podrobností. + + Whitelisted + Povolené + Direction Smer @@ -1473,6 +1549,19 @@ Version Verzia + + Starting Block + Počiatočný Blok + + + Synced Headers + Synchronizované hlavičky + + + + Synced Blocks + Synchronizované bloky + User Agent Aplikácia @@ -1501,6 +1590,10 @@ Ping Time Čas odozvy + + Ping Wait + Čakanie na ping + Time Offset Časový posun @@ -1549,6 +1642,34 @@ Clear console Vymazať konzolu + + &Disconnect Node + &Odpojené uzly + + + Ban Node for + Blokovať uzol na + + + 1 &hour + 1 &hodinu + + + 1 &day + 1 &deň + + + 1 &week + 1 &týždeň + + + 1 &year + 1 &rok + + + &Unban Node + &odblokovať uzol + Welcome to the Bitcoin Core RPC console. Vitajte v RPC konzole pre Jadro Bitcoin. @@ -1577,6 +1698,10 @@ %1 GB %1 GB + + (node id: %1) + (ID uzlu: %1) + via %1 cez %1 @@ -1593,6 +1718,14 @@ Outbound Odchádzajúce + + Yes + Áno + + + No + Nie + Unknown neznámy @@ -1961,6 +2094,10 @@ Copy change Kopírovať zmenu + + Total Amount %1 + Celkové množstvo %1 + or alebo @@ -1993,6 +2130,10 @@ Payment request expired. Vypršala platnosť požiadavky na platbu. + + Pay only the required fee of %1 + Zaplatiť len vyžadovaný poplatok z %1 + The recipient address is not valid. Please recheck. Adresa príjemcu je neplatná. Prosím, overte ju. @@ -2072,6 +2213,10 @@ Remove this entry Odstrániť túto položku + + 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. + Poplatok sa odpočíta od čiastky, ktorú odosielate. Príjemca dostane menej bitcoinov ako zadáte. Ak je vybraných viacero príjemcov, poplatok je rozdelený rovným dielom. + S&ubtract fee from amount Odpočítať poplatok od s&umy @@ -2126,6 +2271,10 @@ &Sign Message &Podpísať Správu + + The Bitcoin address to sign the message with + Bitcoin adresa pre podpísanie správy s + Choose previously used address Vybrať predtým použitú adresu @@ -2600,6 +2749,10 @@ Copy transaction ID Kopírovať ID transakcie + + Copy raw transaction + Kopírovať celú tranzakciu + Edit label Editovať popis @@ -2747,10 +2900,30 @@ Accept command line and JSON-RPC commands Prijímať príkazy z príkazového riadku a JSON-RPC + + Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. + Skontrolujte správnosť nastavenia dátumu a času na vašom počítači! Ak je čas nesprávny Jadro Bitcoin nebude správne fungovať. + + + Error: A fatal internal error occurred, see debug.log for details + Chyba: Vyskytla sa interná chyba, pre viac informácií zobrazte debug.log + + + Fee (in %s/kB) to add to transactions you send (default: %s) + Poplatok (za %s/kB) pridaný do tranzakcie, ktorú posielate (predvolené: %s) + + + Pruning blockstore... + Redukovanie blockstore... + Run in the background as a daemon and accept commands Bežať na pozadí ako démon a prijímať príkazy + + Unable to start HTTP server. See debug log for details. + Nepodarilo sa spustiť HTTP server. Pre viac detailov zobrazte debug log. + Accept connections from outside (default: 1 if no -proxy or -connect) Prijať spojenia zvonku (predvolené: 1 ak žiadne -proxy alebo -connect) @@ -2783,6 +2956,14 @@ Unable to bind to %s on this computer. Bitcoin Core is probably already running. Nepodarilo sa pripojiť na %s na tomto počítači. Bitcoin Jadro je už pravdepodobne spustené. + + WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) + VAROVANIE: príliš veľa vygenerovaných blokov; %d prijatých blokov v posledných %d hodinách (očakávaných %d) + + + WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) + VAROVANIE: skontrolujte sieťové pripojenie, %d prijatých blokov za posledných %d hodín (očakávané %d) + Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Varovanie: Javí sa že sieť sieť úplne nesúhlasí! Niektorí mineri zjavne majú ťažkosti. @@ -2801,6 +2982,10 @@ The network does not appear to fully agree! Some miners appear to be experiencin Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. Uzle na zoznam povolených, ktoré sa pripájajú z danej netmask alebo IP adresy. Môže byť zadané viac krát. + + -maxmempool must be at least %d MB + -maxmempool musí byť najmenej %d MB + <category> can be: <category> môže byť: @@ -2833,6 +3018,18 @@ The network does not appear to fully agree! Some miners appear to be experiencin Do you want to rebuild the block database now? Chcete znovu zostaviť databázu blokov? + + Enable publish hash block in <address> + Povoliť zverejneneie hash blokov pre <address> + + + Enable publish hash transaction in <address> + Povoliť zverejnenie hash tranzakcií pre <address> + + + Enable publish raw block in <address> + Povoliť zverejnenie raw bloku pre <address> + Error initializing block database Chyba inicializácie databázy blokov @@ -2869,6 +3066,10 @@ The network does not appear to fully agree! Some miners appear to be experiencin Invalid -onion address: '%s' Neplatná -onion adresa: '%s' + + Invalid amount for -fallbackfee=<amount>: '%s' + Neplatná suma pre -fallbackfee=<amount>: '%s' + Not enough file descriptors available. Nedostatok kľúčových slov súboru. @@ -2877,6 +3078,14 @@ The network does not appear to fully agree! Some miners appear to be experiencin Only connect to nodes in network <net> (ipv4, ipv6 or onion) Pripojiť iba k uzlom v sieti <net> (ipv4, ipv6, alebo onion) + + Prune cannot be configured with a negative value. + Redukovanie nemôže byť nastavené na zápornú hodnotu. + + + Prune mode is incompatible with -txindex. + Redukovanie je nekompatibilné s -txindex. + Set database cache size in megabytes (%d to %d, default: %d) Nastaviť veľkosť pomocnej pamäti databázy v megabajtoch (%d do %d, prednastavené: %d) @@ -2889,6 +3098,18 @@ The network does not appear to fully agree! Some miners appear to be experiencin Specify wallet file (within data directory) Označ súbor peňaženky (v priečinku s dátami) + + Unsupported argument -benchmark ignored, use -debug=bench. + Nepodporovaný parameter -benchmark bol ignorovaný, použite -debug=bench. + + + Unsupported argument -debugnet ignored, use -debug=net. + Nepodporovaný argument -debugnet bol ignorovaný, použite -debug=net. + + + Unsupported argument -tor found, use -onion. + Nepodporovaný argument -tor, použite -onion. + Use UPnP to map the listening port (default: %u) Použiť UPnP pre mapovanie počúvajúceho portu (predvolené: %u) @@ -2933,6 +3154,10 @@ The network does not appear to fully agree! Some miners appear to be experiencin Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) Vytvoriť nové súbory z predvolenými systémovými právami, namiesto umask 077 (funguje iba z vypnutou funkcionalitou peňaženky) + + Discover own IP addresses (default: 1 when listening and no -externalip or -proxy) + Zisti vlastnú IP adresu (predvolené: 1 pre listen a -externalip alebo -proxy) + Error: Listening for incoming connections failed (listen returned error %s) Chyba: Počúvanie prichádzajúcich spojení zlyhalo (vrátená chyba je %s) @@ -2965,6 +3190,10 @@ The network does not appear to fully agree! Some miners appear to be experiencin Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) Nastaviť počet vlákien pre generáciu mincí (-1 = všetky jadrá, predvolené: %d) + + The transaction amount is too small to send after the fee has been deducted + Suma je príliš malá pre odoslanie tranzakcie + This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard. Tento produkt obsahuje softvér vyvinutý projektom OpenSSL pre použitie sady nástrojov OpenSSL <https://www.openssl.org/> a kryptografického softvéru napísaného Eric Young a UPnP softvér napísaný Thomas Bernard. @@ -2981,6 +3210,18 @@ The network does not appear to fully agree! Some miners appear to be experiencin Accept public REST requests (default: %u) Akceptovať verejné REST žiadosti (predvolené: %u) + + Activating best chain... + Aktivácia najlepšej reťaze... + + + Attempt to recover private keys from a corrupt wallet.dat on startup + Pokus o obnovenie privátnych kľúčov z poškodenej wallet.dat pri spustení + + + Automatically create Tor hidden service (default: %d) + Automaticky vytvoriť skrytú službu Tor (predvolené: %d) + Cannot resolve -whitebind address: '%s' Nedá sa vyriešiť -whitebind adresa: '%s' @@ -3001,10 +3242,18 @@ The network does not appear to fully agree! Some miners appear to be experiencin Error reading from database, shutting down. Chyba pri načítaní z databázy, ukončuje sa. + + Imports blocks from external blk000??.dat file on startup + Importovať bloky z externého súboru blk000??.dat pri štarte + Information Informácia + + Initialization sanity check failed. Bitcoin Core is shutting down. + Inicializačná kontrola zlyhala. Jadro Bitcoin sa ukončuje. + Invalid amount for -maxtxfee=<amount>: '%s' Neplatná suma pre -maxtxfee=<amount>: '%s' @@ -3065,10 +3314,18 @@ The network does not appear to fully agree! Some miners appear to be experiencin Signing transaction failed Podpísanie správy zlyhalo + + The transaction amount is too small to pay the fee + Suma tranzakcie je príliš malá na zaplatenie poplatku + This is experimental software. Toto je experimentálny softvér. + + Tor control port password (default: empty) + Heslo na kontrolu portu pre Tor (predvolené: žiadne) + Transaction amount too small Suma transakcie príliš malá @@ -3089,10 +3346,18 @@ The network does not appear to fully agree! Some miners appear to be experiencin Unable to bind to %s on this computer (bind returned error %s) Na tomto počítači sa nedá vytvoriť väzba %s (vytvorenie väzby vrátilo chybu %s) + + Upgrade wallet to latest format on startup + Aktualizovať peňaženku na posledný formát pri štarte + Username for JSON-RPC connections Užívateľské meno pre JSON-RPC spojenia + + Wallet needed to be rewritten: restart Bitcoin Core to complete + Peňaženka musí byť prepísaná: pre dokončenie reštartujte Jadro Bitcoin + Warning Upozornenie diff --git a/src/qt/locale/bitcoin_sl_SI.ts b/src/qt/locale/bitcoin_sl_SI.ts index c62c8cf273054..1b540a7310f08 100644 --- a/src/qt/locale/bitcoin_sl_SI.ts +++ b/src/qt/locale/bitcoin_sl_SI.ts @@ -427,7 +427,7 @@ %n active connection(s) to Bitcoin network - %n aktivna povezava v bitcoin omrežje%n aktivni povezavi v bitcoin omrežje%n aktivne povezave v bitcoin omrežje%n aktivnih povezav v bitcoin omrežje + %n aktivna povezava v omrežje Bitcoin%n aktivni povezavi v omrežje Bitcoin%n aktivne povezave v omrežje Bitcoin%n aktivnih povezav v omrežje Bitcoin No block source available... @@ -463,7 +463,7 @@ Last received block was generated %1 ago. - Zadnji prejeti blok je bil ustvarjen %1 nazaj. + Zadnji prejeti blok je star %1. Transactions after this will not yet be visible. @@ -1322,7 +1322,7 @@ Node/Service - Vozlišče/Storitev + Naslov Ping Time @@ -1413,10 +1413,6 @@ General Splošno - - Using OpenSSL version - OpenSSL različica v rabi - Using BerkeleyDB version BerkeleyDB različica v rabi @@ -2437,7 +2433,7 @@ Open for %n more block(s) - Odprto še %n blokOdprto še %n blokaOdprto še %n blokeOdprto še %n blokov + Še %n blok do potrditveŠe %n bloka do potrditveŠe %n bloki do potrditveŠe %n blokov do potrditve unknown @@ -2471,7 +2467,7 @@ Open for %n more block(s) - Odprto še %n blokOdprto še %n blokaOdprto še %n blokeOdprto še %n blokov + Še %n blok do potrditveŠe %n bloka do potrditveŠe %n bloki do potrditveŠe %n blokov do potrditve Open until %1 @@ -2955,10 +2951,6 @@ Wallet options: Izbire denarnice: - - Warning: This version is obsolete; upgrade required! - Opozorilo: Različica vašega odjemalca je zastarela. Potrebna je nadgradnja! - You need to rebuild the database using -reindex to change -txindex Ob spremembi vrednosti opcije -txindex boste morali obnoviti bazo podatkov z uporabo opcije -reindex @@ -3009,7 +3001,7 @@ Activating best chain... - Preklapljam na najboljšo verigo ... + Prehajam na najboljšo verigo ... Cannot resolve -whitebind address: '%s' diff --git a/src/qt/locale/bitcoin_sq.ts b/src/qt/locale/bitcoin_sq.ts index 994b065994e38..d87bd9db5811a 100644 --- a/src/qt/locale/bitcoin_sq.ts +++ b/src/qt/locale/bitcoin_sq.ts @@ -29,6 +29,10 @@ Delete the currently selected address from the list Fshi adresen e selektuar nga lista + + Export the data in the current tab to a file + Eksporto të dhënat e skedës korrente në një skedar + &Delete &Fshi @@ -790,6 +794,10 @@ WalletView + + Export the data in the current tab to a file + Eksporto të dhënat e skedës korrente në një skedar + bitcoin-core diff --git a/src/qt/locale/bitcoin_sr@latin.ts b/src/qt/locale/bitcoin_sr@latin.ts new file mode 100644 index 0000000000000..c836c8ddbaedb --- /dev/null +++ b/src/qt/locale/bitcoin_sr@latin.ts @@ -0,0 +1,653 @@ + + + AddressBookPage + + Right-click to edit address or label + Klikni desnim tasterom za uređivanje adrese ili oznake + + + Create a new address + Kreiraj novu adresu + + + &New + &Novi + + + Copy the currently selected address to the system clipboard + Kopiraj selektovanu adresu u sistemski klipbord + + + &Copy + &Kopiraj + + + C&lose + Zatvori + + + &Copy Address + Kopiraj adresu + + + Delete the currently selected address from the list + Briše trenutno izabranu adresu sa liste + + + Export the data in the current tab to a file + Izvoz podataka iz trenutne kartice u datoteku + + + &Export + &Izvoz + + + &Delete + &Izbrisati + + + Choose the address to send coins to + Izaberi adresu za slanje bitkoina + + + Choose the address to receive coins with + Izaberi adresu za primanje bitkoina + + + C&hoose + I&zaberi + + + Sending addresses + Adrese za slanje + + + Receiving addresses + Adrese za primanje + + + These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. + Ovo su vase Bitkoin adrese za slanje bitkoina. Uvek proverite unetu kolicinu bitkoina i adresu za slanje bitkoin pre slanja. + + + These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. + Ovo su vase Bitkoin adrese za primanje bitkoina. Preporuceno je da koristite drugaciju adresu za primanje kod svake transakcije. + + + &Edit + &Izmeni + + + Export Address List + Izvezi listu adresa + + + Comma separated file (*.csv) + Zapetom odvojene ('.csv) datoteke + + + Exporting Failed + Izvoz nije uspeo + + + There was an error trying to save the address list to %1. Please try again. + Dogodila se greska prilikom cuvanja adrese u %1. Molimo pokusajte ponovo. + + + + AddressTableModel + + Label + Etiketa + + + Address + Adresa + + + (no label) + (bez etikete) + + + + AskPassphraseDialog + + Passphrase Dialog + Dialog pristupne fraze + + + Enter passphrase + Unesi pristupnu frazu + + + New passphrase + Nova pristupna fraza + + + Repeat new passphrase + Ponovo unesite pristupnu frazu + + + Encrypt wallet + Enkriptuj/Sifruj novcanik + + + This operation needs your wallet passphrase to unlock the wallet. + Da bi ste otkljucali novcanik potrebno je da unesete pristupnu frazu + + + Unlock wallet + Otkljucaj novcanik + + + This operation needs your wallet passphrase to decrypt the wallet. + Da bi ste dekriptovali/desifrovali novcanik potrebno je da unesete pristupnu frazu + + + Decrypt wallet + Dekriptuj/Desifruj novcanik + + + Change passphrase + Izmeni pristupnu frazu + + + Confirm wallet encryption + Potvrdite enkripciju/sifrovanje novcanika + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! + Upozorenje: Ako ekriptujete/sifrujete novcanik, a izgubite pristupnu frazu <b>IZGUBICETE SVE VASE BITKOINE</b>! + + + Are you sure you wish to encrypt your wallet? + Da li ste sigurni da zelite da enkriptujete/sifrujete novcanik? + + + Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. + Bitcoin Core ce se sada zatvoriti radi zavrsavanje procesa enkripcije/sifrovanja novcanika. Zapamtite da enkriptovanje/sifrovanje novcanika ne moze u potpunosti da zastiti vase bitkoine od kradje od strane virusa koji su zarazili vas racunar. + + + 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. + VAZNO : Bilo koja prethodne rezervne kopije koje ste nacinili od svoje datoteke novcanika treba da se zamene sa novogenerisanom, sifrovanom datotekom novcanika. Iz bezbednosnih razloga, prethodne rezervne kopije su nezasifrovanih datoteka novcanika ce postati beskorisne cim pocnete da koristite novi, sifrovani novčanik. + + + Warning: The Caps Lock key is on! + Upozorenje: Dugme Caps Lock je upaljeno + + + Wallet encrypted + Novcanik je enkriptovan/sifrovan + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. + Unesite novu pristupnu frazu u novcanik.<br/>Molimo koristite pristupnu frazu od <br/>deset ili vise nasumicnih karaktera <br/>, ili <b>osm ili vise reci </b>. + + + Enter the old passphrase and new passphrase to the wallet. + Unesite staru pristupnu frazu i novu pristupnu frazu u novcanik. + + + Wallet encryption failed + Ekripcija/Sifrovanje novcanika nije uspelo + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Enkriptovanje/Sifrovanje novcanika nije uspelo zbog greske. Vas novcanik nije enkriptovan/sifrovan. + + + The supplied passphrases do not match. + Uneta pristupne fraze se ne podudaraju + + + Wallet unlock failed + Otkljucavanje novcanika nije uspelo + + + The passphrase entered for the wallet decryption was incorrect. + Pristupna fraza za dekriptovanje/desifrovanje novcanika nije tacna. + + + Wallet decryption failed + Dekriptovanje/desifrovanje novcanika nije uspelo + + + Wallet passphrase was successfully changed. + Pristupna fraza novcanika je uspesno promenjena. + + + + BanTableModel + + IP/Netmask + IP/Netmask + + + Banned Until + Banovani ste do + + + + BitcoinGUI + + Bitcoin Core + Bitcoin Core + + + Error + Greska + + + + ClientModel + + + CoinControlDialog + + Amount + Kolicina + + + Date + Datum + + + (no label) + (bez etikete) + + + + EditAddressDialog + + + FreespaceChecker + + + HelpMessageDialog + + Bitcoin Core + Bitcoin Core + + + + Intro + + Bitcoin Core + Bitcoin Core + + + Error + Greska + + + + OpenURIDialog + + + OptionsDialog + + + OverviewPage + + + PaymentServer + + + PeerTableModel + + + QObject + + Amount + Kolicina + + + + QRImageWidget + + + RPCConsole + + + ReceiveCoinsDialog + + + ReceiveRequestDialog + + Address + Adresa + + + Amount + Kolicina + + + Label + Etiketa + + + Message + Poruka + + + + RecentRequestsTableModel + + Date + Datum + + + Label + Etiketa + + + Message + Poruka + + + Amount + Kolicina + + + (no label) + (bez etikete) + + + + SendCoinsDialog + + (no label) + (bez etikete) + + + + SendCoinsEntry + + + ShutdownWindow + + + SignVerifyMessageDialog + + + SplashScreen + + Bitcoin Core + Bitcoin Core + + + The Bitcoin Core developers + Razvojni tim Bitcoin Core + + + + TrafficGraphWidget + + + TransactionDesc + + %1/offline + %1/van mreze + + + %1/unconfirmed + %1/nepotvrdjeno + + + %1 confirmations + %1 potvrdjeno/ih + + + Status + Stanje/Status + + + Date + Datum + + + Source + Izvor + + + Generated + Generisano + + + From + Od + + + To + Kome + + + own address + sopstvena adresa + + + watch-only + samo za gledanje + + + label + etiketa + + + Credit + Kredit + + + not accepted + nije prihvaceno + + + Debit + Zaduzenje + + + Total debit + Ukupno zaduzenje + + + Total credit + Totalni kredit + + + Transaction fee + Taksa transakcije + + + Net amount + Neto iznos + + + Message + Poruka + + + Comment + Komentar + + + Transaction ID + ID Transakcije + + + Merchant + Trgovac + + + Debug information + Informacije debugovanja + + + Transaction + Transakcije + + + Inputs + Unosi + + + Amount + Kolicina + + + true + tacno + + + false + netacno + + + , has not been successfully broadcast yet + , nisu uspesno jos emitovano + + + unknown + nepoznato + + + + TransactionDescDialog + + Transaction details + Detalji transakcije + + + + TransactionTableModel + + Date + Datum + + + Type + Tip + + + Label + Etiketa + + + Received with + Primljeno uz + + + Received from + Primljeno od + + + Sent to + Poslat + + + Payment to yourself + Placanje samom sebi + + + Mined + Iskopano + + + watch-only + samo za gledanje + + + + TransactionView + + Received with + Primljeno uz + + + Sent to + Poslat + + + Mined + Iskopano + + + Exporting Failed + Izvoz nije uspeo + + + Comma separated file (*.csv) + Zarezom odvojene ('.csv) datoteke + + + Date + Datum + + + Type + Tip + + + Label + Etiketa + + + Address + Adresa + + + + UnitDisplayStatusBarControl + + + WalletFrame + + + WalletModel + + + WalletView + + &Export + &Izvoz + + + Export the data in the current tab to a file + Izvoz podataka iz trenutne kartice u datoteku + + + + bitcoin-core + + Insufficient funds + Nedovoljno sredstava + + + Loading block index... + Ucitavanje indeksa bloka... + + + Add a node to connect to and attempt to keep the connection open + Dodajte cvor za povezivanje, da bi pokusali da odrzite vezu otvorenom + + + Loading wallet... + Ucitavanje novcanika... + + + Cannot write default address + Nije moguce ispisivanje podrazumevane adrese + + + Rescanning... + Ponovno skeniranje... + + + Done loading + Zavrseno ucitavanje + + + Error + Greska + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_sv.ts b/src/qt/locale/bitcoin_sv.ts index 756114351f880..acf37bd1d4eee 100644 --- a/src/qt/locale/bitcoin_sv.ts +++ b/src/qt/locale/bitcoin_sv.ts @@ -1474,10 +1474,6 @@ Var vänlig och försök igen. General Generell - - Using OpenSSL version - Använder OpenSSL version - Using BerkeleyDB version Använder BerkeleyDB versionen @@ -2980,6 +2976,18 @@ Var vänlig och försök igen. Accept connections from outside (default: 1 if no -proxy or -connect) Acceptera anslutningar utifrån (förvalt: 1 om ingen -proxy eller -connect) + + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. + -fallbackfee är satt väldigt högt! Detta är avgiften du kan komma att betala om uppskattad avgift inte finns tillgänglig. + + + A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s) + En avgiftskurs (i %s/kB) som används när det inte finns tillräcklig data för att uppskatta avgiften (förvalt: %s) + + + Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d) + Acceptera vidarebefodrade transaktioner från vitlistade noder även när transaktioner inte vidarebefodras (förvalt: %d) + Bind to given address and always listen on it. Use [host]:port notation for IPv6 Bind till given adress och lyssna alltid på den. Använd [värd]:port notation för IPv6 @@ -2996,6 +3004,10 @@ Var vänlig och försök igen. Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) Exekvera kommando när en plånbokstransaktion ändras (%s i cmd är ersatt av TxID) + + Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) + Vidarebefodra alltid transaktioner från vitlistade noder även om de bryter mot lokala reläpolicyn (förvalt: %d) + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) Ange antalet skriptkontrolltrådar (%u till %d, 0 = auto, <0 = lämna så många kärnor lediga, förval: %d) @@ -3012,6 +3024,10 @@ Var vänlig och försök igen. Unable to bind to %s on this computer. Bitcoin Core is probably already running. Det går inte att binda till %s på den här datorn. Bitcoin Core är förmodligen redan igång. + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + Argumentet -whitelistalwaysrelay stöds inte utan ignoreras, använd -whitelistrelay och/eller -whitelistforcerelay. + Use UPnP to map the listening port (default: 1 when listening and no -proxy) Använd UPnP för att mappa den lyssnande porten (förvalt: 1 när lyssning aktiverat och utan -proxy) @@ -3028,6 +3044,10 @@ Var vänlig och försök igen. Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Varning: Nätverket verkar inte vara helt överens! Några miners verkar ha problem. + + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + Varning: Okända blockversioner bryts! Det är möjligt att okända regler används + Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Varning: Vi verkar inte helt överens med våra peers! Du kan behöva uppgradera, eller andra noder kan behöva uppgradera. @@ -3048,6 +3068,10 @@ Var vänlig och försök igen. <category> can be: <category> Kan vara: + + Append comment to the user agent string + Lägg till kommentar till user-agent-strängen + Block creation options: Block skapande inställningar: @@ -3092,6 +3116,10 @@ Var vänlig och försök igen. Enable publish raw transaction in <address> Aktivera publicering av råa transaktioner i <adress> + + Enable transaction replacement in the memory pool (default: %u) + Aktivera byte av transaktioner i minnespoolen (förvalt: %u) + Error initializing block database Fel vid initiering av blockdatabasen @@ -3128,10 +3156,22 @@ Var vänlig och försök igen. Invalid -onion address: '%s' Ogiltig -onion adress:'%s' + + Invalid amount for -fallbackfee=<amount>: '%s' + Ogiltigt belopp för -fallbackfee=<belopp>: '%s' + Keep the transaction memory pool below <n> megabytes (default: %u) Håll minnespoolen över transaktioner under <n> megabyte (förvalt: %u) + + Location of the auth cookie (default: data dir) + Plats för authcookie (förvalt: datamapp) + + + Minimum bytes per sigop in transactions we relay and mine (default: %u) + Minimum antal byte per sigop i transaktioner som vi reläar och bryter (förvalt: %u) + Not enough file descriptors available. Inte tillräckligt med filbeskrivningar tillgängliga. @@ -3140,6 +3180,10 @@ Var vänlig och försök igen. Only connect to nodes in network <net> (ipv4, ipv6 or onion) Anslut enbart till noder i nätverket <net> (IPv4, IPv6 eller onion) + + Print version and exit + Visa version och avsluta + Prune cannot be configured with a negative value. Beskärning kan inte konfigureras med ett negativt värde. @@ -3196,10 +3240,6 @@ Var vänlig och försök igen. Wallet options: Plånboksinställningar: - - Warning: This version is obsolete; upgrade required! - Varning: Denna version är föråldrad; uppgradering krävs! - You need to rebuild the database using -reindex to change -txindex Du måste återskapa databasen med -reindex för att ändra -txindex @@ -3296,10 +3336,6 @@ Var vänlig och försök igen. Activating best chain... Aktiverar bästa kedjan... - - Always relay transactions received from whitelisted peers (default: %d) - Vidarebefordra alltid transaktioner från vitlistade noder (förval: %d) - Attempt to recover private keys from a corrupt wallet.dat on startup Försök att rädda privata nycklar från en korrupt wallet.dat vid uppstart @@ -3464,6 +3500,10 @@ Var vänlig och försök igen. Warning Varning + + Warning: unknown new rules activated (versionbit %i) + Varning: okända nya regler aktiverade (versionsbit %i) + Whether to operate in a blocks only mode (default: %u) Ska allt göras i endast block-läge (förval: %u) diff --git a/src/qt/locale/bitcoin_ta.ts b/src/qt/locale/bitcoin_ta.ts new file mode 100644 index 0000000000000..c93524cdacc2f --- /dev/null +++ b/src/qt/locale/bitcoin_ta.ts @@ -0,0 +1,1029 @@ + + + AddressBookPage + + Create a new address + ஒரு புதிய முகவரியை உருவாக்கு + + + &New + &புதிய + + + &Copy + &நகல் + + + C&lose + &மூடு + + + &Copy Address + &முகவரியை நகலெடு + + + &Export + &ஏற்றுமதி + + + &Delete + &அழி + + + C&hoose + &தேர்ந்தெடு + + + Sending addresses + அனுப்பும் முகவரிகள் + + + Receiving addresses + பெறும் முகவரிகள் + + + &Edit + &தொகு + + + + AddressTableModel + + Label + லேபிள் + + + Address + விலாசம் + + + + AskPassphraseDialog + + Encrypt wallet + என்க்ரிப்ட் பணப்பை + + + Decrypt wallet + டிக்ரிப்ட் பணப்பை + + + + BanTableModel + + IP/Netmask + IP/Netmask + + + + BitcoinGUI + + &Overview + &கண்ணோட்டம் + + + &Transactions + &பரிவர்த்தனைகள் + + + E&xit + &வெளியேறு + + + Quit application + விலகு + + + About &Qt + &Qt-ஐ பற்றி + + + &Options... + &விருப்பங்கள்... + + + &Encrypt Wallet... + &என்க்ரிப்ட் பணப்பை... + + + Open &URI... + &URI-ஐ திற + + + &Verify message... + &செய்தியை சரிசெய்... + + + Bitcoin + Bitcoin + + + Wallet + பணப்பை + + + &Send + &அனுப்பு + + + &Receive + &பெறு + + + &Show / Hide + &காட்டு/மறை + + + &File + &கோப்பு + + + &Settings + &அமைப்பு + + + &Help + &உதவி + + + Bitcoin Core + Bitcoin மையம் + + + %n hour(s) + %n மணி%n மணி + + + %1 and %2 + %1 மற்றும் %2 + + + %1 behind + %1 பின்னால் + + + Error + தவறு + + + Warning + எச்சரிக்கை + + + Information + தகவல் + + + Date: %1 + + தேதி: %1 + + + + Amount: %1 + + தொகை: %1 + + + + Type: %1 + + வகை: %1 + + + + Address: %1 + + முகவரி: %1 + + + + Sent transaction + அனுப்பிய பரிவர்த்தனை + + + + ClientModel + + Network Alert + பிணைய எச்சரிக்கை + + + + CoinControlDialog + + Quantity: + அளவு + + + Amount: + விலை: + + + Priority: + முன்னுரிமை + + + Fee: + கட்டணம்: + + + After Fee: + கட்டணத்திறகுப் பின்: + + + Change: + மாற்று: + + + Amount + விலை + + + Date + தேதி + + + Confirmations + உறுதிப்படுத்தல்கள் + + + Confirmed + உறுதியாக + + + Priority + முன்னுரிமை + + + Copy address + பிரதியை முகவரியை + + + Copy amount + நகலை தொகை + + + none + none + + + yes + ஆம் + + + no + இல்லை + + + + EditAddressDialog + + + FreespaceChecker + + name + பெயர் + + + + HelpMessageDialog + + Bitcoin Core + Bitcoin மையம் + + + About Bitcoin Core + Bitcoin மையம் பற்றி + + + + Intro + + Welcome + நல்வரவு + + + Bitcoin Core + Bitcoin மையம் + + + Error + தவறு + + + + OpenURIDialog + + Open URI + URI-ஐ திற + + + URI: + URI: + + + + OptionsDialog + + Options + விருப்பத்தேர்வு + + + &Main + &தலைமை + + + MB + MB + + + &Network + &பிணையம் + + + W&allet + &பணப்பை + + + Expert + வல்லுநர் + + + IPv4 + IPv4 + + + IPv6 + IPv6 + + + Tor + Tor + + + &Window + &சாளரம் + + + &Display + &காட்டு + + + &OK + &சரி + + + &Cancel + &ரத்து + + + default + இயல்புநிலை + + + none + none + + + + OverviewPage + + Form + படிவம் + + + Available: + கிடைக்ககூடிய: + + + Pending: + நிலுவையில்: + + + Immature: + முதிராத: + + + Balances + மீதி + + + Total: + மொத்தம்: + + + + PaymentServer + + + PeerTableModel + + User Agent + பயனர் முகவர் + + + Ping Time + பிங் நேரம் + + + + QObject + + Amount + விலை + + + %1 d + %1 d + + + %1 h + %1 h + + + %1 s + %1 s + + + N/A + N/A + + + %1 ms + %1 ms + + + + QRImageWidget + + &Save Image... + &படத்தை சேமி... + + + &Copy Image + &படத்தை + + + Save QR Code + QR குறியீடு காப்பாற்ற + + + PNG Image (*.png) + PNG படத்தை (*.png) + + + + RPCConsole + + Client name + வாடிக்கையாளர் பெயர் + + + N/A + N/A + + + Client version + வாடிக்கையாளர் பதிப்பு + + + &Information + &தகவல் + + + Network + பிணையம் + + + Name + பெயர் + + + Memory Pool + நினைவக குளம் + + + Memory usage + நினைவக பயன்பாடு + + + Sent + அனுப்பிய + + + Direction + திசை + + + Version + பதிப்பு + + + User Agent + பயனர் முகவர் + + + Ping Time + பிங் நேரம் + + + &Open + &திற + + + &Console + &பணியகம் + + + &Clear + &வழுநீக்கு + + + Totals + மொத்தம் + + + In: + உள்ளே: + + + Out: + வெளியே: + + + 1 &hour + 1 &மணி + + + 1 &day + 1 &நாள் + + + 1 &week + 1 &வாரம் + + + 1 &year + 1 &ஆண்டு + + + %1 B + %1 B + + + %1 KB + %1 KB + + + %1 MB + %1 MB + + + %1 GB + %1 GB + + + via %1 + via %1 + + + never + ஒருபோதும் + + + Inbound + உள்வரும் + + + Outbound + வெளி செல்லும் + + + Yes + ஆம் + + + No + மறு + + + Unknown + அறியப்படாத + + + + ReceiveCoinsDialog + + &Amount: + &தொகை: + + + &Label: + &சிட்டை: + + + &Message: + &செய்தி: + + + Clear + நீக்கு + + + Show + காண்பி + + + Remove + நீக்கு + + + Copy message + நகலை செய்தி + + + Copy amount + நகலை தொகை + + + + ReceiveRequestDialog + + QR Code + QR குறியீடு + + + Copy &URI + நகலை &URI + + + Copy &Address + நகலை விலாசம் + + + &Save Image... + &படத்தை சேமி... + + + URI + URI + + + Address + விலாசம் + + + Amount + விலை + + + Label + லேபிள் + + + Message + செய்தி + + + + RecentRequestsTableModel + + Date + தேதி + + + Label + லேபிள் + + + Message + செய்தி + + + Amount + விலை + + + + SendCoinsDialog + + Quantity: + அளவு + + + Amount: + விலை + + + Priority: + முன்னுரிமை + + + Fee: + கட்டணம்: + + + After Fee: + கட்டணத்திறகுப் பின்: + + + Change: + மாற்று: + + + Choose... + தேர்ந்தெடு... + + + Hide + மறை + + + normal + இயல்பான + + + fast + வேகமாக + + + Balance: + மீதி: + + + S&end + &அனுப்பு + + + %1 to %2 + %1 to %2 + + + Copy amount + நகலை தொகை + + + or + அல்லது + + + + SendCoinsEntry + + A&mount: + &தொகை: + + + &Label: + &சிட்டை: + + + Alt+A + Alt+A + + + Alt+P + Alt+P + + + Message: + செய்தி: + + + + ShutdownWindow + + + SignVerifyMessageDialog + + Alt+A + Alt+A + + + Alt+P + Alt+P + + + Signature + கையொப்பம் + + + + SplashScreen + + Bitcoin Core + Bitcoin மையம் + + + + TrafficGraphWidget + + KB/s + KB/s + + + + TransactionDesc + + Status + நிலை + + + Date + தேதி + + + Source + மூலம் + + + Credit + கடன் + + + Debit + பற்று + + + Total debit + மொத்த பற்று + + + Total credit + மொத்த கடன் + + + Net amount + நிகர தொகை + + + Message + செய்தி + + + Comment + கருத்து + + + Transaction ID + பரிவர்த்தனை ID + + + Merchant + வணிகர் + + + Debug information + சரிசெய்வதற்கான தகவல் + + + Transaction + பரிவர்த்தனை + + + Inputs + உள்ளீடுகள் + + + Amount + விலை + + + true + உண்மை + + + false + தவறான + + + + TransactionDescDialog + + + TransactionTableModel + + Date + தேதி + + + Offline + ஆஃப்லைன் + + + Label + லேபிள் + + + (n/a) + (n/a) + + + + TransactionView + + All + முழுவதும் + + + Today + இன்று + + + This week + இந்த வாரம் + + + This month + இந்த மாதம் + + + Last month + கடந்த மாதம் + + + This year + இந்த வருடம் + + + Range... + எல்லை... + + + Other + வேறு + + + Copy address + பிரதியை முகவரியை + + + Copy amount + நகலை தொகை + + + Confirmed + உறுதியாக + + + Date + தேதி + + + Label + லேபிள் + + + Address + விலாசம் + + + ID + ID + + + Range: + எல்லை: + + + + UnitDisplayStatusBarControl + + + WalletFrame + + + WalletModel + + + WalletView + + &Export + &ஏற்றுமதி + + + + bitcoin-core + + (default: %u) + (default: %u) + + + Information + தகவல் + + + Warning + எச்சரிக்கை + + + (default: %s) + (default: %s) + + + Error + தவறு + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_th_TH.ts b/src/qt/locale/bitcoin_th_TH.ts index 79a55cdd518b5..ba3b1e8741baa 100644 --- a/src/qt/locale/bitcoin_th_TH.ts +++ b/src/qt/locale/bitcoin_th_TH.ts @@ -1,23 +1,99 @@ AddressBookPage + + Right-click to edit address or label + คลิกขวาเพื่อแก้ไขที่อยู่ หรือป้ายชื่อ + Create a new address สร้างที่อยู่ใหม่ + + &New + &สร้างใหม่ + Copy the currently selected address to the system clipboard คัดลอกที่อยู่ที่ถูกเลือกไปยัง คลิปบอร์ดของระบบ + + &Copy + &คัดลอก + + + C&lose + &ปิด + + + &Copy Address + &คัดลอกที่อยู่ + + + Delete the currently selected address from the list + ลบที่อยู่ที่เลือกไว้ในขณะนี้จากรายการ + + + Export the data in the current tab to a file + ส่งออกข้อมูลที่อยู่ในแท็บไปที่ไฟล์ + + + &Export + &ส่งออก + &Delete &ลบ + + Choose the address to send coins to + เลือกที่อยู่เพื่อส่งเหรียญไปไว้ + + + Choose the address to receive coins with + เลือกที่อยู่เพื่อรับเหรียญไว้ + + + C&hoose + &เลือก + + + Sending addresses + ส่งที่อยู่ + + + Receiving addresses + กำลังรับที่อยู่ + + + These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. + ที่อยู่เหล่านี้เป็นที่อยู่ Bitcoin ของคุณ สำหรับใช้เพื่อส่งเงิน กรุณาตรวจสอบจำนวนเงินและที่อยู่สำหรับรับเงินก่อนส่งเหรียญไป + + + Copy &Label + คัดลอก &ป้ายชื่อ + + + &Edit + &แก้ไข + + + Export Address List + ส่งออกรายการที่อยู่ + Comma separated file (*.csv) คั่นไฟล์ด้วยเครื่องหมายจุลภาค (*.csv) - + + Exporting Failed + ส่งออกข้อมูลล้มเหลว + + + There was an error trying to save the address list to %1. Please try again. + พบข้อผิดพลาดบางกระการในการพยายามบันทึกรายชื่อที่อยู่ไปยัง %1. กรุณาลองใหม่อีกครั้ง + + AddressTableModel @@ -75,6 +151,10 @@ Confirm wallet encryption ยืนยันการเข้ารหัสกระเป๋าสตางค์ + + Are you sure you wish to encrypt your wallet? + คุณแน่ใจแล้วหรือว่าต้องการเข้ารหัสกระเป๋าสตางค์ของคุณ? + Wallet encrypted กระเป๋าสตางค์ถูกเข้ารหัสเรียบร้อยแล้ว @@ -129,10 +209,18 @@ Browse transaction history เรียกดูประวัติการทำธุรกรรม + + E&xit + E&ออก + Quit application ออกจากโปรแกรม + + About &Qt + เกี่ยวกับ &Qt + &Options... &ตัวเลือก... @@ -141,6 +229,30 @@ Change the passphrase used for wallet encryption เปลี่ยนรหัสผ่านที่ใช้สำหรับการเข้ารหัสกระเป๋าเงิน + + &Debug window + &หน้าต่างตรวจสอบข้อผิดพลาด + + + &Verify message... + &ยืนยันข้อความ... + + + Bitcoin + Bitcoin + + + Wallet + กระเป๋าสตางค์ + + + &Send + &ส่ง + + + &Receive + &รับ + &File &ไฟล์ @@ -191,6 +303,26 @@ CoinControlDialog + + Amount + จำนวน + + + Date + วันที่ + + + Confirmations + การยืนยัน + + + Confirmed + ยืนยันแล้ว + + + Priority + ระดับความสำคัญ + (no label) (ไม่มีชื่อ) @@ -273,6 +405,10 @@ QObject + + Amount + จำนวน + QRImageWidget @@ -293,6 +429,10 @@ Address ที่อยู่ + + Amount + จำนวน + Label ชื่อ @@ -300,10 +440,18 @@ RecentRequestsTableModel + + Date + วันที่ + Label ชื่อ + + Amount + จำนวน + (no label) (ไม่มีชื่อ) @@ -345,12 +493,24 @@ TransactionDesc + + Date + วันที่ + + + Amount + จำนวน + TransactionDescDialog TransactionTableModel + + Date + วันที่ + Label ชื่อ @@ -362,10 +522,22 @@ Today วันนี้ + + Exporting Failed + ส่งออกข้อมูลล้มเหลว + Comma separated file (*.csv) คั่นไฟล์ด้วยเครื่องหมายจุลภาค (*.csv) + + Confirmed + ยืนยันแล้ว + + + Date + วันที่ + Label ชื่อ @@ -390,6 +562,14 @@ WalletView + + &Export + &ส่งออก + + + Export the data in the current tab to a file + ส่งออกข้อมูลที่อยู่ในแท็บไปที่ไฟล์ + bitcoin-core diff --git a/src/qt/locale/bitcoin_tr.ts b/src/qt/locale/bitcoin_tr.ts index 96fca8bb24f44..2406776773624 100644 --- a/src/qt/locale/bitcoin_tr.ts +++ b/src/qt/locale/bitcoin_tr.ts @@ -1473,10 +1473,6 @@ General Genel - - Using OpenSSL version - Kullanılan OpenSSL sürümü - Using BerkeleyDB version Kullanılan BerkeleyDB sürümü @@ -2941,7 +2937,7 @@ Prune configured below the minimum of %d MiB. Please use a higher number. - Prune, asgari değer olan %d MiB'den düşük olarak ayarlanmıştır. Lütfen daha yüksek bir sayı kullanınız. + Budama, asgari değer olan %d MiB'den düşük olarak ayarlanmıştır. Lütfen daha yüksek bir sayı kullanınız. Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node) @@ -2979,6 +2975,18 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Dışarıdan gelen bağlantıları kabul et (varsayılan: -proxy veya -connect yoksa 1) + + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. + -fallbackfee çok yüksek bir değere ayarlanmış! Ücret tahminleri mevcut değilken ödeyebileceğiniz muamele ücretidir bu. + + + A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s) + Ücret tahmini için yetersiz veri bulunduğunda kullanılacak ücret oranı (%s/kB olarak) (varsayılan: %s) + + + Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d) + Muameleler aktarılmadığında dahi beyaz listedeki eşlerden aktarılan muameleleri kabul et (varsayılan: %d) + Bind to given address and always listen on it. Use [host]:port notation for IPv6 Belirtilen adrese bağlan ve daima ondan dinle. IPv6 için [makine]:port yazımını kullanınız @@ -2995,6 +3003,10 @@ Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) Bir cüzdan muamelesi değiştiğinde komutu çalıştır (komuttaki %s muamele kimliği ile değiştirilecektir) + + Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) + Yerel aktarma politikasını ihlal ettiklerinde bile beyaz listedeki eşlerden gelen muamelelerin aktarılmasını zorla (varsayılan: %d) + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) Betik kontrolü iş parçacıklarının sayısını belirler (%u ilâ %d, 0 = otomatik, <0 = bu sayıda çekirdeği kullanma, varsayılan: %d) @@ -3011,6 +3023,10 @@ Unable to bind to %s on this computer. Bitcoin Core is probably already running. Bu bilgisayarda %s unsuruna bağlanılamadı. Bitcoin Çekirdeği muhtemelen hâlihazırda çalışmaktadır. + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + Desteklenmeyen argüman -whitelistalwaysrelay görmezden gelindi, -whitelistrelay ve/veya -whitelistforcerelay kullanın. + Use UPnP to map the listening port (default: 1 when listening and no -proxy) Dinlenecek portu haritalamak için UPnP kullan (varsayılan: dinlenildiğinde ve -proxy olmadığında 1) @@ -3027,6 +3043,10 @@ Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Uyarı: şebeke tamamen mutabık değil gibi görünüyor! Bazı madenciler sorun yaşıyor gibi görünüyor. + + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + İkaz: bilinmeyen blok sürümü oluşturulmaya çalışılıyor. Bilinmeyen kuralların işlemesi mümkündür. + Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Uyarı: eşlerimizle tamamen mutabık değiliz gibi görünüyor! Güncelleme yapmanız gerekebilir ya da diğer düğümlerin güncelleme yapmaları gerekebilir. @@ -3047,6 +3067,10 @@ <category> can be: <kategori> şunlar olabilir: + + Append comment to the user agent string + Kullanıcı aracı zincirine yorumu ekle + Block creation options: Blok oluşturma seçenekleri: @@ -3091,6 +3115,10 @@ Enable publish raw transaction in <address> Ham muamelenin <adres>te yayınlanmasını etkinleştir + + Enable transaction replacement in the memory pool (default: %u) + Bellek alanında muamele değiştirmeyi etkinleştir (varsayılan: %u) + Error initializing block database Blok veritabanını başlatılırken bir hata meydana geldi @@ -3127,10 +3155,22 @@ Invalid -onion address: '%s' Geçersiz -onion adresi: '%s' + + Invalid amount for -fallbackfee=<amount>: '%s' + -fallbackfee=<meblağ> için geçersiz meblağ: '%s' + Keep the transaction memory pool below <n> megabytes (default: %u) Muamele bellek alanını <n> megabayttan düşük tut (varsayılan: %u) + + Location of the auth cookie (default: data dir) + auth çerezinin konumu (varsayılan: veri klasörü) + + + Minimum bytes per sigop in transactions we relay and mine (default: %u) + Aktardığımız ve oluşturduğumuz muamelelerdeki sigop başına asgari bayt (varsayılan: %u) + Not enough file descriptors available. Kafi derecede dosya tanımlayıcıları mevcut değil. @@ -3139,13 +3179,17 @@ Only connect to nodes in network <net> (ipv4, ipv6 or onion) Sadece <net> şebekesindeki düğümlere bağlan (ipv4, ipv6 veya onion) + + Print version and exit + Sürümü yaz ve çık + Prune cannot be configured with a negative value. - Prune negatif bir değerle yapılandırılamaz. + Budama negatif bir değerle yapılandırılamaz. Prune mode is incompatible with -txindex. - Prune kipi -txindex ile uyumsuzdur. + Budama kipi -txindex ile uyumsuzdur. Set database cache size in megabytes (%d to %d, default: %d) @@ -3195,10 +3239,6 @@ Wallet options: Cüzdan seçenekleri: - - Warning: This version is obsolete; upgrade required! - Uyarı: Bu sürüm çok eskidir; güncellemeniz gerekir! - You need to rebuild the database using -reindex to change -txindex -txindex'i değiştirmek için veritabanını -reindex kullanarak tekrar inşa etmeniz gerekmektedir @@ -3281,7 +3321,7 @@ You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain - Prune olmayan kipe dönmek için veritabanını -reindex ile tekrar derlemeniz gerekir. Bu, tüm blok zincirini tekrar indirecektir + Budama olmayan kipe dönmek için veritabanını -reindex ile tekrar derlemeniz gerekir. Bu, tüm blok zincirini tekrar indirecektir (default: %u) @@ -3295,10 +3335,6 @@ Activating best chain... En iyi zincir etkinleştiriliyor... - - Always relay transactions received from whitelisted peers (default: %d) - Beyaz listedeki eşlerden gelen muameleleri daima aktar (varsayılan: %d) - Attempt to recover private keys from a corrupt wallet.dat on startup Başlangıçta bozuk bir wallet.dat dosyasından özel anahtarları geri kazanmayı dene @@ -3463,6 +3499,10 @@ Warning Uyarı + + Warning: unknown new rules activated (versionbit %i) + İkaz: bilinmeyen yeni kurallar etkinleştirilmiştir (versionbit %i) + Whether to operate in a blocks only mode (default: %u) Salt blok kipinde çalışılıp çalışılmayacağı (varsayılan: %u) diff --git a/src/qt/locale/bitcoin_tr_TR.ts b/src/qt/locale/bitcoin_tr_TR.ts index 10866b011b867..979aeea03811f 100644 --- a/src/qt/locale/bitcoin_tr_TR.ts +++ b/src/qt/locale/bitcoin_tr_TR.ts @@ -85,6 +85,10 @@ Export Address List Adres Listesini Dışa Aktar + + Comma separated file (*.csv) + Virgül ile ayrılmış dosya (*.csv) + Exporting Failed Dışa Aktarma Başarısız Oldu @@ -246,6 +250,10 @@ Exporting Failed Dışa Aktarma Başarısız Oldu + + Comma separated file (*.csv) + Virgül ile ayrılmış dosya (*.csv) + Label Etiket diff --git a/src/qt/locale/bitcoin_uk.ts b/src/qt/locale/bitcoin_uk.ts index ea783aa8569ca..64df7b5ba5780 100644 --- a/src/qt/locale/bitcoin_uk.ts +++ b/src/qt/locale/bitcoin_uk.ts @@ -1473,10 +1473,6 @@ General Загальна - - Using OpenSSL version - Використовується OpenSSL версії - Using BerkeleyDB version Використовується BerkeleyDB версії @@ -3139,6 +3135,10 @@ Only connect to nodes in network <net> (ipv4, ipv6 or onion) Підключатися тільки до вузлів в мережі <net> (ipv4, ipv6 або onion) + + Print version and exit + Версія для друку і виходу + Prune cannot be configured with a negative value. Розмір скороченого ланцюжка блоків не може бути від'ємним. @@ -3195,10 +3195,6 @@ Wallet options: Параметри гаманця: - - Warning: This version is obsolete; upgrade required! - Увага: Поточна версія застаріла, необхідне оновлення! - You need to rebuild the database using -reindex to change -txindex Вам необхідно перебудувати базу даних з використанням -reindex для того, щоб змінити -txindex @@ -3295,10 +3291,6 @@ Activating best chain... Активація найкращого ланцюжка... - - Always relay transactions received from whitelisted peers (default: %d) - Завжди передавайте транзакції отримані від пірів з білого списку (типово: %d) - Attempt to recover private keys from a corrupt wallet.dat on startup Спочатку спробуйте відновити приватні ключі в пошкодженому wallet.dat diff --git a/src/qt/locale/bitcoin_uz@Cyrl.ts b/src/qt/locale/bitcoin_uz@Cyrl.ts index 86724564ffc07..a9f9af6683e50 100644 --- a/src/qt/locale/bitcoin_uz@Cyrl.ts +++ b/src/qt/locale/bitcoin_uz@Cyrl.ts @@ -1167,10 +1167,6 @@ General Асосий - - Using OpenSSL version - Фойдаланилаётган OpenSSL версияси - Using BerkeleyDB version Фойдаланилаётган BerkeleyDB версияси diff --git a/src/qt/locale/bitcoin_uz@Latn.ts b/src/qt/locale/bitcoin_uz@Latn.ts new file mode 100644 index 0000000000000..2e4dabb59fb78 --- /dev/null +++ b/src/qt/locale/bitcoin_uz@Latn.ts @@ -0,0 +1,169 @@ + + + AddressBookPage + + Create a new address + Yangi manzil yaratish + + + &New + &Yangi + + + &Copy + &Nusxalash + + + C&lose + Yo&pish + + + &Copy Address + &Manzillarni nusxalash + + + &Delete + &O'chirish + + + + AddressTableModel + + Label + Yorliq + + + Address + Manzil + + + + AskPassphraseDialog + + + BanTableModel + + + BitcoinGUI + + + ClientModel + + + CoinControlDialog + + + EditAddressDialog + + + FreespaceChecker + + + HelpMessageDialog + + + Intro + + + OpenURIDialog + + + OptionsDialog + + + OverviewPage + + + PaymentServer + + + PeerTableModel + + + QObject + + + QRImageWidget + + + RPCConsole + + + ReceiveCoinsDialog + + + ReceiveRequestDialog + + Address + Manzil + + + Label + Yorliq + + + + RecentRequestsTableModel + + Label + Yorliq + + + + SendCoinsDialog + + + SendCoinsEntry + + + ShutdownWindow + + + SignVerifyMessageDialog + + + SplashScreen + + + TrafficGraphWidget + + + TransactionDesc + + + TransactionDescDialog + + + TransactionTableModel + + Label + Yorliq + + + + TransactionView + + Label + Yorliq + + + Address + Manzil + + + + UnitDisplayStatusBarControl + + + WalletFrame + + + WalletModel + + + WalletView + + + bitcoin-core + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_zh_CN.ts b/src/qt/locale/bitcoin_zh_CN.ts index 0ae2c95c62a1a..cc1b03356480e 100644 --- a/src/qt/locale/bitcoin_zh_CN.ts +++ b/src/qt/locale/bitcoin_zh_CN.ts @@ -1473,10 +1473,6 @@ General 常规 - - Using OpenSSL version - 使用 OpenSSL 版本 - Using BerkeleyDB version 使用的 BerkeleyDB 版本 @@ -2942,6 +2938,14 @@ Prune configured below the minimum of %d MiB. Please use a higher number. 修剪值被设置为低于最小值%d MiB,请使用更大的数值。 + + Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node) + 修剪:最后的钱包同步超过了修剪的数据。你需要通过 -reindex (重新下载整个区块链以防修剪节点) + + + Reduce storage requirements by pruning (deleting) old blocks. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, >%u = target size in MiB to use for block files) + 通过修剪(删除)旧数据块减少存储需求。此模式与 -txindex 和 -rescan不兼容。警告:还原此设置需要重新下载整个区块链。(默认: 0 = 禁用修剪数据块, >%u = 数据块文件目标大小,单位 MiB) + Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again. 无法在开启修剪的状态下重扫描,请使用 -reindex重新下载完整的区块链。 @@ -2972,6 +2976,18 @@ Accept connections from outside (default: 1 if no -proxy or -connect) 接受来自外部的连接 (缺省: 如果不带 -proxy or -connect 参数设置为1) + + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. + -fallbackfree 交易费设置得很高!这是在费用估计不可用时你可能会支付的交易费。 + + + A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s) + 当费用估计数据(default: %s)不足时将会启用的费率 (in %s/kB) + + + Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d) + 即使在无关联交易(默认: %d)时也接受来自白名单同行的关联交易 + Bind to given address and always listen on it. Use [host]:port notation for IPv6 绑定指定的IP地址开始监听。IPv6地址请使用[host]:port 格式 @@ -2988,6 +3004,10 @@ Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) 当最佳区块变化时执行命令 (命令行中的 %s 会被替换成区块哈希值) + + Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) + 强制关联来自白名单同行的交易即使他们违反本地关联政策(默认: %d) + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) 设置脚本验证的程序 (%u 到 %d, 0 = 自动, <0 = 保留自由的核心, 默认值: %d) @@ -3004,6 +3024,10 @@ Unable to bind to %s on this computer. Bitcoin Core is probably already running. 无法 %s的绑定到电脑上,比特币核心钱包可能已经在运行。 + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + 一个不被支持的参数 -whitelistalwaysrelay 被忽略了。请使用 -whitelistrelay 或者 -whitelistforcerelay. + Use UPnP to map the listening port (default: 1 when listening and no -proxy) 使用UPnP暴露本机监听端口(默认:1 当正在监听且不使用代理) @@ -3020,6 +3044,10 @@ Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. 警告:网络似乎并不完全同意!有些矿工似乎遇到了问题。 + + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + 警告: 未知的区块版本被挖掘!未知规则可能已生效 + Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. 警告:我们的同行似乎不完全同意!您可能需要升级,或者其他节点可能需要升级。 @@ -3040,6 +3068,10 @@ <category> can be: <category> 可能是: + + Append comment to the user agent string + 为用户代理字符串附加说明 + Block creation options: 数据块创建选项: @@ -3084,6 +3116,10 @@ Enable publish raw transaction in <address> 允许在<address>广播原始交易 + + Enable transaction replacement in the memory pool (default: %u) + 保证内存池中的交易更换(默认:%u) + Error initializing block database 初始化数据块数据库出错 @@ -3120,10 +3156,22 @@ Invalid -onion address: '%s' 无效的 -onion 地址:“%s” + + Invalid amount for -fallbackfee=<amount>: '%s' + -fallbackfee 的无效数额=<amount>: '%s' + Keep the transaction memory pool below <n> megabytes (default: %u) 保持交易内存池大小低于<n>MB(默认:%u) + + Location of the auth cookie (default: data dir) + 认证Cookie的位置 (默认: data目录) + + + Minimum bytes per sigop in transactions we relay and mine (default: %u) + 我们关联和挖掘的每sigop的最低交易字节(默认: %u) + Not enough file descriptors available. 没有足够的文件描述符可用。 @@ -3132,6 +3180,10 @@ Only connect to nodes in network <net> (ipv4, ipv6 or onion) 只连接 <net>网络中的节点 (ipv4, ipv6 或 onion) + + Print version and exit + 打印版本信息并退出 + Prune cannot be configured with a negative value. 修剪不能配置一个负数。 @@ -3168,6 +3220,10 @@ Use UPnP to map the listening port (default: %u) 使用UPnp映射监听端口 (默认: %u) + + User Agent comment (%s) contains unsafe characters. + 用户代理评论(%s)包含不安全的字符。 + Verifying blocks... 正在验证数据库的完整性... @@ -3184,10 +3240,6 @@ Wallet options: 钱包选项: - - Warning: This version is obsolete; upgrade required! - 警告:此版本已过时,必须升级! - You need to rebuild the database using -reindex to change -txindex 您需要将 -reindex 改为 -txindex 以重建数据库 @@ -3224,6 +3276,10 @@ Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message) 当收到相关提醒或者我们看到一个长分叉时执行命令(%s 将替换为消息) + + Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s) + 交易费(in %s/kB)比这更小的在关联、挖掘和生成交易时将被视为零费交易 (默认: %s) + If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u) 如果未设置交易费用,自动添加足够的交易费以确保交易在平均n个数据块内被确认 (默认: %u) @@ -3280,6 +3336,14 @@ Activating best chain... 正在激活最佳数据链... + + Attempt to recover private keys from a corrupt wallet.dat on startup + 尝试从启动页上的损坏钱包文件中恢复私钥 + + + Automatically create Tor hidden service (default: %d) + 自动建立Tor隐藏服务 (默认:%d) + Cannot resolve -whitebind address: '%s' 无法解析 -whitebind 地址: '%s' diff --git a/src/qt/locale/bitcoin_zh_HK.ts b/src/qt/locale/bitcoin_zh_HK.ts new file mode 100644 index 0000000000000..740a86e117024 --- /dev/null +++ b/src/qt/locale/bitcoin_zh_HK.ts @@ -0,0 +1,521 @@ + + + AddressBookPage + + Right-click to edit address or label + 按右擊修改位址或標記 + + + Create a new address + 新增一個位址 + + + &New + 新增 &N + + + Copy the currently selected address to the system clipboard + 複製目前選擇的位址到系統剪貼簿 + + + &Copy + 複製 &C + + + C&lose + 關閉 &l + + + &Copy Address + 複製位址 &C + + + Delete the currently selected address from the list + 把目前選擇的位址從列表中刪除 + + + Export the data in the current tab to a file + 把目前分頁的資料匯出至檔案 + + + &Export + 匯出 &E + + + &Delete + 刪除 &D + + + Choose the address to send coins to + 選擇要付錢過去的位址 + + + Choose the address to receive coins with + 選擇要收錢的位址 + + + C&hoose + 選取 &h + + + Sending addresses + 付款位址 + + + Receiving addresses + 收款位址 + + + These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. + 這些是你要付款過去的 Bitcoin 位址。在付款之前,務必要檢查金額和收款位址是否正確。 + + + These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. + 這些是你用來收款的 Bitcoin 位址。建議在每次交易時,都使用一個新的收款位址。 + + + Copy &Label + 複製標記 &L + + + &Edit + 編輯 &E + + + Export Address List + 匯出位址清單 + + + Comma separated file (*.csv) + 逗號分隔檔(*.csv) + + + Exporting Failed + 匯出失敗 + + + There was an error trying to save the address list to %1. Please try again. + 儲存位址列表到 %1 時發生錯誤。請再試一次。 + + + + AddressTableModel + + Label + 標記 + + + Address + 位址 + + + (no label) + (無標記) + + + + AskPassphraseDialog + + Passphrase Dialog + 複雜密碼對話方塊 + + + Enter passphrase + 請輸入密碼 + + + New passphrase + 新密碼 + + + Repeat new passphrase + 重複新密碼 + + + Encrypt wallet + 加密錢包 + + + This operation needs your wallet passphrase to unlock the wallet. + 這個動作需要你的錢包密碼來將錢包解鎖。 + + + Unlock wallet + 解鎖錢包 + + + This operation needs your wallet passphrase to decrypt the wallet. + 這個動作需要你的錢包密碼來將錢包解密。 + + + Decrypt wallet + 解密錢包 + + + Change passphrase + 改變密碼 + + + Confirm wallet encryption + 確認錢包加密 + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! + 警告: 如果把錢包加密後又忘記密碼,你就會<b>失去所有 Bitcoin 了</b>! + + + Are you sure you wish to encrypt your wallet? + 你確定要把錢包加密嗎? + + + Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. + Bitcoin Core 現在要關閉以完成加密程序。請記得將錢包加密不能完全防止你的 Bitcoin 經被入侵電腦的惡意程式偷取。 + + + 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. + 重要: 請改用新產生的加密錢包檔,來取代所以舊錢包檔的備份。為安全計,當你開始使用新的加密錢包檔後,舊錢包檔的備份就不能再使用了。 + + + Warning: The Caps Lock key is on! + 警告: Caps Lock 已啟用! + + + Wallet encrypted + 錢包已加密 + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. + 輸入錢包的新密碼。<br/>密碼請用<b>10 個或以上的隨機字元</b>,或是<b>8 個或以上的字詞</b>。 + + + Enter the old passphrase and new passphrase to the wallet. + 請輸入舊密碼和新密碼至錢包。 + + + Wallet encryption failed + 錢包加密失敗 + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + 因內部錯誤導致錢包加密失敗。你的錢包尚未加密。 + + + The supplied passphrases do not match. + 提供的密碼不一樣。 + + + Wallet unlock failed + 錢包解鎖失敗 + + + The passphrase entered for the wallet decryption was incorrect. + 用來解密錢包的密碼不對。 + + + Wallet decryption failed + 錢包解密失敗 + + + Wallet passphrase was successfully changed. + 錢包密碼已成功更改。 + + + + BanTableModel + + IP/Netmask + IP位址/遮罩 + + + Banned Until + 封鎖至 + + + + BitcoinGUI + + Sign &message... + 簽署訊息... &m + + + Synchronizing with network... + 與網絡同步中... + + + &Overview + 總覽 &O + + + Node + 節點 + + + Show general overview of wallet + 顯示錢包一般總覽 + + + &Transactions + 交易 &T + + + Browse transaction history + 瀏覽交易紀錄 + + + E&xit + 結束 &x + + + Quit application + 結束應用程式 + + + About &Qt + 關於 Qt &Q + + + Show information about Qt + 顯示 Qt 相關資訊 + + + &Options... + 選項... &O + + + &Encrypt Wallet... + 加密錢包... &E + + + &Backup Wallet... + 備份錢包... &B + + + &Change Passphrase... + 改變密碼... &C + + + &Sending addresses... + 付款位址... &S + + + &Receiving addresses... + 收款位址... &R + + + Open &URI... + 開啓網址... &U + + + Bitcoin Core client + Bitcoin Core 客戶端 + + + Importing blocks from disk... + 正在從磁碟匯入區塊資料... + + + Reindexing blocks on disk... + 正在為磁碟區塊重建索引... + + + Send coins to a Bitcoin address + 付款至一個 Bitcoin 位址 + + + Backup wallet to another location + 把錢包備份到其它地方 + + + Change the passphrase used for wallet encryption + 改變錢包加密用的密碼 + + + &Debug window + 除錯視窗 &D + + + Open debugging and diagnostic console + 開啓除錯和診斷主控台 + + + &Verify message... + 驗證訊息... &V + + + Bitcoin + Bitcoin + + + Wallet + 錢包 + + + &Send + 付款 &S + + + &Receive + 收款 &R + + + Show information about Bitcoin Core + 顯示 Bitcoin Core 的相關資訊 + + + &Show / Hide + 顯示 / 隱藏 &S + + + Show or hide the main Window + 顯示或隱藏主視窗 + + + + ClientModel + + + CoinControlDialog + + (no label) + (無標記) + + + + EditAddressDialog + + + FreespaceChecker + + + HelpMessageDialog + + + Intro + + + OpenURIDialog + + + OptionsDialog + + + OverviewPage + + + PaymentServer + + + PeerTableModel + + + QObject + + + QRImageWidget + + + RPCConsole + + + ReceiveCoinsDialog + + + ReceiveRequestDialog + + Address + 位址 + + + Label + 標記 + + + + RecentRequestsTableModel + + Label + 標記 + + + (no label) + (無標記) + + + + SendCoinsDialog + + (no label) + (無標記) + + + + SendCoinsEntry + + + ShutdownWindow + + + SignVerifyMessageDialog + + + SplashScreen + + + TrafficGraphWidget + + + TransactionDesc + + + TransactionDescDialog + + + TransactionTableModel + + Label + 標記 + + + + TransactionView + + Exporting Failed + 匯出失敗 + + + Comma separated file (*.csv) + 逗號分隔檔(*.csv) + + + Label + 標記 + + + Address + 位址 + + + + UnitDisplayStatusBarControl + + + WalletFrame + + + WalletModel + + + WalletView + + &Export + 匯出 &E + + + Export the data in the current tab to a file + 把目前分頁的資料匯出至檔案 + + + + bitcoin-core + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_zh_TW.ts b/src/qt/locale/bitcoin_zh_TW.ts index 4026095928ab9..107e7034e5bc9 100644 --- a/src/qt/locale/bitcoin_zh_TW.ts +++ b/src/qt/locale/bitcoin_zh_TW.ts @@ -7,7 +7,7 @@ Create a new address - 新增新的位址 + 產生一個新位址 &New @@ -67,11 +67,11 @@ These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - 這些是你要付款過去的位元幣位址。在付錢之前,務必要檢查金額和收款位址是否正確。 + 這些是你要付款過去的 Bitcoin 位址。在付錢之前,務必要檢查金額和收款位址是否正確。 These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - 這些是你用來收款的位元幣位址。建議在每次交易時,都使用一個新的收款位址。 + 這些是你用來收款的 Bitcoin 位址。建議在每次交易時,都使用一個新的收款位址。 Copy &Label @@ -161,7 +161,7 @@ Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - 警告: 如果把錢包加密後又忘記密碼,你就會從此<b>失去其中所有的位元幣了</b>! + 警告: 如果把錢包加密後又忘記密碼,你就會從此<b>失去其中所有的 Bitcoin 了</b>! Are you sure you wish to encrypt your wallet? @@ -169,7 +169,7 @@ Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - 位元幣核心現在要關閉,好完成加密程序。請注意,加密錢包不能完全防止入侵你的電腦的惡意程式偷取位元幣。 + Bitcoin Core 現在要關閉,好完成加密程序。請注意,加密錢包不能完全防止入侵你的電腦的惡意程式偷取錢幣。 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. @@ -307,7 +307,7 @@ Bitcoin Core client - 位元幣核心客戶端軟體 + Bitcoin Core 客戶端軟體 Importing blocks from disk... @@ -319,7 +319,7 @@ Send coins to a Bitcoin address - 付錢給一個位元幣位址 + 付錢給一個 Bitcoin 位址 Backup wallet to another location @@ -343,7 +343,7 @@ Bitcoin - 位元幣 + Bitcoin Wallet @@ -359,7 +359,7 @@ Show information about Bitcoin Core - 顯示位元幣核心的相關資訊 + 顯示 Bitcoin Core 的相關資訊 &Show / Hide @@ -375,11 +375,11 @@ Sign messages with your Bitcoin addresses to prove you own them - 用位元幣位址簽署訊息來證明位址是你的 + 用 Bitcoin 位址簽署訊息來證明位址是你的 Verify messages to ensure they were signed with specified Bitcoin addresses - 驗證訊息是用來確定訊息是用指定的位元幣位址簽署的 + 驗證訊息是用來確定訊息是用指定的 Bitcoin 位址簽署的 &File @@ -399,19 +399,19 @@ Bitcoin Core - 位元幣核心 + Bitcoin Core Request payments (generates QR codes and bitcoin: URIs) - 要求付款(產生 QR Code 和位元幣付款協議的資源識別碼: URI) + 要求付款(產生 QR Code 和 bitcoin 付款協議的資源識別碼: URI) &About Bitcoin Core - 關於位元幣核心 + 關於 Bitcoin Core Modify configuration options for Bitcoin Core - 修改位元幣核心的設定選項 + 修改 Bitcoin Core 的設定選項 Show the list of used sending addresses and labels @@ -431,11 +431,11 @@ Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - 顯示位元幣核心的說明訊息,來取得可用命令列選項的列表 + 顯示 Bitcoin Core 的說明訊息,來取得可用命令列選項的列表 %n active connection(s) to Bitcoin network - %n 個運作中的位元幣網路連線 + %n 個運作中的 Bitcoin 網路連線 No block source available... @@ -818,7 +818,7 @@ The entered address "%1" is not a valid Bitcoin address. - 輸入的位址 %1 並不是有效的位元幣位址。 + 輸入的位址 %1 並不是有效的 Bitcoin 位址。 Could not unlock wallet. @@ -856,7 +856,7 @@ HelpMessageDialog Bitcoin Core - 位元幣核心 + Bitcoin Core version @@ -868,7 +868,7 @@ About Bitcoin Core - 關於位元幣核心 + 關於 Bitcoin Core Command-line options @@ -919,15 +919,15 @@ Welcome to Bitcoin Core. - 歡迎使用位元幣核心 + 歡迎使用 Bitcoin Core As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - 因為這是程式第一次啓動,你可以選擇位元幣核心儲存資料的地方。 + 因為這是程式第一次啓動,你可以選擇 Bitcoin Core 儲存資料的地方。 Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - 位元幣核心會下載並儲存一份位元幣區塊鏈的拷貝。至少有 %1GB 的資料會儲存到這個目錄中,並且還會持續增長。另外錢包資料也會儲存在這個目錄。 + Bitcoin Core 會下載並儲存一份 Bitcoin 區塊鏈的拷貝。至少有 %1GB 的資料會儲存到這個目錄中,並且還會持續增長。另外錢包資料也會儲存在這個目錄。 Use the default data directory @@ -939,7 +939,7 @@ Bitcoin Core - 位元幣核心 + Bitcoin Core Error: Specified data directory "%1" cannot be created. @@ -1021,7 +1021,7 @@ The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - 可以在這裡設定使用者介面的語言。這個設定在重啓位元幣核心後才會生效。 + 可以在這裡設定使用者介面的語言。這個設定在重啓 Bitcoin Core 後才會生效。 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 |. @@ -1049,11 +1049,11 @@ Automatically start Bitcoin Core after logging in to the system. - 在登入系統後自動啓動位元幣核心。 + 在登入系統後自動啓動 Bitcoin Core。 &Start Bitcoin Core on system login - 系統登入時啟動位元幣核心 + 系統登入時啟動 Bitcoin Core (0 = auto, <0 = leave that many cores free) @@ -1081,7 +1081,7 @@ Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled. - 自動在路由器上開放位元幣的客戶端通訊埠。只有在你的路由器支援且開啓「通用即插即用」協定(UPnP)時才有作用。 + 自動在路由器上開放 Bitcoin 的客戶端通訊埠。只有在你的路由器支援且開啓「通用即插即用」協定(UPnP)時才有作用。 Map port using &UPnP @@ -1089,7 +1089,7 @@ Connect to the Bitcoin network through a SOCKS5 proxy. - 透過 SOCKS5 代理伺服器來連線到位元幣網路。 + 透過 SOCKS5 代理伺服器來連線到 Bitcoin 網路。 &Connect through SOCKS5 proxy (default proxy): @@ -1129,7 +1129,7 @@ Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services. - 透過另外的 SOCKS5 代理伺服器來連線到位元幣網路中的 Tor 隱藏服務。 + 透過另外的 SOCKS5 代理伺服器來連線到 Bitcoin 網路中的 Tor 隱藏服務。 Use separate SOCKS5 proxy to reach peers via Tor hidden services: @@ -1216,7 +1216,7 @@ 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. - 顯示的資訊可能是過期的。跟位元幣網路的連線建立後,你的錢包會自動和網路同步,但是這個步驟還沒完成。 + 顯示的資訊可能是過期的。跟 Bitcoin 網路的連線建立後,你的錢包會自動和網路同步,但是這個步驟還沒完成。 Watch-only: @@ -1323,7 +1323,7 @@ URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - 沒辦法解析資源識別碼(URI)!可能是因為位元幣位址無效,或是 URI 參數格式錯誤。 + 沒辦法解析資源識別碼(URI)!可能是因為 Bitcoin 位址無效,或是 URI 參數格式錯誤。 Payment request file handling @@ -1397,7 +1397,7 @@ Enter a Bitcoin address (e.g. %1) - 輸入位元幣位址 (比如說 %1) + 輸入 Bitcoin 位址 (比如說 %1) %1 d @@ -1473,10 +1473,6 @@ General 普通 - - Using OpenSSL version - 使用的 OpenSSL 版本 - Using BerkeleyDB version 使用 BerkeleyDB 版本 @@ -1519,7 +1515,7 @@ Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. - 從目前的資料目錄下開啓位元幣核心的除錯紀錄檔。當紀錄檔很大時,可能會花好幾秒的時間。 + 從目前的資料目錄下開啓 Bitcoin Core 的除錯紀錄檔。當紀錄檔很大時,可能會花好幾秒的時間。 Received @@ -1679,7 +1675,7 @@ Welcome to the Bitcoin Core RPC console. - 歡迎使用位元幣核心 RPC 主控台。 + 歡迎使用 Bitcoin Core 的 RPC 主控台。 Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. @@ -1762,7 +1758,7 @@ 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. - 附加在付款要求中的訊息,可以不填,打開要求內容時會顯示。注意: 這個訊息不會隨著付款送到位元幣網路上。 + 附加在付款要求中的訊息,可以不填,打開要求內容時會顯示。注意: 這個訊息不會隨著付款送到 Bitcoin 網路上。 An optional label to associate with the new receiving address. @@ -2155,7 +2151,7 @@ Warning: Invalid Bitcoin address - 警告: 位元幣位址無效 + 警告: Bitcoin 位址無效 (no label) @@ -2206,7 +2202,7 @@ The Bitcoin address to send the payment to - 接收付款的位元幣位址 + 接收付款的 Bitcoin 位址 Alt+A @@ -2226,7 +2222,7 @@ 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. - 手續費會從要付款出去的金額中扣掉。因此收款人會收到比輸入的金額還要少的位元幣。如果有多個收款人的話,手續費會平均分配來扣除。 + 手續費會從要付款出去的金額中扣掉。因此收款人會收到比輸入的金額還要少的 bitcoin。如果有多個收款人的話,手續費會平均分配來扣除。 S&ubtract fee from amount @@ -2250,7 +2246,7 @@ 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. - 附加在位元幣付款協議的資源識別碼(URI)中的訊息,會和交易內容一起存起來,給你自己做參考。注意: 這個訊息不會送到位元幣網路上。 + 附加在 Bitcoin 付款協議的資源識別碼(URI)中的訊息,會和交易內容一起存起來,給你自己做參考。注意: 這個訊息不會送到 Bitcoin 網路上。 Pay To: @@ -2265,7 +2261,7 @@ ShutdownWindow Bitcoin Core is shutting down... - 正在關閉位元幣核心中... + 正在關閉 Bitcoin Core 中... Do not shut down the computer until this window disappears. @@ -2288,7 +2284,7 @@ The Bitcoin address to sign the message with - 用來簽署訊息的位元幣位址 + 用來簽署訊息的 Bitcoin 位址 Choose previously used address @@ -2320,7 +2316,7 @@ Sign the message to prove you own this Bitcoin address - 簽署這個訊息來證明這個位元幣位址是你的 + 簽署這個訊息來證明這個 Bitcoin 位址是你的 Sign &Message @@ -2344,11 +2340,11 @@ The Bitcoin address the message was signed with - 簽署這個訊息的位元幣位址 + 簽署這個訊息的 Bitcoin 位址 Verify the message to ensure it was signed with the specified Bitcoin address - 驗證這個訊息來確定是用指定的位元幣位址簽署的 + 驗證這個訊息來確定是用指定的 Bitcoin 位址簽署的 Verify &Message @@ -2415,11 +2411,11 @@ SplashScreen Bitcoin Core - 位元幣核心 + Bitcoin Core The Bitcoin Core developers - 位元幣核心開發人員 + Bitcoin Core 開發人員 [testnet] @@ -2938,7 +2934,7 @@ Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. - 請檢查電腦日期和時間是否正確!位元幣核心沒辦法在時鐘不準的情況下正常運作。 + 請檢查電腦日期和時間是否正確!Bitcoin Core 沒辦法在時鐘不準的情況下正常運作。 Prune configured below the minimum of %d MiB. Please use a higher number. @@ -2970,7 +2966,7 @@ Run in the background as a daemon and accept commands - 用護靈模式在背後執行並接受指令 + 用護靈模式在背景執行並接受指令 Unable to start HTTP server. See debug log for details. @@ -2980,6 +2976,18 @@ Accept connections from outside (default: 1 if no -proxy or -connect) 是否接受外來連線(預設值: 當沒有 -proxy 或 -connect 時為 1) + + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. + 警告: -fallbackfee 設定了很高的金額!這是當預估手續費還沒計算出來時,交易付款預設會付的手續費。 + + + A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s) + 當沒有足夠的資料計算預估手續費時,所使用的手續費費率(單位是 %s/kB, 預設值: %s) + + + Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d) + 接受從白名點節點收到的轉發交易,即使沒有(符合準則)轉發出去(預設值: %d) + Bind to given address and always listen on it. Use [host]:port notation for IPv6 和指定的位址繫結,並且一直在指定位址聽候連線。IPv6 請用 [主機]:通訊埠 這種格式 @@ -2996,6 +3004,10 @@ Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) 當錢包有交易改變時要執行的指令(指令中的 %s 會被取代成交易識別碼) + + Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) + 強制轉發從白名點節點收到的交易,即使它們違反了本機的轉發準則(預設值: %d) + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) 設定指令碼驗證的執行緒數目 (%u 到 %d,0 表示程式自動決定,小於 0 表示保留處理器核心不用的數目,預設值: %d) @@ -3010,7 +3022,11 @@ Unable to bind to %s on this computer. Bitcoin Core is probably already running. - 沒辦法繫結在這台電腦上的 %s 。位元幣核心可能已經在執行了。 + 沒辦法繫結在這台電腦上的 %s 。Bitcoin Core 可能已經在執行了。 + + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + 忽略不支援的參數 -whitelistalwaysrelay,請改用 -whitelistrelay 和 -whitelistforcerelay​ 的組合。 Use UPnP to map the listening port (default: 1 when listening and no -proxy) @@ -3026,7 +3042,11 @@ Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. - 警告: 位元幣網路對於區塊鏈結的決定目前有分歧!看來有些礦工會有問題。 + 警告: 節點網路對於區塊鏈結的決定目前有分歧!看來有些礦工會有問題。 + + + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + 警告: 有礦工正在開採不明版本的區塊!這表示有不明的交易規則正在作用中 Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. @@ -3048,6 +3068,10 @@ <category> can be: <category> 可以是: + + Append comment to the user agent string + 對使用者代理字串添加註解 + Block creation options: 區塊製造選項: @@ -3092,6 +3116,10 @@ Enable publish raw transaction in <address> 開啟傳送交易原始資料到目標 ZeroMQ 位址 <address> 去 + + Enable transaction replacement in the memory pool (default: %u) + 對交易暫存池啟用替代交易(預設值: %u) + Error initializing block database 初始化區塊資料庫時發生錯誤 @@ -3128,10 +3156,22 @@ Invalid -onion address: '%s' 無效的 -onion 位址: '%s' + + Invalid amount for -fallbackfee=<amount>: '%s' + 設定 -fallbackfee=<金額> 的金額無效: '%s' + Keep the transaction memory pool below <n> megabytes (default: %u) 在記憶體暫存池中保持最多 <n> 個百萬位元組的交易(預設值: %u) + + Location of the auth cookie (default: data dir) + 認證 cookie 資料的位置(預設值: 同資料目錄) + + + Minimum bytes per sigop in transactions we relay and mine (default: %u) + 轉發和開採時,對交易資料的 sigop 平均位元組數下限(預設值: %u) + Not enough file descriptors available. 檔案描述元不足。 @@ -3140,6 +3180,10 @@ Only connect to nodes in network <net> (ipv4, ipv6 or onion) 只和 <net> 網路上的節點連線(ipv4, ipv6, 或 onion) + + Print version and exit + 顯示版本後結束 + Prune cannot be configured with a negative value. 修剪值不能設定為負的。 @@ -3196,10 +3240,6 @@ Wallet options: 錢包選項: - - Warning: This version is obsolete; upgrade required! - 警告: 這個版本已經被淘汰了;必須要升級! - You need to rebuild the database using -reindex to change -txindex 改變 -txindex 參數後,必須要用 -reindex 參數來重建資料庫 @@ -3218,7 +3258,7 @@ Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - 沒辦法鎖定資料目錄 %s。位元幣核心可能已經在執行了。 + 沒辦法鎖定資料目錄 %s。Bitcoin Core 可能已經在執行了。 Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) @@ -3296,10 +3336,6 @@ Activating best chain... 啟用最佳鏈結... - - Always relay transactions received from whitelisted peers (default: %d) - 無條件轉發從白名點節點收到的交易(預設值: %d) - Attempt to recover private keys from a corrupt wallet.dat on startup 啟動時嘗試從壞掉的錢包檔 wallet.dat 復原密鑰 @@ -3318,11 +3354,11 @@ Copyright (C) 2009-%i The Bitcoin Core Developers - 版權為位元幣核心開發人員自西元 2009 至 %i 年起所有 + 版權為 Bitcoin Core 開發人員自西元 2009 至 %i 年起所有 Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - 載入 wallet.dat 檔案時發生錯誤: 這個錢包需要新版的位元幣核心 + 載入 wallet.dat 檔案時發生錯誤: 這個錢包需要新版的 Bitcoin Core Error reading from database, shutting down. @@ -3338,7 +3374,7 @@ Initialization sanity check failed. Bitcoin Core is shutting down. - 初始化時的基本檢查失敗了。位元幣核心就要關閉了。 + 初始化時的基本檢查失敗了。Bitcoin Core 就要關閉了。 Invalid amount for -maxtxfee=<amount>: '%s' @@ -3458,12 +3494,16 @@ Wallet needed to be rewritten: restart Bitcoin Core to complete - 錢包需要重寫: 請重新啓動位元幣核心來完成 + 錢包需要重寫: 請重新啓動 Bitcoin Core 來完成 Warning 警告 + + Warning: unknown new rules activated (versionbit %i) + 警告: 不明的交易規則被啟用了(versionbit %i) + Whether to operate in a blocks only mode (default: %u) 是否要用只要區塊模式運作(預設值: %u) @@ -3582,7 +3622,7 @@ Generate coins (default: %u) - 生產位元幣(預設值: %u) + 生產錢幣(預設值: %u) How many blocks to check at startup (default: %u, 0 = all) From 48efec82f3a18364c019577495914fcebb425e35 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 21 Jun 2016 16:09:46 -0700 Subject: [PATCH 0534/1802] Fix some minor compact block issues that came up in review --- src/main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 60a33f9c2f97e..f5b1410114c7f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4613,7 +4613,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam // Track requests for our stuff. GetMainSignals().Inventory(inv.hash); - if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK) + if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || inv.type == MSG_CMPCT_BLOCK) break; } } @@ -5077,8 +5077,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, return true; } - if (it->second->nHeight < chainActive.Height() - 10) { - LogPrint("net", "Peer %d sent us a getblocktxn for a block > 10 deep", pfrom->id); + if (it->second->nHeight < chainActive.Height() - 15) { + LogPrint("net", "Peer %d sent us a getblocktxn for a block > 15 deep", pfrom->id); return true; } From 06f40ef324ce0d4e43b89f7106e50965263aa2c7 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 22 Jun 2016 14:37:39 +0200 Subject: [PATCH 0535/1802] depends: Mention aarch64 as common cross-compile target --- depends/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/depends/README.md b/depends/README.md index 271bbd80bfc4a..6053c531b46a7 100644 --- a/depends/README.md +++ b/depends/README.md @@ -23,7 +23,8 @@ Common `host-platform-triplets` for cross compilation are: - `i686-w64-mingw32` for Win32 - `x86_64-w64-mingw32` for Win64 - `x86_64-apple-darwin11` for MacOSX -- `arm-linux-gnueabihf` for Linux ARM +- `arm-linux-gnueabihf` for Linux ARM 32 bit +- `aarch64-linux-gnu` for Linux ARM 64 bit No other options are needed, the paths are automatically configured. From ecacfd98e657c5819a1bcb1da93b25d3ad4e5045 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 31 Mar 2016 14:43:23 +0200 Subject: [PATCH 0536/1802] --- [SEGWIT] begin: P2P/node/consensus --- From 7030d9eb47254499bba14f1c00abc6bf493efd91 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 6 Nov 2015 01:32:04 +0100 Subject: [PATCH 0537/1802] BIP144: Serialization, hashes, relay (sender side) Contains refactorings by Eric Lombrozo. Contains fixup by Nicolas Dorier. Contains cleanup of CInv::GetCommand by Alex Morcos --- src/core_io.h | 2 +- src/core_memusage.h | 24 ++++- src/core_read.cpp | 16 +++- src/main.cpp | 28 +++--- src/net.h | 17 ++++ src/primitives/block.h | 2 - src/primitives/transaction.cpp | 16 +++- src/primitives/transaction.h | 151 +++++++++++++++++++++++++++--- src/protocol.cpp | 46 +++------ src/protocol.h | 30 +++--- src/qt/coincontroldialog.cpp | 18 +++- src/qt/walletmodeltransaction.cpp | 3 +- src/rpc/rawtransaction.cpp | 6 +- src/script/script.cpp | 12 +++ src/script/script.h | 14 +++ src/streams.h | 33 +++++++ src/test/data/tx_invalid.json | 4 - src/test/sighash_tests.cpp | 2 +- src/test/transaction_tests.cpp | 2 +- src/wallet/rpcwallet.cpp | 2 +- src/wallet/walletdb.h | 1 + 21 files changed, 339 insertions(+), 90 deletions(-) diff --git a/src/core_io.h b/src/core_io.h index e8c0c49e84d53..b559d44bf5a8a 100644 --- a/src/core_io.h +++ b/src/core_io.h @@ -17,7 +17,7 @@ class UniValue; // core_read.cpp extern CScript ParseScript(const std::string& s); extern std::string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode = false); -extern bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx); +extern bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx, bool fTryNoWitness = false); extern bool DecodeHexBlk(CBlock&, const std::string& strHexBlk); extern uint256 ParseHashUV(const UniValue& v, const std::string& strName); extern uint256 ParseHashStr(const std::string&, const std::string& strName); diff --git a/src/core_memusage.h b/src/core_memusage.h index 450537d059c20..dd86f805fe457 100644 --- a/src/core_memusage.h +++ b/src/core_memusage.h @@ -25,8 +25,28 @@ static inline size_t RecursiveDynamicUsage(const CTxOut& out) { return RecursiveDynamicUsage(out.scriptPubKey); } +static inline size_t RecursiveDynamicUsage(const CScriptWitness& scriptWit) { + size_t mem = memusage::DynamicUsage(scriptWit.stack); + for (std::vector >::const_iterator it = scriptWit.stack.begin(); it != scriptWit.stack.end(); it++) { + mem += memusage::DynamicUsage(*it); + } + return mem; +} + +static inline size_t RecursiveDynamicUsage(const CTxinWitness& txinwit) { + return RecursiveDynamicUsage(txinwit.scriptWitness); +} + +static inline size_t RecursiveDynamicUsage(const CTxWitness& txwit) { + size_t mem = memusage::DynamicUsage(txwit.vtxinwit); + for (std::vector::const_iterator it = txwit.vtxinwit.begin(); it != txwit.vtxinwit.end(); it++) { + mem += RecursiveDynamicUsage(*it); + } + return mem; +} + static inline size_t RecursiveDynamicUsage(const CTransaction& tx) { - size_t mem = memusage::DynamicUsage(tx.vin) + memusage::DynamicUsage(tx.vout); + size_t mem = memusage::DynamicUsage(tx.vin) + memusage::DynamicUsage(tx.vout) + RecursiveDynamicUsage(tx.wit); for (std::vector::const_iterator it = tx.vin.begin(); it != tx.vin.end(); it++) { mem += RecursiveDynamicUsage(*it); } @@ -37,7 +57,7 @@ static inline size_t RecursiveDynamicUsage(const CTransaction& tx) { } static inline size_t RecursiveDynamicUsage(const CMutableTransaction& tx) { - size_t mem = memusage::DynamicUsage(tx.vin) + memusage::DynamicUsage(tx.vout); + size_t mem = memusage::DynamicUsage(tx.vin) + memusage::DynamicUsage(tx.vout) + RecursiveDynamicUsage(tx.wit); for (std::vector::const_iterator it = tx.vin.begin(); it != tx.vin.end(); it++) { mem += RecursiveDynamicUsage(*it); } diff --git a/src/core_read.cpp b/src/core_read.cpp index 444a4c7eba195..7cfda6dd6d894 100644 --- a/src/core_read.cpp +++ b/src/core_read.cpp @@ -90,12 +90,26 @@ CScript ParseScript(const std::string& s) return result; } -bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx) +bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx, bool fTryNoWitness) { if (!IsHex(strHexTx)) return false; vector txData(ParseHex(strHexTx)); + + if (fTryNoWitness) { + CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS); + try { + ssData >> tx; + if (ssData.eof()) { + return true; + } + } + catch (const std::exception&) { + // Fall through. + } + } + CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION); try { ssData >> tx; diff --git a/src/main.cpp b/src/main.cpp index ae195ecc40f36..2184940232bc8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1029,8 +1029,8 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state) return state.DoS(10, false, REJECT_INVALID, "bad-txns-vin-empty"); if (tx.vout.empty()) return state.DoS(10, false, REJECT_INVALID, "bad-txns-vout-empty"); - // Size limits - if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE) + // Size limits (this doesn't take the witness into account, as that hasn't been checked for malleability) + if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) > MAX_BLOCK_SIZE) return state.DoS(100, false, REJECT_INVALID, "bad-txns-oversize"); // Check for negative or overflow output values @@ -3396,7 +3396,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P // because we receive the wrong transactions for it. // Size limits - if (block.vtx.empty() || block.vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE) + if (block.vtx.empty() || block.vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) > MAX_BLOCK_SIZE) return state.DoS(100, false, REJECT_INVALID, "bad-blk-length", false, "size limits failed"); // First transaction must be coinbase, the rest must not be @@ -4508,6 +4508,7 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main) switch (inv.type) { case MSG_TX: + case MSG_WITNESS_TX: { assert(recentRejects); if (chainActive.Tip()->GetBlockHash() != hashRecentRejectsChainTip) @@ -4528,6 +4529,7 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main) pcoinsTip->HaveCoinsInCache(inv.hash); } case MSG_BLOCK: + case MSG_WITNESS_BLOCK: return mapBlockIndex.count(inv.hash); } // Don't know what it is, just say we already got one @@ -4552,7 +4554,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam boost::this_thread::interruption_point(); it++; - if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || inv.type == MSG_CMPCT_BLOCK) + if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || inv.type == MSG_CMPCT_BLOCK || inv.type == MSG_WITNESS_BLOCK) { bool send = false; BlockMap::iterator mi = mapBlockIndex.find(inv.hash); @@ -4593,6 +4595,8 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam if (!ReadBlockFromDisk(block, (*mi).second, consensusParams)) assert(!"cannot load block from disk"); if (inv.type == MSG_BLOCK) + pfrom->PushMessageWithFlag(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCK, block); + else if (inv.type == MSG_WITNESS_BLOCK) pfrom->PushMessage(NetMsgType::BLOCK, block); else if (inv.type == MSG_FILTERED_BLOCK) { @@ -4609,7 +4613,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam // however we MUST always provide at least what the remote peer needs typedef std::pair PairType; BOOST_FOREACH(PairType& pair, merkleBlock.vMatchedTxn) - pfrom->PushMessage(NetMsgType::TX, block.vtx[pair.first]); + pfrom->PushMessageWithFlag(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::TX, block.vtx[pair.first]); } // else // no response @@ -4622,9 +4626,9 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam // instead we respond with the full, non-compact block. if (mi->second->nHeight >= chainActive.Height() - 10) { CBlockHeaderAndShortTxIDs cmpctblock(block); - pfrom->PushMessage(NetMsgType::CMPCTBLOCK, cmpctblock); + pfrom->PushMessageWithFlag(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::CMPCTBLOCK, cmpctblock); } else - pfrom->PushMessage(NetMsgType::BLOCK, block); + pfrom->PushMessageWithFlag(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCK, block); } // Trigger the peer node to send a getblocks request for the next batch of inventory @@ -4640,20 +4644,20 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam } } } - else if (inv.type == MSG_TX) + else if (inv.type == MSG_TX || inv.type == MSG_WITNESS_TX) { // Send stream from relay memory bool push = false; auto mi = mapRelay.find(inv.hash); if (mi != mapRelay.end()) { - pfrom->PushMessage(NetMsgType::TX, *mi->second); + pfrom->PushMessageWithFlag(inv.type == MSG_TX ? SERIALIZE_TRANSACTION_NO_WITNESS : 0, NetMsgType::TX, *mi->second); push = true; } else if (pfrom->timeLastMempoolReq) { auto txinfo = mempool.info(inv.hash); // To protect privacy, do not answer getdata using the mempool when // that TX couldn't have been INVed in reply to a MEMPOOL request. if (txinfo.tx && txinfo.nTime <= pfrom->timeLastMempoolReq) { - pfrom->PushMessage(NetMsgType::TX, *txinfo.tx); + pfrom->PushMessageWithFlag(inv.type == MSG_TX ? SERIALIZE_TRANSACTION_NO_WITNESS : 0, NetMsgType::TX, *txinfo.tx); push = true; } } @@ -4665,7 +4669,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam // Track requests for our stuff. GetMainSignals().Inventory(inv.hash); - if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || inv.type == MSG_CMPCT_BLOCK) + if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || inv.type == MSG_CMPCT_BLOCK || inv.type == MSG_WITNESS_BLOCK) break; } } @@ -5146,7 +5150,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } resp.txn[i] = block.vtx[req.indexes[i]]; } - pfrom->PushMessage(NetMsgType::BLOCKTXN, resp); + pfrom->PushMessageWithFlag(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCKTXN, resp); } diff --git a/src/net.h b/src/net.h index aa9b2c11a3c22..cb35d8c4f28c3 100644 --- a/src/net.h +++ b/src/net.h @@ -598,6 +598,23 @@ class CNode } } + /** Send a message containing a1, serialized with flag flag. */ + template + void PushMessageWithFlag(int flag, const char* pszCommand, const T1& a1) + { + try + { + BeginMessage(pszCommand); + WithOrVersion(&ssSend, flag) << a1; + EndMessage(pszCommand); + } + catch (...) + { + AbortMessage(); + throw; + } + } + template void PushMessage(const char* pszCommand, const T1& a1, const T2& a2) { diff --git a/src/primitives/block.h b/src/primitives/block.h index 42276b2bc26bc..29307aed5be48 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -38,7 +38,6 @@ class CBlockHeader template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { READWRITE(this->nVersion); - nVersion = this->nVersion; READWRITE(hashPrevBlock); READWRITE(hashMerkleRoot); READWRITE(nTime); @@ -120,7 +119,6 @@ class CBlock : public CBlockHeader std::string ToString() const; }; - /** Describes a place in the block chain to another node such that if the * other node doesn't have the same branch, it can find a recent common trunk. * The further back it is, the further before the fork it may be. diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index 947f2e6a73baf..b0230530e804f 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -60,21 +60,26 @@ std::string CTxOut::ToString() const } CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::CURRENT_VERSION), nLockTime(0) {} -CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) {} +CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), wit(tx.wit), nLockTime(tx.nLockTime) {} uint256 CMutableTransaction::GetHash() const { - return SerializeHash(*this); + return SerializeHash(*this, SER_GETHASH, SERIALIZE_TRANSACTION_NO_WITNESS); } void CTransaction::UpdateHash() const { - *const_cast(&hash) = SerializeHash(*this); + *const_cast(&hash) = SerializeHash(*this, SER_GETHASH, SERIALIZE_TRANSACTION_NO_WITNESS); +} + +uint256 CTransaction::GetWitnessHash() const +{ + return SerializeHash(*this, SER_GETHASH, 0); } CTransaction::CTransaction() : nVersion(CTransaction::CURRENT_VERSION), vin(), vout(), nLockTime(0) { } -CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) { +CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), wit(tx.wit), nLockTime(tx.nLockTime) { UpdateHash(); } @@ -82,6 +87,7 @@ CTransaction& CTransaction::operator=(const CTransaction &tx) { *const_cast(&nVersion) = tx.nVersion; *const_cast*>(&vin) = tx.vin; *const_cast*>(&vout) = tx.vout; + *const_cast(&wit) = tx.wit; *const_cast(&nLockTime) = tx.nLockTime; *const_cast(&hash) = tx.hash; return *this; @@ -136,6 +142,8 @@ std::string CTransaction::ToString() const nLockTime); for (unsigned int i = 0; i < vin.size(); i++) str += " " + vin[i].ToString() + "\n"; + for (unsigned int i = 0; i < wit.vtxinwit.size(); i++) + str += " " + wit.vtxinwit[i].scriptWitness.ToString() + "\n"; for (unsigned int i = 0; i < vout.size(); i++) str += " " + vout[i].ToString() + "\n"; return str; diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 149816406a831..d8ae41ad78da3 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -11,6 +11,8 @@ #include "serialize.h" #include "uint256.h" +static const int SERIALIZE_TRANSACTION_NO_WITNESS = 0x40000000; + /** An outpoint - a combination of a transaction hash and an index n into its vout */ class COutPoint { @@ -194,8 +196,137 @@ class CTxOut std::string ToString() const; }; +class CTxinWitness +{ +public: + CScriptWitness scriptWitness; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + { + READWRITE(scriptWitness.stack); + } + + bool IsNull() const { return scriptWitness.IsNull(); } + + CTxinWitness() { } +}; + +class CTxWitness +{ +public: + /** In case vtxinwit is missing, all entries are treated as if they were empty CTxInWitnesses */ + std::vector vtxinwit; + + ADD_SERIALIZE_METHODS; + + bool IsEmpty() const { return vtxinwit.empty(); } + + bool IsNull() const + { + for (size_t n = 0; n < vtxinwit.size(); n++) { + if (!vtxinwit[n].IsNull()) { + return false; + } + } + return true; + } + + void SetNull() + { + vtxinwit.clear(); + } + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + { + for (size_t n = 0; n < vtxinwit.size(); n++) { + READWRITE(vtxinwit[n]); + } + if (IsNull()) { + /* It's illegal to encode a witness when all vtxinwit entries are empty. */ + throw std::ios_base::failure("Superfluous witness record"); + } + } +}; + struct CMutableTransaction; +/** + * Basic transaction serialization format: + * - int32_t nVersion + * - std::vector vin + * - std::vector vout + * - uint32_t nLockTime + * + * Extended transaction serialization format: + * - int32_t nVersion + * - unsigned char dummy = 0x00 + * - unsigned char flags (!= 0) + * - std::vector vin + * - std::vector vout + * - if (flags & 1): + * - CTxWitness wit; + * - uint32_t nLockTime + */ +template +inline void SerializeTransaction(TxType& tx, Stream& s, Operation ser_action, int nType, int nVersion) { + READWRITE(*const_cast(&tx.nVersion)); + unsigned char flags = 0; + if (ser_action.ForRead()) { + const_cast*>(&tx.vin)->clear(); + const_cast*>(&tx.vout)->clear(); + const_cast(&tx.wit)->SetNull(); + /* Try to read the vin. In case the dummy is there, this will be read as an empty vector. */ + READWRITE(*const_cast*>(&tx.vin)); + if (tx.vin.size() == 0 && !(nVersion & SERIALIZE_TRANSACTION_NO_WITNESS)) { + /* We read a dummy or an empty vin. */ + READWRITE(flags); + if (flags != 0) { + READWRITE(*const_cast*>(&tx.vin)); + READWRITE(*const_cast*>(&tx.vout)); + } + } else { + /* We read a non-empty vin. Assume a normal vout follows. */ + READWRITE(*const_cast*>(&tx.vout)); + } + if ((flags & 1) && !(nVersion & SERIALIZE_TRANSACTION_NO_WITNESS)) { + /* The witness flag is present, and we support witnesses. */ + flags ^= 1; + const_cast(&tx.wit)->vtxinwit.resize(tx.vin.size()); + READWRITE(tx.wit); + } + if (flags) { + /* Unknown flag in the serialization */ + throw std::ios_base::failure("Unknown transaction optional data"); + } + } else { + // Consistency check + assert(tx.wit.vtxinwit.size() <= tx.vin.size()); + if (!(nVersion & SERIALIZE_TRANSACTION_NO_WITNESS)) { + /* Check whether witnesses need to be serialized. */ + if (!tx.wit.IsNull()) { + flags |= 1; + } + } + if (flags) { + /* Use extended format in case witnesses are to be serialized. */ + std::vector vinDummy; + READWRITE(vinDummy); + READWRITE(flags); + } + READWRITE(*const_cast*>(&tx.vin)); + READWRITE(*const_cast*>(&tx.vout)); + if (flags & 1) { + const_cast(&tx.wit)->vtxinwit.resize(tx.vin.size()); + READWRITE(tx.wit); + } + } + READWRITE(*const_cast(&tx.nLockTime)); +} + /** The basic transaction that is broadcasted on the network and contained in * blocks. A transaction can contain multiple inputs and outputs. */ @@ -224,6 +355,7 @@ class CTransaction const int32_t nVersion; const std::vector vin; const std::vector vout; + CTxWitness wit; // Not const: can change without invalidating the txid cache const uint32_t nLockTime; /** Construct a CTransaction that qualifies as IsNull() */ @@ -238,13 +370,10 @@ class CTransaction template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(*const_cast(&this->nVersion)); - nVersion = this->nVersion; - READWRITE(*const_cast*>(&vin)); - READWRITE(*const_cast*>(&vout)); - READWRITE(*const_cast(&nLockTime)); - if (ser_action.ForRead()) + SerializeTransaction(*this, s, ser_action, nType, nVersion); + if (ser_action.ForRead()) { UpdateHash(); + } } bool IsNull() const { @@ -255,6 +384,9 @@ class CTransaction return hash; } + // Compute a hash that includes both transaction and witness data + uint256 GetWitnessHash() const; + // Return sum of txouts. CAmount GetValueOut() const; // GetValueIn() is a method on CCoinsViewCache, because @@ -290,6 +422,7 @@ struct CMutableTransaction int32_t nVersion; std::vector vin; std::vector vout; + CTxWitness wit; uint32_t nLockTime; CMutableTransaction(); @@ -299,11 +432,7 @@ struct CMutableTransaction template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(this->nVersion); - nVersion = this->nVersion; - READWRITE(vin); - READWRITE(vout); - READWRITE(nLockTime); + SerializeTransaction(*this, s, ser_action, nType, nVersion); } /** Compute the hash of this CMutableTransaction. This is computed on the diff --git a/src/protocol.cpp b/src/protocol.cpp index 2f90fb764cfbc..247c6c212073e 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -41,15 +41,6 @@ const char *GETBLOCKTXN="getblocktxn"; const char *BLOCKTXN="blocktxn"; }; -static const char* ppszTypeName[] = -{ - "ERROR", // Should never occur - NetMsgType::TX, - NetMsgType::BLOCK, - "filtered block", // Should never occur - "compact block" // Should never occur -}; - /** All known message types. Keep this in the same order as the list of * messages above and in protocol.h. */ @@ -166,37 +157,26 @@ CInv::CInv(int typeIn, const uint256& hashIn) hash = hashIn; } -CInv::CInv(const std::string& strType, const uint256& hashIn) -{ - unsigned int i; - for (i = 1; i < ARRAYLEN(ppszTypeName); i++) - { - if (strType == ppszTypeName[i]) - { - type = i; - break; - } - } - if (i == ARRAYLEN(ppszTypeName)) - throw std::out_of_range(strprintf("CInv::CInv(string, uint256): unknown type '%s'", strType)); - hash = hashIn; -} - bool operator<(const CInv& a, const CInv& b) { return (a.type < b.type || (a.type == b.type && a.hash < b.hash)); } -bool CInv::IsKnownType() const +std::string CInv::GetCommand() const { - return (type >= 1 && type < (int)ARRAYLEN(ppszTypeName)); -} - -const char* CInv::GetCommand() const -{ - if (!IsKnownType()) + std::string cmd; + if (type & MSG_WITNESS_FLAG) + cmd.append("witness-"); + int masked = type & MSG_TYPE_MASK; + switch (masked) + { + case MSG_TX: return cmd.append(NetMsgType::TX); + case MSG_BLOCK: return cmd.append(NetMsgType::BLOCK); + case MSG_FILTERED_BLOCK: return cmd.append(NetMsgType::MERKLEBLOCK); + case MSG_CMPCT_BLOCK: return cmd.append(NetMsgType::CMPCTBLOCK); + default: throw std::out_of_range(strprintf("CInv::GetCommand(): type=%d unknown type", type)); - return ppszTypeName[type]; + } } std::string CInv::ToString() const diff --git a/src/protocol.h b/src/protocol.h index a72813e959c64..dd07092f5f8d9 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -309,13 +309,29 @@ class CAddress : public CService unsigned int nTime; }; +/** getdata message types */ +const uint32_t MSG_WITNESS_FLAG = 1 << 30; +const uint32_t MSG_TYPE_MASK = 0xffffffff >> 2; +enum GetDataMsg +{ + UNDEFINED = 0, + MSG_TX, + MSG_BLOCK, + MSG_TYPE_MAX = MSG_BLOCK, + // The following can only occur in getdata. Invs always use TX or BLOCK. + MSG_FILTERED_BLOCK, + MSG_CMPCT_BLOCK, + MSG_WITNESS_BLOCK = MSG_BLOCK | MSG_WITNESS_FLAG, + MSG_WITNESS_TX = MSG_TX | MSG_WITNESS_FLAG, + MSG_FILTERED_WITNESS_BLOCK = MSG_FILTERED_BLOCK | MSG_WITNESS_FLAG, +}; + /** inv message data */ class CInv { public: CInv(); CInv(int typeIn, const uint256& hashIn); - CInv(const std::string& strType, const uint256& hashIn); ADD_SERIALIZE_METHODS; @@ -328,8 +344,7 @@ class CInv friend bool operator<(const CInv& a, const CInv& b); - bool IsKnownType() const; - const char* GetCommand() const; + std::string GetCommand() const; std::string ToString() const; // TODO: make private (improves encapsulation) @@ -338,13 +353,4 @@ class CInv uint256 hash; }; -enum { - MSG_TX = 1, - MSG_BLOCK, - // Nodes may always request a MSG_FILTERED_BLOCK/MSG_CMPCT_BLOCK in a getdata, however, - // MSG_FILTERED_BLOCK/MSG_CMPCT_BLOCK should not appear in any invs except as a part of getdata. - MSG_FILTERED_BLOCK, - MSG_CMPCT_BLOCK, -}; - #endif // BITCOIN_PROTOCOL_H diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index f909499952c7e..837f8ba6c18f5 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -485,6 +485,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) unsigned int nQuantity = 0; int nQuantityUncompressed = 0; bool fAllowFree = false; + bool fWitness = false; std::vector vCoinControl; std::vector vOutputs; @@ -513,7 +514,14 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) // Bytes CTxDestination address; - if(ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) + int witnessversion = 0; + std::vector witnessprogram; + if (out.tx->vout[out.i].scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) + { + nBytesInputs += (32 + 4 + 1 + (107 / WITNESS_SCALE_FACTOR) + 4); + fWitness = true; + } + else if(ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) { CPubKey pubkey; CKeyID *keyid = boost::get(&address); @@ -534,6 +542,14 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) { // Bytes nBytes = nBytesInputs + ((CoinControlDialog::payAmounts.size() > 0 ? CoinControlDialog::payAmounts.size() + 1 : 2) * 34) + 10; // always assume +1 output for change here + if (fWitness) + { + // there is some fudging in these numbers related to the actual virtual transaction size calculation that will keep this estimate from being exact. + // usually, the result will be an overestimate within a couple of satoshis so that the confirmation dialog ends up displaying a slightly smaller fee. + // also, the witness stack size value value is a variable sized integer. usually, the number of stack items will be well under the single byte var int limit. + nBytes += 2; // account for the serialized marker and flag bytes + nBytes += nQuantity; // account for the witness byte that holds the number of stack items for each input. + } // Priority double mempoolEstimatePriority = mempool.estimateSmartPriority(nTxConfirmTarget); diff --git a/src/qt/walletmodeltransaction.cpp b/src/qt/walletmodeltransaction.cpp index 8c970ee8aabe9..ffadf89cc8536 100644 --- a/src/qt/walletmodeltransaction.cpp +++ b/src/qt/walletmodeltransaction.cpp @@ -4,6 +4,7 @@ #include "walletmodeltransaction.h" +#include "policy/policy.h" #include "wallet/wallet.h" WalletModelTransaction::WalletModelTransaction(const QList &recipients) : @@ -33,7 +34,7 @@ CWalletTx *WalletModelTransaction::getTransaction() unsigned int WalletModelTransaction::getTransactionSize() { - return (!walletTransaction ? 0 : (::GetSerializeSize(*(CTransaction*)walletTransaction, SER_NETWORK, PROTOCOL_VERSION))); + return (!walletTransaction ? 0 : ::GetVirtualTransactionSize(*walletTransaction)); } CAmount WalletModelTransaction::getTransactionFee() diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 9723e394d6509..e4a6e0f39b388 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -276,7 +276,7 @@ UniValue gettxoutproof(const UniValue& params, bool fHelp) if (ntxFound != setTxids.size()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "(Not all) transactions not found in specified block"); - CDataStream ssMB(SER_NETWORK, PROTOCOL_VERSION); + CDataStream ssMB(SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS); CMerkleBlock mb(block, setTxids); ssMB << mb; std::string strHex = HexStr(ssMB.begin(), ssMB.end()); @@ -296,7 +296,7 @@ UniValue verifytxoutproof(const UniValue& params, bool fHelp) "[\"txid\"] (array, strings) The txid(s) which the proof commits to, or empty array if the proof is invalid\n" ); - CDataStream ssMB(ParseHexV(params[0], "proof"), SER_NETWORK, PROTOCOL_VERSION); + CDataStream ssMB(ParseHexV(params[0], "proof"), SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS); CMerkleBlock merkleBlock; ssMB >> merkleBlock; @@ -487,7 +487,7 @@ UniValue decoderawtransaction(const UniValue& params, bool fHelp) CTransaction tx; - if (!DecodeHexTx(tx, params[0].get_str())) + if (!DecodeHexTx(tx, params[0].get_str(), true)) throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); UniValue result(UniValue::VOBJ); diff --git a/src/script/script.cpp b/src/script/script.cpp index 9f2809e593756..6b1eb52bbf8c2 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -231,3 +231,15 @@ bool CScript::IsPushOnly() const { return this->IsPushOnly(begin()); } + +std::string CScriptWitness::ToString() const +{ + std::string ret = "CScriptWitness("; + for (unsigned int i = 0; i < stack.size(); i++) { + if (i) { + ret += ", "; + } + ret += HexStr(stack[i]); + } + return ret + ")"; +} diff --git a/src/script/script.h b/src/script/script.h index a2941ce9019d0..0b6d822d81ae0 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -643,6 +643,20 @@ class CScript : public CScriptBase } }; +struct CScriptWitness +{ + // Note that this encodes the data elements being pushed, rather than + // encoding them as a CScript that pushes them. + std::vector > stack; + + // Some compilers complain without a default constructor + CScriptWitness() { } + + bool IsNull() const { return stack.empty(); } + + std::string ToString() const; +}; + class CReserveScript { public: diff --git a/src/streams.h b/src/streams.h index ed14f3f412172..7132364eb1951 100644 --- a/src/streams.h +++ b/src/streams.h @@ -22,6 +22,39 @@ #include #include +template +class OverrideStream +{ + Stream* stream; +public: + const int nType; + const int nVersion; + + OverrideStream(Stream* stream_, int nType_, int nVersion_) : stream(stream_), nType(nType_), nVersion(nVersion_) {} + + template + OverrideStream& operator<<(const T& obj) + { + // Serialize to this stream + ::Serialize(*this->stream, obj, nType, nVersion); + return (*this); + } + + template + OverrideStream& operator>>(T& obj) + { + // Unserialize from this stream + ::Unserialize(*this->stream, obj, nType, nVersion); + return (*this); + } +}; + +template +OverrideStream WithOrVersion(S* s, int nVersionFlag) +{ + return OverrideStream(s, s->GetType(), s->GetVersion() | nVersionFlag); +} + /** Double ended buffer combining vector and stream-like interfaces. * * >> and << read and write unformatted data using the above serialization templates. diff --git a/src/test/data/tx_invalid.json b/src/test/data/tx_invalid.json index 2d7d9b958514b..4719f2b38877a 100644 --- a/src/test/data/tx_invalid.json +++ b/src/test/data/tx_invalid.json @@ -30,10 +30,6 @@ "010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", "P2SH"], ["Tests for CheckTransaction()"], -["No inputs"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]], -"0100000000010000000000000000015100000000", "P2SH"], - ["No outputs"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x05ab9e14d983742513f0f451e105ffb4198d1dd4 EQUAL"]], "01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022100f16703104aab4e4088317c862daec83440242411b039d14280e03dd33b487ab802201318a7be236672c5c56083eb7a5a195bc57a40af7923ff8545016cd3b571e2a601232103c40e5d339df3f30bf753e7e04450ae4ef76c9e45587d1d993bdc4cd06f0651c7acffffffff0000000000", "P2SH"], diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index e43b2ff6c45dc..375accbac7206 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -82,7 +82,7 @@ uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, un } // Serialize and hash - CHashWriter ss(SER_GETHASH, 0); + CHashWriter ss(SER_GETHASH, SERIALIZE_TRANSACTION_NO_WITNESS); ss << txTmp << nHashType; return ss.GetHash(); } diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index d9195bf345ca4..318fddc1ae9f9 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -208,7 +208,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid) } string transaction = test[1].get_str(); - CDataStream stream(ParseHex(transaction), SER_NETWORK, PROTOCOL_VERSION); + CDataStream stream(ParseHex(transaction), SER_NETWORK, PROTOCOL_VERSION ); CTransaction tx; stream >> tx; diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 2d4e95911dd0f..3666c37ac3eda 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2451,7 +2451,7 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) // parse hex string from parameter CTransaction origTx; - if (!DecodeHexTx(origTx, params[0].get_str())) + if (!DecodeHexTx(origTx, params[0].get_str(), true)) throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); if (origTx.vout.size() == 0) diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 71b0ff26db173..d083722dd23ac 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -7,6 +7,7 @@ #define BITCOIN_WALLET_WALLETDB_H #include "amount.h" +#include "primitives/transaction.h" #include "wallet/db.h" #include "key.h" From 449f9b8debcceb61a92043bc7031528a53627c47 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 8 Nov 2015 01:16:45 +0100 Subject: [PATCH 0538/1802] BIP141: Witness program --- src/bitcoin-tx.cpp | 2 +- src/main.cpp | 3 +- src/policy/policy.h | 4 +- src/rpc/rawtransaction.cpp | 2 +- src/script/bitcoinconsensus.cpp | 2 +- src/script/interpreter.cpp | 111 +++++++++++++++++++++++++++++++- src/script/interpreter.h | 12 +++- src/script/script.cpp | 18 ++++++ src/script/script.h | 1 + src/script/script_error.cpp | 14 ++++ src/script/script_error.h | 9 +++ src/script/sign.cpp | 2 +- src/test/multisig_tests.cpp | 16 ++--- src/test/script_P2SH_tests.cpp | 2 +- src/test/script_tests.cpp | 36 ++++++----- src/test/transaction_tests.cpp | 4 +- 16 files changed, 201 insertions(+), 37 deletions(-) diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index f9ea94b9f42d3..82a5583dda6e5 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -472,7 +472,7 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) BOOST_FOREACH(const CTransaction& txv, txVariants) { txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig); } - if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i))) + if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx.wit.vtxinwit.size() > i ? &mergedTx.wit.vtxinwit[i].scriptWitness : NULL, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i))) fComplete = false; } diff --git a/src/main.cpp b/src/main.cpp index 2184940232bc8..d1945a509429c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1867,7 +1867,8 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight) bool CScriptCheck::operator()() { const CScript &scriptSig = ptxTo->vin[nIn].scriptSig; - if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, cacheStore), &error)) { + const CScriptWitness *witness = (nIn < ptxTo->wit.vtxinwit.size()) ? &ptxTo->wit.vtxinwit[nIn].scriptWitness : NULL; + if (!VerifyScript(scriptSig, scriptPubKey, witness, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, cacheStore), &error)) { return false; } return true; diff --git a/src/policy/policy.h b/src/policy/policy.h index 4f9354e36fe71..a6bcc777ff51d 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -41,7 +41,9 @@ static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY | SCRIPT_VERIFY_CHECKSEQUENCEVERIFY | - SCRIPT_VERIFY_LOW_S; + SCRIPT_VERIFY_LOW_S | + SCRIPT_VERIFY_WITNESS | + SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM; /** For convenience, standard but not mandatory verify flags. */ static const unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS; diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index e4a6e0f39b388..17c9a84602e35 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -789,7 +789,7 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp) txin.scriptSig = CombineSignatures(prevPubKey, txConst, i, txin.scriptSig, txv.vin[i].scriptSig); } ScriptError serror = SCRIPT_ERR_OK; - if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i), &serror)) { + if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx.wit.vtxinwit.size() > i ? &mergedTx.wit.vtxinwit[i].scriptWitness : NULL, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i), &serror)) { TxInErrorToJSON(txin, vErrors, ScriptErrorString(serror)); } } diff --git a/src/script/bitcoinconsensus.cpp b/src/script/bitcoinconsensus.cpp index 47ad1d08073b9..5c9e7c0a571a5 100644 --- a/src/script/bitcoinconsensus.cpp +++ b/src/script/bitcoinconsensus.cpp @@ -85,7 +85,7 @@ int bitcoinconsensus_verify_script(const unsigned char *scriptPubKey, unsigned i // Regardless of the verification result, the tx did not error. set_error(err, bitcoinconsensus_ERR_OK); - return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), flags, TransactionSignatureChecker(&tx, nIn), NULL); + return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), nIn < tx.wit.vtxinwit.size() ? &tx.wit.vtxinwit[nIn].scriptWitness : NULL, flags, TransactionSignatureChecker(&tx, nIn), NULL); } catch (const std::exception&) { return set_error(err, bitcoinconsensus_ERR_TX_DESERIALIZE); // Error deserializing } diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index fd4a5674cfea1..be649fca20d3d 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1239,8 +1239,67 @@ bool TransactionSignatureChecker::CheckSequence(const CScriptNum& nSequence) con return true; } -bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror) +static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion, const std::vector& program, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror) { + vector > stack; + CScript scriptPubKey; + + if (witversion == 0) { + if (program.size() == 32) { + // Version 0 segregated witness program: SHA256(CScript) inside the program, CScript + inputs in witness + if (witness.stack.size() == 0) { + return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY); + } + scriptPubKey = CScript(witness.stack.back().begin(), witness.stack.back().end()); + stack = std::vector >(witness.stack.begin(), witness.stack.end() - 1); + uint256 hashScriptPubKey; + CSHA256().Write(&scriptPubKey[0], scriptPubKey.size()).Finalize(hashScriptPubKey.begin()); + if (memcmp(hashScriptPubKey.begin(), &program[0], 32)) { + return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH); + } + } else if (program.size() == 20) { + // Special case for pay-to-pubkeyhash; signature + pubkey in witness + if (witness.stack.size() != 2) { + return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH); // 2 items in witness + } + scriptPubKey << OP_DUP << OP_HASH160 << program << OP_EQUALVERIFY << OP_CHECKSIG; + stack = witness.stack; + } else { + return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH); + } + } else if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM) { + return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM); + } else { + // Higher version witness scripts return true for future softfork compatibility + return set_success(serror); + } + + // Disallow stack item size > MAX_SCRIPT_ELEMENT_SIZE in witness stack + for (unsigned int i = 0; i < stack.size(); i++) { + if (stack.at(i).size() > MAX_SCRIPT_ELEMENT_SIZE) + return set_error(serror, SCRIPT_ERR_PUSH_SIZE); + } + + if (!EvalScript(stack, scriptPubKey, flags, checker, serror)) { + return false; + } + + // Scripts inside witness implicitly require cleanstack behaviour + if (stack.size() != 1) + return set_error(serror, SCRIPT_ERR_EVAL_FALSE); + if (!CastToBool(stack.back())) + return set_error(serror, SCRIPT_ERR_EVAL_FALSE); + return true; +} + +bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror) +{ + static const CScriptWitness emptyWitness; + if (witness == NULL) { + witness = &emptyWitness; + } + bool hadWitness = false; + set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR); if ((flags & SCRIPT_VERIFY_SIGPUSHONLY) != 0 && !scriptSig.IsPushOnly()) { @@ -1261,6 +1320,25 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigne if (CastToBool(stack.back()) == false) return set_error(serror, SCRIPT_ERR_EVAL_FALSE); + // Bare witness programs + int witnessversion; + std::vector witnessprogram; + if (flags & SCRIPT_VERIFY_WITNESS) { + if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) { + hadWitness = true; + if (scriptSig.size() != 0) { + // The scriptSig must be _exactly_ CScript(), otherwise we reintroduce malleability. + return set_error(serror, SCRIPT_ERR_WITNESS_MALLEATED); + } + if (!VerifyWitnessProgram(*witness, witnessversion, witnessprogram, flags, checker, serror)) { + return false; + } + // Bypass the cleanstack check at the end. The actual stack is obviously not clean + // for witness programs. + stack.resize(1); + } + } + // Additional validation for spend-to-script-hash transactions: if ((flags & SCRIPT_VERIFY_P2SH) && scriptPubKey.IsPayToScriptHash()) { @@ -1287,19 +1365,48 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigne return set_error(serror, SCRIPT_ERR_EVAL_FALSE); if (!CastToBool(stack.back())) return set_error(serror, SCRIPT_ERR_EVAL_FALSE); + + // P2SH witness program + if (flags & SCRIPT_VERIFY_WITNESS) { + if (pubKey2.IsWitnessProgram(witnessversion, witnessprogram)) { + hadWitness = true; + if (scriptSig != CScript() << std::vector(pubKey2.begin(), pubKey2.end())) { + // The scriptSig must be _exactly_ a single push of the redeemScript. Otherwise we + // reintroduce malleability. + return set_error(serror, SCRIPT_ERR_WITNESS_MALLEATED_P2SH); + } + if (!VerifyWitnessProgram(*witness, witnessversion, witnessprogram, flags, checker, serror)) { + return false; + } + // Bypass the cleanstack check at the end. The actual stack is obviously not clean + // for witness programs. + stack.resize(1); + } + } } // The CLEANSTACK check is only performed after potential P2SH evaluation, // as the non-P2SH evaluation of a P2SH script will obviously not result in - // a clean stack (the P2SH inputs remain). + // a clean stack (the P2SH inputs remain). The same holds for witness evaluation. if ((flags & SCRIPT_VERIFY_CLEANSTACK) != 0) { // Disallow CLEANSTACK without P2SH, as otherwise a switch CLEANSTACK->P2SH+CLEANSTACK // would be possible, which is not a softfork (and P2SH should be one). assert((flags & SCRIPT_VERIFY_P2SH) != 0); + assert((flags & SCRIPT_VERIFY_WITNESS) != 0); if (stack.size() != 1) { return set_error(serror, SCRIPT_ERR_CLEANSTACK); } } + if (flags & SCRIPT_VERIFY_WITNESS) { + // We can't check for correct unexpected witness data if P2SH was off, so require + // that WITNESS implies P2SH. Otherwise, going from WITNESS->P2SH+WITNESS would be + // possible, which is not a softfork. + assert((flags & SCRIPT_VERIFY_P2SH) != 0); + if (!hadWitness && !witness->IsNull()) { + return set_error(serror, SCRIPT_ERR_WITNESS_UNEXPECTED); + } + } + return set_success(serror); } diff --git a/src/script/interpreter.h b/src/script/interpreter.h index e5cb7290f2225..d1459ed620f6b 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -74,7 +74,7 @@ enum // "At least one stack element must remain, and when interpreted as a boolean, it must be true" to // "Exactly one stack element must remain, and when interpreted as a boolean, it must be true". // (softfork safe, BIP62 rule 6) - // Note: CLEANSTACK should never be used without P2SH. + // Note: CLEANSTACK should never be used without P2SH or WITNESS. SCRIPT_VERIFY_CLEANSTACK = (1U << 8), // Verify CHECKLOCKTIMEVERIFY @@ -86,6 +86,14 @@ enum // // See BIP112 for details SCRIPT_VERIFY_CHECKSEQUENCEVERIFY = (1U << 10), + + // Support segregated witness + // + SCRIPT_VERIFY_WITNESS = (1U << 11), + + // Making v1-v16 witness program non-standard + // + SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM = (1U << 12), }; bool CheckSignatureEncoding(const std::vector &vchSig, unsigned int flags, ScriptError* serror); @@ -139,6 +147,6 @@ class MutableTransactionSignatureChecker : public TransactionSignatureChecker }; bool EvalScript(std::vector >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* error = NULL); -bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* error = NULL); +bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror = NULL); #endif // BITCOIN_SCRIPT_INTERPRETER_H diff --git a/src/script/script.cpp b/src/script/script.cpp index 6b1eb52bbf8c2..73f5a61bf68bd 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -210,6 +210,24 @@ bool CScript::IsPayToScriptHash() const (*this)[22] == OP_EQUAL); } +// A witness program is any valid CScript that consists of a 1-byte push opcode +// followed by a data push between 2 and 40 bytes. +bool CScript::IsWitnessProgram(int& version, std::vector& program) const +{ + if (this->size() < 4 || this->size() > 42) { + return false; + } + if ((*this)[0] != OP_0 && ((*this)[0] < OP_1 || (*this)[0] > OP_16)) { + return false; + } + if ((size_t)((*this)[1] + 2) == this->size()) { + version = DecodeOP_N((opcodetype)(*this)[0]); + program = std::vector(this->begin() + 2, this->end()); + return true; + } + return false; +} + bool CScript::IsPushOnly(const_iterator pc) const { while (pc < end()) diff --git a/src/script/script.h b/src/script/script.h index 0b6d822d81ae0..b9b5be901389c 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -621,6 +621,7 @@ class CScript : public CScriptBase unsigned int GetSigOpCount(const CScript& scriptSig) const; bool IsPayToScriptHash() const; + bool IsWitnessProgram(int& version, std::vector& program) const; /** Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical). */ bool IsPushOnly(const_iterator pc) const; diff --git a/src/script/script_error.cpp b/src/script/script_error.cpp index f1aa1fb408ae5..cef807edcf475 100644 --- a/src/script/script_error.cpp +++ b/src/script/script_error.cpp @@ -65,8 +65,22 @@ const char* ScriptErrorString(const ScriptError serror) return "Dummy CHECKMULTISIG argument must be zero"; case SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS: return "NOPx reserved for soft-fork upgrades"; + case SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM: + return "Witness version reserved for soft-fork upgrades"; case SCRIPT_ERR_PUBKEYTYPE: return "Public key is neither compressed or uncompressed"; + case SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH: + return "Witness program has incorrect length"; + case SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY: + return "Witness program was passed an empty witness"; + case SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH: + return "Witness program hash mismatch"; + case SCRIPT_ERR_WITNESS_MALLEATED: + return "Witness requires empty scriptSig"; + case SCRIPT_ERR_WITNESS_MALLEATED_P2SH: + return "Witness requires only-redeemscript scriptSig"; + case SCRIPT_ERR_WITNESS_UNEXPECTED: + return "Witness provided for non-witness script"; case SCRIPT_ERR_UNKNOWN_ERROR: case SCRIPT_ERR_ERROR_COUNT: default: break; diff --git a/src/script/script_error.h b/src/script/script_error.h index 26df33932fdd6..09dc6945adb45 100644 --- a/src/script/script_error.h +++ b/src/script/script_error.h @@ -51,6 +51,15 @@ typedef enum ScriptError_t /* softfork safeness */ SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS, + SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM, + + /* segregated witness */ + SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH, + SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY, + SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH, + SCRIPT_ERR_WITNESS_MALLEATED, + SCRIPT_ERR_WITNESS_MALLEATED_P2SH, + SCRIPT_ERR_WITNESS_UNEXPECTED, SCRIPT_ERR_ERROR_COUNT } ScriptError; diff --git a/src/script/sign.cpp b/src/script/sign.cpp index 2f4111f786420..37b702de17cb6 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -123,7 +123,7 @@ bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& fromPu } // Test solution - return VerifyScript(scriptSig, fromPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, creator.Checker()); + return VerifyScript(scriptSig, fromPubKey, NULL, STANDARD_SCRIPT_VERIFY_FLAGS, creator.Checker()); } bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, int nHashType) diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp index d48a68ba547c5..a6435d94d3ad4 100644 --- a/src/test/multisig_tests.cpp +++ b/src/test/multisig_tests.cpp @@ -81,20 +81,20 @@ BOOST_AUTO_TEST_CASE(multisig_verify) keys.assign(1,key[0]); keys.push_back(key[1]); s = sign_multisig(a_and_b, keys, txTo[0], 0); - BOOST_CHECK(VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], 0), &err)); + BOOST_CHECK(VerifyScript(s, a_and_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[0], 0), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); for (int i = 0; i < 4; i++) { keys.assign(1,key[i]); s = sign_multisig(a_and_b, keys, txTo[0], 0); - BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], 0), &err), strprintf("a&b 1: %d", i)); + BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[0], 0), &err), strprintf("a&b 1: %d", i)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err)); keys.assign(1,key[1]); keys.push_back(key[i]); s = sign_multisig(a_and_b, keys, txTo[0], 0); - BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], 0), &err), strprintf("a&b 2: %d", i)); + BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[0], 0), &err), strprintf("a&b 2: %d", i)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); } @@ -105,18 +105,18 @@ BOOST_AUTO_TEST_CASE(multisig_verify) s = sign_multisig(a_or_b, keys, txTo[1], 0); if (i == 0 || i == 1) { - BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], 0), &err), strprintf("a|b: %d", i)); + BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[1], 0), &err), strprintf("a|b: %d", i)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); } else { - BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], 0), &err), strprintf("a|b: %d", i)); + BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[1], 0), &err), strprintf("a|b: %d", i)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); } } s.clear(); s << OP_0 << OP_1; - BOOST_CHECK(!VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], 0), &err)); + BOOST_CHECK(!VerifyScript(s, a_or_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[1], 0), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_SIG_DER, ScriptErrorString(err)); @@ -128,12 +128,12 @@ BOOST_AUTO_TEST_CASE(multisig_verify) s = sign_multisig(escrow, keys, txTo[2], 0); if (i < j && i < 3 && j < 3) { - BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, flags, MutableTransactionSignatureChecker(&txTo[2], 0), &err), strprintf("escrow 1: %d %d", i, j)); + BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, NULL, flags, MutableTransactionSignatureChecker(&txTo[2], 0), &err), strprintf("escrow 1: %d %d", i, j)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); } else { - BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, flags, MutableTransactionSignatureChecker(&txTo[2], 0), &err), strprintf("escrow 2: %d %d", i, j)); + BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, NULL, flags, MutableTransactionSignatureChecker(&txTo[2], 0), &err), strprintf("escrow 2: %d %d", i, j)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); } } diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp index d10284fe940e5..d6b5f41d44ac5 100644 --- a/src/test/script_P2SH_tests.cpp +++ b/src/test/script_P2SH_tests.cpp @@ -42,7 +42,7 @@ Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict, Scri txTo.vin[0].scriptSig = scriptSig; txTo.vout[0].nValue = 1; - return VerifyScript(scriptSig, scriptPubKey, fStrict ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE, MutableTransactionSignatureChecker(&txTo, 0), &err); + return VerifyScript(scriptSig, scriptPubKey, NULL, fStrict ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE, MutableTransactionSignatureChecker(&txTo, 0), &err); } diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 39089f103d0c2..d402ba56bbbf6 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -147,10 +147,14 @@ CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CMu void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, int flags, const std::string& message, int scriptError) { bool expect = (scriptError == SCRIPT_ERR_OK); + if (flags & SCRIPT_VERIFY_CLEANSTACK) { + flags |= SCRIPT_VERIFY_P2SH; + flags |= SCRIPT_VERIFY_WITNESS; + } ScriptError err; CMutableTransaction tx = BuildSpendingTransaction(scriptSig, BuildCreditingTransaction(scriptPubKey)); CMutableTransaction tx2 = tx; - BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, flags, MutableTransactionSignatureChecker(&tx, 0), &err) == expect, message); + BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, NULL, flags, MutableTransactionSignatureChecker(&tx, 0), &err) == expect, message); BOOST_CHECK_MESSAGE(err == scriptError, std::string(FormatScriptError(err)) + " where " + std::string(FormatScriptError((ScriptError_t)scriptError)) + " expected: " + message); #if defined(HAVE_CONSENSUS_LIB) CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); @@ -799,18 +803,18 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12) CMutableTransaction txTo12 = BuildSpendingTransaction(CScript(), txFrom12); CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12); - BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0), &err)); + BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, NULL, flags, MutableTransactionSignatureChecker(&txTo12, 0), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); txTo12.vout[0].nValue = 2; - BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0), &err)); + BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, NULL, flags, MutableTransactionSignatureChecker(&txTo12, 0), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); CScript goodsig2 = sign_multisig(scriptPubKey12, key2, txTo12); - BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0), &err)); + BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, NULL, flags, MutableTransactionSignatureChecker(&txTo12, 0), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); CScript badsig1 = sign_multisig(scriptPubKey12, key3, txTo12); - BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0), &err)); + BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, NULL, flags, MutableTransactionSignatureChecker(&txTo12, 0), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); } @@ -832,54 +836,54 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23) std::vector keys; keys.push_back(key1); keys.push_back(key2); CScript goodsig1 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); + BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); keys.clear(); keys.push_back(key1); keys.push_back(key3); CScript goodsig2 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); + BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); keys.clear(); keys.push_back(key2); keys.push_back(key3); CScript goodsig3 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); + BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); keys.clear(); keys.push_back(key2); keys.push_back(key2); // Can't re-use sig CScript badsig1 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); + BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); keys.clear(); keys.push_back(key2); keys.push_back(key1); // sigs must be in correct order CScript badsig2 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); + BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); keys.clear(); keys.push_back(key3); keys.push_back(key2); // sigs must be in correct order CScript badsig3 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); + BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); keys.clear(); keys.push_back(key4); keys.push_back(key2); // sigs must match pubkeys CScript badsig4 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); + BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); keys.clear(); keys.push_back(key1); keys.push_back(key4); // sigs must match pubkeys CScript badsig5 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); + BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); keys.clear(); // Must have signatures CScript badsig6 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); + BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err)); } @@ -999,7 +1003,7 @@ BOOST_AUTO_TEST_CASE(script_standard_push) CScript script; script << i; BOOST_CHECK_MESSAGE(script.IsPushOnly(), "Number " << i << " is not pure push."); - BOOST_CHECK_MESSAGE(VerifyScript(script, CScript() << OP_1, SCRIPT_VERIFY_MINIMALDATA, BaseSignatureChecker(), &err), "Number " << i << " push is not minimal data."); + BOOST_CHECK_MESSAGE(VerifyScript(script, CScript() << OP_1, NULL, SCRIPT_VERIFY_MINIMALDATA, BaseSignatureChecker(), &err), "Number " << i << " push is not minimal data."); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); } @@ -1008,7 +1012,7 @@ BOOST_AUTO_TEST_CASE(script_standard_push) CScript script; script << data; BOOST_CHECK_MESSAGE(script.IsPushOnly(), "Length " << i << " is not pure push."); - BOOST_CHECK_MESSAGE(VerifyScript(script, CScript() << OP_1, SCRIPT_VERIFY_MINIMALDATA, BaseSignatureChecker(), &err), "Length " << i << " push is not minimal data."); + BOOST_CHECK_MESSAGE(VerifyScript(script, CScript() << OP_1, NULL, SCRIPT_VERIFY_MINIMALDATA, BaseSignatureChecker(), &err), "Length " << i << " push is not minimal data."); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); } } diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 318fddc1ae9f9..9a24a613e5164 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -151,7 +151,7 @@ BOOST_AUTO_TEST_CASE(tx_valid) unsigned int verify_flags = ParseScriptFlags(test[2].get_str()); BOOST_CHECK_MESSAGE(VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], - verify_flags, TransactionSignatureChecker(&tx, i), &err), + NULL, verify_flags, TransactionSignatureChecker(&tx, i), &err), strTest); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); } @@ -225,7 +225,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid) unsigned int verify_flags = ParseScriptFlags(test[2].get_str()); fValid = VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], - verify_flags, TransactionSignatureChecker(&tx, i), &err); + NULL, verify_flags, TransactionSignatureChecker(&tx, i), &err); } BOOST_CHECK_MESSAGE(!fValid, strTest); BOOST_CHECK_MESSAGE(err != SCRIPT_ERR_OK, ScriptErrorString(err)); From 8b49040854be2e26b66366aeae1cba4716f93d93 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 6 Nov 2015 01:42:38 +0100 Subject: [PATCH 0539/1802] BIP141: Commitment structure and deployment Includes a fix by Suhas Daftuar and LongShao007 --- src/chainparams.cpp | 14 ++++ src/consensus/merkle.cpp | 11 +++ src/consensus/merkle.h | 6 ++ src/consensus/params.h | 1 + src/consensus/validation.h | 3 + src/main.cpp | 146 +++++++++++++++++++++++++++++++++-- src/main.h | 9 +++ src/miner.cpp | 18 +++++ src/miner.h | 2 + src/primitives/transaction.h | 3 +- src/rpc/blockchain.cpp | 1 + src/rpc/mining.cpp | 20 ++++- src/versionbits.cpp | 4 + 13 files changed, 225 insertions(+), 13 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 8c27a578bb948..2a198e8554c93 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -92,6 +92,11 @@ class CMainParams : public CChainParams { consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 1462060800; // May 1st, 2016 consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 1493596800; // May 1st, 2017 + // Deployment of SegWit (BIP141 and BIP143) + consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].bit = 1; + consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 0; + consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 0; // Never / undefined + /** * The message start string is designed to be unlikely to occur in normal data. * The characters are rarely used upper ASCII, not valid as UTF-8, and produce @@ -183,6 +188,11 @@ class CTestNetParams : public CChainParams { consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 1456790400; // March 1st, 2016 consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 1493596800; // May 1st, 2017 + // Deployment of SegWit (BIP141 and BIP143) + consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].bit = 1; + consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 2000000000; // Far in the future + consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 2100000000; + pchMessageStart[0] = 0x0b; pchMessageStart[1] = 0x11; pchMessageStart[2] = 0x09; @@ -255,6 +265,9 @@ class CRegTestParams : public CChainParams { consensus.vDeployments[Consensus::DEPLOYMENT_CSV].bit = 0; consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 0; consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 999999999999ULL; + consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].bit = 1; + consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 0; + consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 999999999999ULL; pchMessageStart[0] = 0xfa; pchMessageStart[1] = 0xbf; @@ -317,3 +330,4 @@ void SelectParams(const std::string& network) SelectBaseParams(network); pCurrentParams = &Params(network); } + diff --git a/src/consensus/merkle.cpp b/src/consensus/merkle.cpp index 22eb7159a28f9..35f7d2e05a937 100644 --- a/src/consensus/merkle.cpp +++ b/src/consensus/merkle.cpp @@ -165,6 +165,17 @@ uint256 BlockMerkleRoot(const CBlock& block, bool* mutated) return ComputeMerkleRoot(leaves, mutated); } +uint256 BlockWitnessMerkleRoot(const CBlock& block, bool* mutated) +{ + std::vector leaves; + leaves.resize(block.vtx.size()); + leaves[0].SetNull(); // The witness hash of the coinbase is 0. + for (size_t s = 1; s < block.vtx.size(); s++) { + leaves[s] = block.vtx[s].GetWitnessHash(); + } + return ComputeMerkleRoot(leaves, mutated); +} + std::vector BlockMerkleBranch(const CBlock& block, uint32_t position) { std::vector leaves; diff --git a/src/consensus/merkle.h b/src/consensus/merkle.h index 6ef59745ac653..194aea9b75dc3 100644 --- a/src/consensus/merkle.h +++ b/src/consensus/merkle.h @@ -22,6 +22,12 @@ uint256 ComputeMerkleRootFromBranch(const uint256& leaf, const std::vectorpprev, chainparams.GetConsensus())) { + flags |= SCRIPT_VERIFY_WITNESS; + } + int64_t nTime2 = GetTimeMicros(); nTimeForks += nTime2 - nTime1; LogPrint("bench", " - Fork checks: %.2fms [%.2fs]\n", 0.001 * (nTime2 - nTime1), nTimeForks * 0.000001); @@ -3441,6 +3462,71 @@ static bool CheckIndexAgainstCheckpoint(const CBlockIndex* pindexPrev, CValidati return true; } +bool IsWitnessEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& params) +{ + LOCK(cs_main); + return (VersionBitsState(pindexPrev, params, Consensus::DEPLOYMENT_SEGWIT, versionbitscache) == THRESHOLD_ACTIVE); +} + +// Compute at which vout of the block's coinbase transaction the witness +// commitment occurs, or -1 if not found. +static int GetWitnessCommitmentIndex(const CBlock& block) +{ + int commitpos = -1; + for (size_t o = 0; o < block.vtx[0].vout.size(); o++) { + if (block.vtx[0].vout[o].scriptPubKey.size() >= 38 && block.vtx[0].vout[o].scriptPubKey[0] == OP_RETURN && block.vtx[0].vout[o].scriptPubKey[1] == 0x24 && block.vtx[0].vout[o].scriptPubKey[2] == 0xaa && block.vtx[0].vout[o].scriptPubKey[3] == 0x21 && block.vtx[0].vout[o].scriptPubKey[4] == 0xa9 && block.vtx[0].vout[o].scriptPubKey[5] == 0xed) { + commitpos = o; + } + } + return commitpos; +} + +void UpdateUncommittedBlockStructures(CBlock& block, const CBlockIndex* pindexPrev, const Consensus::Params& consensusParams) +{ + int commitpos = GetWitnessCommitmentIndex(block); + static const std::vector nonce(32, 0x00); + if (commitpos != -1 && IsWitnessEnabled(pindexPrev, consensusParams) && block.vtx[0].wit.IsEmpty()) { + block.vtx[0].wit.vtxinwit.resize(1); + block.vtx[0].wit.vtxinwit[0].scriptWitness.stack.resize(1); + block.vtx[0].wit.vtxinwit[0].scriptWitness.stack[0] = nonce; + } +} + +std::vector GenerateCoinbaseCommitment(CBlock& block, const CBlockIndex* pindexPrev, const Consensus::Params& consensusParams) +{ + std::vector commitment; + int commitpos = GetWitnessCommitmentIndex(block); + bool fHaveWitness = false; + for (size_t t = 1; t < block.vtx.size(); t++) { + if (!block.vtx[t].wit.IsNull()) { + fHaveWitness = true; + break; + } + } + std::vector ret(32, 0x00); + if (fHaveWitness && IsWitnessEnabled(pindexPrev, consensusParams)) { + if (commitpos == -1) { + uint256 witnessroot = BlockWitnessMerkleRoot(block, NULL); + CHash256().Write(witnessroot.begin(), 32).Write(&ret[0], 32).Finalize(witnessroot.begin()); + CTxOut out; + out.nValue = 0; + out.scriptPubKey.resize(38); + out.scriptPubKey[0] = OP_RETURN; + out.scriptPubKey[1] = 0x24; + out.scriptPubKey[2] = 0xaa; + out.scriptPubKey[3] = 0x21; + out.scriptPubKey[4] = 0xa9; + out.scriptPubKey[5] = 0xed; + memcpy(&out.scriptPubKey[6], witnessroot.begin(), 32); + commitment = std::vector(out.scriptPubKey.begin(), out.scriptPubKey.end()); + const_cast*>(&block.vtx[0].vout)->push_back(out); + block.vtx[0].UpdateHash(); + } + } + UpdateUncommittedBlockStructures(block, pindexPrev, consensusParams); + return commitment; +} + bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex * const pindexPrev, int64_t nAdjustedTime) { // Check proof of work @@ -3497,6 +3583,43 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn } } + // Validation for witness commitments. + // * We compute the witness hash (which is the hash including witnesses) of all the block's transactions, except the + // coinbase (where 0x0000....0000 is used instead). + // * The coinbase scriptWitness is a stack of a single 32-byte vector, containing a witness nonce (unconstrained). + // * We build a merkle tree with all those witness hashes as leaves (similar to the hashMerkleRoot in the block header). + // * There must be at least one output whose scriptPubKey is a single 36-byte push, the first 4 bytes of which are + // {0xaa, 0x21, 0xa9, 0xed}, and the following 32 bytes are SHA256^2(witness root, witness nonce). In case there are + // multiple, the last one is used. + bool fHaveWitness = false; + if (IsWitnessEnabled(pindexPrev, consensusParams)) { + int commitpos = GetWitnessCommitmentIndex(block); + if (commitpos != -1) { + bool malleated = false; + uint256 hashWitness = BlockWitnessMerkleRoot(block, &malleated); + // The malleation check is ignored; as the transaction tree itself + // already does not permit it, it is impossible to trigger in the + // witness tree. + if (block.vtx[0].wit.vtxinwit.size() != 1 || block.vtx[0].wit.vtxinwit[0].scriptWitness.stack.size() != 1 || block.vtx[0].wit.vtxinwit[0].scriptWitness.stack[0].size() != 32) { + return state.DoS(100, error("%s : invalid witness nonce size", __func__), REJECT_INVALID, "bad-witness-nonce-size", true); + } + CHash256().Write(hashWitness.begin(), 32).Write(&block.vtx[0].wit.vtxinwit[0].scriptWitness.stack[0][0], 32).Finalize(hashWitness.begin()); + if (memcmp(hashWitness.begin(), &block.vtx[0].vout[commitpos].scriptPubKey[6], 32)) { + return state.DoS(100, error("%s : witness merkle commitment mismatch", __func__), REJECT_INVALID, "bad-witness-merkle-match", true); + } + fHaveWitness = true; + } + } + + // No witness data is allowed in blocks that don't commit to witness data, as this would otherwise leave room for spam + if (!fHaveWitness) { + for (size_t i = 0; i < block.vtx.size(); i++) { + if (!block.vtx[i].wit.IsNull()) { + return state.DoS(100, error("%s : unexpected witness data found", __func__), REJECT_INVALID, "unexpected-witness", true); + } + } + } + return true; } @@ -5278,7 +5401,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, else if (!fMissingInputs2) { int nDos = 0; - if (stateDummy.IsInvalid(nDos) && nDos > 0) + if (stateDummy.IsInvalid(nDos) && nDos > 0 && (!state.CorruptionPossible() || State(fromPeer)->fHaveWitness)) { // Punish peer that gave us an invalid orphan tx Misbehaving(fromPeer, nDos); @@ -5289,8 +5412,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // Probably non-standard or insufficient fee/priority LogPrint("mempool", " removed orphan tx %s\n", orphanHash.ToString()); vEraseQueue.push_back(orphanHash); - assert(recentRejects); - recentRejects->insert(orphanHash); + if (!stateDummy.CorruptionPossible()) { + assert(recentRejects); + recentRejects->insert(orphanHash); + } } mempool.check(pcoinsTip); } @@ -5325,8 +5450,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, LogPrint("mempool", "not keeping orphan with rejected parents %s\n",tx.GetHash().ToString()); } } else { - assert(recentRejects); - recentRejects->insert(tx.GetHash()); + if (!state.CorruptionPossible()) { + assert(recentRejects); + recentRejects->insert(tx.GetHash()); + } if (pfrom->fWhitelisted && GetBoolArg("-whitelistforcerelay", DEFAULT_WHITELISTFORCERELAY)) { // Always relay transactions received from whitelisted peers, even @@ -5355,8 +5482,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, if (state.GetRejectCode() < REJECT_INTERNAL) // Never send AcceptToMemoryPool's internal codes over P2P pfrom->PushMessage(NetMsgType::REJECT, strCommand, (unsigned char)state.GetRejectCode(), state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash); - if (nDoS > 0) + if (nDoS > 0 && (!state.CorruptionPossible() || State(pfrom->id)->fHaveWitness)) { + // When a non-witness-supporting peer gives us a transaction that would + // be accepted if witness validation was off, we can't blame them for it. Misbehaving(pfrom->GetId(), nDoS); + } } FlushStateToDisk(state, FLUSH_STATE_PERIODIC); } diff --git a/src/main.h b/src/main.h index f004a29bb1a13..d0dce7068700c 100644 --- a/src/main.h +++ b/src/main.h @@ -453,6 +453,15 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI /** Check a block is completely valid from start to finish (only works on top of our current best block, with cs_main held) */ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, const CBlock& block, CBlockIndex* pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true); +/** Check whether witness commitments are required for block. */ +bool IsWitnessEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& params); + +/** Update uncommitted block structures (currently: only the witness nonce). This is safe for submitted blocks. */ +void UpdateUncommittedBlockStructures(CBlock& block, const CBlockIndex* pindexPrev, const Consensus::Params& consensusParams); + +/** Produce the necessary coinbase commitment for a block (modifies the hash, don't call for mined blocks). */ +std::vector GenerateCoinbaseCommitment(CBlock& block, const CBlockIndex* pindexPrev, const Consensus::Params& consensusParams); + /** RAII wrapper for VerifyDB: Verify consistency of the block and coin databases */ class CVerifyDB { public: diff --git a/src/miner.cpp b/src/miner.cpp index 989ad11a2614d..a7bf9ae84ccd7 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -93,6 +93,7 @@ void BlockAssembler::resetBlock() // Reserve space for coinbase tx nBlockSize = 1000; nBlockSigOps = 100; + fIncludeWitness = false; // These counters do not include coinbase tx nBlockTx = 0; @@ -134,6 +135,14 @@ CBlockTemplate* BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn) ? nMedianTimePast : pblock->GetBlockTime(); + // Decide whether to include witness transactions + // This is only needed in case the witness softfork activation is reverted + // (which would require a very deep reorganization) or when + // -promiscuousmempoolflags is used. + // TODO: replace this with a call to main to assess validity of a mempool + // transaction (which in most cases can be a no-op). + fIncludeWitness = IsWitnessEnabled(pindexPrev, chainparams.GetConsensus()); + addPriorityTxs(); addPackageTxs(); @@ -150,6 +159,7 @@ CBlockTemplate* BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn) coinbaseTx.vout[0].nValue = nFees + GetBlockSubsidy(nHeight, chainparams.GetConsensus()); coinbaseTx.vin[0].scriptSig = CScript() << nHeight << OP_0; pblock->vtx[0] = coinbaseTx; + pblocktemplate->vchCoinbaseCommitment = GenerateCoinbaseCommitment(*pblock, pindexPrev, chainparams.GetConsensus()); pblocktemplate->vTxFees[0] = -nFees; // Fill in header @@ -299,6 +309,10 @@ void BlockAssembler::addScoreTxs() continue; } + // cannot accept witness transactions into a non-witness block + if (!fIncludeWitness && !iter->GetTx().wit.IsNull()) + continue; + // If tx is dependent on other mempool txs which haven't yet been included // then put it in the waitSet if (isStillDependent(iter)) { @@ -543,6 +557,10 @@ void BlockAssembler::addPriorityTxs() continue; } + // cannot accept witness transactions into a non-witness block + if (!fIncludeWitness && !iter->GetTx().wit.IsNull()) + continue; + // If tx is dependent on other mempool txs which haven't yet been included // then put it in the waitSet if (isStillDependent(iter)) { diff --git a/src/miner.h b/src/miner.h index a9fea85304aa6..8bfc1493db19b 100644 --- a/src/miner.h +++ b/src/miner.h @@ -29,6 +29,7 @@ struct CBlockTemplate CBlock block; std::vector vTxFees; std::vector vTxSigOps; + std::vector vchCoinbaseCommitment; }; // Container for tracking updates to ancestor feerate as we include (parent) @@ -139,6 +140,7 @@ class BlockAssembler CBlock* pblock; // Configuration parameters for the block size + bool fIncludeWitness; unsigned int nBlockMaxSize, nBlockMinSize; // Information on the current status of the block diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index d8ae41ad78da3..5a58241347b49 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -335,7 +335,6 @@ class CTransaction private: /** Memory only. */ const uint256 hash; - void UpdateHash() const; public: // Default transaction version. @@ -414,6 +413,8 @@ class CTransaction } std::string ToString() const; + + void UpdateHash() const; }; /** A mutable version of CTransaction. */ diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 1bb365d36cdad..dae283fb6fea7 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -930,6 +930,7 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams)); softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams)); bip9_softforks.push_back(Pair("csv", BIP9SoftForkDesc(consensusParams, Consensus::DEPLOYMENT_CSV))); + bip9_softforks.push_back(Pair("segwit", BIP9SoftForkDesc(consensusParams, Consensus::DEPLOYMENT_SEGWIT))); obj.push_back(Pair("softforks", softforks)); obj.push_back(Pair("bip9_softforks", bip9_softforks)); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 94eeea91f39f2..291314b8b57fa 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -348,7 +348,8 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) " \"transactions\" : [ (array) contents of non-coinbase transactions that should be included in the next block\n" " {\n" " \"data\" : \"xxxx\", (string) transaction data encoded in hexadecimal (byte-for-byte)\n" - " \"hash\" : \"xxxx\", (string) hash/id encoded in little-endian hexadecimal\n" + " \"txid\" : \"xxxx\", (string) transaction id encoded in little-endian hexadecimal\n" + " \"hash\" : \"xxxx\", (string) hash encoded in little-endian hexadecimal\n" " \"depends\" : [ (array) array of numbers \n" " n (numeric) transactions before this one (by 1-based index in 'transactions' list) that must be present in the final block if this one is\n" " ,...\n" @@ -546,7 +547,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) UniValue transactions(UniValue::VARR); map setTxIndex; int i = 0; - BOOST_FOREACH (const CTransaction& tx, pblock->vtx) { + BOOST_FOREACH (CTransaction& tx, pblock->vtx) { uint256 txHash = tx.GetHash(); setTxIndex[txHash] = i++; @@ -556,8 +557,8 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) UniValue entry(UniValue::VOBJ); entry.push_back(Pair("data", EncodeHexTx(tx))); - - entry.push_back(Pair("hash", txHash.GetHex())); + entry.push_back(Pair("txid", txHash.GetHex())); + entry.push_back(Pair("hash", tx.GetWitnessHash().GetHex())); UniValue deps(UniValue::VARR); BOOST_FOREACH (const CTxIn &in, tx.vin) @@ -656,6 +657,9 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) result.push_back(Pair("curtime", pblock->GetBlockTime())); result.push_back(Pair("bits", strprintf("%08x", pblock->nBits))); result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1))); + if (!pblocktemplate->vchCoinbaseCommitment.empty()) { + result.push_back(Pair("default_witness_commitment", HexStr(pblocktemplate->vchCoinbaseCommitment.begin(), pblocktemplate->vchCoinbaseCommitment.end()))); + } return result; } @@ -719,6 +723,14 @@ UniValue submitblock(const UniValue& params, bool fHelp) } } + { + LOCK(cs_main); + BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock); + if (mi != mapBlockIndex.end()) { + UpdateUncommittedBlockStructures(block, mi->second, Params().GetConsensus()); + } + } + CValidationState state; submitblock_StateCatcher sc(block.GetHash()); RegisterValidationInterface(&sc); diff --git a/src/versionbits.cpp b/src/versionbits.cpp index 043819c654b23..bf32ae6627945 100644 --- a/src/versionbits.cpp +++ b/src/versionbits.cpp @@ -14,6 +14,10 @@ const struct BIP9DeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION { /*.name =*/ "csv", /*.gbt_force =*/ true, + }, + { + /*.name =*/ "segwit", + /*.gbt_force =*/ false, } }; From b8a97498df1e83f8dcc49bc3fa4344f9e9799242 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 17 Nov 2015 00:20:49 +0100 Subject: [PATCH 0540/1802] BIP144: Handshake and relay (receiver side) Service bit logic by Nicolas Dorier. Only download blocks from witness peers after fork. --- src/init.cpp | 12 ++++++++++++ src/main.cpp | 44 ++++++++++++++++++++++++++++++++++++-------- src/net.cpp | 6 +++++- src/net.h | 1 + src/protocol.h | 3 +++ src/qt/guiutil.cpp | 3 +++ 6 files changed, 60 insertions(+), 9 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index b572bfc32720a..6bce0a9b49b51 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1377,6 +1377,18 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) } } + if (Params().GetConsensus().vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout != 0) { + // Only advertize witness capabilities if they have a reasonable start time. + // This allows us to have the code merged without a defined softfork, by setting its + // end time to 0. + // Note that setting NODE_WITNESS is never required: the only downside from not + // doing so is that after activation, no upgraded nodes will fetch from you. + nLocalServices = ServiceFlags(nLocalServices | NODE_WITNESS); + // Only care about others providing witness capabilities if there is a softfork + // defined. + nRelevantServices = ServiceFlags(nRelevantServices | NODE_WITNESS); + } + // ********************************************************* Step 10: import blocks if (mapArgs.count("-blocknotify")) diff --git a/src/main.cpp b/src/main.cpp index 8d91d6d625b7a..73e4c8f51c48f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -313,6 +313,7 @@ struct CNodeState { fPreferHeaders = false; fPreferHeaderAndIDs = false; fProvidesHeaderAndIDs = false; + fHaveWitness = false; } }; @@ -4812,6 +4813,14 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam } } +uint32_t GetFetchFlags(CNode* pfrom, CBlockIndex* pprev, const Consensus::Params& chainparams) { + uint32_t nFetchFlags = 0; + if (IsWitnessEnabled(pprev, chainparams) && State(pfrom->GetId())->fHaveWitness) { + nFetchFlags |= MSG_WITNESS_FLAG; + } + return nFetchFlags; +} + bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams) { LogPrint("net", "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->id); @@ -4918,6 +4927,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, pfrom->fClient = !(pfrom->nServices & NODE_NETWORK); + if((pfrom->nServices & NODE_WITNESS)) + { + LOCK(cs_main); + State(pfrom->GetId())->fHaveWitness = true; + } + // Potentially mark this peer as a preferred download peer. { LOCK(cs_main); @@ -5119,17 +5134,23 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, LOCK(cs_main); + uint32_t nFetchFlags = GetFetchFlags(pfrom, chainActive.Tip(), chainparams.GetConsensus()); + std::vector vToFetch; for (unsigned int nInv = 0; nInv < vInv.size(); nInv++) { - const CInv &inv = vInv[nInv]; + CInv &inv = vInv[nInv]; boost::this_thread::interruption_point(); bool fAlreadyHave = AlreadyHave(inv); LogPrint("net", "got inv: %s %s peer=%d\n", inv.ToString(), fAlreadyHave ? "have" : "new", pfrom->id); + if (inv.type == MSG_TX) { + inv.type |= nFetchFlags; + } + if (inv.type == MSG_BLOCK) { UpdateBlockAvailability(pfrom->GetId(), inv.hash); if (!fAlreadyHave && !fImporting && !fReindex && !mapBlocksInFlight.count(inv.hash)) { @@ -5144,7 +5165,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, pfrom->PushMessage(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), inv.hash); CNodeState *nodestate = State(pfrom->GetId()); if (CanDirectFetch(chainparams.GetConsensus()) && - nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) { + nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER && + (!IsWitnessEnabled(chainActive.Tip(), chainparams.GetConsensus()) || State(pfrom->GetId())->fHaveWitness)) { + inv.type |= nFetchFlags; if (nodestate->fProvidesHeaderAndIDs) vToFetch.push_back(CInv(MSG_CMPCT_BLOCK, inv.hash)); else @@ -5730,7 +5753,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // Calculate all the blocks we'd need to switch to pindexLast, up to a limit. while (pindexWalk && !chainActive.Contains(pindexWalk) && vToFetch.size() <= MAX_BLOCKS_IN_TRANSIT_PER_PEER) { if (!(pindexWalk->nStatus & BLOCK_HAVE_DATA) && - !mapBlocksInFlight.count(pindexWalk->GetBlockHash())) { + !mapBlocksInFlight.count(pindexWalk->GetBlockHash()) && + (!IsWitnessEnabled(pindexWalk->pprev, chainparams.GetConsensus()) || State(pfrom->GetId())->fHaveWitness)) { // We don't have this block, and it's not yet in flight. vToFetch.push_back(pindexWalk); } @@ -5752,7 +5776,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // Can't download any more from this peer break; } - vGetData.push_back(CInv(MSG_BLOCK, pindex->GetBlockHash())); + uint32_t nFetchFlags = GetFetchFlags(pfrom, pindex->pprev, chainparams.GetConsensus()); + vGetData.push_back(CInv(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash())); MarkBlockAsInFlight(pfrom->GetId(), pindex->GetBlockHash(), chainparams.GetConsensus(), pindex); LogPrint("net", "Requesting block %s from peer=%d\n", pindex->GetBlockHash().ToString(), pfrom->id); @@ -6598,10 +6623,13 @@ bool SendMessages(CNode* pto) NodeId staller = -1; FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller); BOOST_FOREACH(CBlockIndex *pindex, vToDownload) { - vGetData.push_back(CInv(MSG_BLOCK, pindex->GetBlockHash())); - MarkBlockAsInFlight(pto->GetId(), pindex->GetBlockHash(), consensusParams, pindex); - LogPrint("net", "Requesting block %s (%d) peer=%d\n", pindex->GetBlockHash().ToString(), - pindex->nHeight, pto->id); + if (State(pto->GetId())->fHaveWitness || !IsWitnessEnabled(pindex->pprev, consensusParams)) { + uint32_t nFetchFlags = GetFetchFlags(pto, pindex->pprev, consensusParams); + vGetData.push_back(CInv(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash())); + MarkBlockAsInFlight(pto->GetId(), pindex->GetBlockHash(), consensusParams, pindex); + LogPrint("net", "Requesting block %s (%d) peer=%d\n", pindex->GetBlockHash().ToString(), + pindex->nHeight, pto->id); + } } if (state.nBlocksInFlight == 0 && staller != -1) { if (State(staller)->nStallingSince == 0) { diff --git a/src/net.cpp b/src/net.cpp index 336163a89624d..dc83f19be48c8 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -72,7 +72,7 @@ namespace { const static std::string NET_MESSAGE_COMMAND_OTHER = "*other*"; /** Services this node implementation cares about */ -static const ServiceFlags nRelevantServices = NODE_NETWORK; +ServiceFlags nRelevantServices = NODE_NETWORK; // // Global state variables @@ -1676,6 +1676,10 @@ void ThreadOpenConnections() if (nANow - addr.nLastTry < 600 && nTries < 30) continue; + // only consider nodes missing relevant services after 40 failed attemps + if ((addr.nServices & nRelevantServices) != nRelevantServices && nTries < 40) + continue; + // do not allow non-default ports, unless after 50 invalid addresses selected already if (addr.GetPort() != Params().GetDefaultPort() && nTries < 50) continue; diff --git a/src/net.h b/src/net.h index cb35d8c4f28c3..7ed18b2050a38 100644 --- a/src/net.h +++ b/src/net.h @@ -156,6 +156,7 @@ CAddress GetLocalAddress(const CNetAddr *paddrPeer = NULL); extern bool fDiscover; extern bool fListen; extern ServiceFlags nLocalServices; +extern ServiceFlags nRelevantServices; extern bool fRelayTxes; extern uint64_t nLocalHostNonce; extern CAddrMan addrman; diff --git a/src/protocol.h b/src/protocol.h index dd07092f5f8d9..15f27e2d2fbcb 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -264,6 +264,9 @@ enum ServiceFlags : uint64_t { // Bitcoin Core nodes used to support this by default, without advertising this bit, // but no longer do as of protocol version 70011 (= NO_BLOOM_VERSION) NODE_BLOOM = (1 << 2), + // Indicates that a node can be asked for blocks and transactions including + // witness data. + NODE_WITNESS = (1 << 3), // Bits 24-31 are reserved for temporary experiments. Just pick a bit that // isn't getting used, or one not being used much, and notify the diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index ff4320b36a480..4327de9b0c86d 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -909,6 +909,9 @@ QString formatServicesStr(quint64 mask) case NODE_BLOOM: strList.append("BLOOM"); break; + case NODE_WITNESS: + strList.append("WITNESS"); + break; default: strList.append(QString("%1[%2]").arg("UNKNOWN").arg(check)); } From 0ef1dd3e11dd573b6e443852ef0c72e34093ac68 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 31 Mar 2016 14:51:29 +0200 Subject: [PATCH 0541/1802] Refactor script validation to observe amounts This is a preparation for BIP143 support. --- src/bitcoin-tx.cpp | 3 ++- src/main.cpp | 2 +- src/main.h | 6 ++++-- src/rpc/rawtransaction.cpp | 3 ++- src/script/bitcoinconsensus.cpp | 3 ++- src/script/bitcoinconsensus.h | 2 ++ src/script/interpreter.h | 4 ++-- src/script/sigcache.h | 2 +- src/script/sign.cpp | 5 +++-- src/test/multisig_tests.cpp | 17 +++++++++-------- src/test/script_P2SH_tests.cpp | 2 +- src/test/script_tests.cpp | 29 +++++++++++++++-------------- src/test/transaction_tests.cpp | 6 ++++-- 13 files changed, 48 insertions(+), 36 deletions(-) diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 82a5583dda6e5..68c069659baca 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -462,6 +462,7 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) continue; } const CScript& prevPubKey = coins->vout[txin.prevout.n].scriptPubKey; + const CAmount& amount = coins->vout[txin.prevout.n].nValue; txin.scriptSig.clear(); // Only sign SIGHASH_SINGLE if there's a corresponding output: @@ -472,7 +473,7 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) BOOST_FOREACH(const CTransaction& txv, txVariants) { txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig); } - if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx.wit.vtxinwit.size() > i ? &mergedTx.wit.vtxinwit[i].scriptWitness : NULL, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i))) + if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx.wit.vtxinwit.size() > i ? &mergedTx.wit.vtxinwit[i].scriptWitness : NULL, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i, amount))) fComplete = false; } diff --git a/src/main.cpp b/src/main.cpp index 73e4c8f51c48f..c22faf6db6f58 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1885,7 +1885,7 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight) bool CScriptCheck::operator()() { const CScript &scriptSig = ptxTo->vin[nIn].scriptSig; const CScriptWitness *witness = (nIn < ptxTo->wit.vtxinwit.size()) ? &ptxTo->wit.vtxinwit[nIn].scriptWitness : NULL; - if (!VerifyScript(scriptSig, scriptPubKey, witness, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, cacheStore), &error)) { + if (!VerifyScript(scriptSig, scriptPubKey, witness, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, amount, cacheStore), &error)) { return false; } return true; diff --git a/src/main.h b/src/main.h index d0dce7068700c..6dd4b1aa3d0a2 100644 --- a/src/main.h +++ b/src/main.h @@ -394,6 +394,7 @@ class CScriptCheck { private: CScript scriptPubKey; + CAmount amount; const CTransaction *ptxTo; unsigned int nIn; unsigned int nFlags; @@ -401,9 +402,9 @@ class CScriptCheck ScriptError error; public: - CScriptCheck(): ptxTo(0), nIn(0), nFlags(0), cacheStore(false), error(SCRIPT_ERR_UNKNOWN_ERROR) {} + CScriptCheck(): amount(0), ptxTo(0), nIn(0), nFlags(0), cacheStore(false), error(SCRIPT_ERR_UNKNOWN_ERROR) {} CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn) : - scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey), + scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey), amount(txFromIn.vout[txToIn.vin[nInIn].prevout.n].nValue), ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR) { } bool operator()(); @@ -411,6 +412,7 @@ class CScriptCheck void swap(CScriptCheck &check) { scriptPubKey.swap(check.scriptPubKey); std::swap(ptxTo, check.ptxTo); + std::swap(amount, check.amount); std::swap(nIn, check.nIn); std::swap(nFlags, check.nFlags); std::swap(cacheStore, check.cacheStore); diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 17c9a84602e35..ebfc828d4585b 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -778,6 +778,7 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp) continue; } const CScript& prevPubKey = coins->vout[txin.prevout.n].scriptPubKey; + const CAmount& amount = coins->vout[txin.prevout.n].nValue; txin.scriptSig.clear(); // Only sign SIGHASH_SINGLE if there's a corresponding output: @@ -789,7 +790,7 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp) txin.scriptSig = CombineSignatures(prevPubKey, txConst, i, txin.scriptSig, txv.vin[i].scriptSig); } ScriptError serror = SCRIPT_ERR_OK; - if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx.wit.vtxinwit.size() > i ? &mergedTx.wit.vtxinwit[i].scriptWitness : NULL, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i), &serror)) { + if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx.wit.vtxinwit.size() > i ? &mergedTx.wit.vtxinwit[i].scriptWitness : NULL, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount), &serror)) { TxInErrorToJSON(txin, vErrors, ScriptErrorString(serror)); } } diff --git a/src/script/bitcoinconsensus.cpp b/src/script/bitcoinconsensus.cpp index 5c9e7c0a571a5..26e7a85b7b722 100644 --- a/src/script/bitcoinconsensus.cpp +++ b/src/script/bitcoinconsensus.cpp @@ -85,7 +85,8 @@ int bitcoinconsensus_verify_script(const unsigned char *scriptPubKey, unsigned i // Regardless of the verification result, the tx did not error. set_error(err, bitcoinconsensus_ERR_OK); - return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), nIn < tx.wit.vtxinwit.size() ? &tx.wit.vtxinwit[nIn].scriptWitness : NULL, flags, TransactionSignatureChecker(&tx, nIn), NULL); + CAmount am(0); + return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), nIn < tx.wit.vtxinwit.size() ? &tx.wit.vtxinwit[nIn].scriptWitness : NULL, flags, TransactionSignatureChecker(&tx, nIn, am), NULL); } catch (const std::exception&) { return set_error(err, bitcoinconsensus_ERR_TX_DESERIALIZE); // Error deserializing } diff --git a/src/script/bitcoinconsensus.h b/src/script/bitcoinconsensus.h index 5b8c33c6bf42e..cd3e2f773177b 100644 --- a/src/script/bitcoinconsensus.h +++ b/src/script/bitcoinconsensus.h @@ -6,6 +6,8 @@ #ifndef BITCOIN_BITCOINCONSENSUS_H #define BITCOIN_BITCOINCONSENSUS_H +#include + #if defined(BUILD_BITCOIN_INTERNAL) && defined(HAVE_CONFIG_H) #include "config/bitcoin-config.h" #if defined(_WIN32) diff --git a/src/script/interpreter.h b/src/script/interpreter.h index d1459ed620f6b..6f13e75d78f62 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -131,7 +131,7 @@ class TransactionSignatureChecker : public BaseSignatureChecker virtual bool VerifySignature(const std::vector& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const; public: - TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn) : txTo(txToIn), nIn(nInIn) {} + TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amount) : txTo(txToIn), nIn(nInIn) {} bool CheckSig(const std::vector& scriptSig, const std::vector& vchPubKey, const CScript& scriptCode) const; bool CheckLockTime(const CScriptNum& nLockTime) const; bool CheckSequence(const CScriptNum& nSequence) const; @@ -143,7 +143,7 @@ class MutableTransactionSignatureChecker : public TransactionSignatureChecker const CTransaction txTo; public: - MutableTransactionSignatureChecker(const CMutableTransaction* txToIn, unsigned int nInIn) : TransactionSignatureChecker(&txTo, nInIn), txTo(*txToIn) {} + MutableTransactionSignatureChecker(const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amount) : TransactionSignatureChecker(&txTo, nInIn, amount), txTo(*txToIn) {} }; bool EvalScript(std::vector >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* error = NULL); diff --git a/src/script/sigcache.h b/src/script/sigcache.h index be1df09c2ade2..050bf8cc42290 100644 --- a/src/script/sigcache.h +++ b/src/script/sigcache.h @@ -22,7 +22,7 @@ class CachingTransactionSignatureChecker : public TransactionSignatureChecker bool store; public: - CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, bool storeIn=true) : TransactionSignatureChecker(txToIn, nInIn), store(storeIn) {} + CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amount, bool storeIn) : TransactionSignatureChecker(txToIn, nInIn, amount), store(storeIn) {} bool VerifySignature(const std::vector& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const; }; diff --git a/src/script/sign.cpp b/src/script/sign.cpp index 37b702de17cb6..62d874eed4584 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -18,7 +18,8 @@ using namespace std; typedef std::vector valtype; -TransactionSignatureCreator::TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, int nHashTypeIn) : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), checker(txTo, nIn) {} +static const CAmount amountZero = 0; +TransactionSignatureCreator::TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, int nHashTypeIn) : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), checker(txTo, nIn, amountZero) {} bool TransactionSignatureCreator::CreateSig(std::vector& vchSig, const CKeyID& address, const CScript& scriptCode) const { @@ -258,7 +259,7 @@ static CScript CombineSignatures(const CScript& scriptPubKey, const BaseSignatur CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, const CScript& scriptSig1, const CScript& scriptSig2) { - TransactionSignatureChecker checker(&txTo, nIn); + TransactionSignatureChecker checker(&txTo, nIn, amountZero); return CombineSignatures(scriptPubKey, checker, scriptSig1, scriptSig2); } diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp index a6435d94d3ad4..8c95601ea1a08 100644 --- a/src/test/multisig_tests.cpp +++ b/src/test/multisig_tests.cpp @@ -46,6 +46,7 @@ BOOST_AUTO_TEST_CASE(multisig_verify) ScriptError err; CKey key[4]; + CAmount amount = 0; for (int i = 0; i < 4; i++) key[i].MakeNewKey(true); @@ -81,20 +82,20 @@ BOOST_AUTO_TEST_CASE(multisig_verify) keys.assign(1,key[0]); keys.push_back(key[1]); s = sign_multisig(a_and_b, keys, txTo[0], 0); - BOOST_CHECK(VerifyScript(s, a_and_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[0], 0), &err)); + BOOST_CHECK(VerifyScript(s, a_and_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); for (int i = 0; i < 4; i++) { keys.assign(1,key[i]); s = sign_multisig(a_and_b, keys, txTo[0], 0); - BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[0], 0), &err), strprintf("a&b 1: %d", i)); + BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err), strprintf("a&b 1: %d", i)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err)); keys.assign(1,key[1]); keys.push_back(key[i]); s = sign_multisig(a_and_b, keys, txTo[0], 0); - BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[0], 0), &err), strprintf("a&b 2: %d", i)); + BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err), strprintf("a&b 2: %d", i)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); } @@ -105,18 +106,18 @@ BOOST_AUTO_TEST_CASE(multisig_verify) s = sign_multisig(a_or_b, keys, txTo[1], 0); if (i == 0 || i == 1) { - BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[1], 0), &err), strprintf("a|b: %d", i)); + BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), &err), strprintf("a|b: %d", i)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); } else { - BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[1], 0), &err), strprintf("a|b: %d", i)); + BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), &err), strprintf("a|b: %d", i)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); } } s.clear(); s << OP_0 << OP_1; - BOOST_CHECK(!VerifyScript(s, a_or_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[1], 0), &err)); + BOOST_CHECK(!VerifyScript(s, a_or_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_SIG_DER, ScriptErrorString(err)); @@ -128,12 +129,12 @@ BOOST_AUTO_TEST_CASE(multisig_verify) s = sign_multisig(escrow, keys, txTo[2], 0); if (i < j && i < 3 && j < 3) { - BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, NULL, flags, MutableTransactionSignatureChecker(&txTo[2], 0), &err), strprintf("escrow 1: %d %d", i, j)); + BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, NULL, flags, MutableTransactionSignatureChecker(&txTo[2], 0, amount), &err), strprintf("escrow 1: %d %d", i, j)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); } else { - BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, NULL, flags, MutableTransactionSignatureChecker(&txTo[2], 0), &err), strprintf("escrow 2: %d %d", i, j)); + BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, NULL, flags, MutableTransactionSignatureChecker(&txTo[2], 0, amount), &err), strprintf("escrow 2: %d %d", i, j)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); } } diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp index d6b5f41d44ac5..62deb736aad22 100644 --- a/src/test/script_P2SH_tests.cpp +++ b/src/test/script_P2SH_tests.cpp @@ -42,7 +42,7 @@ Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict, Scri txTo.vin[0].scriptSig = scriptSig; txTo.vout[0].nValue = 1; - return VerifyScript(scriptSig, scriptPubKey, NULL, fStrict ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE, MutableTransactionSignatureChecker(&txTo, 0), &err); + return VerifyScript(scriptSig, scriptPubKey, NULL, fStrict ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE, MutableTransactionSignatureChecker(&txTo, 0, txFrom.vout[0].nValue), &err); } diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index d402ba56bbbf6..9587fecfdf471 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -154,7 +154,8 @@ void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, int flags, co ScriptError err; CMutableTransaction tx = BuildSpendingTransaction(scriptSig, BuildCreditingTransaction(scriptPubKey)); CMutableTransaction tx2 = tx; - BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, NULL, flags, MutableTransactionSignatureChecker(&tx, 0), &err) == expect, message); + static const CAmount amountZero = 0; + BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, NULL, flags, MutableTransactionSignatureChecker(&tx, 0, amountZero), &err) == expect, message); BOOST_CHECK_MESSAGE(err == scriptError, std::string(FormatScriptError(err)) + " where " + std::string(FormatScriptError((ScriptError_t)scriptError)) + " expected: " + message); #if defined(HAVE_CONSENSUS_LIB) CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); @@ -803,18 +804,18 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12) CMutableTransaction txTo12 = BuildSpendingTransaction(CScript(), txFrom12); CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12); - BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, NULL, flags, MutableTransactionSignatureChecker(&txTo12, 0), &err)); + BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, NULL, flags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); txTo12.vout[0].nValue = 2; - BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, NULL, flags, MutableTransactionSignatureChecker(&txTo12, 0), &err)); + BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, NULL, flags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); CScript goodsig2 = sign_multisig(scriptPubKey12, key2, txTo12); - BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, NULL, flags, MutableTransactionSignatureChecker(&txTo12, 0), &err)); + BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, NULL, flags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); CScript badsig1 = sign_multisig(scriptPubKey12, key3, txTo12); - BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, NULL, flags, MutableTransactionSignatureChecker(&txTo12, 0), &err)); + BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, NULL, flags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); } @@ -836,54 +837,54 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23) std::vector keys; keys.push_back(key1); keys.push_back(key2); CScript goodsig1 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); + BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); keys.clear(); keys.push_back(key1); keys.push_back(key3); CScript goodsig2 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); + BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); keys.clear(); keys.push_back(key2); keys.push_back(key3); CScript goodsig3 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); + BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); keys.clear(); keys.push_back(key2); keys.push_back(key2); // Can't re-use sig CScript badsig1 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); + BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); keys.clear(); keys.push_back(key2); keys.push_back(key1); // sigs must be in correct order CScript badsig2 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); + BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); keys.clear(); keys.push_back(key3); keys.push_back(key2); // sigs must be in correct order CScript badsig3 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); + BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); keys.clear(); keys.push_back(key4); keys.push_back(key2); // sigs must match pubkeys CScript badsig4 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); + BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); keys.clear(); keys.push_back(key1); keys.push_back(key4); // sigs must match pubkeys CScript badsig5 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); + BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); keys.clear(); // Must have signatures CScript badsig6 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); + BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, NULL, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err)); } diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 9a24a613e5164..9fb23d8edfab7 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -149,9 +149,10 @@ BOOST_AUTO_TEST_CASE(tx_valid) break; } + CAmount amount = 0; unsigned int verify_flags = ParseScriptFlags(test[2].get_str()); BOOST_CHECK_MESSAGE(VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], - NULL, verify_flags, TransactionSignatureChecker(&tx, i), &err), + NULL, verify_flags, TransactionSignatureChecker(&tx, i, amount), &err), strTest); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); } @@ -224,8 +225,9 @@ BOOST_AUTO_TEST_CASE(tx_invalid) } unsigned int verify_flags = ParseScriptFlags(test[2].get_str()); + CAmount amount = 0; fValid = VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], - NULL, verify_flags, TransactionSignatureChecker(&tx, i), &err); + NULL, verify_flags, TransactionSignatureChecker(&tx, i, amount), &err); } BOOST_CHECK_MESSAGE(!fValid, strTest); BOOST_CHECK_MESSAGE(err != SCRIPT_ERR_OK, ScriptErrorString(err)); From 3dd410294d42f251e4808ef1dfcfcd64817edbac Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 27 Dec 2015 19:49:08 +0100 Subject: [PATCH 0542/1802] BIP143: Verification logic Includes simplifications by Eric Lombrozo. --- src/bitcoin-tx.cpp | 2 +- src/policy/policy.cpp | 2 +- src/rpc/rawtransaction.cpp | 2 +- src/script/interpreter.cpp | 84 ++++++++++++++++++++++++---- src/script/interpreter.h | 17 ++++-- src/script/sign.cpp | 17 +++--- src/script/sign.h | 5 +- src/test/multisig_tests.cpp | 2 +- src/test/script_tests.cpp | 57 +++++++++---------- src/test/sighash_tests.cpp | 4 +- src/test/txvalidationcache_tests.cpp | 2 +- 11 files changed, 131 insertions(+), 63 deletions(-) diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 68c069659baca..424812a6dfbc5 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -471,7 +471,7 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) // ... and merge in other signatures: BOOST_FOREACH(const CTransaction& txv, txVariants) { - txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig); + txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, amount, txin.scriptSig, txv.vin[i].scriptSig); } if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx.wit.vtxinwit.size() > i ? &mergedTx.wit.vtxinwit[i].scriptWitness : NULL, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i, amount))) fComplete = false; diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index d1a15451dc1f6..67434a38fa3c1 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -137,7 +137,7 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs) { std::vector > stack; // convert the scriptSig into a stack, so we can inspect the redeemScript - if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), 0)) + if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), SIGVERSION_BASE)) return false; if (stack.empty()) return false; diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index ebfc828d4585b..38fd98055c42f 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -787,7 +787,7 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp) // ... and merge in other signatures: BOOST_FOREACH(const CMutableTransaction& txv, txVariants) { - txin.scriptSig = CombineSignatures(prevPubKey, txConst, i, txin.scriptSig, txv.vin[i].scriptSig); + txin.scriptSig = CombineSignatures(prevPubKey, txConst, i, amount, txin.scriptSig, txv.vin[i].scriptSig); } ScriptError serror = SCRIPT_ERR_OK; if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx.wit.vtxinwit.size() > i ? &mergedTx.wit.vtxinwit[i].scriptWitness : NULL, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount), &serror)) { diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index be649fca20d3d..4deebd050d45e 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -229,7 +229,7 @@ bool static CheckMinimalPush(const valtype& data, opcodetype opcode) { return true; } -bool EvalScript(vector >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror) +bool EvalScript(vector >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror) { static const CScriptNum bnZero(0); static const CScriptNum bnOne(1); @@ -869,13 +869,15 @@ bool EvalScript(vector >& stack, const CScript& script, un CScript scriptCode(pbegincodehash, pend); // Drop the signature, since there's no way for a signature to sign itself - scriptCode.FindAndDelete(CScript(vchSig)); + if (sigversion == SIGVERSION_BASE) { + scriptCode.FindAndDelete(CScript(vchSig)); + } if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, serror)) { //serror is set return false; } - bool fSuccess = checker.CheckSig(vchSig, vchPubKey, scriptCode); + bool fSuccess = checker.CheckSig(vchSig, vchPubKey, scriptCode, sigversion); popstack(stack); popstack(stack); @@ -925,7 +927,9 @@ bool EvalScript(vector >& stack, const CScript& script, un for (int k = 0; k < nSigsCount; k++) { valtype& vchSig = stacktop(-isig-k); - scriptCode.FindAndDelete(CScript(vchSig)); + if (sigversion == SIGVERSION_BASE) { + scriptCode.FindAndDelete(CScript(vchSig)); + } } bool fSuccess = true; @@ -943,7 +947,7 @@ bool EvalScript(vector >& stack, const CScript& script, un } // Check signature - bool fOk = checker.CheckSig(vchSig, vchPubKey, scriptCode); + bool fOk = checker.CheckSig(vchSig, vchPubKey, scriptCode, sigversion); if (fOk) { isig++; @@ -1106,8 +1110,64 @@ class CTransactionSignatureSerializer { } // anon namespace -uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType) +uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion) { + if (sigversion == SIGVERSION_WITNESS_V0) { + uint256 hashPrevouts; + uint256 hashSequence; + uint256 hashOutputs; + + if (!(nHashType & SIGHASH_ANYONECANPAY)) { + CHashWriter ss(SER_GETHASH, 0); + for (unsigned int n = 0; n < txTo.vin.size(); n++) { + ss << txTo.vin[n].prevout; + } + hashPrevouts = ss.GetHash(); // TODO: cache this value for all signatures in a transaction + } + + if (!(nHashType & SIGHASH_ANYONECANPAY) && (nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) { + CHashWriter ss(SER_GETHASH, 0); + for (unsigned int n = 0; n < txTo.vin.size(); n++) { + ss << txTo.vin[n].nSequence; + } + hashSequence = ss.GetHash(); // TODO: cache this value for all signatures in a transaction + } + + if ((nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) { + CHashWriter ss(SER_GETHASH, 0); + for (unsigned int n = 0; n < txTo.vout.size(); n++) { + ss << txTo.vout[n]; + } + hashOutputs = ss.GetHash(); // TODO: cache this value for all signatures in a transaction + } else if ((nHashType & 0x1f) == SIGHASH_SINGLE && nIn < txTo.vout.size()) { + CHashWriter ss(SER_GETHASH, 0); + ss << txTo.vout[nIn]; + hashOutputs = ss.GetHash(); + } + + CHashWriter ss(SER_GETHASH, 0); + // Version + ss << txTo.nVersion; + // Input prevouts/nSequence (none/all, depending on flags) + ss << hashPrevouts; + ss << hashSequence; + // The input being signed (replacing the scriptSig with scriptCode + amount) + // The prevout may already be contained in hashPrevout, and the nSequence + // may already be contain in hashSequence. + ss << txTo.vin[nIn].prevout; + ss << static_cast(scriptCode); + ss << amount; + ss << txTo.vin[nIn].nSequence; + // Outputs (none/one/all, depending on flags) + ss << hashOutputs; + // Locktime + ss << txTo.nLockTime; + // Sighash type + ss << nHashType; + + return ss.GetHash(); + } + static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001")); if (nIn >= txTo.vin.size()) { // nIn out of range @@ -1136,7 +1196,7 @@ bool TransactionSignatureChecker::VerifySignature(const std::vector& vchSigIn, const vector& vchPubKey, const CScript& scriptCode) const +bool TransactionSignatureChecker::CheckSig(const vector& vchSigIn, const vector& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const { CPubKey pubkey(vchPubKey); if (!pubkey.IsValid()) @@ -1149,7 +1209,7 @@ bool TransactionSignatureChecker::CheckSig(const vector& vchSigIn int nHashType = vchSig.back(); vchSig.pop_back(); - uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType); + uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion); if (!VerifySignature(vchSig, pubkey, sighash)) return false; @@ -1280,7 +1340,7 @@ static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion, return set_error(serror, SCRIPT_ERR_PUSH_SIZE); } - if (!EvalScript(stack, scriptPubKey, flags, checker, serror)) { + if (!EvalScript(stack, scriptPubKey, flags, checker, SIGVERSION_WITNESS_V0, serror)) { return false; } @@ -1307,12 +1367,12 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const C } vector > stack, stackCopy; - if (!EvalScript(stack, scriptSig, flags, checker, serror)) + if (!EvalScript(stack, scriptSig, flags, checker, SIGVERSION_BASE, serror)) // serror is set return false; if (flags & SCRIPT_VERIFY_P2SH) stackCopy = stack; - if (!EvalScript(stack, scriptPubKey, flags, checker, serror)) + if (!EvalScript(stack, scriptPubKey, flags, checker, SIGVERSION_BASE, serror)) // serror is set return false; if (stack.empty()) @@ -1358,7 +1418,7 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const C CScript pubKey2(pubKeySerialized.begin(), pubKeySerialized.end()); popstack(stack); - if (!EvalScript(stack, pubKey2, flags, checker, serror)) + if (!EvalScript(stack, pubKey2, flags, checker, SIGVERSION_BASE, serror)) // serror is set return false; if (stack.empty()) diff --git a/src/script/interpreter.h b/src/script/interpreter.h index 6f13e75d78f62..86437294253e9 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -98,12 +98,18 @@ enum bool CheckSignatureEncoding(const std::vector &vchSig, unsigned int flags, ScriptError* serror); -uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType); +enum SigVersion +{ + SIGVERSION_BASE = 0, + SIGVERSION_WITNESS_V0 = 1, +}; + +uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion); class BaseSignatureChecker { public: - virtual bool CheckSig(const std::vector& scriptSig, const std::vector& vchPubKey, const CScript& scriptCode) const + virtual bool CheckSig(const std::vector& scriptSig, const std::vector& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const { return false; } @@ -126,13 +132,14 @@ class TransactionSignatureChecker : public BaseSignatureChecker private: const CTransaction* txTo; unsigned int nIn; + const CAmount amount; protected: virtual bool VerifySignature(const std::vector& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const; public: - TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amount) : txTo(txToIn), nIn(nInIn) {} - bool CheckSig(const std::vector& scriptSig, const std::vector& vchPubKey, const CScript& scriptCode) const; + TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn) : txTo(txToIn), nIn(nInIn), amount(amountIn) {} + bool CheckSig(const std::vector& scriptSig, const std::vector& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const; bool CheckLockTime(const CScriptNum& nLockTime) const; bool CheckSequence(const CScriptNum& nSequence) const; }; @@ -146,7 +153,7 @@ class MutableTransactionSignatureChecker : public TransactionSignatureChecker MutableTransactionSignatureChecker(const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amount) : TransactionSignatureChecker(&txTo, nInIn, amount), txTo(*txToIn) {} }; -bool EvalScript(std::vector >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* error = NULL); +bool EvalScript(std::vector >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* error = NULL); bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror = NULL); #endif // BITCOIN_SCRIPT_INTERPRETER_H diff --git a/src/script/sign.cpp b/src/script/sign.cpp index 62d874eed4584..83bb0cfa29f58 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -18,8 +18,7 @@ using namespace std; typedef std::vector valtype; -static const CAmount amountZero = 0; -TransactionSignatureCreator::TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, int nHashTypeIn) : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), checker(txTo, nIn, amountZero) {} +TransactionSignatureCreator::TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn) : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), amount(amountIn), checker(txTo, nIn, amountIn) {} bool TransactionSignatureCreator::CreateSig(std::vector& vchSig, const CKeyID& address, const CScript& scriptCode) const { @@ -27,7 +26,7 @@ bool TransactionSignatureCreator::CreateSig(std::vector& vchSig, if (!keystore->GetKey(address, key)) return false; - uint256 hash = SignatureHash(scriptCode, *txTo, nIn, nHashType); + uint256 hash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, SIGVERSION_BASE); if (!key.Sign(hash, vchSig)) return false; vchSig.push_back((unsigned char)nHashType); @@ -186,7 +185,7 @@ static CScript CombineMultisig(const CScript& scriptPubKey, const BaseSignatureC if (sigs.count(pubkey)) continue; // Already got a sig for this pubkey - if (checker.CheckSig(sig, pubkey, scriptPubKey)) + if (checker.CheckSig(sig, pubkey, scriptPubKey, SIGVERSION_BASE)) { sigs[pubkey] = sig; break; @@ -256,10 +255,10 @@ static CScript CombineSignatures(const CScript& scriptPubKey, const BaseSignatur return CScript(); } -CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, +CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, const CAmount& amount, const CScript& scriptSig1, const CScript& scriptSig2) { - TransactionSignatureChecker checker(&txTo, nIn, amountZero); + TransactionSignatureChecker checker(&txTo, nIn, amount); return CombineSignatures(scriptPubKey, checker, scriptSig1, scriptSig2); } @@ -271,9 +270,9 @@ CScript CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecke Solver(scriptPubKey, txType, vSolutions); vector stack1; - EvalScript(stack1, scriptSig1, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker()); + EvalScript(stack1, scriptSig1, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), SIGVERSION_BASE); vector stack2; - EvalScript(stack2, scriptSig2, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker()); + EvalScript(stack2, scriptSig2, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), SIGVERSION_BASE); return CombineSignatures(scriptPubKey, checker, txType, vSolutions, stack1, stack2); } @@ -285,7 +284,7 @@ class DummySignatureChecker : public BaseSignatureChecker public: DummySignatureChecker() {} - bool CheckSig(const std::vector& scriptSig, const std::vector& vchPubKey, const CScript& scriptCode) const + bool CheckSig(const std::vector& scriptSig, const std::vector& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const { return true; } diff --git a/src/script/sign.h b/src/script/sign.h index 47a9cde7f4304..f54511f7a67f5 100644 --- a/src/script/sign.h +++ b/src/script/sign.h @@ -35,10 +35,11 @@ class TransactionSignatureCreator : public BaseSignatureCreator { const CTransaction* txTo; unsigned int nIn; int nHashType; + CAmount amount; const TransactionSignatureChecker checker; public: - TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, int nHashTypeIn=SIGHASH_ALL); + TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn=SIGHASH_ALL); const BaseSignatureChecker& Checker() const { return checker; } bool CreateSig(std::vector& vchSig, const CKeyID& keyid, const CScript& scriptCode) const; }; @@ -62,6 +63,6 @@ bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CMutab CScript CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker, const CScript& scriptSig1, const CScript& scriptSig2); /** Combine two script signatures on transactions. */ -CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, const CScript& scriptSig1, const CScript& scriptSig2); +CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, const CAmount& amount, const CScript& scriptSig1, const CScript& scriptSig2); #endif // BITCOIN_SCRIPT_SIGN_H diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp index 8c95601ea1a08..876b90e4b99ed 100644 --- a/src/test/multisig_tests.cpp +++ b/src/test/multisig_tests.cpp @@ -26,7 +26,7 @@ BOOST_FIXTURE_TEST_SUITE(multisig_tests, BasicTestingSetup) CScript sign_multisig(CScript scriptPubKey, vector keys, CTransaction transaction, int whichIn) { - uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL); + uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL, 0, SIGVERSION_BASE); CScript result; result << OP_0; // CHECKMULTISIG bug workaround diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 9587fecfdf471..c56b9da4e5ab5 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -306,7 +306,7 @@ class TestBuilder TestBuilder& PushSig(const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32) { - uint256 hash = SignatureHash(scriptPubKey, spendTx, 0, nHashType); + uint256 hash = SignatureHash(scriptPubKey, spendTx, 0, nHashType, 0, SIGVERSION_BASE); std::vector vchSig, r, s; uint32_t iter = 0; do { @@ -738,21 +738,21 @@ BOOST_AUTO_TEST_CASE(script_PushData) ScriptError err; vector > directStack; - BOOST_CHECK(EvalScript(directStack, CScript(&direct[0], &direct[sizeof(direct)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), &err)); + BOOST_CHECK(EvalScript(directStack, CScript(&direct[0], &direct[sizeof(direct)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SIGVERSION_BASE, &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); vector > pushdata1Stack; - BOOST_CHECK(EvalScript(pushdata1Stack, CScript(&pushdata1[0], &pushdata1[sizeof(pushdata1)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), &err)); + BOOST_CHECK(EvalScript(pushdata1Stack, CScript(&pushdata1[0], &pushdata1[sizeof(pushdata1)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SIGVERSION_BASE, &err)); BOOST_CHECK(pushdata1Stack == directStack); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); vector > pushdata2Stack; - BOOST_CHECK(EvalScript(pushdata2Stack, CScript(&pushdata2[0], &pushdata2[sizeof(pushdata2)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), &err)); + BOOST_CHECK(EvalScript(pushdata2Stack, CScript(&pushdata2[0], &pushdata2[sizeof(pushdata2)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SIGVERSION_BASE, &err)); BOOST_CHECK(pushdata2Stack == directStack); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); vector > pushdata4Stack; - BOOST_CHECK(EvalScript(pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), &err)); + BOOST_CHECK(EvalScript(pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SIGVERSION_BASE, &err)); BOOST_CHECK(pushdata4Stack == directStack); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); } @@ -760,7 +760,7 @@ BOOST_AUTO_TEST_CASE(script_PushData) CScript sign_multisig(CScript scriptPubKey, std::vector keys, CTransaction transaction) { - uint256 hash = SignatureHash(scriptPubKey, transaction, 0, SIGHASH_ALL); + uint256 hash = SignatureHash(scriptPubKey, transaction, 0, SIGHASH_ALL, 0, SIGVERSION_BASE); CScript result; // @@ -891,6 +891,7 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23) BOOST_AUTO_TEST_CASE(script_combineSigs) { // Test the CombineSignatures function + CAmount amount; CBasicKeyStore keystore; vector keys; vector pubkeys; @@ -909,19 +910,19 @@ BOOST_AUTO_TEST_CASE(script_combineSigs) CScript& scriptSig = txTo.vin[0].scriptSig; CScript empty; - CScript combined = CombineSignatures(scriptPubKey, txTo, 0, empty, empty); + CScript combined = CombineSignatures(scriptPubKey, txTo, 0, amount, empty, empty); BOOST_CHECK(combined.empty()); // Single signature case: SignSignature(keystore, txFrom, txTo, 0); // changes scriptSig - combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty); + combined = CombineSignatures(scriptPubKey, txTo, 0, amount, scriptSig, empty); BOOST_CHECK(combined == scriptSig); - combined = CombineSignatures(scriptPubKey, txTo, 0, empty, scriptSig); + combined = CombineSignatures(scriptPubKey, txTo, 0, amount, empty, scriptSig); BOOST_CHECK(combined == scriptSig); CScript scriptSigCopy = scriptSig; // Signing again will give a different, valid signature: SignSignature(keystore, txFrom, txTo, 0); - combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSigCopy, scriptSig); + combined = CombineSignatures(scriptPubKey, txTo, 0, amount, scriptSigCopy, scriptSig); BOOST_CHECK(combined == scriptSigCopy || combined == scriptSig); // P2SH, single-signature case: @@ -929,41 +930,41 @@ BOOST_AUTO_TEST_CASE(script_combineSigs) keystore.AddCScript(pkSingle); scriptPubKey = GetScriptForDestination(CScriptID(pkSingle)); SignSignature(keystore, txFrom, txTo, 0); - combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty); + combined = CombineSignatures(scriptPubKey, txTo, 0, amount, scriptSig, empty); BOOST_CHECK(combined == scriptSig); - combined = CombineSignatures(scriptPubKey, txTo, 0, empty, scriptSig); + combined = CombineSignatures(scriptPubKey, txTo, 0, amount, empty, scriptSig); BOOST_CHECK(combined == scriptSig); scriptSigCopy = scriptSig; SignSignature(keystore, txFrom, txTo, 0); - combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSigCopy, scriptSig); + combined = CombineSignatures(scriptPubKey, txTo, 0, amount, scriptSigCopy, scriptSig); BOOST_CHECK(combined == scriptSigCopy || combined == scriptSig); // dummy scriptSigCopy with placeholder, should always choose non-placeholder: scriptSigCopy = CScript() << OP_0 << vector(pkSingle.begin(), pkSingle.end()); - combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSigCopy, scriptSig); + combined = CombineSignatures(scriptPubKey, txTo, 0, amount, scriptSigCopy, scriptSig); BOOST_CHECK(combined == scriptSig); - combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, scriptSigCopy); + combined = CombineSignatures(scriptPubKey, txTo, 0, amount, scriptSig, scriptSigCopy); BOOST_CHECK(combined == scriptSig); // Hardest case: Multisig 2-of-3 scriptPubKey = GetScriptForMultisig(2, pubkeys); keystore.AddCScript(scriptPubKey); SignSignature(keystore, txFrom, txTo, 0); - combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty); + combined = CombineSignatures(scriptPubKey, txTo, 0, amount, scriptSig, empty); BOOST_CHECK(combined == scriptSig); - combined = CombineSignatures(scriptPubKey, txTo, 0, empty, scriptSig); + combined = CombineSignatures(scriptPubKey, txTo, 0, amount, empty, scriptSig); BOOST_CHECK(combined == scriptSig); // A couple of partially-signed versions: vector sig1; - uint256 hash1 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_ALL); + uint256 hash1 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_ALL, 0, SIGVERSION_BASE); BOOST_CHECK(keys[0].Sign(hash1, sig1)); sig1.push_back(SIGHASH_ALL); vector sig2; - uint256 hash2 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_NONE); + uint256 hash2 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_NONE, 0, SIGVERSION_BASE); BOOST_CHECK(keys[1].Sign(hash2, sig2)); sig2.push_back(SIGHASH_NONE); vector sig3; - uint256 hash3 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_SINGLE); + uint256 hash3 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_SINGLE, 0, SIGVERSION_BASE); BOOST_CHECK(keys[2].Sign(hash3, sig3)); sig3.push_back(SIGHASH_SINGLE); @@ -979,21 +980,21 @@ BOOST_AUTO_TEST_CASE(script_combineSigs) CScript complete13 = CScript() << OP_0 << sig1 << sig3; CScript complete23 = CScript() << OP_0 << sig2 << sig3; - combined = CombineSignatures(scriptPubKey, txTo, 0, partial1a, partial1b); + combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial1a, partial1b); BOOST_CHECK(combined == partial1a); - combined = CombineSignatures(scriptPubKey, txTo, 0, partial1a, partial2a); + combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial1a, partial2a); BOOST_CHECK(combined == complete12); - combined = CombineSignatures(scriptPubKey, txTo, 0, partial2a, partial1a); + combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial2a, partial1a); BOOST_CHECK(combined == complete12); - combined = CombineSignatures(scriptPubKey, txTo, 0, partial1b, partial2b); + combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial1b, partial2b); BOOST_CHECK(combined == complete12); - combined = CombineSignatures(scriptPubKey, txTo, 0, partial3b, partial1b); + combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial3b, partial1b); BOOST_CHECK(combined == complete13); - combined = CombineSignatures(scriptPubKey, txTo, 0, partial2a, partial3a); + combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial2a, partial3a); BOOST_CHECK(combined == complete23); - combined = CombineSignatures(scriptPubKey, txTo, 0, partial3b, partial2b); + combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial3b, partial2b); BOOST_CHECK(combined == complete23); - combined = CombineSignatures(scriptPubKey, txTo, 0, partial3b, partial3a); + combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial3b, partial3a); BOOST_CHECK(combined == partial3c); } diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index 375accbac7206..4a48347b702dd 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -143,7 +143,7 @@ BOOST_AUTO_TEST_CASE(sighash_test) uint256 sh, sho; sho = SignatureHashOld(scriptCode, txTo, nIn, nHashType); - sh = SignatureHash(scriptCode, txTo, nIn, nHashType); + sh = SignatureHash(scriptCode, txTo, nIn, nHashType, 0, SIGVERSION_BASE); #if defined(PRINT_SIGHASH_JSON) CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss << txTo; @@ -209,7 +209,7 @@ BOOST_AUTO_TEST_CASE(sighash_from_data) continue; } - sh = SignatureHash(scriptCode, tx, nIn, nHashType); + sh = SignatureHash(scriptCode, tx, nIn, nHashType, 0, SIGVERSION_BASE); BOOST_CHECK_MESSAGE(sh.GetHex() == sigHashHex, strTest); } } diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp index c29e30792a2a9..76e4e7a4be865 100644 --- a/src/test/txvalidationcache_tests.cpp +++ b/src/test/txvalidationcache_tests.cpp @@ -48,7 +48,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup) // Sign: std::vector vchSig; - uint256 hash = SignatureHash(scriptPubKey, spends[i], 0, SIGHASH_ALL); + uint256 hash = SignatureHash(scriptPubKey, spends[i], 0, SIGHASH_ALL, 0, SIGVERSION_BASE); BOOST_CHECK(coinbaseKey.Sign(hash, vchSig)); vchSig.push_back((unsigned char)SIGHASH_ALL); spends[i].vin[0].scriptSig << vchSig; From 7c4bf779e8b74e474551982a24f5acc265293abd Mon Sep 17 00:00:00 2001 From: Johnson Lau Date: Sat, 23 Jan 2016 01:46:11 +0800 Subject: [PATCH 0543/1802] [RPC] Return witness data in blockchain RPCs Includes RPC field name changes by Luke-jr. --- src/rpc/blockchain.cpp | 2 ++ src/rpc/rawtransaction.cpp | 22 ++++++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index dae283fb6fea7..f11af876f917c 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -99,6 +99,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx if (chainActive.Contains(blockindex)) confirmations = chainActive.Height() - blockindex->nHeight + 1; result.push_back(Pair("confirmations", confirmations)); + result.push_back(Pair("strippedsize", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS))); result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION))); result.push_back(Pair("height", blockindex->nHeight)); result.push_back(Pair("version", block.nVersion)); @@ -558,6 +559,7 @@ UniValue getblock(const UniValue& params, bool fHelp) " \"hash\" : \"hash\", (string) the block hash (same as provided)\n" " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n" " \"size\" : n, (numeric) The block size\n" + " \"strippedsize\" : n, (numeric) The block size excluding witness data\n" " \"height\" : n, (numeric) The block height or index\n" " \"version\" : n, (numeric) The block version\n" " \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n" diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 38fd98055c42f..12e3eaa9201da 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -62,11 +62,14 @@ void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fInclud void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) { entry.push_back(Pair("txid", tx.GetHash().GetHex())); + entry.push_back(Pair("hash", tx.GetWitnessHash().GetHex())); entry.push_back(Pair("size", (int)::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION))); entry.push_back(Pair("version", tx.nVersion)); entry.push_back(Pair("locktime", (int64_t)tx.nLockTime)); + UniValue vin(UniValue::VARR); - BOOST_FOREACH(const CTxIn& txin, tx.vin) { + for (unsigned int i = 0; i < tx.vin.size(); i++) { + const CTxIn& txin = tx.vin[i]; UniValue in(UniValue::VOBJ); if (tx.IsCoinBase()) in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()))); @@ -78,6 +81,17 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) o.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()))); in.push_back(Pair("scriptSig", o)); } + if (!tx.wit.IsNull()) { + if (!tx.wit.vtxinwit[i].IsNull()) { + UniValue txinwitness(UniValue::VARR); + for (unsigned int j = 0; j < tx.wit.vtxinwit[i].scriptWitness.stack.size(); j++) { + std::vector item = tx.wit.vtxinwit[i].scriptWitness.stack[j]; + txinwitness.push_back(HexStr(item.begin(), item.end())); + } + in.push_back(Pair("txinwitness", txinwitness)); + } + + } in.push_back(Pair("sequence", (int64_t)txin.nSequence)); vin.push_back(in); } @@ -134,7 +148,8 @@ UniValue getrawtransaction(const UniValue& params, bool fHelp) "{\n" " \"hex\" : \"data\", (string) The serialized, hex-encoded data for 'txid'\n" " \"txid\" : \"id\", (string) The transaction id (same as provided)\n" - " \"size\" : n, (numeric) The transaction size\n" + " \"hash\" : \"id\", (string) The transaction hash (differs from txid for witness transactions)\n" + " \"size\" : n, (numeric) The serialized transaction size\n" " \"version\" : n, (numeric) The version\n" " \"locktime\" : ttt, (numeric) The lock time\n" " \"vin\" : [ (array of json objects)\n" @@ -146,6 +161,7 @@ UniValue getrawtransaction(const UniValue& params, bool fHelp) " \"hex\": \"hex\" (string) hex\n" " },\n" " \"sequence\": n (numeric) The script sequence number\n" + " \"txinwitness\": [\"hex\", ...] (array of string) hex-encoded witness data (if any)\n" " }\n" " ,...\n" " ],\n" @@ -443,6 +459,7 @@ UniValue decoderawtransaction(const UniValue& params, bool fHelp) "\nResult:\n" "{\n" " \"txid\" : \"id\", (string) The transaction id\n" + " \"hash\" : \"id\", (string) The transaction hash (differs from txid for witness transactions)\n" " \"size\" : n, (numeric) The transaction size\n" " \"version\" : n, (numeric) The version\n" " \"locktime\" : ttt, (numeric) The lock time\n" @@ -454,6 +471,7 @@ UniValue decoderawtransaction(const UniValue& params, bool fHelp) " \"asm\": \"asm\", (string) asm\n" " \"hex\": \"hex\" (string) hex\n" " },\n" + " \"txinwitness\": [\"hex\", ...] (array of string) hex-encoded witness data (if any)\n" " \"sequence\": n (numeric) The script sequence number\n" " }\n" " ,...\n" From 2b1f6f9ccf36f1e0a2c9d99154e1642f796d7c2b Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 3 Jan 2016 18:54:50 +0100 Subject: [PATCH 0544/1802] BIP141: Other consensus critical limits, and BIP145 Includes changes by Suhas Daftuar, Luke-jr, and mruddy. --- qa/rpc-tests/maxuploadtarget.py | 14 ++-- src/bitcoin-tx.cpp | 2 +- src/blockencodings.cpp | 4 +- src/consensus/consensus.h | 12 +++- src/init.cpp | 1 + src/main.cpp | 78 ++++++++++++++-------- src/main.h | 1 + src/merkleblock.cpp | 2 +- src/miner.cpp | 101 +++++++++++++++++++++-------- src/miner.h | 16 +++-- src/net.cpp | 4 +- src/net.h | 4 +- src/policy/policy.cpp | 14 +++- src/policy/policy.h | 10 ++- src/primitives/block.cpp | 9 +++ src/primitives/block.h | 3 + src/primitives/transaction.cpp | 7 +- src/primitives/transaction.h | 28 ++++++-- src/rpc/blockchain.cpp | 2 + src/rpc/mining.cpp | 18 +++-- src/rpc/rawtransaction.cpp | 3 + src/script/interpreter.cpp | 47 ++++++++++++++ src/script/interpreter.h | 2 + src/test/mempool_tests.cpp | 11 ++-- src/test/miner_tests.cpp | 5 +- src/test/policyestimator_tests.cpp | 3 +- src/test/test_bitcoin.cpp | 2 +- src/test/test_bitcoin.h | 6 +- src/txmempool.cpp | 44 +++++++------ src/txmempool.h | 23 +++---- src/wallet/wallet.cpp | 4 +- 31 files changed, 344 insertions(+), 136 deletions(-) diff --git a/qa/rpc-tests/maxuploadtarget.py b/qa/rpc-tests/maxuploadtarget.py index 5087f0762033a..125d4eb275190 100755 --- a/qa/rpc-tests/maxuploadtarget.py +++ b/qa/rpc-tests/maxuploadtarget.py @@ -97,7 +97,7 @@ def __init__(self): def setup_network(self): # Start a node with maxuploadtarget of 200 MB (/24h) self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, ["-debug", "-maxuploadtarget=200", "-blockmaxsize=999000"])) + self.nodes.append(start_node(0, self.options.tmpdir, ["-debug", "-maxuploadtarget=800", "-blockmaxsize=999000"])) def mine_full_block(self, node, address): # Want to create a full block @@ -175,13 +175,13 @@ def run_test(self): getdata_request = msg_getdata() getdata_request.inv.append(CInv(2, big_old_block)) - max_bytes_per_day = 200*1024*1024 - daily_buffer = 144 * MAX_BLOCK_SIZE + max_bytes_per_day = 800*1024*1024 + daily_buffer = 144 * 4000000 max_bytes_available = max_bytes_per_day - daily_buffer success_count = max_bytes_available // old_block_size - # 144MB will be reserved for relaying new blocks, so expect this to - # succeed for ~70 tries. + # 576MB will be reserved for relaying new blocks, so expect this to + # succeed for ~235 tries. for i in range(success_count): test_nodes[0].send_message(getdata_request) test_nodes[0].sync_with_ping() @@ -198,9 +198,9 @@ def run_test(self): # Requesting the current block on test_nodes[1] should succeed indefinitely, # even when over the max upload target. - # We'll try 200 times + # We'll try 800 times getdata_request.inv = [CInv(2, big_new_block)] - for i in range(200): + for i in range(800): test_nodes[1].send_message(getdata_request) test_nodes[1].sync_with_ping() assert_equal(test_nodes[1].block_receive_map[big_new_block], i+1) diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 424812a6dfbc5..e77aa6c72eea2 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -195,7 +195,7 @@ static void MutateTxAddInput(CMutableTransaction& tx, const string& strInput) uint256 txid(uint256S(strTxid)); static const unsigned int minTxOutSz = 9; - static const unsigned int maxVout = MAX_BLOCK_SIZE / minTxOutSz; + static const unsigned int maxVout = MAX_BLOCK_BASE_SIZE / minTxOutSz; // extract and validate vout string strVout = vStrInputParts[1]; diff --git a/src/blockencodings.cpp b/src/blockencodings.cpp index 7fd6a9cf52d81..5c4c3bd27487c 100644 --- a/src/blockencodings.cpp +++ b/src/blockencodings.cpp @@ -15,7 +15,7 @@ #include -#define MIN_TRANSACTION_SIZE (::GetSerializeSize(CTransaction(), SER_NETWORK, PROTOCOL_VERSION)) +#define MIN_TRANSACTION_BASE_SIZE (::GetSerializeSize(CTransaction(), SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS)) CBlockHeaderAndShortTxIDs::CBlockHeaderAndShortTxIDs(const CBlock& block) : nonce(GetRand(std::numeric_limits::max())), @@ -50,7 +50,7 @@ uint64_t CBlockHeaderAndShortTxIDs::GetShortID(const uint256& txhash) const { ReadStatus PartiallyDownloadedBlock::InitData(const CBlockHeaderAndShortTxIDs& cmpctblock) { if (cmpctblock.header.IsNull() || (cmpctblock.shorttxids.empty() && cmpctblock.prefilledtxn.empty())) return READ_STATUS_INVALID; - if (cmpctblock.shorttxids.size() + cmpctblock.prefilledtxn.size() > MAX_BLOCK_SIZE / MIN_TRANSACTION_SIZE) + if (cmpctblock.shorttxids.size() + cmpctblock.prefilledtxn.size() > MAX_BLOCK_BASE_SIZE / MIN_TRANSACTION_BASE_SIZE) return READ_STATUS_INVALID; assert(header.IsNull() && txn_available.empty()); diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h index ad9cc26175351..81f40593b21a6 100644 --- a/src/consensus/consensus.h +++ b/src/consensus/consensus.h @@ -6,10 +6,16 @@ #ifndef BITCOIN_CONSENSUS_CONSENSUS_H #define BITCOIN_CONSENSUS_CONSENSUS_H -/** The maximum allowed size for a serialized block, in bytes (network rule) */ -static const unsigned int MAX_BLOCK_SIZE = 1000000; +#include + +/** The maximum allowed size for a serialized block, in bytes (only for buffer size limits) */ +static const unsigned int MAX_BLOCK_SERIALIZED_SIZE = 4000000; +/** The maximum allowed cost for a block, see BIP 141 (network rule) */ +static const unsigned int MAX_BLOCK_COST = 4000000; +/** The maximum allowed size for a block excluding witness data, in bytes (network rule) */ +static const unsigned int MAX_BLOCK_BASE_SIZE = 1000000; /** The maximum allowed number of signature check operations in a block (network rule) */ -static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50; +static const int64_t MAX_BLOCK_SIGOPS_COST = 80000; /** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */ static const int COINBASE_MATURITY = 100; diff --git a/src/init.cpp b/src/init.cpp index 6bce0a9b49b51..e924d504bdd82 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -452,6 +452,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-mempoolreplacement", strprintf(_("Enable transaction replacement in the memory pool (default: %u)"), DEFAULT_ENABLE_REPLACEMENT)); strUsage += HelpMessageGroup(_("Block creation options:")); + strUsage += HelpMessageOpt("-blockmaxcost=", strprintf(_("Set maximum block cost (default: %d)"), DEFAULT_BLOCK_MAX_COST)); strUsage += HelpMessageOpt("-blockminsize=", strprintf(_("Set minimum block size in bytes (default: %u)"), DEFAULT_BLOCK_MIN_SIZE)); strUsage += HelpMessageOpt("-blockmaxsize=", strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE)); strUsage += HelpMessageOpt("-blockprioritysize=", strprintf(_("Set maximum size of high-priority/low-fee transactions in bytes (default: %d)"), DEFAULT_BLOCK_PRIORITY_SIZE)); diff --git a/src/main.cpp b/src/main.cpp index c22faf6db6f58..df758bc41f0b5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -684,8 +684,8 @@ bool AddOrphanTx(const CTransaction& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(c // have been mined or received. // 100 orphans, each of which is at most 99,999 bytes big is // at most 10 megabytes of orphans and somewhat more byprev index (in the worst case): - unsigned int sz = tx.GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION); - if (sz >= MAX_STANDARD_TX_SIZE) + unsigned int sz = GetTransactionCost(tx); + if (sz >= MAX_STANDARD_TX_COST) { LogPrint("mempool", "ignoring large orphan tx (size: %u, hash: %s)\n", sz, hash.ToString()); return false; @@ -1018,8 +1018,24 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& in return nSigOps; } +int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, int flags) +{ + int64_t nSigOps = GetLegacySigOpCount(tx) * WITNESS_SCALE_FACTOR; + + if (tx.IsCoinBase()) + return nSigOps; + if (flags & SCRIPT_VERIFY_P2SH) { + nSigOps += GetP2SHSigOpCount(tx, inputs) * WITNESS_SCALE_FACTOR; + } + for (unsigned int i = 0; i < tx.vin.size(); i++) + { + const CTxOut &prevout = inputs.GetOutputFor(tx.vin[i]); + nSigOps += CountWitnessSigOps(tx.vin[i].scriptSig, prevout.scriptPubKey, i < tx.wit.vtxinwit.size() ? &tx.wit.vtxinwit[i].scriptWitness : NULL, flags); + } + return nSigOps; +} @@ -1033,7 +1049,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state) if (tx.vout.empty()) return state.DoS(10, false, REJECT_INVALID, "bad-txns-vout-empty"); // Size limits (this doesn't take the witness into account, as that hasn't been checked for malleability) - if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) > MAX_BLOCK_SIZE) + if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) > MAX_BLOCK_BASE_SIZE) return state.DoS(100, false, REJECT_INVALID, "bad-txns-oversize"); // Check for negative or overflow output values @@ -1239,8 +1255,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C if (fRequireStandard && !AreInputsStandard(tx, view)) return state.Invalid(false, REJECT_NONSTANDARD, "bad-txns-nonstandard-inputs"); - unsigned int nSigOps = GetLegacySigOpCount(tx); - nSigOps += GetP2SHSigOpCount(tx, view); + int64_t nSigOpsCost = GetTransactionSigOpCost(tx, view, STANDARD_SCRIPT_VERIFY_FLAGS); CAmount nValueOut = tx.GetValueOut(); CAmount nFees = nValueIn-nValueOut; @@ -1263,7 +1278,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C } } - CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainActive.Height(), pool.HasNoInputsOf(tx), inChainInputValue, fSpendsCoinbase, nSigOps, lp); + CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainActive.Height(), pool.HasNoInputsOf(tx), inChainInputValue, fSpendsCoinbase, nSigOpsCost, lp); unsigned int nSize = entry.GetTxSize(); // Check that the transaction doesn't have an excessive number of @@ -1271,9 +1286,9 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C // itself can contain sigops MAX_STANDARD_TX_SIGOPS is less than // MAX_BLOCK_SIGOPS; we still consider this an invalid rather than // merely non-standard transaction. - if ((nSigOps > MAX_STANDARD_TX_SIGOPS) || (nBytesPerSigOp && nSigOps > nSize / nBytesPerSigOp)) + if ((nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST) || (nBytesPerSigOp && nSigOpsCost > nSize * WITNESS_SCALE_FACTOR / nBytesPerSigOp)) return state.DoS(0, false, REJECT_NONSTANDARD, "bad-txns-too-many-sigops", false, - strprintf("%d", nSigOps)); + strprintf("%d", nSigOpsCost)); CAmount mempoolRejectFee = pool.GetMinFee(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFee(nSize); if (mempoolRejectFee > 0 && nModifiedFees < mempoolRejectFee) { @@ -2439,7 +2454,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin std::vector prevheights; CAmount nFees = 0; int nInputs = 0; - unsigned int nSigOps = 0; + int64_t nSigOpsCost = 0; CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size())); std::vector > vPos; vPos.reserve(block.vtx.size()); @@ -2449,10 +2464,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin const CTransaction &tx = block.vtx[i]; nInputs += tx.vin.size(); - nSigOps += GetLegacySigOpCount(tx); - if (nSigOps > MAX_BLOCK_SIGOPS) - return state.DoS(100, error("ConnectBlock(): too many sigops"), - REJECT_INVALID, "bad-blk-sigops"); if (!tx.IsCoinBase()) { @@ -2483,18 +2494,19 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return state.DoS(100, error("%s: contains a non-BIP68-final transaction", __func__), REJECT_INVALID, "bad-txns-nonfinal"); } + } - if (fStrictPayToScriptHash) - { - // Add in sigops done by pay-to-script-hash inputs; - // this is to prevent a "rogue miner" from creating - // an incredibly-expensive-to-validate block. - nSigOps += GetP2SHSigOpCount(tx, view); - if (nSigOps > MAX_BLOCK_SIGOPS) - return state.DoS(100, error("ConnectBlock(): too many sigops"), - REJECT_INVALID, "bad-blk-sigops"); - } + // GetTransactionSigOpCost counts 3 types of sigops: + // * legacy (always) + // * p2sh (when P2SH enabled in flags and excludes coinbase) + // * witness (when witness enabled in flags and excludes coinbase) + nSigOpsCost += GetTransactionSigOpCost(tx, view, flags); + if (nSigOpsCost > MAX_BLOCK_SIGOPS_COST) + return state.DoS(100, error("ConnectBlock(): too many sigops"), + REJECT_INVALID, "bad-blk-sigops"); + if (!tx.IsCoinBase()) + { nFees += view.GetValueIn(tx)-tx.GetValueOut(); std::vector vChecks; @@ -3417,9 +3429,11 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P // All potential-corruption validation must be done before we do any // transaction validation, as otherwise we may mark the header as invalid // because we receive the wrong transactions for it. + // Note that witness malleability is checked in ContextualCheckBlock, so no + // checks that use witness data may be performed here. // Size limits - if (block.vtx.empty() || block.vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) > MAX_BLOCK_SIZE) + if (block.vtx.empty() || block.vtx.size() > MAX_BLOCK_BASE_SIZE || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) > MAX_BLOCK_BASE_SIZE) return state.DoS(100, false, REJECT_INVALID, "bad-blk-length", false, "size limits failed"); // First transaction must be coinbase, the rest must not be @@ -3440,7 +3454,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P { nSigOps += GetLegacySigOpCount(tx); } - if (nSigOps > MAX_BLOCK_SIGOPS) + if (nSigOps * WITNESS_SCALE_FACTOR > MAX_BLOCK_SIGOPS_COST) return state.DoS(100, false, REJECT_INVALID, "bad-blk-sigops", false, "out-of-bounds SigOpCount"); if (fCheckPOW && fCheckMerkleRoot) @@ -3621,6 +3635,16 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn } } + // After the coinbase witness nonce and commitment are verified, + // we can check if the block cost passes (before we've checked the + // coinbase witness, it would be possible for the cost to be too + // large by filling up the coinbase witness, which doesn't change + // the block hash, so we couldn't mark the block as permanently + // failed). + if (GetBlockCost(block) > MAX_BLOCK_COST) { + return state.DoS(100, error("ContextualCheckBlock(): cost limit failed"), REJECT_INVALID, "bad-blk-cost"); + } + return true; } @@ -4284,7 +4308,7 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB int nLoaded = 0; try { // This takes over fileIn and calls fclose() on it in the CBufferedFile destructor - CBufferedFile blkdat(fileIn, 2*MAX_BLOCK_SIZE, MAX_BLOCK_SIZE+8, SER_DISK, CLIENT_VERSION); + CBufferedFile blkdat(fileIn, 2*MAX_BLOCK_SERIALIZED_SIZE, MAX_BLOCK_SERIALIZED_SIZE+8, SER_DISK, CLIENT_VERSION); uint64_t nRewind = blkdat.GetPos(); while (!blkdat.eof()) { boost::this_thread::interruption_point(); @@ -4303,7 +4327,7 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB continue; // read size blkdat >> nSize; - if (nSize < 80 || nSize > MAX_BLOCK_SIZE) + if (nSize < 80 || nSize > MAX_BLOCK_SERIALIZED_SIZE) continue; } catch (const std::exception&) { // no valid block header found; don't complain diff --git a/src/main.h b/src/main.h index 6dd4b1aa3d0a2..317470e3c8694 100644 --- a/src/main.h +++ b/src/main.h @@ -152,6 +152,7 @@ typedef boost::unordered_map BlockMap; extern BlockMap mapBlockIndex; extern uint64_t nLastBlockTx; extern uint64_t nLastBlockSize; +extern uint64_t nLastBlockCost; extern const std::string strMessageMagic; extern CWaitableCriticalSection csBestBlock; extern CConditionVariable cvBlockChange; diff --git a/src/merkleblock.cpp b/src/merkleblock.cpp index dca4973cc4d88..31332526a916e 100644 --- a/src/merkleblock.cpp +++ b/src/merkleblock.cpp @@ -155,7 +155,7 @@ uint256 CPartialMerkleTree::ExtractMatches(std::vector &vMatch, std::ve if (nTransactions == 0) return uint256(); // check for excessively high numbers of transactions - if (nTransactions > MAX_BLOCK_SIZE / 60) // 60 is the lower bound for the size of a serialized CTransaction + if (nTransactions > MAX_BLOCK_BASE_SIZE / 60) // 60 is the lower bound for the size of a serialized CTransaction return uint256(); // there can never be more hashes provided than one for every txid if (vHash.size() > nTransactions) diff --git a/src/miner.cpp b/src/miner.cpp index a7bf9ae84ccd7..cfc2dae56ee49 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -45,6 +45,7 @@ using namespace std; uint64_t nLastBlockTx = 0; uint64_t nLastBlockSize = 0; +uint64_t nLastBlockCost = 0; class ScoreCompare { @@ -75,15 +76,36 @@ int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParam BlockAssembler::BlockAssembler(const CChainParams& _chainparams) : chainparams(_chainparams) { - // Largest block you're willing to create: - nBlockMaxSize = GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE); - // Limit to between 1K and MAX_BLOCK_SIZE-1K for sanity: - nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE-1000), nBlockMaxSize)); + // Block resource limits + // If neither -blockmaxsize or -blockmaxcost is given, limit to DEFAULT_BLOCK_MAX_* + // If only one is given, only restrict the specified resource. + // If both are given, restrict both. + nBlockMaxCost = DEFAULT_BLOCK_MAX_COST; + nBlockMaxSize = DEFAULT_BLOCK_MAX_SIZE; + bool fCostSet = false; + if (mapArgs.count("-blockmaxcost")) { + nBlockMaxCost = GetArg("-blockmaxcost", DEFAULT_BLOCK_MAX_COST); + nBlockMaxSize = MAX_BLOCK_SERIALIZED_SIZE; + fCostSet = true; + } + if (mapArgs.count("-blockmaxsize")) { + nBlockMaxSize = GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE); + if (!fCostSet) { + nBlockMaxCost = nBlockMaxSize * WITNESS_SCALE_FACTOR; + } + } + // Limit cost to between 4K and MAX_BLOCK_COST-4K for sanity: + nBlockMaxCost = std::max((unsigned int)4000, std::min((unsigned int)(MAX_BLOCK_COST-4000), nBlockMaxCost)); + // Limit size to between 1K and MAX_BLOCK_SERIALIZED_SIZE-1K for sanity: + nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SERIALIZED_SIZE-1000), nBlockMaxSize)); // Minimum block size you want to create; block will be filled with free transactions // until there are no more or the block reaches this size: nBlockMinSize = GetArg("-blockminsize", DEFAULT_BLOCK_MIN_SIZE); nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize); + + // Whether we need to account for byte usage (in addition to cost usage) + fNeedSizeAccounting = (nBlockMaxSize < MAX_BLOCK_SERIALIZED_SIZE-1000) || (nBlockMinSize > 0); } void BlockAssembler::resetBlock() @@ -92,7 +114,8 @@ void BlockAssembler::resetBlock() // Reserve space for coinbase tx nBlockSize = 1000; - nBlockSigOps = 100; + nBlockCost = 4000; + nBlockSigOpsCost = 400; fIncludeWitness = false; // These counters do not include coinbase tx @@ -116,7 +139,7 @@ CBlockTemplate* BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn) // Add dummy coinbase tx as first transaction pblock->vtx.push_back(CTransaction()); pblocktemplate->vTxFees.push_back(-1); // updated at end - pblocktemplate->vTxSigOps.push_back(-1); // updated at end + pblocktemplate->vTxSigOpsCost.push_back(-1); // updated at end LOCK2(cs_main, mempool.cs); CBlockIndex* pindexPrev = chainActive.Tip(); @@ -144,11 +167,18 @@ CBlockTemplate* BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn) fIncludeWitness = IsWitnessEnabled(pindexPrev, chainparams.GetConsensus()); addPriorityTxs(); - addPackageTxs(); + if (fNeedSizeAccounting) { + // addPackageTxs (the CPFP-based algorithm) cannot deal with size based + // accounting, so fall back to the old algorithm. + addScoreTxs(); + } else { + addPackageTxs(); + } nLastBlockTx = nBlockTx; nLastBlockSize = nBlockSize; - LogPrintf("CreateNewBlock(): total size %u txs: %u fees: %ld sigops %d\n", nBlockSize, nBlockTx, nFees, nBlockSigOps); + nLastBlockCost = nBlockCost; + LogPrintf("CreateNewBlock(): total size %u txs: %u fees: %ld sigops %d\n", nBlockSize, nBlockTx, nFees, nBlockSigOpsCost); // Create coinbase transaction. CMutableTransaction coinbaseTx; @@ -167,7 +197,7 @@ CBlockTemplate* BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn) UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev); pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, chainparams.GetConsensus()); pblock->nNonce = 0; - pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]); + pblocktemplate->vTxSigOpsCost[0] = GetLegacySigOpCount(pblock->vtx[0]); CValidationState state; if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) { @@ -201,11 +231,12 @@ void BlockAssembler::onlyUnconfirmed(CTxMemPool::setEntries& testSet) } } -bool BlockAssembler::TestPackage(uint64_t packageSize, unsigned int packageSigOps) +bool BlockAssembler::TestPackage(uint64_t packageSize, int64_t packageSigOpsCost) { - if (nBlockSize + packageSize >= nBlockMaxSize) + // TODO: switch to cost-based accounting for packages instead of vsize-based accounting. + if (nBlockCost + WITNESS_SCALE_FACTOR * packageSize >= nBlockMaxCost) return false; - if (nBlockSigOps + packageSigOps >= MAX_BLOCK_SIGOPS) + if (nBlockSigOpsCost + packageSigOpsCost >= MAX_BLOCK_SIGOPS_COST) return false; return true; } @@ -223,26 +254,39 @@ bool BlockAssembler::TestPackageFinality(const CTxMemPool::setEntries& package) bool BlockAssembler::TestForBlock(CTxMemPool::txiter iter) { - if (nBlockSize + iter->GetTxSize() >= nBlockMaxSize) { + if (nBlockCost + iter->GetTxCost() >= nBlockMaxCost) { // If the block is so close to full that no more txs will fit // or if we've tried more than 50 times to fill remaining space // then flag that the block is finished - if (nBlockSize > nBlockMaxSize - 100 || lastFewTxs > 50) { + if (nBlockCost > nBlockMaxCost - 400 || lastFewTxs > 50) { blockFinished = true; return false; } - // Once we're within 1000 bytes of a full block, only look at 50 more txs + // Once we're within 4000 cost of a full block, only look at 50 more txs // to try to fill the remaining space. - if (nBlockSize > nBlockMaxSize - 1000) { + if (nBlockCost > nBlockMaxCost - 4000) { lastFewTxs++; } return false; } - if (nBlockSigOps + iter->GetSigOpCount() >= MAX_BLOCK_SIGOPS) { + if (fNeedSizeAccounting) { + if (nBlockSize + ::GetSerializeSize(iter->GetTx(), SER_NETWORK, PROTOCOL_VERSION) >= nBlockMaxSize) { + if (nBlockSize > nBlockMaxSize - 100 || lastFewTxs > 50) { + blockFinished = true; + return false; + } + if (nBlockSize > nBlockMaxSize - 1000) { + lastFewTxs++; + } + return false; + } + } + + if (nBlockSigOpsCost + iter->GetSigOpCost() >= MAX_BLOCK_SIGOPS_COST) { // If the block has room for no more sig ops then // flag that the block is finished - if (nBlockSigOps > MAX_BLOCK_SIGOPS - 2) { + if (nBlockSigOpsCost > MAX_BLOCK_SIGOPS_COST - 8) { blockFinished = true; return false; } @@ -264,10 +308,13 @@ void BlockAssembler::AddToBlock(CTxMemPool::txiter iter) { pblock->vtx.push_back(iter->GetTx()); pblocktemplate->vTxFees.push_back(iter->GetFee()); - pblocktemplate->vTxSigOps.push_back(iter->GetSigOpCount()); - nBlockSize += iter->GetTxSize(); + pblocktemplate->vTxSigOpsCost.push_back(iter->GetSigOpCost()); + if (fNeedSizeAccounting) { + nBlockSize += ::GetSerializeSize(iter->GetTx(), SER_NETWORK, PROTOCOL_VERSION); + } + nBlockCost += iter->GetTxCost(); ++nBlockTx; - nBlockSigOps += iter->GetSigOpCount(); + nBlockSigOpsCost += iter->GetSigOpCost(); nFees += iter->GetFee(); inBlock.insert(iter); @@ -358,7 +405,7 @@ void BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& alread CTxMemPoolModifiedEntry modEntry(desc); modEntry.nSizeWithAncestors -= it->GetTxSize(); modEntry.nModFeesWithAncestors -= it->GetModifiedFee(); - modEntry.nSigOpCountWithAncestors -= it->GetSigOpCount(); + modEntry.nSigOpCostWithAncestors -= it->GetSigOpCost(); mapModifiedTx.insert(modEntry); } else { mapModifiedTx.modify(mit, update_for_parent_inclusion(it)); @@ -460,19 +507,19 @@ void BlockAssembler::addPackageTxs() uint64_t packageSize = iter->GetSizeWithAncestors(); CAmount packageFees = iter->GetModFeesWithAncestors(); - unsigned int packageSigOps = iter->GetSigOpCountWithAncestors(); + int64_t packageSigOpsCost = iter->GetSigOpCostWithAncestors(); if (fUsingModified) { packageSize = modit->nSizeWithAncestors; packageFees = modit->nModFeesWithAncestors; - packageSigOps = modit->nSigOpCountWithAncestors; + packageSigOpsCost = modit->nSigOpCostWithAncestors; } - if (packageFees < ::minRelayTxFee.GetFee(packageSize) && nBlockSize >= nBlockMinSize) { + if (packageFees < ::minRelayTxFee.GetFee(packageSize)) { // Everything else we might consider has a lower fee rate return; } - if (!TestPackage(packageSize, packageSigOps)) { + if (!TestPackage(packageSize, packageSigOpsCost)) { if (fUsingModified) { // Since we always look at the best entry in mapModifiedTx, // we must erase failed entries so that we can consider the @@ -526,6 +573,8 @@ void BlockAssembler::addPriorityTxs() return; } + fNeedSizeAccounting = true; + // This vector will be sorted into a priority queue: vector vecPriority; TxCoinAgePriorityCompare pricomparer; diff --git a/src/miner.h b/src/miner.h index 8bfc1493db19b..b303a8fa3ceb7 100644 --- a/src/miner.h +++ b/src/miner.h @@ -28,7 +28,7 @@ struct CBlockTemplate { CBlock block; std::vector vTxFees; - std::vector vTxSigOps; + std::vector vTxSigOpsCost; std::vector vchCoinbaseCommitment; }; @@ -40,13 +40,13 @@ struct CTxMemPoolModifiedEntry { iter = entry; nSizeWithAncestors = entry->GetSizeWithAncestors(); nModFeesWithAncestors = entry->GetModFeesWithAncestors(); - nSigOpCountWithAncestors = entry->GetSigOpCountWithAncestors(); + nSigOpCostWithAncestors = entry->GetSigOpCostWithAncestors(); } CTxMemPool::txiter iter; uint64_t nSizeWithAncestors; CAmount nModFeesWithAncestors; - unsigned int nSigOpCountWithAncestors; + int64_t nSigOpCostWithAncestors; }; /** Comparator for CTxMemPool::txiter objects. @@ -124,7 +124,7 @@ struct update_for_parent_inclusion { e.nModFeesWithAncestors -= iter->GetFee(); e.nSizeWithAncestors -= iter->GetTxSize(); - e.nSigOpCountWithAncestors -= iter->GetSigOpCount(); + e.nSigOpCostWithAncestors -= iter->GetSigOpCost(); } CTxMemPool::txiter iter; @@ -141,12 +141,14 @@ class BlockAssembler // Configuration parameters for the block size bool fIncludeWitness; - unsigned int nBlockMaxSize, nBlockMinSize; + unsigned int nBlockMaxCost, nBlockMaxSize, nBlockMinSize; + bool fNeedSizeAccounting; // Information on the current status of the block + uint64_t nBlockCost; uint64_t nBlockSize; uint64_t nBlockTx; - unsigned int nBlockSigOps; + uint64_t nBlockSigOpsCost; CAmount nFees; CTxMemPool::setEntries inBlock; @@ -189,7 +191,7 @@ class BlockAssembler /** Remove confirmed (inBlock) entries from given set */ void onlyUnconfirmed(CTxMemPool::setEntries& testSet); /** Test if a new package would "fit" in the block */ - bool TestPackage(uint64_t packageSize, unsigned int packageSigOps); + bool TestPackage(uint64_t packageSize, int64_t packageSigOpsCost); /** Test if a set of transactions are all final */ bool TestPackageFinality(const CTxMemPool::setEntries& package); /** Return true if given transaction from mapTx has already been evaluated, diff --git a/src/net.cpp b/src/net.cpp index dc83f19be48c8..4cbc43e4d8425 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2182,7 +2182,7 @@ void CNode::RecordBytesSent(uint64_t bytes) void CNode::SetMaxOutboundTarget(uint64_t limit) { LOCK(cs_totalBytesSent); - uint64_t recommendedMinimum = (nMaxOutboundTimeframe / 600) * MAX_BLOCK_SIZE; + uint64_t recommendedMinimum = (nMaxOutboundTimeframe / 600) * MAX_BLOCK_SERIALIZED_SIZE; nMaxOutboundLimit = limit; if (limit > 0 && limit < recommendedMinimum) @@ -2237,7 +2237,7 @@ bool CNode::OutboundTargetReached(bool historicalBlockServingLimit) { // keep a large enough buffer to at least relay each block once uint64_t timeLeftInCycle = GetMaxOutboundTimeLeftInCycle(); - uint64_t buffer = timeLeftInCycle / 600 * MAX_BLOCK_SIZE; + uint64_t buffer = timeLeftInCycle / 600 * MAX_BLOCK_SERIALIZED_SIZE; if (buffer >= nMaxOutboundLimit || nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit - buffer) return true; } diff --git a/src/net.h b/src/net.h index 7ed18b2050a38..41315fc9b9fcc 100644 --- a/src/net.h +++ b/src/net.h @@ -45,8 +45,8 @@ static const int TIMEOUT_INTERVAL = 20 * 60; static const unsigned int MAX_INV_SZ = 50000; /** The maximum number of new addresses to accumulate before announcing. */ static const unsigned int MAX_ADDR_TO_SEND = 1000; -/** Maximum length of incoming protocol messages (no message over 2 MiB is currently acceptable). */ -static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH = 2 * 1024 * 1024; +/** Maximum length of incoming protocol messages (no message over 4 MB is currently acceptable). */ +static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH = 4 * 1000 * 1000; /** Maximum length of strSubVer in `version` message */ static const unsigned int MAX_SUBVERSION_LENGTH = 256; /** -listen default */ diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index 67434a38fa3c1..f2148bfe1057d 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -64,8 +64,8 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason) // almost as much to process as they cost the sender in fees, because // computing signature hashes is O(ninputs*txsize). Limiting transactions // to MAX_STANDARD_TX_SIZE mitigates CPU exhaustion attacks. - unsigned int sz = tx.GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION); - if (sz >= MAX_STANDARD_TX_SIZE) { + unsigned int sz = GetTransactionCost(tx); + if (sz >= MAX_STANDARD_TX_COST) { reason = "tx-size"; return false; } @@ -150,3 +150,13 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs) return true; } + +int64_t GetVirtualTransactionSize(int64_t nCost) +{ + return (nCost + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR; +} + +int64_t GetVirtualTransactionSize(const CTransaction& tx) +{ + return GetVirtualTransactionSize(GetTransactionCost(tx)); +} diff --git a/src/policy/policy.h b/src/policy/policy.h index a6bcc777ff51d..fefb562ff9318 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -19,12 +19,14 @@ static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 750000; static const unsigned int DEFAULT_BLOCK_MIN_SIZE = 0; /** Default for -blockprioritysize, maximum space for zero/low-fee transactions **/ static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 0; +/** Default for -blockmaxcost, which control the range of block costs the mining code will create **/ +static const unsigned int DEFAULT_BLOCK_MAX_COST = 3000000; /** The maximum size for transactions we're willing to relay/mine */ -static const unsigned int MAX_STANDARD_TX_SIZE = 100000; +static const unsigned int MAX_STANDARD_TX_COST = 400000; /** Maximum number of signature check operations in an IsStandard() P2SH script */ static const unsigned int MAX_P2SH_SIGOPS = 15; /** The maximum number of sigops we're willing to relay/mine in a single tx */ -static const unsigned int MAX_STANDARD_TX_SIGOPS = MAX_BLOCK_SIGOPS/5; +static const unsigned int MAX_STANDARD_TX_SIGOPS_COST = MAX_BLOCK_SIGOPS_COST/5; /** Default for -maxmempool, maximum megabytes of mempool memory usage */ static const unsigned int DEFAULT_MAX_MEMPOOL_SIZE = 300; /** @@ -65,4 +67,8 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason); */ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs); +/** Compute the virtual transaction size (cost reinterpreted as bytes). */ +int64_t GetVirtualTransactionSize(int64_t nCost); +int64_t GetVirtualTransactionSize(const CTransaction& tx); + #endif // BITCOIN_POLICY_POLICY_H diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp index 6fb33230a53e0..df900388f2678 100644 --- a/src/primitives/block.cpp +++ b/src/primitives/block.cpp @@ -31,3 +31,12 @@ std::string CBlock::ToString() const } return s.str(); } + +int64_t GetBlockCost(const CBlock& block) +{ + // This implements the cost = (stripped_size * 4) + witness_size formula, + // using only serialization with and without witness data. As witness_size + // is equal to total_size - stripped_size, this formula is identical to: + // cost = (stripped_size * 3) + total_size. + return ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION); +} diff --git a/src/primitives/block.h b/src/primitives/block.h index 29307aed5be48..e2a309e63d821 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -154,4 +154,7 @@ struct CBlockLocator } }; +/** Compute the consensus-critical block cost (see BIP 141). */ +int64_t GetBlockCost(const CBlock& tx); + #endif // BITCOIN_PRIMITIVES_BLOCK_H diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index b0230530e804f..7f10409c05397 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -121,7 +121,7 @@ unsigned int CTransaction::CalculateModifiedSize(unsigned int nTxSize) const // Providing any more cleanup incentive than making additional inputs free would // risk encouraging people to create junk outputs to redeem later. if (nTxSize == 0) - nTxSize = ::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION); + nTxSize = (GetTransactionCost(*this) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR; for (std::vector::const_iterator it(vin.begin()); it != vin.end(); ++it) { unsigned int offset = 41U + std::min(110U, (unsigned int)it->scriptSig.size()); @@ -148,3 +148,8 @@ std::string CTransaction::ToString() const str += " " + vout[i].ToString() + "\n"; return str; } + +int64_t GetTransactionCost(const CTransaction& tx) +{ + return ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR -1) + ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); +} diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 5a58241347b49..e87ad90f0d498 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -13,6 +13,8 @@ static const int SERIALIZE_TRANSACTION_NO_WITNESS = 0x40000000; +static const int WITNESS_SCALE_FACTOR = 4; + /** An outpoint - a combination of a transaction hash and an index n into its vout */ class COutPoint { @@ -166,15 +168,30 @@ class CTxOut // which has units satoshis-per-kilobyte. // If you'd pay more than 1/3 in fees // to spend something, then we consider it dust. - // A typical spendable txout is 34 bytes big, and will + // A typical spendable non-segwit txout is 34 bytes big, and will // need a CTxIn of at least 148 bytes to spend: // so dust is a spendable txout less than - // 546*minRelayTxFee/1000 (in satoshis) + // 546*minRelayTxFee/1000 (in satoshis). + // A typical spendable segwit txout is 31 bytes big, and will + // need a CTxIn of at least 67 bytes to spend: + // so dust is a spendable txout less than + // 294*minRelayTxFee/1000 (in satoshis). if (scriptPubKey.IsUnspendable()) return 0; - size_t nSize = GetSerializeSize(SER_DISK,0)+148u; - return 3*minRelayTxFee.GetFee(nSize); + size_t nSize = GetSerializeSize(SER_DISK, 0); + int witnessversion = 0; + std::vector witnessprogram; + + if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) { + // sum the sizes of the parts of a transaction input + // with 75% segwit discount applied to the script size. + nSize += (32 + 4 + 1 + (107 / WITNESS_SCALE_FACTOR) + 4); + } else { + nSize += (32 + 4 + 1 + 107 + 4); // the 148 mentioned above + } + + return 3 * minRelayTxFee.GetFee(nSize); } bool IsDust(const CFeeRate &minRelayTxFee) const @@ -442,4 +459,7 @@ struct CMutableTransaction uint256 GetHash() const; }; +/** Compute the cost of a transaction, as defined by BIP 141 */ +int64_t GetTransactionCost(const CTransaction &tx); + #endif // BITCOIN_PRIMITIVES_TRANSACTION_H diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index f11af876f917c..43ba4edd78c19 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -101,6 +101,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx result.push_back(Pair("confirmations", confirmations)); result.push_back(Pair("strippedsize", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS))); result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION))); + result.push_back(Pair("cost", (int)::GetBlockCost(block))); result.push_back(Pair("height", blockindex->nHeight)); result.push_back(Pair("version", block.nVersion)); result.push_back(Pair("versionHex", strprintf("%08x", block.nVersion))); @@ -560,6 +561,7 @@ UniValue getblock(const UniValue& params, bool fHelp) " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n" " \"size\" : n, (numeric) The block size\n" " \"strippedsize\" : n, (numeric) The block size excluding witness data\n" + " \"cost\" : n (numeric) The block cost\n" " \"height\" : n, (numeric) The block height or index\n" " \"version\" : n, (numeric) The block version\n" " \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n" diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 291314b8b57fa..4c4e5997818ef 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -224,6 +224,7 @@ UniValue getmininginfo(const UniValue& params, bool fHelp) "{\n" " \"blocks\": nnn, (numeric) The current block\n" " \"currentblocksize\": nnn, (numeric) The last block size\n" + " \"currentblockcost\": nnn, (numeric) The last block cost\n" " \"currentblocktx\": nnn, (numeric) The last block transaction\n" " \"difficulty\": xxx.xxxxx (numeric) The current difficulty\n" " \"errors\": \"...\" (string) Current errors\n" @@ -242,6 +243,7 @@ UniValue getmininginfo(const UniValue& params, bool fHelp) UniValue obj(UniValue::VOBJ); obj.push_back(Pair("blocks", (int)chainActive.Height())); obj.push_back(Pair("currentblocksize", (uint64_t)nLastBlockSize)); + obj.push_back(Pair("currentblockcost", (uint64_t)nLastBlockCost)); obj.push_back(Pair("currentblocktx", (uint64_t)nLastBlockTx)); obj.push_back(Pair("difficulty", (double)GetDifficulty())); obj.push_back(Pair("errors", GetWarnings("statusbar"))); @@ -349,13 +351,14 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) " {\n" " \"data\" : \"xxxx\", (string) transaction data encoded in hexadecimal (byte-for-byte)\n" " \"txid\" : \"xxxx\", (string) transaction id encoded in little-endian hexadecimal\n" - " \"hash\" : \"xxxx\", (string) hash encoded in little-endian hexadecimal\n" + " \"hash\" : \"xxxx\", (string) hash encoded in little-endian hexadecimal (including witness data)\n" " \"depends\" : [ (array) array of numbers \n" " n (numeric) transactions before this one (by 1-based index in 'transactions' list) that must be present in the final block if this one is\n" " ,...\n" " ],\n" " \"fee\": n, (numeric) difference in value between transaction inputs and outputs (in Satoshis); for coinbase transactions, this is a negative Number of the total collected block fees (ie, not including the block subsidy); if key is not present, fee is unknown and clients MUST NOT assume there isn't one\n" - " \"sigops\" : n, (numeric) total number of SigOps, as counted for purposes of block limits; if key is not present, sigop count is unknown and clients MUST NOT assume there aren't any\n" + " \"sigops\" : n, (numeric) total SigOps cost, as counted for purposes of block limits; if key is not present, sigop cost is unknown and clients MUST NOT assume it is zero\n" + " \"cost\" : n, (numeric) total transaction size cost, as counted for purposes of block limits\n" " \"required\" : true|false (boolean) if provided and true, this transaction must be in the final block\n" " }\n" " ,...\n" @@ -372,8 +375,9 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) " ,...\n" " ],\n" " \"noncerange\" : \"00000000ffffffff\", (string) A range of valid nonces\n" - " \"sigoplimit\" : n, (numeric) limit of sigops in blocks\n" + " \"sigoplimit\" : n, (numeric) cost limit of sigops in blocks\n" " \"sizelimit\" : n, (numeric) limit of block size\n" + " \"costlimit\" : n, (numeric) limit of block cost\n" " \"curtime\" : ttt, (numeric) current timestamp in seconds since epoch (Jan 1 1970 GMT)\n" " \"bits\" : \"xxx\", (string) compressed target of next block\n" " \"height\" : n (numeric) The height of the next block\n" @@ -570,7 +574,8 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) int index_in_template = i - 1; entry.push_back(Pair("fee", pblocktemplate->vTxFees[index_in_template])); - entry.push_back(Pair("sigops", pblocktemplate->vTxSigOps[index_in_template])); + entry.push_back(Pair("sigops", pblocktemplate->vTxSigOpsCost[index_in_template])); + entry.push_back(Pair("cost", GetTransactionCost(tx))); transactions.push_back(entry); } @@ -652,8 +657,9 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1)); result.push_back(Pair("mutable", aMutable)); result.push_back(Pair("noncerange", "00000000ffffffff")); - result.push_back(Pair("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS)); - result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SIZE)); + result.push_back(Pair("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS_COST)); + result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SERIALIZED_SIZE)); + result.push_back(Pair("costlimit", (int64_t)MAX_BLOCK_COST)); result.push_back(Pair("curtime", pblock->GetBlockTime())); result.push_back(Pair("bits", strprintf("%08x", pblock->nBits))); result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1))); diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 12e3eaa9201da..b36179943f4db 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -64,6 +64,7 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) entry.push_back(Pair("txid", tx.GetHash().GetHex())); entry.push_back(Pair("hash", tx.GetWitnessHash().GetHex())); entry.push_back(Pair("size", (int)::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION))); + entry.push_back(Pair("vsize", (int)::GetVirtualTransactionSize(tx))); entry.push_back(Pair("version", tx.nVersion)); entry.push_back(Pair("locktime", (int64_t)tx.nLockTime)); @@ -150,6 +151,7 @@ UniValue getrawtransaction(const UniValue& params, bool fHelp) " \"txid\" : \"id\", (string) The transaction id (same as provided)\n" " \"hash\" : \"id\", (string) The transaction hash (differs from txid for witness transactions)\n" " \"size\" : n, (numeric) The serialized transaction size\n" + " \"vsize\" : n, (numeric) The virtual transaction size (differs from size for witness transactions)\n" " \"version\" : n, (numeric) The version\n" " \"locktime\" : ttt, (numeric) The lock time\n" " \"vin\" : [ (array of json objects)\n" @@ -461,6 +463,7 @@ UniValue decoderawtransaction(const UniValue& params, bool fHelp) " \"txid\" : \"id\", (string) The transaction id\n" " \"hash\" : \"id\", (string) The transaction hash (differs from txid for witness transactions)\n" " \"size\" : n, (numeric) The transaction size\n" + " \"vsize\" : n, (numeric) The virtual transaction size (differs from size for witness transactions)\n" " \"version\" : n, (numeric) The version\n" " \"locktime\" : ttt, (numeric) The lock time\n" " \"vin\" : [ (array of json objects)\n" diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 4deebd050d45e..bc027e9f0c113 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1470,3 +1470,50 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const C return set_success(serror); } + +size_t static WitnessSigOps(int witversion, const std::vector& witprogram, const CScriptWitness& witness, int flags) +{ + if (witversion == 0) { + if (witprogram.size() == 20) + return 1; + + if (witprogram.size() == 32 && witness.stack.size() > 0) { + CScript subscript(witness.stack.back().begin(), witness.stack.back().end()); + return subscript.GetSigOpCount(true); + } + } + + // Future flags may be implemented here. + return 0; +} + +size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags) +{ + static const CScriptWitness witnessEmpty; + + if ((flags & SCRIPT_VERIFY_WITNESS) == 0) { + return 0; + } + assert((flags & SCRIPT_VERIFY_P2SH) != 0); + + int witnessversion; + std::vector witnessprogram; + if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) { + return WitnessSigOps(witnessversion, witnessprogram, witness ? *witness : witnessEmpty, flags); + } + + if (scriptPubKey.IsPayToScriptHash() && scriptSig.IsPushOnly()) { + CScript::const_iterator pc = scriptSig.begin(); + vector data; + while (pc < scriptSig.end()) { + opcodetype opcode; + scriptSig.GetOp(pc, opcode, data); + } + CScript subscript(data.begin(), data.end()); + if (subscript.IsWitnessProgram(witnessversion, witnessprogram)) { + return WitnessSigOps(witnessversion, witnessprogram, witness ? *witness : witnessEmpty, flags); + } + } + + return 0; +} diff --git a/src/script/interpreter.h b/src/script/interpreter.h index 86437294253e9..bd2f21166368a 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -156,4 +156,6 @@ class MutableTransactionSignatureChecker : public TransactionSignatureChecker bool EvalScript(std::vector >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* error = NULL); bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror = NULL); +size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags); + #endif // BITCOIN_SCRIPT_INTERPRETER_H diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp index c8b43df26ca27..033a50f94f578 100644 --- a/src/test/mempool_tests.cpp +++ b/src/test/mempool_tests.cpp @@ -2,6 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "policy/policy.h" #include "txmempool.h" #include "util.h" @@ -336,7 +337,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest) tx2.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; tx2.vout[0].nValue = 2 * COIN; pool.addUnchecked(tx2.GetHash(), entry.Fee(20000LL).Priority(9.0).FromTx(tx2)); - uint64_t tx2Size = ::GetSerializeSize(tx2, SER_NETWORK, PROTOCOL_VERSION); + uint64_t tx2Size = GetVirtualTransactionSize(tx2); /* lowest fee */ CMutableTransaction tx3 = CMutableTransaction(); @@ -384,7 +385,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest) tx6.vout.resize(1); tx6.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; tx6.vout[0].nValue = 20 * COIN; - uint64_t tx6Size = ::GetSerializeSize(tx6, SER_NETWORK, PROTOCOL_VERSION); + uint64_t tx6Size = GetVirtualTransactionSize(tx6); pool.addUnchecked(tx6.GetHash(), entry.Fee(0LL).FromTx(tx6)); BOOST_CHECK_EQUAL(pool.size(), 6); @@ -398,7 +399,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest) tx7.vout.resize(1); tx7.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL; tx7.vout[0].nValue = 10 * COIN; - uint64_t tx7Size = ::GetSerializeSize(tx7, SER_NETWORK, PROTOCOL_VERSION); + uint64_t tx7Size = GetVirtualTransactionSize(tx7); /* set the fee to just below tx2's feerate when including ancestor */ CAmount fee = (20000/tx2Size)*(tx7Size + tx6Size) - 1; @@ -467,12 +468,12 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest) BOOST_CHECK(pool.exists(tx2.GetHash())); BOOST_CHECK(pool.exists(tx3.GetHash())); - pool.TrimToSize(::GetSerializeSize(CTransaction(tx1), SER_NETWORK, PROTOCOL_VERSION)); // mempool is limited to tx1's size in memory usage, so nothing fits + pool.TrimToSize(GetVirtualTransactionSize(tx1)); // mempool is limited to tx1's size in memory usage, so nothing fits BOOST_CHECK(!pool.exists(tx1.GetHash())); BOOST_CHECK(!pool.exists(tx2.GetHash())); BOOST_CHECK(!pool.exists(tx3.GetHash())); - CFeeRate maxFeeRateRemoved(25000, ::GetSerializeSize(CTransaction(tx3), SER_NETWORK, PROTOCOL_VERSION) + ::GetSerializeSize(CTransaction(tx2), SER_NETWORK, PROTOCOL_VERSION)); + CFeeRate maxFeeRateRemoved(25000, GetVirtualTransactionSize(tx3) + GetVirtualTransactionSize(tx2)); BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), maxFeeRateRemoved.GetFeePerK() + 1000); CMutableTransaction tx4 = CMutableTransaction(); diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index ca8d6d2e05baa..fd581db52ea28 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -181,6 +181,9 @@ void TestPackageSelection(const CChainParams& chainparams, CScript scriptPubKey, // NOTE: These tests rely on CreateNewBlock doing its own self-validation! BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) { + // Disable size accounting (CPFP does not support it) + mapArgs["-blockmaxsize"] = strprintf("%u", MAX_BLOCK_SERIALIZED_SIZE); + const CChainParams& chainparams = Params(CBaseChainParams::MAIN); CScript scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG; CBlockTemplate *pblocktemplate; @@ -264,7 +267,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) hash = tx.GetHash(); bool spendsCoinbase = (i == 0) ? true : false; // only first tx spends coinbase // If we do set the # of sig ops in the CTxMemPoolEntry, template creation passes - mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).SigOps(20).FromTx(tx)); + mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).SigOpsCost(80).FromTx(tx)); tx.vin[0].prevout.hash = hash; } BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey)); diff --git a/src/test/policyestimator_tests.cpp b/src/test/policyestimator_tests.cpp index 2b00e6f567fa8..5c902387f1214 100644 --- a/src/test/policyestimator_tests.cpp +++ b/src/test/policyestimator_tests.cpp @@ -2,6 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "policy/policy.h" #include "policy/fees.h" #include "txmempool.h" #include "uint256.h" @@ -50,7 +51,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates) tx.vin[0].scriptSig = garbage; tx.vout.resize(1); tx.vout[0].nValue=0LL; - CFeeRate baseRate(basefee, ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION)); + CFeeRate baseRate(basefee, GetVirtualTransactionSize(tx)); // Create a fake block std::vector block; diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index 1f3b198800222..856f9b842300c 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -136,7 +136,7 @@ CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(CTransaction &txn, CTxMemPool *po CAmount inChainValue = hasNoDependencies ? txn.GetValueOut() : 0; return CTxMemPoolEntry(txn, nFee, nTime, dPriority, nHeight, - hasNoDependencies, inChainValue, spendsCoinbase, sigOpCount, lp); + hasNoDependencies, inChainValue, spendsCoinbase, sigOpCost, lp); } void Shutdown(void* parg) diff --git a/src/test/test_bitcoin.h b/src/test/test_bitcoin.h index 78b87e7109b7d..bc0d2fe316aa5 100644 --- a/src/test/test_bitcoin.h +++ b/src/test/test_bitcoin.h @@ -70,12 +70,12 @@ struct TestMemPoolEntryHelper unsigned int nHeight; bool hadNoDependencies; bool spendsCoinbase; - unsigned int sigOpCount; + unsigned int sigOpCost; LockPoints lp; TestMemPoolEntryHelper() : nFee(0), nTime(0), dPriority(0.0), nHeight(1), - hadNoDependencies(false), spendsCoinbase(false), sigOpCount(1) { } + hadNoDependencies(false), spendsCoinbase(false), sigOpCost(4) { } CTxMemPoolEntry FromTx(CMutableTransaction &tx, CTxMemPool *pool = NULL); CTxMemPoolEntry FromTx(CTransaction &tx, CTxMemPool *pool = NULL); @@ -87,6 +87,6 @@ struct TestMemPoolEntryHelper TestMemPoolEntryHelper &Height(unsigned int _height) { nHeight = _height; return *this; } TestMemPoolEntryHelper &HadNoDependencies(bool _hnd) { hadNoDependencies = _hnd; return *this; } TestMemPoolEntryHelper &SpendsCoinbase(bool _flag) { spendsCoinbase = _flag; return *this; } - TestMemPoolEntryHelper &SigOps(unsigned int _sigops) { sigOpCount = _sigops; return *this; } + TestMemPoolEntryHelper &SigOpsCost(unsigned int _sigopsCost) { sigOpCost = _sigopsCost; return *this; } }; #endif diff --git a/src/txmempool.cpp b/src/txmempool.cpp index ead28546de56a..a48a6d94659b5 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -9,6 +9,7 @@ #include "consensus/consensus.h" #include "consensus/validation.h" #include "main.h" +#include "policy/policy.h" #include "policy/fees.h" #include "streams.h" #include "timedata.h" @@ -22,17 +23,17 @@ using namespace std; CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee, int64_t _nTime, double _entryPriority, unsigned int _entryHeight, bool poolHasNoInputsOf, CAmount _inChainInputValue, - bool _spendsCoinbase, unsigned int _sigOps, LockPoints lp): + bool _spendsCoinbase, int64_t _sigOpsCost, LockPoints lp): tx(std::make_shared(_tx)), nFee(_nFee), nTime(_nTime), entryPriority(_entryPriority), entryHeight(_entryHeight), hadNoDependencies(poolHasNoInputsOf), inChainInputValue(_inChainInputValue), - spendsCoinbase(_spendsCoinbase), sigOpCount(_sigOps), lockPoints(lp) + spendsCoinbase(_spendsCoinbase), sigOpCost(_sigOpsCost), lockPoints(lp) { - nTxSize = ::GetSerializeSize(_tx, SER_NETWORK, PROTOCOL_VERSION); - nModSize = _tx.CalculateModifiedSize(nTxSize); + nTxCost = GetTransactionCost(_tx); + nModSize = _tx.CalculateModifiedSize(GetTxSize()); nUsageSize = RecursiveDynamicUsage(*tx) + memusage::DynamicUsage(tx); nCountWithDescendants = 1; - nSizeWithDescendants = nTxSize; + nSizeWithDescendants = GetTxSize(); nModFeesWithDescendants = nFee; CAmount nValueIn = _tx.GetValueOut()+nFee; assert(inChainInputValue <= nValueIn); @@ -40,9 +41,9 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee, feeDelta = 0; nCountWithAncestors = 1; - nSizeWithAncestors = nTxSize; + nSizeWithAncestors = GetTxSize(); nModFeesWithAncestors = nFee; - nSigOpCountWithAncestors = sigOpCount; + nSigOpCostWithAncestors = sigOpCost; } CTxMemPoolEntry::CTxMemPoolEntry(const CTxMemPoolEntry& other) @@ -72,6 +73,11 @@ void CTxMemPoolEntry::UpdateLockPoints(const LockPoints& lp) lockPoints = lp; } +size_t CTxMemPoolEntry::GetTxSize() const +{ + return GetVirtualTransactionSize(nTxCost); +} + // Update the given tx for any in-mempool descendants. // Assumes that setMemPoolChildren is correct for the given tx and all // descendants. @@ -111,7 +117,7 @@ void CTxMemPool::UpdateForDescendants(txiter updateIt, cacheMap &cachedDescendan modifyCount++; cachedDescendants[updateIt].insert(cit); // Update ancestor state for each descendant - mapTx.modify(cit, update_ancestor_state(updateIt->GetTxSize(), updateIt->GetModifiedFee(), 1, updateIt->GetSigOpCount())); + mapTx.modify(cit, update_ancestor_state(updateIt->GetTxSize(), updateIt->GetModifiedFee(), 1, updateIt->GetSigOpCost())); } } mapTx.modify(updateIt, update_descendant_state(modifySize, modifyFee, modifyCount)); @@ -247,13 +253,13 @@ void CTxMemPool::UpdateEntryForAncestors(txiter it, const setEntries &setAncesto int64_t updateCount = setAncestors.size(); int64_t updateSize = 0; CAmount updateFee = 0; - int updateSigOps = 0; + int64_t updateSigOpsCost = 0; BOOST_FOREACH(txiter ancestorIt, setAncestors) { updateSize += ancestorIt->GetTxSize(); updateFee += ancestorIt->GetModifiedFee(); - updateSigOps += ancestorIt->GetSigOpCount(); + updateSigOpsCost += ancestorIt->GetSigOpCost(); } - mapTx.modify(it, update_ancestor_state(updateSize, updateFee, updateCount, updateSigOps)); + mapTx.modify(it, update_ancestor_state(updateSize, updateFee, updateCount, updateSigOpsCost)); } void CTxMemPool::UpdateChildrenForRemoval(txiter it) @@ -282,7 +288,7 @@ void CTxMemPool::UpdateForRemoveFromMempool(const setEntries &entriesToRemove, b setDescendants.erase(removeIt); // don't update state for self int64_t modifySize = -((int64_t)removeIt->GetTxSize()); CAmount modifyFee = -removeIt->GetModifiedFee(); - int modifySigOps = -removeIt->GetSigOpCount(); + int modifySigOps = -removeIt->GetSigOpCost(); BOOST_FOREACH(txiter dit, setDescendants) { mapTx.modify(dit, update_ancestor_state(modifySize, modifyFee, -1, modifySigOps)); } @@ -338,8 +344,8 @@ void CTxMemPoolEntry::UpdateAncestorState(int64_t modifySize, CAmount modifyFee, nModFeesWithAncestors += modifyFee; nCountWithAncestors += modifyCount; assert(int64_t(nCountWithAncestors) > 0); - nSigOpCountWithAncestors += modifySigOps; - assert(int(nSigOpCountWithAncestors) >= 0); + nSigOpCostWithAncestors += modifySigOps; + assert(int(nSigOpCostWithAncestors) >= 0); } CTxMemPool::CTxMemPool(const CFeeRate& _minReasonableRelayFee) : @@ -666,7 +672,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const bool fDependsWait = false; setEntries setParentCheck; int64_t parentSizes = 0; - unsigned int parentSigOpCount = 0; + int64_t parentSigOpCost = 0; BOOST_FOREACH(const CTxIn &txin, tx.vin) { // Check that every mempool transaction's inputs refer to available coins, or other mempool tx's. indexed_transaction_set::const_iterator it2 = mapTx.find(txin.prevout.hash); @@ -676,7 +682,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const fDependsWait = true; if (setParentCheck.insert(it2).second) { parentSizes += it2->GetTxSize(); - parentSigOpCount += it2->GetSigOpCount(); + parentSigOpCost += it2->GetSigOpCost(); } } else { const CCoins* coins = pcoins->AccessCoins(txin.prevout.hash); @@ -698,17 +704,17 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const uint64_t nCountCheck = setAncestors.size() + 1; uint64_t nSizeCheck = it->GetTxSize(); CAmount nFeesCheck = it->GetModifiedFee(); - unsigned int nSigOpCheck = it->GetSigOpCount(); + int64_t nSigOpCheck = it->GetSigOpCost(); BOOST_FOREACH(txiter ancestorIt, setAncestors) { nSizeCheck += ancestorIt->GetTxSize(); nFeesCheck += ancestorIt->GetModifiedFee(); - nSigOpCheck += ancestorIt->GetSigOpCount(); + nSigOpCheck += ancestorIt->GetSigOpCost(); } assert(it->GetCountWithAncestors() == nCountCheck); assert(it->GetSizeWithAncestors() == nSizeCheck); - assert(it->GetSigOpCountWithAncestors() == nSigOpCheck); + assert(it->GetSigOpCostWithAncestors() == nSigOpCheck); assert(it->GetModFeesWithAncestors() == nFeesCheck); // Check children against mapNextTx diff --git a/src/txmempool.h b/src/txmempool.h index d6d0d72ff5874..e5a500e19d433 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -78,7 +78,7 @@ class CTxMemPoolEntry private: std::shared_ptr tx; CAmount nFee; //!< Cached to avoid expensive parent-transaction lookups - size_t nTxSize; //!< ... and avoid recomputing tx size + size_t nTxCost; //!< ... and avoid recomputing tx cost (also used for GetTxSize()) size_t nModSize; //!< ... and modified size for priority size_t nUsageSize; //!< ... and total memory usage int64_t nTime; //!< Local time when entering the mempool @@ -87,7 +87,7 @@ class CTxMemPoolEntry bool hadNoDependencies; //!< Not dependent on any other txs when it entered the mempool CAmount inChainInputValue; //!< Sum of all txin values that are already in blockchain bool spendsCoinbase; //!< keep track of transactions that spend a coinbase - unsigned int sigOpCount; //!< Legacy sig ops plus P2SH sig op count + int64_t sigOpCost; //!< Total sigop cost int64_t feeDelta; //!< Used for determining the priority of the transaction for mining in a block LockPoints lockPoints; //!< Track the height and time at which tx was final @@ -104,13 +104,13 @@ class CTxMemPoolEntry uint64_t nCountWithAncestors; uint64_t nSizeWithAncestors; CAmount nModFeesWithAncestors; - unsigned int nSigOpCountWithAncestors; + int64_t nSigOpCostWithAncestors; public: CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee, int64_t _nTime, double _entryPriority, unsigned int _entryHeight, bool poolHasNoInputsOf, CAmount _inChainInputValue, bool spendsCoinbase, - unsigned int nSigOps, LockPoints lp); + int64_t nSigOpsCost, LockPoints lp); CTxMemPoolEntry(const CTxMemPoolEntry& other); const CTransaction& GetTx() const { return *this->tx; } @@ -121,11 +121,12 @@ class CTxMemPoolEntry */ double GetPriority(unsigned int currentHeight) const; const CAmount& GetFee() const { return nFee; } - size_t GetTxSize() const { return nTxSize; } + size_t GetTxSize() const; + size_t GetTxCost() const { return nTxCost; } int64_t GetTime() const { return nTime; } unsigned int GetHeight() const { return entryHeight; } bool WasClearAtEntry() const { return hadNoDependencies; } - unsigned int GetSigOpCount() const { return sigOpCount; } + int64_t GetSigOpCost() const { return sigOpCost; } int64_t GetModifiedFee() const { return nFee + feeDelta; } size_t DynamicMemoryUsage() const { return nUsageSize; } const LockPoints& GetLockPoints() const { return lockPoints; } @@ -149,7 +150,7 @@ class CTxMemPoolEntry uint64_t GetCountWithAncestors() const { return nCountWithAncestors; } uint64_t GetSizeWithAncestors() const { return nSizeWithAncestors; } CAmount GetModFeesWithAncestors() const { return nModFeesWithAncestors; } - unsigned int GetSigOpCountWithAncestors() const { return nSigOpCountWithAncestors; } + int64_t GetSigOpCostWithAncestors() const { return nSigOpCostWithAncestors; } mutable size_t vTxHashesIdx; //!< Index in mempool's vTxHashes }; @@ -172,18 +173,18 @@ struct update_descendant_state struct update_ancestor_state { - update_ancestor_state(int64_t _modifySize, CAmount _modifyFee, int64_t _modifyCount, int _modifySigOps) : - modifySize(_modifySize), modifyFee(_modifyFee), modifyCount(_modifyCount), modifySigOps(_modifySigOps) + update_ancestor_state(int64_t _modifySize, CAmount _modifyFee, int64_t _modifyCount, int64_t _modifySigOpsCost) : + modifySize(_modifySize), modifyFee(_modifyFee), modifyCount(_modifyCount), modifySigOpsCost(_modifySigOpsCost) {} void operator() (CTxMemPoolEntry &e) - { e.UpdateAncestorState(modifySize, modifyFee, modifyCount, modifySigOps); } + { e.UpdateAncestorState(modifySize, modifyFee, modifyCount, modifySigOpsCost); } private: int64_t modifySize; CAmount modifyFee; int64_t modifyCount; - int modifySigOps; + int64_t modifySigOpsCost; }; struct update_fee_delta diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 723b2eceff7b2..babde1a02c3c4 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2348,7 +2348,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt nIn++; } - unsigned int nBytes = ::GetSerializeSize(txNew, SER_NETWORK, PROTOCOL_VERSION); + unsigned int nBytes = GetVirtualTransactionSize(txNew); // Remove scriptSigs if we used dummy signatures for fee calculation if (!sign) { @@ -2360,7 +2360,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt *static_cast(&wtxNew) = CTransaction(txNew); // Limit size - if (nBytes >= MAX_STANDARD_TX_SIZE) + if (GetTransactionCost(txNew) >= MAX_STANDARD_TX_COST) { strFailReason = _("Transaction too large"); return false; From b7dbeb24ebff16198b2925d906c06771e167bd9e Mon Sep 17 00:00:00 2001 From: Thomas Kerin Date: Sun, 24 Jan 2016 16:29:39 +0000 Subject: [PATCH 0545/1802] [libconsensus] Script verification API with amounts script_tests: always test bitcoinconsensus_verify_script_with_amount if VERIFY_WITNESS isn't set Rename internal method + make it static trim bitcoinconsensus_ prefix Add SERIALIZE_TRANSACTION_WITNESS flag --- src/script/bitcoinconsensus.cpp | 30 +++++++++++++++++++++++++----- src/script/bitcoinconsensus.h | 8 +++++++- src/test/script_tests.cpp | 7 ++++++- 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/src/script/bitcoinconsensus.cpp b/src/script/bitcoinconsensus.cpp index 26e7a85b7b722..62fd9031f853a 100644 --- a/src/script/bitcoinconsensus.cpp +++ b/src/script/bitcoinconsensus.cpp @@ -69,7 +69,7 @@ struct ECCryptoClosure ECCryptoClosure instance_of_eccryptoclosure; } -int bitcoinconsensus_verify_script(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, +static int verify_script(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, CAmount amount, const unsigned char *txTo , unsigned int txToLen, unsigned int nIn, unsigned int flags, bitcoinconsensus_error* err) { @@ -82,16 +82,36 @@ int bitcoinconsensus_verify_script(const unsigned char *scriptPubKey, unsigned i if (tx.GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION) != txToLen) return set_error(err, bitcoinconsensus_ERR_TX_SIZE_MISMATCH); - // Regardless of the verification result, the tx did not error. - set_error(err, bitcoinconsensus_ERR_OK); + // Regardless of the verification result, the tx did not error. + set_error(err, bitcoinconsensus_ERR_OK); - CAmount am(0); - return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), nIn < tx.wit.vtxinwit.size() ? &tx.wit.vtxinwit[nIn].scriptWitness : NULL, flags, TransactionSignatureChecker(&tx, nIn, am), NULL); + return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), nIn < tx.wit.vtxinwit.size() ? &tx.wit.vtxinwit[nIn].scriptWitness : NULL, flags, TransactionSignatureChecker(&tx, nIn, amount), NULL); } catch (const std::exception&) { return set_error(err, bitcoinconsensus_ERR_TX_DESERIALIZE); // Error deserializing } } +int bitcoinconsensus_verify_script_with_amount(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, int64_t amount, + const unsigned char *txTo , unsigned int txToLen, + unsigned int nIn, unsigned int flags, bitcoinconsensus_error* err) +{ + CAmount am(amount); + return ::verify_script(scriptPubKey, scriptPubKeyLen, am, txTo, txToLen, nIn, flags, err); +} + + +int bitcoinconsensus_verify_script(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, + const unsigned char *txTo , unsigned int txToLen, + unsigned int nIn, unsigned int flags, bitcoinconsensus_error* err) +{ + if (flags & bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS) { + return set_error(err, bitcoinconsensus_ERR_AMOUNT_REQUIRED); + } + + CAmount am(0); + return ::verify_script(scriptPubKey, scriptPubKeyLen, am, txTo, txToLen, nIn, flags, err); +} + unsigned int bitcoinconsensus_version() { // Just use the API version for now diff --git a/src/script/bitcoinconsensus.h b/src/script/bitcoinconsensus.h index cd3e2f773177b..6f868d0d6d6ab 100644 --- a/src/script/bitcoinconsensus.h +++ b/src/script/bitcoinconsensus.h @@ -33,7 +33,7 @@ extern "C" { #endif -#define BITCOINCONSENSUS_API_VER 0 +#define BITCOINCONSENSUS_API_VER 1 typedef enum bitcoinconsensus_error_t { @@ -41,6 +41,7 @@ typedef enum bitcoinconsensus_error_t bitcoinconsensus_ERR_TX_INDEX, bitcoinconsensus_ERR_TX_SIZE_MISMATCH, bitcoinconsensus_ERR_TX_DESERIALIZE, + bitcoinconsensus_ERR_AMOUNT_REQUIRED, } bitcoinconsensus_error; /** Script verification flags */ @@ -50,6 +51,7 @@ enum bitcoinconsensus_SCRIPT_FLAGS_VERIFY_P2SH = (1U << 0), // evaluate P2SH (BIP16) subscripts bitcoinconsensus_SCRIPT_FLAGS_VERIFY_DERSIG = (1U << 2), // enforce strict DER (BIP66) compliance bitcoinconsensus_SCRIPT_FLAGS_VERIFY_CHECKLOCKTIMEVERIFY = (1U << 9), // enable CHECKLOCKTIMEVERIFY (BIP65) + bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS = (1U << 11), // enable WITNESS (BIP141) }; /// Returns 1 if the input nIn of the serialized transaction pointed to by @@ -57,6 +59,10 @@ enum /// the additional constraints specified by flags. /// If not NULL, err will contain an error/success code for the operation EXPORT_SYMBOL int bitcoinconsensus_verify_script(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, + const unsigned char *txTo , unsigned int txToLen, + unsigned int nIn, unsigned int flags, bitcoinconsensus_error* err); + +EXPORT_SYMBOL int bitcoinconsensus_verify_script_with_amount(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, int64_t amount, const unsigned char *txTo , unsigned int txToLen, unsigned int nIn, unsigned int flags, bitcoinconsensus_error* err); diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index c56b9da4e5ab5..7fd7614e2cfc0 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -160,7 +160,12 @@ void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, int flags, co #if defined(HAVE_CONSENSUS_LIB) CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); stream << tx2; - BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script(begin_ptr(scriptPubKey), scriptPubKey.size(), (const unsigned char*)&stream[0], stream.size(), 0, flags, NULL) == expect,message); + if (flags & bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS) { + BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script_with_amount(begin_ptr(scriptPubKey), scriptPubKey.size(), amountZero, (const unsigned char*)&stream[0], stream.size(), 0, flags, NULL) == expect, message); + } else { + BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script_with_amount(begin_ptr(scriptPubKey), scriptPubKey.size(), 0, (const unsigned char*)&stream[0], stream.size(), 0, flags, NULL) == expect, message); + BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script(begin_ptr(scriptPubKey), scriptPubKey.size(), (const unsigned char*)&stream[0], stream.size(), 0, flags, NULL) == expect,message); + } #endif } From 6032f6930a56c107dad8f30c05fec4aab79c8c22 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 18 Mar 2016 17:20:12 +0100 Subject: [PATCH 0546/1802] Add rewind logic to deal with post-fork software updates Includes logic for dealing with pruning by Suhas Daftuar. --- src/chain.h | 2 + src/init.cpp | 8 ++++ src/main.cpp | 132 +++++++++++++++++++++++++++++++++++++++++++-------- src/main.h | 3 ++ 4 files changed, 126 insertions(+), 19 deletions(-) diff --git a/src/chain.h b/src/chain.h index a13dae33d188a..76a774c1238f1 100644 --- a/src/chain.h +++ b/src/chain.h @@ -144,6 +144,8 @@ enum BlockStatus: uint32_t { BLOCK_FAILED_VALID = 32, //! stage after last reached validness failed BLOCK_FAILED_CHILD = 64, //! descends from failed block BLOCK_FAILED_MASK = BLOCK_FAILED_VALID | BLOCK_FAILED_CHILD, + + BLOCK_OPT_WITNESS = 128, //! block data in blk*.data was received with a witness-enforcing client }; /** The block chain is a tree shaped structure starting with the diff --git a/src/init.cpp b/src/init.cpp index e924d504bdd82..5d29f14eb8821 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1284,6 +1284,14 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) break; } + if (!fReindex) { + uiInterface.InitMessage(_("Rewinding blocks...")); + if (!RewindBlockIndex(chainparams)) { + strLoadError = _("Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain"); + break; + } + } + uiInterface.InitMessage(_("Verifying blocks...")); if (fHavePruned && GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) > MIN_BLOCKS_TO_KEEP) { LogPrintf("Prune: pruned datadir may not have more than %d blocks; only checking available blocks", diff --git a/src/main.cpp b/src/main.cpp index df758bc41f0b5..ec43a667017e3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -658,6 +658,9 @@ CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& loc CBlockIndex* pindex = (*mi).second; if (chain.Contains(pindex)) return pindex; + if (pindex->GetAncestor(chain.Height()) == chain.Tip()) { + return chain.Tip(); + } } } return chain.Genesis(); @@ -2777,7 +2780,7 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { } /** Disconnect chainActive's tip. You probably want to call mempool.removeForReorg and manually re-limit mempool size after this, with cs_main held. */ -bool static DisconnectTip(CValidationState& state, const CChainParams& chainparams) +bool static DisconnectTip(CValidationState& state, const CChainParams& chainparams, bool fBare = false) { CBlockIndex *pindexDelete = chainActive.Tip(); assert(pindexDelete); @@ -2797,24 +2800,28 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara // Write the chain state to disk, if necessary. if (!FlushStateToDisk(state, FLUSH_STATE_IF_NEEDED)) return false; - // Resurrect mempool transactions from the disconnected block. - std::vector vHashUpdate; - BOOST_FOREACH(const CTransaction &tx, block.vtx) { - // ignore validation errors in resurrected transactions - list removed; - CValidationState stateDummy; - if (tx.IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL, true)) { - mempool.removeRecursive(tx, removed); - } else if (mempool.exists(tx.GetHash())) { - vHashUpdate.push_back(tx.GetHash()); - } - } - // AcceptToMemoryPool/addUnchecked all assume that new mempool entries have - // no in-mempool children, which is generally not true when adding - // previously-confirmed transactions back to the mempool. - // UpdateTransactionsFromBlock finds descendants of any transactions in this - // block that were added back and cleans up the mempool state. - mempool.UpdateTransactionsFromBlock(vHashUpdate); + + if (!fBare) { + // Resurrect mempool transactions from the disconnected block. + std::vector vHashUpdate; + BOOST_FOREACH(const CTransaction &tx, block.vtx) { + // ignore validation errors in resurrected transactions + list removed; + CValidationState stateDummy; + if (tx.IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL, true)) { + mempool.removeRecursive(tx, removed); + } else if (mempool.exists(tx.GetHash())) { + vHashUpdate.push_back(tx.GetHash()); + } + } + // AcceptToMemoryPool/addUnchecked all assume that new mempool entries have + // no in-mempool children, which is generally not true when adding + // previously-confirmed transactions back to the mempool. + // UpdateTransactionsFromBlock finds descendants of any transactions in this + // block that were added back and cleans up the mempool state. + mempool.UpdateTransactionsFromBlock(vHashUpdate); + } + // Update chainActive and related variables. UpdateTip(pindexDelete->pprev, chainparams); // Let wallets know transactions went from 1-confirmed to @@ -3266,6 +3273,9 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl pindexNew->nDataPos = pos.nPos; pindexNew->nUndoPos = 0; pindexNew->nStatus |= BLOCK_HAVE_DATA; + if (IsWitnessEnabled(pindexNew->pprev, Params().GetConsensus())) { + pindexNew->nStatus |= BLOCK_OPT_WITNESS; + } pindexNew->RaiseValidity(BLOCK_VALID_TRANSACTIONS); setDirtyBlockIndex.insert(pindexNew); @@ -4214,6 +4224,90 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, return true; } +bool RewindBlockIndex(const CChainParams& params) +{ + LOCK(cs_main); + + int nHeight = 1; + while (nHeight <= chainActive.Height()) { + if (IsWitnessEnabled(chainActive[nHeight - 1], params.GetConsensus()) && !(chainActive[nHeight]->nStatus & BLOCK_OPT_WITNESS)) { + break; + } + nHeight++; + } + + // nHeight is now the height of the first insufficiently-validated block, or tipheight + 1 + CValidationState state; + CBlockIndex* pindex = chainActive.Tip(); + while (chainActive.Height() >= nHeight) { + if (fPruneMode && !(chainActive.Tip()->nStatus & BLOCK_HAVE_DATA)) { + // If pruning, don't try rewinding past the HAVE_DATA point; + // since older blocks can't be served anyway, there's + // no need to walk further, and trying to DisconnectTip() + // will fail (and require a needless reindex/redownload + // of the blockchain). + break; + } + if (!DisconnectTip(state, params, true)) { + return error("RewindBlockIndex: unable to disconnect block at height %i", pindex->nHeight); + } + // Occasionally flush state to disk. + if (!FlushStateToDisk(state, FLUSH_STATE_PERIODIC)) + return false; + } + + // Reduce validity flag and have-data flags. + // We do this after actual disconnecting, otherwise we'll end up writing the lack of data + // to disk before writing the chainstate, resulting in a failure to continue if interrupted. + for (BlockMap::iterator it = mapBlockIndex.begin(); it != mapBlockIndex.end(); it++) { + CBlockIndex* pindexIter = it->second; + + // Note: If we encounter an insufficiently validated block that + // is on chainActive, it must be because we are a pruning node, and + // this block or some successor doesn't HAVE_DATA, so we were unable to + // rewind all the way. Blocks remaining on chainActive at this point + // must not have their validity reduced. + if (IsWitnessEnabled(pindexIter->pprev, params.GetConsensus()) && !(pindexIter->nStatus & BLOCK_OPT_WITNESS) && !chainActive.Contains(pindexIter)) { + // Reduce validity + pindexIter->nStatus = std::min(pindexIter->nStatus & BLOCK_VALID_MASK, BLOCK_VALID_TREE) | (pindexIter->nStatus & ~BLOCK_VALID_MASK); + // Remove have-data flags. + pindexIter->nStatus &= ~(BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO); + // Remove storage location. + pindexIter->nFile = 0; + pindexIter->nDataPos = 0; + pindexIter->nUndoPos = 0; + // Remove various other things + pindexIter->nTx = 0; + pindexIter->nChainTx = 0; + pindexIter->nSequenceId = 0; + // Make sure it gets written. + setDirtyBlockIndex.insert(pindexIter); + // Update indexes + setBlockIndexCandidates.erase(pindexIter); + std::pair::iterator, std::multimap::iterator> ret = mapBlocksUnlinked.equal_range(pindexIter->pprev); + while (ret.first != ret.second) { + if (ret.first->second == pindexIter) { + mapBlocksUnlinked.erase(ret.first++); + } else { + ++ret.first; + } + } + } else if (pindexIter->IsValid(BLOCK_VALID_TRANSACTIONS) && pindexIter->nChainTx) { + setBlockIndexCandidates.insert(pindexIter); + } + } + + PruneBlockIndexCandidates(); + + CheckBlockIndex(params.GetConsensus()); + + if (!FlushStateToDisk(state, FLUSH_STATE_ALWAYS)) { + return false; + } + + return true; +} + void UnloadBlockIndex() { LOCK(cs_main); diff --git a/src/main.h b/src/main.h index 317470e3c8694..84a6044bc9dde 100644 --- a/src/main.h +++ b/src/main.h @@ -459,6 +459,9 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, /** Check whether witness commitments are required for block. */ bool IsWitnessEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& params); +/** When there are blocks in the active chain with missing data, rewind the chainstate and remove them from the block index */ +bool RewindBlockIndex(const CChainParams& params); + /** Update uncommitted block structures (currently: only the witness nonce). This is safe for submitted blocks. */ void UpdateUncommittedBlockStructures(CBlock& block, const CBlockIndex* pindexPrev, const Consensus::Params& consensusParams); From af87a67eff8ce7bf2c7fb29f760da9fc610f162f Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 22 Jun 2016 15:39:26 +0200 Subject: [PATCH 0547/1802] Do not use compact blocks when segwit is enabled --- src/main.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index ec43a667017e3..d1ba70313e3b3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -473,6 +473,10 @@ void UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) { } void MaybeSetPeerAsAnnouncingHeaderAndIDs(const CNodeState* nodestate, CNode* pfrom) { + if (nLocalServices & NODE_WITNESS) { + // Don't ever request compact blocks when segwit is enabled. + return; + } if (nodestate->fProvidesHeaderAndIDs) { BOOST_FOREACH(const NodeId nodeid, lNodesAnnouncingHeaderAndIDs) if (nodeid == pfrom->GetId()) @@ -5286,7 +5290,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER && (!IsWitnessEnabled(chainActive.Tip(), chainparams.GetConsensus()) || State(pfrom->GetId())->fHaveWitness)) { inv.type |= nFetchFlags; - if (nodestate->fProvidesHeaderAndIDs) + if (nodestate->fProvidesHeaderAndIDs && !(nLocalServices & NODE_WITNESS)) vToFetch.push_back(CInv(MSG_CMPCT_BLOCK, inv.hash)); else vToFetch.push_back(inv); @@ -5905,7 +5909,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, pindexLast->GetBlockHash().ToString(), pindexLast->nHeight); } if (vGetData.size() > 0) { - if (nodestate->fProvidesHeaderAndIDs && vGetData.size() == 1 && mapBlocksInFlight.size() == 1 && pindexLast->pprev->IsValid(BLOCK_VALID_CHAIN)) { + if (nodestate->fProvidesHeaderAndIDs && vGetData.size() == 1 && mapBlocksInFlight.size() == 1 && pindexLast->pprev->IsValid(BLOCK_VALID_CHAIN) && !(nLocalServices & NODE_WITNESS)) { // We seem to be rather well-synced, so it appears pfrom was the first to provide us // with this block! Let's get them to announce using compact blocks in the future. MaybeSetPeerAsAnnouncingHeaderAndIDs(nodestate, pfrom); From 9757b57c25c67de611b8f5d0a19f409c2e8753a6 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 31 Mar 2016 14:43:39 +0200 Subject: [PATCH 0548/1802] --- [SEGWIT] begin: wallet --- From 605e8473a7ddca13b24a4020c7bd630aa5d374e2 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 31 Mar 2016 14:54:58 +0200 Subject: [PATCH 0549/1802] BIP143: Signing logic --- src/bitcoin-tx.cpp | 28 +++- src/rpc/rawtransaction.cpp | 17 +- src/script/ismine.cpp | 19 ++- src/script/sign.cpp | 279 +++++++++++++++++++++++---------- src/script/sign.h | 34 ++-- src/script/standard.cpp | 41 +++++ src/script/standard.h | 3 + src/test/DoS_tests.cpp | 4 +- src/test/multisig_tests.cpp | 2 +- src/test/script_P2SH_tests.cpp | 11 +- src/test/script_tests.cpp | 100 ++++++------ src/wallet/wallet.cpp | 10 +- 12 files changed, 382 insertions(+), 166 deletions(-) diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index e77aa6c72eea2..f457ea2bce4d7 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -363,6 +363,18 @@ vector ParseHexUO(map& o, string strKey) return ParseHexUV(o[strKey], strKey); } +static CAmount AmountFromValue(const UniValue& value) +{ + if (!value.isNum() && !value.isStr()) + throw runtime_error("Amount is not a number or string"); + CAmount amount; + if (!ParseFixedPoint(value.getValStr(), 8, &amount)) + throw runtime_error("Invalid amount"); + if (!MoneyRange(amount)) + throw runtime_error("Amount out of range"); + return amount; +} + static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) { int nHashType = SIGHASH_ALL; @@ -434,7 +446,10 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) if ((unsigned int)nOut >= coins->vout.size()) coins->vout.resize(nOut+1); coins->vout[nOut].scriptPubKey = scriptPubKey; - coins->vout[nOut].nValue = 0; // we don't know the actual output value + coins->vout[nOut].nValue = 0; + if (prevOut.exists("amount")) { + coins->vout[nOut].nValue = AmountFromValue(prevOut["amount"]); + } } // if redeemScript given and private keys given, @@ -464,15 +479,16 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) const CScript& prevPubKey = coins->vout[txin.prevout.n].scriptPubKey; const CAmount& amount = coins->vout[txin.prevout.n].nValue; - txin.scriptSig.clear(); + SignatureData sigdata; // Only sign SIGHASH_SINGLE if there's a corresponding output: if (!fHashSingle || (i < mergedTx.vout.size())) - SignSignature(keystore, prevPubKey, mergedTx, i, nHashType); + ProduceSignature(MutableTransactionSignatureCreator(&keystore, &mergedTx, i, amount, nHashType), prevPubKey, sigdata); // ... and merge in other signatures: - BOOST_FOREACH(const CTransaction& txv, txVariants) { - txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, amount, txin.scriptSig, txv.vin[i].scriptSig); - } + BOOST_FOREACH(const CTransaction& txv, txVariants) + sigdata = CombineSignatures(prevPubKey, MutableTransactionSignatureChecker(&mergedTx, i, amount), sigdata, DataFromTransaction(txv, i)); + UpdateTransaction(mergedTx, i, sigdata); + if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx.wit.vtxinwit.size() > i ? &mergedTx.wit.vtxinwit[i].scriptWitness : NULL, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i, amount))) fComplete = false; } diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index b36179943f4db..56ba805b1f6ab 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -592,7 +592,8 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp) " \"txid\":\"id\", (string, required) The transaction id\n" " \"vout\":n, (numeric, required) The output number\n" " \"scriptPubKey\": \"hex\", (string, required) script key\n" - " \"redeemScript\": \"hex\" (string, required for P2SH) redeem script\n" + " \"redeemScript\": \"hex\", (string, required for P2SH) redeem script\n" + " \"amount\": value (numeric, required) The amount spent\n" " }\n" " ,...\n" " ]\n" @@ -735,7 +736,10 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp) if ((unsigned int)nOut >= coins->vout.size()) coins->vout.resize(nOut+1); coins->vout[nOut].scriptPubKey = scriptPubKey; - coins->vout[nOut].nValue = 0; // we don't know the actual output value + coins->vout[nOut].nValue = 0; + if (prevOut.exists("amount")) { + coins->vout[nOut].nValue = AmountFromValue(find_value(prevOut, "amount")); + } } // if redeemScript given and not using the local wallet (private keys @@ -801,15 +805,18 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp) const CScript& prevPubKey = coins->vout[txin.prevout.n].scriptPubKey; const CAmount& amount = coins->vout[txin.prevout.n].nValue; - txin.scriptSig.clear(); + SignatureData sigdata; // Only sign SIGHASH_SINGLE if there's a corresponding output: if (!fHashSingle || (i < mergedTx.vout.size())) - SignSignature(keystore, prevPubKey, mergedTx, i, nHashType); + ProduceSignature(MutableTransactionSignatureCreator(&keystore, &mergedTx, i, amount, nHashType), prevPubKey, sigdata); // ... and merge in other signatures: BOOST_FOREACH(const CMutableTransaction& txv, txVariants) { - txin.scriptSig = CombineSignatures(prevPubKey, txConst, i, amount, txin.scriptSig, txv.vin[i].scriptSig); + sigdata = CombineSignatures(prevPubKey, TransactionSignatureChecker(&txConst, i, amount), sigdata, DataFromTransaction(txv, i)); } + + UpdateTransaction(mergedTx, i, sigdata); + ScriptError serror = SCRIPT_ERR_OK; if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx.wit.vtxinwit.size() > i ? &mergedTx.wit.vtxinwit[i].scriptWitness : NULL, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount), &serror)) { TxInErrorToJSON(txin, vErrors, ScriptErrorString(serror)); diff --git a/src/script/ismine.cpp b/src/script/ismine.cpp index 535c56b57a06a..0bf180341e4cc 100644 --- a/src/script/ismine.cpp +++ b/src/script/ismine.cpp @@ -57,6 +57,7 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) return ISMINE_SPENDABLE; break; case TX_PUBKEYHASH: + case TX_WITNESS_V0_KEYHASH: keyID = CKeyID(uint160(vSolutions[0])); if (keystore.HaveKey(keyID)) return ISMINE_SPENDABLE; @@ -72,6 +73,20 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) } break; } + case TX_WITNESS_V0_SCRIPTHASH: + { + uint160 hash; + CRIPEMD160().Write(&vSolutions[0][0], vSolutions[0].size()).Finalize(hash.begin()); + CScriptID scriptID = CScriptID(hash); + CScript subscript; + if (keystore.GetCScript(scriptID, subscript)) { + isminetype ret = IsMine(keystore, subscript); + if (ret == ISMINE_SPENDABLE) + return ret; + } + break; + } + case TX_MULTISIG: { // Only consider transactions "mine" if we own ALL the @@ -88,8 +103,8 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) if (keystore.HaveWatchOnly(scriptPubKey)) { // TODO: This could be optimized some by doing some work after the above solver - CScript scriptSig; - return ProduceSignature(DummySignatureCreator(&keystore), scriptPubKey, scriptSig) ? ISMINE_WATCH_SOLVABLE : ISMINE_WATCH_UNSOLVABLE; + SignatureData sigs; + return ProduceSignature(DummySignatureCreator(&keystore), scriptPubKey, sigs) ? ISMINE_WATCH_SOLVABLE : ISMINE_WATCH_UNSOLVABLE; } return ISMINE_NO; } diff --git a/src/script/sign.cpp b/src/script/sign.cpp index 83bb0cfa29f58..87f38d9c72565 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -20,29 +20,29 @@ typedef std::vector valtype; TransactionSignatureCreator::TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn) : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), amount(amountIn), checker(txTo, nIn, amountIn) {} -bool TransactionSignatureCreator::CreateSig(std::vector& vchSig, const CKeyID& address, const CScript& scriptCode) const +bool TransactionSignatureCreator::CreateSig(std::vector& vchSig, const CKeyID& address, const CScript& scriptCode, SigVersion sigversion) const { CKey key; if (!keystore->GetKey(address, key)) return false; - uint256 hash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, SIGVERSION_BASE); + uint256 hash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion); if (!key.Sign(hash, vchSig)) return false; vchSig.push_back((unsigned char)nHashType); return true; } -static bool Sign1(const CKeyID& address, const BaseSignatureCreator& creator, const CScript& scriptCode, CScript& scriptSigRet) +static bool Sign1(const CKeyID& address, const BaseSignatureCreator& creator, const CScript& scriptCode, std::vector& ret, SigVersion sigversion) { vector vchSig; - if (!creator.CreateSig(vchSig, address, scriptCode)) + if (!creator.CreateSig(vchSig, address, scriptCode, sigversion)) return false; - scriptSigRet << vchSig; + ret.push_back(vchSig); return true; } -static bool SignN(const vector& multisigdata, const BaseSignatureCreator& creator, const CScript& scriptCode, CScript& scriptSigRet) +static bool SignN(const vector& multisigdata, const BaseSignatureCreator& creator, const CScript& scriptCode, std::vector& ret, SigVersion sigversion) { int nSigned = 0; int nRequired = multisigdata.front()[0]; @@ -50,7 +50,7 @@ static bool SignN(const vector& multisigdata, const BaseSignatureCreato { const valtype& pubkey = multisigdata[i]; CKeyID keyID = CPubKey(pubkey).GetID(); - if (Sign1(keyID, creator, scriptCode, scriptSigRet)) + if (Sign1(keyID, creator, scriptCode, ret, sigversion)) ++nSigned; } return nSigned==nRequired; @@ -63,9 +63,11 @@ static bool SignN(const vector& multisigdata, const BaseSignatureCreato * Returns false if scriptPubKey could not be completely satisfied. */ static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptPubKey, - CScript& scriptSigRet, txnouttype& whichTypeRet) + std::vector& ret, txnouttype& whichTypeRet, SigVersion sigversion) { - scriptSigRet.clear(); + CScript scriptRet; + uint160 h160; + ret.clear(); vector vSolutions; if (!Solver(scriptPubKey, whichTypeRet, vSolutions)) @@ -79,62 +81,142 @@ static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptP return false; case TX_PUBKEY: keyID = CPubKey(vSolutions[0]).GetID(); - return Sign1(keyID, creator, scriptPubKey, scriptSigRet); + return Sign1(keyID, creator, scriptPubKey, ret, sigversion); case TX_PUBKEYHASH: keyID = CKeyID(uint160(vSolutions[0])); - if (!Sign1(keyID, creator, scriptPubKey, scriptSigRet)) + if (!Sign1(keyID, creator, scriptPubKey, ret, sigversion)) return false; else { CPubKey vch; creator.KeyStore().GetPubKey(keyID, vch); - scriptSigRet << ToByteVector(vch); + ret.push_back(ToByteVector(vch)); } return true; case TX_SCRIPTHASH: - return creator.KeyStore().GetCScript(uint160(vSolutions[0]), scriptSigRet); + if (creator.KeyStore().GetCScript(uint160(vSolutions[0]), scriptRet)) { + ret.push_back(std::vector(scriptRet.begin(), scriptRet.end())); + return true; + } + return false; case TX_MULTISIG: - scriptSigRet << OP_0; // workaround CHECKMULTISIG bug - return (SignN(vSolutions, creator, scriptPubKey, scriptSigRet)); + ret.push_back(valtype()); // workaround CHECKMULTISIG bug + return (SignN(vSolutions, creator, scriptPubKey, ret, sigversion)); + + case TX_WITNESS_V0_KEYHASH: + ret.push_back(vSolutions[0]); + return true; + + case TX_WITNESS_V0_SCRIPTHASH: + CRIPEMD160().Write(&vSolutions[0][0], vSolutions[0].size()).Finalize(h160.begin()); + if (creator.KeyStore().GetCScript(h160, scriptRet)) { + ret.push_back(std::vector(scriptRet.begin(), scriptRet.end())); + return true; + } + return false; + + default: + return false; } - return false; } -bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& fromPubKey, CScript& scriptSig) +static CScript PushAll(const vector& values) { + CScript result; + BOOST_FOREACH(const valtype& v, values) { + if (v.size() == 0) { + result << OP_0; + } else if (v.size() == 1 && v[0] >= 1 && v[0] <= 16) { + result << CScript::EncodeOP_N(v[0]); + } else { + result << v; + } + } + return result; +} + +bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& fromPubKey, SignatureData& sigdata) +{ + CScript script = fromPubKey; + bool solved = true; + std::vector result; txnouttype whichType; - if (!SignStep(creator, fromPubKey, scriptSig, whichType)) - return false; + solved = SignStep(creator, script, result, whichType, SIGVERSION_BASE); + bool P2SH = false; + CScript subscript; + sigdata.scriptWitness.stack.clear(); - if (whichType == TX_SCRIPTHASH) + if (solved && whichType == TX_SCRIPTHASH) { - // Solver returns the subscript that need to be evaluated; + // Solver returns the subscript that needs to be evaluated; // the final scriptSig is the signatures from that // and then the serialized subscript: - CScript subscript = scriptSig; + script = subscript = CScript(result[0].begin(), result[0].end()); + solved = solved && SignStep(creator, script, result, whichType, SIGVERSION_BASE) && whichType != TX_SCRIPTHASH; + P2SH = true; + } + if (solved && whichType == TX_WITNESS_V0_KEYHASH) + { + CScript witnessscript; + witnessscript << OP_DUP << OP_HASH160 << ToByteVector(result[0]) << OP_EQUALVERIFY << OP_CHECKSIG; txnouttype subType; - bool fSolved = - SignStep(creator, subscript, scriptSig, subType) && subType != TX_SCRIPTHASH; - // Append serialized subscript whether or not it is completely signed: - scriptSig << valtype(subscript.begin(), subscript.end()); - if (!fSolved) return false; + solved = solved && SignStep(creator, witnessscript, result, subType, SIGVERSION_WITNESS_V0); + sigdata.scriptWitness.stack = result; + result.clear(); + } + else if (solved && whichType == TX_WITNESS_V0_SCRIPTHASH) + { + CScript witnessscript(result[0].begin(), result[0].end()); + txnouttype subType; + solved = solved && SignStep(creator, witnessscript, result, subType, SIGVERSION_WITNESS_V0) && subType != TX_SCRIPTHASH && subType != TX_WITNESS_V0_SCRIPTHASH && subType != TX_WITNESS_V0_KEYHASH; + result.push_back(std::vector(witnessscript.begin(), witnessscript.end())); + sigdata.scriptWitness.stack = result; + result.clear(); } + if (P2SH) { + result.push_back(std::vector(subscript.begin(), subscript.end())); + } + sigdata.scriptSig = PushAll(result); + // Test solution - return VerifyScript(scriptSig, fromPubKey, NULL, STANDARD_SCRIPT_VERIFY_FLAGS, creator.Checker()); + return solved && VerifyScript(sigdata.scriptSig, fromPubKey, &sigdata.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, creator.Checker()); +} + +SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nIn) +{ + SignatureData data; + assert(tx.vin.size() > nIn); + data.scriptSig = tx.vin[nIn].scriptSig; + if (tx.wit.vtxinwit.size() > nIn) { + data.scriptWitness = tx.wit.vtxinwit[nIn].scriptWitness; + } + return data; +} + +void UpdateTransaction(CMutableTransaction& tx, unsigned int nIn, const SignatureData& data) +{ + assert(tx.vin.size() > nIn); + tx.vin[nIn].scriptSig = data.scriptSig; + if (!data.scriptWitness.IsNull() || tx.wit.vtxinwit.size() > nIn) { + tx.wit.vtxinwit.resize(tx.vin.size()); + tx.wit.vtxinwit[nIn].scriptWitness = data.scriptWitness; + } } -bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, int nHashType) +bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType) { assert(nIn < txTo.vin.size()); - CTxIn& txin = txTo.vin[nIn]; CTransaction txToConst(txTo); - TransactionSignatureCreator creator(&keystore, &txToConst, nIn, nHashType); + TransactionSignatureCreator creator(&keystore, &txToConst, nIn, amount, nHashType); - return ProduceSignature(creator, fromPubKey, txin.scriptSig); + SignatureData sigdata; + bool ret = ProduceSignature(creator, fromPubKey, sigdata); + UpdateTransaction(txTo, nIn, sigdata); + return ret; } bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType) @@ -144,20 +226,12 @@ bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CMutab assert(txin.prevout.n < txFrom.vout.size()); const CTxOut& txout = txFrom.vout[txin.prevout.n]; - return SignSignature(keystore, txout.scriptPubKey, txTo, nIn, nHashType); -} - -static CScript PushAll(const vector& values) -{ - CScript result; - BOOST_FOREACH(const valtype& v, values) - result << v; - return result; + return SignSignature(keystore, txout.scriptPubKey, txTo, nIn, txout.nValue, nHashType); } -static CScript CombineMultisig(const CScript& scriptPubKey, const BaseSignatureChecker& checker, +static vector CombineMultisig(const CScript& scriptPubKey, const BaseSignatureChecker& checker, const vector& vSolutions, - const vector& sigs1, const vector& sigs2) + const vector& sigs1, const vector& sigs2, SigVersion sigversion) { // Combine all the signatures we've got: set allsigs; @@ -185,7 +259,7 @@ static CScript CombineMultisig(const CScript& scriptPubKey, const BaseSignatureC if (sigs.count(pubkey)) continue; // Already got a sig for this pubkey - if (checker.CheckSig(sig, pubkey, scriptPubKey, SIGVERSION_BASE)) + if (checker.CheckSig(sig, pubkey, scriptPubKey, sigversion)) { sigs[pubkey] = sig; break; @@ -194,87 +268,126 @@ static CScript CombineMultisig(const CScript& scriptPubKey, const BaseSignatureC } // Now build a merged CScript: unsigned int nSigsHave = 0; - CScript result; result << OP_0; // pop-one-too-many workaround + std::vector result; result.push_back(valtype()); // pop-one-too-many workaround for (unsigned int i = 0; i < nPubKeys && nSigsHave < nSigsRequired; i++) { if (sigs.count(vSolutions[i+1])) { - result << sigs[vSolutions[i+1]]; + result.push_back(sigs[vSolutions[i+1]]); ++nSigsHave; } } // Fill any missing with OP_0: for (unsigned int i = nSigsHave; i < nSigsRequired; i++) - result << OP_0; + result.push_back(valtype()); return result; } -static CScript CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker, +namespace +{ +struct Stacks +{ + std::vector script; + std::vector witness; + + Stacks() {} + explicit Stacks(const std::vector& scriptSigStack_) : script(scriptSigStack_), witness() {} + explicit Stacks(const SignatureData& data) : witness(data.scriptWitness.stack) { + EvalScript(script, data.scriptSig, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), SIGVERSION_BASE); + } + + SignatureData Output() const { + SignatureData result; + result.scriptSig = PushAll(script); + result.scriptWitness.stack = witness; + return result; + } +}; +} + +static Stacks CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker, const txnouttype txType, const vector& vSolutions, - vector& sigs1, vector& sigs2) + Stacks sigs1, Stacks sigs2, SigVersion sigversion) { switch (txType) { case TX_NONSTANDARD: case TX_NULL_DATA: // Don't know anything about this, assume bigger one is correct: - if (sigs1.size() >= sigs2.size()) - return PushAll(sigs1); - return PushAll(sigs2); + if (sigs1.script.size() >= sigs2.script.size()) + return sigs1; + return sigs2; case TX_PUBKEY: case TX_PUBKEYHASH: // Signatures are bigger than placeholders or empty scripts: - if (sigs1.empty() || sigs1[0].empty()) - return PushAll(sigs2); - return PushAll(sigs1); + if (sigs1.script.empty() || sigs1.script[0].empty()) + return sigs2; + return sigs1; + case TX_WITNESS_V0_KEYHASH: + // Signatures are bigger than placeholders or empty scripts: + if (sigs1.witness.empty() || sigs1.witness[0].empty()) + return sigs2; + return sigs1; case TX_SCRIPTHASH: - if (sigs1.empty() || sigs1.back().empty()) - return PushAll(sigs2); - else if (sigs2.empty() || sigs2.back().empty()) - return PushAll(sigs1); + if (sigs1.script.empty() || sigs1.script.back().empty()) + return sigs2; + else if (sigs2.script.empty() || sigs2.script.back().empty()) + return sigs1; else { // Recur to combine: - valtype spk = sigs1.back(); + valtype spk = sigs1.script.back(); CScript pubKey2(spk.begin(), spk.end()); txnouttype txType2; vector > vSolutions2; Solver(pubKey2, txType2, vSolutions2); - sigs1.pop_back(); - sigs2.pop_back(); - CScript result = CombineSignatures(pubKey2, checker, txType2, vSolutions2, sigs1, sigs2); - result << spk; + sigs1.script.pop_back(); + sigs2.script.pop_back(); + Stacks result = CombineSignatures(pubKey2, checker, txType2, vSolutions2, sigs1, sigs2, sigversion); + result.script.push_back(spk); return result; } case TX_MULTISIG: - return CombineMultisig(scriptPubKey, checker, vSolutions, sigs1, sigs2); + return Stacks(CombineMultisig(scriptPubKey, checker, vSolutions, sigs1.script, sigs2.script, sigversion)); + case TX_WITNESS_V0_SCRIPTHASH: + if (sigs1.witness.empty() || sigs1.witness.back().empty()) + return sigs2; + else if (sigs2.witness.empty() || sigs2.witness.back().empty()) + return sigs1; + else + { + // Recur to combine: + CScript pubKey2(sigs1.witness.back().begin(), sigs1.witness.back().end()); + txnouttype txType2; + vector vSolutions2; + Solver(pubKey2, txType2, vSolutions2); + sigs1.witness.pop_back(); + sigs1.script = sigs1.witness; + sigs1.witness.clear(); + sigs2.witness.pop_back(); + sigs2.script = sigs2.witness; + sigs2.witness.clear(); + Stacks result = CombineSignatures(pubKey2, checker, txType2, vSolutions2, sigs1, sigs2, SIGVERSION_WITNESS_V0); + result.witness = result.script; + result.script.clear(); + result.witness.push_back(valtype(pubKey2.begin(), pubKey2.end())); + return result; + } + default: + return Stacks(); } - - return CScript(); } -CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, const CAmount& amount, - const CScript& scriptSig1, const CScript& scriptSig2) -{ - TransactionSignatureChecker checker(&txTo, nIn, amount); - return CombineSignatures(scriptPubKey, checker, scriptSig1, scriptSig2); -} - -CScript CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker, - const CScript& scriptSig1, const CScript& scriptSig2) +SignatureData CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker, + const SignatureData& scriptSig1, const SignatureData& scriptSig2) { txnouttype txType; vector > vSolutions; Solver(scriptPubKey, txType, vSolutions); - vector stack1; - EvalScript(stack1, scriptSig1, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), SIGVERSION_BASE); - vector stack2; - EvalScript(stack2, scriptSig2, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), SIGVERSION_BASE); - - return CombineSignatures(scriptPubKey, checker, txType, vSolutions, stack1, stack2); + return CombineSignatures(scriptPubKey, checker, txType, vSolutions, Stacks(scriptSig1), Stacks(scriptSig2), SIGVERSION_BASE).Output(); } namespace { @@ -297,7 +410,7 @@ const BaseSignatureChecker& DummySignatureCreator::Checker() const return dummyChecker; } -bool DummySignatureCreator::CreateSig(std::vector& vchSig, const CKeyID& keyid, const CScript& scriptCode) const +bool DummySignatureCreator::CreateSig(std::vector& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const { // Create a dummy signature that is a valid DER-encoding vchSig.assign(72, '\000'); diff --git a/src/script/sign.h b/src/script/sign.h index f54511f7a67f5..6404b4523ecaa 100644 --- a/src/script/sign.h +++ b/src/script/sign.h @@ -27,7 +27,7 @@ class BaseSignatureCreator { virtual const BaseSignatureChecker& Checker() const =0; /** Create a singular (non-script) signature. */ - virtual bool CreateSig(std::vector& vchSig, const CKeyID& keyid, const CScript& scriptCode) const =0; + virtual bool CreateSig(std::vector& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const =0; }; /** A signature creator for transactions. */ @@ -41,7 +41,14 @@ class TransactionSignatureCreator : public BaseSignatureCreator { public: TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn=SIGHASH_ALL); const BaseSignatureChecker& Checker() const { return checker; } - bool CreateSig(std::vector& vchSig, const CKeyID& keyid, const CScript& scriptCode) const; + bool CreateSig(std::vector& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const; +}; + +class MutableTransactionSignatureCreator : public TransactionSignatureCreator { + CTransaction tx; + +public: + MutableTransactionSignatureCreator(const CKeyStore* keystoreIn, const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amount, int nHashTypeIn) : TransactionSignatureCreator(keystoreIn, &tx, nInIn, amount, nHashTypeIn), tx(*txToIn) {} }; /** A signature creator that just produces 72-byte empty signatyres. */ @@ -49,20 +56,29 @@ class DummySignatureCreator : public BaseSignatureCreator { public: DummySignatureCreator(const CKeyStore* keystoreIn) : BaseSignatureCreator(keystoreIn) {} const BaseSignatureChecker& Checker() const; - bool CreateSig(std::vector& vchSig, const CKeyID& keyid, const CScript& scriptCode) const; + bool CreateSig(std::vector& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const; +}; + +struct SignatureData { + CScript scriptSig; + CScriptWitness scriptWitness; + + SignatureData() {} + explicit SignatureData(const CScript& script) : scriptSig(script) {} }; /** Produce a script signature using a generic signature creator. */ -bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& scriptPubKey, CScript& scriptSig); +bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& scriptPubKey, SignatureData& sigdata); /** Produce a script signature for a transaction. */ -bool SignSignature(const CKeyStore& keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL); -bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL); +bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType); +bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType); /** Combine two script signatures using a generic signature checker, intelligently, possibly with OP_0 placeholders. */ -CScript CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker, const CScript& scriptSig1, const CScript& scriptSig2); +SignatureData CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker, const SignatureData& scriptSig1, const SignatureData& scriptSig2); -/** Combine two script signatures on transactions. */ -CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, const CAmount& amount, const CScript& scriptSig1, const CScript& scriptSig2); +/** Extract signature data from a transaction, and insert it. */ +SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nIn); +void UpdateTransaction(CMutableTransaction& tx, unsigned int nIn, const SignatureData& data); #endif // BITCOIN_SCRIPT_SIGN_H diff --git a/src/script/standard.cpp b/src/script/standard.cpp index 67b6af327ae37..bb178f49fe9f2 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -31,6 +31,8 @@ const char* GetTxnOutputType(txnouttype t) case TX_SCRIPTHASH: return "scripthash"; case TX_MULTISIG: return "multisig"; case TX_NULL_DATA: return "nulldata"; + case TX_WITNESS_V0_KEYHASH: return "witness_v0_keyhash"; + case TX_WITNESS_V0_SCRIPTHASH: return "witness_v0_scripthash"; } return NULL; } @@ -66,6 +68,22 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector witnessprogram; + if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) { + if (witnessversion == 0 && witnessprogram.size() == 20) { + typeRet = TX_WITNESS_V0_KEYHASH; + vSolutionsRet.push_back(witnessprogram); + return true; + } + if (witnessversion == 0 && witnessprogram.size() == 32) { + typeRet = TX_WITNESS_V0_SCRIPTHASH; + vSolutionsRet.push_back(witnessprogram); + return true; + } + return false; + } + // Provably prunable, data-carrying output // // So long as script passes the IsUnspendable() test and all but the first @@ -282,3 +300,26 @@ CScript GetScriptForMultisig(int nRequired, const std::vector& keys) script << CScript::EncodeOP_N(keys.size()) << OP_CHECKMULTISIG; return script; } + +CScript GetScriptForWitness(const CScript& redeemscript) +{ + CScript ret; + + txnouttype typ; + std::vector > vSolutions; + if (Solver(redeemscript, typ, vSolutions)) { + if (typ == TX_PUBKEY) { + unsigned char h160[20]; + CHash160().Write(&vSolutions[0][0], vSolutions[0].size()).Finalize(h160); + ret << OP_0 << std::vector(&h160[0], &h160[20]); + return ret; + } else if (typ == TX_PUBKEYHASH) { + ret << OP_0 << vSolutions[0]; + return ret; + } + } + uint256 hash; + CSHA256().Write(&redeemscript[0], redeemscript.size()).Finalize(hash.begin()); + ret << OP_0 << ToByteVector(hash); + return ret; +} diff --git a/src/script/standard.h b/src/script/standard.h index f348da8e1982b..72aaea0b7bebe 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -51,6 +51,8 @@ enum txnouttype TX_SCRIPTHASH, TX_MULTISIG, TX_NULL_DATA, + TX_WITNESS_V0_SCRIPTHASH, + TX_WITNESS_V0_KEYHASH, }; class CNoDestination { @@ -77,5 +79,6 @@ bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std:: CScript GetScriptForDestination(const CTxDestination& dest); CScript GetScriptForRawPubKey(const CPubKey& pubkey); CScript GetScriptForMultisig(int nRequired, const std::vector& keys); +CScript GetScriptForWitness(const CScript& redeemscript); #endif // BITCOIN_SCRIPT_STANDARD_H diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index 93f7ae09da741..a8c5f95ace4af 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -148,7 +148,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) tx.vout.resize(1); tx.vout[0].nValue = 1*CENT; tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID()); - SignSignature(keystore, txPrev, tx, 0); + SignSignature(keystore, txPrev, tx, 0, SIGHASH_ALL); AddOrphanTx(tx, i); } @@ -168,7 +168,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) tx.vin[j].prevout.n = j; tx.vin[j].prevout.hash = txPrev.GetHash(); } - SignSignature(keystore, txPrev, tx, 0); + SignSignature(keystore, txPrev, tx, 0, SIGHASH_ALL); // Re-use same signature for other inputs // (they don't have to be valid for this test) for (unsigned int j = 1; j < tx.vin.size(); j++) diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp index 876b90e4b99ed..581b0cee1ec87 100644 --- a/src/test/multisig_tests.cpp +++ b/src/test/multisig_tests.cpp @@ -303,7 +303,7 @@ BOOST_AUTO_TEST_CASE(multisig_Sign) for (int i = 0; i < 3; i++) { - BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i)); + BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i)); } } diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp index 62deb736aad22..5224b57ca4479 100644 --- a/src/test/script_P2SH_tests.cpp +++ b/src/test/script_P2SH_tests.cpp @@ -2,6 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "core_io.h" #include "key.h" #include "keystore.h" #include "main.h" @@ -102,7 +103,7 @@ BOOST_AUTO_TEST_CASE(sign) } for (int i = 0; i < 8; i++) { - BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i)); + BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i)); } // All of the above should be OK, and the txTos have valid signatures // Check to make sure signature verification fails if we use the wrong ScriptSig: @@ -197,7 +198,7 @@ BOOST_AUTO_TEST_CASE(set) } for (int i = 0; i < 4; i++) { - BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i)); + BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i)); BOOST_CHECK_MESSAGE(IsStandardTx(txTo[i], reason), strprintf("txTo[%d].IsStandard", i)); } } @@ -326,9 +327,9 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard) txTo.vin[i].prevout.n = i; txTo.vin[i].prevout.hash = txFrom.GetHash(); } - BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 0)); - BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 1)); - BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 2)); + BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL)); + BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 1, SIGHASH_ALL)); + BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 2, SIGHASH_ALL)); // SignSignature doesn't know how to sign these. We're // not testing validating signatures, so just create // dummy signatures that DO include the correct P2SH scripts: diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 7fd7614e2cfc0..1d69194c3e89c 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -152,16 +152,16 @@ void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, int flags, co flags |= SCRIPT_VERIFY_WITNESS; } ScriptError err; - CMutableTransaction tx = BuildSpendingTransaction(scriptSig, BuildCreditingTransaction(scriptPubKey)); + CMutableTransaction txCredit = BuildCreditingTransaction(scriptPubKey); + CMutableTransaction tx = BuildSpendingTransaction(scriptSig, txCredit); CMutableTransaction tx2 = tx; - static const CAmount amountZero = 0; - BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, NULL, flags, MutableTransactionSignatureChecker(&tx, 0, amountZero), &err) == expect, message); + BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, NULL, flags, MutableTransactionSignatureChecker(&tx, 0, txCredit.vout[0].nValue), &err) == expect, message); BOOST_CHECK_MESSAGE(err == scriptError, std::string(FormatScriptError(err)) + " where " + std::string(FormatScriptError((ScriptError_t)scriptError)) + " expected: " + message); #if defined(HAVE_CONSENSUS_LIB) CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); stream << tx2; if (flags & bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS) { - BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script_with_amount(begin_ptr(scriptPubKey), scriptPubKey.size(), amountZero, (const unsigned char*)&stream[0], stream.size(), 0, flags, NULL) == expect, message); + BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script_with_amount(begin_ptr(scriptPubKey), scriptPubKey.size(), txCredit.vout[0].nValue, (const unsigned char*)&stream[0], stream.size(), 0, flags, NULL) == expect, message); } else { BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script_with_amount(begin_ptr(scriptPubKey), scriptPubKey.size(), 0, (const unsigned char*)&stream[0], stream.size(), 0, flags, NULL) == expect, message); BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script(begin_ptr(scriptPubKey), scriptPubKey.size(), (const unsigned char*)&stream[0], stream.size(), 0, flags, NULL) == expect,message); @@ -896,7 +896,7 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23) BOOST_AUTO_TEST_CASE(script_combineSigs) { // Test the CombineSignatures function - CAmount amount; + CAmount amount = 0; CBasicKeyStore keystore; vector keys; vector pubkeys; @@ -914,50 +914,50 @@ BOOST_AUTO_TEST_CASE(script_combineSigs) CScript& scriptPubKey = txFrom.vout[0].scriptPubKey; CScript& scriptSig = txTo.vin[0].scriptSig; - CScript empty; - CScript combined = CombineSignatures(scriptPubKey, txTo, 0, amount, empty, empty); - BOOST_CHECK(combined.empty()); + SignatureData empty; + SignatureData combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, empty); + BOOST_CHECK(combined.scriptSig.empty()); // Single signature case: - SignSignature(keystore, txFrom, txTo, 0); // changes scriptSig - combined = CombineSignatures(scriptPubKey, txTo, 0, amount, scriptSig, empty); - BOOST_CHECK(combined == scriptSig); - combined = CombineSignatures(scriptPubKey, txTo, 0, amount, empty, scriptSig); - BOOST_CHECK(combined == scriptSig); + SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL); // changes scriptSig + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty); + BOOST_CHECK(combined.scriptSig == scriptSig); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, SignatureData(scriptSig)); + BOOST_CHECK(combined.scriptSig == scriptSig); CScript scriptSigCopy = scriptSig; // Signing again will give a different, valid signature: - SignSignature(keystore, txFrom, txTo, 0); - combined = CombineSignatures(scriptPubKey, txTo, 0, amount, scriptSigCopy, scriptSig); - BOOST_CHECK(combined == scriptSigCopy || combined == scriptSig); + SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig)); + BOOST_CHECK(combined.scriptSig == scriptSigCopy || combined.scriptSig == scriptSig); // P2SH, single-signature case: CScript pkSingle; pkSingle << ToByteVector(keys[0].GetPubKey()) << OP_CHECKSIG; keystore.AddCScript(pkSingle); scriptPubKey = GetScriptForDestination(CScriptID(pkSingle)); - SignSignature(keystore, txFrom, txTo, 0); - combined = CombineSignatures(scriptPubKey, txTo, 0, amount, scriptSig, empty); - BOOST_CHECK(combined == scriptSig); - combined = CombineSignatures(scriptPubKey, txTo, 0, amount, empty, scriptSig); - BOOST_CHECK(combined == scriptSig); + SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty); + BOOST_CHECK(combined.scriptSig == scriptSig); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, SignatureData(scriptSig)); + BOOST_CHECK(combined.scriptSig == scriptSig); scriptSigCopy = scriptSig; - SignSignature(keystore, txFrom, txTo, 0); - combined = CombineSignatures(scriptPubKey, txTo, 0, amount, scriptSigCopy, scriptSig); - BOOST_CHECK(combined == scriptSigCopy || combined == scriptSig); + SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig)); + BOOST_CHECK(combined.scriptSig == scriptSigCopy || combined.scriptSig == scriptSig); // dummy scriptSigCopy with placeholder, should always choose non-placeholder: - scriptSigCopy = CScript() << OP_0 << vector(pkSingle.begin(), pkSingle.end()); - combined = CombineSignatures(scriptPubKey, txTo, 0, amount, scriptSigCopy, scriptSig); - BOOST_CHECK(combined == scriptSig); - combined = CombineSignatures(scriptPubKey, txTo, 0, amount, scriptSig, scriptSigCopy); - BOOST_CHECK(combined == scriptSig); + scriptSigCopy = CScript() << OP_0 << std::vector(pkSingle.begin(), pkSingle.end()); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig)); + BOOST_CHECK(combined.scriptSig == scriptSig); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), SignatureData(scriptSigCopy)); + BOOST_CHECK(combined.scriptSig == scriptSig); // Hardest case: Multisig 2-of-3 scriptPubKey = GetScriptForMultisig(2, pubkeys); keystore.AddCScript(scriptPubKey); - SignSignature(keystore, txFrom, txTo, 0); - combined = CombineSignatures(scriptPubKey, txTo, 0, amount, scriptSig, empty); - BOOST_CHECK(combined == scriptSig); - combined = CombineSignatures(scriptPubKey, txTo, 0, amount, empty, scriptSig); - BOOST_CHECK(combined == scriptSig); + SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty); + BOOST_CHECK(combined.scriptSig == scriptSig); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, SignatureData(scriptSig)); + BOOST_CHECK(combined.scriptSig == scriptSig); // A couple of partially-signed versions: vector sig1; @@ -985,22 +985,22 @@ BOOST_AUTO_TEST_CASE(script_combineSigs) CScript complete13 = CScript() << OP_0 << sig1 << sig3; CScript complete23 = CScript() << OP_0 << sig2 << sig3; - combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial1a, partial1b); - BOOST_CHECK(combined == partial1a); - combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial1a, partial2a); - BOOST_CHECK(combined == complete12); - combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial2a, partial1a); - BOOST_CHECK(combined == complete12); - combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial1b, partial2b); - BOOST_CHECK(combined == complete12); - combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial3b, partial1b); - BOOST_CHECK(combined == complete13); - combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial2a, partial3a); - BOOST_CHECK(combined == complete23); - combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial3b, partial2b); - BOOST_CHECK(combined == complete23); - combined = CombineSignatures(scriptPubKey, txTo, 0, amount, partial3b, partial3a); - BOOST_CHECK(combined == partial3c); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial1a), SignatureData(partial1b)); + BOOST_CHECK(combined.scriptSig == partial1a); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial1a), SignatureData(partial2a)); + BOOST_CHECK(combined.scriptSig == complete12); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial2a), SignatureData(partial1a)); + BOOST_CHECK(combined.scriptSig == complete12); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial1b), SignatureData(partial2b)); + BOOST_CHECK(combined.scriptSig == complete12); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial3b), SignatureData(partial1b)); + BOOST_CHECK(combined.scriptSig == complete13); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial2a), SignatureData(partial3a)); + BOOST_CHECK(combined.scriptSig == complete23); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial3b), SignatureData(partial2b)); + BOOST_CHECK(combined.scriptSig == complete23); + combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial3b), SignatureData(partial3a)); + BOOST_CHECK(combined.scriptSig == partial3c); } BOOST_AUTO_TEST_CASE(script_standard_push) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index babde1a02c3c4..b36c6f0259f68 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2334,17 +2334,20 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt { bool signSuccess; const CScript& scriptPubKey = coin.first->vout[coin.second].scriptPubKey; - CScript& scriptSigRes = txNew.vin[nIn].scriptSig; + SignatureData sigdata; if (sign) - signSuccess = ProduceSignature(TransactionSignatureCreator(this, &txNewConst, nIn, SIGHASH_ALL), scriptPubKey, scriptSigRes); + signSuccess = ProduceSignature(TransactionSignatureCreator(this, &txNewConst, nIn, coin.first->vout[coin.second].nValue, SIGHASH_ALL), scriptPubKey, sigdata); else - signSuccess = ProduceSignature(DummySignatureCreator(this), scriptPubKey, scriptSigRes); + signSuccess = ProduceSignature(DummySignatureCreator(this), scriptPubKey, sigdata); if (!signSuccess) { strFailReason = _("Signing transaction failed"); return false; + } else { + UpdateTransaction(txNew, nIn, sigdata); } + nIn++; } @@ -2354,6 +2357,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt if (!sign) { BOOST_FOREACH (CTxIn& vin, txNew.vin) vin.scriptSig = CScript(); + txNew.wit.SetNull(); } // Embed the constructed transaction data in wtxNew. From f4691ab3a9d4f3321afa024984c03fe6e10bfdbc Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 30 Dec 2015 01:13:08 +0100 Subject: [PATCH 0550/1802] [RPC] Add wallet support for witness transactions (using P2SH) Includes support for pushkeyhash wit v0 by Alex Morcos. --- src/rpc/misc.cpp | 38 +++++++++++++++++++ src/wallet/rpcwallet.cpp | 80 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 09f51857815e2..f2a29416e675d 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -312,6 +312,43 @@ UniValue createmultisig(const UniValue& params, bool fHelp) return result; } +UniValue createwitnessaddress(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 1) + { + string msg = "createwitnessaddress \"script\"\n" + "\nCreates a witness address for a particular script.\n" + "It returns a json object with the address and witness script.\n" + + "\nArguments:\n" + "1. \"script\" (string, required) A hex encoded script\n" + + "\nResult:\n" + "{\n" + " \"address\":\"multisigaddress\", (string) The value of the new address (P2SH of witness script).\n" + " \"witnessScript\":\"script\" (string) The string value of the hex-encoded witness script.\n" + "}\n" + ; + throw runtime_error(msg); + } + + if (!IsHex(params[0].get_str())) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Script must be hex-encoded"); + } + + std::vector code = ParseHex(params[0].get_str()); + CScript script(code.begin(), code.end()); + CScript witscript = GetScriptForWitness(script); + CScriptID witscriptid(witscript); + CBitcoinAddress address(witscriptid); + + UniValue result(UniValue::VOBJ); + result.push_back(Pair("address", address.ToString())); + result.push_back(Pair("witnessScript", HexStr(witscript.begin(), witscript.end()))); + + return result; +} + UniValue verifymessage(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 3) @@ -445,6 +482,7 @@ static const CRPCCommand commands[] = { "control", "getinfo", &getinfo, true }, /* uses wallet if enabled */ { "util", "validateaddress", &validateaddress, true }, /* uses wallet if enabled */ { "util", "createmultisig", &createmultisig, true }, + { "util", "createwitnessaddress", &createwitnessaddress, true }, { "util", "verifymessage", &verifymessage, true }, { "util", "signmessagewithprivkey", &signmessagewithprivkey, true }, diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 3666c37ac3eda..afbb9a1113f48 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -1011,6 +1011,85 @@ UniValue addmultisigaddress(const UniValue& params, bool fHelp) return CBitcoinAddress(innerID).ToString(); } +class Witnessifier : public boost::static_visitor +{ +public: + CScriptID result; + + bool operator()(const CNoDestination &dest) const { return false; } + + bool operator()(const CKeyID &keyID) { + CPubKey pubkey; + if (pwalletMain && pwalletMain->GetPubKey(keyID, pubkey)) { + CScript basescript; + basescript << ToByteVector(pubkey) << OP_CHECKSIG; + CScript witscript = GetScriptForWitness(basescript); + pwalletMain->AddCScript(witscript); + result = CScriptID(witscript); + return true; + } + return false; + } + + bool operator()(const CScriptID &scriptID) { + CScript subscript; + if (pwalletMain && pwalletMain->GetCScript(scriptID, subscript)) { + int witnessversion; + std::vector witprog; + if (subscript.IsWitnessProgram(witnessversion, witprog)) { + result = scriptID; + return true; + } + CScript witscript = GetScriptForWitness(subscript); + pwalletMain->AddCScript(witscript); + result = CScriptID(witscript); + return true; + } + return false; + } +}; + +UniValue addwitnessaddress(const UniValue& params, bool fHelp) +{ + if (!EnsureWalletIsAvailable(fHelp)) + return NullUniValue; + + if (fHelp || params.size() < 1 || params.size() > 1) + { + string msg = "addwitnessaddress \"address\"\n" + "\nAdd a witness address for a script (with pubkey or redeemscript known).\n" + "It returns the witness script.\n" + + "\nArguments:\n" + "1. \"address\" (string, required) An address known to the wallet\n" + + "\nResult:\n" + "\"witnessaddress\", (string) The value of the new address (P2SH of witness script).\n" + "}\n" + ; + throw runtime_error(msg); + } + + { + LOCK(cs_main); + if (!IsWitnessEnabled(chainActive.Tip(), Params().GetConsensus())) { + throw JSONRPCError(RPC_WALLET_ERROR, "Segregated witness not enabled on network"); + } + } + + CBitcoinAddress address(params[0].get_str()); + if (!address.IsValid()) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); + + Witnessifier w; + CTxDestination dest = address.Get(); + bool ret = boost::apply_visitor(w, dest); + if (!ret) { + throw JSONRPCError(RPC_WALLET_ERROR, "Public key or redeemscript not known to wallet"); + } + + return CBitcoinAddress(w.result).ToString(); +} struct tallyitem { @@ -2491,6 +2570,7 @@ static const CRPCCommand commands[] = { "hidden", "resendwallettransactions", &resendwallettransactions, true }, { "wallet", "abandontransaction", &abandontransaction, false }, { "wallet", "addmultisigaddress", &addmultisigaddress, true }, + { "wallet", "addwitnessaddress", &addwitnessaddress, true }, { "wallet", "backupwallet", &backupwallet, true }, { "wallet", "dumpprivkey", &dumpprivkey, true }, { "wallet", "dumpwallet", &dumpwallet, true }, From 745eb678ef5d52c74edcd9c322ebd1f3232a9310 Mon Sep 17 00:00:00 2001 From: NicolasDorier Date: Sun, 10 Apr 2016 15:59:23 +0900 Subject: [PATCH 0551/1802] [RPC] signrawtransaction can sign P2WSH --- src/bitcoin-tx.cpp | 2 +- src/rpc/rawtransaction.cpp | 4 ++-- src/script/script.cpp | 8 ++++++++ src/script/script.h | 1 + 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index f457ea2bce4d7..8e8ac47455cbe 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -454,7 +454,7 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) // if redeemScript given and private keys given, // add redeemScript to the tempKeystore so it can be signed: - if (fGivenKeys && scriptPubKey.IsPayToScriptHash() && + if (fGivenKeys && (scriptPubKey.IsPayToScriptHash() || scriptPubKey.IsPayToWitnessScriptHash()) && prevOut.exists("redeemScript")) { UniValue v = prevOut["redeemScript"]; vector rsData(ParseHexUV(v, "redeemScript")); diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 56ba805b1f6ab..3270cd384f4b6 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -592,7 +592,7 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp) " \"txid\":\"id\", (string, required) The transaction id\n" " \"vout\":n, (numeric, required) The output number\n" " \"scriptPubKey\": \"hex\", (string, required) script key\n" - " \"redeemScript\": \"hex\", (string, required for P2SH) redeem script\n" + " \"redeemScript\": \"hex\", (string, required for P2SH or P2WSH) redeem script\n" " \"amount\": value (numeric, required) The amount spent\n" " }\n" " ,...\n" @@ -744,7 +744,7 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp) // if redeemScript given and not using the local wallet (private keys // given), add redeemScript to the tempKeystore so it can be signed: - if (fGivenKeys && scriptPubKey.IsPayToScriptHash()) { + if (fGivenKeys && (scriptPubKey.IsPayToScriptHash() || scriptPubKey.IsPayToWitnessScriptHash())) { RPCTypeCheckObj(prevOut, { {"txid", UniValueType(UniValue::VSTR)}, diff --git a/src/script/script.cpp b/src/script/script.cpp index 73f5a61bf68bd..da551c23ee678 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -210,6 +210,14 @@ bool CScript::IsPayToScriptHash() const (*this)[22] == OP_EQUAL); } +bool CScript::IsPayToWitnessScriptHash() const +{ + // Extra-fast test for pay-to-witness-script-hash CScripts: + return (this->size() == 34 && + (*this)[0] == OP_0 && + (*this)[1] == 0x20); +} + // A witness program is any valid CScript that consists of a 1-byte push opcode // followed by a data push between 2 and 40 bytes. bool CScript::IsWitnessProgram(int& version, std::vector& program) const diff --git a/src/script/script.h b/src/script/script.h index b9b5be901389c..71af3754bcd17 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -621,6 +621,7 @@ class CScript : public CScriptBase unsigned int GetSigOpCount(const CScript& scriptSig) const; bool IsPayToScriptHash() const; + bool IsPayToWitnessScriptHash() const; bool IsWitnessProgram(int& version, std::vector& program) const; /** Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical). */ From 978e2004ad659ad216d820dbd79e212e276405f4 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 31 Mar 2016 14:43:46 +0200 Subject: [PATCH 0552/1802] --- [SEGWIT] begin: tests --- From 0aa92074516c37a10d4150d68918e20db91289a5 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 20 Nov 2015 16:22:47 +0100 Subject: [PATCH 0553/1802] [qa] Witness version 0 signing unit tests --- src/test/transaction_tests.cpp | 276 +++++++++++++++++++++++++++++++++ 1 file changed, 276 insertions(+) diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 9fb23d8edfab7..76f998ac24eec 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -14,7 +14,9 @@ #include "main.h" // For CheckTransaction #include "policy/policy.h" #include "script/script.h" +#include "script/sign.h" #include "script/script_error.h" +#include "script/standard.h" #include "utilstrencodings.h" #include @@ -25,11 +27,14 @@ #include #include #include +#include #include using namespace std; +typedef vector valtype; + // In script_tests.cpp extern UniValue read_json(const std::string& jsondata); @@ -315,6 +320,277 @@ BOOST_AUTO_TEST_CASE(test_Get) BOOST_CHECK_EQUAL(coins.GetValueIn(t1), (50+21+22)*CENT); } +void CreateCreditAndSpend(const CKeyStore& keystore, const CScript& outscript, CTransaction& output, CMutableTransaction& input, bool success = true) +{ + CMutableTransaction outputm; + outputm.nVersion = 1; + outputm.vin.resize(1); + outputm.vin[0].prevout.SetNull(); + outputm.vin[0].scriptSig = CScript(); + outputm.wit.vtxinwit.resize(1); + outputm.vout.resize(1); + outputm.vout[0].nValue = 1; + outputm.vout[0].scriptPubKey = outscript; + CDataStream ssout(SER_NETWORK, PROTOCOL_VERSION); + ssout << outputm; + ssout >> output; + assert(output.vin.size() == 1); + assert(output.vin[0] == outputm.vin[0]); + assert(output.vout.size() == 1); + assert(output.vout[0] == outputm.vout[0]); + assert(output.wit.vtxinwit.size() == 0); + + CMutableTransaction inputm; + inputm.nVersion = 1; + inputm.vin.resize(1); + inputm.vin[0].prevout.hash = output.GetHash(); + inputm.vin[0].prevout.n = 0; + inputm.wit.vtxinwit.resize(1); + inputm.vout.resize(1); + inputm.vout[0].nValue = 1; + inputm.vout[0].scriptPubKey = CScript(); + bool ret = SignSignature(keystore, output, inputm, 0, SIGHASH_ALL); + assert(ret == success); + CDataStream ssin(SER_NETWORK, PROTOCOL_VERSION); + ssin << inputm; + ssin >> input; + assert(input.vin.size() == 1); + assert(input.vin[0] == inputm.vin[0]); + assert(input.vout.size() == 1); + assert(input.vout[0] == inputm.vout[0]); + if (inputm.wit.IsNull()) { + assert(input.wit.IsNull()); + } else { + assert(!input.wit.IsNull()); + assert(input.wit.vtxinwit.size() == 1); + assert(input.wit.vtxinwit[0].scriptWitness.stack == inputm.wit.vtxinwit[0].scriptWitness.stack); + } +} + +void CheckWithFlag(const CTransaction& output, const CMutableTransaction& input, int flags, bool success) +{ + ScriptError error; + CTransaction inputi(input); + bool ret = VerifyScript(inputi.vin[0].scriptSig, output.vout[0].scriptPubKey, inputi.wit.vtxinwit.size() > 0 ? &inputi.wit.vtxinwit[0].scriptWitness : NULL, flags, TransactionSignatureChecker(&inputi, 0, output.vout[0].nValue), &error); + assert(ret == success); +} + +static CScript PushAll(const vector& values) +{ + CScript result; + BOOST_FOREACH(const valtype& v, values) { + if (v.size() == 0) { + result << OP_0; + } else if (v.size() == 1 && v[0] >= 1 && v[0] <= 16) { + result << CScript::EncodeOP_N(v[0]); + } else { + result << v; + } + } + return result; +} + +void ReplaceRedeemScript(CScript& script, const CScript& redeemScript) +{ + vector stack; + EvalScript(stack, script, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), SIGVERSION_BASE); + assert(stack.size() > 0); + stack.back() = std::vector(redeemScript.begin(), redeemScript.end()); + script = PushAll(stack); +} + +BOOST_AUTO_TEST_CASE(test_witness) +{ + CBasicKeyStore keystore, keystore2; + CKey key1, key2, key3, key1L, key2L; + CPubKey pubkey1, pubkey2, pubkey3, pubkey1L, pubkey2L; + key1.MakeNewKey(true); + key2.MakeNewKey(true); + key3.MakeNewKey(true); + key1L.MakeNewKey(false); + key2L.MakeNewKey(false); + pubkey1 = key1.GetPubKey(); + pubkey2 = key2.GetPubKey(); + pubkey3 = key3.GetPubKey(); + pubkey1L = key1L.GetPubKey(); + pubkey2L = key2L.GetPubKey(); + keystore.AddKeyPubKey(key1, pubkey1); + keystore.AddKeyPubKey(key2, pubkey2); + keystore.AddKeyPubKey(key1L, pubkey1L); + keystore.AddKeyPubKey(key2L, pubkey2L); + CScript scriptPubkey1, scriptPubkey2, scriptPubkey1L, scriptPubkey2L, scriptMulti; + scriptPubkey1 << ToByteVector(pubkey1) << OP_CHECKSIG; + scriptPubkey2 << ToByteVector(pubkey2) << OP_CHECKSIG; + scriptPubkey1L << ToByteVector(pubkey1L) << OP_CHECKSIG; + scriptPubkey2L << ToByteVector(pubkey2L) << OP_CHECKSIG; + std::vector oneandthree; + oneandthree.push_back(pubkey1); + oneandthree.push_back(pubkey3); + scriptMulti = GetScriptForMultisig(2, oneandthree); + keystore.AddCScript(scriptPubkey1); + keystore.AddCScript(scriptPubkey2); + keystore.AddCScript(scriptPubkey1L); + keystore.AddCScript(scriptPubkey2L); + keystore.AddCScript(scriptMulti); + keystore.AddCScript(GetScriptForWitness(scriptPubkey1)); + keystore.AddCScript(GetScriptForWitness(scriptPubkey2)); + keystore.AddCScript(GetScriptForWitness(scriptPubkey1L)); + keystore.AddCScript(GetScriptForWitness(scriptPubkey2L)); + keystore.AddCScript(GetScriptForWitness(scriptMulti)); + keystore2.AddCScript(scriptMulti); + keystore2.AddCScript(GetScriptForWitness(scriptMulti)); + keystore2.AddKeyPubKey(key3, pubkey3); + + CTransaction output1, output2; + CMutableTransaction input1, input2; + SignatureData sigdata; + + // Normal pay-to-compressed-pubkey. + CreateCreditAndSpend(keystore, scriptPubkey1, output1, input1); + CreateCreditAndSpend(keystore, scriptPubkey2, output2, input2); + CheckWithFlag(output1, input1, 0, true); + CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true); + CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true); + CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true); + CheckWithFlag(output1, input2, 0, false); + CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, false); + CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false); + CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false); + + // P2SH pay-to-compressed-pubkey. + CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(scriptPubkey1)), output1, input1); + CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(scriptPubkey2)), output2, input2); + ReplaceRedeemScript(input2.vin[0].scriptSig, scriptPubkey1); + CheckWithFlag(output1, input1, 0, true); + CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true); + CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true); + CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true); + CheckWithFlag(output1, input2, 0, true); + CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, false); + CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false); + CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false); + + // Witness pay-to-compressed-pubkey (v0). + CreateCreditAndSpend(keystore, GetScriptForWitness(scriptPubkey1), output1, input1); + CreateCreditAndSpend(keystore, GetScriptForWitness(scriptPubkey2), output2, input2); + CheckWithFlag(output1, input1, 0, true); + CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true); + CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true); + CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true); + CheckWithFlag(output1, input2, 0, true); + CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, true); + CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false); + CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false); + + // P2SH witness pay-to-compressed-pubkey (v0). + CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey1))), output1, input1); + CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey2))), output2, input2); + ReplaceRedeemScript(input2.vin[0].scriptSig, GetScriptForWitness(scriptPubkey1)); + CheckWithFlag(output1, input1, 0, true); + CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true); + CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true); + CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true); + CheckWithFlag(output1, input2, 0, true); + CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, true); + CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false); + CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false); + + // Normal pay-to-uncompressed-pubkey. + CreateCreditAndSpend(keystore, scriptPubkey1L, output1, input1); + CreateCreditAndSpend(keystore, scriptPubkey2L, output2, input2); + CheckWithFlag(output1, input1, 0, true); + CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true); + CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true); + CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true); + CheckWithFlag(output1, input2, 0, false); + CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, false); + CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false); + CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false); + + // P2SH pay-to-uncompressed-pubkey. + CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(scriptPubkey1L)), output1, input1); + CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(scriptPubkey2L)), output2, input2); + ReplaceRedeemScript(input2.vin[0].scriptSig, scriptPubkey1L); + CheckWithFlag(output1, input1, 0, true); + CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true); + CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true); + CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true); + CheckWithFlag(output1, input2, 0, true); + CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, false); + CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false); + CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false); + + // Witness pay-to-uncompressed-pubkey (v1). + CreateCreditAndSpend(keystore, GetScriptForWitness(scriptPubkey1L), output1, input1); + CreateCreditAndSpend(keystore, GetScriptForWitness(scriptPubkey2L), output2, input2); + CheckWithFlag(output1, input1, 0, true); + CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true); + CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true); + CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true); + CheckWithFlag(output1, input2, 0, true); + CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, true); + CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false); + CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false); + + // P2SH witness pay-to-uncompressed-pubkey (v1). + CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey1L))), output1, input1); + CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey2L))), output2, input2); + ReplaceRedeemScript(input2.vin[0].scriptSig, GetScriptForWitness(scriptPubkey1L)); + CheckWithFlag(output1, input1, 0, true); + CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true); + CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true); + CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true); + CheckWithFlag(output1, input2, 0, true); + CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, true); + CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false); + CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false); + + // Normal 2-of-2 multisig + CreateCreditAndSpend(keystore, scriptMulti, output1, input1, false); + CheckWithFlag(output1, input1, 0, false); + CreateCreditAndSpend(keystore2, scriptMulti, output2, input2, false); + CheckWithFlag(output2, input2, 0, false); + BOOST_CHECK(output1 == output2); + UpdateTransaction(input1, 0, CombineSignatures(output1.vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1.vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0))); + CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true); + + // P2SH 2-of-2 multisig + CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(scriptMulti)), output1, input1, false); + CheckWithFlag(output1, input1, 0, true); + CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, false); + CreateCreditAndSpend(keystore2, GetScriptForDestination(CScriptID(scriptMulti)), output2, input2, false); + CheckWithFlag(output2, input2, 0, true); + CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH, false); + BOOST_CHECK(output1 == output2); + UpdateTransaction(input1, 0, CombineSignatures(output1.vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1.vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0))); + CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true); + CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true); + + // Witness 2-of-2 multisig + CreateCreditAndSpend(keystore, GetScriptForWitness(scriptMulti), output1, input1, false); + CheckWithFlag(output1, input1, 0, true); + CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false); + CreateCreditAndSpend(keystore2, GetScriptForWitness(scriptMulti), output2, input2, false); + CheckWithFlag(output2, input2, 0, true); + CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false); + BOOST_CHECK(output1 == output2); + UpdateTransaction(input1, 0, CombineSignatures(output1.vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1.vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0))); + CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true); + CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true); + + // P2SH witness 2-of-2 multisig + CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptMulti))), output1, input1, false); + CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true); + CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false); + CreateCreditAndSpend(keystore2, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptMulti))), output2, input2, false); + CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH, true); + CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false); + BOOST_CHECK(output1 == output2); + UpdateTransaction(input1, 0, CombineSignatures(output1.vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1.vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0))); + CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true); + CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true); +} + BOOST_AUTO_TEST_CASE(test_IsStandard) { LOCK(cs_main); From 00f46cbcd9d33fadfeb391e764bda3ac220be3ea Mon Sep 17 00:00:00 2001 From: NicolasDorier Date: Sun, 3 Apr 2016 23:48:50 +0900 Subject: [PATCH 0554/1802] [qa] Add transaction tests for segwit Including BIP143 P2WSH examples by jl2012. --- src/test/data/tx_invalid.json | 63 ++++++++++++ src/test/data/tx_valid.json | 170 +++++++++++++++++++++++++++++++++ src/test/transaction_tests.cpp | 40 ++++++-- 3 files changed, 263 insertions(+), 10 deletions(-) diff --git a/src/test/data/tx_invalid.json b/src/test/data/tx_invalid.json index 4719f2b38877a..05502a83f73b1 100644 --- a/src/test/data/tx_invalid.json +++ b/src/test/data/tx_invalid.json @@ -251,5 +251,68 @@ [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 NOP3 1"]], "010000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], +["Unknown witness program version (with DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x60 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], +["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], +"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b00000000000001510002483045022100a3cec69b52cba2d2de623ffffffffff1606184ea55476c0f8189fda231bc9cbb022003181ad597f7c380a7d1c740286b1d022b8b04ded028b833282e055e03b8efef812103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS,DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"], + +["Unknown length for witness program v0"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x15 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3fff", 2000], +["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], +"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff04b60300000000000001519e070000000000000151860b0000000000000100960000000000000001510002473044022022fceb54f62f8feea77faac7083c3b56c4676a78f93745adc8a35800bc36adfa022026927df9abcf0a8777829bcfcce3ff0a385fa54c3f9df577405e3ef24ee56479022103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], + +["Witness with SigHash Single|AnyoneCanPay (same index output value changed)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], +["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], +"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e80300000000000001516c070000000000000151b80b0000000000000151000248304502210092f4777a0f17bf5aeb8ae768dec5f2c14feabf9d1fe2c89c78dfed0f13fdb86902206da90a86042e252bcd1e80a168c719e4a1ddcc3cebea24b9812c5453c79107e9832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], + +["Witness with SigHash None|AnyoneCanPay (input sequence changed)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], +["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], +"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff000100000000000000000000000000000000000000000000000000000000000001000000000100000000010000000000000000000000000000000000000000000000000000000000000200000000ffffffff00000248304502210091b32274295c2a3fa02f5bce92fb2789e3fc6ea947fbe1a76e52ea3f4ef2381a022079ad72aefa3837a2e0c033a8652a59731da05fa4a813f4fc48e87c075037256b822103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], + +["Witness with SigHash All|AnyoneCanPay (third output value changed)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], +["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], +"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151540b00000000000001510002483045022100a3cec69b52cba2d2de623eeef89e0ba1606184ea55476c0f8189fda231bc9cbb022003181ad597f7c380a7d1c740286b1d022b8b04ded028b833282e055e03b8efef812103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], + +["Witness with a push of 521 bytes"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x20 0x33198a9bfef674ebddb9ffaa52928017b8472791e54c609cb95f278ac6b1e349", 1000]], +"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff010000000000000000015102fd0902000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002755100000000", "P2SH,WITNESS"], + +["Witness with unknown version which push false on the stack should be invalid (even without DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x02 0x0000", 2000]], +"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff010000000000000000015101010100000000", "P2SH,WITNESS"], + +["Witness program should leave clean stack"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x20 0x2f04a3aa051f1f60d695f6c44c0c3d383973dfd446ace8962664a76bb10e31a8", 2000]], +"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01000000000000000001510102515100000000", "P2SH,WITNESS"], + +["Witness v0 with a push of 2 bytes"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x02 0x0001", 2000]], +"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff010000000000000000015101040002000100000000", "P2SH,WITNESS"], + +["Unknown witness version with non empty scriptSig"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x02 0x0001", 2000]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000000151ffffffff010000000000000000015100000000", "P2SH,WITNESS"], + +["Non witness Single|AnyoneCanPay hash input's position (permutation)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x03596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71 CHECKSIG", 1000], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x21 0x03596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71 CHECKSIG", 1001]], +"010000000200010000000000000000000000000000000000000000000000000000000000000100000049483045022100acb96cfdbda6dc94b489fd06f2d720983b5f350e31ba906cdbd800773e80b21c02200d74ea5bdf114212b4bbe9ed82c36d2e369e302dff57cb60d01c428f0bd3daab83ffffffff0001000000000000000000000000000000000000000000000000000000000000000000004847304402202a0b4b1294d70540235ae033d78e64b4897ec859c7b6f1b2b1d8a02e1d46006702201445e756d2254b0f1dfda9ab8e1e1bc26df9668077403204f32d16a49a36eb6983ffffffff02e9030000000000000151e803000000000000015100000000", "P2SH,WITNESS"], + +["P2WSH with a redeem representing a witness scriptPubKey should fail"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x20 0x34b6c399093e06cf9f0f7f660a1abcfe78fcf7b576f43993208edd9518a0ae9b", 1000]], +"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0001045102010100000000", "P2SH,WITNESS"], + +["33 bytes push should be considered a witness scriptPubKey"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x21 0xff25429251b5a84f452230a3c75fd886b7fc5a7865ce4a7bb7a9d7c5be6da3dbff", 1000]], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH,WITNESS,DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"], + ["Make diffs cleaner by leaving a comment here without comma at the end"] ] diff --git a/src/test/data/tx_valid.json b/src/test/data/tx_valid.json index 717ad19549eb9..c9fe4e313a2eb 100644 --- a/src/test/data/tx_valid.json +++ b/src/test/data/tx_valid.json @@ -317,5 +317,175 @@ [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7c17aff532f22beb54069942f9bf567a66133eaf EQUAL"]], "0200000001000100000000000000000000000000000000000000000000000000000000000000000000030251b2010000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], +["Valid P2WPKH (Private key of segwit tests is L5AQtV2HDm4xGsseLokK2VAT2EtYKcTm3c7HwqnJBFt9LdaQULsM)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000]], +"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e8030000000000001976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac02483045022100cfb07164b36ba64c1b1e8c7720a56ad64d96f6ef332d3d37f9cb3c96477dc44502200a464cd7a9cf94cd70f66ce4f4f0625ef650052c7afcfe29d7d7e01830ff91ed012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000", "P2SH,WITNESS"], + +["Valid P2WSH"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x20 0xff25429251b5a84f452230a3c75fd886b7fc5a7865ce4a7bb7a9d7c5be6da3db", 1000]], +"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e8030000000000001976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac02483045022100aa5d8aa40a90f23ce2c3d11bc845ca4a12acd99cbea37de6b9f6d86edebba8cb022022dedc2aa0a255f74d04c0b76ece2d7c691f9dd11a64a8ac49f62a99c3a05f9d01232103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ac00000000", "P2SH,WITNESS"], + +["Valid P2SH(P2WPKH)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xfe9c7dacc9fcfbf7e3b7d5ad06aa2b28c5a7b7e3 EQUAL", 1000]], +"01000000000101000100000000000000000000000000000000000000000000000000000000000000000000171600144c9c3dfac4207d5d8cb89df5722cb3d712385e3fffffffff01e8030000000000001976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac02483045022100cfb07164b36ba64c1b1e8c7720a56ad64d96f6ef332d3d37f9cb3c96477dc44502200a464cd7a9cf94cd70f66ce4f4f0625ef650052c7afcfe29d7d7e01830ff91ed012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000", "P2SH,WITNESS"], + +["Valid P2SH(P2WSH)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x2135ab4f0981830311e35600eebc7376dce3a914 EQUAL", 1000]], +"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000023220020ff25429251b5a84f452230a3c75fd886b7fc5a7865ce4a7bb7a9d7c5be6da3dbffffffff01e8030000000000001976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac02483045022100aa5d8aa40a90f23ce2c3d11bc845ca4a12acd99cbea37de6b9f6d86edebba8cb022022dedc2aa0a255f74d04c0b76ece2d7c691f9dd11a64a8ac49f62a99c3a05f9d01232103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ac00000000", "P2SH,WITNESS"], + +["Witness with SigHash Single|AnyoneCanPay"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1100], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], +["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3100], +["0000000000000000000000000000000000000000000000000000000000000100", 3, "0x51", 4100]], +"0100000000010400010000000000000000000000000000000000000000000000000000000000000200000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000300000000ffffffff05540b0000000000000151d0070000000000000151840300000000000001513c0f00000000000001512c010000000000000151000248304502210092f4777a0f17bf5aeb8ae768dec5f2c14feabf9d1fe2c89c78dfed0f13fdb86902206da90a86042e252bcd1e80a168c719e4a1ddcc3cebea24b9812c5453c79107e9832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71000000000000", "P2SH,WITNESS"], + +["Witness with SigHash Single|AnyoneCanPay (same signature as previous)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], +["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], +"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b0000000000000151000248304502210092f4777a0f17bf5aeb8ae768dec5f2c14feabf9d1fe2c89c78dfed0f13fdb86902206da90a86042e252bcd1e80a168c719e4a1ddcc3cebea24b9812c5453c79107e9832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], + +["Witness with SigHash Single"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], +["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], +"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff0484030000000000000151d0070000000000000151540b0000000000000151c800000000000000015100024730440220699e6b0cfe015b64ca3283e6551440a34f901ba62dd4c72fe1cb815afb2e6761022021cc5e84db498b1479de14efda49093219441adc6c543e5534979605e273d80b032103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], + +["Witness with SigHash Single (same signature as previous)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], +["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], +"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b000000000000015100024730440220699e6b0cfe015b64ca3283e6551440a34f901ba62dd4c72fe1cb815afb2e6761022021cc5e84db498b1479de14efda49093219441adc6c543e5534979605e273d80b032103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], + +["Witness with SigHash None|AnyoneCanPay"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1100], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], +["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3100], +["0000000000000000000000000000000000000000000000000000000000000100", 3, "0x51", 4100]], +"0100000000010400010000000000000000000000000000000000000000000000000000000000000200000000ffffffff00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000300000000ffffffff04b60300000000000001519e070000000000000151860b00000000000001009600000000000000015100000248304502210091b32274295c2a3fa02f5bce92fb2789e3fc6ea947fbe1a76e52ea3f4ef2381a022079ad72aefa3837a2e0c033a8652a59731da05fa4a813f4fc48e87c075037256b822103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], + +["Witness with SigHash None|AnyoneCanPay (same signature as previous)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], +["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], +"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b0000000000000151000248304502210091b32274295c2a3fa02f5bce92fb2789e3fc6ea947fbe1a76e52ea3f4ef2381a022079ad72aefa3837a2e0c033a8652a59731da05fa4a813f4fc48e87c075037256b822103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], + +["Witness with SigHash None"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], +["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], +"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff04b60300000000000001519e070000000000000151860b0000000000000100960000000000000001510002473044022022fceb54f62f8feea77faac7083c3b56c4676a78f93745adc8a35800bc36adfa022026927df9abcf0a8777829bcfcce3ff0a385fa54c3f9df577405e3ef24ee56479022103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], + +["Witness with SigHash None (same signature as previous)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], +["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], +"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b00000000000001510002473044022022fceb54f62f8feea77faac7083c3b56c4676a78f93745adc8a35800bc36adfa022026927df9abcf0a8777829bcfcce3ff0a385fa54c3f9df577405e3ef24ee56479022103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], + +["Witness with SigHash None (same signature, only sequences changed)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], +["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], +"01000000000103000100000000000000000000000000000000000000000000000000000000000000000000000200000000010000000000000000000000000000000000000000000000000000000000000100000000ffffffff000100000000000000000000000000000000000000000000000000000000000002000000000200000003e8030000000000000151d0070000000000000151b80b00000000000001510002473044022022fceb54f62f8feea77faac7083c3b56c4676a78f93745adc8a35800bc36adfa022026927df9abcf0a8777829bcfcce3ff0a385fa54c3f9df577405e3ef24ee56479022103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], + +["Witness with SigHash All|AnyoneCanPay"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1100], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], +["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3100], +["0000000000000000000000000000000000000000000000000000000000000100", 3, "0x51", 4100]], +"0100000000010400010000000000000000000000000000000000000000000000000000000000000200000000ffffffff00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000300000000ffffffff03e8030000000000000151d0070000000000000151b80b0000000000000151000002483045022100a3cec69b52cba2d2de623eeef89e0ba1606184ea55476c0f8189fda231bc9cbb022003181ad597f7c380a7d1c740286b1d022b8b04ded028b833282e055e03b8efef812103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], + +["Witness with SigHash All|AnyoneCanPay (same signature as previous)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], +["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], +"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b00000000000001510002483045022100a3cec69b52cba2d2de623eeef89e0ba1606184ea55476c0f8189fda231bc9cbb022003181ad597f7c380a7d1c740286b1d022b8b04ded028b833282e055e03b8efef812103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], + +["Unknown witness program version (without DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x60 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], +["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], +"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b00000000000001510002483045022100a3cec69b52cba2d2de623ffffffffff1606184ea55476c0f8189fda231bc9cbb022003181ad597f7c380a7d1c740286b1d022b8b04ded028b833282e055e03b8efef812103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], + +["Witness with a push of 520 bytes"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x20 0x33198a9bfef674ebddb9ffaa52928017b8472791e54c609cb95f278ac6b1e349", 1000]], +"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff010000000000000000015102fd08020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002755100000000", "P2SH,WITNESS"], + +["Transaction mixing all SigHash, segwit and normal inputs"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1001], +["0000000000000000000000000000000000000000000000000000000000000100", 2, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1002], +["0000000000000000000000000000000000000000000000000000000000000100", 3, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1003], +["0000000000000000000000000000000000000000000000000000000000000100", 4, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1004], +["0000000000000000000000000000000000000000000000000000000000000100", 5, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1005], +["0000000000000000000000000000000000000000000000000000000000000100", 6, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1006], +["0000000000000000000000000000000000000000000000000000000000000100", 7, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1007], +["0000000000000000000000000000000000000000000000000000000000000100", 8, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1008], +["0000000000000000000000000000000000000000000000000000000000000100", 9, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1009], +["0000000000000000000000000000000000000000000000000000000000000100", 10, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1010], +["0000000000000000000000000000000000000000000000000000000000000100", 11, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1011]], +"0100000000010c00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff0001000000000000000000000000000000000000000000000000000000000000020000006a473044022026c2e65b33fcd03b2a3b0f25030f0244bd23cc45ae4dec0f48ae62255b1998a00220463aa3982b718d593a6b9e0044513fd67a5009c2fdccc59992cffc2b167889f4012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0001000000000000000000000000000000000000000000000000000000000000030000006a4730440220008bd8382911218dcb4c9f2e75bf5c5c3635f2f2df49b36994fde85b0be21a1a02205a539ef10fb4c778b522c1be852352ea06c67ab74200977c722b0bc68972575a012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0001000000000000000000000000000000000000000000000000000000000000040000006b483045022100d9436c32ff065127d71e1a20e319e4fe0a103ba0272743dbd8580be4659ab5d302203fd62571ee1fe790b182d078ecfd092a509eac112bea558d122974ef9cc012c7012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0001000000000000000000000000000000000000000000000000000000000000050000006a47304402200e2c149b114ec546015c13b2b464bbcb0cdc5872e6775787527af6cbc4830b6c02207e9396c6979fb15a9a2b96ca08a633866eaf20dc0ff3c03e512c1d5a1654f148012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0001000000000000000000000000000000000000000000000000000000000000060000006b483045022100b20e70d897dc15420bccb5e0d3e208d27bdd676af109abbd3f88dbdb7721e6d6022005836e663173fbdfe069f54cde3c2decd3d0ea84378092a5d9d85ec8642e8a41012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff00010000000000000000000000000000000000000000000000000000000000000700000000ffffffff00010000000000000000000000000000000000000000000000000000000000000800000000ffffffff00010000000000000000000000000000000000000000000000000000000000000900000000ffffffff00010000000000000000000000000000000000000000000000000000000000000a00000000ffffffff00010000000000000000000000000000000000000000000000000000000000000b0000006a47304402206639c6e05e3b9d2675a7f3876286bdf7584fe2bbd15e0ce52dd4e02c0092cdc60220757d60b0a61fc95ada79d23746744c72bac1545a75ff6c2c7cdb6ae04e7e9592012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0ce8030000000000000151e9030000000000000151ea030000000000000151eb030000000000000151ec030000000000000151ed030000000000000151ee030000000000000151ef030000000000000151f0030000000000000151f1030000000000000151f2030000000000000151f30300000000000001510248304502210082219a54f61bf126bfc3fa068c6e33831222d1d7138c6faa9d33ca87fd4202d6022063f9902519624254d7c2c8ea7ba2d66ae975e4e229ae38043973ec707d5d4a83012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7102473044022017fb58502475848c1b09f162cb1688d0920ff7f142bed0ef904da2ccc88b168f02201798afa61850c65e77889cbcd648a5703b487895517c88f85cdd18b021ee246a012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000000247304402202830b7926e488da75782c81a54cd281720890d1af064629ebf2e31bf9f5435f30220089afaa8b455bbeb7d9b9c3fe1ed37d07685ade8455c76472cda424d93e4074a012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7102473044022026326fcdae9207b596c2b05921dbac11d81040c4d40378513670f19d9f4af893022034ecd7a282c0163b89aaa62c22ec202cef4736c58cd251649bad0d8139bcbf55012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71024730440220214978daeb2f38cd426ee6e2f44131a33d6b191af1c216247f1dd7d74c16d84a02205fdc05529b0bc0c430b4d5987264d9d075351c4f4484c16e91662e90a72aab24012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710247304402204a6e9f199dc9672cf2ff8094aaa784363be1eb62b679f7ff2df361124f1dca3302205eeb11f70fab5355c9c8ad1a0700ea355d315e334822fa182227e9815308ee8f012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], + +["Unknown version witness program with empty witness"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000]], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH,WITNESS"], + +["Witness SIGHASH_SINGLE with output out of bound"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x20 0x4d6c2a32c87821d68fc016fca70797abdb80df6cd84651d40a9300c6bad79e62", 1000]], +"0100000000010200010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff01d00700000000000001510003483045022100e078de4e96a0e05dcdc0a414124dd8475782b5f3f0ed3f607919e9a5eeeb22bf02201de309b3a3109adb3de8074b3610d4cf454c49b61247a2779a0bcbf31c889333032103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc711976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac00000000", "P2SH,WITNESS"], + +["1 byte push should not be considered a witness scriptPubKey"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x01 0x01", 1000]], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH,WITNESS,DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"], + +["41 bytes push should not be considered a witness scriptPubKey"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x29 0xff25429251b5a84f452230a3c75fd886b7fc5a7865ce4a7bb7a9d7c5be6da3dbff0000000000000000", 1000]], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH,WITNESS,DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"], + +["The witness version must use OP_1 to OP_16 only"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x01 0x10 0x02 0x0001", 1000]], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH,WITNESS,DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"], + +["The witness program push must be canonical"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x4c02 0x0001", 1000]], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH,WITNESS,DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"], + +["Witness Single|AnyoneCanPay does not hash input's position"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1001]], +"0100000000010200010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff02e8030000000000000151e90300000000000001510247304402206d59682663faab5e4cb733c562e22cdae59294895929ec38d7c016621ff90da0022063ef0af5f970afe8a45ea836e3509b8847ed39463253106ac17d19c437d3d56b832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710248304502210085001a820bfcbc9f9de0298af714493f8a37b3b354bfd21a7097c3e009f2018c022050a8b4dbc8155d4d04da2f5cdd575dcf8dd0108de8bec759bd897ea01ecb3af7832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000", "P2SH,WITNESS"], + +["Witness Single|AnyoneCanPay does not hash input's position (permutation)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1001]], +"0100000000010200010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff02e9030000000000000151e80300000000000001510248304502210085001a820bfcbc9f9de0298af714493f8a37b3b354bfd21a7097c3e009f2018c022050a8b4dbc8155d4d04da2f5cdd575dcf8dd0108de8bec759bd897ea01ecb3af7832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710247304402206d59682663faab5e4cb733c562e22cdae59294895929ec38d7c016621ff90da0022063ef0af5f970afe8a45ea836e3509b8847ed39463253106ac17d19c437d3d56b832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000", "P2SH,WITNESS"], + +["Non witness Single|AnyoneCanPay hash input's position"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x03596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71 CHECKSIG", 1000], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x21 0x03596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71 CHECKSIG", 1001]], +"01000000020001000000000000000000000000000000000000000000000000000000000000000000004847304402202a0b4b1294d70540235ae033d78e64b4897ec859c7b6f1b2b1d8a02e1d46006702201445e756d2254b0f1dfda9ab8e1e1bc26df9668077403204f32d16a49a36eb6983ffffffff00010000000000000000000000000000000000000000000000000000000000000100000049483045022100acb96cfdbda6dc94b489fd06f2d720983b5f350e31ba906cdbd800773e80b21c02200d74ea5bdf114212b4bbe9ed82c36d2e369e302dff57cb60d01c428f0bd3daab83ffffffff02e8030000000000000151e903000000000000015100000000", "P2SH,WITNESS"], + +["BIP143 examples: details and private keys are available in BIP143"], +["BIP143 example: P2WSH with OP_CODESEPARATOR and out-of-range SIGHASH_SINGLE."], +[[["6eb316926b1c5d567cd6f5e6a84fec606fc53d7b474526d1fff3948020c93dfe", 0, "0x21 0x036d5c20fa14fb2f635474c1dc4ef5909d4568e5569b79fc94d3448486e14685f8 CHECKSIG", 156250000], +["f825690aee1b3dc247da796cacb12687a5e802429fd291cfd63e010f02cf1508", 0, "0x00 0x20 0x5d1b56b63d714eebe542309525f484b7e9d6f686b3781b6f61ef925d66d6f6a0", 4900000000]], +"01000000000102fe3dc9208094f3ffd12645477b3dc56f60ec4fa8e6f5d67c565d1c6b9216b36e000000004847304402200af4e47c9b9629dbecc21f73af989bdaa911f7e6f6c2e9394588a3aa68f81e9902204f3fcf6ade7e5abb1295b6774c8e0abd94ae62217367096bc02ee5e435b67da201ffffffff0815cf020f013ed6cf91d29f4202e8a58726b1ac6c79da47c23d1bee0a6925f80000000000ffffffff0100f2052a010000001976a914a30741f8145e5acadf23f751864167f32e0963f788ac000347304402200de66acf4527789bfda55fc5459e214fa6083f936b430a762c629656216805ac0220396f550692cd347171cbc1ef1f51e15282e837bb2b30860dc77c8f78bc8501e503473044022027dc95ad6b740fe5129e7e62a75dd00f291a2aeb1200b84b09d9e3789406b6c002201a9ecd315dd6a0e632ab20bbb98948bc0c6fb204f2c286963bb48517a7058e27034721026dccc749adc2a9d0d89497ac511f760f45c47dc5ed9cf352a58ac706453880aeadab210255a9626aebf5e29c0e6538428ba0d1dcf6ca98ffdf086aa8ced5e0d0215ea465ac00000000", "P2SH,WITNESS"], + +["BIP143 example: P2WSH with unexecuted OP_CODESEPARATOR and SINGLE|ANYONECANPAY"], +[[["01c0cf7fba650638e55eb91261b183251fbb466f90dff17f10086817c542b5e9", 0, "0x00 0x20 0xba468eea561b26301e4cf69fa34bde4ad60c81e70f059f045ca9a79931004a4d", 16777215], +["1b2a9a426ba603ba357ce7773cb5805cb9c7c2b386d100d1fc9263513188e680", 0, "0x00 0x20 0xd9bbfbe56af7c4b7f960a70d7ea107156913d9e5a26b0a71429df5e097ca6537", 16777215]], +"01000000000102e9b542c5176808107ff1df906f46bb1f2583b16112b95ee5380665ba7fcfc0010000000000ffffffff80e68831516392fcd100d186b3c2c7b95c80b53c77e77c35ba03a66b429a2a1b0000000000ffffffff0280969800000000001976a914de4b231626ef508c9a74a8517e6783c0546d6b2888ac80969800000000001976a9146648a8cd4531e1ec47f35916de8e259237294d1e88ac02483045022100f6a10b8604e6dc910194b79ccfc93e1bc0ec7c03453caaa8987f7d6c3413566002206216229ede9b4d6ec2d325be245c5b508ff0339bf1794078e20bfe0babc7ffe683270063ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac024730440220032521802a76ad7bf74d0e2c218b72cf0cbc867066e2e53db905ba37f130397e02207709e2188ed7f08f4c952d9d13986da504502b8c3be59617e043552f506c46ff83275163ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac00000000", "P2SH,WITNESS"], + +["BIP143 example: Same as the previous example with input-output paris swapped"], +[[["1b2a9a426ba603ba357ce7773cb5805cb9c7c2b386d100d1fc9263513188e680", 0, "0x00 0x20 0xd9bbfbe56af7c4b7f960a70d7ea107156913d9e5a26b0a71429df5e097ca6537", 16777215], +["01c0cf7fba650638e55eb91261b183251fbb466f90dff17f10086817c542b5e9", 0, "0x00 0x20 0xba468eea561b26301e4cf69fa34bde4ad60c81e70f059f045ca9a79931004a4d", 16777215]], +"0100000000010280e68831516392fcd100d186b3c2c7b95c80b53c77e77c35ba03a66b429a2a1b0000000000ffffffffe9b542c5176808107ff1df906f46bb1f2583b16112b95ee5380665ba7fcfc0010000000000ffffffff0280969800000000001976a9146648a8cd4531e1ec47f35916de8e259237294d1e88ac80969800000000001976a914de4b231626ef508c9a74a8517e6783c0546d6b2888ac024730440220032521802a76ad7bf74d0e2c218b72cf0cbc867066e2e53db905ba37f130397e02207709e2188ed7f08f4c952d9d13986da504502b8c3be59617e043552f506c46ff83275163ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac02483045022100f6a10b8604e6dc910194b79ccfc93e1bc0ec7c03453caaa8987f7d6c3413566002206216229ede9b4d6ec2d325be245c5b508ff0339bf1794078e20bfe0babc7ffe683270063ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac00000000", "P2SH,WITNESS"], + +["BIP143 example: P2SH-P2WSH 6-of-6 multisig signed with 6 different SIGHASH types"], +[[["6eb98797a21c6c10aa74edf29d618be109f48a8e94c694f3701e08ca69186436", 1, "HASH160 0x14 0x9993a429037b5d912407a71c252019287b8d27a5 EQUAL", 987654321]], +"0100000000010136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000023220020a16b5755f7f6f96dbd65f5f0d6ab9418b89af4b1f14a1bb8a09062c35f0dcb54ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac080047304402206ac44d672dac41f9b00e28f4df20c52eeb087207e8d758d76d92c6fab3b73e2b0220367750dbbe19290069cba53d096f44530e4f98acaa594810388cf7409a1870ce01473044022068c7946a43232757cbdf9176f009a928e1cd9a1a8c212f15c1e11ac9f2925d9002205b75f937ff2f9f3c1246e547e54f62e027f64eefa2695578cc6432cdabce271502473044022059ebf56d98010a932cf8ecfec54c48e6139ed6adb0728c09cbe1e4fa0915302e022007cd986c8fa870ff5d2b3a89139c9fe7e499259875357e20fcbb15571c76795403483045022100fbefd94bd0a488d50b79102b5dad4ab6ced30c4069f1eaa69a4b5a763414067e02203156c6a5c9cf88f91265f5a942e96213afae16d83321c8b31bb342142a14d16381483045022100a5263ea0553ba89221984bd7f0b13613db16e7a70c549a86de0cc0444141a407022005c360ef0ae5a5d4f9f2f87a56c1546cc8268cab08c73501d6b3be2e1e1a8a08824730440220525406a1482936d5a21888260dc165497a90a15669636d8edca6b9fe490d309c022032af0c646a34a44d1f4576bf6a4a74b67940f8faa84c7df9abe12a01a11e2b4783cf56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae00000000", "P2SH,WITNESS"], + ["Make diffs cleaner by leaving a comment here without comma at the end"] ] diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 76f998ac24eec..fd4f174b40c80 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -50,7 +50,9 @@ static std::map mapFlagNames = boost::assign::map_list_of (string("DISCOURAGE_UPGRADABLE_NOPS"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) (string("CLEANSTACK"), (unsigned int)SCRIPT_VERIFY_CLEANSTACK) (string("CHECKLOCKTIMEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY) - (string("CHECKSEQUENCEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKSEQUENCEVERIFY); + (string("CHECKSEQUENCEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKSEQUENCEVERIFY) + (string("WITNESS"), (unsigned int)SCRIPT_VERIFY_WITNESS) + (string("DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM); unsigned int ParseScriptFlags(string strFlags) { @@ -113,6 +115,7 @@ BOOST_AUTO_TEST_CASE(tx_valid) } map mapprevOutScriptPubKeys; + map mapprevOutValues; UniValue inputs = test[0].get_array(); bool fValid = true; for (unsigned int inpIdx = 0; inpIdx < inputs.size(); inpIdx++) { @@ -123,13 +126,17 @@ BOOST_AUTO_TEST_CASE(tx_valid) break; } UniValue vinput = input.get_array(); - if (vinput.size() != 3) + if (vinput.size() < 3 || vinput.size() > 4) { fValid = false; break; } - - mapprevOutScriptPubKeys[COutPoint(uint256S(vinput[0].get_str()), vinput[1].get_int())] = ParseScript(vinput[2].get_str()); + COutPoint outpoint(uint256S(vinput[0].get_str()), vinput[1].get_int()); + mapprevOutScriptPubKeys[outpoint] = ParseScript(vinput[2].get_str()); + if (vinput.size() >= 4) + { + mapprevOutValues[outpoint] = vinput[3].get_int64(); + } } if (!fValid) { @@ -155,9 +162,13 @@ BOOST_AUTO_TEST_CASE(tx_valid) } CAmount amount = 0; + if (mapprevOutValues.count(tx.vin[i].prevout)) { + amount = mapprevOutValues[tx.vin[i].prevout]; + } unsigned int verify_flags = ParseScriptFlags(test[2].get_str()); + const CScriptWitness *witness = (i < tx.wit.vtxinwit.size()) ? &tx.wit.vtxinwit[i].scriptWitness : NULL; BOOST_CHECK_MESSAGE(VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], - NULL, verify_flags, TransactionSignatureChecker(&tx, i, amount), &err), + witness, verify_flags, TransactionSignatureChecker(&tx, i, amount), &err), strTest); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); } @@ -189,6 +200,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid) } map mapprevOutScriptPubKeys; + map mapprevOutValues; UniValue inputs = test[0].get_array(); bool fValid = true; for (unsigned int inpIdx = 0; inpIdx < inputs.size(); inpIdx++) { @@ -199,13 +211,17 @@ BOOST_AUTO_TEST_CASE(tx_invalid) break; } UniValue vinput = input.get_array(); - if (vinput.size() != 3) + if (vinput.size() < 3 || vinput.size() > 4) { fValid = false; break; } - - mapprevOutScriptPubKeys[COutPoint(uint256S(vinput[0].get_str()), vinput[1].get_int())] = ParseScript(vinput[2].get_str()); + COutPoint outpoint(uint256S(vinput[0].get_str()), vinput[1].get_int()); + mapprevOutScriptPubKeys[outpoint] = ParseScript(vinput[2].get_str()); + if (vinput.size() >= 4) + { + mapprevOutValues[outpoint] = vinput[3].get_int64(); + } } if (!fValid) { @@ -231,8 +247,12 @@ BOOST_AUTO_TEST_CASE(tx_invalid) unsigned int verify_flags = ParseScriptFlags(test[2].get_str()); CAmount amount = 0; + if (mapprevOutValues.count(tx.vin[i].prevout)) { + amount = mapprevOutValues[tx.vin[i].prevout]; + } + const CScriptWitness *witness = (i < tx.wit.vtxinwit.size()) ? &tx.wit.vtxinwit[i].scriptWitness : NULL; fValid = VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], - NULL, verify_flags, TransactionSignatureChecker(&tx, i, amount), &err); + witness, verify_flags, TransactionSignatureChecker(&tx, i, amount), &err); } BOOST_CHECK_MESSAGE(!fValid, strTest); BOOST_CHECK_MESSAGE(err != SCRIPT_ERR_OK, ScriptErrorString(err)); @@ -422,7 +442,7 @@ BOOST_AUTO_TEST_CASE(test_witness) scriptPubkey1 << ToByteVector(pubkey1) << OP_CHECKSIG; scriptPubkey2 << ToByteVector(pubkey2) << OP_CHECKSIG; scriptPubkey1L << ToByteVector(pubkey1L) << OP_CHECKSIG; - scriptPubkey2L << ToByteVector(pubkey2L) << OP_CHECKSIG; + scriptPubkey2L << ToByteVector(pubkey2L) << OP_CHECKSIG; std::vector oneandthree; oneandthree.push_back(pubkey1); oneandthree.push_back(pubkey3); From 06d3805c1a44aae39ad95538063e6882249b7633 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 4 Apr 2016 16:01:27 +0200 Subject: [PATCH 0555/1802] [qa] Add segwit support to script_tests Contains fix by Johnson Lau. --- src/test/data/script_tests.json | 8 ++++- src/test/script_tests.cpp | 53 ++++++++++++++++++++++----------- 2 files changed, 42 insertions(+), 19 deletions(-) diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json index 0bdac182e0079..f6ee7ade42530 100644 --- a/src/test/data/script_tests.json +++ b/src/test/data/script_tests.json @@ -1,5 +1,5 @@ [ -["Format is: [scriptSig, scriptPubKey, flags, expected_scripterror, ... comments]"], +["Format is: [[wit...]?, scriptSig, scriptPubKey, flags, expected_scripterror, ... comments]"], ["It is evaluated as if there was a crediting coinbase transaction with two 0"], ["pushes as scriptSig, and one output of 0 satoshi and given scriptPubKey,"], ["followed by a spending transaction which spends this output as only input (and"], @@ -1253,6 +1253,12 @@ ["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Zero-length S is incorrectly encoded for DERSIG"], ["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Negative S is incorrectly encoded for DERSIG"], +["Some basic segwit checks"], +[["00"], "", "0 0x206e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", "P2SH,WITNESS", "EVAL_FALSE", "Invalid witness script"], +[["51"], "", "0 0x206e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", "P2SH,WITNESS", "WITNESS_PROGRAM_MISMATCH", "Witness script hash mismatch"], +[["00"], "", "0 0x206e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", "", "OK", "Invalid witness script without WITNESS"], +[["51"], "", "0 0x206e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", "", "OK", "Witness script hash mismatch without WITNESS"], + ["Automatically generated test cases"], [ "0x47 0x304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001", diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 1d69194c3e89c..88f1562b103b0 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -88,7 +88,14 @@ static ScriptErrorDesc script_errors[]={ {SCRIPT_ERR_SIG_NULLDUMMY, "SIG_NULLDUMMY"}, {SCRIPT_ERR_PUBKEYTYPE, "PUBKEYTYPE"}, {SCRIPT_ERR_CLEANSTACK, "CLEANSTACK"}, - {SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS, "DISCOURAGE_UPGRADABLE_NOPS"} + {SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS, "DISCOURAGE_UPGRADABLE_NOPS"}, + {SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM, "DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"}, + {SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH, "WITNESS_PROGRAM_WRONG_LENGTH"}, + {SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY, "WITNESS_PROGRAM_WITNESS_EMPTY"}, + {SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH, "WITNESS_PROGRAM_MISMATCH"}, + {SCRIPT_ERR_WITNESS_MALLEATED, "WITNESS_MALLEATED"}, + {SCRIPT_ERR_WITNESS_MALLEATED_P2SH, "WITNESS_MALLEATED_P2SH"}, + {SCRIPT_ERR_WITNESS_UNEXPECTED, "WITNESS_UNEXPECTED"}, }; const char *FormatScriptError(ScriptError_t err) @@ -127,13 +134,15 @@ CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey) return txCredit; } -CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CMutableTransaction& txCredit) +CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CScriptWitness& scriptWitness, const CMutableTransaction& txCredit) { CMutableTransaction txSpend; txSpend.nVersion = 1; txSpend.nLockTime = 0; txSpend.vin.resize(1); txSpend.vout.resize(1); + txSpend.wit.vtxinwit.resize(1); + txSpend.wit.vtxinwit[0].scriptWitness = scriptWitness; txSpend.vin[0].prevout.hash = txCredit.GetHash(); txSpend.vin[0].prevout.n = 0; txSpend.vin[0].scriptSig = scriptSig; @@ -144,7 +153,7 @@ CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CMu return txSpend; } -void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, int flags, const std::string& message, int scriptError) +void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, const CScriptWitness& scriptWitness, int flags, const std::string& message, int scriptError) { bool expect = (scriptError == SCRIPT_ERR_OK); if (flags & SCRIPT_VERIFY_CLEANSTACK) { @@ -153,12 +162,12 @@ void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, int flags, co } ScriptError err; CMutableTransaction txCredit = BuildCreditingTransaction(scriptPubKey); - CMutableTransaction tx = BuildSpendingTransaction(scriptSig, txCredit); + CMutableTransaction tx = BuildSpendingTransaction(scriptSig, scriptWitness, txCredit); CMutableTransaction tx2 = tx; - BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, NULL, flags, MutableTransactionSignatureChecker(&tx, 0, txCredit.vout[0].nValue), &err) == expect, message); + BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, &scriptWitness, flags, MutableTransactionSignatureChecker(&tx, 0, txCredit.vout[0].nValue), &err) == expect, message); BOOST_CHECK_MESSAGE(err == scriptError, std::string(FormatScriptError(err)) + " where " + std::string(FormatScriptError((ScriptError_t)scriptError)) + " expected: " + message); #if defined(HAVE_CONSENSUS_LIB) - CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); + CDataStream stream(SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_WITNESS); stream << tx2; if (flags & bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS) { BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script_with_amount(begin_ptr(scriptPubKey), scriptPubKey.size(), txCredit.vout[0].nValue, (const unsigned char*)&stream[0], stream.size(), 0, flags, NULL) == expect, message); @@ -280,7 +289,7 @@ class TestBuilder } else { creditTx = BuildCreditingTransaction(redeemScript); } - spendTx = BuildSpendingTransaction(CScript(), creditTx); + spendTx = BuildSpendingTransaction(CScript(), CScriptWitness(), creditTx); } TestBuilder& ScriptError(ScriptError_t err) @@ -363,7 +372,7 @@ class TestBuilder { TestBuilder copy = *this; // Make a copy so we can rollback the push. DoPush(); - DoTest(creditTx.vout[0].scriptPubKey, spendTx.vin[0].scriptSig, flags, comment, scriptError); + DoTest(creditTx.vout[0].scriptPubKey, spendTx.vin[0].scriptSig, CScriptWitness(), flags, comment, scriptError); *this = copy; return *this; } @@ -706,7 +715,7 @@ BOOST_AUTO_TEST_CASE(script_json_test) { // Read tests from test/data/script_tests.json // Format is an array of arrays - // Inner arrays are [ "scriptSig", "scriptPubKey", "flags", "expected_scripterror" ] + // Inner arrays are [ ["wit"...]?, "scriptSig", "scriptPubKey", "flags", "expected_scripterror" ] // ... where scriptSig and scriptPubKey are stringified // scripts. UniValue tests = read_json(std::string(json_tests::script_tests, json_tests::script_tests + sizeof(json_tests::script_tests))); @@ -714,21 +723,29 @@ BOOST_AUTO_TEST_CASE(script_json_test) for (unsigned int idx = 0; idx < tests.size(); idx++) { UniValue test = tests[idx]; string strTest = test.write(); - if (test.size() < 4) // Allow size > 3; extra stuff ignored (useful for comments) + CScriptWitness witness; + unsigned int pos = 0; + if (test.size() > 0 && test[pos].isArray()) { + for (unsigned int i = 0; i < test[pos].size(); i++) { + witness.stack.push_back(ParseHex(test[pos][i].get_str())); + } + pos++; + } + if (test.size() < 4 + pos) // Allow size > 3; extra stuff ignored (useful for comments) { if (test.size() != 1) { BOOST_ERROR("Bad test: " << strTest); } continue; } - string scriptSigString = test[0].get_str(); + string scriptSigString = test[pos++].get_str(); CScript scriptSig = ParseScript(scriptSigString); - string scriptPubKeyString = test[1].get_str(); + string scriptPubKeyString = test[pos++].get_str(); CScript scriptPubKey = ParseScript(scriptPubKeyString); - unsigned int scriptflags = ParseScriptFlags(test[2].get_str()); - int scriptError = ParseScriptError(test[3].get_str()); + unsigned int scriptflags = ParseScriptFlags(test[pos++].get_str()); + int scriptError = ParseScriptError(test[pos++].get_str()); - DoTest(scriptPubKey, scriptSig, scriptflags, strTest, scriptError); + DoTest(scriptPubKey, scriptSig, witness, scriptflags, strTest, scriptError); } } @@ -806,7 +823,7 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12) scriptPubKey12 << OP_1 << ToByteVector(key1.GetPubKey()) << ToByteVector(key2.GetPubKey()) << OP_2 << OP_CHECKMULTISIG; CMutableTransaction txFrom12 = BuildCreditingTransaction(scriptPubKey12); - CMutableTransaction txTo12 = BuildSpendingTransaction(CScript(), txFrom12); + CMutableTransaction txTo12 = BuildSpendingTransaction(CScript(), CScriptWitness(), txFrom12); CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12); BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, NULL, flags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err)); @@ -837,7 +854,7 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23) scriptPubKey23 << OP_2 << ToByteVector(key1.GetPubKey()) << ToByteVector(key2.GetPubKey()) << ToByteVector(key3.GetPubKey()) << OP_3 << OP_CHECKMULTISIG; CMutableTransaction txFrom23 = BuildCreditingTransaction(scriptPubKey23); - CMutableTransaction txTo23 = BuildSpendingTransaction(CScript(), txFrom23); + CMutableTransaction txTo23 = BuildSpendingTransaction(CScript(), CScriptWitness(), txFrom23); std::vector keys; keys.push_back(key1); keys.push_back(key2); @@ -910,7 +927,7 @@ BOOST_AUTO_TEST_CASE(script_combineSigs) } CMutableTransaction txFrom = BuildCreditingTransaction(GetScriptForDestination(keys[0].GetPubKey().GetID())); - CMutableTransaction txTo = BuildSpendingTransaction(CScript(), txFrom); + CMutableTransaction txTo = BuildSpendingTransaction(CScript(), CScriptWitness(), txFrom); CScript& scriptPubKey = txFrom.vout[0].scriptPubKey; CScript& scriptSig = txTo.vin[0].scriptSig; From 66cca79130a204277e61088b7844b405dc3868a5 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 5 Apr 2016 13:37:24 +0200 Subject: [PATCH 0556/1802] [qa] Autogeneration support for witness in script_tests --- src/test/data/script_tests.json | 132 ++++++++++++++++++++++++++++++++ src/test/script_tests.cpp | 105 ++++++++++++++++++++++--- 2 files changed, 227 insertions(+), 10 deletions(-) diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json index f6ee7ade42530..4311b0923fbec 100644 --- a/src/test/data/script_tests.json +++ b/src/test/data/script_tests.json @@ -1834,6 +1834,138 @@ "OK", "P2SH with CLEANSTACK" ], +[ + [ + "3044022039105b995a5f448639a997a5c90fda06f50b49df30c3bdb6663217bf79323db002206fecd54269dec569fcc517178880eb58bb40f381a282bb75766ff3637d5f4b4301", + "410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac" + ], + "", + "0 0x20 0xb95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64", + "P2SH,WITNESS", + "OK", + "Basic P2WSH" +], +[ + [ + "304402201a96950593cb0af32d080b0f193517f4559241a8ebd1e95e414533ad64a3f423022047f4f6d3095c23235bdff3aeff480d0529c027a3f093cb265b7cbf148553b85101", + "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8" + ], + "", + "0 0x14 0x91b24bf9f5288532960ac687abb035127b1d28a5", + "P2SH,WITNESS", + "OK", + "Basic P2WPKH" +], +[ + [ + "3044022061fc1a144e221ec77a58a4281936eb6a1b715b9349e446e74d106ec26c8633ba022008064a0d112e8ad514440fcdfaa1006e48305d6844f50a65873fb4b2cf9c035f01", + "410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac" + ], + "0x22 0x0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64", + "HASH160 0x14 0xf386c2ba255cc56d20cfa6ea8b062f8b59945518 EQUAL", + "P2SH,WITNESS", + "OK", + "Basic P2SH(P2WSH)" +], +[ + [ + "3044022014e69768e174972f21d32d93002ca6fc26133cb9e819ceef7efb970798bde7b4022078b86849dbbec692ec9355aa2a763fce7ea11bf72fdd8ea5ea8083de6f8a77fe01", + "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8" + ], + "0x16 0x001491b24bf9f5288532960ac687abb035127b1d28a5", + "HASH160 0x14 0x17743beb429c55c942d2ec703b98c4d57c2df5c6 EQUAL", + "P2SH,WITNESS", + "OK", + "Basic P2SH(P2WPKH)" +], +[ + [ + "304402202589f0512cb2408fb08ed9bd24f85eb3059744d9e4f2262d0b7f1338cff6e8b902206c0978f449693e0578c71bc543b11079fd0baae700ee5e9a6bee94db490af9fc01", + "41048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26cafac" + ], + "", + "0 0x20 0xac8ebd9e52c17619a381fa4f71aebb696087c6ef17c960fd0587addad99c0610", + "P2SH,WITNESS", + "EVAL_FALSE", + "Basic P2WSH with the wrong key" +], +[ + [ + "304402206ef7fdb2986325d37c6eb1a8bb24aeb46dede112ed8fc76c7d7500b9b83c0d3d02201edc2322c794fe2d6b0bd73ed319e714aa9b86d8891961530d5c9b7156b60d4e01", + "048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf" + ], + "", + "0 0x14 0x7cf9c846cd4882efec4bf07e44ebdad495c94f4b", + "P2SH,WITNESS", + "EVAL_FALSE", + "Basic P2WPKH with the wrong key" +], +[ + [ + "30440220069ea3581afaf8187f63feee1fd2bd1f9c0dc71ea7d6e8a8b07ee2ebcf824bf402201a4fdef4c532eae59223be1eda6a397fc835142d4ddc6c74f4aa85b766a5c16f01", + "41048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26cafac" + ], + "0x22 0x0020ac8ebd9e52c17619a381fa4f71aebb696087c6ef17c960fd0587addad99c0610", + "HASH160 0x14 0x61039a003883787c0d6ebc66d97fdabe8e31449d EQUAL", + "P2SH,WITNESS", + "EVAL_FALSE", + "Basic P2SH(P2WSH) with the wrong key" +], +[ + [ + "304402204209e49457c2358f80d0256bc24535b8754c14d08840fc4be762d6f5a0aed80b02202eaf7d8fc8d62f60c67adcd99295528d0e491ae93c195cec5a67e7a09532a88001", + "048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf" + ], + "0x16 0x00147cf9c846cd4882efec4bf07e44ebdad495c94f4b", + "HASH160 0x14 0x4e0c2aed91315303fc6a1dc4c7bc21c88f75402e EQUAL", + "P2SH,WITNESS", + "EVAL_FALSE", + "Basic P2SH(P2WPKH) with the wrong key" +], +[ + [ + "304402202589f0512cb2408fb08ed9bd24f85eb3059744d9e4f2262d0b7f1338cff6e8b902206c0978f449693e0578c71bc543b11079fd0baae700ee5e9a6bee94db490af9fc01", + "41048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26cafac" + ], + "", + "0 0x20 0xac8ebd9e52c17619a381fa4f71aebb696087c6ef17c960fd0587addad99c0610", + "P2SH", + "OK", + "Basic P2WSH with the wrong key but no WITNESS" +], +[ + [ + "304402206ef7fdb2986325d37c6eb1a8bb24aeb46dede112ed8fc76c7d7500b9b83c0d3d02201edc2322c794fe2d6b0bd73ed319e714aa9b86d8891961530d5c9b7156b60d4e01", + "048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf" + ], + "", + "0 0x14 0x7cf9c846cd4882efec4bf07e44ebdad495c94f4b", + "P2SH", + "OK", + "Basic P2WPKH with the wrong key but no WITNESS" +], +[ + [ + "30440220069ea3581afaf8187f63feee1fd2bd1f9c0dc71ea7d6e8a8b07ee2ebcf824bf402201a4fdef4c532eae59223be1eda6a397fc835142d4ddc6c74f4aa85b766a5c16f01", + "41048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26cafac" + ], + "0x22 0x0020ac8ebd9e52c17619a381fa4f71aebb696087c6ef17c960fd0587addad99c0610", + "HASH160 0x14 0x61039a003883787c0d6ebc66d97fdabe8e31449d EQUAL", + "P2SH", + "OK", + "Basic P2SH(P2WSH) with the wrong key but no WITNESS" +], +[ + [ + "304402204209e49457c2358f80d0256bc24535b8754c14d08840fc4be762d6f5a0aed80b02202eaf7d8fc8d62f60c67adcd99295528d0e491ae93c195cec5a67e7a09532a88001", + "048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf" + ], + "0x16 0x00147cf9c846cd4882efec4bf07e44ebdad495c94f4b", + "HASH160 0x14 0x4e0c2aed91315303fc6a1dc4c7bc21c88f75402e EQUAL", + "P2SH", + "OK", + "Basic P2SH(P2WPKH) with the wrong key but no WITNESS" +], ["CHECKSEQUENCEVERIFY tests"], ["", "NOP3", "CHECKSEQUENCEVERIFY", "INVALID_STACK_OPERATION", "CSV automatically fails on a empty stack"], diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 88f1562b103b0..ab373edc90cf5 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -167,7 +167,7 @@ void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, const CScript BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, &scriptWitness, flags, MutableTransactionSignatureChecker(&tx, 0, txCredit.vout[0].nValue), &err) == expect, message); BOOST_CHECK_MESSAGE(err == scriptError, std::string(FormatScriptError(err)) + " where " + std::string(FormatScriptError((ScriptError_t)scriptError)) + " expected: " + message); #if defined(HAVE_CONSENSUS_LIB) - CDataStream stream(SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_WITNESS); + CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); stream << tx2; if (flags & bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS) { BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script_with_amount(begin_ptr(scriptPubKey), scriptPubKey.size(), txCredit.vout[0].nValue, (const unsigned char*)&stream[0], stream.size(), 0, flags, NULL) == expect, message); @@ -253,11 +253,22 @@ struct KeyData } }; +enum WitnessMode { + WITNESS_NONE, + WITNESS_PKH, + WITNESS_SH +}; class TestBuilder { private: - CScript scriptPubKey; + //! Actually executed script + CScript script; + //! The P2SH redeemscript + CScript redeemscript; + //! The Witness embedded script + CScript witscript; + CScriptWitness scriptWitness; CTransaction creditTx; CMutableTransaction spendTx; bool havePush; @@ -282,13 +293,25 @@ class TestBuilder } public: - TestBuilder(const CScript& redeemScript, const std::string& comment_, int flags_, bool P2SH = false) : scriptPubKey(redeemScript), havePush(false), comment(comment_), flags(flags_), scriptError(SCRIPT_ERR_OK) + TestBuilder(const CScript& script_, const std::string& comment_, int flags_, bool P2SH = false, WitnessMode wm = WITNESS_NONE) : script(script_), havePush(false), comment(comment_), flags(flags_), scriptError(SCRIPT_ERR_OK) { + CScript scriptPubKey = script; + if (wm == WITNESS_PKH) { + uint160 hash; + CHash160().Write(&script[1], script.size() - 1).Finalize(hash.begin()); + script = CScript() << OP_DUP << OP_HASH160 << ToByteVector(hash) << OP_EQUALVERIFY << OP_CHECKSIG; + scriptPubKey = CScript() << OP_0 << ToByteVector(hash); + } else if (wm == WITNESS_SH) { + witscript = scriptPubKey; + uint256 hash; + CSHA256().Write(&witscript[0], witscript.size()).Finalize(hash.begin()); + scriptPubKey = CScript() << OP_0 << ToByteVector(hash); + } if (P2SH) { - creditTx = BuildCreditingTransaction(CScript() << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL); - } else { - creditTx = BuildCreditingTransaction(redeemScript); + redeemscript = scriptPubKey; + scriptPubKey = CScript() << OP_HASH160 << ToByteVector(CScriptID(redeemscript)) << OP_EQUAL; } + creditTx = BuildCreditingTransaction(scriptPubKey); spendTx = BuildSpendingTransaction(CScript(), CScriptWitness(), creditTx); } @@ -318,9 +341,9 @@ class TestBuilder return *this; } - TestBuilder& PushSig(const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32) + TestBuilder& PushSig(const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32, SigVersion sigversion = SIGVERSION_BASE) { - uint256 hash = SignatureHash(scriptPubKey, spendTx, 0, nHashType, 0, SIGVERSION_BASE); + uint256 hash = SignatureHash(script, spendTx, 0, nHashType, 0, sigversion); std::vector vchSig, r, s; uint32_t iter = 0; do { @@ -336,6 +359,11 @@ class TestBuilder return *this; } + TestBuilder& PushWitSig(const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32, SigVersion sigversion = SIGVERSION_WITNESS_V0) + { + return PushSig(key, nHashType, lenR, lenS, sigversion).AsWit(); + } + TestBuilder& Push(const CPubKey& pubkey) { DoPush(std::vector(pubkey.begin(), pubkey.end())); @@ -344,10 +372,16 @@ class TestBuilder TestBuilder& PushRedeem() { - DoPush(std::vector(scriptPubKey.begin(), scriptPubKey.end())); + DoPush(std::vector(redeemscript.begin(), redeemscript.end())); return *this; } + TestBuilder& PushWitRedeem() + { + DoPush(std::vector(witscript.begin(), witscript.end())); + return AsWit(); + } + TestBuilder& EditPush(unsigned int pos, const std::string& hexin, const std::string& hexout) { assert(havePush); @@ -372,15 +406,30 @@ class TestBuilder { TestBuilder copy = *this; // Make a copy so we can rollback the push. DoPush(); - DoTest(creditTx.vout[0].scriptPubKey, spendTx.vin[0].scriptSig, CScriptWitness(), flags, comment, scriptError); + DoTest(creditTx.vout[0].scriptPubKey, spendTx.vin[0].scriptSig, scriptWitness, flags, comment, scriptError); *this = copy; return *this; } + TestBuilder& AsWit() + { + assert(havePush); + scriptWitness.stack.push_back(push); + havePush = false; + return *this; + } + UniValue GetJSON() { DoPush(); UniValue array(UniValue::VARR); + if (!scriptWitness.stack.empty()) { + UniValue wit(UniValue::VARR); + for (unsigned i = 0; i < scriptWitness.stack.size(); i++) { + wit.push_back(HexStr(scriptWitness.stack[i])); + } + array.push_back(wit); + } array.push_back(FormatScript(spendTx.vin[0].scriptSig)); array.push_back(FormatScript(creditTx.vout[0].scriptPubKey)); array.push_back(FormatScriptFlags(flags)); @@ -679,6 +728,42 @@ BOOST_AUTO_TEST_CASE(script_build) "P2SH with CLEANSTACK", SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_P2SH, true ).PushSig(keys.key0).PushRedeem()); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, + "Basic P2WSH", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH + ).PushWitSig(keys.key0).PushWitRedeem()); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0), + "Basic P2WPKH", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_PKH + ).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit()); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, + "Basic P2SH(P2WSH)", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_SH + ).PushWitSig(keys.key0).PushWitRedeem().PushRedeem()); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0), + "Basic P2SH(P2WPKH)", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_PKH + ).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().PushRedeem()); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG, + "Basic P2WSH with the wrong key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH + ).PushWitSig(keys.key0).PushWitRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1), + "Basic P2WPKH with the wrong key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_PKH + ).PushWitSig(keys.key0).Push(keys.pubkey1).AsWit().ScriptError(SCRIPT_ERR_EVAL_FALSE)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG, + "Basic P2SH(P2WSH) with the wrong key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_SH + ).PushWitSig(keys.key0).PushWitRedeem().PushRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1), + "Basic P2SH(P2WPKH) with the wrong key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_PKH + ).PushWitSig(keys.key0).Push(keys.pubkey1).AsWit().PushRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG, + "Basic P2WSH with the wrong key but no WITNESS", SCRIPT_VERIFY_P2SH, false, WITNESS_SH + ).PushWitSig(keys.key0).PushWitRedeem()); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1), + "Basic P2WPKH with the wrong key but no WITNESS", SCRIPT_VERIFY_P2SH, false, WITNESS_PKH + ).PushWitSig(keys.key0).Push(keys.pubkey1).AsWit()); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG, + "Basic P2SH(P2WSH) with the wrong key but no WITNESS", SCRIPT_VERIFY_P2SH, true, WITNESS_SH + ).PushWitSig(keys.key0).PushWitRedeem().PushRedeem()); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1), + "Basic P2SH(P2WPKH) with the wrong key but no WITNESS", SCRIPT_VERIFY_P2SH, true, WITNESS_PKH + ).PushWitSig(keys.key0).Push(keys.pubkey1).AsWit().PushRedeem()); std::set tests_set; From 4f7ff00497803fddc5a0fb5340502a73e395134d Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Fri, 1 Jan 2016 23:18:34 -0600 Subject: [PATCH 0557/1802] [qa] Add rpc test for segwit Amended by Pieter Wuille to use multisig 1-of-1 for P2WSH tests, and BIP9 based switchover logic. Fixes and py3 conversion by Marco Falke. --- contrib/devtools/check-doc.py | 2 +- qa/pull-tester/rpc-tests.py | 1 + qa/rpc-tests/segwit.py | 209 ++++++++++++++++++++++++++++++++++ src/main.cpp | 15 ++- src/wallet/rpcwallet.cpp | 2 +- 5 files changed, 222 insertions(+), 7 deletions(-) create mode 100755 qa/rpc-tests/segwit.py diff --git a/contrib/devtools/check-doc.py b/contrib/devtools/check-doc.py index 8c73cf1e8a735..06c9551cebae5 100755 --- a/contrib/devtools/check-doc.py +++ b/contrib/devtools/check-doc.py @@ -21,7 +21,7 @@ REGEX_ARG = re.compile(r'(?:map(?:Multi)?Args(?:\.count\(|\[)|Get(?:Bool)?Arg\()\"(\-[^\"]+?)\"') REGEX_DOC = re.compile(r'HelpMessageOpt\(\"(\-[^\"=]+?)(?:=|\")') # list unsupported, deprecated and duplicate args as they need no documentation -SET_DOC_OPTIONAL = set(['-rpcssl', '-benchmark', '-h', '-help', '-socks', '-tor', '-debugnet', '-whitelistalwaysrelay']) +SET_DOC_OPTIONAL = set(['-rpcssl', '-benchmark', '-h', '-help', '-socks', '-tor', '-debugnet', '-whitelistalwaysrelay', '-prematurewitness', '-walletprematurewitness', '-promiscuousmempoolflags']) def main(): used = check_output(CMD_GREP_ARGS, shell=True) diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index 6c0ed4510f103..8fa20945e665b 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -136,6 +136,7 @@ 'invalidtxrequest.py', 'abandonconflict.py', 'p2p-versionbits-warning.py', + 'segwit.py', 'importprunedfunds.py', 'signmessages.py', ] diff --git a/qa/rpc-tests/segwit.py b/qa/rpc-tests/segwit.py new file mode 100755 index 0000000000000..d4c9a8afed32c --- /dev/null +++ b/qa/rpc-tests/segwit.py @@ -0,0 +1,209 @@ +#!/usr/bin/env python3 +# Copyright (c) 2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# +# Test the SegWit changeover logic +# + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * +from test_framework.mininode import sha256, ripemd160 +import os +import shutil + +NODE_0 = 0 +NODE_1 = 1 +NODE_2 = 2 +WIT_V0 = 0 +WIT_V1 = 1 + +def witness_script(version, pubkey): + if (version == 0): + pubkeyhash = bytes_to_hex_str(ripemd160(sha256(hex_str_to_bytes(pubkey)))) + pkscript = "0014" + pubkeyhash + elif (version == 1): + # 1-of-1 multisig + scripthash = bytes_to_hex_str(sha256(hex_str_to_bytes("5121" + pubkey + "51ae"))) + pkscript = "0020" + scripthash + else: + assert("Wrong version" == "0 or 1") + return pkscript + +def addlength(script): + scriptlen = format(len(script)//2, 'x') + assert(len(scriptlen) == 2) + return scriptlen + script + +def create_witnessprogram(version, node, utxo, pubkey, encode_p2sh, amount): + pkscript = witness_script(version, pubkey); + if (encode_p2sh): + p2sh_hash = bytes_to_hex_str(ripemd160(sha256(hex_str_to_bytes(pkscript)))) + pkscript = "a914"+p2sh_hash+"87" + inputs = [] + outputs = {} + inputs.append({ "txid" : utxo["txid"], "vout" : utxo["vout"]} ) + DUMMY_P2SH = "2MySexEGVzZpRgNQ1JdjdP5bRETznm3roQ2" # P2SH of "OP_1 OP_DROP" + outputs[DUMMY_P2SH] = amount + tx_to_witness = node.createrawtransaction(inputs,outputs) + #replace dummy output with our own + tx_to_witness = tx_to_witness[0:110] + addlength(pkscript) + tx_to_witness[-8:] + return tx_to_witness + +def send_to_witness(version, node, utxo, pubkey, encode_p2sh, amount, sign=True, insert_redeem_script=""): + tx_to_witness = create_witnessprogram(version, node, utxo, pubkey, encode_p2sh, amount) + if (sign): + signed = node.signrawtransaction(tx_to_witness) + assert("errors" not in signed or len(["errors"]) == 0) + return node.sendrawtransaction(signed["hex"]) + else: + if (insert_redeem_script): + tx_to_witness = tx_to_witness[0:82] + addlength(insert_redeem_script) + tx_to_witness[84:] + + return node.sendrawtransaction(tx_to_witness) + +def getutxo(txid): + utxo = {} + utxo["vout"] = 0 + utxo["txid"] = txid + return utxo + +class SegWitTest(BitcoinTestFramework): + + def setup_chain(self): + print("Initializing test directory "+self.options.tmpdir) + initialize_chain_clean(self.options.tmpdir, 3) + + def setup_network(self): + self.nodes = [] + self.nodes.append(start_node(0, self.options.tmpdir, ["-logtimemicros", "-debug", "-walletprematurewitness"])) + self.nodes.append(start_node(1, self.options.tmpdir, ["-logtimemicros", "-debug", "-blockversion=4", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness"])) + self.nodes.append(start_node(2, self.options.tmpdir, ["-logtimemicros", "-debug", "-blockversion=536870915", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness"])) + connect_nodes(self.nodes[1], 0) + connect_nodes(self.nodes[2], 1) + connect_nodes(self.nodes[0], 2) + self.is_network_split = False + self.sync_all() + + def success_mine(self, node, txid, sign, redeem_script=""): + send_to_witness(1, node, getutxo(txid), self.pubkey[0], False, Decimal("49.998"), sign, redeem_script) + block = node.generate(1) + assert_equal(len(node.getblock(block[0])["tx"]), 2) + sync_blocks(self.nodes) + + def skip_mine(self, node, txid, sign, redeem_script=""): + send_to_witness(1, node, getutxo(txid), self.pubkey[0], False, Decimal("49.998"), sign, redeem_script) + block = node.generate(1) + assert_equal(len(node.getblock(block[0])["tx"]), 1) + sync_blocks(self.nodes) + + def fail_accept(self, node, txid, sign, redeem_script=""): + try: + send_to_witness(1, node, getutxo(txid), self.pubkey[0], False, Decimal("49.998"), sign, redeem_script) + except JSONRPCException as exp: + assert(exp.error["code"] == -26) + else: + raise AssertionError("Tx should not have been accepted") + + def fail_mine(self, node, txid, sign, redeem_script=""): + send_to_witness(1, node, getutxo(txid), self.pubkey[0], False, Decimal("49.998"), sign, redeem_script) + try: + node.generate(1) + except JSONRPCException as exp: + assert(exp.error["code"] == -1) + else: + raise AssertionError("Created valid block when TestBlockValidity should have failed") + sync_blocks(self.nodes) + + def run_test(self): + self.nodes[0].generate(160) #block 160 + + self.pubkey = [] + p2sh_ids = [] # p2sh_ids[NODE][VER] is an array of txids that spend to a witness version VER pkscript to an address for NODE embedded in p2sh + wit_ids = [] # wit_ids[NODE][VER] is an array of txids that spend to a witness version VER pkscript to an address for NODE via bare witness + for i in range(3): + newaddress = self.nodes[i].getnewaddress() + self.pubkey.append(self.nodes[i].validateaddress(newaddress)["pubkey"]) + multiaddress = self.nodes[i].addmultisigaddress(1, [self.pubkey[-1]]) + self.nodes[i].addwitnessaddress(newaddress) + self.nodes[i].addwitnessaddress(multiaddress) + p2sh_ids.append([]) + wit_ids.append([]) + for v in range(2): + p2sh_ids[i].append([]) + wit_ids[i].append([]) + + for i in range(5): + for n in range(3): + for v in range(2): + wit_ids[n][v].append(send_to_witness(v, self.nodes[0], self.nodes[0].listunspent()[0], self.pubkey[n], False, Decimal("49.999"))) + p2sh_ids[n][v].append(send_to_witness(v, self.nodes[0], self.nodes[0].listunspent()[0], self.pubkey[n], True, Decimal("49.999"))) + + self.nodes[0].generate(1) #block 161 + sync_blocks(self.nodes) + + # Make sure all nodes recognize the transactions as theirs + assert_equal(self.nodes[0].getbalance(), 60*50 - 60*50 + 20*Decimal("49.999") + 50) + assert_equal(self.nodes[1].getbalance(), 20*Decimal("49.999")) + assert_equal(self.nodes[2].getbalance(), 20*Decimal("49.999")) + + self.nodes[0].generate(262) #block 423 + sync_blocks(self.nodes) + + print("Verify default node can't accept any witness format txs before fork") + # unsigned, no scriptsig + self.fail_accept(self.nodes[0], wit_ids[NODE_0][WIT_V0][0], False) + self.fail_accept(self.nodes[0], wit_ids[NODE_0][WIT_V1][0], False) + self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V0][0], False) + self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V1][0], False) + # unsigned with redeem script + self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V0][0], False, addlength(witness_script(0, self.pubkey[0]))) + self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V1][0], False, addlength(witness_script(1, self.pubkey[0]))) + # signed + self.fail_accept(self.nodes[0], wit_ids[NODE_0][WIT_V0][0], True) + self.fail_accept(self.nodes[0], wit_ids[NODE_0][WIT_V1][0], True) + self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V0][0], True) + self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V1][0], True) + + print("Verify witness txs are skipped for mining before the fork") + self.skip_mine(self.nodes[2], wit_ids[NODE_2][WIT_V0][0], True) #block 424 + self.skip_mine(self.nodes[2], wit_ids[NODE_2][WIT_V1][0], True) #block 425 + self.skip_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][0], True) #block 426 + self.skip_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][0], True) #block 427 + + # TODO: An old node would see these txs without witnesses and be able to mine them + + print("Verify unsigned bare witness txs in versionbits-setting blocks are valid before the fork") + self.success_mine(self.nodes[2], wit_ids[NODE_2][WIT_V0][1], False) #block 428 + self.success_mine(self.nodes[2], wit_ids[NODE_2][WIT_V1][1], False) #block 429 + + print("Verify unsigned p2sh witness txs without a redeem script are invalid") + self.fail_accept(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][1], False) + self.fail_accept(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][1], False) + + print("Verify unsigned p2sh witness txs with a redeem script in versionbits-settings blocks are valid before the fork") + self.success_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][1], False, addlength(witness_script(0, self.pubkey[2]))) #block 430 + self.success_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][1], False, addlength(witness_script(1, self.pubkey[2]))) #block 431 + + print("Verify previous witness txs skipped for mining can now be mined") + assert_equal(len(self.nodes[2].getrawmempool()), 4) + block = self.nodes[2].generate(1) #block 432 (first block with new rules; 432 = 144 * 3) + sync_blocks(self.nodes) + assert_equal(len(self.nodes[2].getrawmempool()), 0) + assert_equal(len(self.nodes[2].getblock(block[0])["tx"]), 5) + + print("Verify witness txs without witness data are invalid after the fork") + self.fail_mine(self.nodes[2], wit_ids[NODE_2][WIT_V0][2], False) + self.fail_mine(self.nodes[2], wit_ids[NODE_2][WIT_V1][2], False) + self.fail_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][2], False, addlength(witness_script(0, self.pubkey[2]))) + self.fail_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][2], False, addlength(witness_script(1, self.pubkey[2]))) + + print("Verify default node can now use witness txs") + self.success_mine(self.nodes[0], wit_ids[NODE_0][WIT_V0][0], True) #block 432 + self.success_mine(self.nodes[0], wit_ids[NODE_0][WIT_V1][0], True) #block 433 + self.success_mine(self.nodes[0], p2sh_ids[NODE_0][WIT_V0][0], True) #block 434 + self.success_mine(self.nodes[0], p2sh_ids[NODE_0][WIT_V1][0], True) #block 435 + +if __name__ == '__main__': + SegWitTest().main() diff --git a/src/main.cpp b/src/main.cpp index d1ba70313e3b3..6cdd55e3979df 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1145,8 +1145,8 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C return state.DoS(0, false, REJECT_NONSTANDARD, "premature-version2-tx"); } - // Don't accept witness transactions before the final threshold passes - if (!tx.wit.IsNull() && !IsWitnessEnabled(chainActive.Tip(), Params().GetConsensus())) { + // Reject transactions with witness before segregated witness activates (override with -prematurewitness) + if (!GetBoolArg("-prematurewitness",false) && !tx.wit.IsNull() && !IsWitnessEnabled(chainActive.Tip(), Params().GetConsensus())) { return state.DoS(0, false, REJECT_NONSTANDARD, "no-witness-yet", true); } @@ -1487,14 +1487,19 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C } } + unsigned int scriptVerifyFlags = STANDARD_SCRIPT_VERIFY_FLAGS; + if (!Params().RequireStandard()) { + scriptVerifyFlags = GetArg("-promiscuousmempoolflags", scriptVerifyFlags); + } + // Check against previous transactions // This is done last to help prevent CPU exhaustion denial-of-service attacks. - if (!CheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true)) { + if (!CheckInputs(tx, state, view, true, scriptVerifyFlags, true)) { // SCRIPT_VERIFY_CLEANSTACK requires SCRIPT_VERIFY_WITNESS, so we // need to turn both off, and compare against just turning off CLEANSTACK // to see if the failure is specifically due to witness validation. - if (CheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS & ~(SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_CLEANSTACK), true) && - !CheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS & ~SCRIPT_VERIFY_CLEANSTACK, true)) { + if (CheckInputs(tx, state, view, true, scriptVerifyFlags & ~(SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_CLEANSTACK), true) && + !CheckInputs(tx, state, view, true, scriptVerifyFlags & ~SCRIPT_VERIFY_CLEANSTACK, true)) { // Only the witness is wrong, so the transaction itself may be fine. state.SetCorruptionPossible(); } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index afbb9a1113f48..8538f880ff636 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -1072,7 +1072,7 @@ UniValue addwitnessaddress(const UniValue& params, bool fHelp) { LOCK(cs_main); - if (!IsWitnessEnabled(chainActive.Tip(), Params().GetConsensus())) { + if (!IsWitnessEnabled(chainActive.Tip(), Params().GetConsensus()) && !GetBoolArg("-walletprematurewitness", false)) { throw JSONRPCError(RPC_WALLET_ERROR, "Segregated witness not enabled on network"); } } From 330b0f31ee5719d94f9e52dfc83c5d82168241f9 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Fri, 8 Apr 2016 21:02:24 -0400 Subject: [PATCH 0558/1802] [qa] p2p segwit tests mininode now supports witness transactions/blocks, blocktools has a helper for adding witness commitments to blocks, and script has a function to calculate hashes for signature under sigversion 1, used by segwit. Py3 conversion by Marco Falke Test to make sure upgraded nodes don't ask for non-wit blocks by Gregory Sanders. --- qa/pull-tester/rpc-tests.py | 1 + qa/rpc-tests/p2p-segwit.py | 1646 +++++++++++++++++++++ qa/rpc-tests/test_framework/blocktools.py | 25 +- qa/rpc-tests/test_framework/mininode.py | 212 ++- qa/rpc-tests/test_framework/script.py | 52 +- src/test/data/script_tests.json | 84 ++ src/test/script_tests.cpp | 47 +- 7 files changed, 2037 insertions(+), 30 deletions(-) create mode 100755 qa/rpc-tests/p2p-segwit.py diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index 8fa20945e665b..37979a933fc29 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -136,6 +136,7 @@ 'invalidtxrequest.py', 'abandonconflict.py', 'p2p-versionbits-warning.py', + 'p2p-segwit.py', 'segwit.py', 'importprunedfunds.py', 'signmessages.py', diff --git a/qa/rpc-tests/p2p-segwit.py b/qa/rpc-tests/p2p-segwit.py new file mode 100755 index 0000000000000..cf78954f286bc --- /dev/null +++ b/qa/rpc-tests/p2p-segwit.py @@ -0,0 +1,1646 @@ +#!/usr/bin/env python3 +# Copyright (c) 2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +from test_framework.mininode import * +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * +from test_framework.script import * +from test_framework.blocktools import create_block, create_coinbase, add_witness_commitment, WITNESS_COMMITMENT_HEADER +from test_framework.key import CECKey, CPubKey +import time +import random +from binascii import hexlify + +# The versionbit bit used to signal activation of SegWit +VB_WITNESS_BIT = 1 +VB_PERIOD = 144 +VB_ACTIVATION_THRESHOLD = 108 +VB_TOP_BITS = 0x20000000 + +MAX_SIGOP_COST = 80000 + +''' +SegWit p2p test. +''' + +# Calculate the virtual size of a witness block: +# (base + witness/4) +def get_virtual_size(witness_block): + base_size = len(witness_block.serialize()) + total_size = len(witness_block.serialize(with_witness=True)) + # the "+3" is so we round up + vsize = int((3*base_size + total_size + 3)/4) + return vsize + +# Note: we can reduce code by using SingleNodeConnCB (in master, not 0.12) +class TestNode(NodeConnCB): + def __init__(self): + NodeConnCB.__init__(self) + self.connection = None + self.ping_counter = 1 + self.last_pong = msg_pong(0) + self.sleep_time = 0.05 + self.getdataset = set() + + def add_connection(self, conn): + self.connection = conn + + # Wrapper for the NodeConn's send_message function + def send_message(self, message): + self.connection.send_message(message) + + def on_inv(self, conn, message): + self.last_inv = message + + def on_block(self, conn, message): + self.last_block = message.block + self.last_block.calc_sha256() + + def on_getdata(self, conn, message): + for inv in message.inv: + self.getdataset.add(inv.hash) + self.last_getdata = message + + def on_pong(self, conn, message): + self.last_pong = message + + def on_reject(self, conn, message): + self.last_reject = message + #print message + + # Syncing helpers + def sync(self, test_function, timeout=60): + while timeout > 0: + with mininode_lock: + if test_function(): + return + time.sleep(self.sleep_time) + timeout -= self.sleep_time + raise AssertionError("Sync failed to complete") + + def sync_with_ping(self, timeout=60): + self.send_message(msg_ping(nonce=self.ping_counter)) + test_function = lambda: self.last_pong.nonce == self.ping_counter + self.sync(test_function, timeout) + self.ping_counter += 1 + return + + def wait_for_block(self, blockhash, timeout=60): + test_function = lambda: self.last_block != None and self.last_block.sha256 == blockhash + self.sync(test_function, timeout) + return + + def wait_for_getdata(self, timeout=60): + test_function = lambda: self.last_getdata != None + self.sync(test_function, timeout) + + def wait_for_inv(self, expected_inv, timeout=60): + test_function = lambda: self.last_inv != expected_inv + self.sync(test_function, timeout) + + def announce_tx_and_wait_for_getdata(self, tx, timeout=60): + with mininode_lock: + self.last_getdata = None + self.send_message(msg_inv(inv=[CInv(1, tx.sha256)])) + self.wait_for_getdata(timeout) + return + + def announce_block_and_wait_for_getdata(self, block, use_header, timeout=60): + with mininode_lock: + self.last_getdata = None + if use_header: + msg = msg_headers() + msg.headers = [ CBlockHeader(block) ] + self.send_message(msg) + else: + self.send_message(msg_inv(inv=[CInv(2, block.sha256)])) + self.wait_for_getdata() + return + + def announce_block(self, block, use_header): + with mininode_lock: + self.last_getdata = None + if use_header: + msg = msg_headers() + msg.headers = [ CBlockHeader(block) ] + self.send_message(msg) + else: + self.send_message(msg_inv(inv=[CInv(2, block.sha256)])) + + def request_block(self, blockhash, inv_type, timeout=60): + with mininode_lock: + self.last_block = None + self.send_message(msg_getdata(inv=[CInv(inv_type, blockhash)])) + self.wait_for_block(blockhash, timeout) + return self.last_block + + def test_transaction_acceptance(self, tx, with_witness, accepted): + tx_message = msg_tx(tx) + if with_witness: + tx_message = msg_witness_tx(tx) + self.send_message(tx_message) + self.sync_with_ping() + assert_equal(tx.hash in self.connection.rpc.getrawmempool(), accepted) + + # Test whether a witness block had the correct effect on the tip + def test_witness_block(self, block, accepted, with_witness=True): + if with_witness: + self.send_message(msg_witness_block(block)) + else: + self.send_message(msg_block(block)) + self.sync_with_ping() + assert_equal(self.connection.rpc.getbestblockhash() == block.hash, accepted) + + +# Used to keep track of anyone-can-spend outputs that we can use in the tests +class UTXO(object): + def __init__(self, sha256, n, nValue): + self.sha256 = sha256 + self.n = n + self.nValue = nValue + + +class SegWitTest(BitcoinTestFramework): + def setup_chain(self): + initialize_chain_clean(self.options.tmpdir, 3) + + def add_options(self, parser): + parser.add_option("--oldbinary", dest="oldbinary", + default=None, + help="pre-segwit bitcoind binary for upgrade testing") + + def setup_network(self): + self.nodes = [] + self.nodes.append(start_node(0, self.options.tmpdir, ["-debug", "-logtimemicros=1", "-whitelist=127.0.0.1"])) + # Start a node for testing IsStandard rules. + self.nodes.append(start_node(1, self.options.tmpdir, ["-debug", "-logtimemicros=1", "-whitelist=127.0.0.1", "-acceptnonstdtxn=0"])) + connect_nodes(self.nodes[0], 1) + + # If an old bitcoind is given, do the upgrade-after-activation test. + self.test_upgrade = False + if (self.options.oldbinary != None): + self.nodes.append(start_node(2, self.options.tmpdir, ["-debug", "-whitelist=127.0.0.1"], binary=self.options.oldbinary)) + connect_nodes(self.nodes[0], 2) + self.test_upgrade = True + + ''' Helpers ''' + # Build a block on top of node0's tip. + def build_next_block(self, nVersion=4): + tip = self.nodes[0].getbestblockhash() + height = self.nodes[0].getblockcount() + 1 + block_time = self.nodes[0].getblockheader(tip)["mediantime"] + 1 + block = create_block(int(tip, 16), create_coinbase(height), block_time) + block.nVersion = nVersion + block.rehash() + return block + + # Adds list of transactions to block, adds witness commitment, then solves. + def update_witness_block_with_transactions(self, block, tx_list, nonce=0): + block.vtx.extend(tx_list) + add_witness_commitment(block, nonce) + block.solve() + return + + ''' Individual tests ''' + def test_witness_services(self): + print("\tVerifying NODE_WITNESS service bit") + assert((self.test_node.connection.nServices & NODE_WITNESS) != 0) + + + # See if sending a regular transaction works, and create a utxo + # to use in later tests. + def test_non_witness_transaction(self): + # Mine a block with an anyone-can-spend coinbase, + # let it mature, then try to spend it. + print("\tTesting non-witness transaction") + block = self.build_next_block(nVersion=1) + block.solve() + self.test_node.send_message(msg_block(block)) + self.test_node.sync_with_ping() # make sure the block was processed + txid = block.vtx[0].sha256 + + self.nodes[0].generate(99) # let the block mature + + # Create a transaction that spends the coinbase + tx = CTransaction() + tx.vin.append(CTxIn(COutPoint(txid, 0), b"")) + tx.vout.append(CTxOut(49*100000000, CScript([OP_TRUE]))) + tx.calc_sha256() + + # Check that serializing it with or without witness is the same + # This is a sanity check of our testing framework. + assert_equal(msg_tx(tx).serialize(), msg_witness_tx(tx).serialize()) + + self.test_node.send_message(msg_witness_tx(tx)) + self.test_node.sync_with_ping() # make sure the tx was processed + assert(tx.hash in self.nodes[0].getrawmempool()) + # Save this transaction for later + self.utxo.append(UTXO(tx.sha256, 0, 49*100000000)) + self.nodes[0].generate(1) + + + # Verify that blocks with witnesses are rejected before activation. + def test_unnecessary_witness_before_segwit_activation(self): + print("\tTesting behavior of unnecessary witnesses") + # For now, rely on earlier tests to have created at least one utxo for + # us to use + assert(len(self.utxo) > 0) + assert(get_bip9_status(self.nodes[0], 'segwit')['status'] != 'active') + + tx = CTransaction() + tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")) + tx.vout.append(CTxOut(self.utxo[0].nValue-1000, CScript([OP_TRUE]))) + tx.wit.vtxinwit.append(CTxinWitness()) + tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([CScriptNum(1)])] + + # Verify the hash with witness differs from the txid + # (otherwise our testing framework must be broken!) + tx.rehash() + assert(tx.sha256 != tx.calc_sha256(with_witness=True)) + + # Construct a segwit-signaling block that includes the transaction. + block = self.build_next_block(nVersion=(VB_TOP_BITS|(1 << VB_WITNESS_BIT))) + self.update_witness_block_with_transactions(block, [tx]) + # Sending witness data before activation is not allowed (anti-spam + # rule). + self.test_node.test_witness_block(block, accepted=False) + # TODO: fix synchronization so we can test reject reason + # Right now, bitcoind delays sending reject messages for blocks + # until the future, making synchronization here difficult. + #assert_equal(self.test_node.last_reject.reason, "unexpected-witness") + + # But it should not be permanently marked bad... + # Resend without witness information. + self.test_node.send_message(msg_block(block)) + self.test_node.sync_with_ping() + assert_equal(self.nodes[0].getbestblockhash(), block.hash) + + # Update our utxo list; we spent the first entry. + self.utxo.pop(0) + self.utxo.append(UTXO(tx.sha256, 0, tx.vout[0].nValue)) + + + # Mine enough blocks for segwit's vb state to be 'started'. + def advance_to_segwit_started(self): + height = self.nodes[0].getblockcount() + # Will need to rewrite the tests here if we are past the first period + assert(height < VB_PERIOD - 1) + # Genesis block is 'defined'. + assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'defined') + # Advance to end of period, status should now be 'started' + self.nodes[0].generate(VB_PERIOD-height-1) + assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'started') + + # Mine enough blocks to lock in segwit, but don't activate. + # TODO: we could verify that lockin only happens at the right threshold of + # signalling blocks, rather than just at the right period boundary. + def advance_to_segwit_lockin(self): + height = self.nodes[0].getblockcount() + assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'started') + # Advance to end of period, and verify lock-in happens at the end + self.nodes[0].generate(VB_PERIOD-1) + height = self.nodes[0].getblockcount() + assert((height % VB_PERIOD) == VB_PERIOD - 2) + assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'started') + self.nodes[0].generate(1) + assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'locked_in') + + + # Mine enough blocks to activate segwit. + # TODO: we could verify that activation only happens at the right threshold + # of signalling blocks, rather than just at the right period boundary. + def advance_to_segwit_active(self): + assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'locked_in') + height = self.nodes[0].getblockcount() + self.nodes[0].generate(VB_PERIOD - (height%VB_PERIOD) - 2) + assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'locked_in') + self.nodes[0].generate(1) + assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'active') + + + # This test can only be run after segwit has activated + def test_witness_commitments(self): + print("\tTesting witness commitments") + + # First try a correct witness commitment. + block = self.build_next_block() + add_witness_commitment(block) + block.solve() + + # Test the test -- witness serialization should be different + assert(msg_witness_block(block).serialize() != msg_block(block).serialize()) + + # This empty block should be valid. + self.test_node.test_witness_block(block, accepted=True) + + # Try to tweak the nonce + block_2 = self.build_next_block() + add_witness_commitment(block_2, nonce=28) + block_2.solve() + + # The commitment should have changed! + assert(block_2.vtx[0].vout[-1] != block.vtx[0].vout[-1]) + + # This should also be valid. + self.test_node.test_witness_block(block_2, accepted=True) + + # Now test commitments with actual transactions + assert (len(self.utxo) > 0) + tx = CTransaction() + tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")) + + # Let's construct a witness program + witness_program = CScript([OP_TRUE]) + witness_hash = sha256(witness_program) + scriptPubKey = CScript([OP_0, witness_hash]) + tx.vout.append(CTxOut(self.utxo[0].nValue-1000, scriptPubKey)) + tx.rehash() + + # tx2 will spend tx1, and send back to a regular anyone-can-spend address + tx2 = CTransaction() + tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b"")) + tx2.vout.append(CTxOut(tx.vout[0].nValue-1000, witness_program)) + tx2.wit.vtxinwit.append(CTxinWitness()) + tx2.wit.vtxinwit[0].scriptWitness.stack = [witness_program] + tx2.rehash() + + block_3 = self.build_next_block() + self.update_witness_block_with_transactions(block_3, [tx, tx2], nonce=1) + # Add an extra OP_RETURN output that matches the witness commitment template, + # even though it has extra data after the incorrect commitment. + # This block should fail. + block_3.vtx[0].vout.append(CTxOut(0, CScript([OP_RETURN, WITNESS_COMMITMENT_HEADER + ser_uint256(2), 10]))) + block_3.vtx[0].rehash() + block_3.hashMerkleRoot = block_3.calc_merkle_root() + block_3.rehash() + block_3.solve() + + self.test_node.test_witness_block(block_3, accepted=False) + + # Add a different commitment with different nonce, but in the + # right location, and with some funds burned(!). + # This should succeed (nValue shouldn't affect finding the + # witness commitment). + add_witness_commitment(block_3, nonce=0) + block_3.vtx[0].vout[0].nValue -= 1 + block_3.vtx[0].vout[-1].nValue += 1 + block_3.vtx[0].rehash() + block_3.hashMerkleRoot = block_3.calc_merkle_root() + block_3.rehash() + assert(len(block_3.vtx[0].vout) == 4) # 3 OP_returns + block_3.solve() + self.test_node.test_witness_block(block_3, accepted=True) + + # Finally test that a block with no witness transactions can + # omit the commitment. + block_4 = self.build_next_block() + tx3 = CTransaction() + tx3.vin.append(CTxIn(COutPoint(tx2.sha256, 0), b"")) + tx3.vout.append(CTxOut(tx.vout[0].nValue-1000, witness_program)) + tx3.rehash() + block_4.vtx.append(tx3) + block_4.hashMerkleRoot = block_4.calc_merkle_root() + block_4.solve() + self.test_node.test_witness_block(block_4, with_witness=False, accepted=True) + + # Update available utxo's for use in later test. + self.utxo.pop(0) + self.utxo.append(UTXO(tx3.sha256, 0, tx3.vout[0].nValue)) + + + def test_block_malleability(self): + print("\tTesting witness block malleability") + + # Make sure that a block that has too big a virtual size + # because of a too-large coinbase witness is not permanently + # marked bad. + block = self.build_next_block() + add_witness_commitment(block) + block.solve() + + block.vtx[0].wit.vtxinwit[0].scriptWitness.stack.append(b'a'*5000000) + assert(get_virtual_size(block) > MAX_BLOCK_SIZE) + + # We can't send over the p2p network, because this is too big to relay + # TODO: repeat this test with a block that can be relayed + self.nodes[0].submitblock(bytes_to_hex_str(block.serialize(True))) + + assert(self.nodes[0].getbestblockhash() != block.hash) + + block.vtx[0].wit.vtxinwit[0].scriptWitness.stack.pop() + assert(get_virtual_size(block) < MAX_BLOCK_SIZE) + self.nodes[0].submitblock(bytes_to_hex_str(block.serialize(True))) + + assert(self.nodes[0].getbestblockhash() == block.hash) + + # Now make sure that malleating the witness nonce doesn't + # result in a block permanently marked bad. + block = self.build_next_block() + add_witness_commitment(block) + block.solve() + + # Change the nonce -- should not cause the block to be permanently + # failed + block.vtx[0].wit.vtxinwit[0].scriptWitness.stack = [ ser_uint256(1) ] + self.test_node.test_witness_block(block, accepted=False) + + # Changing the witness nonce doesn't change the block hash + block.vtx[0].wit.vtxinwit[0].scriptWitness.stack = [ ser_uint256(0) ] + self.test_node.test_witness_block(block, accepted=True) + + + def test_witness_block_size(self): + print("\tTesting witness block size limit") + # TODO: Test that non-witness carrying blocks can't exceed 1MB + # Skipping this test for now; this is covered in p2p-fullblocktest.py + + # Test that witness-bearing blocks are limited at ceil(base + wit/4) <= 1MB. + block = self.build_next_block() + + assert(len(self.utxo) > 0) + + # Create a P2WSH transaction. + # The witness program will be a bunch of OP_2DROP's, followed by OP_TRUE. + # This should give us plenty of room to tweak the spending tx's + # virtual size. + NUM_DROPS = 200 # 201 max ops per script! + NUM_OUTPUTS = 50 + + witness_program = CScript([OP_2DROP]*NUM_DROPS + [OP_TRUE]) + witness_hash = uint256_from_str(sha256(witness_program)) + scriptPubKey = CScript([OP_0, ser_uint256(witness_hash)]) + + prevout = COutPoint(self.utxo[0].sha256, self.utxo[0].n) + value = self.utxo[0].nValue + + parent_tx = CTransaction() + parent_tx.vin.append(CTxIn(prevout, b"")) + child_value = int(value/NUM_OUTPUTS) + for i in range(NUM_OUTPUTS): + parent_tx.vout.append(CTxOut(child_value, scriptPubKey)) + parent_tx.vout[0].nValue -= 50000 + assert(parent_tx.vout[0].nValue > 0) + parent_tx.rehash() + + child_tx = CTransaction() + for i in range(NUM_OUTPUTS): + child_tx.vin.append(CTxIn(COutPoint(parent_tx.sha256, i), b"")) + child_tx.vout = [CTxOut(value - 100000, CScript([OP_TRUE]))] + for i in range(NUM_OUTPUTS): + child_tx.wit.vtxinwit.append(CTxinWitness()) + child_tx.wit.vtxinwit[-1].scriptWitness.stack = [b'a'*195]*(2*NUM_DROPS) + [witness_program] + child_tx.rehash() + self.update_witness_block_with_transactions(block, [parent_tx, child_tx]) + + vsize = get_virtual_size(block) + additional_bytes = (MAX_BLOCK_SIZE - vsize)*4 + i = 0 + while additional_bytes > 0: + # Add some more bytes to each input until we hit MAX_BLOCK_SIZE+1 + extra_bytes = min(additional_bytes+1, 55) + block.vtx[-1].wit.vtxinwit[int(i/(2*NUM_DROPS))].scriptWitness.stack[i%(2*NUM_DROPS)] = b'a'*(195+extra_bytes) + additional_bytes -= extra_bytes + i += 1 + + block.vtx[0].vout.pop() # Remove old commitment + add_witness_commitment(block) + block.solve() + vsize = get_virtual_size(block) + assert_equal(vsize, MAX_BLOCK_SIZE + 1) + # Make sure that our test case would exceed the old max-network-message + # limit + assert(len(block.serialize(True)) > 2*1024*1024) + + self.test_node.test_witness_block(block, accepted=False) + + # Now resize the second transaction to make the block fit. + cur_length = len(block.vtx[-1].wit.vtxinwit[0].scriptWitness.stack[0]) + block.vtx[-1].wit.vtxinwit[0].scriptWitness.stack[0] = b'a'*(cur_length-1) + block.vtx[0].vout.pop() + add_witness_commitment(block) + block.solve() + assert(get_virtual_size(block) == MAX_BLOCK_SIZE) + + self.test_node.test_witness_block(block, accepted=True) + + # Update available utxo's + self.utxo.pop(0) + self.utxo.append(UTXO(block.vtx[-1].sha256, 0, block.vtx[-1].vout[0].nValue)) + + + # submitblock will try to add the nonce automatically, so that mining + # software doesn't need to worry about doing so itself. + def test_submit_block(self): + block = self.build_next_block() + + # Try using a custom nonce and then don't supply it. + # This shouldn't possibly work. + add_witness_commitment(block, nonce=1) + block.vtx[0].wit = CTxWitness() # drop the nonce + block.solve() + self.nodes[0].submitblock(bytes_to_hex_str(block.serialize(True))) + assert(self.nodes[0].getbestblockhash() != block.hash) + + # Now redo commitment with the standard nonce, but let bitcoind fill it in. + add_witness_commitment(block, nonce=0) + block.vtx[0].wit = CTxWitness() + block.solve() + self.nodes[0].submitblock(bytes_to_hex_str(block.serialize(True))) + assert_equal(self.nodes[0].getbestblockhash(), block.hash) + + # This time, add a tx with non-empty witness, but don't supply + # the commitment. + block_2 = self.build_next_block() + + add_witness_commitment(block_2) + + block_2.solve() + + # Drop commitment and nonce -- submitblock should not fill in. + block_2.vtx[0].vout.pop() + block_2.vtx[0].wit = CTxWitness() + + self.nodes[0].submitblock(bytes_to_hex_str(block_2.serialize(True))) + # Tip should not advance! + assert(self.nodes[0].getbestblockhash() != block_2.hash) + + + # Consensus tests of extra witness data in a transaction. + def test_extra_witness_data(self): + print("\tTesting extra witness data in tx") + + assert(len(self.utxo) > 0) + + block = self.build_next_block() + + witness_program = CScript([OP_DROP, OP_TRUE]) + witness_hash = sha256(witness_program) + scriptPubKey = CScript([OP_0, witness_hash]) + + # First try extra witness data on a tx that doesn't require a witness + tx = CTransaction() + tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")) + tx.vout.append(CTxOut(self.utxo[0].nValue-2000, scriptPubKey)) + tx.vout.append(CTxOut(1000, CScript([OP_TRUE]))) # non-witness output + tx.wit.vtxinwit.append(CTxinWitness()) + tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([])] + tx.rehash() + self.update_witness_block_with_transactions(block, [tx]) + + # Extra witness data should not be allowed. + self.test_node.test_witness_block(block, accepted=False) + + # Try extra signature data. Ok if we're not spending a witness output. + block.vtx[1].wit.vtxinwit = [] + block.vtx[1].vin[0].scriptSig = CScript([OP_0]) + block.vtx[1].rehash() + add_witness_commitment(block) + block.solve() + + self.test_node.test_witness_block(block, accepted=True) + + # Now try extra witness/signature data on an input that DOES require a + # witness + tx2 = CTransaction() + tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b"")) # witness output + tx2.vin.append(CTxIn(COutPoint(tx.sha256, 1), b"")) # non-witness + tx2.vout.append(CTxOut(tx.vout[0].nValue, CScript([OP_TRUE]))) + tx2.wit.vtxinwit.extend([CTxinWitness(), CTxinWitness()]) + tx2.wit.vtxinwit[0].scriptWitness.stack = [ CScript([CScriptNum(1)]), CScript([CScriptNum(1)]), witness_program ] + tx2.wit.vtxinwit[1].scriptWitness.stack = [ CScript([OP_TRUE]) ] + + block = self.build_next_block() + self.update_witness_block_with_transactions(block, [tx2]) + + # This has extra witness data, so it should fail. + self.test_node.test_witness_block(block, accepted=False) + + # Now get rid of the extra witness, but add extra scriptSig data + tx2.vin[0].scriptSig = CScript([OP_TRUE]) + tx2.vin[1].scriptSig = CScript([OP_TRUE]) + tx2.wit.vtxinwit[0].scriptWitness.stack.pop(0) + tx2.wit.vtxinwit[1].scriptWitness.stack = [] + tx2.rehash() + add_witness_commitment(block) + block.solve() + + # This has extra signature data for a witness input, so it should fail. + self.test_node.test_witness_block(block, accepted=False) + + # Now get rid of the extra scriptsig on the witness input, and verify + # success (even with extra scriptsig data in the non-witness input) + tx2.vin[0].scriptSig = b"" + tx2.rehash() + add_witness_commitment(block) + block.solve() + + self.test_node.test_witness_block(block, accepted=True) + + # Update utxo for later tests + self.utxo.pop(0) + self.utxo.append(UTXO(tx2.sha256, 0, tx2.vout[0].nValue)) + + + def test_max_witness_push_length(self): + ''' Should only allow up to 520 byte pushes in witness stack ''' + print("\tTesting maximum witness push size") + MAX_SCRIPT_ELEMENT_SIZE = 520 + assert(len(self.utxo)) + + block = self.build_next_block() + + witness_program = CScript([OP_DROP, OP_TRUE]) + witness_hash = sha256(witness_program) + scriptPubKey = CScript([OP_0, witness_hash]) + + tx = CTransaction() + tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")) + tx.vout.append(CTxOut(self.utxo[0].nValue-1000, scriptPubKey)) + tx.rehash() + + tx2 = CTransaction() + tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b"")) + tx2.vout.append(CTxOut(tx.vout[0].nValue-1000, CScript([OP_TRUE]))) + tx2.wit.vtxinwit.append(CTxinWitness()) + # First try a 521-byte stack element + tx2.wit.vtxinwit[0].scriptWitness.stack = [ b'a'*(MAX_SCRIPT_ELEMENT_SIZE+1), witness_program ] + tx2.rehash() + + self.update_witness_block_with_transactions(block, [tx, tx2]) + self.test_node.test_witness_block(block, accepted=False) + + # Now reduce the length of the stack element + tx2.wit.vtxinwit[0].scriptWitness.stack[0] = b'a'*(MAX_SCRIPT_ELEMENT_SIZE) + + add_witness_commitment(block) + block.solve() + self.test_node.test_witness_block(block, accepted=True) + + # Update the utxo for later tests + self.utxo.pop() + self.utxo.append(UTXO(tx2.sha256, 0, tx2.vout[0].nValue)) + + def test_max_witness_program_length(self): + # Can create witness outputs that are long, but can't be greater than + # 10k bytes to successfully spend + print("\tTesting maximum witness program length") + assert(len(self.utxo)) + MAX_PROGRAM_LENGTH = 10000 + + # This program is 19 max pushes (9937 bytes), then 64 more opcode-bytes. + long_witness_program = CScript([b'a'*520]*19 + [OP_DROP]*63 + [OP_TRUE]) + assert(len(long_witness_program) == MAX_PROGRAM_LENGTH+1) + long_witness_hash = sha256(long_witness_program) + long_scriptPubKey = CScript([OP_0, long_witness_hash]) + + block = self.build_next_block() + + tx = CTransaction() + tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")) + tx.vout.append(CTxOut(self.utxo[0].nValue-1000, long_scriptPubKey)) + tx.rehash() + + tx2 = CTransaction() + tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b"")) + tx2.vout.append(CTxOut(tx.vout[0].nValue-1000, CScript([OP_TRUE]))) + tx2.wit.vtxinwit.append(CTxinWitness()) + tx2.wit.vtxinwit[0].scriptWitness.stack = [b'a']*44 + [long_witness_program] + tx2.rehash() + + self.update_witness_block_with_transactions(block, [tx, tx2]) + + self.test_node.test_witness_block(block, accepted=False) + + # Try again with one less byte in the witness program + witness_program = CScript([b'a'*520]*19 + [OP_DROP]*62 + [OP_TRUE]) + assert(len(witness_program) == MAX_PROGRAM_LENGTH) + witness_hash = sha256(witness_program) + scriptPubKey = CScript([OP_0, witness_hash]) + + tx.vout[0] = CTxOut(tx.vout[0].nValue, scriptPubKey) + tx.rehash() + tx2.vin[0].prevout.hash = tx.sha256 + tx2.wit.vtxinwit[0].scriptWitness.stack = [b'a']*43 + [witness_program] + tx2.rehash() + block.vtx = [block.vtx[0]] + self.update_witness_block_with_transactions(block, [tx, tx2]) + self.test_node.test_witness_block(block, accepted=True) + + self.utxo.pop() + self.utxo.append(UTXO(tx2.sha256, 0, tx2.vout[0].nValue)) + + + def test_witness_input_length(self): + ''' Ensure that vin length must match vtxinwit length ''' + print("\tTesting witness input length") + assert(len(self.utxo)) + + witness_program = CScript([OP_DROP, OP_TRUE]) + witness_hash = sha256(witness_program) + scriptPubKey = CScript([OP_0, witness_hash]) + + # Create a transaction that splits our utxo into many outputs + tx = CTransaction() + tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")) + nValue = self.utxo[0].nValue + for i in range(10): + tx.vout.append(CTxOut(int(nValue/10), scriptPubKey)) + tx.vout[0].nValue -= 1000 + assert(tx.vout[0].nValue >= 0) + + block = self.build_next_block() + self.update_witness_block_with_transactions(block, [tx]) + self.test_node.test_witness_block(block, accepted=True) + + # Try various ways to spend tx that should all break. + # This "broken" transaction serializer will not normalize + # the length of vtxinwit. + class BrokenCTransaction(CTransaction): + def serialize_with_witness(self): + flags = 0 + if not self.wit.is_null(): + flags |= 1 + r = b"" + r += struct.pack(" version 1 transactions + # are non-standard + scriptPubKey = CScript([CScriptOp(OP_1), witness_hash]) + tx2 = CTransaction() + tx2.vin = [CTxIn(COutPoint(tx.sha256, 0), b"")] + tx2.vout = [CTxOut(tx.vout[0].nValue-1000, scriptPubKey)] + tx2.wit.vtxinwit.append(CTxinWitness()) + tx2.wit.vtxinwit[0].scriptWitness.stack = [ witness_program ] + tx2.rehash() + # Gets accepted to test_node, because standardness of outputs isn't + # checked with fRequireStandard + self.test_node.test_transaction_acceptance(tx2, with_witness=True, accepted=True) + self.std_node.test_transaction_acceptance(tx2, with_witness=True, accepted=False) + temp_utxo.pop() # last entry in temp_utxo was the output we just spent + temp_utxo.append(UTXO(tx2.sha256, 0, tx2.vout[0].nValue)) + + # Spend everything in temp_utxo back to an OP_TRUE output. + tx3 = CTransaction() + total_value = 0 + for i in temp_utxo: + tx3.vin.append(CTxIn(COutPoint(i.sha256, i.n), b"")) + tx3.wit.vtxinwit.append(CTxinWitness()) + total_value += i.nValue + tx3.wit.vtxinwit[-1].scriptWitness.stack = [witness_program] + tx3.vout.append(CTxOut(total_value - 1000, CScript([OP_TRUE]))) + tx3.rehash() + # Spending a higher version witness output is not allowed by policy, + # even with fRequireStandard=false. + self.test_node.test_transaction_acceptance(tx3, with_witness=True, accepted=False) + self.test_node.sync_with_ping() + with mininode_lock: + assert(b"reserved for soft-fork upgrades" in self.test_node.last_reject.reason) + + # Building a block with the transaction must be valid, however. + block = self.build_next_block() + self.update_witness_block_with_transactions(block, [tx2, tx3]) + self.test_node.test_witness_block(block, accepted=True) + sync_blocks(self.nodes) + + # Add utxo to our list + self.utxo.append(UTXO(tx3.sha256, 0, tx3.vout[0].nValue)) + + + def test_premature_coinbase_witness_spend(self): + print("\tTesting premature coinbase witness spend") + block = self.build_next_block() + # Change the output of the block to be a witness output. + witness_program = CScript([OP_TRUE]) + witness_hash = sha256(witness_program) + scriptPubKey = CScript([OP_0, witness_hash]) + block.vtx[0].vout[0].scriptPubKey = scriptPubKey + # This next line will rehash the coinbase and update the merkle + # root, and solve. + self.update_witness_block_with_transactions(block, []) + self.test_node.test_witness_block(block, accepted=True) + + spend_tx = CTransaction() + spend_tx.vin = [CTxIn(COutPoint(block.vtx[0].sha256, 0), b"")] + spend_tx.vout = [CTxOut(block.vtx[0].vout[0].nValue, witness_program)] + spend_tx.wit.vtxinwit.append(CTxinWitness()) + spend_tx.wit.vtxinwit[0].scriptWitness.stack = [ witness_program ] + spend_tx.rehash() + + # Now test a premature spend. + self.nodes[0].generate(98) + sync_blocks(self.nodes) + block2 = self.build_next_block() + self.update_witness_block_with_transactions(block2, [spend_tx]) + self.test_node.test_witness_block(block2, accepted=False) + + # Advancing one more block should allow the spend. + self.nodes[0].generate(1) + block2 = self.build_next_block() + self.update_witness_block_with_transactions(block2, [spend_tx]) + self.test_node.test_witness_block(block2, accepted=True) + sync_blocks(self.nodes) + + + def test_signature_version_1(self): + print("\tTesting segwit signature hash version 1") + key = CECKey() + key.set_secretbytes(b"9") + pubkey = CPubKey(key.get_pubkey()) + + witness_program = CScript([pubkey, CScriptOp(OP_CHECKSIG)]) + witness_hash = sha256(witness_program) + scriptPubKey = CScript([OP_0, witness_hash]) + + # First create a witness output for use in the tests. + assert(len(self.utxo)) + tx = CTransaction() + tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")) + tx.vout.append(CTxOut(self.utxo[0].nValue-1000, scriptPubKey)) + tx.rehash() + + self.test_node.test_transaction_acceptance(tx, with_witness=True, accepted=True) + # Mine this transaction in preparation for following tests. + block = self.build_next_block() + self.update_witness_block_with_transactions(block, [tx]) + self.test_node.test_witness_block(block, accepted=True) + sync_blocks(self.nodes) + self.utxo.pop(0) + + # Add signature for a P2PK witness program. + def sign_P2PK_witness_input(script, txTo, inIdx, hashtype, value, key): + tx_hash = SegwitVersion1SignatureHash(script, txTo, inIdx, hashtype, value) + signature = key.sign(tx_hash) + chr(hashtype).encode('latin-1') + txTo.wit.vtxinwit[inIdx].scriptWitness.stack = [signature, script] + txTo.rehash() + + # Test each hashtype + prev_utxo = UTXO(tx.sha256, 0, tx.vout[0].nValue) + for sigflag in [ 0, SIGHASH_ANYONECANPAY ]: + for hashtype in [SIGHASH_ALL, SIGHASH_NONE, SIGHASH_SINGLE]: + hashtype |= sigflag + block = self.build_next_block() + tx = CTransaction() + tx.vin.append(CTxIn(COutPoint(prev_utxo.sha256, prev_utxo.n), b"")) + tx.vout.append(CTxOut(prev_utxo.nValue - 1000, scriptPubKey)) + tx.wit.vtxinwit.append(CTxinWitness()) + # Too-large input value + sign_P2PK_witness_input(witness_program, tx, 0, hashtype, prev_utxo.nValue+1, key) + self.update_witness_block_with_transactions(block, [tx]) + self.test_node.test_witness_block(block, accepted=False) + + # Too-small input value + sign_P2PK_witness_input(witness_program, tx, 0, hashtype, prev_utxo.nValue-1, key) + block.vtx.pop() # remove last tx + self.update_witness_block_with_transactions(block, [tx]) + self.test_node.test_witness_block(block, accepted=False) + + # Now try correct value + sign_P2PK_witness_input(witness_program, tx, 0, hashtype, prev_utxo.nValue, key) + block.vtx.pop() + self.update_witness_block_with_transactions(block, [tx]) + self.test_node.test_witness_block(block, accepted=True) + + prev_utxo = UTXO(tx.sha256, 0, tx.vout[0].nValue) + + # Test combinations of signature hashes. + # Split the utxo into a lot of outputs. + # Randomly choose up to 10 to spend, sign with different hashtypes, and + # output to a random number of outputs. Repeat NUM_TESTS times. + # Ensure that we've tested a situation where we use SIGHASH_SINGLE with + # an input index > number of outputs. + NUM_TESTS = 500 + temp_utxos = [] + tx = CTransaction() + tx.vin.append(CTxIn(COutPoint(prev_utxo.sha256, prev_utxo.n), b"")) + split_value = prev_utxo.nValue // NUM_TESTS + for i in range(NUM_TESTS): + tx.vout.append(CTxOut(split_value, scriptPubKey)) + tx.wit.vtxinwit.append(CTxinWitness()) + sign_P2PK_witness_input(witness_program, tx, 0, SIGHASH_ALL, prev_utxo.nValue, key) + for i in range(NUM_TESTS): + temp_utxos.append(UTXO(tx.sha256, i, split_value)) + + block = self.build_next_block() + self.update_witness_block_with_transactions(block, [tx]) + self.test_node.test_witness_block(block, accepted=True) + + block = self.build_next_block() + used_sighash_single_out_of_bounds = False + for i in range(NUM_TESTS): + # Choose random number of inputs to use. + num_inputs = random.randint(1, 10) + # Create a slight bias for producing more utxos + num_outputs = random.randint(1, 11) + random.shuffle(temp_utxos) + assert(len(temp_utxos) > num_inputs) + tx = CTransaction() + total_value = 0 + for i in range(num_inputs): + tx.vin.append(CTxIn(COutPoint(temp_utxos[i].sha256, temp_utxos[i].n), b"")) + tx.wit.vtxinwit.append(CTxinWitness()) + total_value += temp_utxos[i].nValue + split_value = total_value // num_outputs + for i in range(num_outputs): + tx.vout.append(CTxOut(split_value, scriptPubKey)) + for i in range(num_inputs): + # Now try to sign each input, using a random hashtype. + anyonecanpay = 0 + if random.randint(0, 1): + anyonecanpay = SIGHASH_ANYONECANPAY + hashtype = random.randint(1, 3) | anyonecanpay + sign_P2PK_witness_input(witness_program, tx, i, hashtype, temp_utxos[i].nValue, key) + if (hashtype == SIGHASH_SINGLE and i >= num_outputs): + used_sighash_single_out_of_bounds = True + tx.rehash() + for i in range(num_outputs): + temp_utxos.append(UTXO(tx.sha256, i, split_value)) + temp_utxos = temp_utxos[num_inputs:] + + block.vtx.append(tx) + + # Test the block periodically, if we're close to maxblocksize + if (get_virtual_size(block) > MAX_BLOCK_SIZE - 1000): + self.update_witness_block_with_transactions(block, []) + self.test_node.test_witness_block(block, accepted=True) + block = self.build_next_block() + + if (not used_sighash_single_out_of_bounds): + print("WARNING: this test run didn't attempt SIGHASH_SINGLE with out-of-bounds index value") + # Test the transactions we've added to the block + if (len(block.vtx) > 1): + self.update_witness_block_with_transactions(block, []) + self.test_node.test_witness_block(block, accepted=True) + + # Now test witness version 0 P2PKH transactions + pubkeyhash = hash160(pubkey) + scriptPKH = CScript([OP_0, pubkeyhash]) + tx = CTransaction() + tx.vin.append(CTxIn(COutPoint(temp_utxos[0].sha256, temp_utxos[0].n), b"")) + tx.vout.append(CTxOut(temp_utxos[0].nValue, scriptPKH)) + tx.wit.vtxinwit.append(CTxinWitness()) + sign_P2PK_witness_input(witness_program, tx, 0, SIGHASH_ALL, temp_utxos[0].nValue, key) + tx2 = CTransaction() + tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b"")) + tx2.vout.append(CTxOut(tx.vout[0].nValue, CScript([OP_TRUE]))) + + script = CScript([CScriptOp(OP_DUP), CScriptOp(OP_HASH160), pubkeyhash, CScriptOp(OP_EQUALVERIFY), CScriptOp(OP_CHECKSIG)]) + sig_hash = SegwitVersion1SignatureHash(script, tx2, 0, SIGHASH_ALL, tx.vout[0].nValue) + signature = key.sign(sig_hash) + b'\x01' # 0x1 is SIGHASH_ALL + + # Check that we can't have a scriptSig + tx2.vin[0].scriptSig = CScript([signature, pubkey]) + block = self.build_next_block() + self.update_witness_block_with_transactions(block, [tx, tx2]) + self.test_node.test_witness_block(block, accepted=False) + + # Move the signature to the witness. + block.vtx.pop() + tx2.wit.vtxinwit.append(CTxinWitness()) + tx2.wit.vtxinwit[0].scriptWitness.stack = [signature, pubkey] + tx2.vin[0].scriptSig = b"" + tx2.rehash() + + self.update_witness_block_with_transactions(block, [tx2]) + self.test_node.test_witness_block(block, accepted=True) + + temp_utxos.pop(0) + + # Update self.utxos for later tests. Just spend everything in + # temp_utxos to a corresponding entry in self.utxos + tx = CTransaction() + index = 0 + for i in temp_utxos: + # Just spend to our usual anyone-can-spend output + # Use SIGHASH_SINGLE|SIGHASH_ANYONECANPAY so we can build up + # the signatures as we go. + tx.vin.append(CTxIn(COutPoint(i.sha256, i.n), b"")) + tx.vout.append(CTxOut(i.nValue, CScript([OP_TRUE]))) + tx.wit.vtxinwit.append(CTxinWitness()) + sign_P2PK_witness_input(witness_program, tx, index, SIGHASH_SINGLE|SIGHASH_ANYONECANPAY, i.nValue, key) + index += 1 + block = self.build_next_block() + self.update_witness_block_with_transactions(block, [tx]) + self.test_node.test_witness_block(block, accepted=True) + + for i in range(len(tx.vout)): + self.utxo.append(UTXO(tx.sha256, i, tx.vout[i].nValue)) + + + # Test P2SH wrapped witness programs. + def test_p2sh_witness(self, segwit_activated): + print("\tTesting P2SH witness transactions") + + assert(len(self.utxo)) + + # Prepare the p2sh-wrapped witness output + witness_program = CScript([OP_DROP, OP_TRUE]) + witness_hash = sha256(witness_program) + p2wsh_pubkey = CScript([OP_0, witness_hash]) + p2sh_witness_hash = hash160(p2wsh_pubkey) + scriptPubKey = CScript([OP_HASH160, p2sh_witness_hash, OP_EQUAL]) + scriptSig = CScript([p2wsh_pubkey]) # a push of the redeem script + + # Fund the P2SH output + tx = CTransaction() + tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")) + tx.vout.append(CTxOut(self.utxo[0].nValue-1000, scriptPubKey)) + tx.rehash() + + # Verify mempool acceptance and block validity + self.test_node.test_transaction_acceptance(tx, with_witness=False, accepted=True) + block = self.build_next_block() + self.update_witness_block_with_transactions(block, [tx]) + self.test_node.test_witness_block(block, accepted=True, with_witness=segwit_activated) + sync_blocks(self.nodes) + + # Now test attempts to spend the output. + spend_tx = CTransaction() + spend_tx.vin.append(CTxIn(COutPoint(tx.sha256, 0), scriptSig)) + spend_tx.vout.append(CTxOut(tx.vout[0].nValue-1000, CScript([OP_TRUE]))) + spend_tx.rehash() + + # This transaction should not be accepted into the mempool pre- or + # post-segwit. Mempool acceptance will use SCRIPT_VERIFY_WITNESS which + # will require a witness to spend a witness program regardless of + # segwit activation. Note that older bitcoind's that are not + # segwit-aware would also reject this for failing CLEANSTACK. + self.test_node.test_transaction_acceptance(spend_tx, with_witness=False, accepted=False) + + # Try to put the witness script in the scriptSig, should also fail. + spend_tx.vin[0].scriptSig = CScript([p2wsh_pubkey, b'a']) + spend_tx.rehash() + self.test_node.test_transaction_acceptance(spend_tx, with_witness=False, accepted=False) + + # Now put the witness script in the witness, should succeed after + # segwit activates. + spend_tx.vin[0].scriptSig = scriptSig + spend_tx.rehash() + spend_tx.wit.vtxinwit.append(CTxinWitness()) + spend_tx.wit.vtxinwit[0].scriptWitness.stack = [ b'a', witness_program ] + + # Verify mempool acceptance + self.test_node.test_transaction_acceptance(spend_tx, with_witness=True, accepted=segwit_activated) + block = self.build_next_block() + self.update_witness_block_with_transactions(block, [spend_tx]) + + # If we're before activation, then sending this without witnesses + # should be valid. If we're after activation, then sending this with + # witnesses should be valid. + if segwit_activated: + self.test_node.test_witness_block(block, accepted=True) + else: + self.test_node.test_witness_block(block, accepted=True, with_witness=False) + + # Update self.utxo + self.utxo.pop(0) + self.utxo.append(UTXO(spend_tx.sha256, 0, spend_tx.vout[0].nValue)) + + # Test the behavior of starting up a segwit-aware node after the softfork + # has activated. As segwit requires different block data than pre-segwit + # nodes would have stored, this requires special handling. + # To enable this test, pass --oldbinary= to + # the test. + def test_upgrade_after_activation(self, node, node_id): + print("\tTesting software upgrade after softfork activation") + + assert(node_id != 0) # node0 is assumed to be a segwit-active bitcoind + + # Make sure the nodes are all up + sync_blocks(self.nodes) + + # Restart with the new binary + stop_node(node, node_id) + self.nodes[node_id] = start_node(node_id, self.options.tmpdir, ["-debug"]) + connect_nodes(self.nodes[0], node_id) + + sync_blocks(self.nodes) + + # Make sure that this peer thinks segwit has activated. + assert(get_bip9_status(node, 'segwit')['status'] == "active") + + # Make sure this peers blocks match those of node0. + height = node.getblockcount() + while height >= 0: + block_hash = node.getblockhash(height) + assert_equal(block_hash, self.nodes[0].getblockhash(height)) + assert_equal(self.nodes[0].getblock(block_hash), node.getblock(block_hash)) + height -= 1 + + + def test_witness_sigops(self): + '''Ensure sigop counting is correct inside witnesses.''' + print("\tTesting sigops limit") + + assert(len(self.utxo)) + + # Keep this under MAX_OPS_PER_SCRIPT (201) + witness_program = CScript([OP_TRUE, OP_IF, OP_TRUE, OP_ELSE] + [OP_CHECKMULTISIG]*5 + [OP_CHECKSIG]*193 + [OP_ENDIF]) + witness_hash = sha256(witness_program) + scriptPubKey = CScript([OP_0, witness_hash]) + + sigops_per_script = 20*5 + 193*1 + # We'll produce 2 extra outputs, one with a program that would take us + # over max sig ops, and one with a program that would exactly reach max + # sig ops + outputs = (MAX_SIGOP_COST // sigops_per_script) + 2 + extra_sigops_available = MAX_SIGOP_COST % sigops_per_script + + # We chose the number of checkmultisigs/checksigs to make this work: + assert(extra_sigops_available < 100) # steer clear of MAX_OPS_PER_SCRIPT + + # This script, when spent with the first + # N(=MAX_SIGOP_COST//sigops_per_script) outputs of our transaction, + # would push us just over the block sigop limit. + witness_program_toomany = CScript([OP_TRUE, OP_IF, OP_TRUE, OP_ELSE] + [OP_CHECKSIG]*(extra_sigops_available + 1) + [OP_ENDIF]) + witness_hash_toomany = sha256(witness_program_toomany) + scriptPubKey_toomany = CScript([OP_0, witness_hash_toomany]) + + # If we spend this script instead, we would exactly reach our sigop + # limit (for witness sigops). + witness_program_justright = CScript([OP_TRUE, OP_IF, OP_TRUE, OP_ELSE] + [OP_CHECKSIG]*(extra_sigops_available) + [OP_ENDIF]) + witness_hash_justright = sha256(witness_program_justright) + scriptPubKey_justright = CScript([OP_0, witness_hash_justright]) + + # First split our available utxo into a bunch of outputs + split_value = self.utxo[0].nValue // outputs + tx = CTransaction() + tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")) + for i in range(outputs): + tx.vout.append(CTxOut(split_value, scriptPubKey)) + tx.vout[-2].scriptPubKey = scriptPubKey_toomany + tx.vout[-1].scriptPubKey = scriptPubKey_justright + tx.rehash() + + block_1 = self.build_next_block() + self.update_witness_block_with_transactions(block_1, [tx]) + self.test_node.test_witness_block(block_1, accepted=True) + + tx2 = CTransaction() + # If we try to spend the first n-1 outputs from tx, that should be + # too many sigops. + total_value = 0 + for i in range(outputs-1): + tx2.vin.append(CTxIn(COutPoint(tx.sha256, i), b"")) + tx2.wit.vtxinwit.append(CTxinWitness()) + tx2.wit.vtxinwit[-1].scriptWitness.stack = [ witness_program ] + total_value += tx.vout[i].nValue + tx2.wit.vtxinwit[-1].scriptWitness.stack = [ witness_program_toomany ] + tx2.vout.append(CTxOut(total_value, CScript([OP_TRUE]))) + tx2.rehash() + + block_2 = self.build_next_block() + self.update_witness_block_with_transactions(block_2, [tx2]) + self.test_node.test_witness_block(block_2, accepted=False) + + # Try dropping the last input in tx2, and add an output that has + # too many sigops (contributing to legacy sigop count). + checksig_count = (extra_sigops_available // 4) + 1 + scriptPubKey_checksigs = CScript([OP_CHECKSIG]*checksig_count) + tx2.vout.append(CTxOut(0, scriptPubKey_checksigs)); + tx2.vin.pop() + tx2.wit.vtxinwit.pop() + tx2.vout[0].nValue -= tx.vout[-2].nValue + tx2.rehash() + block_3 = self.build_next_block() + self.update_witness_block_with_transactions(block_3, [tx2]) + self.test_node.test_witness_block(block_3, accepted=False) + + # If we drop the last checksig in this output, the tx should succeed. + block_4 = self.build_next_block() + tx2.vout[-1].scriptPubKey = CScript([OP_CHECKSIG]*(checksig_count-1)) + tx2.rehash() + self.update_witness_block_with_transactions(block_4, [tx2]) + self.test_node.test_witness_block(block_4, accepted=True) + + # Reset the tip back down for the next test + sync_blocks(self.nodes) + for x in self.nodes: + x.invalidateblock(block_4.hash) + + # Try replacing the last input of tx2 to be spending the last + # output of tx + block_5 = self.build_next_block() + tx2.vout.pop() + tx2.vin.append(CTxIn(COutPoint(tx.sha256, outputs-1), b"")) + tx2.wit.vtxinwit.append(CTxinWitness()) + tx2.wit.vtxinwit[-1].scriptWitness.stack = [ witness_program_justright ] + tx2.rehash() + self.update_witness_block_with_transactions(block_5, [tx2]) + self.test_node.test_witness_block(block_5, accepted=True) + + # TODO: test p2sh sigop counting + + def test_getblocktemplate_before_lockin(self): + print("\tTesting getblocktemplate setting of segwit versionbit (before lockin)") + block_version = (self.nodes[0].getblocktemplate())['version'] + assert_equal(block_version & (1 << VB_WITNESS_BIT), 0) + + # Workaround: + # Can either change the tip, or change the mempool and wait 5 seconds + # to trigger a recomputation of getblocktemplate. + self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1) + # Using mocktime lets us avoid sleep() + self.nodes[0].setmocktime(int(time.time())+10) + + block_version = self.nodes[0].getblocktemplate({"rules" : ["segwit"]})['version'] + assert(block_version & (1 << VB_WITNESS_BIT) != 0) + self.nodes[0].setmocktime(0) # undo mocktime + + def run_test(self): + # Setup the p2p connections and start up the network thread. + self.test_node = TestNode() # sets NODE_WITNESS|NODE_NETWORK + self.old_node = TestNode() # only NODE_NETWORK + self.std_node = TestNode() # for testing node1 (fRequireStandard=true) + + self.p2p_connections = [self.test_node, self.old_node] + + self.connections = [] + self.connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], self.test_node, services=NODE_NETWORK|NODE_WITNESS)) + self.connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], self.old_node, services=NODE_NETWORK)) + self.connections.append(NodeConn('127.0.0.1', p2p_port(1), self.nodes[1], self.std_node, services=NODE_NETWORK|NODE_WITNESS)) + self.test_node.add_connection(self.connections[0]) + self.old_node.add_connection(self.connections[1]) + self.std_node.add_connection(self.connections[2]) + + NetworkThread().start() # Start up network handling in another thread + + # Keep a place to store utxo's that can be used in later tests + self.utxo = [] + + # Test logic begins here + self.test_node.wait_for_verack() + + print("\nStarting tests before segwit lock in:") + + self.test_witness_services() # Verifies NODE_WITNESS + self.test_non_witness_transaction() # non-witness tx's are accepted + self.test_unnecessary_witness_before_segwit_activation() + self.test_block_relay(segwit_activated=False) + + # Advance to segwit being 'started' + self.advance_to_segwit_started() + self.test_getblocktemplate_before_lockin() + + sync_blocks(self.nodes) + + # At lockin, nothing should change. + print("\nTesting behavior post lockin, pre-activation") + self.advance_to_segwit_lockin() + + # Retest unnecessary witnesses + self.test_unnecessary_witness_before_segwit_activation() + self.test_witness_tx_relay_before_segwit_activation() + self.test_block_relay(segwit_activated=False) + self.test_p2sh_witness(segwit_activated=False) + + sync_blocks(self.nodes) + + # Now activate segwit + print("\nTesting behavior after segwit activation") + self.advance_to_segwit_active() + + sync_blocks(self.nodes) + + # Test P2SH witness handling again + self.test_p2sh_witness(segwit_activated=True) + self.test_witness_commitments() + self.test_block_malleability() + self.test_witness_block_size() + self.test_submit_block() + self.test_extra_witness_data() + self.test_max_witness_push_length() + self.test_max_witness_program_length() + self.test_witness_input_length() + self.test_block_relay(segwit_activated=True) + self.test_tx_relay_after_segwit_activation() + self.test_segwit_versions() + self.test_premature_coinbase_witness_spend() + self.test_signature_version_1() + sync_blocks(self.nodes) + if self.test_upgrade: + self.test_upgrade_after_activation(self.nodes[2], 2) + else: + print("\tSkipping upgrade-after-activation test (use --oldbinary to enable)") + self.test_witness_sigops() + + +if __name__ == '__main__': + SegWitTest().main() diff --git a/qa/rpc-tests/test_framework/blocktools.py b/qa/rpc-tests/test_framework/blocktools.py index 26cc3963151ed..df4fe13e5c1c6 100644 --- a/qa/rpc-tests/test_framework/blocktools.py +++ b/qa/rpc-tests/test_framework/blocktools.py @@ -5,7 +5,7 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. from .mininode import * -from .script import CScript, OP_TRUE, OP_CHECKSIG +from .script import CScript, OP_TRUE, OP_CHECKSIG, OP_RETURN # Create a block (with regtest difficulty) def create_block(hashprev, coinbase, nTime=None): @@ -22,6 +22,29 @@ def create_block(hashprev, coinbase, nTime=None): block.calc_sha256() return block +# From BIP141 +WITNESS_COMMITMENT_HEADER = b"\xaa\x21\xa9\xed" + +# According to BIP141, blocks with witness rules active must commit to the +# hash of all in-block transactions including witness. +def add_witness_commitment(block, nonce=0): + # First calculate the merkle root of the block's + # transactions, with witnesses. + witness_nonce = nonce + witness_root = block.calc_witness_merkle_root() + witness_commitment = uint256_from_str(hash256(ser_uint256(witness_root)+ser_uint256(witness_nonce))) + # witness_nonce should go to coinbase witness. + block.vtx[0].wit.vtxinwit = [CTxinWitness()] + block.vtx[0].wit.vtxinwit[0].scriptWitness.stack = [ser_uint256(witness_nonce)] + + # witness commitment is the last OP_RETURN output in coinbase + output_data = WITNESS_COMMITMENT_HEADER + ser_uint256(witness_commitment) + block.vtx[0].vout.append(CTxOut(0, CScript([OP_RETURN, output_data]))) + block.vtx[0].rehash() + block.hashMerkleRoot = block.calc_merkle_root() + block.rehash() + + def serialize_script_num(value): r = bytearray(0) if value == 0: diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index 6612b99b84234..4548e2e7c080f 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -28,7 +28,7 @@ import time import sys import random -from binascii import hexlify, unhexlify +from .util import hex_str_to_bytes, bytes_to_hex_str from io import BytesIO from codecs import encode import hashlib @@ -46,6 +46,11 @@ COIN = 100000000 # 1 btc in satoshis +NODE_NETWORK = (1 << 0) +NODE_GETUTXO = (1 << 1) +NODE_BLOOM = (1 << 2) +NODE_WITNESS = (1 << 3) + # Keep our own socket map for asyncore, so that we can track disconnects # ourselves (to workaround an issue with closing an asyncore socket when # using select) @@ -63,6 +68,8 @@ def sha256(s): return hashlib.new('sha256', s).digest() +def ripemd160(s): + return hashlib.new('ripemd160', s).digest() def hash256(s): return sha256(sha256(s)) @@ -133,7 +140,10 @@ def deser_vector(f, c): return r -def ser_vector(l): +# ser_function_name: Allow for an alternate serialization function on the +# entries in the vector (we use this for serializing the vector of transactions +# for a witness block). +def ser_vector(l, ser_function_name=None): r = b"" if len(l) < 253: r = struct.pack("B", len(l)) @@ -144,7 +154,10 @@ def ser_vector(l): else: r = struct.pack(" 1: newhashes = [] for i in range(0, len(hashes), 2): @@ -537,6 +663,24 @@ def calc_merkle_root(self): hashes = newhashes return uint256_from_str(hashes[0]) + def calc_merkle_root(self): + hashes = [] + for tx in self.vtx: + tx.calc_sha256() + hashes.append(ser_uint256(tx.sha256)) + return self.get_merkle_root(hashes) + + def calc_witness_merkle_root(self): + # For witness root purposes, the hash of the + # coinbase, with witness, is defined to be 0...0 + hashes = [ser_uint256(0)] + + for tx in self.vtx[1:]: + # Calculate the hashes with witness data + hashes.append(ser_uint256(tx.calc_sha256(True))) + + return self.get_merkle_root(hashes) + def is_valid(self): self.calc_sha256() target = uint256_from_compact(self.nBits) @@ -812,11 +956,16 @@ def deserialize(self, f): self.tx.deserialize(f) def serialize(self): - return self.tx.serialize() + return self.tx.serialize_without_witness() def __repr__(self): return "msg_tx(tx=%s)" % (repr(self.tx)) +class msg_witness_tx(msg_tx): + + def serialize(self): + return self.tx.serialize_with_witness() + class msg_block(object): command = b"block" @@ -849,6 +998,12 @@ def serialize(self): def __repr__(self): return "msg_generic()" +class msg_witness_block(msg_block): + + def serialize(self): + r = self.block.serialize(with_witness=True) + return r + class msg_getaddr(object): command = b"getaddr" @@ -947,6 +1102,7 @@ def serialize(self): def __repr__(self): return "msg_sendheaders()" + # getheaders message has # number of entries # vector of hashes @@ -1068,6 +1224,8 @@ def __init__(self): # tests; it causes message delivery to sleep for the specified time # before acquiring the global lock and delivering the next message. self.deliver_sleep_time = None + # Remember the services our peer has advertised + self.peer_services = None def set_deliver_sleep_time(self, value): with mininode_lock: @@ -1105,6 +1263,7 @@ def on_version(self, conn, message): conn.ver_send = min(MY_VERSION, message.nVersion) if message.nVersion < 209: conn.ver_recv = conn.ver_send + conn.nServices = message.nServices def on_verack(self, conn, message): conn.ver_recv = conn.ver_send @@ -1135,6 +1294,7 @@ def on_close(self, conn): pass def on_mempool(self, conn): pass def on_pong(self, conn, message): pass def on_feefilter(self, conn, message): pass + def on_sendheaders(self, conn, message): pass # More useful callbacks and functions for NodeConnCB's which have a single NodeConn class SingleNodeConnCB(NodeConnCB): @@ -1183,15 +1343,16 @@ class NodeConn(asyncore.dispatcher): b"getheaders": msg_getheaders, b"reject": msg_reject, b"mempool": msg_mempool, - b"feefilter": msg_feefilter + b"feefilter": msg_feefilter, + b"sendheaders": msg_sendheaders } MAGIC_BYTES = { "mainnet": b"\xf9\xbe\xb4\xd9", # mainnet "testnet3": b"\x0b\x11\x09\x07", # testnet3 - "regtest": b"\xfa\xbf\xb5\xda" # regtest + "regtest": b"\xfa\xbf\xb5\xda", # regtest } - def __init__(self, dstaddr, dstport, rpc, callback, net="regtest", services=1): + def __init__(self, dstaddr, dstport, rpc, callback, net="regtest", services=NODE_NETWORK): asyncore.dispatcher.__init__(self, map=mininode_socket_map) self.log = logging.getLogger("NodeConn(%s:%d)" % (dstaddr, dstport)) self.dstaddr = dstaddr @@ -1206,6 +1367,7 @@ def __init__(self, dstaddr, dstport, rpc, callback, net="regtest", services=1): self.network = net self.cb = callback self.disconnect = False + self.nServices = 0 # stuff version msg into sendbuf vt = msg_version() diff --git a/qa/rpc-tests/test_framework/script.py b/qa/rpc-tests/test_framework/script.py index 44a894fc8f488..7678228c42bb5 100644 --- a/qa/rpc-tests/test_framework/script.py +++ b/qa/rpc-tests/test_framework/script.py @@ -15,8 +15,9 @@ """ -from .mininode import CTransaction, CTxOut, hash256 +from .mininode import CTransaction, CTxOut, sha256, hash256, uint256_from_str, ser_uint256, ser_string from binascii import hexlify +import hashlib import sys bchr = chr @@ -36,6 +37,10 @@ OPCODE_NAMES = {} +def hash160(s): + return hashlib.new('ripemd160', sha256(s)).digest() + + _opcode_instances = [] class CScriptOp(int): """A single script opcode""" @@ -895,3 +900,48 @@ def SignatureHash(script, txTo, inIdx, hashtype): hash = hash256(s) return (hash, None) + +# TODO: Allow cached hashPrevouts/hashSequence/hashOutputs to be provided. +# Performance optimization probably not necessary for python tests, however. +# Note that this corresponds to sigversion == 1 in EvalScript, which is used +# for version 0 witnesses. +def SegwitVersion1SignatureHash(script, txTo, inIdx, hashtype, amount): + + hashPrevouts = 0 + hashSequence = 0 + hashOutputs = 0 + + if not (hashtype & SIGHASH_ANYONECANPAY): + serialize_prevouts = bytes() + for i in txTo.vin: + serialize_prevouts += i.prevout.serialize() + hashPrevouts = uint256_from_str(hash256(serialize_prevouts)) + + if (not (hashtype & SIGHASH_ANYONECANPAY) and (hashtype & 0x1f) != SIGHASH_SINGLE and (hashtype & 0x1f) != SIGHASH_NONE): + serialize_sequence = bytes() + for i in txTo.vin: + serialize_sequence += struct.pack("(script.begin(), script.end())); + return *this; + } + TestBuilder& PushSig(const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32, SigVersion sigversion = SIGVERSION_BASE) { uint256 hash = SignatureHash(script, spendTx, 0, nHashType, 0, sigversion); @@ -765,6 +770,42 @@ BOOST_AUTO_TEST_CASE(script_build) "Basic P2SH(P2WPKH) with the wrong key but no WITNESS", SCRIPT_VERIFY_P2SH, true, WITNESS_PKH ).PushWitSig(keys.key0).Push(keys.pubkey1).AsWit().PushRedeem()); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0), + "P2WPKH with future witness version", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | + SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM, false, WITNESS_PKH, 1 + ).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().ScriptError(SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)); + { + CScript witscript = CScript() << ToByteVector(keys.pubkey0); + uint256 hash; + CSHA256().Write(&witscript[0], witscript.size()).Finalize(hash.begin()); + vector hashBytes = ToByteVector(hash); + hashBytes.pop_back(); + tests.push_back(TestBuilder(CScript() << OP_0 << hashBytes, + "P2WPKH with wrong witness program length", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false + ).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().ScriptError(SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH)); + } + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, + "P2WSH with empty witness", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH + ).ScriptError(SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY)); + { + CScript witscript = CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG; + tests.push_back(TestBuilder(witscript, + "P2WSH with witness program mismatch", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH + ).PushWitSig(keys.key0).Push(witscript).DamagePush(0).AsWit().ScriptError(SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH)); + } + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0), + "P2WPKH with witness program mismatch", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_PKH + ).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().Push("0").AsWit().ScriptError(SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0), + "P2WPKH with non-empty scriptSig", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_PKH + ).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().Num(11).ScriptError(SCRIPT_ERR_WITNESS_MALLEATED)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1), + "P2SH(P2WPKH) with superfluous push in scriptSig", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_PKH + ).PushWitSig(keys.key0).Push(keys.pubkey1).AsWit().Num(11).PushRedeem().ScriptError(SCRIPT_ERR_WITNESS_MALLEATED_P2SH)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, + "P2PK with witness", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH + ).PushSig(keys.key0).Push("0").AsWit().ScriptError(SCRIPT_ERR_WITNESS_UNEXPECTED)); + std::set tests_set; { From d846e0237256a4105199673d2eb90ed1dbb55b35 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Sun, 22 May 2016 07:35:43 -0400 Subject: [PATCH 0559/1802] [qa] script_tests: witness tests can specify tx amount Add tests that witness signatures cover value --- src/test/data/script_tests.json | 123 ++++++++++++++++++++++++-------- src/test/script_tests.cpp | 68 ++++++++++++------ 2 files changed, 140 insertions(+), 51 deletions(-) diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json index a59e1389f9bfb..9b81e0c77ddf7 100644 --- a/src/test/data/script_tests.json +++ b/src/test/data/script_tests.json @@ -1,5 +1,5 @@ [ -["Format is: [[wit...]?, scriptSig, scriptPubKey, flags, expected_scripterror, ... comments]"], +["Format is: [[wit..., amount]?, scriptSig, scriptPubKey, flags, expected_scripterror, ... comments]"], ["It is evaluated as if there was a crediting coinbase transaction with two 0"], ["pushes as scriptSig, and one output of 0 satoshi and given scriptPubKey,"], ["followed by a spending transaction which spends this output as only input (and"], @@ -1254,10 +1254,10 @@ ["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Negative S is incorrectly encoded for DERSIG"], ["Some basic segwit checks"], -[["00"], "", "0 0x206e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", "P2SH,WITNESS", "EVAL_FALSE", "Invalid witness script"], -[["51"], "", "0 0x206e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", "P2SH,WITNESS", "WITNESS_PROGRAM_MISMATCH", "Witness script hash mismatch"], -[["00"], "", "0 0x206e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", "", "OK", "Invalid witness script without WITNESS"], -[["51"], "", "0 0x206e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", "", "OK", "Witness script hash mismatch without WITNESS"], +[["00", 0.00000000 ], "", "0 0x206e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", "P2SH,WITNESS", "EVAL_FALSE", "Invalid witness script"], +[["51", 0.00000000 ], "", "0 0x206e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", "P2SH,WITNESS", "WITNESS_PROGRAM_MISMATCH", "Witness script hash mismatch"], +[["00", 0.00000000 ], "", "0 0x206e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", "", "OK", "Invalid witness script without WITNESS"], +[["51", 0.00000000 ], "", "0 0x206e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", "", "OK", "Witness script hash mismatch without WITNESS"], ["Automatically generated test cases"], [ @@ -1836,8 +1836,9 @@ ], [ [ - "3044022039105b995a5f448639a997a5c90fda06f50b49df30c3bdb6663217bf79323db002206fecd54269dec569fcc517178880eb58bb40f381a282bb75766ff3637d5f4b4301", - "410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac" + "304402200d461c140cfdfcf36b94961db57ae8c18d1cb80e9d95a9e47ac22470c1bf125502201c8dc1cbfef6a3ef90acbbb992ca22fe9466ee6f9d4898eda277a7ac3ab4b25101", + "410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac", + 0.00000001 ], "", "0 0x20 0xb95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64", @@ -1847,8 +1848,9 @@ ], [ [ - "304402201a96950593cb0af32d080b0f193517f4559241a8ebd1e95e414533ad64a3f423022047f4f6d3095c23235bdff3aeff480d0529c027a3f093cb265b7cbf148553b85101", - "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8" + "304402201e7216e5ccb3b61d46946ec6cc7e8c4e0117d13ac2fd4b152197e4805191c74202203e9903e33e84d9ee1dd13fb057afb7ccfb47006c23f6a067185efbc9dd780fc501", + "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", + 0.00000001 ], "", "0 0x14 0x91b24bf9f5288532960ac687abb035127b1d28a5", @@ -1858,8 +1860,9 @@ ], [ [ - "3044022061fc1a144e221ec77a58a4281936eb6a1b715b9349e446e74d106ec26c8633ba022008064a0d112e8ad514440fcdfaa1006e48305d6844f50a65873fb4b2cf9c035f01", - "410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac" + "3044022066e02c19a513049d49349cf5311a1b012b7c4fae023795a18ab1d91c23496c22022025e216342c8e07ce8ef51e8daee88f84306a9de66236cab230bb63067ded1ad301", + "410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac", + 0.00000001 ], "0x22 0x0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64", "HASH160 0x14 0xf386c2ba255cc56d20cfa6ea8b062f8b59945518 EQUAL", @@ -1869,8 +1872,9 @@ ], [ [ - "3044022014e69768e174972f21d32d93002ca6fc26133cb9e819ceef7efb970798bde7b4022078b86849dbbec692ec9355aa2a763fce7ea11bf72fdd8ea5ea8083de6f8a77fe01", - "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8" + "304402200929d11561cd958460371200f82e9cae64c727a495715a31828e27a7ad57b36d0220361732ced04a6f97351ecca21a56d0b8cd4932c1da1f8f569a2b68e5e48aed7801", + "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", + 0.00000001 ], "0x16 0x001491b24bf9f5288532960ac687abb035127b1d28a5", "HASH160 0x14 0x17743beb429c55c942d2ec703b98c4d57c2df5c6 EQUAL", @@ -1881,7 +1885,8 @@ [ [ "304402202589f0512cb2408fb08ed9bd24f85eb3059744d9e4f2262d0b7f1338cff6e8b902206c0978f449693e0578c71bc543b11079fd0baae700ee5e9a6bee94db490af9fc01", - "41048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26cafac" + "41048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26cafac", + 0.00000000 ], "", "0 0x20 0xac8ebd9e52c17619a381fa4f71aebb696087c6ef17c960fd0587addad99c0610", @@ -1892,7 +1897,8 @@ [ [ "304402206ef7fdb2986325d37c6eb1a8bb24aeb46dede112ed8fc76c7d7500b9b83c0d3d02201edc2322c794fe2d6b0bd73ed319e714aa9b86d8891961530d5c9b7156b60d4e01", - "048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf" + "048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf", + 0.00000000 ], "", "0 0x14 0x7cf9c846cd4882efec4bf07e44ebdad495c94f4b", @@ -1903,7 +1909,8 @@ [ [ "30440220069ea3581afaf8187f63feee1fd2bd1f9c0dc71ea7d6e8a8b07ee2ebcf824bf402201a4fdef4c532eae59223be1eda6a397fc835142d4ddc6c74f4aa85b766a5c16f01", - "41048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26cafac" + "41048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26cafac", + 0.00000000 ], "0x22 0x0020ac8ebd9e52c17619a381fa4f71aebb696087c6ef17c960fd0587addad99c0610", "HASH160 0x14 0x61039a003883787c0d6ebc66d97fdabe8e31449d EQUAL", @@ -1914,7 +1921,8 @@ [ [ "304402204209e49457c2358f80d0256bc24535b8754c14d08840fc4be762d6f5a0aed80b02202eaf7d8fc8d62f60c67adcd99295528d0e491ae93c195cec5a67e7a09532a88001", - "048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf" + "048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf", + 0.00000000 ], "0x16 0x00147cf9c846cd4882efec4bf07e44ebdad495c94f4b", "HASH160 0x14 0x4e0c2aed91315303fc6a1dc4c7bc21c88f75402e EQUAL", @@ -1925,7 +1933,8 @@ [ [ "304402202589f0512cb2408fb08ed9bd24f85eb3059744d9e4f2262d0b7f1338cff6e8b902206c0978f449693e0578c71bc543b11079fd0baae700ee5e9a6bee94db490af9fc01", - "41048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26cafac" + "41048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26cafac", + 0.00000000 ], "", "0 0x20 0xac8ebd9e52c17619a381fa4f71aebb696087c6ef17c960fd0587addad99c0610", @@ -1936,7 +1945,8 @@ [ [ "304402206ef7fdb2986325d37c6eb1a8bb24aeb46dede112ed8fc76c7d7500b9b83c0d3d02201edc2322c794fe2d6b0bd73ed319e714aa9b86d8891961530d5c9b7156b60d4e01", - "048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf" + "048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf", + 0.00000000 ], "", "0 0x14 0x7cf9c846cd4882efec4bf07e44ebdad495c94f4b", @@ -1947,7 +1957,8 @@ [ [ "30440220069ea3581afaf8187f63feee1fd2bd1f9c0dc71ea7d6e8a8b07ee2ebcf824bf402201a4fdef4c532eae59223be1eda6a397fc835142d4ddc6c74f4aa85b766a5c16f01", - "41048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26cafac" + "41048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26cafac", + 0.00000000 ], "0x22 0x0020ac8ebd9e52c17619a381fa4f71aebb696087c6ef17c960fd0587addad99c0610", "HASH160 0x14 0x61039a003883787c0d6ebc66d97fdabe8e31449d EQUAL", @@ -1958,7 +1969,8 @@ [ [ "304402204209e49457c2358f80d0256bc24535b8754c14d08840fc4be762d6f5a0aed80b02202eaf7d8fc8d62f60c67adcd99295528d0e491ae93c195cec5a67e7a09532a88001", - "048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf" + "048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf", + 0.00000000 ], "0x16 0x00147cf9c846cd4882efec4bf07e44ebdad495c94f4b", "HASH160 0x14 0x4e0c2aed91315303fc6a1dc4c7bc21c88f75402e EQUAL", @@ -1966,10 +1978,59 @@ "OK", "Basic P2SH(P2WPKH) with the wrong key but no WITNESS" ], +[ + [ + "3044022066faa86e74e8b30e82691b985b373de4f9e26dc144ec399c4f066aa59308e7c202204712b86f28c32503faa051dbeabff2c238ece861abc36c5e0b40b1139ca222f001", + "410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac", + 0.00000000 + ], + "", + "0 0x20 0xb95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64", + "P2SH,WITNESS", + "EVAL_FALSE", + "Basic P2WSH with wrong value" +], +[ + [ + "304402203b3389b87448d7dfdb5e82fb854fcf92d7925f9938ea5444e36abef02c3d6a9602202410bc3265049abb07fd2e252c65ab7034d95c9d5acccabe9fadbdc63a52712601", + "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", + 0.00000000 + ], + "", + "0 0x14 0x91b24bf9f5288532960ac687abb035127b1d28a5", + "P2SH,WITNESS", + "EVAL_FALSE", + "Basic P2WPKH with wrong value" +], +[ + [ + "3044022000a30c4cfc10e4387be528613575434826ad3c15587475e0df8ce3b1746aa210022008149265e4f8e9dafe1f3ea50d90cb425e9e40ea7ebdd383069a7cfa2b77004701", + "410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac", + 0.00000000 + ], + "0x22 0x0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64", + "HASH160 0x14 0xf386c2ba255cc56d20cfa6ea8b062f8b59945518 EQUAL", + "P2SH,WITNESS", + "EVAL_FALSE", + "Basic P2SH(P2WSH) with wrong value" +], +[ + [ + "304402204fc3a2cd61a47913f2a5f9107d0ad4a504c7b31ee2d6b3b2f38c2b10ee031e940220055d58b7c3c281aaa381d8f486ac0f3e361939acfd568046cb6a311cdfa974cf01", + "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", + 0.00000000 + ], + "0x16 0x001491b24bf9f5288532960ac687abb035127b1d28a5", + "HASH160 0x14 0x17743beb429c55c942d2ec703b98c4d57c2df5c6 EQUAL", + "P2SH,WITNESS", + "EVAL_FALSE", + "Basic P2SH(P2WPKH) with wrong value" +], [ [ "304402205ae57ae0534c05ca9981c8a6cdf353b505eaacb7375f96681a2d1a4ba6f02f84022056248e68643b7d8ce7c7d128c9f1f348bcab8be15d094ad5cadd24251a28df8001", - "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8" + "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", + 0.00000000 ], "", "1 0x14 0x91b24bf9f5288532960ac687abb035127b1d28a5", @@ -1980,7 +2041,8 @@ [ [ "3044022064100ca0e2a33332136775a86cd83d0230e58b9aebb889c5ac952abff79a46ef02205f1bf900e022039ad3091bdaf27ac2aef3eae9ed9f190d821d3e508405b9513101", - "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8" + "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", + 0.00000000 ], "", "0 0x1f 0xb34b78da162751647974d5cb7410aa428ad339dbf7d1e16e833f68a0cbf1c3", @@ -1998,7 +2060,8 @@ [ [ "3044022039105b995a5f448639a997a5c90fda06f50b49df30c3bdb6663217bf79323db002206fecd54269dec569fcc517178880eb58bb40f381a282bb75766ff3637d5f4b4301", - "400479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac" + "400479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac", + 0.00000000 ], "", "0 0x20 0xb95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64", @@ -2010,7 +2073,8 @@ [ "304402201a96950593cb0af32d080b0f193517f4559241a8ebd1e95e414533ad64a3f423022047f4f6d3095c23235bdff3aeff480d0529c027a3f093cb265b7cbf148553b85101", "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", - "" + "", + 0.00000000 ], "", "0 0x14 0x91b24bf9f5288532960ac687abb035127b1d28a5", @@ -2021,7 +2085,8 @@ [ [ "304402201a96950593cb0af32d080b0f193517f4559241a8ebd1e95e414533ad64a3f423022047f4f6d3095c23235bdff3aeff480d0529c027a3f093cb265b7cbf148553b85101", - "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8" + "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", + 0.00000000 ], "11", "0 0x14 0x91b24bf9f5288532960ac687abb035127b1d28a5", @@ -2032,7 +2097,8 @@ [ [ "304402204209e49457c2358f80d0256bc24535b8754c14d08840fc4be762d6f5a0aed80b02202eaf7d8fc8d62f60c67adcd99295528d0e491ae93c195cec5a67e7a09532a88001", - "048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf" + "048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf", + 0.00000000 ], "11 0x16 0x00147cf9c846cd4882efec4bf07e44ebdad495c94f4b", "HASH160 0x14 0x4e0c2aed91315303fc6a1dc4c7bc21c88f75402e EQUAL", @@ -2042,7 +2108,8 @@ ], [ [ - "" + "", + 0.00000000 ], "0x47 0x304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 1497bde9d1550..5a9aaf9bc0738 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -13,6 +13,7 @@ #include "util.h" #include "utilstrencodings.h" #include "test/test_bitcoin.h" +#include "rpc/server.h" #if defined(HAVE_CONSENSUS_LIB) #include "script/bitcoinconsensus.h" @@ -118,7 +119,7 @@ ScriptError_t ParseScriptError(const std::string &name) BOOST_FIXTURE_TEST_SUITE(script_tests, BasicTestingSetup) -CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey) +CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey, int nValue = 0) { CMutableTransaction txCredit; txCredit.nVersion = 1; @@ -129,7 +130,7 @@ CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey) txCredit.vin[0].scriptSig = CScript() << CScriptNum(0) << CScriptNum(0); txCredit.vin[0].nSequence = CTxIn::SEQUENCE_FINAL; txCredit.vout[0].scriptPubKey = scriptPubKey; - txCredit.vout[0].nValue = 0; + txCredit.vout[0].nValue = nValue; return txCredit; } @@ -148,12 +149,12 @@ CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CSc txSpend.vin[0].scriptSig = scriptSig; txSpend.vin[0].nSequence = CTxIn::SEQUENCE_FINAL; txSpend.vout[0].scriptPubKey = CScript(); - txSpend.vout[0].nValue = 0; + txSpend.vout[0].nValue = txCredit.vout[0].nValue; return txSpend; } -void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, const CScriptWitness& scriptWitness, int flags, const std::string& message, int scriptError) +void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, const CScriptWitness& scriptWitness, int flags, const std::string& message, int scriptError, CAmount nValue = 0) { bool expect = (scriptError == SCRIPT_ERR_OK); if (flags & SCRIPT_VERIFY_CLEANSTACK) { @@ -161,7 +162,7 @@ void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, const CScript flags |= SCRIPT_VERIFY_WITNESS; } ScriptError err; - CMutableTransaction txCredit = BuildCreditingTransaction(scriptPubKey); + CMutableTransaction txCredit = BuildCreditingTransaction(scriptPubKey, nValue); CMutableTransaction tx = BuildSpendingTransaction(scriptSig, scriptWitness, txCredit); CMutableTransaction tx2 = tx; BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, &scriptWitness, flags, MutableTransactionSignatureChecker(&tx, 0, txCredit.vout[0].nValue), &err) == expect, message); @@ -276,6 +277,7 @@ class TestBuilder std::string comment; int flags; int scriptError; + CAmount nValue; void DoPush() { @@ -293,7 +295,7 @@ class TestBuilder } public: - TestBuilder(const CScript& script_, const std::string& comment_, int flags_, bool P2SH = false, WitnessMode wm = WITNESS_NONE, int witnessversion = 0) : script(script_), havePush(false), comment(comment_), flags(flags_), scriptError(SCRIPT_ERR_OK) + TestBuilder(const CScript& script_, const std::string& comment_, int flags_, bool P2SH = false, WitnessMode wm = WITNESS_NONE, int witnessversion = 0, CAmount nValue_ = 0) : script(script_), havePush(false), comment(comment_), flags(flags_), scriptError(SCRIPT_ERR_OK), nValue(nValue_) { CScript scriptPubKey = script; if (wm == WITNESS_PKH) { @@ -311,7 +313,7 @@ class TestBuilder redeemscript = scriptPubKey; scriptPubKey = CScript() << OP_HASH160 << ToByteVector(CScriptID(redeemscript)) << OP_EQUAL; } - creditTx = BuildCreditingTransaction(scriptPubKey); + creditTx = BuildCreditingTransaction(scriptPubKey, nValue); spendTx = BuildSpendingTransaction(CScript(), CScriptWitness(), creditTx); } @@ -346,9 +348,9 @@ class TestBuilder return *this; } - TestBuilder& PushSig(const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32, SigVersion sigversion = SIGVERSION_BASE) + TestBuilder& PushSig(const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32, SigVersion sigversion = SIGVERSION_BASE, CAmount amount = 0) { - uint256 hash = SignatureHash(script, spendTx, 0, nHashType, 0, sigversion); + uint256 hash = SignatureHash(script, spendTx, 0, nHashType, amount, sigversion); std::vector vchSig, r, s; uint32_t iter = 0; do { @@ -364,9 +366,11 @@ class TestBuilder return *this; } - TestBuilder& PushWitSig(const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32, SigVersion sigversion = SIGVERSION_WITNESS_V0) + TestBuilder& PushWitSig(const CKey& key, CAmount amount = -1, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32, SigVersion sigversion = SIGVERSION_WITNESS_V0) { - return PushSig(key, nHashType, lenR, lenS, sigversion).AsWit(); + if (amount == -1) + amount = nValue; + return PushSig(key, nHashType, lenR, lenS, sigversion, amount).AsWit(); } TestBuilder& Push(const CPubKey& pubkey) @@ -411,7 +415,7 @@ class TestBuilder { TestBuilder copy = *this; // Make a copy so we can rollback the push. DoPush(); - DoTest(creditTx.vout[0].scriptPubKey, spendTx.vin[0].scriptSig, scriptWitness, flags, comment, scriptError); + DoTest(creditTx.vout[0].scriptPubKey, spendTx.vin[0].scriptSig, scriptWitness, flags, comment, scriptError, nValue); *this = copy; return *this; } @@ -433,6 +437,7 @@ class TestBuilder for (unsigned i = 0; i < scriptWitness.stack.size(); i++) { wit.push_back(HexStr(scriptWitness.stack[i])); } + wit.push_back(ValueFromAmount(nValue)); array.push_back(wit); } array.push_back(FormatScript(spendTx.vin[0].scriptSig)); @@ -734,17 +739,17 @@ BOOST_AUTO_TEST_CASE(script_build) ).PushSig(keys.key0).PushRedeem()); tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, - "Basic P2WSH", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH - ).PushWitSig(keys.key0).PushWitRedeem()); + "Basic P2WSH", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH, + 0, 1).PushWitSig(keys.key0).PushWitRedeem()); tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0), - "Basic P2WPKH", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_PKH - ).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit()); + "Basic P2WPKH", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_PKH, + 0, 1).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit()); tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, - "Basic P2SH(P2WSH)", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_SH - ).PushWitSig(keys.key0).PushWitRedeem().PushRedeem()); + "Basic P2SH(P2WSH)", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_SH, + 0, 1).PushWitSig(keys.key0).PushWitRedeem().PushRedeem()); tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0), - "Basic P2SH(P2WPKH)", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_PKH - ).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().PushRedeem()); + "Basic P2SH(P2WPKH)", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_PKH, + 0, 1).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().PushRedeem()); tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG, "Basic P2WSH with the wrong key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH ).PushWitSig(keys.key0).PushWitRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE)); @@ -769,6 +774,18 @@ BOOST_AUTO_TEST_CASE(script_build) tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1), "Basic P2SH(P2WPKH) with the wrong key but no WITNESS", SCRIPT_VERIFY_P2SH, true, WITNESS_PKH ).PushWitSig(keys.key0).Push(keys.pubkey1).AsWit().PushRedeem()); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, + "Basic P2WSH with wrong value", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH, + 0, 0).PushWitSig(keys.key0, 1).PushWitRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0), + "Basic P2WPKH with wrong value", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_PKH, + 0, 0).PushWitSig(keys.key0, 1).Push(keys.pubkey0).AsWit().ScriptError(SCRIPT_ERR_EVAL_FALSE)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, + "Basic P2SH(P2WSH) with wrong value", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_SH, + 0, 0).PushWitSig(keys.key0, 1).PushWitRedeem().PushRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0), + "Basic P2SH(P2WPKH) with wrong value", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_PKH, + 0, 0).PushWitSig(keys.key0, 1).Push(keys.pubkey0).AsWit().PushRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE)); tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0), "P2WPKH with future witness version", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | @@ -841,20 +858,25 @@ BOOST_AUTO_TEST_CASE(script_json_test) { // Read tests from test/data/script_tests.json // Format is an array of arrays - // Inner arrays are [ ["wit"...]?, "scriptSig", "scriptPubKey", "flags", "expected_scripterror" ] + // Inner arrays are [ ["wit"..., nValue]?, "scriptSig", "scriptPubKey", "flags", "expected_scripterror" ] // ... where scriptSig and scriptPubKey are stringified // scripts. + // If a witness is given, then the last value in the array should be the + // amount (nValue) to use in the crediting tx UniValue tests = read_json(std::string(json_tests::script_tests, json_tests::script_tests + sizeof(json_tests::script_tests))); for (unsigned int idx = 0; idx < tests.size(); idx++) { UniValue test = tests[idx]; string strTest = test.write(); CScriptWitness witness; + CAmount nValue = 0; unsigned int pos = 0; if (test.size() > 0 && test[pos].isArray()) { - for (unsigned int i = 0; i < test[pos].size(); i++) { + unsigned int i=0; + for (i = 0; i < test[pos].size()-1; i++) { witness.stack.push_back(ParseHex(test[pos][i].get_str())); } + nValue = AmountFromValue(test[pos][i]); pos++; } if (test.size() < 4 + pos) // Allow size > 3; extra stuff ignored (useful for comments) @@ -871,7 +893,7 @@ BOOST_AUTO_TEST_CASE(script_json_test) unsigned int scriptflags = ParseScriptFlags(test[pos++].get_str()); int scriptError = ParseScriptError(test[pos++].get_str()); - DoTest(scriptPubKey, scriptSig, witness, scriptflags, strTest, scriptError); + DoTest(scriptPubKey, scriptSig, witness, scriptflags, strTest, scriptError, nValue); } } From fdb43df23eb507d1c79b7ae9cc2e61c3e52c8988 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Sat, 28 May 2016 19:22:13 +0200 Subject: [PATCH 0560/1802] [qa] Add GetTransactionSigOpCost unit tests --- src/main.h | 8 ++ src/test/sigopcount_tests.cpp | 177 ++++++++++++++++++++++++++++++++++ 2 files changed, 185 insertions(+) diff --git a/src/main.h b/src/main.h index 84a6044bc9dde..2ffe5770dccb0 100644 --- a/src/main.h +++ b/src/main.h @@ -333,6 +333,14 @@ unsigned int GetLegacySigOpCount(const CTransaction& tx); */ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& mapInputs); +/** + * Compute total signature operation cost of a transaction. + * @param[in] tx Transaction for which we are computing the cost + * @param[in] inputs Map of previous transactions that have outputs we're spending + * @param[out] flags Script verification flags + * @return Total signature operation cost of tx + */ +int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, int flags); /** * Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts) diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp index a207fd9216a10..8dea388332b21 100644 --- a/src/test/sigopcount_tests.cpp +++ b/src/test/sigopcount_tests.cpp @@ -2,6 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "main.h" #include "pubkey.h" #include "key.h" #include "script/script.h" @@ -64,4 +65,180 @@ BOOST_AUTO_TEST_CASE(GetSigOpCount) BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(scriptSig2), 3U); } +/** + * Verifies script execution of the zeroth scriptPubKey of tx output and + * zeroth scriptSig and witness of tx input. + */ +ScriptError VerifyWithFlag(const CTransaction& output, const CMutableTransaction& input, int flags) +{ + ScriptError error; + CTransaction inputi(input); + bool ret = VerifyScript(inputi.vin[0].scriptSig, output.vout[0].scriptPubKey, inputi.wit.vtxinwit.size() > 0 ? &inputi.wit.vtxinwit[0].scriptWitness : NULL, flags, TransactionSignatureChecker(&inputi, 0, output.vout[0].nValue), &error); + BOOST_CHECK((ret == true) == (error == SCRIPT_ERR_OK)); + + return error; +} + +/** + * Builds a creationTx from scriptPubKey and a spendingTx from scriptSig + * and witness such that spendingTx spends output zero of creationTx. + * Also inserts creationTx's output into the coins view. + */ +void BuildTxs(CMutableTransaction& spendingTx, CCoinsViewCache& coins, CMutableTransaction& creationTx, const CScript& scriptPubKey, const CScript& scriptSig, const CTxinWitness& witness) +{ + creationTx.nVersion = 1; + creationTx.vin.resize(1); + creationTx.vin[0].prevout.SetNull(); + creationTx.vin[0].scriptSig = CScript(); + creationTx.wit.vtxinwit.resize(1); + creationTx.vout.resize(1); + creationTx.vout[0].nValue = 1; + creationTx.vout[0].scriptPubKey = scriptPubKey; + + spendingTx.nVersion = 1; + spendingTx.vin.resize(1); + spendingTx.vin[0].prevout.hash = creationTx.GetHash(); + spendingTx.vin[0].prevout.n = 0; + spendingTx.vin[0].scriptSig = scriptSig; + spendingTx.wit.vtxinwit.resize(1); + spendingTx.wit.vtxinwit[0] = witness; + spendingTx.vout.resize(1); + spendingTx.vout[0].nValue = 1; + spendingTx.vout[0].scriptPubKey = CScript(); + + coins.ModifyCoins(creationTx.GetHash())->FromTx(creationTx, 0); +} + +BOOST_AUTO_TEST_CASE(GetTxSigOpCost) +{ + // Transaction creates outputs + CMutableTransaction creationTx; + // Transaction that spends outputs and whose + // sig op cost is going to be tested + CMutableTransaction spendingTx; + + // Create utxo set + CCoinsView coinsDummy; + CCoinsViewCache coins(&coinsDummy); + // Create key + CKey key; + key.MakeNewKey(true); + CPubKey pubkey = key.GetPubKey(); + // Default flags + int flags = SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH; + + // Multisig script (legacy counting) + { + CScript scriptPubKey = CScript() << 1 << ToByteVector(pubkey) << ToByteVector(pubkey) << 2 << OP_CHECKMULTISIGVERIFY; + // Do not use a valid signature to avoid using wallet operations. + CScript scriptSig = CScript() << OP_0 << OP_0; + + BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, CTxinWitness()); + // Legacy counting only includes signature operations in scriptSigs and scriptPubKeys + // of a transaction and does not take the actual executed sig operations into account. + // spendingTx in itself does not contain a signature operation. + assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 0); + // creationTx contains two signature operations in its scriptPubKey, but legacy counting + // is not accurate. + assert(GetTransactionSigOpCost(CTransaction(creationTx), coins, flags) == MAX_PUBKEYS_PER_MULTISIG * WITNESS_SCALE_FACTOR); + // Sanity check: script verification fails because of an invalid signature. + assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY); + } + + // Multisig nested in P2SH + { + CScript redeemScript = CScript() << 1 << ToByteVector(pubkey) << ToByteVector(pubkey) << 2 << OP_CHECKMULTISIGVERIFY; + CScript scriptPubKey = GetScriptForDestination(CScriptID(redeemScript)); + CScript scriptSig = CScript() << OP_0 << OP_0 << ToByteVector(redeemScript); + + BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, CTxinWitness()); + assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 2 * WITNESS_SCALE_FACTOR); + assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY); + } + + // P2WPKH witness program + { + CScript p2pk = CScript() << ToByteVector(pubkey) << OP_CHECKSIG; + CScript scriptPubKey = GetScriptForWitness(p2pk); + CScript scriptSig = CScript(); + CTxinWitness witness; + CScriptWitness scriptWitness; + scriptWitness.stack.push_back(vector(0)); + scriptWitness.stack.push_back(vector(0)); + witness.scriptWitness = scriptWitness; + + + BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, witness); + assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 1); + // No signature operations if we don't verify the witness. + assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags & ~SCRIPT_VERIFY_WITNESS) == 0); + assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_EQUALVERIFY); + + // The sig op cost for witness version != 0 is zero. + assert(scriptPubKey[0] == 0x00); + scriptPubKey[0] = 0x51; + BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, witness); + assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 0); + scriptPubKey[0] = 0x00; + BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, witness); + + // The witness of a coinbase transaction is not taken into account. + spendingTx.vin[0].prevout.SetNull(); + assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 0); + } + + // P2WPKH nested in P2SH + { + CScript p2pk = CScript() << ToByteVector(pubkey) << OP_CHECKSIG; + CScript scriptSig = GetScriptForWitness(p2pk); + CScript scriptPubKey = GetScriptForDestination(CScriptID(scriptSig)); + scriptSig = CScript() << ToByteVector(scriptSig); + CTxinWitness witness; + CScriptWitness scriptWitness; + scriptWitness.stack.push_back(vector(0)); + scriptWitness.stack.push_back(vector(0)); + witness.scriptWitness = scriptWitness; + + BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, witness); + assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 1); + assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_EQUALVERIFY); + } + + // P2WSH witness program + { + CScript witnessScript = CScript() << 1 << ToByteVector(pubkey) << ToByteVector(pubkey) << 2 << OP_CHECKMULTISIGVERIFY; + CScript scriptPubKey = GetScriptForWitness(witnessScript); + CScript scriptSig = CScript(); + CTxinWitness witness; + CScriptWitness scriptWitness; + scriptWitness.stack.push_back(vector(0)); + scriptWitness.stack.push_back(vector(0)); + scriptWitness.stack.push_back(vector(witnessScript.begin(), witnessScript.end())); + witness.scriptWitness = scriptWitness; + + BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, witness); + assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 2); + assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags & ~SCRIPT_VERIFY_WITNESS) == 0); + assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY); + } + + // P2WSH nested in P2SH + { + CScript witnessScript = CScript() << 1 << ToByteVector(pubkey) << ToByteVector(pubkey) << 2 << OP_CHECKMULTISIGVERIFY; + CScript redeemScript = GetScriptForWitness(witnessScript); + CScript scriptPubKey = GetScriptForDestination(CScriptID(redeemScript)); + CScript scriptSig = CScript() << ToByteVector(redeemScript); + CTxinWitness witness; + CScriptWitness scriptWitness; + scriptWitness.stack.push_back(vector(0)); + scriptWitness.stack.push_back(vector(0)); + scriptWitness.stack.push_back(vector(witnessScript.begin(), witnessScript.end())); + witness.scriptWitness = scriptWitness; + + BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, witness); + assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 2); + assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY); + } +} + BOOST_AUTO_TEST_SUITE_END() From 070dbc48a9338375fd7ce0a86ee05b476cf487a4 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 4 Jun 2016 22:38:36 +0200 Subject: [PATCH 0561/1802] --- [SEGWIT] begin: deployment --- From f8528134fc188abc5c7175a19680206964a8fade Mon Sep 17 00:00:00 2001 From: Johnson Lau Date: Fri, 6 May 2016 07:29:34 +0200 Subject: [PATCH 0562/1802] BIP9 parameters for testnet --- src/chainparams.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 2a198e8554c93..69d4a9ecbeb6e 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -190,8 +190,8 @@ class CTestNetParams : public CChainParams { // Deployment of SegWit (BIP141 and BIP143) consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].bit = 1; - consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 2000000000; // Far in the future - consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 2100000000; + consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 1462060800; // May 1st 2016 + consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1493596800; // May 1st 2017 pchMessageStart[0] = 0x0b; pchMessageStart[1] = 0x11; From 27f8126ff37ec590c266adc6228d216857606536 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Thu, 23 Jun 2016 12:44:53 +1000 Subject: [PATCH 0563/1802] remove unnecessary LOCK(cs_main) --- src/rpc/blockchain.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 1bb365d36cdad..e63232b4805d9 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -289,8 +289,6 @@ UniValue getrawmempool(const UniValue& params, bool fHelp) + HelpExampleRpc("getrawmempool", "true") ); - LOCK(cs_main); - bool fVerbose = false; if (params.size() > 0) fVerbose = params[0].get_bool(); From a1c92c29fd1c242831867ede4c67e544377ae473 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 23 Jun 2016 12:25:04 +0200 Subject: [PATCH 0564/1802] trivial: capitalize BIP32 in option help For consistency, BIP32 should be in uppercase in translation message. Reported by @pryds on Transifex. --- src/qt/bitcoinstrings.cpp | 2 +- src/qt/locale/bitcoin_en.ts | 14 +++++++------- src/wallet/wallet.cpp | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp index ce8753fc7ddc6..83901732acf17 100644 --- a/src/qt/bitcoinstrings.cpp +++ b/src/qt/bitcoinstrings.cpp @@ -173,7 +173,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" QT_TRANSLATE_NOOP("bitcoin-core", "" "Use UPnP to map the listening port (default: 1 when listening and no -proxy)"), QT_TRANSLATE_NOOP("bitcoin-core", "" -"Use hierarchical deterministic key generation (HD) after bip32. Only has " +"Use hierarchical deterministic key generation (HD) after BIP32. Only has " "effect during wallet creation/first start"), QT_TRANSLATE_NOOP("bitcoin-core", "" "Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: " diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts index f122273a35216..4e4c9f45e6ccd 100644 --- a/src/qt/locale/bitcoin_en.ts +++ b/src/qt/locale/bitcoin_en.ts @@ -2417,12 +2417,7 @@ - - Use hierarchical deterministic key generation (HD) after bip32. Only has effect during wallet creation/first start - - - - + WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) @@ -2852,7 +2847,12 @@ - + + Use hierarchical deterministic key generation (HD) after BIP32. Only has effect during wallet creation/first start + + + + 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 diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 723b2eceff7b2..ba5f92a987991 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3209,7 +3209,7 @@ std::string CWallet::GetWalletHelpString(bool showDebug) strUsage += HelpMessageOpt("-sendfreetransactions", strprintf(_("Send transactions as zero-fee transactions if possible (default: %u)"), DEFAULT_SEND_FREE_TRANSACTIONS)); strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), DEFAULT_SPEND_ZEROCONF_CHANGE)); strUsage += HelpMessageOpt("-txconfirmtarget=", strprintf(_("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)"), DEFAULT_TX_CONFIRM_TARGET)); - strUsage += HelpMessageOpt("-usehd", _("Use hierarchical deterministic key generation (HD) after bip32. Only has effect during wallet creation/first start") + " " + strprintf(_("(default: %u)"), DEFAULT_USE_HD_WALLET)); + strUsage += HelpMessageOpt("-usehd", _("Use hierarchical deterministic key generation (HD) after BIP32. Only has effect during wallet creation/first start") + " " + strprintf(_("(default: %u)"), DEFAULT_USE_HD_WALLET)); strUsage += HelpMessageOpt("-upgradewallet", _("Upgrade wallet to latest format on startup")); strUsage += HelpMessageOpt("-wallet=", _("Specify wallet file (within data directory)") + " " + strprintf(_("(default: %s)"), DEFAULT_WALLET_DAT)); strUsage += HelpMessageOpt("-walletbroadcast", _("Make the wallet broadcast transactions") + " " + strprintf(_("(default: %u)"), DEFAULT_WALLETBROADCAST)); From 133deb83dfedb09d1c5c477a01fb12665cbae16f Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 23 Jun 2016 15:44:35 +0200 Subject: [PATCH 0565/1802] Mark my dnsseed as supporting filtering --- src/chainparams.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 6eb66c78e2b6f..d888aae0963da 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -109,7 +109,7 @@ class CMainParams : public CChainParams { assert(consensus.hashGenesisBlock == uint256S("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f")); assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); - vSeeds.push_back(CDNSSeedData("bitcoin.sipa.be", "seed.bitcoin.sipa.be")); // Pieter Wuille + vSeeds.push_back(CDNSSeedData("bitcoin.sipa.be", "seed.bitcoin.sipa.be", true)); // Pieter Wuille vSeeds.push_back(CDNSSeedData("bluematt.me", "dnsseed.bluematt.me")); // Matt Corallo vSeeds.push_back(CDNSSeedData("dashjr.org", "dnsseed.bitcoin.dashjr.org")); // Luke Dashjr vSeeds.push_back(CDNSSeedData("bitcoinstats.com", "seed.bitcoinstats.com")); // Christian Decker From be1d451225cc6d1e4bfe08ac7e67ad0780450f04 Mon Sep 17 00:00:00 2001 From: Will Binns Date: Sun, 19 Jun 2016 17:15:36 -0600 Subject: [PATCH 0566/1802] contributing.md: Fix formatting This commit contains two changes to CONTRIBUTING.md that: Fix line line lengths. There were several instances where line lengths were well over 80 characters. This commit adjusts them to make them conform to formatting best practices, to stay under 80 characters when possible. Adhere to consist use of quotes. There are a few instances where smart quotes are used (perhaps because it was pasted from a word processor). This commit replaces them with dumb quotes to keep it consistent with the quotation formatting found in the rest of the document. --- CONTRIBUTING.md | 142 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 109 insertions(+), 33 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5c1138b812d47..62ebc7917aad4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,15 +1,26 @@ Contributing to Bitcoin Core ============================ -The Bitcoin Core project operates an open contributor model where anyone is welcome to contribute towards development in the form of peer review, testing and patches. This document explains the practical process and guidelines for contributing. +The Bitcoin Core project operates an open contributor model where anyone is +welcome to contribute towards development in the form of peer review, testing +and patches. This document explains the practical process and guidelines for +contributing. -Firstly in terms of structure, there is no particular concept of “Core developers” in the sense of privileged people. Open source often naturally revolves around meritocracy where longer term contributors gain more trust from the developer community. However, some hierarchy is necessary for practical purposes. As such there are repository “maintainers” who are responsible for merging pull requests as well as a “lead maintainer” who is responsible for the release cycle, overall merging, moderation and appointment of maintainers. +Firstly in terms of structure, there is no particular concept of "Core +developers" in the sense of privileged people. Open source often naturally +revolves around meritocracy where longer term contributors gain more trust from +the developer community. However, some hierarchy is necessary for practical +purposes. As such there are repository "maintainers" who are responsible for +merging pull requests as well as a "lead maintainer" who is responsible for the +release cycle, overall merging, moderation and appointment of maintainers. Contributor Workflow -------------------- -The codebase is maintained using the “contributor workflow” where everyone without exception contributes patch proposals using “pull requests”. This facilitates social contribution, easy testing and peer review. +The codebase is maintained using the "contributor workflow" where everyone +without exception contributes patch proposals using "pull requests". This +facilitates social contribution, easy testing and peer review. To contribute a patch, the workflow is as follows: @@ -17,35 +28,56 @@ To contribute a patch, the workflow is as follows: - Create topic branch - Commit patches -The project coding conventions in the [developer notes](doc/developer-notes.md) must be adhered to. +The project coding conventions in the [developer notes](doc/developer-notes.md) +must be adhered to. -In general [commits should be atomic](https://en.wikipedia.org/wiki/Atomic_commit#Atomic_commit_convention) and diffs should be easy to read. For this reason do not mix any formatting fixes or code moves with actual code changes. +In general [commits should be atomic](https://en.wikipedia.org/wiki/Atomic_commit#Atomic_commit_convention) +and diffs should be easy to read. For this reason do not mix any formatting +fixes or code moves with actual code changes. -Commit messages should be verbose by default consisting of a short subject line (50 chars max), a blank line and detailed explanatory text as separate paragraph(s); unless the title alone is self-explanatory (like "Corrected typo in main.cpp") then a single title line is sufficient. Commit messages should be helpful to people reading your code in the future, so explain the reasoning for your decisions. Further explanation [here](http://chris.beams.io/posts/git-commit/). +Commit messages should be verbose by default consisting of a short subject line +(50 chars max), a blank line and detailed explanatory text as separate +paragraph(s); unless the title alone is self-explanatory (like "Corrected typo +in main.cpp") then a single title line is sufficient. Commit messages should be +helpful to people reading your code in the future, so explain the reasoning for +your decisions. Further explanation [here](http://chris.beams.io/posts/git-commit/). -If a particular commit references another issue, please add the reference, for example `refs #1234`, or `fixes #4321`. Using the `fixes` or `closes` keywords will cause the corresponding issue to be closed when the pull request is merged. +If a particular commit references another issue, please add the reference, for +example `refs #1234`, or `fixes #4321`. Using the `fixes` or `closes` keywords +will cause the corresponding issue to be closed when the pull request is merged. -Please refer to the [Git manual](https://git-scm.com/doc) for more information about Git. +Please refer to the [Git manual](https://git-scm.com/doc) for more information +about Git. - Push changes to your fork - Create pull request -The title of the pull request should be prefixed by the component or area that the pull request affects. Examples: +The title of the pull request should be prefixed by the component or area that +the pull request affects. Examples: Consensus: Add new opcode for BIP-XXXX OP_CHECKAWESOMESIG Net: Automatically create hidden service, listen on Tor Qt: Add feed bump button Trivial: Fix typo in main.cpp -If a pull request is specifically not to be considered for merging (yet) please prefix the title with [WIP] or use [Tasks Lists](https://help.github.com/articles/basic-writing-and-formatting-syntax/#task-lists) in the body of the pull request to indicate tasks are pending. +If a pull request is specifically not to be considered for merging (yet) please +prefix the title with [WIP] or use [Tasks Lists](https://help.github.com/articles/basic-writing-and-formatting-syntax/#task-lists) +in the body of the pull request to indicate tasks are pending. -The body of the pull request should contain enough description about what the patch does together with any justification/reasoning. You should include references to any discussions (for example other tickets or mailing list discussions). +The body of the pull request should contain enough description about what the +patch does together with any justification/reasoning. You should include +references to any discussions (for example other tickets or mailing list +discussions). -At this stage one should expect comments and review from other contributors. You can add more commits to your pull request by committing them locally and pushing to your fork until you have satisfied all feedback. +At this stage one should expect comments and review from other contributors. You +can add more commits to your pull request by committing them locally and pushing +to your fork until you have satisfied all feedback. Squashing Commits --------------------------- -If your pull request is accepted for merging, you may be asked by a maintainer to squash and or [rebase](https://git-scm.com/docs/git-rebase) your commits before it will be merged. The basic squashing workflow is shown below. +If your pull request is accepted for merging, you may be asked by a maintainer +to squash and or [rebase](https://git-scm.com/docs/git-rebase) your commits +before it will be merged. The basic squashing workflow is shown below. git checkout your_branch_name git rebase -i HEAD~n @@ -55,67 +87,111 @@ If your pull request is accepted for merging, you may be asked by a maintainer t # save and quit git push -f # (force push to GitHub) -The length of time required for peer review is unpredictable and will vary from pull request to pull request. +The length of time required for peer review is unpredictable and will vary from +pull request to pull request. Pull Request Philosophy ----------------------- -Patchsets should always be focused. For example, a pull request could add a feature, fix a bug, or refactor code; but not a mixture. Please also avoid super pull requests which attempt to do too much, are overly large, or overly complex as this makes review difficult. +Patchsets should always be focused. For example, a pull request could add a +feature, fix a bug, or refactor code; but not a mixture. Please also avoid super +pull requests which attempt to do too much, are overly large, or overly complex +as this makes review difficult. ###Features -When adding a new feature, thought must be given to the long term technical debt and maintenance that feature may require after inclusion. Before proposing a new feature that will require maintenance, please consider if you are willing to maintain it (including bug fixing). If features get orphaned with no maintainer in the future, they may be removed by the Repository Maintainer. +When adding a new feature, thought must be given to the long term technical debt +and maintenance that feature may require after inclusion. Before proposing a new +feature that will require maintenance, please consider if you are willing to +maintain it (including bug fixing). If features get orphaned with no maintainer +in the future, they may be removed by the Repository Maintainer. ###Refactoring -Refactoring is a necessary part of any software project's evolution. The following guidelines cover refactoring pull requests for the project. +Refactoring is a necessary part of any software project's evolution. The +following guidelines cover refactoring pull requests for the project. -There are three categories of refactoring, code only moves, code style fixes, code refactoring. In general refactoring pull requests should not mix these three kinds of activity in order to make refactoring pull requests easy to review and uncontroversial. In all cases, refactoring PRs must not change the behaviour of code within the pull request (bugs must be preserved as is). +There are three categories of refactoring, code only moves, code style fixes, +code refactoring. In general refactoring pull requests should not mix these +three kinds of activity in order to make refactoring pull requests easy to +review and uncontroversial. In all cases, refactoring PRs must not change the +behaviour of code within the pull request (bugs must be preserved as is). -Project maintainers aim for a quick turnaround on refactoring pull requests, so where possible keep them short, uncomplex and easy to verify. +Project maintainers aim for a quick turnaround on refactoring pull requests, so +where possible keep them short, uncomplex and easy to verify. "Decision Making" Process ------------------------- -The following applies to code changes to the Bitcoin Core project (and related projects such as libsecp256k1), and is not to be confused with overall Bitcoin Network Protocol consensus changes. +The following applies to code changes to the Bitcoin Core project (and related +projects such as libsecp256k1), and is not to be confused with overall Bitcoin +Network Protocol consensus changes. -Whether a pull request is merged into Bitcoin Core rests with the project merge maintainers and ultimately the project lead. +Whether a pull request is merged into Bitcoin Core rests with the project merge +maintainers and ultimately the project lead. -Maintainers will take into consideration if a patch is in line with the general principles of the project; meets the minimum standards for inclusion; and will judge the general consensus of contributors. +Maintainers will take into consideration if a patch is in line with the general +principles of the project; meets the minimum standards for inclusion; and will +judge the general consensus of contributors. In general, all pull requests must: - - have a clear use case, fix a demonstrable bug or serve the greater good of the project (for example refactoring for modularisation); + - have a clear use case, fix a demonstrable bug or serve the greater good of + the project (for example refactoring for modularisation); - be well peer reviewed; - have unit tests and functional tests where appropriate; - follow code style guidelines; - not break the existing test suite; - - where bugs are fixed, where possible, there should be unit tests demonstrating the bug and also proving the fix. This helps prevent regression. + - where bugs are fixed, where possible, there should be unit tests + demonstrating the bug and also proving the fix. This helps prevent regression. -Patches that change Bitcoin consensus rules are considerably more involved than normal because they affect the entire ecosystem and so must be preceded by extensive mailing list discussions and have a numbered BIP. While each case will be different, one should be prepared to expend more time and effort than for other kinds of patches because of increased peer review and consensus building requirements. +Patches that change Bitcoin consensus rules are considerably more involved than +normal because they affect the entire ecosystem and so must be preceded by +extensive mailing list discussions and have a numbered BIP. While each case will +be different, one should be prepared to expend more time and effort than for +other kinds of patches because of increased peer review and consensus building +requirements. ###Peer Review -Anyone may participate in peer review which is expressed by comments in the pull request. Typically reviewers will review the code for obvious errors, as well as test out the patch set and opine on the technical merits of the patch. Project maintainers take into account the peer review when determining if there is consensus to merge a pull request (remember that discussions may have been spread out over github, mailing list and IRC discussions). The following language is used within pull-request comments: +Anyone may participate in peer review which is expressed by comments in the pull +request. Typically reviewers will review the code for obvious errors, as well as +test out the patch set and opine on the technical merits of the patch. Project +maintainers take into account the peer review when determining if there is +consensus to merge a pull request (remember that discussions may have been +spread out over github, mailing list and IRC discussions). The following +language is used within pull-request comments: - ACK means "I have tested the code and I agree it should be merged"; - - NACK means "I disagree this should be merged", and must be accompanied by sound technical justification. NACKs without accompanying reasoning may be disregarded; - - utACK means "I have not tested the code, but I have reviewed it and it looks OK, I agree it can be merged"; + - NACK means "I disagree this should be merged", and must be accompanied by + sound technical justification. NACKs without accompanying reasoning may be disregarded; + - utACK means "I have not tested the code, but I have reviewed it and it looks + OK, I agree it can be merged"; - Concept ACK means "I agree in the general principle of this pull request"; - Nit refers to trivial, often non-blocking issues. Reviewers should include the commit hash which they reviewed in their comments. -Project maintainers reserve the right to weigh the opinions of peer reviewers using common sense judgement and also may weight based on meritocracy: Those that have demonstrated a deeper commitment and understanding towards the project (over time) or have clear domain expertise may naturally have more weight, as one would expect in all walks of life. - -Where a patch set affects consensus critical code, the bar will be set much higher in terms of discussion and peer review requirements, keeping in mind that mistakes could be very costly to the wider community. This includes refactoring of consensus critical code. - -Where a patch set proposes to change the Bitcoin consensus, it must have been discussed extensively on the mailing list and IRC, be accompanied by a widely discussed BIP and have a generally widely perceived technical consensus of being a worthwhile change based on the judgement of the maintainers. +Project maintainers reserve the right to weigh the opinions of peer reviewers +using common sense judgement and also may weight based on meritocracy: Those +that have demonstrated a deeper commitment and understanding towards the project +(over time) or have clear domain expertise may naturally have more weight, as +one would expect in all walks of life. + +Where a patch set affects consensus critical code, the bar will be set much +higher in terms of discussion and peer review requirements, keeping in mind that +mistakes could be very costly to the wider community. This includes refactoring +of consensus critical code. + +Where a patch set proposes to change the Bitcoin consensus, it must have been +discussed extensively on the mailing list and IRC, be accompanied by a widely +discussed BIP and have a generally widely perceived technical consensus of being +a worthwhile change based on the judgement of the maintainers. Release Policy From f70bcfc6c052bab8c7f78fae8aa69bbe64adaa94 Mon Sep 17 00:00:00 2001 From: fanquake Date: Fri, 24 Jun 2016 15:01:45 +0800 Subject: [PATCH 0567/1802] [trivial] Add aarch64 to depends .gitignore --- depends/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/depends/.gitignore b/depends/.gitignore index 1f163897b9ef7..3cb4b9ac15557 100644 --- a/depends/.gitignore +++ b/depends/.gitignore @@ -7,3 +7,4 @@ x86_64* i686* mips* arm* +aarch64* From d24148742e2e3df1011a65c1b4c5589609bab05e Mon Sep 17 00:00:00 2001 From: fanquake Date: Fri, 24 Jun 2016 15:32:48 +0800 Subject: [PATCH 0568/1802] [doc] Add OS X ZMQ requirement to QA readme --- qa/README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/qa/README.md b/qa/README.md index 7489eb5130ac0..723660c6c857e 100644 --- a/qa/README.md +++ b/qa/README.md @@ -16,6 +16,12 @@ The python3-zmq library is required. On Ubuntu or Debian it can be installed via sudo apt-get install python3-zmq ``` +OS X +------ +``` +pip3 install pyzmq +``` + Running tests ============= @@ -36,7 +42,7 @@ Run all possible tests with qa/pull-tester/rpc-tests.py -extended By default, tests will be run in parallel if you want to specify how many -tests should be run in parallel, append `-paralell=n` (default n=4). +tests should be run in parallel, append `-parallel=n` (default n=4). If you want to create a basic coverage report for the rpc test suite, append `--coverage`. From d7828abd5b08ae17a42a7b8efe3b546fe2d09f4b Mon Sep 17 00:00:00 2001 From: fsb4000 Date: Fri, 24 Jun 2016 17:05:45 +0700 Subject: [PATCH 0569/1802] check that transactionView->selectionModel()->selectedRows(0) exists --- src/qt/transactionview.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index 199a7b2d77b1b..48cf94050297b 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -365,6 +365,8 @@ void TransactionView::contextualMenu(const QPoint &point) { QModelIndex index = transactionView->indexAt(point); QModelIndexList selection = transactionView->selectionModel()->selectedRows(0); + if (selection.empty()) + return; // check if transaction can be abandoned, disable context menu action in case it doesn't uint256 hash; From 1acf1db76fc3e07deb8f0f837934ea90383fedb5 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 24 Jun 2016 16:35:21 +0200 Subject: [PATCH 0570/1802] Do not ask a UI question from bitcoind --- src/init.cpp | 3 ++- src/noui.cpp | 6 ++++++ src/qt/bitcoingui.cpp | 2 ++ src/ui_interface.h | 3 +++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/init.cpp b/src/init.cpp index b572bfc32720a..fe367c6a33315 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1317,8 +1317,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (!fLoaded) { // first suggest a reindex if (!fReset) { - bool fRet = uiInterface.ThreadSafeMessageBox( + bool fRet = uiInterface.ThreadSafeQuestion( strLoadError + ".\n\n" + _("Do you want to rebuild the block database now?"), + strLoadError + ".\nPlease restart with -reindex or -reindex-chainstate to recover.", "", CClientUIInterface::MSG_ERROR | CClientUIInterface::BTN_ABORT); if (fRet) { fReindex = true; diff --git a/src/noui.cpp b/src/noui.cpp index 3a77361919e63..0d9207c11a319 100644 --- a/src/noui.cpp +++ b/src/noui.cpp @@ -39,6 +39,11 @@ static bool noui_ThreadSafeMessageBox(const std::string& message, const std::str return false; } +static bool noui_ThreadSafeQuestion(const std::string& /* ignored interactive message */, const std::string& message, const std::string& caption, unsigned int style) +{ + return noui_ThreadSafeMessageBox(message, caption, style); +} + static void noui_InitMessage(const std::string& message) { LogPrintf("init message: %s\n", message); @@ -48,5 +53,6 @@ void noui_connect() { // Connect bitcoind signal handlers uiInterface.ThreadSafeMessageBox.connect(noui_ThreadSafeMessageBox); + uiInterface.ThreadSafeQuestion.connect(noui_ThreadSafeQuestion); uiInterface.InitMessage.connect(noui_InitMessage); } diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 50c19c3848046..9042e3b56a3b8 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -1105,12 +1105,14 @@ void BitcoinGUI::subscribeToCoreSignals() { // Connect signals to client uiInterface.ThreadSafeMessageBox.connect(boost::bind(ThreadSafeMessageBox, this, _1, _2, _3)); + uiInterface.ThreadSafeQuestion.connect(boost::bind(ThreadSafeMessageBox, this, _1, _3, _4)); } void BitcoinGUI::unsubscribeFromCoreSignals() { // Disconnect signals from client uiInterface.ThreadSafeMessageBox.disconnect(boost::bind(ThreadSafeMessageBox, this, _1, _2, _3)); + uiInterface.ThreadSafeQuestion.disconnect(boost::bind(ThreadSafeMessageBox, this, _1, _3, _4)); } UnitDisplayStatusBarControl::UnitDisplayStatusBarControl(const PlatformStyle *platformStyle) : diff --git a/src/ui_interface.h b/src/ui_interface.h index 7ebfc17e5dd52..7e6557f8e21b0 100644 --- a/src/ui_interface.h +++ b/src/ui_interface.h @@ -76,6 +76,9 @@ class CClientUIInterface /** Show message box. */ boost::signals2::signal > ThreadSafeMessageBox; + /** If possible, ask the user a question. If not, falls back to ThreadSafeMessageBox(noninteractive_message, caption, style) and returns false. */ + boost::signals2::signal > ThreadSafeQuestion; + /** Progress message during initialization. */ boost::signals2::signal InitMessage; From b0be3a0186114c8f566292fc9001debcbe79a663 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 22 Jun 2016 16:29:00 +0200 Subject: [PATCH 0571/1802] doc: Mention Windows XP end of support in release notes Closes #7681. --- doc/release-notes.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/doc/release-notes.md b/doc/release-notes.md index df3c265dcdbd2..6e4f390cbcc75 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -16,6 +16,28 @@ To receive security and update notifications, please subscribe to: +Compatibility +============== + +Microsoft ended support for Windows XP on [April 8th, 2014](https://www.microsoft.com/en-us/WindowsForBusiness/end-of-xp-support), +an OS initially released in 2001. This means that not even critical security +updates will be released anymore. Without security updates, using a bitcoin +wallet on a XP machine is irresponsible at least. + +In addition to that, with 0.12.x there have been varied reports of Bitcoin Core +randomly crashing on Windows XP. It is [not clear](https://github.com/bitcoin/bitcoin/issues/7681#issuecomment-217439891) +what the source of these crashes is, but it is likely that upstream +libraries such as Qt are no longer being tested on XP. + +We do not have time nor resources to provide support for an OS that is +end-of-life. From 0.13.0 on, Windows XP is no longer supported. Users are +suggested to upgrade to a newer verion of Windows, or install an alternative OS +that is supported. + +No attempt is made to prevent installing or running the software on Windows XP, +you can still do so at your own risk, but do not expect it to work: do not +report issues about Windows XP to the issue tracker. + Notable changes =============== From 409f83322e9fe3257cf9f3f61813195ac1aaa20c Mon Sep 17 00:00:00 2001 From: jl2012 Date: Sat, 25 Jun 2016 00:55:07 +0800 Subject: [PATCH 0572/1802] RPC: Hide softfork if timeout is 0 --- src/rpc/blockchain.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 43ba4edd78c19..60462b9f87aaa 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -868,6 +868,15 @@ static UniValue BIP9SoftForkDesc(const Consensus::Params& consensusParams, Conse return rv; } +void BIP9SoftForkDescPushBack(UniValue& bip9_softforks, const std::string &name, const Consensus::Params& consensusParams, Consensus::DeploymentPos id) +{ + // Deployments with timeout value of 0 are hidden. + // A timeout value of 0 guarantees a softfork will never be activated. + // This is used when softfork codes are merged without specifying the deployment schedule. + if (consensusParams.vDeployments[id].nTimeout > 0) + bip9_softforks.push_back(Pair(name, BIP9SoftForkDesc(consensusParams, id))); +} + UniValue getblockchaininfo(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 0) @@ -901,7 +910,7 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) " ],\n" " \"bip9_softforks\": { (object) status of BIP9 softforks in progress\n" " \"xxxx\" : { (string) name of the softfork\n" - " \"status\": \"xxxx\", (string) one of \"defined\", \"started\", \"lockedin\", \"active\", \"failed\"\n" + " \"status\": \"xxxx\", (string) one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\"\n" " \"bit\": xx, (numeric) the bit, 0-28, in the block version field used to signal this soft fork\n" " \"startTime\": xx, (numeric) the minimum median time past of a block at which the bit gains its meaning\n" " \"timeout\": xx (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in\n" @@ -933,8 +942,8 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams)); softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams)); softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams)); - bip9_softforks.push_back(Pair("csv", BIP9SoftForkDesc(consensusParams, Consensus::DEPLOYMENT_CSV))); - bip9_softforks.push_back(Pair("segwit", BIP9SoftForkDesc(consensusParams, Consensus::DEPLOYMENT_SEGWIT))); + BIP9SoftForkDescPushBack(bip9_softforks, "csv", consensusParams, Consensus::DEPLOYMENT_CSV); + BIP9SoftForkDescPushBack(bip9_softforks, "segwit", consensusParams, Consensus::DEPLOYMENT_SEGWIT); obj.push_back(Pair("softforks", softforks)); obj.push_back(Pair("bip9_softforks", bip9_softforks)); From 873e81f89b3197580aca3dd4a591d00e41696a89 Mon Sep 17 00:00:00 2001 From: Matthew King Date: Sun, 26 Jun 2016 16:47:03 +0300 Subject: [PATCH 0573/1802] Use portable #! in python scripts (/usr/bin/env) --- contrib/devtools/security-check.py | 2 +- contrib/devtools/symbol-check.py | 2 +- contrib/devtools/test-security-check.py | 2 +- contrib/devtools/update-translations.py | 2 +- contrib/linearize/linearize-data.py | 2 +- contrib/linearize/linearize-hashes.py | 2 +- contrib/seeds/generate-seeds.py | 2 +- share/qt/extract_strings_qt.py | 2 +- src/test/bitcoin-util-test.py | 2 +- src/test/buildenv.py.in | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/contrib/devtools/security-check.py b/contrib/devtools/security-check.py index 301fea85c1f6f..24e44cf5d8628 100755 --- a/contrib/devtools/security-check.py +++ b/contrib/devtools/security-check.py @@ -1,4 +1,4 @@ -#!/usr/bin/python2 +#!/usr/bin/env python2 ''' Perform basic ELF security checks on a series of executables. Exit status will be 0 if successful, and the program will be silent. diff --git a/contrib/devtools/symbol-check.py b/contrib/devtools/symbol-check.py index e26c0fbb94455..8c064a1822b00 100755 --- a/contrib/devtools/symbol-check.py +++ b/contrib/devtools/symbol-check.py @@ -1,4 +1,4 @@ -#!/usr/bin/python2 +#!/usr/bin/env python2 # Copyright (c) 2014 Wladimir J. van der Laan # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/contrib/devtools/test-security-check.py b/contrib/devtools/test-security-check.py index fed7626aabaaf..324b7bcd85ae3 100755 --- a/contrib/devtools/test-security-check.py +++ b/contrib/devtools/test-security-check.py @@ -1,4 +1,4 @@ -#!/usr/bin/python2 +#!/usr/bin/env python2 ''' Test script for security-check.py ''' diff --git a/contrib/devtools/update-translations.py b/contrib/devtools/update-translations.py index 2b6e807b4718c..78b9f9d179eb6 100755 --- a/contrib/devtools/update-translations.py +++ b/contrib/devtools/update-translations.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # Copyright (c) 2014 Wladimir J. van der Laan # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/contrib/linearize/linearize-data.py b/contrib/linearize/linearize-data.py index 0f6fde2a6e052..8badb4b318b01 100755 --- a/contrib/linearize/linearize-data.py +++ b/contrib/linearize/linearize-data.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # # linearize-data.py: Construct a linear, no-fork version of the chain. # diff --git a/contrib/linearize/linearize-hashes.py b/contrib/linearize/linearize-hashes.py index 854cf1f9eeb3d..cb40c664fafde 100755 --- a/contrib/linearize/linearize-hashes.py +++ b/contrib/linearize/linearize-hashes.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # # linearize-hashes.py: List blocks in a linear, no-fork version of the chain. # diff --git a/contrib/seeds/generate-seeds.py b/contrib/seeds/generate-seeds.py index a3d035218789b..f43dc0b218adb 100755 --- a/contrib/seeds/generate-seeds.py +++ b/contrib/seeds/generate-seeds.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # Copyright (c) 2014 Wladimir J. van der Laan # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/share/qt/extract_strings_qt.py b/share/qt/extract_strings_qt.py index 2ba8bb9b3acb7..9624abf1fcdd3 100755 --- a/share/qt/extract_strings_qt.py +++ b/share/qt/extract_strings_qt.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python ''' Extract _("...") strings for translation and convert to Qt stringdefs so that they can be picked up by Qt linguist. diff --git a/src/test/bitcoin-util-test.py b/src/test/bitcoin-util-test.py index 95dd3e81b4369..882b5c67b862d 100755 --- a/src/test/bitcoin-util-test.py +++ b/src/test/bitcoin-util-test.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # Copyright 2014 BitPay, Inc. # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/buildenv.py.in b/src/test/buildenv.py.in index 1618bdeb764b8..153f34a3dbc71 100644 --- a/src/test/buildenv.py.in +++ b/src/test/buildenv.py.in @@ -1,2 +1,2 @@ -#!/usr/bin/python +#!/usr/bin/env python exeext="@EXEEXT@" From 252675efc69ec0638d96a69fbc349a612cd1e2b7 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 26 Jun 2016 20:19:00 +0200 Subject: [PATCH 0574/1802] Do not send witnesses in cmpctblock --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 6cdd55e3979df..0bc90ab4a7224 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6538,7 +6538,7 @@ bool SendMessages(CNode* pto) CBlock block; assert(ReadBlockFromDisk(block, pBestIndex, consensusParams)); CBlockHeaderAndShortTxIDs cmpctblock(block); - pto->PushMessage(NetMsgType::CMPCTBLOCK, cmpctblock); + pto->PushMessageWithFlag(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::CMPCTBLOCK, cmpctblock); state.pindexBestHeaderSent = pBestIndex; } else if (state.fPreferHeaders) { if (vHeaders.size() > 1) { From f15c2cde455174c7c899833fd5792460ed49a472 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Mon, 27 Jun 2016 10:58:58 -0400 Subject: [PATCH 0575/1802] CreateNewBlock: add support for size-accounting to addPackageTxs Includes a change to not continue to use size-accounting in addScoreTxs or addPackageTxs just because addPriorityTxs() is used. --- src/miner.cpp | 25 +++++++++++++++---------- src/miner.h | 2 +- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/miner.cpp b/src/miner.cpp index cfc2dae56ee49..a3e29431d7552 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -94,6 +94,7 @@ BlockAssembler::BlockAssembler(const CChainParams& _chainparams) nBlockMaxCost = nBlockMaxSize * WITNESS_SCALE_FACTOR; } } + // Limit cost to between 4K and MAX_BLOCK_COST-4K for sanity: nBlockMaxCost = std::max((unsigned int)4000, std::min((unsigned int)(MAX_BLOCK_COST-4000), nBlockMaxCost)); // Limit size to between 1K and MAX_BLOCK_SERIALIZED_SIZE-1K for sanity: @@ -167,13 +168,7 @@ CBlockTemplate* BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn) fIncludeWitness = IsWitnessEnabled(pindexPrev, chainparams.GetConsensus()); addPriorityTxs(); - if (fNeedSizeAccounting) { - // addPackageTxs (the CPFP-based algorithm) cannot deal with size based - // accounting, so fall back to the old algorithm. - addScoreTxs(); - } else { - addPackageTxs(); - } + addPackageTxs(); nLastBlockTx = nBlockTx; nLastBlockSize = nBlockSize; @@ -243,11 +238,19 @@ bool BlockAssembler::TestPackage(uint64_t packageSize, int64_t packageSigOpsCost // Block size and sigops have already been tested. Check that all transactions // are final. -bool BlockAssembler::TestPackageFinality(const CTxMemPool::setEntries& package) +bool BlockAssembler::TestPackageFinalityAndSerializedSize(const CTxMemPool::setEntries& package) { + uint64_t nPotentialBlockSize = nBlockSize; // only used with fNeedSizeAccounting BOOST_FOREACH (const CTxMemPool::txiter it, package) { if (!IsFinalTx(it->GetTx(), nHeight, nLockTimeCutoff)) return false; + if (fNeedSizeAccounting) { + uint64_t nTxSize = ::GetSerializeSize(it->GetTx(), SER_NETWORK, PROTOCOL_VERSION); + if (nPotentialBlockSize + nTxSize >= nBlockMaxSize) { + return false; + } + nPotentialBlockSize += nTxSize; + } } return true; } @@ -539,7 +542,7 @@ void BlockAssembler::addPackageTxs() ancestors.insert(iter); // Test if all tx's are Final - if (!TestPackageFinality(ancestors)) { + if (!TestPackageFinalityAndSerializedSize(ancestors)) { if (fUsingModified) { mapModifiedTx.get().erase(modit); failedTx.insert(iter); @@ -573,6 +576,7 @@ void BlockAssembler::addPriorityTxs() return; } + bool fSizeAccounting = fNeedSizeAccounting; fNeedSizeAccounting = true; // This vector will be sorted into a priority queue: @@ -624,7 +628,7 @@ void BlockAssembler::addPriorityTxs() // If now that this txs is added we've surpassed our desired priority size // or have dropped below the AllowFreeThreshold, then we're done adding priority txs if (nBlockSize >= nBlockPrioritySize || !AllowFree(actualPriority)) { - return; + break; } // This tx was successfully added, so @@ -640,6 +644,7 @@ void BlockAssembler::addPriorityTxs() } } } + fNeedSizeAccounting = fSizeAccounting; } void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned int& nExtraNonce) diff --git a/src/miner.h b/src/miner.h index b303a8fa3ceb7..bc4da63da074f 100644 --- a/src/miner.h +++ b/src/miner.h @@ -193,7 +193,7 @@ class BlockAssembler /** Test if a new package would "fit" in the block */ bool TestPackage(uint64_t packageSize, int64_t packageSigOpsCost); /** Test if a set of transactions are all final */ - bool TestPackageFinality(const CTxMemPool::setEntries& package); + bool TestPackageFinalityAndSerializedSize(const CTxMemPool::setEntries& package); /** Return true if given transaction from mapTx has already been evaluated, * or if the transaction's cached data in mapTx is incorrect. */ bool SkipMapTxEntry(CTxMemPool::txiter it, indexed_modified_transaction_set &mapModifiedTx, CTxMemPool::setEntries &failedTx); From 695041e4952ea40e02e3b0431d04ca6af7ec9711 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 27 Jun 2016 17:06:47 +0200 Subject: [PATCH 0576/1802] util: Update tinyformat Updates `tinyformat.h` to commit https://github.com/c42f/tinyformat/commit/3a33bbf65442432277eee079e83d3e8fac51730c upstream. Makes sure that our local changes are kept: - #3767 1b8fd35aadfad6a1e55391f02add6076c8c9ea8f Make tinyformat errors raise an exception instead of assert()ing - #4735 9b6d4c5cdc1ad7b12b8b7ba05125dad9ba2d396e Move strprintf define to tinyformat.h - #4748 6e5fd003e04b81115b6b164b21f048472d575535 include stdexcept (for std::exception) - #8000 9eaa0afa6ec5d3dd01e4d01121314ef51f2bc305 force USE_VARIADIC_TEMPLATES - Add `std::string format(const std::string &fmt...` added this at the time, as we want to be able to do `strprintf(_(...), ...)` Inspired by #8264. --- src/tinyformat.h | 700 +++++++++++++++++++++++++---------------------- 1 file changed, 368 insertions(+), 332 deletions(-) diff --git a/src/tinyformat.h b/src/tinyformat.h index c6ec0419b3943..17f0360c42f24 100644 --- a/src/tinyformat.h +++ b/src/tinyformat.h @@ -67,7 +67,9 @@ // weekday, month, day, hour, min); // std::cout << date; // -// These are the three primary interface functions. +// These are the three primary interface functions. There is also a +// convenience function printfln() which appends a newline to the usual result +// of printf() for super simple logging. // // // User defined format functions @@ -86,6 +88,18 @@ // defined function bodies, use the macro TINYFORMAT_FOREACH_ARGNUM. For an // example, see the implementation of printf() at the end of the source file. // +// Sometimes it's useful to be able to pass a list of format arguments through +// to a non-template function. The FormatList class is provided as a way to do +// this by storing the argument list in a type-opaque way. Continuing the +// example from above, we construct a FormatList using makeFormatList(): +// +// FormatListRef formatList = tfm::makeFormatList(weekday, month, day, hour, min); +// +// The format list can now be passed into any non-template function and used +// via a call to the vformat() function: +// +// tfm::vformat(std::cout, "%s, %s %d, %.2d:%.2d\n", formatList); +// // // Additional API information // -------------------------- @@ -118,6 +132,7 @@ namespace tfm = tinyformat; //------------------------------------------------------------------------------ // Implementation details. +#include #include #include #include @@ -133,20 +148,20 @@ namespace tfm = tinyformat; # endif #endif -#ifdef __GNUC__ -# define TINYFORMAT_NOINLINE __attribute__((noinline)) -#elif defined(_MSC_VER) -# define TINYFORMAT_NOINLINE __declspec(noinline) -#else -# define TINYFORMAT_NOINLINE -#endif - #if defined(__GLIBCXX__) && __GLIBCXX__ < 20080201 // std::showpos is broken on old libstdc++ as provided with OSX. See // http://gcc.gnu.org/ml/libstdc++/2007-11/msg00075.html # define TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND #endif +#ifdef __APPLE__ +// Workaround OSX linker warning: xcode uses different default symbol +// visibilities for static libs vs executables (see issue #25) +# define TINYFORMAT_HIDDEN __attribute__((visibility("hidden"))) +#else +# define TINYFORMAT_HIDDEN +#endif + namespace tinyformat { //------------------------------------------------------------------------------ @@ -247,6 +262,29 @@ struct convertToInt static int invoke(const T& value) { return static_cast(value); } }; +// Format at most ntrunc characters to the given stream. +template +inline void formatTruncated(std::ostream& out, const T& value, int ntrunc) +{ + std::ostringstream tmp; + tmp << value; + std::string result = tmp.str(); + out.write(result.c_str(), (std::min)(ntrunc, static_cast(result.size()))); +} +#define TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR(type) \ +inline void formatTruncated(std::ostream& out, type* value, int ntrunc) \ +{ \ + std::streamsize len = 0; \ + while(len < ntrunc && value[len] != 0) \ + ++len; \ + out.write(value, len); \ +} +// Overload for const char* and char*. Could overload for signed & unsigned +// char too, but these are technically unneeded for printf compatibility. +TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR(const char) +TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR(char) +#undef TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR + } // namespace detail @@ -255,18 +293,20 @@ struct convertToInt // desired. -// Format a value into a stream. Called from format() for all types by default. -// -// Users may override this for their own types. When this function is called, -// the stream flags will have been modified according to the format string. -// The format specification is provided in the range [fmtBegin, fmtEnd). -// -// By default, formatValue() uses the usual stream insertion operator -// operator<< to format the type T, with special cases for the %c and %p -// conversions. +/// Format a value into a stream, delegating to operator<< by default. +/// +/// Users may override this for their own types. When this function is called, +/// the stream flags will have been modified according to the format string. +/// The format specification is provided in the range [fmtBegin, fmtEnd). For +/// truncating conversions, ntrunc is set to the desired maximum number of +/// characters, for example "%.7s" calls formatValue with ntrunc = 7. +/// +/// By default, formatValue() uses the usual stream insertion operator +/// operator<< to format the type T, with special cases for the %c and %p +/// conversions. template inline void formatValue(std::ostream& out, const char* /*fmtBegin*/, - const char* fmtEnd, const T& value) + const char* fmtEnd, int ntrunc, const T& value) { #ifndef TINYFORMAT_ALLOW_WCHAR_STRINGS // Since we don't support printing of wchar_t using "%ls", make it fail at @@ -288,6 +328,12 @@ inline void formatValue(std::ostream& out, const char* /*fmtBegin*/, #ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND else if(detail::formatZeroIntegerWorkaround::invoke(out, value)) /**/; #endif + else if(ntrunc >= 0) + { + // Take care not to overread C strings in truncating conversions like + // "%.4s" where at most 4 characters may be read. + detail::formatTruncated(out, value, ntrunc); + } else out << value; } @@ -296,7 +342,7 @@ inline void formatValue(std::ostream& out, const char* /*fmtBegin*/, // Overloaded version for char types to support printing as an integer #define TINYFORMAT_DEFINE_FORMATVALUE_CHAR(charType) \ inline void formatValue(std::ostream& out, const char* /*fmtBegin*/, \ - const char* fmtEnd, charType value) \ + const char* fmtEnd, int /**/, charType value) \ { \ switch(*(fmtEnd-1)) \ { \ @@ -435,225 +481,91 @@ cog.outl('#define TINYFORMAT_FOREACH_ARGNUM(m) \\\n ' + namespace detail { -// Class holding current position in format string and an output stream into -// which arguments are formatted. -class FormatIterator +// Type-opaque holder for an argument to format(), with associated actions on +// the type held as explicit function pointers. This allows FormatArg's for +// each argument to be allocated as a homogenous array inside FormatList +// whereas a naive implementation based on inheritance does not. +class FormatArg { public: - // Flags for features not representable with standard stream state - enum ExtraFormatFlags - { - Flag_None = 0, - Flag_TruncateToPrecision = 1<<0, // truncate length to stream precision() - Flag_SpacePadPositive = 1<<1, // pad positive values with spaces - Flag_VariableWidth = 1<<2, // variable field width in arg list - Flag_VariablePrecision = 1<<3 // variable field precision in arg list - }; - - // out is the output stream, fmt is the full format string - FormatIterator(std::ostream& out, const char* fmt) - : m_out(out), - m_fmt(fmt), - m_extraFlags(Flag_None), - m_wantWidth(false), - m_wantPrecision(false), - m_variableWidth(0), - m_variablePrecision(0), - m_origWidth(out.width()), - m_origPrecision(out.precision()), - m_origFlags(out.flags()), - m_origFill(out.fill()) + FormatArg() {} + + template + FormatArg(const T& value) + : m_value(static_cast(&value)), + m_formatImpl(&formatImpl), + m_toIntImpl(&toIntImpl) { } - // Print remaining part of format string. - void finish() + void format(std::ostream& out, const char* fmtBegin, + const char* fmtEnd, int ntrunc) const { - // It would be nice if we could do this from the destructor, but we - // can't if TINFORMAT_ERROR is used to throw an exception! - m_fmt = printFormatStringLiteral(m_out, m_fmt); - if(*m_fmt != '\0') - TINYFORMAT_ERROR("tinyformat: Too many conversion specifiers in format string"); + m_formatImpl(out, fmtBegin, fmtEnd, ntrunc, m_value); } - ~FormatIterator() + int toInt() const { - // Restore stream state - m_out.width(m_origWidth); - m_out.precision(m_origPrecision); - m_out.flags(m_origFlags); - m_out.fill(m_origFill); + return m_toIntImpl(m_value); } - template - void accept(const T& value); - private: - // Parse and return an integer from the string c, as atoi() - // On return, c is set to one past the end of the integer. - static int parseIntAndAdvance(const char*& c) + template + TINYFORMAT_HIDDEN static void formatImpl(std::ostream& out, const char* fmtBegin, + const char* fmtEnd, int ntrunc, const void* value) { - int i = 0; - for(;*c >= '0' && *c <= '9'; ++c) - i = 10*i + (*c - '0'); - return i; + formatValue(out, fmtBegin, fmtEnd, ntrunc, *static_cast(value)); } - // Format at most truncLen characters of a C string to the given - // stream. Return true if formatting proceeded (generic version always - // returns false) template - static bool formatCStringTruncate(std::ostream& /*out*/, const T& /*value*/, - std::streamsize /*truncLen*/) + TINYFORMAT_HIDDEN static int toIntImpl(const void* value) { - return false; - } -# define TINYFORMAT_DEFINE_FORMAT_C_STRING_TRUNCATE(type) \ - static bool formatCStringTruncate(std::ostream& out, type* value, \ - std::streamsize truncLen) \ - { \ - std::streamsize len = 0; \ - while(len < truncLen && value[len] != 0) \ - ++len; \ - out.write(value, len); \ - return true; \ - } - // Overload for const char* and char*. Could overload for signed & - // unsigned char too, but these are technically unneeded for printf - // compatibility. - TINYFORMAT_DEFINE_FORMAT_C_STRING_TRUNCATE(const char) - TINYFORMAT_DEFINE_FORMAT_C_STRING_TRUNCATE(char) -# undef TINYFORMAT_DEFINE_FORMAT_C_STRING_TRUNCATE - - // Print literal part of format string and return next format spec - // position. - // - // Skips over any occurrences of '%%', printing a literal '%' to the - // output. The position of the first % character of the next - // nontrivial format spec is returned, or the end of string. - static const char* printFormatStringLiteral(std::ostream& out, - const char* fmt) - { - const char* c = fmt; - for(; true; ++c) - { - switch(*c) - { - case '\0': - out.write(fmt, static_cast(c - fmt)); - return c; - case '%': - out.write(fmt, static_cast(c - fmt)); - if(*(c+1) != '%') - return c; - // for "%%", tack trailing % onto next literal section. - fmt = ++c; - break; - } - } + return convertToInt::invoke(*static_cast(value)); } - static const char* streamStateFromFormat(std::ostream& out, - unsigned int& extraFlags, - const char* fmtStart, - int variableWidth, - int variablePrecision); - - // Private copy & assign: Kill gcc warnings with -Weffc++ - FormatIterator(const FormatIterator&); - FormatIterator& operator=(const FormatIterator&); - - // Stream, current format string & state - std::ostream& m_out; - const char* m_fmt; - unsigned int m_extraFlags; - // State machine info for handling of variable width & precision - bool m_wantWidth; - bool m_wantPrecision; - int m_variableWidth; - int m_variablePrecision; - // Saved stream state - std::streamsize m_origWidth; - std::streamsize m_origPrecision; - std::ios::fmtflags m_origFlags; - char m_origFill; + const void* m_value; + void (*m_formatImpl)(std::ostream& out, const char* fmtBegin, + const char* fmtEnd, int ntrunc, const void* value); + int (*m_toIntImpl)(const void* value); }; -// Accept a value for formatting into the internal stream. -template -TINYFORMAT_NOINLINE // < greatly reduces bloat in optimized builds -void FormatIterator::accept(const T& value) +// Parse and return an integer from the string c, as atoi() +// On return, c is set to one past the end of the integer. +inline int parseIntAndAdvance(const char*& c) { - // Parse the format string - const char* fmtEnd = 0; - if(m_extraFlags == Flag_None && !m_wantWidth && !m_wantPrecision) - { - m_fmt = printFormatStringLiteral(m_out, m_fmt); - fmtEnd = streamStateFromFormat(m_out, m_extraFlags, m_fmt, 0, 0); - m_wantWidth = (m_extraFlags & Flag_VariableWidth) != 0; - m_wantPrecision = (m_extraFlags & Flag_VariablePrecision) != 0; - } - // Consume value as variable width and precision specifier if necessary - if(m_extraFlags & (Flag_VariableWidth | Flag_VariablePrecision)) - { - if(m_wantWidth || m_wantPrecision) - { - int v = convertToInt::invoke(value); - if(m_wantWidth) - { - m_variableWidth = v; - m_wantWidth = false; - } - else if(m_wantPrecision) - { - m_variablePrecision = v; - m_wantPrecision = false; - } - return; - } - // If we get here, we've set both the variable precision and width as - // required and we need to rerun the stream state setup to insert these. - fmtEnd = streamStateFromFormat(m_out, m_extraFlags, m_fmt, - m_variableWidth, m_variablePrecision); - } + int i = 0; + for(;*c >= '0' && *c <= '9'; ++c) + i = 10*i + (*c - '0'); + return i; +} - // Format the value into the stream. - if(!(m_extraFlags & (Flag_SpacePadPositive | Flag_TruncateToPrecision))) - formatValue(m_out, m_fmt, fmtEnd, value); - else +// Print literal part of format string and return next format spec +// position. +// +// Skips over any occurrences of '%%', printing a literal '%' to the +// output. The position of the first % character of the next +// nontrivial format spec is returned, or the end of string. +inline const char* printFormatStringLiteral(std::ostream& out, const char* fmt) +{ + const char* c = fmt; + for(;; ++c) { - // The following are special cases where there's no direct - // correspondence between stream formatting and the printf() behaviour. - // Instead, we simulate the behaviour crudely by formatting into a - // temporary string stream and munging the resulting string. - std::ostringstream tmpStream; - tmpStream.copyfmt(m_out); - if(m_extraFlags & Flag_SpacePadPositive) - tmpStream.setf(std::ios::showpos); - // formatCStringTruncate is required for truncating conversions like - // "%.4s" where at most 4 characters of the c-string should be read. - // If we didn't include this special case, we might read off the end. - if(!( (m_extraFlags & Flag_TruncateToPrecision) && - formatCStringTruncate(tmpStream, value, m_out.precision()) )) - { - // Not a truncated c-string; just format normally. - formatValue(tmpStream, m_fmt, fmtEnd, value); - } - std::string result = tmpStream.str(); // allocates... yuck. - if(m_extraFlags & Flag_SpacePadPositive) + switch(*c) { - for(size_t i = 0, iend = result.size(); i < iend; ++i) - if(result[i] == '+') - result[i] = ' '; + case '\0': + out.write(fmt, c - fmt); + return c; + case '%': + out.write(fmt, c - fmt); + if(*(c+1) != '%') + return c; + // for "%%", tack trailing % onto next literal section. + fmt = ++c; + break; + default: + break; } - if((m_extraFlags & Flag_TruncateToPrecision) && - (int)result.size() > (int)m_out.precision()) - m_out.write(result.c_str(), m_out.precision()); - else - m_out << result; } - m_extraFlags = Flag_None; - m_fmt = fmtEnd; } @@ -663,13 +575,14 @@ void FormatIterator::accept(const T& value) // with the form "%[flags][width][.precision][length]type". // // Formatting options which can't be natively represented using the ostream -// state are returned in the extraFlags parameter which is a bitwise -// combination of values from the ExtraFormatFlags enum. -inline const char* FormatIterator::streamStateFromFormat(std::ostream& out, - unsigned int& extraFlags, - const char* fmtStart, - int variableWidth, - int variablePrecision) +// state are returned in spacePadPositive (for space padded positive numbers) +// and ntrunc (for truncating conversions). argIndex is incremented if +// necessary to pull out variable width and precision . The function returns a +// pointer to the character after the end of the current format spec. +inline const char* streamStateFromFormat(std::ostream& out, bool& spacePadPositive, + int& ntrunc, const char* fmtStart, + const detail::FormatArg* formatters, + int& argIndex, int numFormatters) { if(*fmtStart != '%') { @@ -684,9 +597,9 @@ inline const char* FormatIterator::streamStateFromFormat(std::ostream& out, out.unsetf(std::ios::adjustfield | std::ios::basefield | std::ios::floatfield | std::ios::showbase | std::ios::boolalpha | std::ios::showpoint | std::ios::showpos | std::ios::uppercase); - extraFlags = Flag_None; bool precisionSet = false; bool widthSet = false; + int widthExtra = 0; const char* c = fmtStart + 1; // 1) Parse flags for(;; ++c) @@ -713,12 +626,15 @@ inline const char* FormatIterator::streamStateFromFormat(std::ostream& out, case ' ': // overridden by show positive sign, '+' flag. if(!(out.flags() & std::ios::showpos)) - extraFlags |= Flag_SpacePadPositive; + spacePadPositive = true; continue; case '+': out.setf(std::ios::showpos); - extraFlags &= ~Flag_SpacePadPositive; + spacePadPositive = false; + widthExtra = 1; continue; + default: + break; } break; } @@ -731,15 +647,19 @@ inline const char* FormatIterator::streamStateFromFormat(std::ostream& out, if(*c == '*') { widthSet = true; - if(variableWidth < 0) + int width = 0; + if(argIndex < numFormatters) + width = formatters[argIndex++].toInt(); + else + TINYFORMAT_ERROR("tinyformat: Not enough arguments to read variable width"); + if(width < 0) { // negative widths correspond to '-' flag set out.fill(' '); out.setf(std::ios::left, std::ios::adjustfield); - variableWidth = -variableWidth; + width = -width; } - out.width(variableWidth); - extraFlags |= Flag_VariableWidth; + out.width(width); ++c; } // 3) Parse precision @@ -750,8 +670,10 @@ inline const char* FormatIterator::streamStateFromFormat(std::ostream& out, if(*c == '*') { ++c; - extraFlags |= Flag_VariablePrecision; - precision = variablePrecision; + if(argIndex < numFormatters) + precision = formatters[argIndex++].toInt(); + else + TINYFORMAT_ERROR("tinyformat: Not enough arguments to read variable precision"); } else { @@ -814,7 +736,7 @@ inline const char* FormatIterator::streamStateFromFormat(std::ostream& out, break; case 's': if(precisionSet) - extraFlags |= Flag_TruncateToPrecision; + ntrunc = static_cast(out.precision()); // Make %s print booleans as "true" and "false" out.setf(std::ios::boolalpha); break; @@ -826,6 +748,8 @@ inline const char* FormatIterator::streamStateFromFormat(std::ostream& out, TINYFORMAT_ERROR("tinyformat: Conversion spec incorrectly " "terminated by end of string"); return c; + default: + break; } if(intConversion && precisionSet && !widthSet) { @@ -833,7 +757,7 @@ inline const char* FormatIterator::streamStateFromFormat(std::ostream& out, // padded with zeros on the left). This isn't really supported by the // iostreams, but we can approximately simulate it with the width if // the width isn't otherwise used. - out.width(out.precision()); + out.width(out.precision() + widthExtra); out.setf(std::ios::internal, std::ios::adjustfield); out.fill('0'); } @@ -841,170 +765,282 @@ inline const char* FormatIterator::streamStateFromFormat(std::ostream& out, } - //------------------------------------------------------------------------------ -// Private format function on top of which the public interface is implemented. -// We enforce a mimimum of one value to be formatted to prevent bugs looking like -// -// const char* myStr = "100% broken"; -// printf(myStr); // Parses % as a format specifier -#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES - -template -void format(FormatIterator& fmtIter, const T1& value1) +inline void formatImpl(std::ostream& out, const char* fmt, + const detail::FormatArg* formatters, + int numFormatters) { - fmtIter.accept(value1); - fmtIter.finish(); + // Saved stream state + std::streamsize origWidth = out.width(); + std::streamsize origPrecision = out.precision(); + std::ios::fmtflags origFlags = out.flags(); + char origFill = out.fill(); + + for (int argIndex = 0; argIndex < numFormatters; ++argIndex) + { + // Parse the format string + fmt = printFormatStringLiteral(out, fmt); + bool spacePadPositive = false; + int ntrunc = -1; + const char* fmtEnd = streamStateFromFormat(out, spacePadPositive, ntrunc, fmt, + formatters, argIndex, numFormatters); + if (argIndex >= numFormatters) + { + // Check args remain after reading any variable width/precision + TINYFORMAT_ERROR("tinyformat: Not enough format arguments"); + return; + } + const FormatArg& arg = formatters[argIndex]; + // Format the arg into the stream. + if(!spacePadPositive) + arg.format(out, fmt, fmtEnd, ntrunc); + else + { + // The following is a special case with no direct correspondence + // between stream formatting and the printf() behaviour. Simulate + // it crudely by formatting into a temporary string stream and + // munging the resulting string. + std::ostringstream tmpStream; + tmpStream.copyfmt(out); + tmpStream.setf(std::ios::showpos); + arg.format(tmpStream, fmt, fmtEnd, ntrunc); + std::string result = tmpStream.str(); // allocates... yuck. + for(size_t i = 0, iend = result.size(); i < iend; ++i) + if(result[i] == '+') result[i] = ' '; + out << result; + } + fmt = fmtEnd; + } + + // Print remaining part of format string. + fmt = printFormatStringLiteral(out, fmt); + if(*fmt != '\0') + TINYFORMAT_ERROR("tinyformat: Too many conversion specifiers in format string"); + + // Restore stream state + out.width(origWidth); + out.precision(origPrecision); + out.flags(origFlags); + out.fill(origFill); } -// General version for C++11 -template -void format(FormatIterator& fmtIter, const T1& value1, const Args&... args) +} // namespace detail + + +/// List of template arguments format(), held in a type-opaque way. +/// +/// A const reference to FormatList (typedef'd as FormatListRef) may be +/// conveniently used to pass arguments to non-template functions: All type +/// information has been stripped from the arguments, leaving just enough of a +/// common interface to perform formatting as required. +class FormatList { - fmtIter.accept(value1); - format(fmtIter, args...); -} + public: + FormatList(detail::FormatArg* formatters, int N) + : m_formatters(formatters), m_N(N) { } -#else + friend void vformat(std::ostream& out, const char* fmt, + const FormatList& list); -inline void format(FormatIterator& fmtIter) + private: + const detail::FormatArg* m_formatters; + int m_N; +}; + +/// Reference to type-opaque format list for passing to vformat() +typedef const FormatList& FormatListRef; + + +namespace detail { + +// Format list subclass with fixed storage to avoid dynamic allocation +template +class FormatListN : public FormatList { - fmtIter.finish(); -} + public: +#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES + template + FormatListN(const Args&... args) + : FormatList(&m_formatterStore[0], N), + m_formatterStore { FormatArg(args)... } + { static_assert(sizeof...(args) == N, "Number of args must be N"); } +#else // C++98 version + void init(int) {} +# define TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR(n) \ + \ + template \ + FormatListN(TINYFORMAT_VARARGS(n)) \ + : FormatList(&m_formatterStore[0], n) \ + { assert(n == N); init(0, TINYFORMAT_PASSARGS(n)); } \ + \ + template \ + void init(int i, TINYFORMAT_VARARGS(n)) \ + { \ + m_formatterStore[i] = FormatArg(v1); \ + init(i+1 TINYFORMAT_PASSARGS_TAIL(n)); \ + } -// General version for C++98 -#define TINYFORMAT_MAKE_FORMAT_DETAIL(n) \ -template \ -void format(detail::FormatIterator& fmtIter, TINYFORMAT_VARARGS(n)) \ -{ \ - fmtIter.accept(v1); \ - format(fmtIter TINYFORMAT_PASSARGS_TAIL(n)); \ -} + TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR) +# undef TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR +#endif -TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_FORMAT_DETAIL) -#undef TINYFORMAT_MAKE_FORMAT_DETAIL + private: + FormatArg m_formatterStore[N]; +}; -#endif // End C++98 variadic template emulation for format() +// Special 0-arg version - MSVC says zero-sized C array in struct is nonstandard +template<> class FormatListN<0> : public FormatList +{ + public: FormatListN() : FormatList(0, 0) {} +}; } // namespace detail //------------------------------------------------------------------------------ -// Implement all the main interface functions here in terms of detail::format() +// Primary API functions #ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES -// C++11 - the simple case -template -void format(std::ostream& out, const char* fmt, const T1& v1, const Args&... args) +/// Make type-agnostic format list from list of template arguments. +/// +/// The exact return type of this function is an implementation detail and +/// shouldn't be relied upon. Instead it should be stored as a FormatListRef: +/// +/// FormatListRef formatList = makeFormatList( /*...*/ ); +template +detail::FormatListN makeFormatList(const Args&... args) { - detail::FormatIterator fmtIter(out, fmt); - format(fmtIter, v1, args...); + return detail::FormatListN(args...); } -template -std::string format(const char* fmt, const T1& v1, const Args&... args) +#else // C++98 version + +inline detail::FormatListN<0> makeFormatList() +{ + return detail::FormatListN<0>(); +} +#define TINYFORMAT_MAKE_MAKEFORMATLIST(n) \ +template \ +detail::FormatListN makeFormatList(TINYFORMAT_VARARGS(n)) \ +{ \ + return detail::FormatListN(TINYFORMAT_PASSARGS(n)); \ +} +TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_MAKEFORMATLIST) +#undef TINYFORMAT_MAKE_MAKEFORMATLIST + +#endif + +/// Format list of arguments to the stream according to the given format string. +/// +/// The name vformat() is chosen for the semantic similarity to vprintf(): the +/// list of format arguments is held in a single function argument. +inline void vformat(std::ostream& out, const char* fmt, FormatListRef list) +{ + detail::formatImpl(out, fmt, list.m_formatters, list.m_N); +} + + +#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES + +/// Format list of arguments to the stream according to given format string. +template +void format(std::ostream& out, const char* fmt, const Args&... args) +{ + vformat(out, fmt, makeFormatList(args...)); +} + +/// Format list of arguments according to the given format string and return +/// the result as a string. +template +std::string format(const char* fmt, const Args&... args) { std::ostringstream oss; - format(oss, fmt, v1, args...); + format(oss, fmt, args...); return oss.str(); } -template -std::string format(const std::string &fmt, const T1& v1, const Args&... args) +/// Format list of arguments to std::cout, according to the given format string +template +void printf(const char* fmt, const Args&... args) +{ + format(std::cout, fmt, args...); +} + +template +void printfln(const char* fmt, const Args&... args) +{ + format(std::cout, fmt, args...); + std::cout << '\n'; +} + +#else // C++98 version + +inline void format(std::ostream& out, const char* fmt) +{ + vformat(out, fmt, makeFormatList()); +} + +inline std::string format(const char* fmt) { std::ostringstream oss; - format(oss, fmt.c_str(), v1, args...); + format(oss, fmt); return oss.str(); } -template -void printf(const char* fmt, const T1& v1, const Args&... args) +inline void printf(const char* fmt) { - format(std::cout, fmt, v1, args...); + format(std::cout, fmt); } -#else +inline void printfln(const char* fmt) +{ + format(std::cout, fmt); + std::cout << '\n'; +} -// C++98 - define the interface functions using the wrapping macros #define TINYFORMAT_MAKE_FORMAT_FUNCS(n) \ \ template \ void format(std::ostream& out, const char* fmt, TINYFORMAT_VARARGS(n)) \ { \ - tinyformat::detail::FormatIterator fmtIter(out, fmt); \ - tinyformat::detail::format(fmtIter, TINYFORMAT_PASSARGS(n)); \ + vformat(out, fmt, makeFormatList(TINYFORMAT_PASSARGS(n))); \ } \ \ template \ std::string format(const char* fmt, TINYFORMAT_VARARGS(n)) \ { \ std::ostringstream oss; \ - tinyformat::format(oss, fmt, TINYFORMAT_PASSARGS(n)); \ + format(oss, fmt, TINYFORMAT_PASSARGS(n)); \ return oss.str(); \ } \ \ template \ -std::string format(const std::string &fmt, TINYFORMAT_VARARGS(n)) \ +void printf(const char* fmt, TINYFORMAT_VARARGS(n)) \ { \ - std::ostringstream oss; \ - tinyformat::format(oss, fmt.c_str(), TINYFORMAT_PASSARGS(n)); \ - return oss.str(); \ + format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \ } \ \ template \ -void printf(const char* fmt, TINYFORMAT_VARARGS(n)) \ +void printfln(const char* fmt, TINYFORMAT_VARARGS(n)) \ { \ - tinyformat::format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \ + format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \ + std::cout << '\n'; \ } TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_FORMAT_FUNCS) #undef TINYFORMAT_MAKE_FORMAT_FUNCS -#endif - -//------------------------------------------------------------------------------ -// Define deprecated wrapping macro for backward compatibility in tinyformat -// 1.x. Will be removed in version 2! -#define TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS -#define TINYFORMAT_WRAP_FORMAT_N(n, returnType, funcName, funcDeclSuffix, \ - bodyPrefix, streamName, bodySuffix) \ -template \ -returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt, \ - TINYFORMAT_VARARGS(n)) funcDeclSuffix \ -{ \ - bodyPrefix \ - tinyformat::format(streamName, fmt, TINYFORMAT_PASSARGS(n)); \ - bodySuffix \ -} \ - -#define TINYFORMAT_WRAP_FORMAT(returnType, funcName, funcDeclSuffix, \ - bodyPrefix, streamName, bodySuffix) \ -inline \ -returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt \ - ) funcDeclSuffix \ -{ \ - bodyPrefix \ - tinyformat::detail::FormatIterator(streamName, fmt).finish(); \ - bodySuffix \ -} \ -TINYFORMAT_WRAP_FORMAT_N(1 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ -TINYFORMAT_WRAP_FORMAT_N(2 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ -TINYFORMAT_WRAP_FORMAT_N(3 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ -TINYFORMAT_WRAP_FORMAT_N(4 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ -TINYFORMAT_WRAP_FORMAT_N(5 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ -TINYFORMAT_WRAP_FORMAT_N(6 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ -TINYFORMAT_WRAP_FORMAT_N(7 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ -TINYFORMAT_WRAP_FORMAT_N(8 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ -TINYFORMAT_WRAP_FORMAT_N(9 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ -TINYFORMAT_WRAP_FORMAT_N(10, returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ -TINYFORMAT_WRAP_FORMAT_N(11, returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ -TINYFORMAT_WRAP_FORMAT_N(12, returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ -TINYFORMAT_WRAP_FORMAT_N(13, returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ -TINYFORMAT_WRAP_FORMAT_N(14, returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ -TINYFORMAT_WRAP_FORMAT_N(15, returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ -TINYFORMAT_WRAP_FORMAT_N(16, returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \ +#endif +// Added for Bitcoin Core +template +std::string format(const std::string &fmt, const Args&... args) +{ + std::ostringstream oss; + format(oss, fmt.c_str(), args...); + return oss.str(); +} } // namespace tinyformat From a5072a773071b8f4b644f84a77643e2ad18dba3a Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 27 Jun 2016 18:39:25 +0200 Subject: [PATCH 0577/1802] util: Remove zero-argument versions of LogPrint and error Changes in tinyformat, recently imported from upstream have made the zero-argument versions of formatting functions unnecessary. Remove them. This is a slight semantic change: `%` characters in the zero-argument call are now regarded and need to be escaped. As for as I know, the only use of this is in `main.cpp`. --- src/main.cpp | 2 +- src/util.h | 28 ++++++---------------------- 2 files changed, 7 insertions(+), 23 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 6cdd55e3979df..bb65fc0de3eb8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4159,7 +4159,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, int nGoodTransactions = 0; CValidationState state; int reportDone = 0; - LogPrintf("[0%]..."); + LogPrintf("[0%%]..."); for (CBlockIndex* pindex = chainActive.Tip(); pindex && pindex->pprev; pindex = pindex->pprev) { boost::this_thread::interruption_point(); diff --git a/src/util.h b/src/util.h index ac4b947785f43..39328b51ef154 100644 --- a/src/util.h +++ b/src/util.h @@ -77,33 +77,17 @@ int LogPrintStr(const std::string &str); #define LogPrintf(...) LogPrint(NULL, __VA_ARGS__) -template -static inline int LogPrint(const char* category, const char* fmt, const T1& v1, const Args&... args) +template +static inline int LogPrint(const char* category, const char* fmt, const Args&... args) { if(!LogAcceptCategory(category)) return 0; \ - return LogPrintStr(tfm::format(fmt, v1, args...)); + return LogPrintStr(tfm::format(fmt, args...)); } -template -bool error(const char* fmt, const T1& v1, const Args&... args) +template +bool error(const char* fmt, const Args&... args) { - LogPrintStr("ERROR: " + tfm::format(fmt, v1, args...) + "\n"); - return false; -} - -/** - * Zero-arg versions of logging and error, these are not covered by - * the variadic templates above (and don't take format arguments but - * bare strings). - */ -static inline int LogPrint(const char* category, const char* s) -{ - if(!LogAcceptCategory(category)) return 0; - return LogPrintStr(s); -} -static inline bool error(const char* s) -{ - LogPrintStr(std::string("ERROR: ") + s + "\n"); + LogPrintStr("ERROR: " + tfm::format(fmt, args...) + "\n"); return false; } From 2129fcea69ee0cf71c5e082607d101c3680af84c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Sat, 25 Jun 2016 08:19:36 +0200 Subject: [PATCH 0578/1802] The bit field is shown only when status is "started" --- src/rpc/blockchain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 9d1d12a47edbb..20eefa1c574c5 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -909,7 +909,7 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) " \"bip9_softforks\": { (object) status of BIP9 softforks in progress\n" " \"xxxx\" : { (string) name of the softfork\n" " \"status\": \"xxxx\", (string) one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\"\n" - " \"bit\": xx, (numeric) the bit, 0-28, in the block version field used to signal this soft fork\n" + " \"bit\": xx, (numeric) the bit (0-28) in the block version field used to signal this softfork (only for \"started\" status)\n" " \"startTime\": xx, (numeric) the minimum median time past of a block at which the bit gains its meaning\n" " \"timeout\": xx (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in\n" " }\n" From 9a227e95bb1dee07d20d1042f48f12db8cc048a6 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 27 Jun 2016 12:49:40 +0000 Subject: [PATCH 0579/1802] tx: change slug to `bitcoin.qt-translation-013x` Fetch the 0.13 translations, not the 0.12 translations. --- .tx/config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.tx/config b/.tx/config index d6cc3aab8879c..3ce2ae71d0adb 100644 --- a/.tx/config +++ b/.tx/config @@ -1,7 +1,7 @@ [main] host = https://www.transifex.com -[bitcoin.qt-translation-012x] +[bitcoin.qt-translation-013x] file_filter = src/qt/locale/bitcoin_.ts source_file = src/qt/locale/bitcoin_en.ts source_lang = en From 3b2dadc8d5bbe1f2485fd9e9cef0df31dffa2f57 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 28 Jun 2016 09:47:37 +0000 Subject: [PATCH 0580/1802] qt: Periodic translations update --- src/Makefile.qt.include | 6 +- src/qt/bitcoin_locale.qrc | 6 +- src/qt/bitcoinstrings.cpp | 5 + src/qt/locale/bitcoin_af.ts | 251 +--- src/qt/locale/bitcoin_af_ZA.ts | 403 +----- src/qt/locale/bitcoin_ar.ts | 945 +------------ src/qt/locale/bitcoin_be_BY.ts | 725 +--------- src/qt/locale/bitcoin_bg.ts | 1153 +--------------- src/qt/locale/bitcoin_bg_BG.ts | 157 --- src/qt/locale/bitcoin_bs.ts | 169 --- src/qt/locale/bitcoin_ca.ts | 1535 ++------------------- src/qt/locale/bitcoin_ca@valencia.ts | 1755 +++--------------------- src/qt/locale/bitcoin_ca_ES.ts | 1531 ++------------------- src/qt/locale/bitcoin_cs.ts | 1759 +++--------------------- src/qt/locale/bitcoin_cs_CZ.ts | 371 +---- src/qt/locale/bitcoin_cy.ts | 333 +---- src/qt/locale/bitcoin_da.ts | 1805 +++++-------------------- src/qt/locale/bitcoin_de.ts | 1801 ++++--------------------- src/qt/locale/bitcoin_el.ts | 149 +- src/qt/locale/bitcoin_el_GR.ts | 1204 +---------------- src/qt/locale/bitcoin_en.ts | 69 +- src/qt/locale/bitcoin_en_GB.ts | 1811 +++++-------------------- src/qt/locale/bitcoin_eo.ts | 1107 +-------------- src/qt/locale/bitcoin_es.ts | 1802 +++++-------------------- src/qt/locale/bitcoin_es_419.ts | 173 --- src/qt/locale/bitcoin_es_AR.ts | 239 +--- src/qt/locale/bitcoin_es_CL.ts | 768 +---------- src/qt/locale/bitcoin_es_CO.ts | 264 +--- src/qt/locale/bitcoin_es_DO.ts | 1124 +-------------- src/qt/locale/bitcoin_es_ES.ts | 251 +--- src/qt/locale/bitcoin_es_MX.ts | 695 +--------- src/qt/locale/bitcoin_es_UY.ts | 274 +--- src/qt/locale/bitcoin_es_VE.ts | 583 +------- src/qt/locale/bitcoin_et.ts | 837 +----------- src/qt/locale/bitcoin_eu_ES.ts | 479 +------ src/qt/locale/bitcoin_fa.ts | 1121 +++------------ src/qt/locale/bitcoin_fa_IR.ts | 579 +------- src/qt/locale/bitcoin_fi.ts | 1523 ++------------------- src/qt/locale/bitcoin_fil.ts | 157 --- src/qt/locale/bitcoin_fr.ts | 1875 +++++--------------------- src/qt/locale/bitcoin_fr_CA.ts | 121 +- src/qt/locale/bitcoin_fr_FR.ts | 1084 +-------------- src/qt/locale/bitcoin_gl.ts | 1049 +------------- src/qt/locale/bitcoin_he.ts | 1535 ++++----------------- src/qt/locale/bitcoin_hi_IN.ts | 461 +------ src/qt/locale/bitcoin_hr.ts | 835 +----------- src/qt/locale/bitcoin_hu.ts | 1085 +-------------- src/qt/locale/bitcoin_id_ID.ts | 1203 +---------------- src/qt/locale/bitcoin_it.ts | 1765 +++--------------------- src/qt/locale/bitcoin_it_IT.ts | 187 +-- src/qt/locale/bitcoin_ja.ts | 1809 +++++-------------------- src/qt/locale/bitcoin_ka.ts | 1163 +--------------- src/qt/locale/bitcoin_kk_KZ.ts | 159 +-- src/qt/locale/bitcoin_ko_KR.ts | 1765 +++--------------------- src/qt/locale/bitcoin_ku_IQ.ts | 272 ++++ src/qt/locale/bitcoin_ky.ts | 101 +- src/qt/locale/bitcoin_la.ts | 749 +--------- src/qt/locale/bitcoin_lt.ts | 887 +----------- src/qt/locale/bitcoin_lv_LV.ts | 1123 +-------------- src/qt/locale/bitcoin_mk_MK.ts | 471 +------ src/qt/locale/bitcoin_mn.ts | 561 +------- src/qt/locale/bitcoin_ms_MY.ts | 77 +- src/qt/locale/bitcoin_nb.ts | 1763 +++--------------------- src/qt/locale/bitcoin_nl.ts | 1817 +++++-------------------- src/qt/locale/bitcoin_pam.ts | 705 +--------- src/qt/locale/bitcoin_pl.ts | 1827 +++++-------------------- src/qt/locale/bitcoin_pt_BR.ts | 1783 ++++-------------------- src/qt/locale/bitcoin_pt_PT.ts | 1783 ++++-------------------- src/qt/locale/bitcoin_ro.ts | 81 +- src/qt/locale/bitcoin_ro_RO.ts | 1483 ++------------------ src/qt/locale/bitcoin_ru.ts | 1773 +++--------------------- src/qt/locale/bitcoin_ru_RU.ts | 113 +- src/qt/locale/bitcoin_sk.ts | 1535 ++------------------- src/qt/locale/bitcoin_sl_SI.ts | 1475 ++------------------ src/qt/locale/bitcoin_sq.ts | 407 +----- src/qt/locale/bitcoin_sr.ts | 447 +----- src/qt/locale/bitcoin_sr@latin.ts | 459 +------ src/qt/locale/bitcoin_sv.ts | 1812 +++++-------------------- src/qt/locale/bitcoin_ta.ts | 351 +---- src/qt/locale/bitcoin_th_TH.ts | 821 +++++++---- src/qt/locale/bitcoin_tr.ts | 1809 +++++-------------------- src/qt/locale/bitcoin_tr_TR.ts | 155 +-- src/qt/locale/bitcoin_uk.ts | 1767 +++--------------------- src/qt/locale/bitcoin_ur_PK.ts | 209 +-- src/qt/locale/bitcoin_uz@Cyrl.ts | 965 +------------ src/qt/locale/bitcoin_uz@Latn.ts | 169 --- src/qt/locale/bitcoin_vi.ts | 107 +- src/qt/locale/bitcoin_vi_VN.ts | 293 +--- src/qt/locale/bitcoin_zh.ts | 77 -- src/qt/locale/bitcoin_zh_CN.ts | 1756 +++--------------------- src/qt/locale/bitcoin_zh_HK.ts | 253 ---- src/qt/locale/bitcoin_zh_TW.ts | 1793 +++++------------------- 92 files changed, 7965 insertions(+), 72079 deletions(-) delete mode 100644 src/qt/locale/bitcoin_bg_BG.ts delete mode 100644 src/qt/locale/bitcoin_bs.ts delete mode 100644 src/qt/locale/bitcoin_es_419.ts delete mode 100644 src/qt/locale/bitcoin_fil.ts create mode 100644 src/qt/locale/bitcoin_ku_IQ.ts delete mode 100644 src/qt/locale/bitcoin_uz@Latn.ts diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index dc775a3568d78..36a21dd06fec1 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -7,9 +7,7 @@ QT_TS = \ qt/locale/bitcoin_af_ZA.ts \ qt/locale/bitcoin_ar.ts \ qt/locale/bitcoin_be_BY.ts \ - qt/locale/bitcoin_bg_BG.ts \ qt/locale/bitcoin_bg.ts \ - qt/locale/bitcoin_bs.ts \ qt/locale/bitcoin_ca_ES.ts \ qt/locale/bitcoin_ca.ts \ qt/locale/bitcoin_ca@valencia.ts \ @@ -23,7 +21,6 @@ QT_TS = \ qt/locale/bitcoin_en_GB.ts \ qt/locale/bitcoin_en.ts \ qt/locale/bitcoin_eo.ts \ - qt/locale/bitcoin_es_419.ts \ qt/locale/bitcoin_es_AR.ts \ qt/locale/bitcoin_es_CL.ts \ qt/locale/bitcoin_es_CO.ts \ @@ -37,7 +34,6 @@ QT_TS = \ qt/locale/bitcoin_eu_ES.ts \ qt/locale/bitcoin_fa_IR.ts \ qt/locale/bitcoin_fa.ts \ - qt/locale/bitcoin_fil.ts \ qt/locale/bitcoin_fi.ts \ qt/locale/bitcoin_fr_CA.ts \ qt/locale/bitcoin_fr_FR.ts \ @@ -54,6 +50,7 @@ QT_TS = \ qt/locale/bitcoin_ka.ts \ qt/locale/bitcoin_kk_KZ.ts \ qt/locale/bitcoin_ko_KR.ts \ + qt/locale/bitcoin_ku_IQ.ts \ qt/locale/bitcoin_ky.ts \ qt/locale/bitcoin_la.ts \ qt/locale/bitcoin_lt.ts \ @@ -84,7 +81,6 @@ QT_TS = \ qt/locale/bitcoin_uk.ts \ qt/locale/bitcoin_ur_PK.ts \ qt/locale/bitcoin_uz@Cyrl.ts \ - qt/locale/bitcoin_uz@Latn.ts \ qt/locale/bitcoin_vi.ts \ qt/locale/bitcoin_vi_VN.ts \ qt/locale/bitcoin_zh_CN.ts \ diff --git a/src/qt/bitcoin_locale.qrc b/src/qt/bitcoin_locale.qrc index 1acda7f28caaf..54d36ac0118fa 100644 --- a/src/qt/bitcoin_locale.qrc +++ b/src/qt/bitcoin_locale.qrc @@ -4,9 +4,7 @@ locale/bitcoin_af_ZA.qm locale/bitcoin_ar.qm locale/bitcoin_be_BY.qm - locale/bitcoin_bg_BG.qm locale/bitcoin_bg.qm - locale/bitcoin_bs.qm locale/bitcoin_ca_ES.qm locale/bitcoin_ca.qm locale/bitcoin_ca@valencia.qm @@ -20,7 +18,6 @@ locale/bitcoin_en_GB.qm locale/bitcoin_en.qm locale/bitcoin_eo.qm - locale/bitcoin_es_419.qm locale/bitcoin_es_AR.qm locale/bitcoin_es_CL.qm locale/bitcoin_es_CO.qm @@ -34,7 +31,6 @@ locale/bitcoin_eu_ES.qm locale/bitcoin_fa_IR.qm locale/bitcoin_fa.qm - locale/bitcoin_fil.qm locale/bitcoin_fi.qm locale/bitcoin_fr_CA.qm locale/bitcoin_fr_FR.qm @@ -51,6 +47,7 @@ locale/bitcoin_ka.qm locale/bitcoin_kk_KZ.qm locale/bitcoin_ko_KR.qm + locale/bitcoin_ku_IQ.qm locale/bitcoin_ky.qm locale/bitcoin_la.qm locale/bitcoin_lt.qm @@ -81,7 +78,6 @@ locale/bitcoin_uk.qm locale/bitcoin_ur_PK.qm locale/bitcoin_uz@Cyrl.qm - locale/bitcoin_uz@Latn.qm locale/bitcoin_vi.qm locale/bitcoin_vi_VN.qm locale/bitcoin_zh_CN.qm diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp index 83901732acf17..7cf32cd34e8f7 100644 --- a/src/qt/bitcoinstrings.cpp +++ b/src/qt/bitcoinstrings.cpp @@ -165,6 +165,9 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" "Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = " "no limit (default: %d)"), QT_TRANSLATE_NOOP("bitcoin-core", "" +"Unable to rewind the database to a pre-fork state. You will need to " +"redownload the blockchain"), +QT_TRANSLATE_NOOP("bitcoin-core", "" "Unsupported argument -socks found. Setting SOCKS version isn't possible " "anymore, only SOCKS5 proxies are supported."), QT_TRANSLATE_NOOP("bitcoin-core", "" @@ -308,11 +311,13 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Relay and mine data carrier transactions (def QT_TRANSLATE_NOOP("bitcoin-core", "Relay non-P2SH multisig (default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "Rescan the block chain for missing wallet transactions on startup"), QT_TRANSLATE_NOOP("bitcoin-core", "Rescanning..."), +QT_TRANSLATE_NOOP("bitcoin-core", "Rewinding blocks..."), QT_TRANSLATE_NOOP("bitcoin-core", "Run in the background as a daemon and accept commands"), QT_TRANSLATE_NOOP("bitcoin-core", "Send trace/debug info to console instead of debug.log file"), QT_TRANSLATE_NOOP("bitcoin-core", "Send transactions as zero-fee transactions if possible (default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "Set database cache size in megabytes (%d to %d, default: %d)"), QT_TRANSLATE_NOOP("bitcoin-core", "Set key pool size to (default: %u)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Set maximum block cost (default: %d)"), QT_TRANSLATE_NOOP("bitcoin-core", "Set maximum block size in bytes (default: %d)"), QT_TRANSLATE_NOOP("bitcoin-core", "Set minimum block size in bytes (default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "Set the number of threads to service RPC calls (default: %d)"), diff --git a/src/qt/locale/bitcoin_af.ts b/src/qt/locale/bitcoin_af.ts index 492c7bccd4e1b..7c2d294c7e8ff 100644 --- a/src/qt/locale/bitcoin_af.ts +++ b/src/qt/locale/bitcoin_af.ts @@ -21,10 +21,6 @@ &Copy &Dupliseer - - &Copy Address - &Dupliseer Adres - Delete the currently selected address from the list Verwyder die adres wat u gekies het van die lys @@ -41,61 +37,6 @@ &Delete &Vee uit - - Choose the address to send coins to - Kies die adres waarheen u munte wil stuur - - - Choose the address to receive coins with - Kies die adres wat die munte moet ontvang - - - Sending addresses - Stuurders adresse - - - Receiving addresses - Ontvanger adresse - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Hierdie is die adresse vanwaar u Bitcoin betalings stuur. U moet altyd die bedrag en die adres van die ontvanger nagaan voordat u enige munte stuur. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Hierdie is die adresse waar u Bitcoins sal ontvang. Ons beveel aan dat u 'n nuwe adres kies vir elke transaksie - - - &Edit - &Verander - - - Export Address List - Voer adreslys uit - - - Comma separated file (*.csv) - Comma separated file (*.csv) - - - Exporting Failed - Uitvoer was onsuksesvol - - - There was an error trying to save the address list to %1. Please try again. - Die adreslys kon nie in %1 gestoor word nie. Probeer asseblief weer. - - - - AddressTableModel - - Address - Adres - - - (no label) - (geen etiket) - AskPassphraseDialog @@ -115,87 +56,7 @@ Repeat new passphrase Herhaal nuwe wagwoord - - Encrypt wallet - Kodifiseer beursie - - - This operation needs your wallet passphrase to unlock the wallet. - U het u beursie se wagwoord nodig om toegang tot u beursie te verkry. - - - Unlock wallet - Sluit beursie oop - - - This operation needs your wallet passphrase to decrypt the wallet. - U het u beursie se wagwoord nodig om u beursie se kode te ontsyfer. - - - Decrypt wallet - Ontsleutel beursie - - - Change passphrase - Verander wagwoord - - - Confirm wallet encryption - Bevestig dat die beursie gekodifiseer is - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Waarskuwing: Indien u die beursie kodifiseer en u vergeet u wagwoord <b>VERLOOR U AL U BITCOINS</b>! - - - Are you sure you wish to encrypt your wallet? - Is u seker dat u die beursie wil kodifiseer? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Bitcoin Kern gaan nou toemaak om die kodifikasie af te handel. Onthou dat die kodifikasie van u beursie nie altyd u munte kan beskerm teen diefstal deur kwaadwillige sagteware op u rekenaar nie. - - - 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. - BELANGRIK: Alle vorige kopieë en rugsteun-weergawes wat u tevore van die gemaak het, moet vervang word met die jongste weergawe van u nuutste gekodifiseerde beursie. Alle vorige weergawes en rugsteun-kopieë van u beursie sal nutteloos raak die oomblik wat u die nuut-gekodifiseerde beursie begin gebruik. - - - Warning: The Caps Lock key is on! - WAARSKUWING: Outomatiese Kapitalisering is aktief op u sleutelbord! - - - Wallet encrypted - Beursie gekodifiseer - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Tik die nuwe wagwoord vir u beursie.<br/>Gerbuik asseblief 'n wagwoord met <b>tien of meer lukrake karakters</b>, of <b>agt of meer woorde</b>. - - - Enter the old passphrase and new passphrase to the wallet. - Tik die ou en die nuwe wagwoorde vir die beursie. - - - Wallet encryption failed - Kodifikasie was onsuksesvol - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Weens 'n interne fout het kodifikasie het nie geslaag nie. U beursie is nie gekodifiseer nie - - - The supplied passphrases do not match. - Die wagwoorde stem nie ooreen nie. - - - Wallet unlock failed - Die beursie is nie oopgesluit nie - - - The passphrase entered for the wallet decryption was incorrect. - U het die verkeerde wagwoord ingetik. - - + BanTableModel @@ -257,14 +118,6 @@ Open &URI... Oop & URI... - - Bitcoin Core client - Bitcoin Kern klient - - - Importing blocks from disk... - Besig om blokke vanaf die hardeskyf in te voer... - Reindexing blocks on disk... Besig met herindeksering van blokke op hardeskyf... @@ -297,10 +150,6 @@ &Receive &Ontvang - - Show information about Bitcoin Core - Vertoon inligting oor Bitcoin Kern - Show or hide the main Window Wys of versteek die hoofbladsy @@ -321,22 +170,10 @@ &Help &Help - - Bitcoin Core - Bitcoin Kern - Request payments (generates QR codes and bitcoin: URIs) Versoek betalings (genereer QR-kodes en bitcoin: URI's) - - &About Bitcoin Core - &Omtrent Bitcoin Kern - - - Modify configuration options for Bitcoin Core - Verander konfigurasie-opsies vir Bitcoin Kern - Show the list of used sending addresses and labels Vertoon die lys van gebruikte versendingsadresse en etikette @@ -350,15 +187,8 @@ Skep 'n bitcoin: URI of betalingsversoek - - ClientModel - CoinControlDialog - - (no label) - (geen etiket) - EditAddressDialog @@ -368,21 +198,9 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin Kern - - - Reset all settings changes made over the GUI - Herstel al my veranderinge aan die stellings terug na die verstek-opsies - - + Intro - - Bitcoin Core - Bitcoin Kern - OpenURIDialog @@ -393,18 +211,12 @@ OverviewPage - - PaymentServer - PeerTableModel QObject - - QRImageWidget - RPCConsole @@ -413,24 +225,9 @@ ReceiveRequestDialog - - Address - Adres - - - - RecentRequestsTableModel - - (no label) - (geen etiket) - SendCoinsDialog - - (no label) - (geen etiket) - SendCoinsEntry @@ -443,60 +240,22 @@ SplashScreen - - Bitcoin Core - Bitcoin Kern - TrafficGraphWidget - - TransactionDesc - TransactionDescDialog - - TransactionTableModel - - - TransactionView - - Exporting Failed - Uitvoer was onsuksesvol - - - Comma separated file (*.csv) - Comma separated file (*.csv) - - - Address - Adres - - UnitDisplayStatusBarControl - WalletFrame - - - WalletModel - - - WalletView - - &Export - &Voer uit - + bitcoin-core - Export the data in the current tab to a file - Voer die inligting op hierdie bladsy uit na 'n leer + Bitcoin Core + Bitcoin Kern - - - bitcoin-core WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) WAARSKUWING: toets die status van u netwerk, %d blokke ontvang in die laaste %d ure (%d verwag) diff --git a/src/qt/locale/bitcoin_af_ZA.ts b/src/qt/locale/bitcoin_af_ZA.ts index 12ac21eb80dcf..e553fc775936f 100644 --- a/src/qt/locale/bitcoin_af_ZA.ts +++ b/src/qt/locale/bitcoin_af_ZA.ts @@ -13,21 +13,6 @@ &Delete &Verwyder - - - AddressTableModel - - Label - Etiket - - - Address - Adres - - - (no label) - (geen etiket) - AskPassphraseDialog @@ -47,70 +32,6 @@ Repeat new passphrase Herhaal nuwe wagfrase - - Encrypt wallet - Enkripteer beursie - - - This operation needs your wallet passphrase to unlock the wallet. - Hierdie operasie benodig 'n wagwoord om die beursie oop te sluit. - - - Unlock wallet - Sluit beursie oop - - - This operation needs your wallet passphrase to decrypt the wallet. - Hierdie operasie benodig 'n wagwoord om die beursie oop te sluit. - - - Decrypt wallet - Sluit beursie oop - - - Change passphrase - Verander wagfrase - - - Confirm wallet encryption - Bevestig beursie enkripsie. - - - Wallet encrypted - Die beursie is nou bewaak - - - Enter the old passphrase and new passphrase to the wallet. - Tik in die ou wagfrase en die nuwe wagfrase vir die beursie. - - - Wallet encryption failed - Die beursie kon nie bewaak word nie - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Beursie bewaaking het misluk as gevolg van 'n interne fout. Die beursie is nie bewaak nie! - - - The supplied passphrases do not match. - Die wagfrase stem nie ooreen nie - - - Wallet unlock failed - Beursie oopsluiting het misluk - - - The passphrase entered for the wallet decryption was incorrect. - Die wagfrase wat ingetik was om die beursie oop te sluit, was verkeerd. - - - Wallet decryption failed - Beursie dekripsie het misluk - - - Wallet passphrase was successfully changed. - Die beursie se wagfrase verandering was suksesvol. - BanTableModel @@ -194,9 +115,6 @@ Informasie - - ClientModel - CoinControlDialog @@ -211,18 +129,6 @@ Date Datum - - Copy address - Maak kopie van adres - - - Copy amount - Kopieer bedrag - - - (no label) - (geen etiket) - EditAddressDialog @@ -234,27 +140,7 @@ &Address &Adres - - New receiving address - Nuwe ontvangende adres - - - New sending address - Nuwe stuurende adres - - - Edit receiving address - Wysig ontvangende adres - - - Edit sending address - Wysig stuurende adres - - - Could not unlock wallet. - Kon nie die beursie oopsluit nie. - - + FreespaceChecker @@ -293,9 +179,6 @@ Vorm - - PaymentServer - PeerTableModel @@ -306,9 +189,6 @@ Bedrag - - QRImageWidget - RPCConsole @@ -326,52 +206,9 @@ &Message: &Boodskap: - - Copy amount - Kopieer bedrag - - - - ReceiveRequestDialog - - Address - Adres - - - Amount - Bedrag - - - Label - Etiket - - - Message - Boodskap - - RecentRequestsTableModel - - Date - Datum - - - Label - Etiket - - - Message - Boodskap - - - Amount - Bedrag - - - (no label) - (geen etiket) - + ReceiveRequestDialog SendCoinsDialog @@ -403,15 +240,7 @@ S&end S&tuur - - Copy amount - Kopieer bedrag - - - (no label) - (geen etiket) - - + SendCoinsEntry @@ -447,234 +276,12 @@ TrafficGraphWidget - - TransactionDesc - - Date - Datum - - - From - Van - - - To - Na - - - own address - eie adres - - - label - etiket - - - Credit - Krediet - - - not accepted - nie aanvaar nie - - - Debit - Debiet - - - Transaction fee - Transaksie fooi - - - Net amount - Netto bedrag - - - Message - Boodskap - - - Transaction ID - Transaksie ID - - - Transaction - Transaksie - - - Amount - Bedrag - - - true - waar - - - false - onwaar - - - unknown - onbekend - - TransactionDescDialog - - TransactionTableModel - - Date - Datum - - - Type - Tipe - - - Label - Etiket - - - Received with - Ontvang met - - - Received from - Ontvang van - - - Sent to - Gestuur na - - - Payment to yourself - Betalings Aan/na jouself - - - Mined - Gemyn - - - (n/a) - (n.v.t) - - - Date and time that the transaction was received. - Datum en tyd wat die transaksie ontvang was. - - - Type of transaction. - Tipe transaksie. - - - - TransactionView - - All - Alles - - - Today - Vandag - - - This week - Hierdie week - - - This month - Hierdie maand - - - Last month - Verlede maand - - - This year - Hierdie jaar - - - Range... - Reeks... - - - Received with - Ontvang met - - - Sent to - Gestuur na - - - To yourself - Aan/na jouself - - - Mined - Gemyn - - - Other - Ander - - - Min amount - Min bedrag - - - Copy address - Maak kopie van adres - - - Copy amount - Kopieer bedrag - - - Date - Datum - - - Type - Tipe - - - Label - Etiket - - - Address - Adres - - - ID - ID - - - Range: - Reeks: - - - to - aan - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - Send Coins - Stuur Munstukke - - - - WalletView - bitcoin-core @@ -689,10 +296,6 @@ Information Informasie - - This help message - Hierdie help boodskap - Loading addresses... Laai adresse... diff --git a/src/qt/locale/bitcoin_ar.ts b/src/qt/locale/bitcoin_ar.ts index 1e74564ed3ead..78fd074434316 100644 --- a/src/qt/locale/bitcoin_ar.ts +++ b/src/qt/locale/bitcoin_ar.ts @@ -25,10 +25,6 @@ C&lose &اغلاق - - &Copy Address - انسخ العنوان - Delete the currently selected address from the list حذف العنوان المحدد من القائمة @@ -45,73 +41,6 @@ &Delete &أمسح - - Choose the address to send coins to - اختر العنوان الذي سترسل له العملات - - - Choose the address to receive coins with - اختر العنوان الذي تستقبل عليه العملات - - - C&hoose - &اختر - - - Sending addresses - ارسال العناوين - - - Receiving addresses - استقبال العناوين - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - هذه هي عناوين Bitcion التابعة لك من أجل إرسال الدفعات. تحقق دائما من المبلغ و عنوان المرسل المستقبل قبل إرسال العملات - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - هذه هي عناوين Bitcion التابعة لك من أجل إستقبال الدفعات. ينصح استخدام عنوان جديد من أجل كل صفقة - - - Copy &Label - نسخ &الوصف - - - &Edit - تعديل - - - Export Address List - تصدير قائمة العناوين - - - Comma separated file (*.csv) - ملف مفصول بفواصل (*.csv) - - - Exporting Failed - فشل التصدير - - - There was an error trying to save the address list to %1. Please try again. - لقد حدث خطأ أثناء حفظ قائمة العناوين إلى %1. يرجى المحاولة مرة أخرى. - - - - AddressTableModel - - Label - وصف - - - Address - عنوان - - - (no label) - (لا وصف) - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase ادخل كلمة المرور الجديدة مرة أخرى - - Encrypt wallet - تشفير المحفظة - - - This operation needs your wallet passphrase to unlock the wallet. - هذه العملية تحتاج كلمة مرور محفظتك لفتحها - - - Unlock wallet - إفتح المحفظة - - - This operation needs your wallet passphrase to decrypt the wallet. - هذه العملية تحتاج كلمة مرور محفظتك لفك تشفيرها - - - Decrypt wallet - فك تشفير المحفظة - - - Change passphrase - تغيير كلمة المرور - - - Confirm wallet encryption - تأكيد تشفير المحفظة - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - تحذير: إذا قمت بتشفير محفظتك وفقدت كلمة المرور الخاص بك, ستفقد كل عملات BITCOINS الخاصة بك. - - - Are you sure you wish to encrypt your wallet? - هل أنت متأكد من رغبتك في تشفير محفظتك ؟ - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - بتكوين سوف يغلق الآن لإنهاء عملية التشفير. تذكر أن التشفير لا يستطيع حماية محفظتك تمامًا من السرقة من خلال البرمجيات الخبيثة التي تصيب جهازك - - - 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. - هام: أي نسخة إحتياطية سابقة قمت بها لمحفظتك يجب استبدالها بأخرى حديثة، مشفرة. لأسباب أمنية، النسخ الاحتياطية السابقة لملفات المحفظة الغير مشفرة تصبح عديمة الفائدة مع بداية استخدام المحفظة المشفرة الجديدة. - - - Warning: The Caps Lock key is on! - تحذير: مفتاح الحروف الكبيرة مفعل - - - Wallet encrypted - محفظة مشفرة - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - أدخل عبارة مرور جديدة إلى المحفظة. الرجاء استخدام عبارة مرور تتكون من10 حروف عشوائية على الاقل, أو أكثر من 7 كلمات - - - Enter the old passphrase and new passphrase to the wallet. - أدخل كلمة المرور القديمة والجديدة للمحفظة. - - - Wallet encryption failed - فشل تشفير المحفظة - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - فشل تشفير المحفظة بسبب خطأ داخلي. لم يتم تشفير محفظتك. - - - The supplied passphrases do not match. - كلمتي المرور ليستا متطابقتان - - - Wallet unlock failed - فشل فتح المحفظة - - - The passphrase entered for the wallet decryption was incorrect. - كلمة المرور التي تم إدخالها لفك تشفير المحفظة غير صحيحة. - - - Wallet decryption failed - فشل فك التشفير المحفظة - - - Wallet passphrase was successfully changed. - لقد تم تغير عبارة مرور المحفظة بنجاح - BanTableModel @@ -269,9 +110,17 @@ Quit application الخروج من التطبيق + + &About %1 + &عن %1 + + + Show information about %1 + أظهر المعلومات حولة %1 + About &Qt - عن + عن &Qt Show information about Qt @@ -305,14 +154,6 @@ Open &URI... افتح &URI... - - Bitcoin Core client - عميل bitcion core - - - Importing blocks from disk... - استيراد كتل من القرص ... - Reindexing blocks on disk... إعادة الفهرسة الكتل على القرص ... @@ -357,10 +198,6 @@ &Receive &استقبل - - Show information about Bitcoin Core - اظهار معلومات حول bitcion core - &Show / Hide &عرض / اخفاء @@ -397,22 +234,10 @@ Tabs toolbar شريط أدوات علامات التبويب - - Bitcoin Core - جوهر البيت كوين - Request payments (generates QR codes and bitcoin: URIs) أطلب دفعات (يولد كودات الرمز المربع وبيت كوين: العناوين المعطاة) - - &About Bitcoin Core - حول bitcoin core - - - Modify configuration options for Bitcoin Core - تغيير خيارات الإعداد لأساس Bitcoin - Show the list of used sending addresses and labels عرض قائمة عناوين الإرسال المستخدمة والملصقات @@ -429,6 +254,14 @@ &Command-line options &خيارات سطر الأوامر + + Indexing blocks on disk... + ترتيب الفهرسة الكتل على القرص... + + + Processing blocks on disk... + معالجة الكتل على القرص... + No block source available... لا يوجد أي مصدر الكتلة @@ -490,13 +323,6 @@ المحفظة <b>مشفرة</b> و <b>مقفلة</b> حاليا - - ClientModel - - Network Alert - تنبيه من الشبكة - - CoinControlDialog @@ -551,114 +377,6 @@ Priority أفضلية - - Copy address - انسخ عنوان - - - Copy label - انسخ التسمية - - - Copy amount - نسخ الكمية - - - Copy transaction ID - نسخ رقم العملية - - - Copy quantity - نسخ الكمية - - - Copy fee - نسخ الرسوم - - - Copy after fee - نسخ بعد الرسوم - - - Copy priority - نسخ الافضلية - - - Copy change - نسخ التعديل - - - highest - الاعلى - - - higher - اعلى - - - high - عالي - - - medium-high - متوسط-مرتفع - - - medium - متوسط - - - low-medium - متوسط-منخفض - - - low - منخفض - - - lower - أدنى - - - lowest - الأدنى - - - none - لا شيء - - - This label turns red if the transaction size is greater than 1000 bytes. - هذا الملصق يصبح أخمرا إذا كان حجم المعاملة أكبر من 1000 بايت. - - - yes - نعم - - - no - لا - - - This means a fee of at least %1 per kB is required. - هذا يعني أن من المطلوب أن يكون الرسم ألى الأقل %1 لكل كيلوبايت. - - - Can vary +/- 1 byte per input. - يمكن أن يتفاوت بـ 1 بايت لكل مساهمة. - - - Transactions with higher priority are more likely to get included into a block. - المعاملات التي لديها أولوية أعلى على الأرجح سيتم إنضمامها في الكتلة. - - - (no label) - (لا وصف) - - - (change) - (تغير) - EditAddressDialog @@ -674,38 +392,6 @@ &Address &العنوان - - New receiving address - عنوان أستلام جديد - - - New sending address - عنوان إرسال جديد - - - Edit receiving address - تعديل عنوان الأستلام - - - Edit sending address - تعديل عنوان الارسال - - - The entered address "%1" is already in the address book. - هدا العنوان "%1" موجود مسبقا في دفتر العناوين - - - The entered address "%1" is not a valid Bitcoin address. - العنوان المدخل "%1" ليس عنوان بيت كوين صحيح. - - - Could not unlock wallet. - يمكن فتح المحفظة. - - - New key generation failed. - فشل توليد مفتاح جديد. - FreespaceChecker @@ -732,18 +418,10 @@ HelpMessageDialog - - Bitcoin Core - جوهر البيت كوين - version النسخة - - About Bitcoin Core - عن جوهر البيت كوين - Command-line options خيارات سطر الأوامر @@ -772,11 +450,7 @@ Show splash screen on startup (default: %u) أظهر شاشة البداية عند بدء التشغيل (افتراضي: %u) - - Reset all settings changes made over the GUI - إعادة تعيين كل الإعدادات تم تغييرها من خلال الواجهة الرسومية - - + Intro @@ -791,10 +465,6 @@ Use a custom data directory: استخدام دليل بيانات مخصص: - - Bitcoin Core - جوهر البيت كوين - Error خطأ @@ -806,10 +476,6 @@ Select payment request file حدد ملف طلب الدفع - - Select payment request file to open - حدد ملف طلب الدفع لفتحه - OptionsDialog @@ -925,13 +591,6 @@ رصيدك الكلي الحالي - - PaymentServer - - Bad response from server %1 - استجابة سيئة من الملقم %1 - - PeerTableModel @@ -954,25 +613,6 @@ غير معروف - - QRImageWidget - - &Save Image... - &حفظ الصورة - - - &Copy Image - &نسخ الصورة - - - Save QR Code - حفظ رمز الاستجابة السريعة QR - - - PNG Image (*.png) - صورة PNG (*.png) - - RPCConsole @@ -1063,10 +703,6 @@ Out: خارج: - - Build date - وقت البناء - Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. استخدم اسهم الاعلى و الاسفل للتنقل بين السجلات و <b>Ctrl-L</b> لمسح الشاشة @@ -1134,18 +770,6 @@ Remove ازل - - Copy label - انسخ التسمية - - - Copy message - انسخ الرسالة - - - Copy amount - نسخ الكمية - ReceiveRequestDialog @@ -1165,58 +789,7 @@ &Save Image... &حفظ الصورة - - Payment information - معلومات الدفع - - - URI - URI - - - Address - عنوان - - - Amount - المبلغ - - - Label - وصف - - - Message - رسالة - - - - RecentRequestsTableModel - - Date - التاريخ - - - Label - وصف - - - Message - رسالة - - - Amount - المبلغ - - - (no label) - (لا وصف) - - - (no message) - ( لا رسائل ) - - + SendCoinsDialog @@ -1260,7 +833,11 @@ رسوم المعاملة: - Send to multiple recipients at once + Hide + إخفاء + + + Send to multiple recipients at once إرسال إلى عدة مستلمين في وقت واحد @@ -1287,59 +864,7 @@ S&end &ارسال - - Confirm send coins - تأكيد الإرسال Coins - - - %1 to %2 - %1 الى %2 - - - Copy quantity - نسخ الكمية - - - Copy amount - نسخ الكمية - - - Copy fee - نسخ الرسوم - - - Copy after fee - نسخ بعد الرسوم - - - Copy priority - نسخ الافضلية - - - Copy change - نسخ التعديل - - - or - أو - - - The amount to pay must be larger than 0. - المبلغ المدفوع يجب ان يكون اكبر من 0 - - - The amount exceeds your balance. - القيمة تتجاوز رصيدك - - - The total exceeds your balance when the %1 transaction fee is included. - المجموع يتجاوز رصيدك عندما يتم اضافة %1 رسوم العملية - - - (no label) - (لا وصف) - - + SendCoinsEntry @@ -1350,10 +875,6 @@ Pay &To: ادفع &الى : - - Enter a label for this address to add it to your address book - إدخال تسمية لهذا العنوان لإضافته إلى دفتر العناوين الخاص بك - &Label: &وصف : @@ -1432,61 +953,9 @@ Verify &Message تحقق &الرسالة - - Click "Sign Message" to generate signature - اضغط "توقيع الرسالة" لتوليد التوقيع - - - The entered address is invalid. - العنوان المدخل غير صالح - - - Please check the address and try again. - الرجاء التأكد من العنوان والمحاولة مرة اخرى - - - The entered address does not refer to a key. - العنوان المدخل لا يشير الى مفتاح - - - Wallet unlock was cancelled. - تم الغاء عملية فتح المحفظة - - - Private key for the entered address is not available. - المفتاح الخاص للعنوان المدخل غير موجود. - - - Message signing failed. - فشل توقيع الرسالة. - - - Message signed. - الرسالة موقعة. - - - Please check the signature and try again. - فضلا تاكد من التوقيع وحاول مرة اخرى - - - Message verification failed. - فشلت عملية التأكد من الرسالة. - - - Message verified. - تم تأكيد الرسالة. - - + SplashScreen - - Bitcoin Core - جوهر البيت كوين - - - The Bitcoin Core developers - مطوري جوهر البيت كوين - [testnet] [testnet] @@ -1495,362 +964,16 @@ TrafficGraphWidget - - TransactionDesc - - Open until %1 - مفتوح حتى %1 - - - conflicted - يتعارض - - - %1/offline - %1 غير متواجد - - - %1/unconfirmed - غير مؤكدة/%1 - - - %1 confirmations - تأكيد %1 - - - Status - الحالة. - - - Date - التاريخ - - - Source - المصدر - - - Generated - تم اصداره. - - - From - من - - - To - الى - - - own address - عنوانه - - - label - علامة - - - not accepted - غير مقبولة - - - Debit - دين - - - Transaction fee - رسوم المعاملة - - - Message - رسالة - - - Comment - تعليق - - - Transaction ID - رقم المعاملة - - - Merchant - تاجر - - - Transaction - معاملة - - - Amount - المبلغ - - - true - صحيح - - - false - خاطئ - - - , has not been successfully broadcast yet - , لم يتم حتى الآن البث بنجاح - - - unknown - غير معروف - - TransactionDescDialog - - Transaction details - تفاصيل المعاملة - This pane shows a detailed description of the transaction يبين هذا الجزء وصفا مفصلا لهده المعاملة - - TransactionTableModel - - Date - التاريخ - - - Type - النوع - - - Open until %1 - مفتوح حتى %1 - - - This block was not received by any other nodes and will probably not be accepted! - لم يتم تلقى هذه الكتلة (Block) من قبل أي العقد الأخرى وربما لن تكون مقبولة! - - - Generated but not accepted - ولدت ولكن لم تقبل - - - Offline - غير متصل - - - Label - وصف - - - Conflicted - يتعارض - - - Received with - استقبل مع - - - Received from - استقبل من - - - Sent to - أرسل إلى - - - Payment to yourself - دفع لنفسك - - - Mined - Mined - - - (n/a) - غير متوفر - - - Transaction status. Hover over this field to show number of confirmations. - حالة المعاملة. تحوم حول هذا الحقل لعرض عدد التأكيدات. - - - Date and time that the transaction was received. - التاريخ والوقت الذي تم فيه تلقي المعاملة. - - - Type of transaction. - نوع المعاملات - - - Amount removed from or added to balance. - المبلغ الذي أزيل أو أضيف الى الرصيد - - - - TransactionView - - All - الكل - - - Today - اليوم - - - This week - هدا الاسبوع - - - This month - هدا الشهر - - - Last month - الشهر الماضي - - - This year - هدا العام - - - Range... - المدى... - - - Received with - استقبل مع - - - Sent to - أرسل إلى - - - To yourself - إليك - - - Mined - Mined - - - Other - اخرى - - - Enter address or label to search - ادخل عنوان أووصف للبحث - - - Min amount - الحد الأدنى - - - Copy address - انسخ عنوان - - - Copy label - انسخ التسمية - - - Copy amount - نسخ الكمية - - - Copy transaction ID - نسخ رقم العملية - - - Edit label - عدل الوصف - - - Show transaction details - عرض تفاصيل المعاملة - - - Exporting Failed - فشل التصدير - - - Exporting Successful - نجح التصدير - - - Comma separated file (*.csv) - ملف مفصول بفواصل (*.csv) - - - Confirmed - تأكيد - - - Date - التاريخ - - - Type - النوع - - - Label - وصف - - - Address - عنوان - - - ID - العنوان - - - Range: - المدى: - - - to - الى - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - Send Coins - إرسال Coins - - - - WalletView - - &Export - &تصدير - - - Export the data in the current tab to a file - تحميل البيانات في علامة التبويب الحالية إلى ملف. - - - Backup Wallet - نسخ احتياط للمحفظة - - - Backup Failed - فشل النسخ الاحتياطي - - - Backup Successful - نجاح النسخ الاحتياطي - - bitcoin-core @@ -1865,6 +988,10 @@ Accept connections from outside (default: 1 if no -proxy or -connect) قبول الاتصالات من خارج + + Bitcoin Core + جوهر البيت كوين + Error: Disk space is low! تحذير: مساحة القرص منخفضة @@ -1909,22 +1036,10 @@ Warning تحذير - - This help message - رسالة المساعدة هذه - Loading addresses... تحميل العنوان - - Error loading wallet.dat: Wallet corrupted - خطأ عند تنزيل wallet.dat: المحفظة تالفة - - - Error loading wallet.dat - خطأ عند تنزيل wallet.dat - Invalid -proxy address: '%s' عنوان البروكسي غير صحيح : '%s' diff --git a/src/qt/locale/bitcoin_be_BY.ts b/src/qt/locale/bitcoin_be_BY.ts index 2709ff37e5157..5894148fe0342 100644 --- a/src/qt/locale/bitcoin_be_BY.ts +++ b/src/qt/locale/bitcoin_be_BY.ts @@ -25,10 +25,6 @@ C&lose Зачыніць - - &Copy Address - Капіяваць адрас - Delete the currently selected address from the list Выдаліць абраны адрас са спісу @@ -45,73 +41,6 @@ &Delete Выдаліць - - Choose the address to send coins to - Выбраць адрас, куды выслаць сродкі - - - Choose the address to receive coins with - Выбраць адрас, на які атрымаць сродкі - - - C&hoose - Выбраць - - - Sending addresses - адрасы Адпраўкі - - - Receiving addresses - адрасы Прымання - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Тут знаходзяцца Біткойн-адрасы для высылання плацяжоў. Заўсёды спраўджвайце колькасць і адрас прызначэння перад здзяйсненнем транзакцыі. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Тут знаходзяцца Біткойн-адрасы для прымання плацяжоў. Пажадана выкарыстоўваць новы адрас для кожнай транзакцыі. - - - Copy &Label - Капіяваць Метку - - - &Edit - Рэдагаваць - - - Export Address List - Экспартаваць Спіс Адрасоў - - - Comma separated file (*.csv) - Коскамі падзелены файл (*.csv) - - - Exporting Failed - Экспартаванне няўдалае - - - There was an error trying to save the address list to %1. Please try again. - Адбылася памылка падчас спробы захаваць адрас у %1. Паспрабуйце зноў. - - - - AddressTableModel - - Label - Метка - - - Address - Адрас - - - (no label) - непазначаны - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase Паўтарыце новую кодавую фразу - - Encrypt wallet - Зашыфраваць гаманец. - - - This operation needs your wallet passphrase to unlock the wallet. - Гэтая аперацыя патрабуе кодавую фразу, каб рзблакаваць гаманец. - - - Unlock wallet - Разблакаваць гаманец - - - This operation needs your wallet passphrase to decrypt the wallet. - Гэтая аперацыя патрабуе пароль каб расшыфраваць гаманец. - - - Decrypt wallet - Рачшыфраваць гаманец - - - Change passphrase - Змяніць пароль - - - Confirm wallet encryption - Пацвердзіце шыфраванне гаманца - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Увага: калі вы зашыфруеце свой гаманец і страціце парольную фразу, то <b>СТРАЦІЦЕ ЎСЕ СВАЕ БІТКОЙНЫ</b>! - - - Are you sure you wish to encrypt your wallet? - Ці ўпэўненыя вы, што жадаеце зашыфраваць свой гаманец? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Bitcoin Core зараз будзе зачынены, каб фіналізаваць працэс шыфравання. Памятайце, што шыфраванне вашага гаманца не гарантуе абсалютную абарону ад магчымасці крадзяжу біткойнаў шкоднымі праграмамі, якія могуць інфікаваць ваш камп'ютар. - - - 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. - ВАЖНА: Усе папярэднія копіі гаманца варта замяніць новым зашыфраваным файлам. У мэтах бяспекі папярэднія копіі незашыфраванага файла-гаманца стануць неўжывальнымі, калі вы станеце карыстацца новым зашыфраваным гаманцом. - - - Warning: The Caps Lock key is on! - Увага: Caps Lock уключаны! - - - Wallet encrypted - Гаманец зашыфраваны - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Увядзіце новы пароль для гаманца.<br/>Парольная фраза павинна складацца<b> не меньш чым з дзесяці сімвалаў</b>, ці <b>больш чым з васьмі слоў</b>. - - - Enter the old passphrase and new passphrase to the wallet. - Увядзіце стары пароль і новы пароль для гаманца. - - - Wallet encryption failed - Шыфраванне гаманца няўдалае - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Шыфраванне гаманца не адбылося з-за ўнутранай памылкі. Гаманец незашыфраваны. - - - The supplied passphrases do not match. - Уведдзеныя паролі не супадаюць - - - Wallet unlock failed - Разблакаванне гаманца няўдалае - - - The passphrase entered for the wallet decryption was incorrect. - Уведзены пароль для расшыфравання гаманца памылковы - - - Wallet decryption failed - Расшыфраванне гаманца няўдалае - - - Wallet passphrase was successfully changed. - Парольная фраза гаманца паспяхова зменена. - BanTableModel @@ -297,14 +138,6 @@ Open &URI... Адчыниць &URI... - - Bitcoin Core client - Bitcoin Core кліент - - - Importing blocks from disk... - Імпартуюцца блокі з дыску... - Reindexing blocks on disk... Пераіндэксацыя блокаў на дыску... @@ -349,10 +182,6 @@ &Receive Атрымаць - - Show information about Bitcoin Core - Паказаць інфармацыю аб Bitcoin Core - &Show / Hide &Паказаць / Схаваць @@ -385,22 +214,10 @@ &Help Дапамога - - Bitcoin Core - Bitcoin Core - Request payments (generates QR codes and bitcoin: URIs) Запатрабаваць плацёж (генеруецца QR-код для біткойн URI) - - &About Bitcoin Core - Аб Bitcoin Core - - - Modify configuration options for Bitcoin Core - Мадыфікаваць опцыі канфігурацыі Bitcoin Core - Show the list of used sending addresses and labels Паказаць спіс адрасоў і метак для дасылання @@ -417,10 +234,6 @@ &Command-line options Опцыі каманднага радка - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Паказваць даведку Bitcoin Core каб атрымаць спіс магчымых опцый каманднага радка - %n active connection(s) to Bitcoin network %n актыўнае злучэнне з сецівам Bitcoin%n актыўных злучэнняў з сецівам Bitcoin%n актыўных злучэнняў з сецівам Bitcoin%n актыўных злучэнняў з сецівам Bitcoin @@ -532,13 +345,6 @@ Гаманец <b>зашыфраваны</b> і зараз <b>заблакаваны</b> - - ClientModel - - Network Alert - Трывога Сеціва - - CoinControlDialog @@ -609,111 +415,7 @@ Priority Прыярытэт - - Copy address - Капіяваць адрас - - - Copy label - Капіяваць пазнаку - - - Copy amount - Капіяваць колькасць - - - Copy transaction ID - Капіяваць ID транзакцыі - - - Lock unspent - Замкнуць непатрачанае - - - Unlock unspent - Адамкнуць непатрачанае - - - Copy quantity - Капіяваць колькасць - - - Copy fee - Капіяваць камісію - - - Copy after fee - Капіяваць з выняткам камісіі - - - Copy bytes - Капіяваць байты - - - Copy priority - Капіяваць прыярытэт - - - Copy dust - Капіяваць пыл - - - highest - найвышэйшы - - - higher - вышэйшы - - - high - высокі - - - medium-high - вышэй сярэдняга - - - medium - сярэдні - - - low-medium - ніжэй сярэдняга - - - low - нізкі - - - lower - ніжэйшы - - - lowest - найніжэйшы - - - yes - так - - - no - не - - - This means a fee of at least %1 per kB is required. - Гэта значыць патрэбную камісію мінімум %1 на Кб. - - - Transactions with higher priority are more likely to get included into a block. - Транзакцыя большага прыярытэту больш прываблівая для ўключэння ў блок. - - - (no label) - непазначаны - - + EditAddressDialog @@ -728,34 +430,6 @@ &Address Адрас - - New receiving address - Новы адрас для атрымання - - - New sending address - Новы адрас для дасылання - - - Edit receiving address - Рэдагаваць адрас прымання - - - Edit sending address - Рэдагаваць адрас дасылання - - - The entered address "%1" is already in the address book. - Уведзены адрас "%1" ужо ў кніге адрасоў - - - Could not unlock wallet. - Немагчыма разблакаваць гаманец - - - New key generation failed. - Генерацыя новага ключа няўдалая - FreespaceChecker @@ -774,18 +448,10 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin Core - (%1-bit) (%1-біт) - - About Bitcoin Core - Аб Bitcoin Core - Command-line options Опцыі каманднага радка @@ -805,14 +471,6 @@ Welcome Вітаем - - Welcome to Bitcoin Core. - Вітаем у Bitcoin Core. - - - Bitcoin Core - Bitcoin Core - Error Памылка @@ -855,9 +513,6 @@ Форма - - PaymentServer - PeerTableModel @@ -868,9 +523,6 @@ Колькасць - - QRImageWidget - RPCConsole @@ -892,60 +544,13 @@ &Label: Метка: - - Copy label - Капіяваць пазнаку - - - Copy amount - Капіяваць колькасць - - + ReceiveRequestDialog Copy &Address Капіяваць адрас - - Address - Адрас - - - Amount - Колькасць - - - Label - Метка - - - Message - Паведамленне - - - - RecentRequestsTableModel - - Date - Дата - - - Label - Метка - - - Message - Паведамленне - - - Amount - Колькасць - - - (no label) - непазначаны - SendCoinsDialog @@ -997,46 +602,6 @@ Confirm the send action Пацвердзіць дасыланне - - Confirm send coins - Пацвердзіць дасыланне манет - - - Copy quantity - Капіяваць колькасць - - - Copy amount - Капіяваць колькасць - - - Copy fee - Капіяваць камісію - - - Copy after fee - Капіяваць з выняткам камісіі - - - Copy bytes - Капіяваць байты - - - Copy priority - Капіяваць прыярытэт - - - The amount to pay must be larger than 0. - Велічыня плацяжу мае быць больш за 0. - - - (no label) - непазначаны - - - Copy dust - Капіяваць пыл - SendCoinsEntry @@ -1048,10 +613,6 @@ Pay &To: Заплаціць да: - - Enter a label for this address to add it to your address book - Увядзіце пазнаку гэтаму адрасу, каб дадаць яго ў адрасную кнігу - &Label: Метка: @@ -1101,14 +662,6 @@ SplashScreen - - Bitcoin Core - Bitcoin Core - - - The Bitcoin Core developers - Распрацоўнікі Bitcoin Core - [testnet] [testnet] @@ -1121,274 +674,16 @@ Кб/с - - TransactionDesc - - %1/offline - %1/offline - - - %1/unconfirmed - %1/непацверджана - - - %1 confirmations - %1 пацверджанняў - - - Status - Статус - - - Date - Дата - - - Message - Паведамленне - - - Comment - Каментар - - - Transaction ID - ID - - - Amount - Колькасць - - - , has not been successfully broadcast yet - , пакуль не было паспяхова транслявана - - - unknown - невядома - - TransactionDescDialog - - Transaction details - Дэталі транзакцыі - This pane shows a detailed description of the transaction Гэтая панэль паказвае дэтальнае апісанне транзакцыі - - TransactionTableModel - - Date - Дата - - - Type - Тып - - - Confirmed (%1 confirmations) - Пацверджана (%1 пацверджанняў) - - - This block was not received by any other nodes and will probably not be accepted! - Гэты блок не быў прыняты іншымі вузламі і магчыма не будзе ўхвалены! - - - Generated but not accepted - Згенеравана, але не прынята - - - Label - Метка - - - Received with - Прынята з - - - Received from - Прынята ад - - - Sent to - Даслана да - - - Payment to yourself - Плацёж самому сабе - - - Mined - Здабыта - - - (n/a) - (n/a) - - - Transaction status. Hover over this field to show number of confirmations. - Статус транзакцыі. Навядзіце курсар на гэтае поле, каб паказаць колькасць пацверджанняў. - - - Date and time that the transaction was received. - Дата і час, калі транзакцыя была прынята. - - - Type of transaction. - Тып транзакцыі - - - Amount removed from or added to balance. - Колькасць аднятая ці даданая да балансу. - - - - TransactionView - - All - Усё - - - Today - Сёння - - - This week - Гэты тыдзень - - - This month - Гэты месяц - - - Last month - Мінулы месяц - - - This year - Гэты год - - - Range... - Прамежак... - - - Received with - Прынята з - - - Sent to - Даслана да - - - To yourself - Да сябе - - - Mined - Здабыта - - - Other - Іншыя - - - Enter address or label to search - Увядзіце адрас ці пазнаку для пошуку - - - Min amount - Мін. колькасць - - - Copy address - Капіяваць адрас - - - Copy label - Капіяваць пазнаку - - - Copy amount - Капіяваць колькасць - - - Copy transaction ID - Капіяваць ID транзакцыі - - - Edit label - Рэдагаваць пазнаку - - - Exporting Failed - Экспартаванне няўдалае - - - Comma separated file (*.csv) - Коскамі падзелены файл (*.csv) - - - Confirmed - Пацверджана - - - Date - Дата - - - Type - Тып - - - Label - Метка - - - Address - Адрас - - - ID - ID - - - Range: - Прамежак: - - - to - да - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - Send Coins - Даслаць Манеты - - - - WalletView - - &Export - Экспарт - - - Export the data in the current tab to a file - Экспартаваць гэтыя звесткі у файл - - bitcoin-core @@ -1407,6 +702,10 @@ Run in the background as a daemon and accept commands Запусціць у фоне як дэман і прымаць каманды + + Bitcoin Core + Bitcoin Core + Do you want to rebuild the block database now? Ці жадаеце вы перабудаваць зараз базу звестак блокаў? @@ -1455,10 +754,6 @@ Wallet options: Опцыі гаманца: - - Activating best chain... - Актывацыя лепшага ланцуга... - Information Інфармацыя @@ -1507,14 +802,6 @@ Loading addresses... Загружаем адрасы... - - Error loading wallet.dat: Wallet corrupted - Памылка загрузкі wallet.dat: гаманец пашкоджаны - - - Error loading wallet.dat - Памылка загрузкі wallet.dat - Insufficient funds Недастаткова сродкаў diff --git a/src/qt/locale/bitcoin_bg.ts b/src/qt/locale/bitcoin_bg.ts index 54bf8136a60b4..3bb881318288f 100644 --- a/src/qt/locale/bitcoin_bg.ts +++ b/src/qt/locale/bitcoin_bg.ts @@ -25,10 +25,6 @@ C&lose Затвори - - &Copy Address - &Копирай адрес - Delete the currently selected address from the list Изтрий избрания адрес от списъка @@ -45,73 +41,6 @@ &Delete &Изтриване - - Choose the address to send coins to - Изберете адрес, на който да се изпращат монети - - - Choose the address to receive coins with - Изберете адрес, на който ще получавате монети - - - C&hoose - Избери - - - Sending addresses - Адреси за изпращане - - - Receiving addresses - Адреси за получаване - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Това са адресите на получателите на плащания. Винаги проверявайте размера на сумата и адреса на получателя, преди да изпратите монети. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Това са Вашите Биткойн адреси,благодарение на които ще получавате плащания.Препоръчително е да използвате нови адреси за получаване на всяка транзакция. - - - Copy &Label - Копирай &име - - - &Edit - &Редактирай - - - Export Address List - Изнасяне на списъка с адреси - - - Comma separated file (*.csv) - CSV файл (*.csv) - - - Exporting Failed - Грешка при изнасянето - - - There was an error trying to save the address list to %1. Please try again. - Възникна грешка при опита за запазване на списъка с адреси в %1.Моля опитайте отново. - - - - AddressTableModel - - Label - Име - - - Address - Адрес - - - (no label) - (без име) - AskPassphraseDialog @@ -131,86 +60,6 @@ Repeat new passphrase Въведете новата парола повторно - - Encrypt wallet - Шифриране на портфейла - - - This operation needs your wallet passphrase to unlock the wallet. - Тази операция изисква Вашата парола за отключване на портфейла. - - - Unlock wallet - Отключване на портфейла - - - This operation needs your wallet passphrase to decrypt the wallet. - Тази операция изисква Вашата парола за дешифриране на портфейла. - - - Decrypt wallet - Дешифриране на портфейла - - - Change passphrase - Смяна на паролата - - - Confirm wallet encryption - Потвърдете на шифрирането на портфейла - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - ВНИМАНИЕ: Ако шифрирате вашият портфейл и изгубите паролата си, <b>ЩЕ ИЗГУБИТЕ ВСИЧКИТЕ СИ БИТКОИНИ</b>! - - - Are you sure you wish to encrypt your wallet? - Наистина ли желаете да шифрирате портфейла си? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Биткоин сега ще се затоври за да завърши процеса на криптиране. Запомнете, че криптирането на вашия портефейл не може напълно да предпази вашите монети от кражба чрез зловреден софтуер, инфектирал вашия компютър - - - 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. - ВАЖНО: Всички стари запазвания, които сте направили на Вашият портфейл трябва да замените с запазване на новополучения, шифриран портфейл. От съображения за сигурност, предишните запазвания на нешифрирани портфейли ще станат неизползваеми веднага, щом започнете да използвате новият, шифриран портфейл. - - - Warning: The Caps Lock key is on! - Внимание: Caps Lock (главни букви) е включен. - - - Wallet encrypted - Портфейлът е шифриран - - - Wallet encryption failed - Шифрирането беше неуспешно - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Шифрирането на портфейла беше неуспешно, поради софтуерен проблем. Портфейлът не е шифриран. - - - The supplied passphrases do not match. - Паролите не съвпадат - - - Wallet unlock failed - Неуспешно отключване на портфейла - - - The passphrase entered for the wallet decryption was incorrect. - Паролата въведена за дешифриране на портфейла е грешна. - - - Wallet decryption failed - Дешифрирането на портфейла беше неуспешно - - - Wallet passphrase was successfully changed. - Паролата на портфейла беше променена успешно. - BanTableModel @@ -293,10 +142,6 @@ Open &URI... Отвори &URI... - - Bitcoin Core client - Bitcoin Core клиент - Send coins to a Bitcoin address Изпращане към Биткоин адрес @@ -337,10 +182,6 @@ &Receive &Получаване - - Show information about Bitcoin Core - Покажете информация за Биткойн ядрото - &Show / Hide &Показване / Скриване @@ -377,18 +218,10 @@ Tabs toolbar Раздели - - Bitcoin Core - Биткойн ядро - Request payments (generates QR codes and bitcoin: URIs) Изискване на плащания(генерира QR кодове и биткойн: URIs) - - &About Bitcoin Core - &Относно Bitcoin Core - Show the list of used sending addresses and labels Показване на списъка с използвани адреси и имена @@ -405,10 +238,6 @@ &Command-line options &Налични команди - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Покажи помощните съобщения на Биткойн за да видиш наличните и валидни команди - No block source available... Липсва източник на блоковете... @@ -496,13 +325,6 @@ Портфейлът е <b>криптиран</b> и <b>заключен</b> - - ClientModel - - Network Alert - Мрежови проблем - - CoinControlDialog @@ -581,134 +403,6 @@ Priority Приоритет - - Copy address - Копирай адрес - - - Copy label - Копирай име - - - Copy amount - Копирай сума - - - Copy transaction ID - Копирай транзакция с ID - - - Lock unspent - Заключване на неизхарченото - - - Unlock unspent - Отключване на неизхарченото - - - Copy quantity - Копиране на количеството - - - Copy fee - Копиране на данък добавена стойност - - - Copy after fee - Копиране след прилагане на данък добавена стойност - - - Copy bytes - Копиране на байтовете - - - Copy priority - Копиране на приоритет - - - Copy dust - Копирай прахта: - - - Copy change - Копирай рестото - - - highest - Най-висок - - - higher - По-висок - - - high - Висок - - - medium-high - Средно-висок - - - medium - Среден - - - low-medium - Ниско-среден - - - low - Нисък - - - lower - По-нисък - - - lowest - Най-нисък - - - (%1 locked) - (%1 заключен) - - - none - нищо - - - This label turns red if the transaction size is greater than 1000 bytes. - Този етикет става червен, когато размера на транзакцията е по-голяма от 1000 бита. - - - yes - да - - - no - не - - - This means a fee of at least %1 per kB is required. - Това означава че се изисква такса от поне %1 на килобайт. - - - Can vary +/- 1 byte per input. - Може да варира с +-1 байт - - - (no label) - (без име) - - - change from %1 (%2) - ресто от %1 (%2) - - - (change) - (промени) - EditAddressDialog @@ -724,38 +418,6 @@ &Address &Адрес - - New receiving address - Нов адрес за получаване - - - New sending address - Нов адрес за изпращане - - - Edit receiving address - Редактиране на адрес за получаване - - - Edit sending address - Редактиране на адрес за изпращане - - - The entered address "%1" is already in the address book. - Вече има адрес "%1" в списъка с адреси. - - - The entered address "%1" is not a valid Bitcoin address. - "%1" не е валиден Биткоин адрес. - - - Could not unlock wallet. - Отключването на портфейла беше неуспешно. - - - New key generation failed. - Създаването на ключ беше неуспешно. - FreespaceChecker @@ -782,10 +444,6 @@ HelpMessageDialog - - Bitcoin Core - Биткойн ядро - version версия @@ -794,10 +452,6 @@ (%1-bit) (%1-битов) - - About Bitcoin Core - Относно Bitcoin Core - Command-line options Списък с команди @@ -817,14 +471,6 @@ Welcome Добре дошли - - Welcome to Bitcoin Core. - Добре дошли в Биткойн ядрото. - - - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - Тъй като това е първото стартиране на програмата можете да изберете къде Биткон ядрото да запази данните си. - Use the default data directory Използване на директория по подразбиране @@ -833,10 +479,6 @@ Use a custom data directory: Използване на директория ръчно - - Bitcoin Core - Биткойн ядро - Error Грешка @@ -899,10 +541,6 @@ &Network &Мрежа - - Automatically start Bitcoin Core after logging in to the system. - Автоматично стартиране на Bitcoin Core след влизане в системата. - W&allet По&ртфейл @@ -1071,73 +709,6 @@ Скорошни транзакции - - PaymentServer - - URI handling - Справяне с URI - - - Invalid payment address %1 - Невалиден адрес на плащане %1 - - - Payment request rejected - Заявката за плащане беше отхвърлена - - - Payment request network doesn't match client network. - Мрежата от която се извършва заявката за плащане не съвпада с мрежата на клиента. - - - Requested payment amount of %1 is too small (considered dust). - Заявената сума за плащане: %1 е твърде малка (счита се за отпадък) - - - Payment request error - Възникна грешка по време назаявката за плащане - - - Cannot start bitcoin: click-to-pay handler - Биткойн не можe да се стартира: click-to-pay handler - - - Payment request file handling - Файл за справяне със заявки - - - Payment request expired. - Заявката за плащане е изтекла. - - - Invalid payment request. - Невалидна заявка за плащане. - - - Refund from %1 - Възстановяване на сума от %1 - - - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - Заявката за плащане %1 е твърде голям (%2 байта, позволени %3 байта). - - - Error communicating with %1: %2 - Грешка при комуникацията с %1: %2 - - - Bad response from server %1 - Възникна проблем при свързването със сървър %1 - - - Payment acknowledged - Плащането е прието - - - Network request error - Грешка в мрежата по време на заявката - - PeerTableModel @@ -1188,25 +759,6 @@ %1 милисекунда - - QRImageWidget - - &Save Image... - &Запиши изображение... - - - &Copy Image - &Копирай изображение - - - Save QR Code - Запази QR Код - - - PNG Image (*.png) - PNG Изображение (*.png) - - RPCConsole @@ -1337,10 +889,6 @@ Out: Изходящи - - Build date - Дата на създаване - Debug log file Лог файл,съдържащ грешките @@ -1448,18 +996,6 @@ Remove Премахване - - Copy label - Копирай име - - - Copy message - Копиране на съобщението - - - Copy amount - Копирай сума - ReceiveRequestDialog @@ -1479,79 +1015,20 @@ &Save Image... &Запиши изображение... + + + SendCoinsDialog - Request payment to %1 - Изискване на плащане от %1 + Send Coins + Изпращане - Payment information - Данни за плащането + Coin Control Features + Настройки за контрол на монетите - Address - Адрес - - - Amount - Сума - - - Label - Име - - - Message - Съобщение - - - Error encoding URI into QR Code. - Грешка при създаването на QR Code от URI. - - - - RecentRequestsTableModel - - Date - Дата - - - Label - Име - - - Message - Съобщение - - - Amount - Сума - - - (no label) - (без име) - - - (no message) - (без съобщение) - - - (no amount) - (липсва сума) - - - - SendCoinsDialog - - Send Coins - Изпращане - - - Coin Control Features - Настройки за контрол на монетите - - - automatically selected - астоматично избран + automatically selected + астоматично избран Insufficient funds! @@ -1661,86 +1138,6 @@ S&end И&зпрати - - Confirm send coins - Потвърждаване - - - Copy quantity - Копиране на количеството - - - Copy amount - Копирай сума - - - Copy fee - Копиране на данък добавена стойност - - - Copy after fee - Копиране след прилагане на данък добавена стойност - - - Copy bytes - Копиране на байтовете - - - Copy priority - Копиране на приоритет - - - Copy change - Копирай рестото - - - or - или - - - The amount to pay must be larger than 0. - Сумата трябва да е по-голяма от 0. - - - The amount exceeds your balance. - Сумата надвишава текущия баланс - - - The total exceeds your balance when the %1 transaction fee is included. - Сумата при добавяне на данък добавена стойност по %1 транзакцията надвишава сумата по вашата сметка. - - - Transaction creation failed! - Грешка при създаването на транзакция! - - - Payment request expired. - Заявката за плащане е изтекла. - - - Warning: Invalid Bitcoin address - Внимание: Невалиден Биткойн адрес - - - (no label) - (без име) - - - Warning: Unknown change address - Внимание:Неизвестен адрес за промяна - - - Copy dust - Копирай прахта: - - - Are you sure you want to send? - Наистина ли искате да изпратите? - - - added as transaction fee - добавено като такса за транзакция - SendCoinsEntry @@ -1752,10 +1149,6 @@ Pay &To: Плати &На: - - Enter a label for this address to add it to your address book - Въведете име за този адрес, за да го добавите в списъка с адреси - &Label: &Име: @@ -1799,10 +1192,6 @@ ShutdownWindow - - Bitcoin Core is shutting down... - Биткойн ядрото се изключва... - Do not shut down the computer until this window disappears. Не изключвайте компютъра докато този прозорец не изчезне. @@ -1870,69 +1259,9 @@ Verify &Message Потвърди &съобщението - - Click "Sign Message" to generate signature - Натиснете "Подписване на съобщение" за да създадете подпис - - - The entered address is invalid. - Въведеният адрес е невалиден. - - - Please check the address and try again. - Моля проверете адреса и опитайте отново. - - - The entered address does not refer to a key. - Въведеният адрес не може да се съпостави с валиден ключ. - - - Wallet unlock was cancelled. - Отключването на портфейла беше отменено. - - - Private key for the entered address is not available. - Не е наличен частен ключ за въведеният адрес. - - - Message signing failed. - Подписването на съобщение беше неуспешно. - - - Message signed. - Съобщението е подписано. - - - The signature could not be decoded. - Подписът не може да бъде декодиран. - - - Please check the signature and try again. - Проверете подписа и опитайте отново. - - - The signature did not match the message digest. - Подписът не отговаря на комбинацията от съобщение и адрес. - - - Message verification failed. - Проверката на съобщението беше неуспешна. - - - Message verified. - Съобщението е потвърдено. - - + SplashScreen - - Bitcoin Core - Биткойн ядро - - - The Bitcoin Core developers - Разработчици на Bitcoin Core - [testnet] [testnet] @@ -1945,438 +1274,16 @@ Килобайта в секунда - - TransactionDesc - - Open until %1 - Подлежи на промяна до %1 - - - conflicted - припокриващ се - - - %1/offline - %1/офлайн - - - %1/unconfirmed - %1/непотвърдени - - - %1 confirmations - включена в %1 блока - - - Status - Статус - - - Date - Дата - - - Source - Източник - - - Generated - Издадени - - - From - От - - - To - За - - - own address - собствен адрес - - - watch-only - само гледане - - - label - име - - - Credit - Кредит - - - not accepted - не е приет - - - Debit - Дебит - - - Total debit - Общ дълг - - - Total credit - Общ дълг - - - Transaction fee - Такса - - - Net amount - Нетна сума - - - Message - Съобщение - - - Comment - Коментар - - - Transaction ID - ID - - - Merchant - Търговец - - - 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. - Генерираните монети трябва да отлежат %1 блока преди да могат да бъдат похарчени. Когато генерираш блока, той се разпространява в мрежата, за да се добави в блок-веригата. Ако не успее да се добави във веригата, неговия статус ще се стане "неприет" и няма да може да се похарчи. Това е възможно да се случи случайно, ако друг възел генерира блок няколко секунди след твоя. - - - Debug information - Информация за грешките - - - Transaction - Транзакция - - - Amount - Сума - - - true - true - - - false - false - - - , has not been successfully broadcast yet - , все още не е изпратено - - - unknown - неизвестен - - TransactionDescDialog - - Transaction details - Транзакция - This pane shows a detailed description of the transaction Описание на транзакцията - - TransactionTableModel - - Date - Дата - - - Type - Тип - - - Immature (%1 confirmations, will be available after %2) - Неплатим (%1 потвърждения, ще бъде платим след %2) - - - Open until %1 - Подлежи на промяна до %1 - - - Confirmed (%1 confirmations) - Потвърдени (%1 потвърждения) - - - This block was not received by any other nodes and will probably not be accepted! - Блокът не е получен от останалите участници и най-вероятно няма да бъде одобрен. - - - Generated but not accepted - Генерирана, но отхвърлена от мрежата - - - Offline - Извън линия - - - Label - Име - - - Unconfirmed - Непотвърдено - - - Confirming (%1 of %2 recommended confirmations) - Потвърждаване (%1 от %2 препоръчвани потвърждения) - - - Conflicted - Конфликтно - - - Received with - Получени - - - Received from - Получен от - - - Sent to - Изпратени на - - - Payment to yourself - Плащане към себе си - - - Mined - Емитирани - - - watch-only - само гледане - - - (n/a) - (n/a) - - - Transaction status. Hover over this field to show number of confirmations. - Състояние на транзакцията. Задръжте върху това поле за брой потвърждения. - - - Date and time that the transaction was received. - Дата и час на получаване на транзакцията. - - - Type of transaction. - Вид транзакция. - - - Amount removed from or added to balance. - Сума извадена или добавена към баланса. - - - - TransactionView - - All - Всички - - - Today - Днес - - - This week - Тази седмица - - - This month - Този месец - - - Last month - Предния месец - - - This year - Тази година - - - Range... - От - до... - - - Received with - Получени - - - Sent to - Изпратени на - - - To yourself - Собствени - - - Mined - Емитирани - - - Other - Други - - - Enter address or label to search - Търсене по адрес или име - - - Min amount - Минимална сума - - - Copy address - Копирай адрес - - - Copy label - Копирай име - - - Copy amount - Копирай сума - - - Copy transaction ID - Копирай транзакция с ID - - - Edit label - Редактирай име - - - Show transaction details - Подробности за транзакцията - - - Export Transaction History - Изнасяне историята на транзакциите - - - Watch-only - само гледане - - - Exporting Failed - Грешка при изнасянето - - - Exporting Successful - Изнасянето е успешна - - - The transaction history was successfully saved to %1. - Историята с транзакциите беше успешно запазена в %1. - - - Comma separated file (*.csv) - CSV файл (*.csv) - - - Confirmed - Потвърдени - - - Date - Дата - - - Type - Тип - - - Label - Име - - - Address - Адрес - - - ID - ИД - - - Range: - От: - - - to - до - - UnitDisplayStatusBarControl - - WalletFrame - - No wallet has been loaded. - Няма зареден портфейл. - - - - WalletModel - - Send Coins - Изпращане - - - - WalletView - - &Export - Изнеси - - - Export the data in the current tab to a file - Запишете данните от текущия раздел във файл - - - Backup Wallet - Запазване на портфейла - - - Wallet Data (*.dat) - Информация за портфейла (*.dat) - - - Backup Failed - Неуспешно запазване на портфейла - - - There was an error trying to save the wallet data to %1. - Възникна грешка при запазването на информацията за портфейла в %1. - - - The wallet data was successfully saved to %1. - Информацията за портфейла беше успешно запазена в %1. - - - Backup Successful - Успешно запазване на портфейла - - bitcoin-core @@ -2399,6 +1306,10 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Приемайте връзки отвън.(по подразбиране:1 в противен случай -proxy или -connect) + + Bitcoin Core + Биткойн ядро + Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. Сложете в бял списък пиъри,свързващи се от дадената интернет маска или айпи адрес.Може да бъде заложено неколкократно. @@ -2443,34 +1354,14 @@ Wallet options: Настройки на портфейла: - - Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) - Заложете броя на нишки за генерация на монети ако е включено(-1 = всички ядра, по подразбиране: %d) - Connect through SOCKS5 proxy Свързване чрез SOCKS5 прокси - - Copyright (C) 2009-%i The Bitcoin Core Developers - Всички права запазени (C) 2009-%i Доставчиците на Биткойн - Information Информация - - Invalid amount for -maxtxfee=<amount>: '%s' - Невалидна сума за -maxtxfee=<amount>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Невалидна сума за -minrelaytxfee=<amount>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - Невалидна сума за -mintxfee=<amount>: '%s' - Send trace/debug info to console instead of debug.log file Изпрати локализиращата или дебъг информацията към конзолата, вместо файлът debug.log @@ -2503,22 +1394,10 @@ Password for JSON-RPC connections Парола за JSON-RPC връзките - - This help message - Това помощно съобщение - Loading addresses... Зареждане на адреси... - - Error loading wallet.dat: Wallet corrupted - Грешка при зареждане на wallet.dat: портфейлът е повреден - - - Error loading wallet.dat - Грешка при зареждане на wallet.dat - Invalid -proxy address: '%s' Невалиден -proxy address: '%s' @@ -2535,10 +1414,6 @@ Specify pid file (default: %s) Задайте pid файл(по подразбиране: %s) - - Invalid amount for -paytxfee=<amount>: '%s' - Невалидна сума за -paytxfee=<amount>: '%s' - Insufficient funds Недостатъчно средства diff --git a/src/qt/locale/bitcoin_bg_BG.ts b/src/qt/locale/bitcoin_bg_BG.ts deleted file mode 100644 index 353f6d7715ec9..0000000000000 --- a/src/qt/locale/bitcoin_bg_BG.ts +++ /dev/null @@ -1,157 +0,0 @@ - - - AddressBookPage - - Right-click to edit address or label - Клик с десен бутон на мишката за промяна на адрес или етикет - - - Create a new address - Създай нов адрес - - - &New - Нов - - - &Copy - Копирай - - - C&lose - Затвори - - - - AddressTableModel - - - AskPassphraseDialog - - - BanTableModel - - - BitcoinGUI - - Bitcoin Core - Биткойн ядро - - - &About Bitcoin Core - За Биткойн ядрото - - - - ClientModel - - - CoinControlDialog - - - EditAddressDialog - - - FreespaceChecker - - - HelpMessageDialog - - Bitcoin Core - Биткойн ядро - - - About Bitcoin Core - За Биткойн ядрото - - - - Intro - - Bitcoin Core - Биткойн ядро - - - - OpenURIDialog - - - OptionsDialog - - - OverviewPage - - - PaymentServer - - - PeerTableModel - - - QObject - - - QRImageWidget - - - RPCConsole - - - ReceiveCoinsDialog - - - ReceiveRequestDialog - - - RecentRequestsTableModel - - - SendCoinsDialog - - - SendCoinsEntry - - - ShutdownWindow - - - SignVerifyMessageDialog - - - SplashScreen - - Bitcoin Core - Биткойн ядро - - - - TrafficGraphWidget - - - TransactionDesc - - - TransactionDescDialog - - - TransactionTableModel - - - TransactionView - - - UnitDisplayStatusBarControl - - - WalletFrame - - - WalletModel - - - WalletView - - - bitcoin-core - - \ No newline at end of file diff --git a/src/qt/locale/bitcoin_bs.ts b/src/qt/locale/bitcoin_bs.ts deleted file mode 100644 index a186842201f02..0000000000000 --- a/src/qt/locale/bitcoin_bs.ts +++ /dev/null @@ -1,169 +0,0 @@ - - - AddressBookPage - - - AddressTableModel - - - AskPassphraseDialog - - - BanTableModel - - - BitcoinGUI - - Bitcoin - Bitcoin - - - Bitcoin Core - Bitcoin Jezrga - - - - ClientModel - - - CoinControlDialog - - - EditAddressDialog - - - FreespaceChecker - - - HelpMessageDialog - - Bitcoin Core - Bitcoin Jezrga - - - - Intro - - Bitcoin Core - Bitcoin Jezrga - - - - OpenURIDialog - - - OptionsDialog - - - OverviewPage - - - PaymentServer - - - PeerTableModel - - - QObject - - - QRImageWidget - - - RPCConsole - - - ReceiveCoinsDialog - - - ReceiveRequestDialog - - - RecentRequestsTableModel - - - SendCoinsDialog - - - SendCoinsEntry - - Alt+A - Alt+A - - - Alt+P - Alt+P - - - - ShutdownWindow - - - SignVerifyMessageDialog - - Alt+A - Alt+A - - - Alt+P - Alt+P - - - - SplashScreen - - Bitcoin Core - Bitcoin Jezrga - - - - TrafficGraphWidget - - - TransactionDesc - - - TransactionDescDialog - - - TransactionTableModel - - - TransactionView - - All - Sve - - - Today - Danas - - - This month - Ovaj mjesec - - - Last month - Prošli mjesec - - - This year - Ove godine - - - - UnitDisplayStatusBarControl - - - WalletFrame - - - WalletModel - - - WalletView - - - bitcoin-core - - \ No newline at end of file diff --git a/src/qt/locale/bitcoin_ca.ts b/src/qt/locale/bitcoin_ca.ts index 8bc9281f1daaa..3eb384868ed43 100644 --- a/src/qt/locale/bitcoin_ca.ts +++ b/src/qt/locale/bitcoin_ca.ts @@ -25,10 +25,6 @@ C&lose &Tanca - - &Copy Address - &Copia l'adreça - Delete the currently selected address from the list Elimina l'adreça sel·leccionada actualment de la llista @@ -45,73 +41,6 @@ &Delete &Elimina - - Choose the address to send coins to - Trieu una adreça on voleu enviar monedes - - - Choose the address to receive coins with - Trieu l'adreça on voleu rebre monedes - - - C&hoose - T&ria - - - Sending addresses - S'estan enviant les adreces - - - Receiving addresses - S'estan rebent les adreces - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Aquestes són les vostres adreces de Bitcoin per enviar els pagaments. Sempre reviseu l'import i l'adreça del destinatari abans de transferir monedes. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Aquestes són les vostres adreces Bitcoin per rebre pagaments. Es recomana utilitzar una adreça nova de recepció per a cada transacció. - - - Copy &Label - Copia l'&etiqueta - - - &Edit - &Edita - - - Export Address List - Exporta la llista d'adreces - - - Comma separated file (*.csv) - Fitxer de separació amb comes (*.csv) - - - Exporting Failed - L'exportació ha fallat - - - There was an error trying to save the address list to %1. Please try again. - S'ha produït un error en desar la llista d'adreces a %1. Torneu-ho a provar. - - - - AddressTableModel - - Label - Etiqueta - - - Address - Adreça - - - (no label) - (sense etiqueta) - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase Repetiu la nova contrasenya - - Encrypt wallet - Encripta el moneder - - - This operation needs your wallet passphrase to unlock the wallet. - Aquesta operació requereix la contrasenya del moneder per a desbloquejar-lo. - - - Unlock wallet - Desbloqueja el moneder - - - This operation needs your wallet passphrase to decrypt the wallet. - Aquesta operació requereix la contrasenya del moneder per desencriptar-lo. - - - Decrypt wallet - Desencripta el moneder - - - Change passphrase - Canvia la contrasenya - - - Confirm wallet encryption - Confirma l'encriptació del moneder - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Avís: si encripteu el vostre moneder i perdeu la contrasenya, <b>PERDREU TOTS ELS VOSTRES BITCOINS</b>! - - - Are you sure you wish to encrypt your wallet? - Esteu segur que voleu encriptar el vostre moneder? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Ara es tancarà el Bitcoin Core per finalitzar el procés d'encriptació. Tingueu present que encriptar el vostre moneder no garanteix que les vostres bitcoins no puguin ser robades per programari maliciós que infecti l'ordinador. - - - 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. - IMPORTANT: Tota copia de seguretat que hàgiu realitzat hauria de ser reemplaçada pel, recentment generat, fitxer encriptat del moneder. - - - Warning: The Caps Lock key is on! - Avís: Les lletres majúscules estan activades! - - - Wallet encrypted - Moneder encriptat - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Introduïu la contrasenya nova al moneder.<br/>Utilitzeu una contrasenya de <b>deu o més caràcters aleatoris</b>, o <b>vuit o més paraules</b>. - - - Enter the old passphrase and new passphrase to the wallet. - Introduïu la contrasenya antiga i la contrasenya nova al moneder. - - - Wallet encryption failed - L'encriptació del moneder ha fallat - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - L'encriptació del moneder ha fallat per un error intern. El moneder no ha estat encriptat. - - - The supplied passphrases do not match. - La contrasenya introduïda no coincideix. - - - Wallet unlock failed - El desbloqueig del moneder ha fallat - - - The passphrase entered for the wallet decryption was incorrect. - La contrasenya introduïda per a desencriptar el moneder és incorrecta. - - - Wallet decryption failed - La desencriptació del moneder ha fallat - - - Wallet passphrase was successfully changed. - La contrasenya del moneder ha estat modificada correctament. - BanTableModel @@ -305,14 +146,6 @@ Open &URI... Obre un &URI... - - Bitcoin Core client - Client del Bitcoin Core - - - Importing blocks from disk... - S'estan important els blocs del disc... - Reindexing blocks on disk... S'estan reindexant els blocs al disc... @@ -357,10 +190,6 @@ &Receive &Rep - - Show information about Bitcoin Core - Mostra informació del Bitcoin Core - &Show / Hide &Mostra / Amaga @@ -397,22 +226,10 @@ Tabs toolbar Barra d'eines de les pestanyes - - Bitcoin Core - Nucli de Bitcoin - Request payments (generates QR codes and bitcoin: URIs) Sol·licita pagaments (genera codis QR i bitcoin: URI) - - &About Bitcoin Core - &Quant al Bitcoin Core - - - Modify configuration options for Bitcoin Core - Modifica les opcions de configuració del Bitcoin Core - Show the list of used sending addresses and labels Mostra la llista d'adreces d'enviament i etiquetes utilitzades @@ -429,10 +246,6 @@ &Command-line options Opcions de la &línia d'ordres - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Mostra el missatge d'ajuda del Bitcoin Core per obtenir una llista amb les possibles opcions de línia d'ordres de Bitcoin - %n active connection(s) to Bitcoin network %n connexió activa a la xarxa Bitcoin%n connexions actives a la xarxa Bitcoin @@ -544,13 +357,6 @@ El moneder està <b>encriptat</b> i actualment <b>bloquejat</b> - - ClientModel - - Network Alert - Alerta de xarxa - - CoinControlDialog @@ -629,150 +435,6 @@ Priority Prioritat - - Copy address - Copiar adreça - - - Copy label - Copiar etiqueta - - - Copy amount - Copia l'import - - - Copy transaction ID - Copiar ID de transacció - - - Lock unspent - Bloqueja sense gastar - - - Unlock unspent - Desbloqueja sense gastar - - - Copy quantity - Copia la quantitat - - - Copy fee - Copia la comissió - - - Copy after fee - Copia la comissió posterior - - - Copy bytes - Copia els bytes - - - Copy priority - Copia la prioritat - - - Copy dust - Copia el polsim - - - Copy change - Copia el canvi - - - highest - El més alt - - - higher - Més alt - - - high - Alt - - - medium-high - mig-alt - - - medium - mig - - - low-medium - baix-mig - - - low - baix - - - lower - més baix - - - lowest - el més baix - - - (%1 locked) - (%1 bloquejada) - - - none - cap - - - This label turns red if the transaction size is greater than 1000 bytes. - Aquesta etiqueta es torna en vermell si la transacció és superior a 1000 bytes. - - - This label turns red if the priority is smaller than "medium". - Aquesta etiqueta es torna en vermell si la propietat és inferior que la «mitjana». - - - This label turns red if any recipient receives an amount smaller than %1. - Aquesta etiqueta es torna vermella si el destinatari rep un import inferior de %1. - - - Can vary +/- %1 satoshi(s) per input. - Pot variar +/- %1 satoshi(s) per entrada. - - - yes - - - - no - no - - - This means a fee of at least %1 per kB is required. - Això comporta una comissió d'almenys %1 per kB. - - - Can vary +/- 1 byte per input. - Pot variar +/- 1 byte per entrada. - - - Transactions with higher priority are more likely to get included into a block. - Les transaccions amb una major prioritat són més propenses a ser incloses en un bloc. - - - (no label) - (sense etiqueta) - - - change from %1 (%2) - canvia de %1 (%2) - - - (change) - (canvia) - EditAddressDialog @@ -796,38 +458,6 @@ &Address &Adreça - - New receiving address - Nova adreça de recepció. - - - New sending address - Nova adreça d'enviament - - - Edit receiving address - Edita les adreces de recepció - - - Edit sending address - Edita les adreces d'enviament - - - The entered address "%1" is already in the address book. - L'adreça introduïda «%1» ja és present a la llibreta d'adreces. - - - The entered address "%1" is not a valid Bitcoin address. - L'adreça introduïda «%1» no és una adreça de Bitcoin vàlida. - - - Could not unlock wallet. - No s'ha pogut desbloquejar el moneder. - - - New key generation failed. - Ha fallat la generació d'una nova clau. - FreespaceChecker @@ -854,10 +484,6 @@ HelpMessageDialog - - Bitcoin Core - Nucli de Bitcoin - version versió @@ -866,10 +492,6 @@ (%1-bit) (%1-bit) - - About Bitcoin Core - Quant al Bitcoin Core - Command-line options Opcions de línia d'ordres @@ -906,29 +528,13 @@ Show splash screen on startup (default: %u) Mostra la pantalla de benvinguda a l'inici (per defecte: %u) - - Reset all settings changes made over the GUI - Reinicialitza tots els canvis de configuració fets des de la interfície gràfica - - + Intro Welcome Us donem la benviguda - - Welcome to Bitcoin Core. - Us donem la benvinguda al Bitcoin Core. - - - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - Atès que és la primera vegada que executeu el programa, podeu triar on emmagatzemarà el Bitcoin Core les dades. - - - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - El Bitcoin Core descarregarà i emmagatzemarà una còpia de la cadena de blocs de Bitcoin. Com a mínim s'emmagatzemaran %1 GB de dades en aquest directori, que seguiran creixent gradualment. També s'hi emmagatzemarà el moneder. - Use the default data directory Utilitza el directori de dades per defecte @@ -937,10 +543,6 @@ Use a custom data directory: Utilitza un directori de dades personalitzat: - - Bitcoin Core - Nucli de Bitcoin - Error: Specified data directory "%1" cannot be created. Error: el directori de dades «%1» especificat no pot ser creat. @@ -976,10 +578,6 @@ Select payment request file Selecciona un fitxer de sol·licitud de pagament - - Select payment request file to open - Selecciona el fitxer de sol·licitud de pagament per obrir - OptionsDialog @@ -1019,10 +617,6 @@ 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. Minimitza en comptes de sortir de l'aplicació quan la finestra es tanca. Quan s'habilita aquesta opció l'aplicació es tancara només quan se selecciona Surt del menú. - - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - La interfície d'usuari pot definir-se des d'aquí. El paràmetre tindrà efecte després de reiniciar el Bitcoin Core. - 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 |. URL de terceres parts (p. ex. explorador de blocs) que apareix en la pestanya de transaccions com elements del menú contextual. %s en l'URL es reemplaçat pel resum de la transacció. Diferents URL estan separades per una barra vertical |. @@ -1047,14 +641,6 @@ &Network &Xarxa - - Automatically start Bitcoin Core after logging in to the system. - Inicia el Bitcoin Core automàticament després d'iniciar una sessió en el sistema. - - - &Start Bitcoin Core on system login - &Inicia el Bitcoin Core en inciar el sistema - (0 = auto, <0 = leave that many cores free) (0 = auto, <0 = deixa tants nuclis lliures) @@ -1284,190 +870,80 @@ - PaymentServer + PeerTableModel - URI handling - Gestió d'URI + User Agent + Agent d'usuari - Invalid payment address %1 - Adreça de pagament no vàlida %1 + Node/Service + Node/Servei - Payment request rejected - La sol·licitud de pagament s'ha rebutjat + Ping Time + Temps de ping + + + QObject - Payment request network doesn't match client network. - La xarxa de la sol·licitud de pagament no coincideix amb la xarxa del client. + Amount + Import - Payment request is not initialized. - La sol·licitud de pagament no està inicialitzada. + Enter a Bitcoin address (e.g. %1) + Introduïu una adreça de Bitcoin (p. ex. %1) - Requested payment amount of %1 is too small (considered dust). - L'import de pagament sol·licitat %1 és massa petit (es considera polsim). + %1 d + %1 d - Payment request error - Error en la sol·licitud de pagament + %1 h + %1 h - Cannot start bitcoin: click-to-pay handler - No es pot iniciar bitcoin: gestor clica-per-pagar + %1 m + %1 m - Payment request fetch URL is invalid: %1 - L'URL de recuperació de la sol·licitud de pagament no és vàlida: %1 + %1 s + %1 s - URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - L'URI no pot ser analitzat! Això pot ser a causa d'una adreça de Bitcoin no vàlida o per paràmetres URI amb mal format. + None + Cap - Payment request file handling - Gestió de fitxers de les sol·licituds de pagament + N/A + N/A - Payment request file cannot be read! This can be caused by an invalid payment request file. - No es pot llegir el fitxer de la sol·licitud de pagament. Això pot ser causat per un fitxer de sol·licitud de pagament no vàlid. + %1 ms + %1 ms + + + RPCConsole - Payment request expired. - La sol·licitud de pagament ha vençut. + Client name + Nom del client - Unverified payment requests to custom payment scripts are unsupported. - No s'accepten sol·licituds de pagament no verificades a scripts de pagament personalitzats. + N/A + N/A - Invalid payment request. - Sol·licitud de pagament no vàlida. + Client version + Versió del client - Refund from %1 - Reemborsament de %1 + &Information + &Informació - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - La sol·licitud de pagament %1 és massa gran (%2 bytes, permès %3 bytes). - - - Error communicating with %1: %2 - Error en comunicar amb %1: %2 - - - Payment request cannot be parsed! - No es pot analitzar la sol·licitud de pagament! - - - Bad response from server %1 - Mala resposta del servidor %1 - - - Payment acknowledged - Pagament reconegut - - - Network request error - Error en la sol·licitud de xarxa - - - - PeerTableModel - - User Agent - Agent d'usuari - - - Node/Service - Node/Servei - - - Ping Time - Temps de ping - - - - QObject - - Amount - Import - - - Enter a Bitcoin address (e.g. %1) - Introduïu una adreça de Bitcoin (p. ex. %1) - - - %1 d - %1 d - - - %1 h - %1 h - - - %1 m - %1 m - - - %1 s - %1 s - - - None - Cap - - - N/A - N/A - - - %1 ms - %1 ms - - - - QRImageWidget - - &Save Image... - De&sa la imatge... - - - &Copy Image - &Copia la imatge - - - Save QR Code - Desa el codi QR - - - PNG Image (*.png) - Imatge PNG (*.png) - - - - RPCConsole - - Client name - Nom del client - - - N/A - N/A - - - Client version - Versió del client - - - &Information - &Informació - - - Debug window - Finestra de depuració + Debug window + Finestra de depuració General @@ -1513,10 +989,6 @@ Memory usage Us de memoria - - Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. - Obre el fitxer de registre de depuració del Bitcoin Core del directori de dades actual. Pot portar uns quants segons per a fitxers de registre grans. - Received Rebut @@ -1633,10 +1105,6 @@ Out: Fora: - - Build date - Data de compilació - Debug log file Fitxer de registre de depuració @@ -1673,10 +1141,6 @@ &Unban Node &Desbandeja el node - - Welcome to the Bitcoin Core RPC console. - Us donem la benviguda a la consola RPC del Bitcoin Core. - Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. Utilitza les fletxes d'amunt i avall per navegar per l'historial, i <b>Ctrl-L<\b> per netejar la pantalla. @@ -1804,18 +1268,6 @@ Remove Esborra - - Copy label - Copia l'etiqueta - - - Copy message - Copia el missatge - - - Copy amount - Copia l'import - ReceiveRequestDialog @@ -1835,73 +1287,6 @@ &Save Image... De&sa la imatge... - - Request payment to %1 - Sol·licita un pagament a %1 - - - Payment information - Informació de pagament - - - URI - URI - - - Address - Adreça - - - Amount - Import - - - Label - Etiqueta - - - Message - Missatge - - - Resulting URI too long, try to reduce the text for label / message. - URI resultant massa llarga, intenta reduir el text per a la etiqueta / missatge - - - Error encoding URI into QR Code. - Error en codificar l'URI en un codi QR. - - - - RecentRequestsTableModel - - Date - Data - - - Label - Etiqueta - - - Message - Missatge - - - Amount - Import - - - (no label) - (sense etiqueta) - - - (no message) - (sense missatge) - - - (no amount) - (sense import) - SendCoinsDialog @@ -2021,14 +1406,6 @@ fast ràpid - - Send as zero-fee transaction if possible - Envia com a transacció de comissió zero si és possible - - - (confirmation may take longer) - (la confirmació pot trigar més temps) - Send to multiple recipients at once Envia a múltiples destinataris al mateix temps @@ -2061,118 +1438,6 @@ S&end E&nvia - - Confirm send coins - Confirma l'enviament de monedes - - - %1 to %2 - %1 a %2 - - - Copy quantity - Copia la quantitat - - - Copy amount - Copia l'import - - - Copy fee - Copia la comissió - - - Copy after fee - Copia la comissió posterior - - - Copy bytes - Copia els bytes - - - Copy priority - Copia la prioritat - - - Copy change - Copia el canvi - - - Total Amount %1 - Import total %1 - - - or - o - - - The amount to pay must be larger than 0. - L'import a pagar ha de ser major que 0. - - - The amount exceeds your balance. - L'import supera el vostre balanç. - - - The total exceeds your balance when the %1 transaction fee is included. - El total excedeix el teu balanç quan s'afegeix la comissió a la transacció %1. - - - Transaction creation failed! - Ha fallat la creació de la transacció! - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - S'ha rebutjat la transacció! Això pot passar si alguna de les monedes del vostre moneder ja s'han gastat; per exemple, si heu fet servir una còpia de seguretat del fitxer wallet.dat i s'haguessin gastat monedes de la còpia però sense marcar-les-hi com a gastades. - - - A fee higher than %1 is considered an absurdly high fee. - Una comissió superior a %1 es considera una comissió absurdament alta. - - - Payment request expired. - La sol·licitud de pagament ha vençut. - - - Pay only the required fee of %1 - Paga només la comissió necessària de %1 - - - Estimated to begin confirmation within %n block(s). - Estimat per començar la confirmació en %n bloc.Estimat per començar la confirmació en %n blocs. - - - The recipient address is not valid. Please recheck. - L'adreça de destinatari no és vàlida. Torneu-la a comprovar. - - - Duplicate address found: addresses should only be used once each. - S'ha trobat una adreça duplicada: cal utilitzar les adreces només un cop cada vegada. - - - Warning: Invalid Bitcoin address - Avís: adreça Bitcoin no vàlida - - - (no label) - (sense etiqueta) - - - Warning: Unknown change address - Avís: adreça de canvi desconeguda - - - Copy dust - Copia el polsim - - - Are you sure you want to send? - Esteu segur que ho voleu enviar? - - - added as transaction fee - S'ha afegit una taxa de transacció - SendCoinsEntry @@ -2184,10 +1449,6 @@ Pay &To: Paga &a: - - Enter a label for this address to add it to your address book - Introduïu una etiqueta per a aquesta adreça per afegir-la a la llibreta d'adreces - &Label: &Etiqueta: @@ -2259,10 +1520,6 @@ ShutdownWindow - - Bitcoin Core is shutting down... - S'està aturant el Bitcoin Core... - Do not shut down the computer until this window disappears. No apagueu l'ordinador fins que no desaparegui aquesta finestra. @@ -2354,598 +1611,72 @@ Reset all verify message fields Neteja tots els camps de verificació de missatge + + + SplashScreen - Click "Sign Message" to generate signature - Feu clic a «Signa el missatge» per a generar una signatura + [testnet] + [testnet] + + + TrafficGraphWidget - The entered address is invalid. - L'adreça introduïda no és vàlida. + KB/s + KB/s + + + TransactionDescDialog - Please check the address and try again. - Comproveu l'adreça i torneu-ho a provar. + This pane shows a detailed description of the transaction + Aquest panell mostra una descripció detallada de la transacció + + + UnitDisplayStatusBarControl - The entered address does not refer to a key. - L'adreça introduïda no referencia a cap clau. + Unit to show amounts in. Click to select another unit. + Unitat en què mostrar els imports. Feu clic per seleccionar una altra unitat. + + + bitcoin-core - Wallet unlock was cancelled. - El desbloqueig del moneder ha estat cancelat. + Options: + Opcions: - Private key for the entered address is not available. - La clau privada per a la adreça introduïda no està disponible. + Specify data directory + Especifica el directori de dades - Message signing failed. - La signatura del missatge ha fallat. + Connect to a node to retrieve peer addresses, and disconnect + Connecta al node per obtenir les adreces de les connexions, i desconnecta - Message signed. - Missatge signat. + Specify your own public address + Especifiqueu la vostra adreça pública - The signature could not be decoded. - La signatura no s'ha pogut descodificar. + Accept command line and JSON-RPC commands + Accepta la línia d'ordres i ordres JSON-RPC - Please check the signature and try again. - Comproveu la signatura i torneu-ho a provar. + If <category> is not supplied or if <category> = 1, output all debugging information. + Si no es proporciona <category> o si <category> = 1, treu a la sortida tota la informació de depuració. - The signature did not match the message digest. - La signatura no coincideix amb el resum del missatge. + Prune configured below the minimum of %d MiB. Please use a higher number. + Poda configurada per sota el mínim de %d MiB. Utilitzeu un nombre superior. - Message verification failed. - Ha fallat la verificació del missatge. + Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node) + Poda: la darrera sincronització del moneder va més enllà de les dades podades. Cal que activeu -reindex (baixeu tota la cadena de blocs de nou en cas de node podat) - Message verified. - Missatge verificat. - - - - SplashScreen - - Bitcoin Core - Bitcoin Core - - - The Bitcoin Core developers - Els desenvolupadors del Bitcoin Core - - - [testnet] - [testnet] - - - - TrafficGraphWidget - - KB/s - KB/s - - - - TransactionDesc - - Open until %1 - Obert fins %1 - - - conflicted - en conflicte - - - %1/offline - %1/fora de línia - - - %1/unconfirmed - %1/sense confirmar - - - %1 confirmations - %1 confirmacions - - - Status - Estat - - - , broadcast through %n node(s) - , difusió a través de %n node, difusió a través de %n nodes - - - Date - Data - - - Source - Font - - - Generated - Generat - - - From - Des de - - - To - A - - - own address - Adreça pròpia - - - watch-only - només lectura - - - label - etiqueta - - - Credit - Crèdit - - - matures in %n more block(s) - disponible en %n bloc mésdisponibles en %n blocs més - - - not accepted - no acceptat - - - Debit - Dèbit - - - Total debit - Dèbit total - - - Total credit - Crèdit total - - - Transaction fee - Comissió de transacció - - - Net amount - Import net - - - Message - Missatge - - - Comment - Comentar - - - Transaction ID - ID de transacció - - - Merchant - Mercader - - - 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. - Les monedes generades han de madurar %1 blocs abans de poder ser gastades. Quan genereu aquest bloc, es farà saber a la xarxa per tal d'afegir-lo a la cadena de blocs. Si no pot fer-se lloc a la cadena, el seu estat canviarà a «no acceptat» i no es podrà gastar. Això pot passar ocasionalment si un altre node genera un bloc en un marge de segons respecte al vostre. - - - Debug information - Informació de depuració - - - Transaction - Transacció - - - Inputs - Entrades - - - Amount - Import - - - true - cert - - - false - fals - - - , has not been successfully broadcast yet - , encara no ha estat emès correctement - - - Open for %n more block(s) - Obre per %n bloc mésObre per %n blocs més - - - unknown - desconegut - - - - TransactionDescDialog - - Transaction details - Detall de la transacció - - - This pane shows a detailed description of the transaction - Aquest panell mostra una descripció detallada de la transacció - - - - TransactionTableModel - - Date - Data - - - Type - Tipus - - - Immature (%1 confirmations, will be available after %2) - Immadur (%1 confirmacions, serà disponible després de %2) - - - Open for %n more block(s) - Obre per %n bloc mésObre per %n blocs més - - - Open until %1 - Obert fins %1 - - - Confirmed (%1 confirmations) - Confirmat (%1 confirmacions) - - - This block was not received by any other nodes and will probably not be accepted! - Aquest bloc no ha estat rebut per cap altre node i probablement no serà acceptat! - - - Generated but not accepted - Generat però no acceptat - - - Offline - Fora de línia - - - Label - Etiqueta - - - Unconfirmed - Sense confirmar - - - Confirming (%1 of %2 recommended confirmations) - Confirmant (%1 de %2 confirmacions recomanades) - - - Conflicted - En conflicte - - - Received with - Rebut amb - - - Received from - Rebut de - - - Sent to - Enviat a - - - Payment to yourself - Pagament a un mateix - - - Mined - Minat - - - watch-only - només lectura - - - (n/a) - (n/a) - - - Transaction status. Hover over this field to show number of confirmations. - Estat de la transacció. Desplaceu-vos sobre aquest camp per mostrar el nombre de confirmacions. - - - Date and time that the transaction was received. - Data i hora en que la transacció va ser rebuda. - - - Type of transaction. - Tipus de transacció. - - - Whether or not a watch-only address is involved in this transaction. - Si està implicada o no una adreça només de lectura en la transacció. - - - User-defined intent/purpose of the transaction. - Intenció/propòsit de la transacció definida per l'usuari. - - - Amount removed from or added to balance. - Import extret o afegit del balanç. - - - - TransactionView - - All - Tot - - - Today - Avui - - - This week - Aquesta setmana - - - This month - Aquest mes - - - Last month - El mes passat - - - This year - Enguany - - - Range... - Rang... - - - Received with - Rebut amb - - - Sent to - Enviat a - - - To yourself - A un mateix - - - Mined - Minat - - - Other - Altres - - - Enter address or label to search - Introduïu una adreça o una etiqueta per cercar - - - Min amount - Import mínim - - - Copy address - Copia l'adreça - - - Copy label - Copiar etiqueta - - - Copy amount - Copia l'import - - - Copy transaction ID - Copiar ID de transacció - - - Copy raw transaction - Copia la transacció crua - - - Edit label - Editar etiqueta - - - Show transaction details - Mostra detalls de la transacció - - - Export Transaction History - Exporta l'historial de transacció - - - Watch-only - Només de lectura - - - Exporting Failed - L'exportació ha fallat - - - There was an error trying to save the transaction history to %1. - S'ha produït un error en provar de desar l'historial de transacció a %1. - - - Exporting Successful - Exportació amb èxit - - - The transaction history was successfully saved to %1. - L'historial de transaccions s'ha desat correctament a %1. - - - Comma separated file (*.csv) - Fitxer separat per comes (*.csv) - - - Confirmed - Confirmat - - - Date - Data - - - Type - Tipus - - - Label - Etiqueta - - - Address - Adreça - - - ID - ID - - - Range: - Rang: - - - to - a - - - - UnitDisplayStatusBarControl - - Unit to show amounts in. Click to select another unit. - Unitat en què mostrar els imports. Feu clic per seleccionar una altra unitat. - - - - WalletFrame - - No wallet has been loaded. - No s'ha carregat cap moneder. - - - - WalletModel - - Send Coins - Envia monedes - - - - WalletView - - &Export - &Exporta - - - Export the data in the current tab to a file - Exporta les dades de la pestanya actual a un fitxer - - - Backup Wallet - Còpia de seguretat del moneder - - - Wallet Data (*.dat) - Dades del moneder (*.dat) - - - Backup Failed - Ha fallat la còpia de seguretat - - - There was an error trying to save the wallet data to %1. - S'ha produït un error en provar de desar les dades del moneder a %1. - - - The wallet data was successfully saved to %1. - S'han desat les dades del moneder correctament a %1. - - - Backup Successful - La còpia de seguretat s'ha realitzat correctament - - - - bitcoin-core - - Options: - Opcions: - - - Specify data directory - Especifica el directori de dades - - - Connect to a node to retrieve peer addresses, and disconnect - Connecta al node per obtenir les adreces de les connexions, i desconnecta - - - Specify your own public address - Especifiqueu la vostra adreça pública - - - Accept command line and JSON-RPC commands - Accepta la línia d'ordres i ordres JSON-RPC - - - If <category> is not supplied or if <category> = 1, output all debugging information. - Si no es proporciona <category> o si <category> = 1, treu a la sortida tota la informació de depuració. - - - Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s) - Comissions totals màximes (en %s) per utilitzar en una única transacció de moneder; definir-ne una massa baixa pot interrompre les transaccions més grans (per defecte: %s) - - - Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. - Comproveu que la data i hora de l'ordinador són correctes! Si el vostre rellotge no té l'hora correcta, el Bitcoin Core no funcionarà adequadament. - - - Prune configured below the minimum of %d MiB. Please use a higher number. - Poda configurada per sota el mínim de %d MiB. Utilitzeu un nombre superior. - - - Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node) - Poda: la darrera sincronització del moneder va més enllà de les dades podades. Cal que activeu -reindex (baixeu tota la cadena de blocs de nou en cas de node podat) - - - Reduce storage requirements by pruning (deleting) old blocks. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, >%u = target size in MiB to use for block files) - Reduïu els requisits d'emmagatzematge podant (suprimint) els blocs antics. Aquest mode és incompatible amb -txindex i -rescan. Avís: la reversió d'aquest paràmetre implica haver de tornar a baixar la cadena de blocs sencera. (per defecte: 0 = inhabilita la poda de blocs, >%u = mida objectiu en MiB per utilitzar en els fitxers de blocs) + Reduce storage requirements by pruning (deleting) old blocks. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, >%u = target size in MiB to use for block files) + Reduïu els requisits d'emmagatzematge podant (suprimint) els blocs antics. Aquest mode és incompatible amb -txindex i -rescan. Avís: la reversió d'aquest paràmetre implica haver de tornar a baixar la cadena de blocs sencera. (per defecte: 0 = inhabilita la poda de blocs, >%u = mida objectiu en MiB per utilitzar en els fitxers de blocs) Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again. @@ -2975,6 +1706,10 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Accepta connexions de fora (per defecte: 1 si no -proxy o -connect) + + Bitcoin Core + Bitcoin Core + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. -fallbackfee és molt elevat. Aquesta és la comissió de transacció que podeu pagar quan les estimacions de comissions no estan disponibles. @@ -3003,10 +1738,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Aquesta és una versió de pre-llançament - utilitza-la sota la teva responsabilitat - No usar per a minería o aplicacions de compra-venda - - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - No es pot enllaçar %s a aquest ordinador. El Bitcoin Core probablement ja estigui executant-s'hi. - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) AVÍS: s'ha generat un nombre anòmalament alt de blocs, %d blocs rebuts en les darreres %d hores (se n'esperaven %d) @@ -3023,10 +1754,6 @@ Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Avís: sembla que no estem plenament d'acord amb els nostres iguals! Podria caler que actualitzar l'aplicació, o potser que ho facin altres nodes. - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Avís: el fitxer wallet.dat és corrupte, dades rescatades! L'arxiu wallet.dat original ha estat desat com wallet.{estampa_temporal}.bak al directori %s; si el teu balanç o transaccions son incorrectes hauries de restaurar-lo de un backup. - Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. Afegeix a la llista blanca els iguals que es connecten de la màscara de xarxa o adreça IP donada. Es pot especificar moltes vegades. @@ -3147,10 +1874,6 @@ Wallet options: Opcions de moneder: - - You need to rebuild the database using -reindex to change -txindex - Cal que reconstruïu la base de dades fent servir -reindex per canviar -txindex - 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 Permet les connexions JSON-RPC d'una font específica. Vàlid per a <ip> són una IP individual (p. ex., 1.2.3.4), una xarxa / màscara de xarxa (p. ex., 1.2.3.4/255.255.255.0) o una xarxa/CIDR (p. ex., 1.2.3.4/24). Es pot especificar aquesta opció moltes vegades @@ -3163,10 +1886,6 @@ Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces) Vincula a l'adreça donada per a escoltar les connexions JSON-RPC. Feu servir la notació [host]:port per a IPv6. Aquesta opció pot ser especificada moltes vegades (per defecte: vincula a totes les interfícies) - - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - No es pot obtenir un bloqueig del directori de dades %s. El Bitcoin Core probablement ja s'estigui executant. - Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) Crea fitxers nous amb els permisos per defecte del sistema, en comptes de l'umask 077 (només efectiu amb la funcionalitat de moneder inhabilitada) @@ -3207,10 +1926,6 @@ Set maximum size of high-priority/low-fee transactions in bytes (default: %d) Defineix la mida màxima de transaccions d'alta prioritat / baixa comissió en bytes (per defecte: %d) - - Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) - Defineix el nombre de fils per a la generació de moneda si està habilitat (-1 = tots els nuclis, per defecte: %d) - The transaction amount is too small to send after the fee has been deducted L'import de la transacció és massa petit per enviar-la després que se'n dedueixi la comissió @@ -3235,26 +1950,10 @@ Accept public REST requests (default: %u) Accepta sol·licituds REST públiques (per defecte: %u) - - Activating best chain... - S'està activant la millor cadena... - - - Cannot resolve -whitebind address: '%s' - No es pot resoldre l'adreça -whitebind: «%s» - Connect through SOCKS5 proxy Connecta a través del proxy SOCKS5 - - Copyright (C) 2009-%i The Bitcoin Core Developers - Copyright (C) 2009-%i Els desenvolupadors del Bitcoin Core - - - Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - Error en carregar wallet.dat: el moneder requereix una versió més nova del Bitcoin core - Error reading from database, shutting down. Error en llegir la base de dades, tancant. @@ -3263,22 +1962,6 @@ Information &Informació - - Initialization sanity check failed. Bitcoin Core is shutting down. - Ha fallat la inicialització de la comprovació de validesa. El Bitcoin Core s'està aturant. - - - Invalid amount for -maxtxfee=<amount>: '%s' - Import no vàlid per a -maxtxfee=<amount>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Import no vàlid per a -minrelaytxfee=<amount>: «%s» - - - Invalid amount for -mintxfee=<amount>: '%s' - Import no vàlid per a -mintxfee=<amount>: «%s» - Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) Import no vàlid per a -paytxfee=<amount>: «%s» (ha de ser com a mínim %s) @@ -3303,14 +1986,6 @@ RPC server options: Opcions del servidor RPC: - - Rebuild block chain index from current blk000??.dat files on startup - Reconstrueix l'índex de la cadena de blocs dels fitxers blk000??.dat actuals a l'inici. - - - Receive and display P2P network alerts (default: %u) - Rep i mostra avisos de la xarxa P2P (per defecte: %u) - Send trace/debug info to console instead of debug.log file Envia informació de traça/depuració a la consola en comptes del fitxer debug.log @@ -3363,10 +2038,6 @@ Username for JSON-RPC connections Nom d'usuari per a connexions JSON-RPC - - Wallet needed to be rewritten: restart Bitcoin Core to complete - Cal reescriure el moneder: reiniceu el Bitcoin Core per completar-ho. - Warning Avís @@ -3375,10 +2046,6 @@ Zapping all transactions from wallet... Se suprimeixen totes les transaccions del moneder... - - wallet.dat corrupt, salvage failed - El fitxer wallet.data és corrupte. El rescat de les dades ha fallat - Password for JSON-RPC connections Contrasenya per a connexions JSON-RPC @@ -3387,10 +2054,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) Executa l'ordre quan el millor bloc canviï (%s en cmd es reemplaça per un resum de bloc) - - This help message - Aquest misatge d'ajuda - Allow DNS lookups for -addnode, -seednode and -connect Permet consultes DNS per a -addnode, -seednode i -connect @@ -3399,10 +2062,6 @@ Loading addresses... S'estan carregant les adreces... - - Error loading wallet.dat: Wallet corrupted - Error en carregar wallet.dat: Moneder corrupte - (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) (1 = manté les metadades de les tx, p. ex., propietari del compte i informació de sol·licitud del pagament, 2 = prescindeix de les metadades de les tx) @@ -3435,14 +2094,6 @@ Always query for peer addresses via DNS lookup (default: %u) Demana sempre les adreces dels iguals a través de consultes DNS (per defecte: %u) - - Error loading wallet.dat - Error en carregar wallet.dat - - - Generate coins (default: %u) - Genera monedes (per defecte: %u) - How many blocks to check at startup (default: %u, 0 = all) Quants blocs per comprovar a l'inici (per defecte: %u, 0 = tots) @@ -3527,18 +2178,6 @@ Unknown network specified in -onlynet: '%s' Xarxa desconeguda especificada a -onlynet: '%s' - - Cannot resolve -bind address: '%s' - No es pot resoldre l'adreça -bind: '%s' - - - Cannot resolve -externalip address: '%s' - No es pot resoldre l'adreça -externalip: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - Import no vàlid per a -paytxfee=<amount>: «%s» - Insufficient funds Balanç insuficient diff --git a/src/qt/locale/bitcoin_ca@valencia.ts b/src/qt/locale/bitcoin_ca@valencia.ts index e5744fcbbf9b4..1fdf0249a5b73 100644 --- a/src/qt/locale/bitcoin_ca@valencia.ts +++ b/src/qt/locale/bitcoin_ca@valencia.ts @@ -25,10 +25,6 @@ C&lose &Tanca - - &Copy Address - &Copia l'adreça - Delete the currently selected address from the list Elimina l'adreça sel·leccionada actualment de la llista @@ -45,73 +41,6 @@ &Delete &Elimina - - Choose the address to send coins to - Trieu una adreça on voleu enviar monedes - - - Choose the address to receive coins with - Trieu l'adreça on voleu rebre monedes - - - C&hoose - T&ria - - - Sending addresses - S'estan enviant les adreces - - - Receiving addresses - S'estan rebent les adreces - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Estes són les vostres adreces de Bitcoin per enviar els pagaments. Sempre reviseu l'import i l'adreça del destinatari abans de transferir monedes. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Estes són les vostres adreces Bitcoin per rebre pagaments. Es recomana utilitzar una adreça nova de recepció per a cada transacció. - - - Copy &Label - Copia l'&etiqueta - - - &Edit - &Edita - - - Export Address List - Exporta la llista d'adreces - - - Comma separated file (*.csv) - Fitxer de separació amb comes (*.csv) - - - Exporting Failed - L'exportació ha fallat - - - There was an error trying to save the address list to %1. Please try again. - S'ha produït un error en guardar la llista d'adreces a %1. Torneu-ho a provar. - - - - AddressTableModel - - Label - Etiqueta - - - Address - Adreça - - - (no label) - (sense etiqueta) - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase Repetiu la nova contrasenya - - Encrypt wallet - Encripta el moneder - - - This operation needs your wallet passphrase to unlock the wallet. - Esta operació requereix la contrasenya del moneder per a desbloquejar-lo. - - - Unlock wallet - Desbloqueja el moneder - - - This operation needs your wallet passphrase to decrypt the wallet. - Esta operació requereix la contrasenya del moneder per desencriptar-lo. - - - Decrypt wallet - Desencripta el moneder - - - Change passphrase - Canvia la contrasenya - - - Confirm wallet encryption - Confirma l'encriptació del moneder - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Avís: si encripteu el vostre moneder i perdeu la contrasenya, <b>PERDREU TOTS ELS VOSTRES BITCOINS</b>! - - - Are you sure you wish to encrypt your wallet? - Esteu segur que voleu encriptar el vostre moneder? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Ara es tancarà el Bitcoin Core per finalitzar el procés d'encriptació. Tingueu present que encriptar el vostre moneder no garanteix que les vostres bitcoins no puguen ser robades per programari maliciós que infecti l'ordinador. - - - 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. - IMPORTANT: Tota copia de seguretat que hàgeu realitzat hauria de ser reemplaçada pel, recentment generat, fitxer encriptat del moneder. - - - Warning: The Caps Lock key is on! - Avís: Les lletres majúscules estan activades! - - - Wallet encrypted - Moneder encriptat - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Introduïu la contrasenya nova al moneder.<br/>Utilitzeu una contrasenya de <b>deu o més caràcters aleatoris</b>, o <b>vuit o més paraules</b>. - - - Enter the old passphrase and new passphrase to the wallet. - Introduïu la contrasenya antiga i la contrasenya nova al moneder. - - - Wallet encryption failed - L'encriptació del moneder ha fallat - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - L'encriptació del moneder ha fallat per un error intern. El moneder no ha estat encriptat. - - - The supplied passphrases do not match. - La contrasenya introduïda no coincideix. - - - Wallet unlock failed - El desbloqueig del moneder ha fallat - - - The passphrase entered for the wallet decryption was incorrect. - La contrasenya introduïda per a desencriptar el moneder és incorrecta. - - - Wallet decryption failed - La desencriptació del moneder ha fallat - - - Wallet passphrase was successfully changed. - La contrasenya del moneder ha estat modificada correctament. - BanTableModel @@ -297,14 +138,6 @@ Open &URI... Obri un &URI... - - Bitcoin Core client - Client del Bitcoin Core - - - Importing blocks from disk... - S'estan important els blocs del disc... - Reindexing blocks on disk... S'estan reindexant els blocs al disc... @@ -349,10 +182,6 @@ &Receive &Rep - - Show information about Bitcoin Core - Mostra informació del Bitcoin Core - &Show / Hide &Mostra / Amaga @@ -389,22 +218,10 @@ Tabs toolbar Barra d'eines de les pestanyes - - Bitcoin Core - Nucli de Bitcoin - Request payments (generates QR codes and bitcoin: URIs) Sol·licita pagaments (genera codis QR i bitcoin: URI) - - &About Bitcoin Core - &Quant al Bitcoin Core - - - Modify configuration options for Bitcoin Core - Modifica les opcions de configuració del Bitcoin Core - Show the list of used sending addresses and labels Mostra la llista d'adreces d'enviament i etiquetes utilitzades @@ -421,10 +238,6 @@ &Command-line options Opcions de la &línia d'ordes - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Mostra el missatge d'ajuda del Bitcoin Core per obtindre una llista amb les possibles opcions de línia d'ordes de Bitcoin - %n active connection(s) to Bitcoin network %n connexió activa a la xarxa Bitcoin%n connexions actives a la xarxa Bitcoin @@ -536,13 +349,6 @@ El moneder està <b>encriptat</b> i actualment <b>bloquejat</b> - - ClientModel - - Network Alert - Alerta de xarxa - - CoinControlDialog @@ -621,150 +427,6 @@ Priority Prioritat - - Copy address - Copiar adreça - - - Copy label - Copiar etiqueta - - - Copy amount - Copia l'import - - - Copy transaction ID - Copiar ID de transacció - - - Lock unspent - Bloqueja sense gastar - - - Unlock unspent - Desbloqueja sense gastar - - - Copy quantity - Copia la quantitat - - - Copy fee - Copia la comissió - - - Copy after fee - Copia la comissió posterior - - - Copy bytes - Copia els bytes - - - Copy priority - Copia la prioritat - - - Copy dust - Copia el polsim - - - Copy change - Copia el canvi - - - highest - El més alt - - - higher - Més alt - - - high - Alt - - - medium-high - mig-alt - - - medium - mig - - - low-medium - baix-mig - - - low - baix - - - lower - més baix - - - lowest - el més baix - - - (%1 locked) - (%1 bloquejada) - - - none - cap - - - This label turns red if the transaction size is greater than 1000 bytes. - Esta etiqueta es torna en roig si la transacció és superior a 1000 bytes. - - - This label turns red if the priority is smaller than "medium". - Esta etiqueta es torna en roig si la propietat és inferior que la «mitjana». - - - This label turns red if any recipient receives an amount smaller than %1. - Esta etiqueta es torna roja si el destinatari rep un import inferior de %1. - - - Can vary +/- %1 satoshi(s) per input. - Pot variar +/- %1 satoshi(s) per entrada. - - - yes - - - - no - no - - - This means a fee of at least %1 per kB is required. - Això comporta una comissió d'almenys %1 per kB. - - - Can vary +/- 1 byte per input. - Pot variar +/- 1 byte per entrada. - - - Transactions with higher priority are more likely to get included into a block. - Les transaccions amb una major prioritat són més propenses a ser incloses en un bloc. - - - (no label) - (sense etiqueta) - - - change from %1 (%2) - canvia de %1 (%2) - - - (change) - (canvia) - EditAddressDialog @@ -788,38 +450,6 @@ &Address &Adreça - - New receiving address - Nova adreça de recepció. - - - New sending address - Nova adreça d'enviament - - - Edit receiving address - Edita les adreces de recepció - - - Edit sending address - Edita les adreces d'enviament - - - The entered address "%1" is already in the address book. - L'adreça introduïda «%1» ja és present a la llibreta d'adreces. - - - The entered address "%1" is not a valid Bitcoin address. - L'adreça introduïda «%1» no és una adreça de Bitcoin vàlida. - - - Could not unlock wallet. - No s'ha pogut desbloquejar el moneder. - - - New key generation failed. - Ha fallat la generació d'una nova clau. - FreespaceChecker @@ -846,10 +476,6 @@ HelpMessageDialog - - Bitcoin Core - Nucli de Bitcoin - version versió @@ -858,10 +484,6 @@ (%1-bit) (%1-bit) - - About Bitcoin Core - Quant al Bitcoin Core - Command-line options Opcions de línia d'ordes @@ -881,18 +503,6 @@ Welcome Vos donem la benviguda - - Welcome to Bitcoin Core. - Vos donem la benvinguda al Bitcoin Core. - - - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - Atès que és la primera vegada que executeu el programa, podeu triar on emmagatzemarà el Bitcoin Core les dades. - - - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - El Bitcoin Core descarregarà i emmagatzemarà una còpia de la cadena de blocs de Bitcoin. Com a mínim s'emmagatzemaran %1 GB de dades en este directori, que seguiran creixent gradualment. També s'hi emmagatzemarà el moneder. - Use the default data directory Utilitza el directori de dades per defecte @@ -901,10 +511,6 @@ Use a custom data directory: Utilitza un directori de dades personalitzat: - - Bitcoin Core - Nucli de Bitcoin - Error: Specified data directory "%1" cannot be created. Error: el directori de dades «%1» especificat no pot ser creat. @@ -940,10 +546,6 @@ Select payment request file Selecciona un fitxer de sol·licitud de pagament - - Select payment request file to open - Selecciona el fitxer de sol·licitud de pagament per obrir - OptionsDialog @@ -983,10 +585,6 @@ 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. Minimitza en comptes d'eixir de l'aplicació quan la finestra es tanca. Quan s'habilita esta opció l'aplicació es tancara només quan se selecciona Ix del menú. - - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - La interfície d'usuari pot definir-se des d'ací. El paràmetre tindrà efecte després de reiniciar el Bitcoin Core. - 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 |. URL de terceres parts (p. ex. explorador de blocs) que apareix en la pestanya de transaccions com elements del menú contextual. %s en l'URL es reemplaçat pel resum de la transacció. Diferents URL estan separades per una barra vertical |. @@ -1011,14 +609,6 @@ &Network &Xarxa - - Automatically start Bitcoin Core after logging in to the system. - Inicia el Bitcoin Core automàticament després d'iniciar una sessió en el sistema. - - - &Start Bitcoin Core on system login - &Inicia el Bitcoin Core en inciar el sistema - (0 = auto, <0 = leave that many cores free) (0 = auto, <0 = deixa tants nuclis lliures) @@ -1224,198 +814,88 @@ - PaymentServer + PeerTableModel - URI handling - Gestió d'URI + User Agent + Agent d'usuari - Invalid payment address %1 - Adreça de pagament no vàlida %1 + Node/Service + Node/Servei - Payment request rejected - La sol·licitud de pagament s'ha rebutjat + Ping Time + Temps de ping + + + QObject - Payment request network doesn't match client network. - La xarxa de la sol·licitud de pagament no coincideix amb la xarxa del client. + Amount + Import - Payment request is not initialized. - La sol·licitud de pagament no està inicialitzada. + Enter a Bitcoin address (e.g. %1) + Introduïu una adreça de Bitcoin (p. ex. %1) - Requested payment amount of %1 is too small (considered dust). - L'import de pagament sol·licitat %1 és massa petit (es considera polsim). + %1 d + %1 d - Payment request error - Error en la sol·licitud de pagament + %1 h + %1 h - Cannot start bitcoin: click-to-pay handler - No es pot iniciar bitcoin: gestor clica-per-pagar + %1 m + %1 m - Payment request fetch URL is invalid: %1 - L'URL de recuperació de la sol·licitud de pagament no és vàlida: %1 + %1 s + %1 s - URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - L'URI no pot ser analitzat! Això pot ser a causa d'una adreça de Bitcoin no vàlida o per paràmetres URI amb mal format. + None + Cap - Payment request file handling - Gestió de fitxers de les sol·licituds de pagament + N/A + N/A - Payment request file cannot be read! This can be caused by an invalid payment request file. - No es pot llegir el fitxer de la sol·licitud de pagament. Això pot ser causat per un fitxer de sol·licitud de pagament no vàlid. + %1 ms + %1 ms + + + RPCConsole - Payment request expired. - La sol·licitud de pagament ha vençut. + Client name + Nom del client - Unverified payment requests to custom payment scripts are unsupported. - No s'accepten sol·licituds de pagament no verificades a scripts de pagament personalitzats. + N/A + N/A - Invalid payment request. - Sol·licitud de pagament no vàlida. + Client version + Versió del client - Refund from %1 - Reemborsament de %1 + &Information + &Informació - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - La sol·licitud de pagament %1 és massa gran (%2 bytes, permés %3 bytes). + Debug window + Finestra de depuració - Error communicating with %1: %2 - Error en comunicar amb %1: %2 + General + General - Payment request cannot be parsed! - No es pot analitzar la sol·licitud de pagament! - - - Bad response from server %1 - Mala resposta del servidor %1 - - - Payment acknowledged - Pagament reconegut - - - Network request error - Error en la sol·licitud de xarxa - - - - PeerTableModel - - User Agent - Agent d'usuari - - - Node/Service - Node/Servei - - - Ping Time - Temps de ping - - - - QObject - - Amount - Import - - - Enter a Bitcoin address (e.g. %1) - Introduïu una adreça de Bitcoin (p. ex. %1) - - - %1 d - %1 d - - - %1 h - %1 h - - - %1 m - %1 m - - - %1 s - %1 s - - - None - Cap - - - N/A - N/A - - - %1 ms - %1 ms - - - - QRImageWidget - - &Save Image... - &Guarda la imatge... - - - &Copy Image - &Copia la imatge - - - Save QR Code - Guarda el codi QR - - - PNG Image (*.png) - Imatge PNG (*.png) - - - - RPCConsole - - Client name - Nom del client - - - N/A - N/A - - - Client version - Versió del client - - - &Information - &Informació - - - Debug window - Finestra de depuració - - - General - General - - - Using BerkeleyDB version - Utilitzant BerkeleyDB versió + Using BerkeleyDB version + Utilitzant BerkeleyDB versió Startup time @@ -1441,10 +921,6 @@ Current number of blocks Nombre de blocs actuals - - Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. - Obri el fitxer de registre de depuració del Bitcoin Core del directori de dades actual. Pot portar uns quants segons per a fitxers de registre grans. - Received Rebut @@ -1533,10 +1009,6 @@ Out: Fora: - - Build date - Data de compilació - Debug log file Fitxer de registre de depuració @@ -1545,10 +1017,6 @@ Clear console Neteja la consola - - Welcome to the Bitcoin Core RPC console. - Vos donem la benviguda a la consola RPC del Bitcoin Core. - Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. Utilitza les fletxes d'amunt i avall per navegar per l'historial, i <b>Ctrl-L<\b> per netejar la pantalla. @@ -1672,18 +1140,6 @@ Remove Esborra - - Copy label - Copia l'etiqueta - - - Copy message - Copia el missatge - - - Copy amount - Copia l'import - ReceiveRequestDialog @@ -1703,73 +1159,6 @@ &Save Image... &Guarda la imatge... - - Request payment to %1 - Sol·licita un pagament a %1 - - - Payment information - Informació de pagament - - - URI - URI - - - Address - Adreça - - - Amount - Import - - - Label - Etiqueta - - - Message - Missatge - - - Resulting URI too long, try to reduce the text for label / message. - URI resultant massa llarga, intenta reduir el text per a la etiqueta / missatge - - - Error encoding URI into QR Code. - Error en codificar l'URI en un codi QR. - - - - RecentRequestsTableModel - - Date - Data - - - Label - Etiqueta - - - Message - Missatge - - - Amount - Import - - - (no label) - (sense etiqueta) - - - (no message) - (sense missatge) - - - (no amount) - (sense import) - SendCoinsDialog @@ -1807,954 +1196,320 @@ Priority: - Prioritat: - - - Fee: - Comissió: - - - After Fee: - Comissió posterior: - - - Change: - Canvi: - - - If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address. - Si s'activa això, però l'adreça de canvi està buida o bé no és vàlida, el canvi s'enviarà a una adreça generada de nou. - - - Custom change address - Personalitza l'adreça de canvi - - - Transaction Fee: - Comissió de transacció - - - Choose... - Tria... - - - collapse fee-settings - redueix els paràmetres de comissió - - - per kilobyte - per kilobyte - - - If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte. - Si la comissió personalitzada es defineix a 1000 satoshis i la transacció és de només 250 bytes, llavors «per kilobyte» només es paguen 250 satoshis en una comissió, mentre que amb la de «total com a mínim» es pagarien 1000 satoshis. Per a transaccions superiors al kilobyte, en tots dos casos es paga per kilobyte. - - - Hide - Amaga - - - total at least - total com a mínim - - - Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process. - No hi ha cap problema en pagar només la comissió mínima sempre que hi haja menys volum de transacció que espai en els blocs. Però tingueu present que això pot acabar en una transacció que mai es confirme una vegada hi haja més demanda de transaccions de bitcoins que la xarxa puga processar. - - - (read the tooltip) - (llegiu l'indicador de funció) - - - Recommended: - Recomanada: - - - Custom: - Personalitzada: - - - (Smart fee not initialized yet. This usually takes a few blocks...) - (No s'ha inicialitzat encara la comissió intel·ligent. Normalment pren uns pocs blocs...) - - - Confirmation time: - Temps de confirmació: - - - normal - normal - - - fast - ràpid - - - Send as zero-fee transaction if possible - Envia com a transacció de comissió zero si és possible - - - (confirmation may take longer) - (la confirmació pot trigar més temps) - - - Send to multiple recipients at once - Envia a múltiples destinataris al mateix temps - - - Add &Recipient - Afig &destinatari - - - Clear all fields of the form. - Netejar tots els camps del formulari. - - - Dust: - Polsim: - - - Clear &All - Neteja-ho &tot - - - Balance: - Balanç: - - - Confirm the send action - Confirma l'acció d'enviament - - - S&end - E&nvia - - - Confirm send coins - Confirma l'enviament de monedes - - - %1 to %2 - %1 a %2 - - - Copy quantity - Copia la quantitat - - - Copy amount - Copia l'import - - - Copy fee - Copia la comissió - - - Copy after fee - Copia la comissió posterior - - - Copy bytes - Copia els bytes - - - Copy priority - Copia la prioritat - - - Copy change - Copia el canvi - - - or - o - - - The amount to pay must be larger than 0. - L'import a pagar ha de ser major que 0. - - - The amount exceeds your balance. - L'import supera el vostre balanç. - - - The total exceeds your balance when the %1 transaction fee is included. - El total excedeix el teu balanç quan s'afig la comissió a la transacció %1. - - - Transaction creation failed! - Ha fallat la creació de la transacció! - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - S'ha rebutjat la transacció! Això pot passar si alguna de les monedes del vostre moneder ja s'han gastat; per exemple, si heu fet servir una còpia de seguretat del fitxer wallet.dat i s'hagueren gastat monedes de la còpia però sense marcar-les-hi com a gastades. - - - A fee higher than %1 is considered an absurdly high fee. - Una comissió superior a %1 es considera una comissió absurdament alta. - - - Payment request expired. - La sol·licitud de pagament ha vençut. - - - Estimated to begin confirmation within %n block(s). - Estimat per començar la confirmació en %n bloc.Estimat per començar la confirmació en %n blocs. - - - The recipient address is not valid. Please recheck. - L'adreça de destinatari no és vàlida. Torneu-la a comprovar. - - - Duplicate address found: addresses should only be used once each. - S'ha trobat una adreça duplicada: cal utilitzar les adreces només un cop cada vegada. - - - Warning: Invalid Bitcoin address - Avís: adreça Bitcoin no vàlida - - - (no label) - (sense etiqueta) - - - Warning: Unknown change address - Avís: adreça de canvi desconeguda - - - Copy dust - Copia el polsim - - - Are you sure you want to send? - Esteu segur que ho voleu enviar? - - - added as transaction fee - S'ha afegit una taxa de transacció - - - - SendCoinsEntry - - A&mount: - Q&uantitat: - - - Pay &To: - Paga &a: - - - Enter a label for this address to add it to your address book - Introduïu una etiqueta per a esta adreça per afegir-la a la llibreta d'adreces - - - &Label: - &Etiqueta: - - - Choose previously used address - Trieu una adreça feta servir anteriorment - - - This is a normal payment. - Això és un pagament normal. - - - The Bitcoin address to send the payment to - L'adreça Bitcoin on enviar el pagament - - - Alt+A - Alta+A - - - Paste address from clipboard - Apegar adreça del porta-retalls - - - Alt+P - Alt+P - - - Remove this entry - Elimina esta entrada - - - 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. - La comissió es deduirà de l'import que s'enviarà. El destinatari rebrà menys bitcoins que les que introduïu al camp d'import. Si se seleccionen múltiples destinataris, la comissió es dividirà per igual. - - - S&ubtract fee from amount - S&ubstreu la comissió de l'import - - - Message: - Missatge: - - - This is an unauthenticated payment request. - Esta és una sol·licitud de pagament no autenticada. - - - This is an authenticated payment request. - Esta és una sol·licitud de pagament autenticada. - - - Enter a label for this address to add it to the list of used addresses - Introduïu una etiqueta per a esta adreça per afegir-la a la llista d'adreces utilitzades - - - 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. - Un missatge que s'ha adjuntat al bitcoin: URI que s'emmagatzemarà amb la transacció per a la vostra referència. Nota: el missatge no s'enviarà a través de la xarxa Bitcoin. - - - Pay To: - Paga a: - - - Memo: - Memo: - - - - ShutdownWindow - - Bitcoin Core is shutting down... - S'està parant el Bitcoin Core... - - - Do not shut down the computer until this window disappears. - No apagueu l'ordinador fins que no desaparegui esta finestra. - - - - SignVerifyMessageDialog - - Signatures - Sign / Verify a Message - Signatures - Signa / verifica un missatge - - - &Sign Message - &Signa el missatge - - - 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. - Podeu signar missatges/acords amb les vostres adreces per provar que rebeu les bitcoins que s'hi envien. Aneu amb compte no signar res que siga vague o aleatori, perquè en alguns atacs de suplantació es pot provar que hi signeu la vostra identitat. Només signeu aquelles declaracions completament detallades en què hi esteu d'acord. - - - The Bitcoin address to sign the message with - L'adreça Bitcoin amb què signar el missatge - - - Choose previously used address - Tria les adreces fetes servir amb anterioritat - - - Alt+A - Alt+A - - - Paste address from clipboard - Apega l'adreça del porta-retalls - - - Alt+P - Alt+P - - - Enter the message you want to sign here - Introduïu ací el missatge que voleu signar - - - Signature - Signatura - - - Copy the current signature to the system clipboard - Copia la signatura actual al porta-retalls del sistema - - - Sign the message to prove you own this Bitcoin address - Signa el missatge per provar que ets propietari d'esta adreça Bitcoin - - - Sign &Message - Signa el &missatge - - - Reset all sign message fields - Neteja tots els camps de clau - - - Clear &All - Neteja-ho &tot - - - &Verify Message - &Verifica el missatge - - - 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! - Introduïu l'adreça del receptor, el missatge (assegureu-vos de copiar els salts de línia, espais, tabuladors, etc. exactament) i signatura de sota per verificar el missatge. Tingueu cura de no llegir més en la signatura del que està al missatge signat, per evitar ser enganyat per un atac d'home-en-el-mig. Tingueu en compte que això només demostra que la part que signa rep amb l'adreça, i no es pot provar l'enviament de qualsevol transacció! - - - The Bitcoin address the message was signed with - L'adreça Bitcoin amb què va ser signat el missatge - - - Verify the message to ensure it was signed with the specified Bitcoin address - Verificar el missatge per assegurar-se que ha estat signat amb una adreça Bitcoin específica - - - Verify &Message - Verifica el &missatge - - - Reset all verify message fields - Neteja tots els camps de verificació de missatge - - - Click "Sign Message" to generate signature - Feu clic a «Signa el missatge» per a generar una signatura - - - The entered address is invalid. - L'adreça introduïda no és vàlida. - - - Please check the address and try again. - Comproveu l'adreça i torneu-ho a provar. - - - The entered address does not refer to a key. - L'adreça introduïda no referencia a cap clau. - - - Wallet unlock was cancelled. - El desbloqueig del moneder ha estat cancelat. - - - Private key for the entered address is not available. - La clau privada per a la adreça introduïda no està disponible. - - - Message signing failed. - La signatura del missatge ha fallat. - - - Message signed. - Missatge signat. - - - The signature could not be decoded. - La signatura no s'ha pogut descodificar. - - - Please check the signature and try again. - Comproveu la signatura i torneu-ho a provar. - - - The signature did not match the message digest. - La signatura no coincideix amb el resum del missatge. - - - Message verification failed. - Ha fallat la verificació del missatge. - - - Message verified. - Missatge verificat. - - - - SplashScreen - - Bitcoin Core - Bitcoin Core - - - The Bitcoin Core developers - Els desenvolupadors del Bitcoin Core - - - [testnet] - [testnet] - - - - TrafficGraphWidget - - KB/s - KB/s - - - - TransactionDesc - - Open until %1 - Obert fins %1 - - - conflicted - en conflicte - - - %1/offline - %1/fora de línia - - - %1/unconfirmed - %1/sense confirmar - - - %1 confirmations - %1 confirmacions - - - Status - Estat - - - , broadcast through %n node(s) - , difusió a través de %n node, difusió a través de %n nodes - - - Date - Data - - - Source - Font - - - Generated - Generat - - - From - Des de - - - To - A - - - own address - Adreça pròpia - - - watch-only - només lectura - - - label - etiqueta - - - Credit - Crèdit - - - matures in %n more block(s) - madura en %n bloc mésmadura en %n blocs més - - - not accepted - no acceptat - - - Debit - Dèbit - - - Total debit - Dèbit total - - - Total credit - Crèdit total - - - Transaction fee - Comissió de transacció - - - Net amount - Import net - - - Message - Missatge - - - Comment - Comentar - - - Transaction ID - ID de transacció - - - Merchant - Mercader - - - 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. - Les monedes generades han de madurar %1 blocs abans de poder ser gastades. Quan genereu este bloc, es farà saber a la xarxa per tal d'afegir-lo a la cadena de blocs. Si no pot fer-se lloc a la cadena, el seu estat canviarà a «no acceptat» i no es podrà gastar. Això pot passar ocasionalment si un altre node genera un bloc en un marge de segons respecte al vostre. - - - Debug information - Informació de depuració + Prioritat: - Transaction - Transacció + Fee: + Comissió: - Inputs - Entrades + After Fee: + Comissió posterior: - Amount - Import + Change: + Canvi: - true - cert + If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address. + Si s'activa això, però l'adreça de canvi està buida o bé no és vàlida, el canvi s'enviarà a una adreça generada de nou. - false - fals + Custom change address + Personalitza l'adreça de canvi - , has not been successfully broadcast yet - , encara no ha estat emés correctement - - - Open for %n more block(s) - Obri per %n bloc mésObri per %n blocs més + Transaction Fee: + Comissió de transacció - unknown - desconegut + Choose... + Tria... - - - TransactionDescDialog - Transaction details - Detall de la transacció + collapse fee-settings + redueix els paràmetres de comissió - This pane shows a detailed description of the transaction - Este panell mostra una descripció detallada de la transacció + per kilobyte + per kilobyte - - - TransactionTableModel - Date - Data + If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte. + Si la comissió personalitzada es defineix a 1000 satoshis i la transacció és de només 250 bytes, llavors «per kilobyte» només es paguen 250 satoshis en una comissió, mentre que amb la de «total com a mínim» es pagarien 1000 satoshis. Per a transaccions superiors al kilobyte, en tots dos casos es paga per kilobyte. - Type - Tipus + Hide + Amaga - Immature (%1 confirmations, will be available after %2) - Immadur (%1 confirmacions, serà disponible després de %2) - - - Open for %n more block(s) - Obri per %n bloc mésObri per %n blocs més + total at least + total com a mínim - Open until %1 - Obert fins %1 + Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process. + No hi ha cap problema en pagar només la comissió mínima sempre que hi haja menys volum de transacció que espai en els blocs. Però tingueu present que això pot acabar en una transacció que mai es confirme una vegada hi haja més demanda de transaccions de bitcoins que la xarxa puga processar. - Confirmed (%1 confirmations) - Confirmat (%1 confirmacions) + (read the tooltip) + (llegiu l'indicador de funció) - This block was not received by any other nodes and will probably not be accepted! - Este bloc no ha estat rebut per cap altre node i probablement no serà acceptat! + Recommended: + Recomanada: - Generated but not accepted - Generat però no acceptat + Custom: + Personalitzada: - Offline - Fora de línia + (Smart fee not initialized yet. This usually takes a few blocks...) + (No s'ha inicialitzat encara la comissió intel·ligent. Normalment pren uns pocs blocs...) - Label - Etiqueta + Confirmation time: + Temps de confirmació: - Unconfirmed - Sense confirmar + normal + normal - Confirming (%1 of %2 recommended confirmations) - Confirmant (%1 de %2 confirmacions recomanades) + fast + ràpid - Conflicted - En conflicte + Send to multiple recipients at once + Envia a múltiples destinataris al mateix temps - Received with - Rebut amb + Add &Recipient + Afig &destinatari - Received from - Rebut de + Clear all fields of the form. + Netejar tots els camps del formulari. - Sent to - Enviat a + Dust: + Polsim: - Payment to yourself - Pagament a un mateix + Clear &All + Neteja-ho &tot - Mined - Minat + Balance: + Balanç: - watch-only - només lectura + Confirm the send action + Confirma l'acció d'enviament - (n/a) - (n/a) + S&end + E&nvia + + + SendCoinsEntry - Transaction status. Hover over this field to show number of confirmations. - Estat de la transacció. Desplaceu-vos sobre este camp per mostrar el nombre de confirmacions. + A&mount: + Q&uantitat: - Date and time that the transaction was received. - Data i hora en que la transacció va ser rebuda. + Pay &To: + Paga &a: - Type of transaction. - Tipus de transacció. + &Label: + &Etiqueta: - Whether or not a watch-only address is involved in this transaction. - Si està implicada o no una adreça només de lectura en la transacció. + Choose previously used address + Trieu una adreça feta servir anteriorment - User-defined intent/purpose of the transaction. - Intenció/propòsit de la transacció definida per l'usuari. + This is a normal payment. + Això és un pagament normal. - Amount removed from or added to balance. - Import extret o afegit del balanç. + The Bitcoin address to send the payment to + L'adreça Bitcoin on enviar el pagament - - - TransactionView - All - Tot + Alt+A + Alta+A - Today - Hui + Paste address from clipboard + Apegar adreça del porta-retalls - This week - Esta setmana + Alt+P + Alt+P - This month - Este mes + Remove this entry + Elimina esta entrada - Last month - El mes passat + 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. + La comissió es deduirà de l'import que s'enviarà. El destinatari rebrà menys bitcoins que les que introduïu al camp d'import. Si se seleccionen múltiples destinataris, la comissió es dividirà per igual. - This year - Enguany + S&ubtract fee from amount + S&ubstreu la comissió de l'import - Range... - Rang... + Message: + Missatge: - Received with - Rebut amb + This is an unauthenticated payment request. + Esta és una sol·licitud de pagament no autenticada. - Sent to - Enviat a + This is an authenticated payment request. + Esta és una sol·licitud de pagament autenticada. - To yourself - A un mateix + Enter a label for this address to add it to the list of used addresses + Introduïu una etiqueta per a esta adreça per afegir-la a la llista d'adreces utilitzades - Mined - Minat + 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. + Un missatge que s'ha adjuntat al bitcoin: URI que s'emmagatzemarà amb la transacció per a la vostra referència. Nota: el missatge no s'enviarà a través de la xarxa Bitcoin. - Other - Altres + Pay To: + Paga a: - Enter address or label to search - Introduïu una adreça o una etiqueta per cercar + Memo: + Memo: + + + ShutdownWindow - Min amount - Import mínim + Do not shut down the computer until this window disappears. + No apagueu l'ordinador fins que no desaparegui esta finestra. + + + SignVerifyMessageDialog - Copy address - Copia l'adreça + Signatures - Sign / Verify a Message + Signatures - Signa / verifica un missatge - Copy label - Copiar etiqueta + &Sign Message + &Signa el missatge - Copy amount - Copia l'import + 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. + Podeu signar missatges/acords amb les vostres adreces per provar que rebeu les bitcoins que s'hi envien. Aneu amb compte no signar res que siga vague o aleatori, perquè en alguns atacs de suplantació es pot provar que hi signeu la vostra identitat. Només signeu aquelles declaracions completament detallades en què hi esteu d'acord. - Copy transaction ID - Copiar ID de transacció + The Bitcoin address to sign the message with + L'adreça Bitcoin amb què signar el missatge - Edit label - Editar etiqueta + Choose previously used address + Tria les adreces fetes servir amb anterioritat - Show transaction details - Mostra detalls de la transacció + Alt+A + Alt+A - Export Transaction History - Exporta l'historial de transacció + Paste address from clipboard + Apega l'adreça del porta-retalls - Watch-only - Només de lectura + Alt+P + Alt+P - Exporting Failed - L'exportació ha fallat + Enter the message you want to sign here + Introduïu ací el missatge que voleu signar - There was an error trying to save the transaction history to %1. - S'ha produït un error en provar de guardar l'historial de transacció a %1. + Signature + Signatura - Exporting Successful - Exportació amb èxit + Copy the current signature to the system clipboard + Copia la signatura actual al porta-retalls del sistema - The transaction history was successfully saved to %1. - L'historial de transaccions s'ha guardat correctament a %1. + Sign the message to prove you own this Bitcoin address + Signa el missatge per provar que ets propietari d'esta adreça Bitcoin - Comma separated file (*.csv) - Fitxer separat per comes (*.csv) + Sign &Message + Signa el &missatge - Confirmed - Confirmat + Reset all sign message fields + Neteja tots els camps de clau - Date - Data + Clear &All + Neteja-ho &tot - Type - Tipus + &Verify Message + &Verifica el missatge - Label - Etiqueta + 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! + Introduïu l'adreça del receptor, el missatge (assegureu-vos de copiar els salts de línia, espais, tabuladors, etc. exactament) i signatura de sota per verificar el missatge. Tingueu cura de no llegir més en la signatura del que està al missatge signat, per evitar ser enganyat per un atac d'home-en-el-mig. Tingueu en compte que això només demostra que la part que signa rep amb l'adreça, i no es pot provar l'enviament de qualsevol transacció! - Address - Adreça + The Bitcoin address the message was signed with + L'adreça Bitcoin amb què va ser signat el missatge - ID - ID + Verify the message to ensure it was signed with the specified Bitcoin address + Verificar el missatge per assegurar-se que ha estat signat amb una adreça Bitcoin específica - Range: - Rang: + Verify &Message + Verifica el &missatge - to - a + Reset all verify message fields + Neteja tots els camps de verificació de missatge - UnitDisplayStatusBarControl + SplashScreen - Unit to show amounts in. Click to select another unit. - Unitat en què mostrar els imports. Feu clic per seleccionar una altra unitat. + [testnet] + [testnet] - WalletFrame + TrafficGraphWidget - No wallet has been loaded. - No s'ha carregat cap moneder. + KB/s + KB/s - WalletModel + TransactionDescDialog - Send Coins - Envia monedes + This pane shows a detailed description of the transaction + Este panell mostra una descripció detallada de la transacció - WalletView - - &Export - &Exporta - - - Export the data in the current tab to a file - Exporta les dades de la pestanya actual a un fitxer - - - Backup Wallet - Còpia de seguretat del moneder - - - Wallet Data (*.dat) - Dades del moneder (*.dat) - - - Backup Failed - Ha fallat la còpia de seguretat - - - There was an error trying to save the wallet data to %1. - S'ha produït un error en provar de guardar les dades del moneder a %1. - - - The wallet data was successfully saved to %1. - S'han guardat les dades del moneder correctament a %1. - + UnitDisplayStatusBarControl - Backup Successful - La còpia de seguretat s'ha realitzat correctament + Unit to show amounts in. Click to select another unit. + Unitat en què mostrar els imports. Feu clic per seleccionar una altra unitat. @@ -2787,6 +1542,10 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Accepta connexions de fora (per defecte: 1 si no -proxy o -connect) + + Bitcoin Core + Bitcoin Core + Bind to given address and always listen on it. Use [host]:port notation for IPv6 Vincula a una adreça específica i sempre escolta-hi. Utilitza la notació [host]:port per IPv6 @@ -2811,10 +1570,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Esta és una versió de pre-llançament - utilitza-la sota la teva responsabilitat - No usar per a minería o aplicacions de compra-venda - - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - No es pot enllaçar %s a este ordinador. El Bitcoin Core probablement ja estiga executant-s'hi. - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) AVÍS: s'ha generat un nombre anòmalament alt de blocs, %d blocs rebuts en les darreres %d hores (se n'esperaven %d) @@ -2831,10 +1586,6 @@ Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Avís: pareix que no estem plenament d'acord amb els nostres iguals! Podria caldre que actualitzar l'aplicació, o potser que ho facen altres nodes. - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Avís: el fitxer wallet.dat és corrupte, dades rescatades! L'arxiu wallet.dat original ha estat guardat com wallet.{estampa_temporal}.bak al directori %s; si el teu balanç o transaccions son incorrectes hauries de restaurar-lo de un backup. - Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. Afig a la llista blanca els iguals que es connecten de la màscara de xarxa o adreça IP donada. Es pot especificar moltes vegades. @@ -2955,10 +1706,6 @@ Wallet options: Opcions de moneder: - - You need to rebuild the database using -reindex to change -txindex - Cal que reconstruïu la base de dades fent servir -reindex per canviar -txindex - 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 Permet les connexions JSON-RPC d'una font específica. Vàlid per a <ip> són una IP individual (p. ex., 1.2.3.4), una xarxa / màscara de xarxa (p. ex., 1.2.3.4/255.255.255.0) o una xarxa/CIDR (p. ex., 1.2.3.4/24). Es pot especificar esta opció moltes vegades @@ -2971,10 +1718,6 @@ Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces) Vincula a l'adreça donada per a escoltar les connexions JSON-RPC. Feu servir la notació [host]:port per a IPv6. Esta opció pot ser especificada moltes vegades (per defecte: vincula a totes les interfícies) - - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - No es pot obtindre un bloqueig del directori de dades %s. El Bitcoin Core probablement ja s'estiga executant. - Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) Crea fitxers nous amb els permisos per defecte del sistema, en comptes de l'umask 077 (només efectiu amb la funcionalitat de moneder inhabilitada) @@ -3015,10 +1758,6 @@ Set maximum size of high-priority/low-fee transactions in bytes (default: %d) Defineix la mida màxima de transaccions d'alta prioritat / baixa comissió en bytes (per defecte: %d) - - Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) - Defineix el nombre de fils per a la generació de moneda si està habilitat (-1 = tots els nuclis, per defecte: %d) - The transaction amount is too small to send after the fee has been deducted L'import de la transacció és massa petit per enviar-la després que se'n deduïsca la comissió @@ -3043,26 +1782,10 @@ Accept public REST requests (default: %u) Accepta sol·licituds REST públiques (per defecte: %u) - - Activating best chain... - S'està activant la millor cadena... - - - Cannot resolve -whitebind address: '%s' - No es pot resoldre l'adreça -whitebind: «%s» - Connect through SOCKS5 proxy Connecta a través del proxy SOCKS5 - - Copyright (C) 2009-%i The Bitcoin Core Developers - Copyright (C) 2009-%i Els desenvolupadors del Bitcoin Core - - - Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - Error en carregar wallet.dat: el moneder requereix una versió més nova del Bitcoin core - Error reading from database, shutting down. Error en llegir la base de dades, tancant. @@ -3071,22 +1794,6 @@ Information &Informació - - Initialization sanity check failed. Bitcoin Core is shutting down. - Ha fallat la inicialització de la comprovació de validesa. El Bitcoin Core s'està parant. - - - Invalid amount for -maxtxfee=<amount>: '%s' - Import no vàlid per a -maxtxfee=<amount>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Import no vàlid per a -minrelaytxfee=<amount>: «%s» - - - Invalid amount for -mintxfee=<amount>: '%s' - Import no vàlid per a -mintxfee=<amount>: «%s» - Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) Import no vàlid per a -paytxfee=<amount>: «%s» (ha de ser com a mínim %s) @@ -3111,14 +1818,6 @@ RPC server options: Opcions del servidor RPC: - - Rebuild block chain index from current blk000??.dat files on startup - Reconstrueix l'índex de la cadena de blocs dels fitxers blk000??.dat actuals a l'inici. - - - Receive and display P2P network alerts (default: %u) - Rep i mostra avisos de la xarxa P2P (per defecte: %u) - Send trace/debug info to console instead of debug.log file Envia informació de traça/depuració a la consola en comptes del fitxer debug.log @@ -3171,10 +1870,6 @@ Username for JSON-RPC connections Nom d'usuari per a connexions JSON-RPC - - Wallet needed to be rewritten: restart Bitcoin Core to complete - Cal reescriure el moneder: reiniceu el Bitcoin Core per completar-ho. - Warning Avís @@ -3183,10 +1878,6 @@ Zapping all transactions from wallet... Se suprimeixen totes les transaccions del moneder... - - wallet.dat corrupt, salvage failed - El fitxer wallet.data és corrupte. El rescat de les dades ha fallat - Password for JSON-RPC connections Contrasenya per a connexions JSON-RPC @@ -3195,10 +1886,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) Executa l'orde quan el millor bloc canvie (%s en cmd es reemplaça per un resum de bloc) - - This help message - Este misatge d'ajuda - Allow DNS lookups for -addnode, -seednode and -connect Permet consultes DNS per a -addnode, -seednode i -connect @@ -3207,10 +1894,6 @@ Loading addresses... S'estan carregant les adreces... - - Error loading wallet.dat: Wallet corrupted - Error en carregar wallet.dat: Moneder corrupte - (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) (1 = manté les metadades de les tx, p. ex., propietari del compte i informació de sol·licitud del pagament, 2 = prescindeix de les metadades de les tx) @@ -3243,14 +1926,6 @@ Always query for peer addresses via DNS lookup (default: %u) Demana sempre les adreces dels iguals a través de consultes DNS (per defecte: %u) - - Error loading wallet.dat - Error en carregar wallet.dat - - - Generate coins (default: %u) - Genera monedes (per defecte: %u) - How many blocks to check at startup (default: %u, 0 = all) Quants blocs per comprovar a l'inici (per defecte: %u, 0 = tots) @@ -3335,18 +2010,6 @@ Unknown network specified in -onlynet: '%s' Xarxa desconeguda especificada a -onlynet: '%s' - - Cannot resolve -bind address: '%s' - No es pot resoldre l'adreça -bind: '%s' - - - Cannot resolve -externalip address: '%s' - No es pot resoldre l'adreça -externalip: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - Import no vàlid per a -paytxfee=<amount>: «%s» - Insufficient funds Balanç insuficient diff --git a/src/qt/locale/bitcoin_ca_ES.ts b/src/qt/locale/bitcoin_ca_ES.ts index 2c238bb44f34a..30004e10e405a 100644 --- a/src/qt/locale/bitcoin_ca_ES.ts +++ b/src/qt/locale/bitcoin_ca_ES.ts @@ -25,10 +25,6 @@ C&lose &Tanca - - &Copy Address - &Copia l'adreça - Delete the currently selected address from the list Elimina l'adreça sel·leccionada actualment de la llista @@ -45,73 +41,6 @@ &Delete &Elimina - - Choose the address to send coins to - Trieu una adreça on voleu enviar monedes - - - Choose the address to receive coins with - Trieu l'adreça on voleu rebre monedes - - - C&hoose - T&ria - - - Sending addresses - S'estan enviant les adreces - - - Receiving addresses - S'estan rebent les adreces - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Aquestes són les vostres adreces de Bitcoin per enviar els pagaments. Sempre reviseu l'import i l'adreça del destinatari abans de transferir monedes. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Aquestes són les vostres adreces Bitcoin per rebre pagaments. Es recomana utilitzar una adreça nova de recepció per a cada transacció. - - - Copy &Label - Copia l'&etiqueta - - - &Edit - &Edita - - - Export Address List - Exporta la llista d'adreces - - - Comma separated file (*.csv) - Fitxer de separació amb comes (*.csv) - - - Exporting Failed - L'exportació ha fallat - - - There was an error trying to save the address list to %1. Please try again. - S'ha produït un error en desar la llista d'adreces a %1. Torneu-ho a provar. - - - - AddressTableModel - - Label - Etiqueta - - - Address - Adreça - - - (no label) - (sense etiqueta) - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase Repetiu la nova contrasenya - - Encrypt wallet - Encripta el moneder - - - This operation needs your wallet passphrase to unlock the wallet. - Aquesta operació requereix la contrasenya del moneder per a desbloquejar-lo. - - - Unlock wallet - Desbloqueja el moneder - - - This operation needs your wallet passphrase to decrypt the wallet. - Aquesta operació requereix la contrasenya del moneder per desencriptar-lo. - - - Decrypt wallet - Desencripta el moneder - - - Change passphrase - Canvia la contrasenya - - - Confirm wallet encryption - Confirma l'encriptació del moneder - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Avís: si encripteu el vostre moneder i perdeu la contrasenya, <b>PERDREU TOTS ELS VOSTRES BITCOINS</b>! - - - Are you sure you wish to encrypt your wallet? - Esteu segur que voleu encriptar el vostre moneder? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Ara es tancarà el Bitcoin Core per finalitzar el procés d'encriptació. Tingueu present que encriptar el vostre moneder no garanteix que les vostres bitcoins no puguin ser robades per programari maliciós que infecti l'ordinador. - - - 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. - IMPORTANT: Tota copia de seguretat que hàgiu realitzat hauria de ser reemplaçada pel, recentment generat, fitxer encriptat del moneder. - - - Warning: The Caps Lock key is on! - Avís: Les lletres majúscules estan activades! - - - Wallet encrypted - Moneder encriptat - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Introduïu la contrasenya nova al moneder.<br/>Utilitzeu una contrasenya de <b>deu o més caràcters aleatoris</b>, o <b>vuit o més paraules</b>. - - - Enter the old passphrase and new passphrase to the wallet. - Introduïu la contrasenya antiga i la contrasenya nova al moneder. - - - Wallet encryption failed - L'encriptació del moneder ha fallat - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - L'encriptació del moneder ha fallat per un error intern. El moneder no ha estat encriptat. - - - The supplied passphrases do not match. - La contrasenya introduïda no coincideix. - - - Wallet unlock failed - El desbloqueig del moneder ha fallat - - - The passphrase entered for the wallet decryption was incorrect. - La contrasenya introduïda per a desencriptar el moneder és incorrecta. - - - Wallet decryption failed - La desencriptació del moneder ha fallat - - - Wallet passphrase was successfully changed. - La contrasenya del moneder ha estat modificada correctament. - BanTableModel @@ -305,14 +146,6 @@ Open &URI... Obre un &URI... - - Bitcoin Core client - Client del Bitcoin Core - - - Importing blocks from disk... - S'estan important els blocs del disc... - Reindexing blocks on disk... S'estan reindexant els blocs al disc... @@ -357,10 +190,6 @@ &Receive &Rep - - Show information about Bitcoin Core - Mostra informació del Bitcoin Core - &Show / Hide &Mostra / Amaga @@ -397,22 +226,10 @@ Tabs toolbar Barra d'eines de les pestanyes - - Bitcoin Core - Nucli de Bitcoin - Request payments (generates QR codes and bitcoin: URIs) Sol·licita pagaments (genera codis QR i bitcoin: URI) - - &About Bitcoin Core - &Quant al Bitcoin Core - - - Modify configuration options for Bitcoin Core - Modifica les opcions de configuració del Bitcoin Core - Show the list of used sending addresses and labels Mostra la llista d'adreces d'enviament i etiquetes utilitzades @@ -429,10 +246,6 @@ &Command-line options Opcions de la &línia d'ordres - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Mostra el missatge d'ajuda del Bitcoin Core per obtenir una llista amb les possibles opcions de línia d'ordres de Bitcoin - %n active connection(s) to Bitcoin network %n connexió activa a la xarxa Bitcoin%n connexions actives a la xarxa Bitcoin @@ -544,13 +357,6 @@ El moneder està <b>encriptat</b> i actualment <b>bloquejat</b> - - ClientModel - - Network Alert - Alerta de xarxa - - CoinControlDialog @@ -629,150 +435,6 @@ Priority Prioritat - - Copy address - Copiar adreça - - - Copy label - Copiar etiqueta - - - Copy amount - Copia l'import - - - Copy transaction ID - Copiar ID de transacció - - - Lock unspent - Bloqueja sense gastar - - - Unlock unspent - Desbloqueja sense gastar - - - Copy quantity - Copia la quantitat - - - Copy fee - Copia la comissió - - - Copy after fee - Copia la comissió posterior - - - Copy bytes - Copia els bytes - - - Copy priority - Copia la prioritat - - - Copy dust - Copia el polsim - - - Copy change - Copia el canvi - - - highest - El més alt - - - higher - Més alt - - - high - Alt - - - medium-high - mig-alt - - - medium - mig - - - low-medium - baix-mig - - - low - baix - - - lower - més baix - - - lowest - el més baix - - - (%1 locked) - (%1 bloquejada) - - - none - cap - - - This label turns red if the transaction size is greater than 1000 bytes. - Aquesta etiqueta es torna en vermell si la transacció és superior a 1000 bytes. - - - This label turns red if the priority is smaller than "medium". - Aquesta etiqueta es torna en vermell si la propietat és inferior que la «mitjana». - - - This label turns red if any recipient receives an amount smaller than %1. - Aquesta etiqueta es torna vermella si el destinatari rep un import inferior de %1. - - - Can vary +/- %1 satoshi(s) per input. - Pot variar +/- %1 satoshi(s) per entrada. - - - yes - - - - no - no - - - This means a fee of at least %1 per kB is required. - Això comporta una comissió d'almenys %1 per kB. - - - Can vary +/- 1 byte per input. - Pot variar +/- 1 byte per entrada. - - - Transactions with higher priority are more likely to get included into a block. - Les transaccions amb una major prioritat són més propenses a ser incloses en un bloc. - - - (no label) - (sense etiqueta) - - - change from %1 (%2) - canvia de %1 (%2) - - - (change) - (canvia) - EditAddressDialog @@ -796,38 +458,6 @@ &Address &Adreça - - New receiving address - Nova adreça de recepció. - - - New sending address - Nova adreça d'enviament - - - Edit receiving address - Edita les adreces de recepció - - - Edit sending address - Edita les adreces d'enviament - - - The entered address "%1" is already in the address book. - L'adreça introduïda «%1» ja és present a la llibreta d'adreces. - - - The entered address "%1" is not a valid Bitcoin address. - L'adreça introduïda «%1» no és una adreça de Bitcoin vàlida. - - - Could not unlock wallet. - No s'ha pogut desbloquejar el moneder. - - - New key generation failed. - Ha fallat la generació d'una nova clau. - FreespaceChecker @@ -854,10 +484,6 @@ HelpMessageDialog - - Bitcoin Core - Nucli de Bitcoin - version versió @@ -866,10 +492,6 @@ (%1-bit) (%1-bit) - - About Bitcoin Core - Quant al Bitcoin Core - Command-line options Opcions de línia d'ordres @@ -906,29 +528,13 @@ Show splash screen on startup (default: %u) Mostra la pantalla de benvinguda a l'inici (per defecte: %u) - - Reset all settings changes made over the GUI - Reinicialitza tots els canvis de configuració fets des de la interfície gràfica - - + Intro Welcome Us donem la benviguda - - Welcome to Bitcoin Core. - Us donem la benvinguda al Bitcoin Core. - - - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - Atès que és la primera vegada que executeu el programa, podeu triar on emmagatzemarà el Bitcoin Core les dades. - - - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - El Bitcoin Core descarregarà i emmagatzemarà una còpia de la cadena de blocs de Bitcoin. Com a mínim s'emmagatzemaran %1 GB de dades en aquest directori, que seguiran creixent gradualment. També s'hi emmagatzemarà el moneder. - Use the default data directory Utilitza el directori de dades per defecte @@ -937,10 +543,6 @@ Use a custom data directory: Utilitza un directori de dades personalitzat: - - Bitcoin Core - Nucli de Bitcoin - Error: Specified data directory "%1" cannot be created. Error: el directori de dades «%1» especificat no pot ser creat. @@ -976,10 +578,6 @@ Select payment request file Selecciona un fitxer de sol·licitud de pagament - - Select payment request file to open - Selecciona el fitxer de sol·licitud de pagament per obrir - OptionsDialog @@ -1019,10 +617,6 @@ 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. Minimitza en comptes de sortir de l'aplicació quan la finestra es tanca. Quan s'habilita aquesta opció l'aplicació es tancara només quan se selecciona Surt del menú. - - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - La interfície d'usuari pot definir-se des d'aquí. El paràmetre tindrà efecte després de reiniciar el Bitcoin Core. - 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 |. URL de terceres parts (p. ex. explorador de blocs) que apareix en la pestanya de transaccions com elements del menú contextual. %s en l'URL es reemplaçat pel resum de la transacció. Diferents URL estan separades per una barra vertical |. @@ -1047,14 +641,6 @@ &Network &Xarxa - - Automatically start Bitcoin Core after logging in to the system. - Inicia el Bitcoin Core automàticament després d'iniciar una sessió en el sistema. - - - &Start Bitcoin Core on system login - &Inicia el Bitcoin Core en inciar el sistema - (0 = auto, <0 = leave that many cores free) (0 = auto, <0 = deixa tants nuclis lliures) @@ -1284,186 +870,76 @@ - PaymentServer + PeerTableModel - URI handling - Gestió d'URI + User Agent + Agent d'usuari - Invalid payment address %1 - Adreça de pagament no vàlida %1 + Node/Service + Node/Servei - Payment request rejected - La sol·licitud de pagament s'ha rebutjat + Ping Time + Temps de ping + + + QObject - Payment request network doesn't match client network. - La xarxa de la sol·licitud de pagament no coincideix amb la xarxa del client. + Amount + Import - Payment request is not initialized. - La sol·licitud de pagament no està inicialitzada. + Enter a Bitcoin address (e.g. %1) + Introduïu una adreça de Bitcoin (p. ex. %1) - Requested payment amount of %1 is too small (considered dust). - L'import de pagament sol·licitat %1 és massa petit (es considera polsim). + %1 d + %1 d - Payment request error - Error en la sol·licitud de pagament + %1 h + %1 h - Cannot start bitcoin: click-to-pay handler - No es pot iniciar bitcoin: gestor clica-per-pagar + %1 m + %1 m - Payment request fetch URL is invalid: %1 - L'URL de recuperació de la sol·licitud de pagament no és vàlida: %1 + %1 s + %1 s - URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - L'URI no pot ser analitzat! Això pot ser a causa d'una adreça de Bitcoin no vàlida o per paràmetres URI amb mal format. + None + Cap - Payment request file handling - Gestió de fitxers de les sol·licituds de pagament + N/A + N/A - Payment request file cannot be read! This can be caused by an invalid payment request file. - No es pot llegir el fitxer de la sol·licitud de pagament. Això pot ser causat per un fitxer de sol·licitud de pagament no vàlid. + %1 ms + %1 ms + + + RPCConsole - Payment request expired. - La sol·licitud de pagament ha vençut. + Client name + Nom del client - Unverified payment requests to custom payment scripts are unsupported. - No s'accepten sol·licituds de pagament no verificades a scripts de pagament personalitzats. + N/A + N/A - Invalid payment request. - Sol·licitud de pagament no vàlida. + Client version + Versió del client - Refund from %1 - Reemborsament de %1 - - - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - La sol·licitud de pagament %1 és massa gran (%2 bytes, permès %3 bytes). - - - Error communicating with %1: %2 - Error en comunicar amb %1: %2 - - - Payment request cannot be parsed! - No es pot analitzar la sol·licitud de pagament! - - - Bad response from server %1 - Mala resposta del servidor %1 - - - Payment acknowledged - Pagament reconegut - - - Network request error - Error en la sol·licitud de xarxa - - - - PeerTableModel - - User Agent - Agent d'usuari - - - Node/Service - Node/Servei - - - Ping Time - Temps de ping - - - - QObject - - Amount - Import - - - Enter a Bitcoin address (e.g. %1) - Introduïu una adreça de Bitcoin (p. ex. %1) - - - %1 d - %1 d - - - %1 h - %1 h - - - %1 m - %1 m - - - %1 s - %1 s - - - None - Cap - - - N/A - N/A - - - %1 ms - %1 ms - - - - QRImageWidget - - &Save Image... - De&sa la imatge... - - - &Copy Image - &Copia la imatge - - - Save QR Code - Desa el codi QR - - - PNG Image (*.png) - Imatge PNG (*.png) - - - - RPCConsole - - Client name - Nom del client - - - N/A - N/A - - - Client version - Versió del client - - - &Information - &Informació + &Information + &Informació Debug window @@ -1513,10 +989,6 @@ Memory usage Us de memoria - - Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. - Obre el fitxer de registre de depuració del Bitcoin Core del directori de dades actual. Pot portar uns quants segons per a fitxers de registre grans. - Received Rebut @@ -1633,10 +1105,6 @@ Out: Fora: - - Build date - Data de compilació - Debug log file Fitxer de registre de depuració @@ -1673,10 +1141,6 @@ &Unban Node &Desbandeja el node - - Welcome to the Bitcoin Core RPC console. - Us donem la benviguda a la consola RPC del Bitcoin Core. - Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. Utilitza les fletxes d'amunt i avall per navegar per l'historial, i <b>Ctrl-L<\b> per netejar la pantalla. @@ -1804,18 +1268,6 @@ Remove Esborra - - Copy label - Copia l'etiqueta - - - Copy message - Copia el missatge - - - Copy amount - Copia l'import - ReceiveRequestDialog @@ -1835,73 +1287,6 @@ &Save Image... De&sa la imatge... - - Request payment to %1 - Sol·licita un pagament a %1 - - - Payment information - Informació de pagament - - - URI - URI - - - Address - Adreça - - - Amount - Import - - - Label - Etiqueta - - - Message - Missatge - - - Resulting URI too long, try to reduce the text for label / message. - URI resultant massa llarga, intenta reduir el text per a la etiqueta / missatge - - - Error encoding URI into QR Code. - Error en codificar l'URI en un codi QR. - - - - RecentRequestsTableModel - - Date - Data - - - Label - Etiqueta - - - Message - Missatge - - - Amount - Import - - - (no label) - (sense etiqueta) - - - (no message) - (sense missatge) - - - (no amount) - (sense import) - SendCoinsDialog @@ -2021,14 +1406,6 @@ fast ràpid - - Send as zero-fee transaction if possible - Envia com a transacció de comissió zero si és possible - - - (confirmation may take longer) - (la confirmació pot trigar més temps) - Send to multiple recipients at once Envia a múltiples destinataris al mateix temps @@ -2061,118 +1438,6 @@ S&end E&nvia - - Confirm send coins - Confirma l'enviament de monedes - - - %1 to %2 - %1 a %2 - - - Copy quantity - Copia la quantitat - - - Copy amount - Copia l'import - - - Copy fee - Copia la comissió - - - Copy after fee - Copia la comissió posterior - - - Copy bytes - Copia els bytes - - - Copy priority - Copia la prioritat - - - Copy change - Copia el canvi - - - Total Amount %1 - Import total %1 - - - or - o - - - The amount to pay must be larger than 0. - L'import a pagar ha de ser major que 0. - - - The amount exceeds your balance. - L'import supera el vostre balanç. - - - The total exceeds your balance when the %1 transaction fee is included. - El total excedeix el teu balanç quan s'afegeix la comissió a la transacció %1. - - - Transaction creation failed! - Ha fallat la creació de la transacció! - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - S'ha rebutjat la transacció! Això pot passar si alguna de les monedes del vostre moneder ja s'han gastat; per exemple, si heu fet servir una còpia de seguretat del fitxer wallet.dat i s'haguessin gastat monedes de la còpia però sense marcar-les-hi com a gastades. - - - A fee higher than %1 is considered an absurdly high fee. - Una comissió superior a %1 es considera una comissió absurdament alta. - - - Payment request expired. - La sol·licitud de pagament ha vençut. - - - Pay only the required fee of %1 - Paga només la comissió necessària de %1 - - - Estimated to begin confirmation within %n block(s). - Estimat per començar la confirmació en %n bloc.Estimat per començar la confirmació en %n blocs. - - - The recipient address is not valid. Please recheck. - L'adreça de destinatari no és vàlida. Torneu-la a comprovar. - - - Duplicate address found: addresses should only be used once each. - S'ha trobat una adreça duplicada: cal utilitzar les adreces només un cop cada vegada. - - - Warning: Invalid Bitcoin address - Avís: adreça Bitcoin no vàlida - - - (no label) - (sense etiqueta) - - - Warning: Unknown change address - Avís: adreça de canvi desconeguda - - - Copy dust - Copia el polsim - - - Are you sure you want to send? - Esteu segur que ho voleu enviar? - - - added as transaction fee - S'ha afegit una taxa de transacció - SendCoinsEntry @@ -2184,10 +1449,6 @@ Pay &To: Paga &a: - - Enter a label for this address to add it to your address book - Introduïu una etiqueta per a aquesta adreça per afegir-la a la llibreta d'adreces - &Label: &Etiqueta: @@ -2259,10 +1520,6 @@ ShutdownWindow - - Bitcoin Core is shutting down... - S'està aturant el Bitcoin Core... - Do not shut down the computer until this window disappears. No apagueu l'ordinador fins que no desaparegui aquesta finestra. @@ -2354,598 +1611,72 @@ Reset all verify message fields Neteja tots els camps de verificació de missatge + + + SplashScreen - Click "Sign Message" to generate signature - Feu clic a «Signa el missatge» per a generar una signatura + [testnet] + [testnet] + + + TrafficGraphWidget - The entered address is invalid. - L'adreça introduïda no és vàlida. + KB/s + KB/s + + + TransactionDescDialog - Please check the address and try again. - Comproveu l'adreça i torneu-ho a provar. + This pane shows a detailed description of the transaction + Aquest panell mostra una descripció detallada de la transacció + + + UnitDisplayStatusBarControl - The entered address does not refer to a key. - L'adreça introduïda no referencia a cap clau. + Unit to show amounts in. Click to select another unit. + Unitat en què mostrar els imports. Feu clic per seleccionar una altra unitat. + + + bitcoin-core - Wallet unlock was cancelled. - El desbloqueig del moneder ha estat cancelat. + Options: + Opcions: - Private key for the entered address is not available. - La clau privada per a la adreça introduïda no està disponible. + Specify data directory + Especifica el directori de dades - Message signing failed. - La signatura del missatge ha fallat. + Connect to a node to retrieve peer addresses, and disconnect + Connecta al node per obtenir les adreces de les connexions, i desconnecta - Message signed. - Missatge signat. + Specify your own public address + Especifiqueu la vostra adreça pública - The signature could not be decoded. - La signatura no s'ha pogut descodificar. + Accept command line and JSON-RPC commands + Accepta la línia d'ordres i ordres JSON-RPC - Please check the signature and try again. - Comproveu la signatura i torneu-ho a provar. + If <category> is not supplied or if <category> = 1, output all debugging information. + Si no es proporciona <category> o si <category> = 1, treu a la sortida tota la informació de depuració. - The signature did not match the message digest. - La signatura no coincideix amb el resum del missatge. + Prune configured below the minimum of %d MiB. Please use a higher number. + Poda configurada per sota el mínim de %d MiB. Utilitzeu un nombre superior. - Message verification failed. - Ha fallat la verificació del missatge. + Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node) + Poda: la darrera sincronització del moneder va més enllà de les dades podades. Cal que activeu -reindex (baixeu tota la cadena de blocs de nou en cas de node podat) - Message verified. - Missatge verificat. - - - - SplashScreen - - Bitcoin Core - Bitcoin Core - - - The Bitcoin Core developers - Els desenvolupadors del Bitcoin Core - - - [testnet] - [testnet] - - - - TrafficGraphWidget - - KB/s - KB/s - - - - TransactionDesc - - Open until %1 - Obert fins %1 - - - conflicted - en conflicte - - - %1/offline - %1/fora de línia - - - %1/unconfirmed - %1/sense confirmar - - - %1 confirmations - %1 confirmacions - - - Status - Estat - - - , broadcast through %n node(s) - , difusió a través de %n node, difusió a través de %n nodes - - - Date - Data - - - Source - Font - - - Generated - Generat - - - From - Des de - - - To - A - - - own address - Adreça pròpia - - - watch-only - només lectura - - - label - etiqueta - - - Credit - Crèdit - - - matures in %n more block(s) - disponible en %n bloc mésdisponibles en %n blocs més - - - not accepted - no acceptat - - - Debit - Dèbit - - - Total debit - Dèbit total - - - Total credit - Crèdit total - - - Transaction fee - Comissió de transacció - - - Net amount - Import net - - - Message - Missatge - - - Comment - Comentar - - - Transaction ID - ID de transacció - - - Merchant - Mercader - - - 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. - Les monedes generades han de madurar %1 blocs abans de poder ser gastades. Quan genereu aquest bloc, es farà saber a la xarxa per tal d'afegir-lo a la cadena de blocs. Si no pot fer-se lloc a la cadena, el seu estat canviarà a «no acceptat» i no es podrà gastar. Això pot passar ocasionalment si un altre node genera un bloc en un marge de segons respecte al vostre. - - - Debug information - Informació de depuració - - - Transaction - Transacció - - - Inputs - Entrades - - - Amount - Import - - - true - cert - - - false - fals - - - , has not been successfully broadcast yet - , encara no ha estat emès correctement - - - Open for %n more block(s) - Obre per %n bloc mésObre per %n blocs més - - - unknown - desconegut - - - - TransactionDescDialog - - Transaction details - Detall de la transacció - - - This pane shows a detailed description of the transaction - Aquest panell mostra una descripció detallada de la transacció - - - - TransactionTableModel - - Date - Data - - - Type - Tipus - - - Immature (%1 confirmations, will be available after %2) - Immadur (%1 confirmacions, serà disponible després de %2) - - - Open for %n more block(s) - Obre per %n bloc mésObre per %n blocs més - - - Open until %1 - Obert fins %1 - - - Confirmed (%1 confirmations) - Confirmat (%1 confirmacions) - - - This block was not received by any other nodes and will probably not be accepted! - Aquest bloc no ha estat rebut per cap altre node i probablement no serà acceptat! - - - Generated but not accepted - Generat però no acceptat - - - Offline - Fora de línia - - - Label - Etiqueta - - - Unconfirmed - Sense confirmar - - - Confirming (%1 of %2 recommended confirmations) - Confirmant (%1 de %2 confirmacions recomanades) - - - Conflicted - En conflicte - - - Received with - Rebut amb - - - Received from - Rebut de - - - Sent to - Enviat a - - - Payment to yourself - Pagament a un mateix - - - Mined - Minat - - - watch-only - només lectura - - - (n/a) - (n/a) - - - Transaction status. Hover over this field to show number of confirmations. - Estat de la transacció. Desplaceu-vos sobre aquest camp per mostrar el nombre de confirmacions. - - - Date and time that the transaction was received. - Data i hora en que la transacció va ser rebuda. - - - Type of transaction. - Tipus de transacció. - - - Whether or not a watch-only address is involved in this transaction. - Si està implicada o no una adreça només de lectura en la transacció. - - - User-defined intent/purpose of the transaction. - Intenció/propòsit de la transacció definida per l'usuari. - - - Amount removed from or added to balance. - Import extret o afegit del balanç. - - - - TransactionView - - All - Tot - - - Today - Avui - - - This week - Aquesta setmana - - - This month - Aquest mes - - - Last month - El mes passat - - - This year - Enguany - - - Range... - Rang... - - - Received with - Rebut amb - - - Sent to - Enviat a - - - To yourself - A un mateix - - - Mined - Minat - - - Other - Altres - - - Enter address or label to search - Introduïu una adreça o una etiqueta per cercar - - - Min amount - Import mínim - - - Copy address - Copia l'adreça - - - Copy label - Copiar etiqueta - - - Copy amount - Copia l'import - - - Copy transaction ID - Copiar ID de transacció - - - Copy raw transaction - Copia la transacció crua - - - Edit label - Editar etiqueta - - - Show transaction details - Mostra detalls de la transacció - - - Export Transaction History - Exporta l'historial de transacció - - - Watch-only - Només de lectura - - - Exporting Failed - L'exportació ha fallat - - - There was an error trying to save the transaction history to %1. - S'ha produït un error en provar de desar l'historial de transacció a %1. - - - Exporting Successful - Exportació amb èxit - - - The transaction history was successfully saved to %1. - L'historial de transaccions s'ha desat correctament a %1. - - - Comma separated file (*.csv) - Fitxer separat per comes (*.csv) - - - Confirmed - Confirmat - - - Date - Data - - - Type - Tipus - - - Label - Etiqueta - - - Address - Adreça - - - ID - ID - - - Range: - Rang: - - - to - a - - - - UnitDisplayStatusBarControl - - Unit to show amounts in. Click to select another unit. - Unitat en què mostrar els imports. Feu clic per seleccionar una altra unitat. - - - - WalletFrame - - No wallet has been loaded. - No s'ha carregat cap moneder. - - - - WalletModel - - Send Coins - Envia monedes - - - - WalletView - - &Export - &Exporta - - - Export the data in the current tab to a file - Exporta les dades de la pestanya actual a un fitxer - - - Backup Wallet - Còpia de seguretat del moneder - - - Wallet Data (*.dat) - Dades del moneder (*.dat) - - - Backup Failed - Ha fallat la còpia de seguretat - - - There was an error trying to save the wallet data to %1. - S'ha produït un error en provar de desar les dades del moneder a %1. - - - The wallet data was successfully saved to %1. - S'han desat les dades del moneder correctament a %1. - - - Backup Successful - La còpia de seguretat s'ha realitzat correctament - - - - bitcoin-core - - Options: - Opcions: - - - Specify data directory - Especifica el directori de dades - - - Connect to a node to retrieve peer addresses, and disconnect - Connecta al node per obtenir les adreces de les connexions, i desconnecta - - - Specify your own public address - Especifiqueu la vostra adreça pública - - - Accept command line and JSON-RPC commands - Accepta la línia d'ordres i ordres JSON-RPC - - - If <category> is not supplied or if <category> = 1, output all debugging information. - Si no es proporciona <category> o si <category> = 1, treu a la sortida tota la informació de depuració. - - - Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s) - Comissions totals màximes (en %s) per utilitzar en una única transacció de moneder; definir-ne una massa baixa pot interrompre les transaccions més grans (per defecte: %s) - - - Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. - Comproveu que la data i hora de l'ordinador són correctes! Si el vostre rellotge no té l'hora correcta, el Bitcoin Core no funcionarà adequadament. - - - Prune configured below the minimum of %d MiB. Please use a higher number. - Poda configurada per sota el mínim de %d MiB. Utilitzeu un nombre superior. - - - Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node) - Poda: la darrera sincronització del moneder va més enllà de les dades podades. Cal que activeu -reindex (baixeu tota la cadena de blocs de nou en cas de node podat) - - - Reduce storage requirements by pruning (deleting) old blocks. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, >%u = target size in MiB to use for block files) - Reduïu els requisits d'emmagatzematge podant (suprimint) els blocs antics. Aquest mode és incompatible amb -txindex i -rescan. Avís: la reversió d'aquest paràmetre implica haver de tornar a baixar la cadena de blocs sencera. (per defecte: 0 = inhabilita la poda de blocs, >%u = mida objectiu en MiB per utilitzar en els fitxers de blocs) + Reduce storage requirements by pruning (deleting) old blocks. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, >%u = target size in MiB to use for block files) + Reduïu els requisits d'emmagatzematge podant (suprimint) els blocs antics. Aquest mode és incompatible amb -txindex i -rescan. Avís: la reversió d'aquest paràmetre implica haver de tornar a baixar la cadena de blocs sencera. (per defecte: 0 = inhabilita la poda de blocs, >%u = mida objectiu en MiB per utilitzar en els fitxers de blocs) Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again. @@ -2975,6 +1706,10 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Accepta connexions de fora (per defecte: 1 si no -proxy o -connect) + + Bitcoin Core + Nucli de Bitcoin + Bind to given address and always listen on it. Use [host]:port notation for IPv6 Vincula a una adreça específica i sempre escolta-hi. Utilitza la notació [host]:port per IPv6 @@ -2999,10 +1734,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Aquesta és una versió de pre-llançament - utilitza-la sota la teva responsabilitat - No usar per a minería o aplicacions de compra-venda - - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - No es pot enllaçar %s a aquest ordinador. El Bitcoin Core probablement ja estigui executant-s'hi. - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) AVÍS: s'ha generat un nombre anòmalament alt de blocs, %d blocs rebuts en les darreres %d hores (se n'esperaven %d) @@ -3019,10 +1750,6 @@ Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Avís: sembla que no estem plenament d'acord amb els nostres iguals! Podria caler que actualitzar l'aplicació, o potser que ho facin altres nodes. - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Avís: el fitxer wallet.dat és corrupte, dades rescatades! L'arxiu wallet.dat original ha estat desat com wallet.{estampa_temporal}.bak al directori %s; si el teu balanç o transaccions son incorrectes hauries de restaurar-lo de un backup. - Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. Afegeix a la llista blanca els iguals que es connecten de la màscara de xarxa o adreça IP donada. Es pot especificar moltes vegades. @@ -3143,10 +1870,6 @@ Wallet options: Opcions de moneder: - - You need to rebuild the database using -reindex to change -txindex - Cal que reconstruïu la base de dades fent servir -reindex per canviar -txindex - 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 Permet les connexions JSON-RPC d'una font específica. Vàlid per a <ip> són una IP individual (p. ex., 1.2.3.4), una xarxa / màscara de xarxa (p. ex., 1.2.3.4/255.255.255.0) o una xarxa/CIDR (p. ex., 1.2.3.4/24). Es pot especificar aquesta opció moltes vegades @@ -3159,10 +1882,6 @@ Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces) Vincula a l'adreça donada per a escoltar les connexions JSON-RPC. Feu servir la notació [host]:port per a IPv6. Aquesta opció pot ser especificada moltes vegades (per defecte: vincula a totes les interfícies) - - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - No es pot obtenir un bloqueig del directori de dades %s. El Bitcoin Core probablement ja s'estigui executant. - Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) Crea fitxers nous amb els permisos per defecte del sistema, en comptes de l'umask 077 (només efectiu amb la funcionalitat de moneder inhabilitada) @@ -3203,10 +1922,6 @@ Set maximum size of high-priority/low-fee transactions in bytes (default: %d) Defineix la mida màxima de transaccions d'alta prioritat / baixa comissió en bytes (per defecte: %d) - - Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) - Defineix el nombre de fils per a la generació de moneda si està habilitat (-1 = tots els nuclis, per defecte: %d) - The transaction amount is too small to send after the fee has been deducted L'import de la transacció és massa petit per enviar-la després que se'n dedueixi la comissió @@ -3231,26 +1946,10 @@ Accept public REST requests (default: %u) Accepta sol·licituds REST públiques (per defecte: %u) - - Activating best chain... - S'està activant la millor cadena... - - - Cannot resolve -whitebind address: '%s' - No es pot resoldre l'adreça -whitebind: «%s» - Connect through SOCKS5 proxy Connecta a través del proxy SOCKS5 - - Copyright (C) 2009-%i The Bitcoin Core Developers - Copyright (C) 2009-%i Els desenvolupadors del Bitcoin Core - - - Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - Error en carregar wallet.dat: el moneder requereix una versió més nova del Bitcoin core - Error reading from database, shutting down. Error en llegir la base de dades, tancant. @@ -3259,22 +1958,6 @@ Information &Informació - - Initialization sanity check failed. Bitcoin Core is shutting down. - Ha fallat la inicialització de la comprovació de validesa. El Bitcoin Core s'està aturant. - - - Invalid amount for -maxtxfee=<amount>: '%s' - Import no vàlid per a -maxtxfee=<amount>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Import no vàlid per a -minrelaytxfee=<amount>: «%s» - - - Invalid amount for -mintxfee=<amount>: '%s' - Import no vàlid per a -mintxfee=<amount>: «%s» - Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) Import no vàlid per a -paytxfee=<amount>: «%s» (ha de ser com a mínim %s) @@ -3299,14 +1982,6 @@ RPC server options: Opcions del servidor RPC: - - Rebuild block chain index from current blk000??.dat files on startup - Reconstrueix l'índex de la cadena de blocs dels fitxers blk000??.dat actuals a l'inici. - - - Receive and display P2P network alerts (default: %u) - Rep i mostra avisos de la xarxa P2P (per defecte: %u) - Send trace/debug info to console instead of debug.log file Envia informació de traça/depuració a la consola en comptes del fitxer debug.log @@ -3359,10 +2034,6 @@ Username for JSON-RPC connections Nom d'usuari per a connexions JSON-RPC - - Wallet needed to be rewritten: restart Bitcoin Core to complete - Cal reescriure el moneder: reiniceu el Bitcoin Core per completar-ho. - Warning Avís @@ -3371,10 +2042,6 @@ Zapping all transactions from wallet... Se suprimeixen totes les transaccions del moneder... - - wallet.dat corrupt, salvage failed - El fitxer wallet.data és corrupte. El rescat de les dades ha fallat - Password for JSON-RPC connections Contrasenya per a connexions JSON-RPC @@ -3383,10 +2050,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) Executa l'ordre quan el millor bloc canviï (%s en cmd es reemplaça per un resum de bloc) - - This help message - Aquest misatge d'ajuda - Allow DNS lookups for -addnode, -seednode and -connect Permet consultes DNS per a -addnode, -seednode i -connect @@ -3395,10 +2058,6 @@ Loading addresses... S'estan carregant les adreces... - - Error loading wallet.dat: Wallet corrupted - Error en carregar wallet.dat: Moneder corrupte - (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) (1 = manté les metadades de les tx, p. ex., propietari del compte i informació de sol·licitud del pagament, 2 = prescindeix de les metadades de les tx) @@ -3431,14 +2090,6 @@ Always query for peer addresses via DNS lookup (default: %u) Demana sempre les adreces dels iguals a través de consultes DNS (per defecte: %u) - - Error loading wallet.dat - Error en carregar wallet.dat - - - Generate coins (default: %u) - Genera monedes (per defecte: %u) - How many blocks to check at startup (default: %u, 0 = all) Quants blocs per comprovar a l'inici (per defecte: %u, 0 = tots) @@ -3523,18 +2174,6 @@ Unknown network specified in -onlynet: '%s' Xarxa desconeguda especificada a -onlynet: '%s' - - Cannot resolve -bind address: '%s' - No es pot resoldre l'adreça -bind: '%s' - - - Cannot resolve -externalip address: '%s' - No es pot resoldre l'adreça -externalip: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - Import no vàlid per a -paytxfee=<amount>: «%s» - Insufficient funds Balanç insuficient diff --git a/src/qt/locale/bitcoin_cs.ts b/src/qt/locale/bitcoin_cs.ts index d3ff5c1f57d64..d76839723fc0e 100644 --- a/src/qt/locale/bitcoin_cs.ts +++ b/src/qt/locale/bitcoin_cs.ts @@ -25,10 +25,6 @@ C&lose &Zavřít - - &Copy Address - &Kopíruj adresu - Delete the currently selected address from the list Smaž zvolenou adresu ze seznamu @@ -45,73 +41,6 @@ &Delete S&maž - - Choose the address to send coins to - Zvol adresu, na kterou pošleš mince - - - Choose the address to receive coins with - Zvol adres na příjem mincí - - - C&hoose - &Zvol - - - Sending addresses - Odesílací adresy - - - Receiving addresses - Přijímací adresy - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - 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. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Tohle jsou tvé Bitcoinové adresy pro příjem plateb. Nezapomeň si pro každou transakci vždy vygenerovat novou adresu. - - - Copy &Label - Kopíruj &označení - - - &Edit - &Uprav - - - Export Address List - Export seznamu adres - - - Comma separated file (*.csv) - Formát CSV (*.csv) - - - Exporting Failed - Exportování selhalo - - - There was an error trying to save the address list to %1. Please try again. - Při ukládání seznamu adres do %1 se přihodila nějaká chyba. Zkus to prosím znovu. - - - - AddressTableModel - - Label - Označení - - - Address - Adresa - - - (no label) - (bez označení) - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase Totéž heslo ještě jednou - - Encrypt wallet - Zašifruj peněženku - - - This operation needs your wallet passphrase to unlock the wallet. - K provedení této operace musíš zadat heslo k peněžence, aby se mohla odemknout. - - - Unlock wallet - Odemkni peněženku - - - This operation needs your wallet passphrase to decrypt the wallet. - K provedení této operace musíš zadat heslo k peněžence, aby se mohla dešifrovat. - - - Decrypt wallet - Dešifruj peněženku - - - Change passphrase - Změň heslo - - - Confirm wallet encryption - Potvrď zašifrování peněženky - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Upozornění: Pokud si zašifruješ peněženku a ztratíš či zapomeneš heslo, <b>PŘIJDEŠ O VŠECHNY BITCOINY</b>! - - - Are you sure you wish to encrypt your wallet? - Jsi si jistý, že chceš peněženku zašifrovat? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Bitcoin Core se teď ukončí, aby dokončil zašifrování. Pamatuj však, že pouhé zašifrování peněženky nemůže zabránit krádeži tvých bitcoinů malwarem, kterým se může počítač nakazit. - - - 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. - DŮLEŽITÉ: Všechny předchozí zálohy peněženky by měly být nahrazeny nově vygenerovanou, zašifrovanou peněženkou. Z bezpečnostních důvodů budou předchozí zálohy nešifrované peněženky nepoužitelné, jakmile začneš používat novou zašifrovanou peněženku. - - - Warning: The Caps Lock key is on! - Upozornění: Caps Lock je zapnutý! - - - Wallet encrypted - Peněženka je zašifrována - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Zadej nové heslo k peněžence.<br/>Použij <b>alespoň deset náhodných znaků</b> nebo <b>alespoň osm slov</b>. - - - Enter the old passphrase and new passphrase to the wallet. - Zadej staré a nové heslo k peněžence. - - - Wallet encryption failed - Zašifrování peněženky selhalo - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Zašifrování peněženky selhalo kvůli vnitřní chybě. Tvá peněženka tedy nebyla zašifrována. - - - The supplied passphrases do not match. - Zadaná hesla nejsou shodná. - - - Wallet unlock failed - Nepodařilo se odemknout peněženku - - - The passphrase entered for the wallet decryption was incorrect. - Nezadal jsi správné heslo pro dešifrování peněženky. - - - Wallet decryption failed - Nepodařilo se dešifrovat peněženku - - - Wallet passphrase was successfully changed. - Heslo k peněžence bylo v pořádku změněno. - BanTableModel @@ -297,14 +138,6 @@ Open &URI... Načíst &URI... - - Bitcoin Core client - Bitcoin Core klient - - - Importing blocks from disk... - Importuji bloky z disku... - Reindexing blocks on disk... Vytvářím nový index bloků na disku... @@ -349,10 +182,6 @@ &Receive Při&jmi - - Show information about Bitcoin Core - Zobraz informace o Bitcoin Core - &Show / Hide &Zobraz/Skryj @@ -389,22 +218,10 @@ Tabs toolbar Panel s listy - - Bitcoin Core - Bitcoin Core - Request payments (generates QR codes and bitcoin: URIs) Požaduj platby (generuje QR kódy a bitcoin: URI) - - &About Bitcoin Core - O &Bitcoin Core - - - Modify configuration options for Bitcoin Core - Uprav nastavení Bitcoin Core - Show the list of used sending addresses and labels Ukaž seznam použitých odesílacích adres a jejich označení @@ -421,10 +238,6 @@ &Command-line options Ar&gumenty příkazové řádky - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Seznam argumentů Bitcoinu pro příkazovou řádku získáš v nápovědě Bitcoinu Core - %n active connection(s) to Bitcoin network %n aktivní spojení do Bitcoinové sítě%n aktivní spojení do Bitcoinové sítě%n aktivních spojení do Bitcoinové sítě @@ -536,13 +349,6 @@ Peněženka je <b>zašifrovaná</b> a momentálně <b>zamčená</b> - - ClientModel - - Network Alert - Upozornění sítě - - CoinControlDialog @@ -621,150 +427,6 @@ Priority Priorita - - Copy address - Kopíruj adresu - - - Copy label - Kopíruj její označení - - - Copy amount - Kopíruj částku - - - Copy transaction ID - Kopíruj ID transakce - - - Lock unspent - Zamkni neutracené - - - Unlock unspent - Odemkni k utracení - - - Copy quantity - Kopíruj počet - - - Copy fee - Kopíruj poplatek - - - Copy after fee - Kopíruj čistou částku - - - Copy bytes - Kopíruj bajty - - - Copy priority - Kopíruj prioritu - - - Copy dust - Kopíruj prach - - - Copy change - Kopíruj drobné - - - highest - nejvyšší - - - higher - vyšší - - - high - vysoká - - - medium-high - vyšší střední - - - medium - střední - - - low-medium - nižší střední - - - low - nízká - - - lower - nižší - - - lowest - nejnižší - - - (%1 locked) - (%1 zamčeno) - - - none - žádná - - - This label turns red if the transaction size is greater than 1000 bytes. - Popisek zčervená, pokud je velikost transakce větší než 1000 bajtů. - - - This label turns red if the priority is smaller than "medium". - Popisek zčervená, pokud je priorita menší než „střední“. - - - This label turns red if any recipient receives an amount smaller than %1. - Popisek zčervená, pokud má některý příjemce obdržet částku menší než %1. - - - Can vary +/- %1 satoshi(s) per input. - Může se lišit o +/– %1 satoshi na každý vstup. - - - yes - ano - - - no - ne - - - This means a fee of at least %1 per kB is required. - To znamená, že je vyžadován poplatek alespoň %1 za kB. - - - Can vary +/- 1 byte per input. - Může se lišit o +/– 1 bajt na každý vstup. - - - Transactions with higher priority are more likely to get included into a block. - Transakce s vyšší prioritou mají větší šanci na zařazení do bloku. - - - (no label) - (bez označení) - - - change from %1 (%2) - drobné z %1 (%2) - - - (change) - (drobné) - EditAddressDialog @@ -788,38 +450,6 @@ &Address &Adresa - - New receiving address - Nová přijímací adresa - - - New sending address - Nová odesílací adresa - - - Edit receiving address - Uprav přijímací adresu - - - Edit sending address - Uprav odesílací adresu - - - The entered address "%1" is already in the address book. - Zadaná adresa „%1“ už v adresáři je. - - - The entered address "%1" is not a valid Bitcoin address. - Zadaná adresa „%1“ není platná Bitcoinová adresa. - - - Could not unlock wallet. - Nemohu odemknout peněženku. - - - New key generation failed. - Nepodařilo se mi vygenerovat nový klíč. - FreespaceChecker @@ -846,10 +476,6 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin Core - version verze @@ -858,10 +484,6 @@ (%1-bit) (%1-bit) - - About Bitcoin Core - O Bitcoin Core - Command-line options Argumenty příkazové řádky @@ -898,29 +520,13 @@ Show splash screen on startup (default: %u) Zobrazit startovací obrazovku (výchozí: %u) - - Reset all settings changes made over the GUI - Resetovat všechna nastavení provedené v GUI - - + Intro Welcome Vítej - - Welcome to Bitcoin Core. - Vítej v Bitcoin Core. - - - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - Tohle je poprvé, co spouštíš Bitcoin Core, takže si můžeš zvolit, kam bude ukládat svá data. - - - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - Bitcoin Core bude stahovat kopii řetězce bloků. Proto bude potřeba do tohoto adresáře uložit nejméně %1 GB dat – toto číslo bude navíc v průběhu času pomalu růst. Tvá peněženka bude rovněž uložena v tomto adresáři. - Use the default data directory Použij výchozí adresář pro data @@ -929,10 +535,6 @@ Use a custom data directory: Použij tento adresář pro data: - - Bitcoin Core - Bitcoin Core - Error: Specified data directory "%1" cannot be created. Chyba: Nejde vytvořit požadovaný adresář pro data „%1“. @@ -968,10 +570,6 @@ Select payment request file Vyber soubor platebního požadavku - - Select payment request file to open - Vyber soubor platebního požadavku k načtení - OptionsDialog @@ -1011,10 +609,6 @@ 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. Zavřením se aplikace minimalizuje. Pokud je tato volba zaškrtnuta, tak se aplikace ukončí pouze zvolením Konec v menu. - - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - Tady lze nastavit jazyk uživatelského rozhraní. Nastavení se projeví až po restartování Bitcoin Core. - 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 |. URL třetích stran (např. block exploreru), která se zobrazí v kontextovém menu v záložce Transakce. %s v URL se nahradí hashem transakce. Více URL odděl svislítkem |. @@ -1039,14 +633,6 @@ &Network &Síť - - Automatically start Bitcoin Core after logging in to the system. - Automaticky spustí Bitcoin Core po přihlášení do systému. - - - &Start Bitcoin Core on system login - S&pustit Bitcoin Core po přihlášení do systému - (0 = auto, <0 = leave that many cores free) (0 = automaticky, <0 = nechat daný počet jader volný, výchozí: 0) @@ -1276,186 +862,76 @@ - PaymentServer + PeerTableModel - URI handling - Zpracování URI + User Agent + Typ klienta - Invalid payment address %1 - Neplatná platební adresa %1 + Node/Service + Uzel/Služba - Payment request rejected - Platební požadavek byl odmítnut + Ping Time + Odezva + + + QObject - Payment request network doesn't match client network. - Síť platebního požadavku neodpovídá síti klienta. + Amount + Částka - Payment request is not initialized. - Platební požadavek není zahájený. + Enter a Bitcoin address (e.g. %1) + Zadej Bitcoinovou adresu (např. %1) - Requested payment amount of %1 is too small (considered dust). - Požadovaná platební částka %1 je příliš malá (je považována za prach). + %1 d + %1 d - Payment request error - Chyba platebního požadavku + %1 h + %1 h - Cannot start bitcoin: click-to-pay handler - Nemůžu spustit bitcoin: obsluha click-to-pay + %1 m + %1 m - Payment request fetch URL is invalid: %1 - Zdrojová URL platebního požadavku není platná: %1 + %1 s + %1 s - URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - Nepodařilo se analyzovat URI! Důvodem může být neplatná Bitcoinová adresa nebo poškozené parametry URI. + None + Žádné - Payment request file handling - Zpracování souboru platebního požadavku + N/A + N/A - Payment request file cannot be read! This can be caused by an invalid payment request file. - Soubor platebního požadavku nejde přečíst nebo zpracovat! Příčinou může být špatný soubor platebního požadavku. + %1 ms + %1 ms + + + RPCConsole - Payment request expired. - Platební požadavek vypršel. + Client name + Název klienta - Unverified payment requests to custom payment scripts are unsupported. - Neověřené platební požadavky k uživatelským platebním skriptům nejsou podporované. + N/A + N/A - Invalid payment request. - Neplatný platební požadavek. + Client version + Verze klienta - Refund from %1 - Vrácení peněz od %1 - - - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - Platební požadavek %1 je moc velký (%2 bajtů, povoleno %3 bajtů). - - - Error communicating with %1: %2 - Chyba při komunikaci s %1: %2 - - - Payment request cannot be parsed! - Platební požadavek je nečitelný! - - - Bad response from server %1 - Chybná odpověď ze serveru %1 - - - Payment acknowledged - Platba potvrzena - - - Network request error - Chyba síťového požadavku - - - - PeerTableModel - - User Agent - Typ klienta - - - Node/Service - Uzel/Služba - - - Ping Time - Odezva - - - - QObject - - Amount - Částka - - - Enter a Bitcoin address (e.g. %1) - Zadej Bitcoinovou adresu (např. %1) - - - %1 d - %1 d - - - %1 h - %1 h - - - %1 m - %1 m - - - %1 s - %1 s - - - None - Žádné - - - N/A - N/A - - - %1 ms - %1 ms - - - - QRImageWidget - - &Save Image... - &Ulož obrázek... - - - &Copy Image - &Kopíruj obrázek - - - Save QR Code - Ulož QR kód - - - PNG Image (*.png) - PNG obrázek (*.png) - - - - RPCConsole - - Client name - Název klienta - - - N/A - N/A - - - Client version - Verze klienta - - - &Information - &Informace + &Information + &Informace Debug window @@ -1497,10 +973,6 @@ Memory usage Využití paměti - - Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. - Otevři soubor s ladicími záznamy Bitcoin Core z aktuálního datového adresáře. U velkých logů to může pár vteřin zabrat. - Received Přijato @@ -1589,10 +1061,6 @@ Out: Ven: - - Build date - Datum kompilace - Debug log file Soubor s ladicími záznamy @@ -1629,10 +1097,6 @@ &Unban Node &Zbavit uzel klatby - - Welcome to the Bitcoin Core RPC console. - Vítej v RPC konzoli Bitcoin Core. - Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. V historii se pohybuješ šipkami nahoru a dolů a pomocí <b>Ctrl-L</b> čistíš obrazovku. @@ -1760,18 +1224,6 @@ Remove Smazat - - Copy label - Kopíruj její označení - - - Copy message - Kopíruj zprávu - - - Copy amount - Kopíruj částku - ReceiveRequestDialog @@ -1791,73 +1243,6 @@ &Save Image... &Ulož obrázek... - - Request payment to %1 - Platební požadavek: %1 - - - Payment information - Informace o platbě - - - URI - URI - - - Address - Adresa - - - Amount - Částka - - - Label - Označení - - - Message - Zpráva - - - Resulting URI too long, try to reduce the text for label / message. - Výsledná URI je příliš dlouhá, zkus zkrátit text označení/zprávy. - - - Error encoding URI into QR Code. - Chyba při kódování URI do QR kódu. - - - - RecentRequestsTableModel - - Date - Datum - - - Label - Označení - - - Message - Zpráva - - - Amount - Částka - - - (no label) - (bez označení) - - - (no message) - (bez zprávy) - - - (no amount) - (bez částky) - SendCoinsDialog @@ -1918,943 +1303,297 @@ Vlastní adresa pro drobné - Transaction Fee: - Transakční poplatek: - - - Choose... - Zvol... - - - collapse fee-settings - sbal nastavení poplatků - - - per kilobyte - za kilobajt - - - If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte. - Pokud je vlastní poplatek nastavený na 1000 satoshi a transakce má pouze 250 bajtů, tak „za kilobajt“ zaplatí poplatek jen 250 satoshi, zatímco „přinejmenším“ zaplatí 1000 satoshi. Pro transakce větší než kilobajt obě možnosti platí za kilobajt. - - - Hide - Skryj - - - total at least - přinejmenším - - - Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process. - Platit jen minimální poplatek je v pořádku, pokud je zrovna méně transakcí než místa v blocích. Ale počítej s tím, že to také může skončit transakcí, která nikdy nebude potvrzena, pokud je větší poptávka po bitcoinových transakcích, než síť zvládne zpracovat. - - - (read the tooltip) - (viz bublina) - - - Recommended: - Doporučený: - - - Custom: - Vlastní: - - - (Smart fee not initialized yet. This usually takes a few blocks...) - (Inteligentní poplatek ještě není inicializovaný. Obvykle mu to tak pár bloků trvá...) - - - Confirmation time: - Rychlost potvrzení: - - - normal - normální - - - fast - rychlá - - - Send as zero-fee transaction if possible - Pošli transakci pokud možno bez poplatku - - - (confirmation may take longer) - (potvrzení může trvat déle) - - - Send to multiple recipients at once - Pošli více příjemcům naráz - - - Add &Recipient - Při&dej příjemce - - - Clear all fields of the form. - Promaž obsah ze všech formulářových políček. - - - Dust: - Prach: - - - Clear &All - Všechno s&maž - - - Balance: - Stav účtu: - - - Confirm the send action - Potvrď odeslání - - - S&end - Pošl&i - - - Confirm send coins - Potvrď odeslání mincí - - - %1 to %2 - %1 pro %2 - - - Copy quantity - Kopíruj počet - - - Copy amount - Kopíruj částku - - - Copy fee - Kopíruj poplatek - - - Copy after fee - Kopíruj čistou částku - - - Copy bytes - Kopíruj bajty - - - Copy priority - Kopíruj prioritu - - - Copy change - Kopíruj drobné - - - Total Amount %1 - Celková částka %1 - - - or - nebo - - - The amount to pay must be larger than 0. - Odesílaná částka musí být větší než 0. - - - The amount exceeds your balance. - Částka překračuje stav účtu. - - - The total exceeds your balance when the %1 transaction fee is included. - Celková částka při připočítání poplatku %1 překročí stav účtu. - - - Transaction creation failed! - Vytvoření transakce selhalo! - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - Transakce byla odmítnuta! Tohle může nastat, pokud nějaké mince z tvé peněženky už jednou byly utraceny, například pokud používáš kopii souboru wallet.dat a mince byly utraceny v druhé kopii, ale nebyly označeny jako utracené v této. - - - A fee higher than %1 is considered an absurdly high fee. - Poplatek vyšší než %1 je považován za absurdně vysoký. - - - Payment request expired. - Platební požadavek vypršel. - - - Pay only the required fee of %1 - Zaplatit pouze vyžadovaný poplatek %1 - - - Estimated to begin confirmation within %n block(s). - Potvrzování by podle odhadu mělo začít během %n bloku.Potvrzování by podle odhadu mělo začít během %n bloků.Potvrzování by podle odhadu mělo začít během %n bloků. - - - The recipient address is not valid. Please recheck. - Adresa příjemce je neplatná – překontroluj ji prosím. - - - Duplicate address found: addresses should only be used once each. - Zaznamenána duplicitní adresa: každá adresa by ale měla být použita vždy jen jednou. - - - Warning: Invalid Bitcoin address - Upozornění: Neplatná Bitcoinová adresa - - - (no label) - (bez označení) - - - Warning: Unknown change address - Upozornění: Neznámá adresa pro drobné - - - Copy dust - Kopíruj prach - - - Are you sure you want to send? - Jsi si jistý, že to chceš poslat? - - - added as transaction fee - přidán jako transakční poplatek - - - - SendCoinsEntry - - A&mount: - Čás&tka: - - - Pay &To: - &Komu: - - - Enter a label for this address to add it to your address book - Zadej označení této adresy; obojí se ti pak uloží do adresáře - - - &Label: - O&značení: - - - Choose previously used address - Vyber již použitou adresu - - - This is a normal payment. - Tohle je normální platba. - - - The Bitcoin address to send the payment to - Bitcoinová adresa příjemce - - - Alt+A - Alt+A - - - Paste address from clipboard - Vlož adresu ze schránky - - - Alt+P - Alt+P - - - Remove this entry - Smaž tento záznam - - - 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. - Poplatek se odečte od posílané částky. Příjemce tak dostane méně bitcoinů, než zadáš do pole Částka. Pokud vybereš více příjemců, tak se poplatek rovnoměrně rozloží. - - - S&ubtract fee from amount - Od&ečíst poplatek od částky - - - Message: - Zpráva: - - - This is an unauthenticated payment request. - Tohle je neověřený platební požadavek. - - - This is an authenticated payment request. - Tohle je ověřený platební požadavek. - - - Enter a label for this address to add it to the list of used addresses - Zadej označení této adresy; obojí se ti pak uloží do adresáře - - - 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. - Zpráva, která byla připojena k bitcoin: URI a která se ti pro přehled uloží k transakci. Poznámka: Tahle zpráva se neposílá s platbou po Bitcoinové síti. - - - Pay To: - Komu: - - - Memo: - Poznámka: - - - - ShutdownWindow - - Bitcoin Core is shutting down... - Bitcoin Core se ukončuje... - - - Do not shut down the computer until this window disappears. - Nevypínej počítač, dokud toto okno nezmizí. - - - - SignVerifyMessageDialog - - Signatures - Sign / Verify a Message - Podpisy - podepsat/ověřit zprávu - - - &Sign Message - &Podepiš zprávu - - - 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. - Podepsáním zprávy/smlouvy svými adresami můžeš prokázat, že jsi na ně schopen přijmout bitcoiny. Buď opatrný a nepodepisuj nic vágního nebo náhodného; například při phishingových útocích můžeš být lákán, abys něco takového podepsal. Podepisuj pouze naprosto úplná a detailní prohlášení, se kterými souhlasíš. - - - The Bitcoin address to sign the message with - Bitcoinová adresa, kterou se zpráva podepíše - - - Choose previously used address - Vyber již použitou adresu - - - Alt+A - Alt+A - - - Paste address from clipboard - Vlož adresu ze schránky - - - Alt+P - Alt+P - - - Enter the message you want to sign here - Sem vepiš zprávu, kterou chceš podepsat - - - Signature - Podpis - - - Copy the current signature to the system clipboard - Zkopíruj tento podpis do schránky - - - Sign the message to prove you own this Bitcoin address - Podepiš zprávu, čímž prokážeš, že jsi vlastníkem této Bitcoinové adresy - - - Sign &Message - Po&depiš zprávu - - - Reset all sign message fields - Vymaž všechna pole formuláře pro podepsání zrávy - - - Clear &All - Všechno &smaž - - - &Verify Message - &Ověř zprávu - - - 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! - K ověření podpisu zprávy zadej adresu příjemce, zprávu (ověř si, že správně kopíruješ zalomení řádků, mezery, tabulátory apod.) a podpis. Dávej pozor na to, abys nezkopíroval do podpisu víc, než co je v samotné podepsané zprávě, abys nebyl napálen man-in-the-middle útokem. Poznamenejme však, že takto lze pouze prokázat, že podepisující je schopný na dané adrese přijmout platbu, ale není možnéprokázat, že odeslal jakoukoli transakci! - - - The Bitcoin address the message was signed with - Bitcoinová adresa, kterou je zpráva podepsána - - - Verify the message to ensure it was signed with the specified Bitcoin address - Ověř zprávu, aby ses ujistil, že byla podepsána danou Bitcoinovou adresou - - - Verify &Message - O&věř zprávu - - - Reset all verify message fields - Vymaž všechna pole formuláře pro ověření zrávy - - - Click "Sign Message" to generate signature - Kliknutím na „Podepiš zprávu“ vygeneruješ podpis - - - The entered address is invalid. - Zadaná adresa je neplatná. - - - Please check the address and try again. - Zkontroluj ji prosím a zkus to pak znovu. - - - The entered address does not refer to a key. - Zadaná adresa nepasuje ke klíči. - - - Wallet unlock was cancelled. - Odemčení peněženky bylo zrušeno. - - - Private key for the entered address is not available. - Soukromý klíč pro zadanou adresu není dostupný. - - - Message signing failed. - Nepodařilo se podepsat zprávu. - - - Message signed. - Zpráva podepsána. - - - The signature could not be decoded. - Podpis nejde dekódovat. - - - Please check the signature and try again. - Zkontroluj ho prosím a zkus to pak znovu. - - - The signature did not match the message digest. - Podpis se neshoduje s hašem zprávy. - - - Message verification failed. - Nepodařilo se ověřit zprávu. - - - Message verified. - Zpráva ověřena. - - - - SplashScreen - - Bitcoin Core - Bitcoin Core - - - The Bitcoin Core developers - Vývojáři Bitcoin Core - - - [testnet] - [testnet] - - - - TrafficGraphWidget - - KB/s - kB/s - - - - TransactionDesc - - Open until %1 - Otřevřeno dokud %1 - - - conflicted - kolidující - - - %1/offline - %1/offline - - - %1/unconfirmed - %1/nepotvrzeno - - - %1 confirmations - %1 potvrzení - - - Status - Stav - - - , broadcast through %n node(s) - , rozesláno přes %n uzel, rozesláno přes %n uzly, rozesláno přes %n uzlů - - - Date - Datum - - - Source - Zdroj - - - Generated - Vygenerováno - - - From - Od - - - To - Pro - - - own address - vlastní adresa - - - watch-only - sledovaná - - - label - označení - - - Credit - Příjem - - - matures in %n more block(s) - dozraje po %n blokudozraje po %n blocíchdozraje po %n blocích - - - not accepted - neakceptováno - - - Debit - Výdaj - - - Total debit - Celkové výdaje - - - Total credit - Celkové příjmy - - - Transaction fee - Transakční poplatek - - - Net amount - Čistá částka - - - Message - Zpráva - - - Comment - Komentář - - - Transaction ID - ID transakce - - - Merchant - Obchodník - - - 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. - Vygenerované mince musí čekat %1 bloků, než mohou být utraceny. Když jsi vygeneroval tenhle blok, tak byl rozposlán do sítě, aby byl přidán do řetězce bloků. Pokud se mu nepodaří dostat se do řetězce, změní se na „neakceptovaný“ a nepůjde utratit. To se občas může stát, pokud jiný uzel vygeneruje blok zhruba ve stejném okamžiku jako ty. - - - Debug information - Ladicí informace - - - Transaction - Transakce - - - Inputs - Vstupy - - - Amount - Částka - - - true - true - - - false - false - - - , has not been successfully broadcast yet - , ještě nebylo rozesláno - - - Open for %n more block(s) - Otevřeno pro %n další blokOtevřeno pro %n další blokyOtevřeno pro %n dalších bloků - - - unknown - neznámo + Transaction Fee: + Transakční poplatek: - - - TransactionDescDialog - Transaction details - Detaily transakce + Choose... + Zvol... - This pane shows a detailed description of the transaction - Toto okno zobrazuje detailní popis transakce + collapse fee-settings + sbal nastavení poplatků - - - TransactionTableModel - Date - Datum + per kilobyte + za kilobajt - Type - Typ + If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte. + Pokud je vlastní poplatek nastavený na 1000 satoshi a transakce má pouze 250 bajtů, tak „za kilobajt“ zaplatí poplatek jen 250 satoshi, zatímco „přinejmenším“ zaplatí 1000 satoshi. Pro transakce větší než kilobajt obě možnosti platí za kilobajt. - Immature (%1 confirmations, will be available after %2) - Nedozráno (%1 potvrzení, dozraje při %2 potvrzeních) - - - Open for %n more block(s) - Otevřeno pro %n další blokOtevřeno pro %n další blokyOtevřeno pro %n dalších bloků + Hide + Skryj - Open until %1 - Otřevřeno dokud %1 + total at least + přinejmenším - Confirmed (%1 confirmations) - Potvrzeno (%1 potvrzení) + Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process. + Platit jen minimální poplatek je v pořádku, pokud je zrovna méně transakcí než místa v blocích. Ale počítej s tím, že to také může skončit transakcí, která nikdy nebude potvrzena, pokud je větší poptávka po bitcoinových transakcích, než síť zvládne zpracovat. - This block was not received by any other nodes and will probably not be accepted! - Tento blok nedostal žádný jiný uzel a pravděpodobně nebude akceptován! + (read the tooltip) + (viz bublina) - Generated but not accepted - Vygenerováno, ale neakceptováno + Recommended: + Doporučený: - Offline - Offline + Custom: + Vlastní: - Label - Označení + (Smart fee not initialized yet. This usually takes a few blocks...) + (Inteligentní poplatek ještě není inicializovaný. Obvykle mu to tak pár bloků trvá...) - Unconfirmed - Nepotvrzeno + Confirmation time: + Rychlost potvrzení: - Confirming (%1 of %2 recommended confirmations) - Potvrzuje se (%1 z %2 doporučených potvrzení) + normal + normální - Conflicted - V kolizi + fast + rychlá - Received with - Přijato do + Send to multiple recipients at once + Pošli více příjemcům naráz - Received from - Přijato od + Add &Recipient + Při&dej příjemce - Sent to - Posláno na + Clear all fields of the form. + Promaž obsah ze všech formulářových políček. - Payment to yourself - Platba sama sobě + Dust: + Prach: - Mined - Vytěženo + Clear &All + Všechno s&maž - watch-only - sledovací + Balance: + Stav účtu: - (n/a) - (n/a) + Confirm the send action + Potvrď odeslání - Transaction status. Hover over this field to show number of confirmations. - Stav transakce. Najetím myši na toto políčko si zobrazíš počet potvrzení. + S&end + Pošl&i + + + SendCoinsEntry - Date and time that the transaction was received. - Datum a čas přijetí transakce. + A&mount: + Čás&tka: - Type of transaction. - Druh transakce. + Pay &To: + &Komu: - Whether or not a watch-only address is involved in this transaction. - Zda tato transakce zahrnuje i některou sledovanou adresu. + &Label: + O&značení: - User-defined intent/purpose of the transaction. - Uživatelsky určený účel transakce. + Choose previously used address + Vyber již použitou adresu - Amount removed from or added to balance. - Částka odečtená z nebo přičtená k účtu. + This is a normal payment. + Tohle je normální platba. - - - TransactionView - All - Vše + The Bitcoin address to send the payment to + Bitcoinová adresa příjemce - Today - Dnes + Alt+A + Alt+A - This week - Tento týden + Paste address from clipboard + Vlož adresu ze schránky - This month - Tento měsíc + Alt+P + Alt+P - Last month - Minulý měsíc + Remove this entry + Smaž tento záznam - This year - Letos + 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. + Poplatek se odečte od posílané částky. Příjemce tak dostane méně bitcoinů, než zadáš do pole Částka. Pokud vybereš více příjemců, tak se poplatek rovnoměrně rozloží. - Range... - Rozsah... + S&ubtract fee from amount + Od&ečíst poplatek od částky - Received with - Přijato + Message: + Zpráva: - Sent to - Posláno + This is an unauthenticated payment request. + Tohle je neověřený platební požadavek. - To yourself - Sám sobě + This is an authenticated payment request. + Tohle je ověřený platební požadavek. - Mined - Vytěženo + Enter a label for this address to add it to the list of used addresses + Zadej označení této adresy; obojí se ti pak uloží do adresáře - Other - Ostatní + 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. + Zpráva, která byla připojena k bitcoin: URI a která se ti pro přehled uloží k transakci. Poznámka: Tahle zpráva se neposílá s platbou po Bitcoinové síti. - Enter address or label to search - Zadej adresu nebo označení pro její vyhledání + Pay To: + Komu: - Min amount - Minimální částka + Memo: + Poznámka: + + + ShutdownWindow - Copy address - Kopíruj adresu + Do not shut down the computer until this window disappears. + Nevypínej počítač, dokud toto okno nezmizí. + + + SignVerifyMessageDialog - Copy label - Kopíruj její označení + Signatures - Sign / Verify a Message + Podpisy - podepsat/ověřit zprávu - Copy amount - Kopíruj částku + &Sign Message + &Podepiš zprávu - Copy transaction ID - Kopíruj ID transakce + 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. + Podepsáním zprávy/smlouvy svými adresami můžeš prokázat, že jsi na ně schopen přijmout bitcoiny. Buď opatrný a nepodepisuj nic vágního nebo náhodného; například při phishingových útocích můžeš být lákán, abys něco takového podepsal. Podepisuj pouze naprosto úplná a detailní prohlášení, se kterými souhlasíš. - Copy raw transaction - Kopíruj surovou transakci + The Bitcoin address to sign the message with + Bitcoinová adresa, kterou se zpráva podepíše - Edit label - Uprav označení + Choose previously used address + Vyber již použitou adresu - Show transaction details - Zobraz detaily transakce + Alt+A + Alt+A - Export Transaction History - Exportuj transakční historii + Paste address from clipboard + Vlož adresu ze schránky - Watch-only - Sledovaná + Alt+P + Alt+P - Exporting Failed - Exportování selhalo + Enter the message you want to sign here + Sem vepiš zprávu, kterou chceš podepsat - There was an error trying to save the transaction history to %1. - Při ukládání transakční historie do %1 se přihodila nějaká chyba. + Signature + Podpis - Exporting Successful - Úspěšně vyexportováno + Copy the current signature to the system clipboard + Zkopíruj tento podpis do schránky - The transaction history was successfully saved to %1. - Transakční historie byla v pořádku uložena do %1. + Sign the message to prove you own this Bitcoin address + Podepiš zprávu, čímž prokážeš, že jsi vlastníkem této Bitcoinové adresy - Comma separated file (*.csv) - Formát CSV (*.csv) + Sign &Message + Po&depiš zprávu - Confirmed - Potvrzeno + Reset all sign message fields + Vymaž všechna pole formuláře pro podepsání zrávy - Date - Datum + Clear &All + Všechno &smaž - Type - Typ + &Verify Message + &Ověř zprávu - Label - Označení + 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! + K ověření podpisu zprávy zadej adresu příjemce, zprávu (ověř si, že správně kopíruješ zalomení řádků, mezery, tabulátory apod.) a podpis. Dávej pozor na to, abys nezkopíroval do podpisu víc, než co je v samotné podepsané zprávě, abys nebyl napálen man-in-the-middle útokem. Poznamenejme však, že takto lze pouze prokázat, že podepisující je schopný na dané adrese přijmout platbu, ale není možnéprokázat, že odeslal jakoukoli transakci! - Address - Adresa + The Bitcoin address the message was signed with + Bitcoinová adresa, kterou je zpráva podepsána - ID - ID + Verify the message to ensure it was signed with the specified Bitcoin address + Ověř zprávu, aby ses ujistil, že byla podepsána danou Bitcoinovou adresou - Range: - Rozsah: + Verify &Message + O&věř zprávu - to - + Reset all verify message fields + Vymaž všechna pole formuláře pro ověření zrávy - UnitDisplayStatusBarControl + SplashScreen - Unit to show amounts in. Click to select another unit. - Jednotka pro částky. Klikni pro výběr nějaké jiné. + [testnet] + [testnet] - WalletFrame + TrafficGraphWidget - No wallet has been loaded. - Žádná peněženka se nenačetla. + KB/s + kB/s - WalletModel + TransactionDescDialog - Send Coins - Pošli mince + This pane shows a detailed description of the transaction + Toto okno zobrazuje detailní popis transakce - WalletView - - &Export - &Export - - - Export the data in the current tab to a file - Exportuj data z tohoto panelu do souboru - - - Backup Wallet - Záloha peněženky - - - Wallet Data (*.dat) - Data peněženky (*.dat) - - - Backup Failed - Zálohování selhalo - - - There was an error trying to save the wallet data to %1. - Při ukládání peněženky do %1 se přihodila nějaká chyba. - - - The wallet data was successfully saved to %1. - Data z peněženky byla v pořádku uložena do %1. - + UnitDisplayStatusBarControl - Backup Successful - Úspěšně zazálohováno + Unit to show amounts in. Click to select another unit. + Jednotka pro částky. Klikni pro výběr nějaké jiné. @@ -2883,10 +1622,6 @@ If <category> is not supplied or if <category> = 1, output all debugging information. Pokud není <category> zadána nebo je <category> = 1, bude tisknout veškeré ladicí informace. - - Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. - Prosím zkontrolujte nastavení času na svém počítači. Pokud čas a datum není nastaven správně, Bitcoin Core nebude fungovat! - Prune configured below the minimum of %d MiB. Please use a higher number. Prořezávání je nastaveno pod minimum %d MiB. Použij, prosím, nějaké vyšší číslo. @@ -2927,6 +1662,10 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Přijímat spojení zvenčí (výchozí: 1, pokud není zadáno -proxy nebo -connect) + + Bitcoin Core + Bitcoin Core + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. -fallbackfee je nastaveno velmi vysoko! Toto je transakční poplatek, který bys platil, pokud nebude k dispozici odhad poplatků. @@ -2971,14 +1710,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Tohle je testovací verze – používej ji jen na vlastní riziko, ale rozhodně ji nepoužívej k těžbě nebo pro obchodní aplikace - - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - Nedaří se mi připojit na %s na tomhle počítači. Bitcoin Core už pravděpodobně jednou běží. - - - Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. - Nepodporovaný argument -whitelistalwaysrelay se ignoruje, použij -whitelistrelay a/nebo -whitelistforcerelay. - Use UPnP to map the listening port (default: 1 when listening and no -proxy) Použít UPnP k namapování naslouchacího portu (výchozí: 1, pokud naslouchá a nepoužívá -proxy) @@ -2999,10 +1730,6 @@ Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Upozornění: Nesouhlasím zcela se svými protějšky! Možná potřebuji aktualizovat nebo ostatní uzly potřebují aktualizovat. - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Upozornění: soubor wallet.dat je poškozený, data jsou však zachráněna! Původní soubor wallet.dat je uložený jako wallet.{timestamp}.bak v %s. Pokud jsou stav tvého účtu nebo transakce nesprávné, zřejmě bys měl obnovit zálohu. - Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. Vždy vítat protějšky připojující se z dané podsítě či IP adresy. Lze zadat i vícekrát. @@ -3167,10 +1894,6 @@ Wallet options: Možnosti peněženky: - - You need to rebuild the database using -reindex to change -txindex - Je třeba přestavět databázi použitím -reindex, aby bylo možné změnit -txindex - 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 Povolit JSON-RPC spojení ze specifikovaného zdroje. Platnou hodnotou <ip> je jednotlivá IP adresa (např. 1.2.3.4), síť/maska (např. 1.2.3.4/255.255.255.0) nebo síť/CIDR (např. 1.2.3.4/24). Tuto volbu lze použít i vícekrát @@ -3183,10 +1906,6 @@ Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces) Čekat na zadané adrese na JSON-RPC spojení. Pro zápis IPv6 adresy použij notaci [adresa]:port. Tuto volbu lze použít i vícekrát (výchozí: poslouchat na všech rozhraních) - - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - Nedaří se mi získat zámek na datový adresář %s. Bitcoin Core pravděpodobně už jednou běží. - Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) Vytvářet nové soubory s výchozími systémovými právy namísto umask 077 (uplatní se, pouze pokud je vypnutá funkce peněženky) @@ -3231,10 +1950,6 @@ Set maximum size of high-priority/low-fee transactions in bytes (default: %d) Nastavit maximální velikost prioritních/nízkopoplatkových transakcí v bajtech (výchozí: %d) - - Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) - Nastavení počtu vláken pro těžení, je-li zapnuté (-1 = všechna jádra, výchozí: %d) - The transaction amount is too small to send after the fee has been deducted Částka v transakci po odečtení poplatku je příliš malá na odeslání @@ -3259,34 +1974,14 @@ Accept public REST requests (default: %u) Přijímat veřejné REST požadavky (výchozí: %u) - - Activating best chain... - Aktivuji nejlepší řetězec... - - - Attempt to recover private keys from a corrupt wallet.dat on startup - Pokusit se při startu zachránit soukromé klíče z poškozeného souboru wallet.dat - Automatically create Tor hidden service (default: %d) Automaticky v Toru vytvářet skryté služby (výchozí: %d) - - Cannot resolve -whitebind address: '%s' - Nemohu přeložit -whitebind adresu: '%s' - Connect through SOCKS5 proxy Připojit se přes SOCKS5 proxy - - Copyright (C) 2009-%i The Bitcoin Core Developers - Copyright (C) 2009-%i Vývojáři Bitcoin Core - - - Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - Chyba při načítání wallet.dat: peněženka vyžaduje novější verzi Bitcoin Core - Error reading from database, shutting down. Chyba při čtení z databáze, ukončuji se. @@ -3299,22 +1994,6 @@ Information Informace - - Initialization sanity check failed. Bitcoin Core is shutting down. - Selhala úvodní zevrubná prověrka. Bitcoin Core se ukončuje. - - - Invalid amount for -maxtxfee=<amount>: '%s' - Neplatná částka pro -maxtxfee=<amount>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Neplatná částka pro -minrelaytxfee=<částka>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - Neplatná částka pro -mintxfee=<částka>: '%s' - Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) Neplatná částka pro -paytxfee=<částka>: '%s' (musí být alespoň %s) @@ -3339,14 +2018,6 @@ RPC server options: Možnosti RPC serveru: - - Rebuild block chain index from current blk000??.dat files on startup - Při startu znovu vytvořit index řetězce bloků z aktuálních blk000??.dat souborů - - - Receive and display P2P network alerts (default: %u) - Přijímat a zobrazovat poplachy z P2P sítě (výchozí: %u) - Reducing -maxconnections from %d to %d, because of system limitations. Omezuji -maxconnections z %d na %d kvůli systémovým omezením. @@ -3419,10 +2090,6 @@ Username for JSON-RPC connections Uživatelské jméno pro JSON-RPC spojení - - Wallet needed to be rewritten: restart Bitcoin Core to complete - Soubor s peněženkou potřeboval přepsat: restartuj Bitcoin Core, aby se operace dokončila - Warning Upozornění @@ -3439,10 +2106,6 @@ ZeroMQ notification options: Možnosti ZeroMQ oznámení: - - wallet.dat corrupt, salvage failed - Soubor wallet.dat je poškozen, jeho záchrana se nezdařila - Password for JSON-RPC connections Heslo pro JSON-RPC spojení @@ -3451,10 +2114,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) Spustit příkaz, když se změní nejlepší blok (%s se v příkazu nahradí hashem bloku) - - This help message - Tato nápověda - Allow DNS lookups for -addnode, -seednode and -connect Povolit DNS dotazy pro -addnode (přidání uzlu), -seednode a -connect (připojení) @@ -3463,10 +2122,6 @@ Loading addresses... Načítám adresy... - - Error loading wallet.dat: Wallet corrupted - Chyba při načítání wallet.dat: peněženka je poškozená - (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) (1 = ukládat transakční metadata, např. majitele účtu a informace o platebním požadavku, 2 = mazat transakční metadata) @@ -3483,10 +2138,6 @@ Do not keep transactions in the mempool longer than <n> hours (default: %u) Nedržet transakce v zásobníku déle než <n> hodin (výchozí: %u) - - Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. - Nastala chyba při čtení souboru wallet.dat! Všechny klíče se přečetly správně, ale data o transakcích nebo záznamy v adresáři mohou chybět či být nesprávné. - Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) Poplatky (v %s/kB) menší než tato hodnota jsou považovány za nulové pro účely vytváření transakcí (výchozí: %s) @@ -3523,6 +2174,10 @@ Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported. Byl použit nepodporovaný argument -socks. Nastavení verze SOCKS už není možné, podporovány jsou pouze SOCKS5 proxy. + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + Nepodporovaný argument -whitelistalwaysrelay se ignoruje, použij -whitelistrelay a/nebo -whitelistforcerelay. + Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s) Použít samostatnou SOCKS5 proxy ke spojení s protějšky přes skryté služby v Toru (výchozí: %s) @@ -3539,14 +2194,6 @@ Always query for peer addresses via DNS lookup (default: %u) Vždy získávat adresy dalších protějšků přes DNS (výchozí: %u) - - Error loading wallet.dat - Chyba při načítání wallet.dat - - - Generate coins (default: %u) - Těžit (výchozí: %u) - How many blocks to check at startup (default: %u, 0 = all) Kolik bloků při startu zkontrolovat (výchozí: %u, 0 = všechny) @@ -3627,18 +2274,6 @@ Unknown network specified in -onlynet: '%s' V -onlynet byla uvedena neznámá síť: '%s' - - Cannot resolve -bind address: '%s' - Nemohu přeložit -bind adresu: '%s' - - - Cannot resolve -externalip address: '%s' - Nemohu přeložit -externalip adresu: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - Neplatná částka pro -paytxfee=<částka>: '%s' - Insufficient funds Nedostatek prostředků diff --git a/src/qt/locale/bitcoin_cs_CZ.ts b/src/qt/locale/bitcoin_cs_CZ.ts index 34d7b4b4a1644..70aa981f5036d 100644 --- a/src/qt/locale/bitcoin_cs_CZ.ts +++ b/src/qt/locale/bitcoin_cs_CZ.ts @@ -29,25 +29,6 @@ &Delete &Odstranit - - Comma separated file (*.csv) - Textový soubor oddělený středníkem (*.csv) - - - - AddressTableModel - - Label - Popis - - - Address - Adresa - - - (no label) - (bez popisu) - AskPassphraseDialog @@ -63,63 +44,7 @@ Repeat new passphrase Zopakujte nové heslo - - Encrypt wallet - Zašifrovat peněženku - - - This operation needs your wallet passphrase to unlock the wallet. - Tato operace vyžaduje heslo k odemknutí peněženky. - - - Unlock wallet - Odemknout peněženku - - - This operation needs your wallet passphrase to decrypt the wallet. - Tato operace vyžaduje heslo k dešifrování peněženky. - - - Decrypt wallet - Dešifrovat peněženku - - - Change passphrase - Změnit heslo - - - Confirm wallet encryption - Potvrďte zašifrování peněženky - - - Wallet encrypted - Peněženka zašifrována - - - Wallet encryption failed - Zašifrování peněženky selhalo - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Šifrování peněženky selhalo vinou vnitřní chyby. Vaše peněženka nebyla zašifrována. - - - The supplied passphrases do not match. - Zadaná hesla nejsou shodná. - - - Wallet unlock failed - Odemčení peněženky selhalo - - - The passphrase entered for the wallet decryption was incorrect. - Heslo zadané k dešifrování peněženky nebylo správné - - - Wallet decryption failed - Deěifrování peněženky selhalo - - + BanTableModel @@ -202,9 +127,6 @@ Peněženka je <b>zašifrována</b> a momentálně <b>uzamčená</b> - - ClientModel - CoinControlDialog @@ -223,18 +145,6 @@ Confirmed Potvrzeno - - Copy address - Kopírovat sdresu - - - Copy label - Kopírovat popis - - - (no label) - (bez popisu) - EditAddressDialog @@ -250,34 +160,6 @@ &Address &Adresa - - New receiving address - Nová adresa pro příjem - - - New sending address - Nová adresa k odeslání - - - Edit receiving address - Upravit adresu pro příjem - - - Edit sending address - Upravit adresu k odeslání - - - The entered address "%1" is already in the address book. - Zadaná adresa "%1" se již v seznamu adres nachází. - - - Could not unlock wallet. - Nemohu odemknout peněženku - - - New key generation failed. - Generování nového klíče selhalo. - FreespaceChecker @@ -317,9 +199,6 @@ OverviewPage - - PaymentServer - PeerTableModel @@ -330,9 +209,6 @@ Množství - - QRImageWidget - RPCConsole @@ -350,52 +226,9 @@ &Message: Zpráva: - - Copy label - Kopírovat popis - ReceiveRequestDialog - - Address - Adresa - - - Amount - Množství - - - Label - Popis - - - Message - Zpráva - - - - RecentRequestsTableModel - - Date - Datum - - - Label - Popis - - - Message - Zpráva - - - Amount - Množství - - - (no label) - (bez popisu) - SendCoinsDialog @@ -407,14 +240,6 @@ Balance: Zůstatek: - - The amount to pay must be larger than 0. - Částka k zaplacení musí být větší než 0. - - - (no label) - (bez popisu) - SendCoinsEntry @@ -443,210 +268,16 @@ TrafficGraphWidget - - TransactionDesc - - %1/unconfirmed - %1 potvrzeno - - - %1 confirmations - %1 potvrzení - - - Status - Stav - - - Date - Datum - - - Message - Zpráva - - - Transaction - Transakce - - - Amount - Množství - - TransactionDescDialog - - Transaction details - Detaily transakce - This pane shows a detailed description of the transaction Toto podokno zobrazuje detailní popis transakce - - TransactionTableModel - - Date - Datum - - - Type - Typ - - - Confirmed (%1 confirmations) - Potvrzeno (%1 potvrzení) - - - This block was not received by any other nodes and will probably not be accepted! - Tento blok nebyl přijat žádným dalším uzlem a pravděpodobně nebude akceptován! - - - Label - Popis - - - Received with - Přijato s - - - Sent to - Odesláno na - - - Payment to yourself - Platba sobě samému - - - Mined - Vytěženo - - - Type of transaction. - Typ transakce. - - - - TransactionView - - All - Vše - - - Today - Dnes - - - This week - Tento týden - - - This month - Tento měsíc - - - Last month - Minulý měsíc - - - This year - Tento rok - - - Range... - Rozsah... - - - Received with - Přijato s - - - Sent to - Odesláno na - - - To yourself - Sobě samému - - - Mined - Vytěženo - - - Other - Ostatní - - - Min amount - Min. množství - - - Copy address - Kopírovat sdresu - - - Copy label - Kopírovat popis - - - Edit label - Upravit popis - - - Comma separated file (*.csv) - Textový soubor oddělený středníkem (*.csv) - - - Confirmed - Potvrzeno - - - Date - Datum - - - Type - Typ - - - Label - Popis - - - Address - Adresa - - - ID - ID - - - Range: - Rozsah: - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - - WalletView - - &Export - &Exportovat - - - Export the data in the current tab to a file - Exportovat aktuální pohled do souboru - - bitcoin-core diff --git a/src/qt/locale/bitcoin_cy.ts b/src/qt/locale/bitcoin_cy.ts index c32d236a919e2..38bc45775bc1a 100644 --- a/src/qt/locale/bitcoin_cy.ts +++ b/src/qt/locale/bitcoin_cy.ts @@ -21,10 +21,6 @@ C&lose C&au - - &Copy Address - &Cyfeiriad Copi - &Export &Allforio @@ -33,49 +29,6 @@ &Delete &Dileu - - C&hoose - &Dewis - - - Sending addresses - Cyfeiriadau anfon - - - Receiving addresses - Cyfeiriadau derbyn - - - Copy &Label - Copïo &Label - - - &Edit - &Golygu - - - Export Address List - Allforio Rhestr Cyfeiriad - - - Exporting Failed - Methodd Allfor - - - - AddressTableModel - - Label - Label - - - Address - Cyfeiriad - - - (no label) - (heb label) - AskPassphraseDialog @@ -91,63 +44,7 @@ Repeat new passphrase Ailadroddwch gyfrinymadrodd newydd - - Encrypt wallet - Amgryptio'r waled - - - This operation needs your wallet passphrase to unlock the wallet. - Mae angen i'r gweithred hon ddefnyddio'ch cyfrinymadrodd er mwyn datgloi'r waled. - - - Unlock wallet - Datgloi'r waled - - - This operation needs your wallet passphrase to decrypt the wallet. - Mae angen i'r gweithred hon ddefnyddio'ch cyfrinymadrodd er mwyn dadgryptio'r waled. - - - Decrypt wallet - Dadgryptio'r waled - - - Change passphrase - Newid cyfrinymadrodd - - - Confirm wallet encryption - Cadarnau amgryptiad y waled - - - Are you sure you wish to encrypt your wallet? - Ydych chi'n siwr eich bod chi eisiau amgryptio dy waled di? - - - Wallet encrypted - Waled wedi'i amgryptio - - - Wallet encryption failed - Amgryptiad waled wedi methu - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Methodd amgryptiad y waled oherwydd gwall mewnol. Ni amgryptwyd eich waled. - - - The supplied passphrases do not match. - Dydy'r cyfrinymadroddion a ddarparwyd ddim yn cyd-fynd â'u gilydd. - - - Wallet unlock failed - Methodd ddatgloi'r waled - - - Wallet decryption failed - Methodd dadgryptiad y waled - - + BanTableModel @@ -229,10 +126,6 @@ &Receive &Derbyn - - Show information about Bitcoin Core - Dangos gwybodaeth am Graidd Bitcoin - &Show / Hide &Dangos / Cuddio @@ -253,14 +146,6 @@ Tabs toolbar Bar offer tabiau - - Bitcoin Core - Craidd Bitcoin - - - &About Bitcoin Core - &Ynghylch Craidd Bitcoin - %n hour(s) %n awr%n awr%n awr%n awr @@ -342,9 +227,6 @@ Mae'r waled <b>wedi'i amgryptio</b> ac <b>ar glo</b> ar hyn o bryd - - ClientModel - CoinControlDialog @@ -355,23 +237,7 @@ Date Dyddiad - - Copy address - Cyfeiriad copi - - - Copy label - Copïo label - - - (no label) - (heb label) - - - (change) - (newid) - - + EditAddressDialog @@ -386,34 +252,6 @@ &Address &Cyfeiriad - - New receiving address - Cyfeiriad derbyn newydd - - - New sending address - Cyfeiriad anfon newydd - - - Edit receiving address - Golygu'r cyfeiriad derbyn - - - Edit sending address - Golygu'r cyfeiriad anfon - - - The entered address "%1" is already in the address book. - Mae'r cyfeiriad "%1" sydd newydd gael ei geisio gennych yn y llyfr cyfeiriad yn barod. - - - Could not unlock wallet. - Methodd ddatgloi'r waled. - - - New key generation failed. - Methodd gynhyrchu allwedd newydd. - FreespaceChecker @@ -424,14 +262,6 @@ HelpMessageDialog - - Bitcoin Core - Craidd Bitcoin - - - About Bitcoin Core - Ynghylch Craidd Bitcoin - Usage: Cynefod: @@ -443,14 +273,6 @@ Welcome Croeso - - Welcome to Bitcoin Core. - Croeso i Graidd Bitcoin - - - Bitcoin Core - Craidd Bitcoin - Error Gwall @@ -509,18 +331,12 @@ Ffurflen - - PaymentServer - PeerTableModel QObject - - QRImageWidget - RPCConsole @@ -542,10 +358,6 @@ &Label: &Label: - - Copy label - Copïo label - ReceiveRequestDialog @@ -553,37 +365,6 @@ Copy &Address &Cyfeiriad Copi - - Address - Cyfeiriad - - - Label - Label - - - Message - Neges - - - - RecentRequestsTableModel - - Date - Dyddiad - - - Label - Label - - - Message - Neges - - - (no label) - (heb label) - SendCoinsDialog @@ -607,14 +388,6 @@ Confirm the send action Cadarnhau'r gweithrediad anfon - - %1 to %2 - %1 i %2 - - - (no label) - (heb label) - SendCoinsEntry @@ -663,14 +436,6 @@ SplashScreen - - Bitcoin Core - Craidd Bitcoin - - - The Bitcoin Core developers - Datblygwyr Graidd Bitcoin - [testnet] [testnet] @@ -679,108 +444,22 @@ TrafficGraphWidget - - TransactionDesc - - Open until %1 - Agor tan %1 - - - Date - Dyddiad - - - Message - Neges - - TransactionDescDialog - - TransactionTableModel - - Date - Dyddiad - - - Type - Math - - - Open until %1 - Agor tan %1 - - - Label - Label - - - - TransactionView - - Today - Heddiw - - - This year - Eleni - - - Copy address - Cyfeiriad copi - - - Copy label - Copïo label - - - Exporting Failed - Methodd Allfor - - - Date - Dyddiad - - - Type - Math - - - Label - Label - - - Address - Cyfeiriad - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - Send Coins - Anfon arian - - - - WalletView - - &Export - &Allforio - - bitcoin-core Options: Opsiynau: + + Bitcoin Core + Craidd Bitcoin + Information Gwybodaeth diff --git a/src/qt/locale/bitcoin_da.ts b/src/qt/locale/bitcoin_da.ts index 7d11825a618a7..91903088cf5a4 100644 --- a/src/qt/locale/bitcoin_da.ts +++ b/src/qt/locale/bitcoin_da.ts @@ -25,10 +25,6 @@ C&lose &Luk - - &Copy Address - &Kopiér adresse - Delete the currently selected address from the list Slet den markerede adresse fra listen @@ -45,73 +41,6 @@ &Delete &Slet - - Choose the address to send coins to - Vælg adresse at sende bitcoins til - - - Choose the address to receive coins with - Vælg adresse at modtage bitcoins med - - - C&hoose - &Vælg - - - Sending addresses - Afsendelsesadresser - - - Receiving addresses - Modtagelsesadresser - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Disse er dine Bitcoin-adresser for at sende betalinger. Tjek altid beløb og modtageradresse, inden du sender bitcoins. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Dette er dine Bitcoin-adresser til at modtage betalinger med. Det anbefales are bruge en ny modtagelsesadresse for hver transaktion. - - - Copy &Label - Kopiér &mærkat - - - &Edit - &Redigér - - - Export Address List - Eksportér adresseliste - - - Comma separated file (*.csv) - Kommasepareret fil (*.csv) - - - Exporting Failed - Eksport mislykkedes - - - There was an error trying to save the address list to %1. Please try again. - Der opstod en fejl under gemning af adresselisten til %1. Prøv venligst igen. - - - - AddressTableModel - - Label - Mærkat - - - Address - Adresse - - - (no label) - (ingen mærkat) - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase Gentag ny adgangskode - - Encrypt wallet - Kryptér tegnebog - - - This operation needs your wallet passphrase to unlock the wallet. - Denne funktion har brug for din tegnebogs adgangskode for at låse tegnebogen op. - - - Unlock wallet - Lås tegnebog op - - - This operation needs your wallet passphrase to decrypt the wallet. - Denne funktion har brug for din tegnebogs adgangskode for at dekryptere tegnebogen. - - - Decrypt wallet - Dekryptér tegnebog - - - Change passphrase - Skift adgangskode - - - Confirm wallet encryption - Bekræft tegnebogskryptering - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Advarsel: Hvis du krypterer din tegnebog og mister din adgangskode, vil du <b>MISTE ALLE DINE BITCOINS</b>! - - - Are you sure you wish to encrypt your wallet? - Er du sikker på, at du ønsker at kryptere din tegnebog? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Bitcoin Core vil nu lukke for at færdiggøre krypteringsprocessen. Husk at kryptering af din tegnebog kan ikke beskytte dine bitcoin fuldt ud mod at blive stjålet af eventuel malware, der måtte have inficeret din computer. - - - 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. - VIGTIGT: Enhver tidligere sikkerhedskopi, som du har lavet af tegnebogsfilen, bør blive erstattet af den nyligt genererede, krypterede tegnebogsfil. Af sikkerhedsmæssige årsager vil tidligere sikkerhedskopier af den ikke-krypterede tegnebogsfil blive ubrugelige i det øjeblik, du starter med at anvende den nye, krypterede tegnebog. - - - Warning: The Caps Lock key is on! - Advarsel: Caps Lock-tasten er aktiveret! - - - Wallet encrypted - Tegnebog krypteret - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Indtast det nye kodeord til tegnebogen.<br/>Brug venligst et kodeord på <b>ti eller flere tilfældige tegn</b> eller <b>otte eller flere ord</b>. - - - Enter the old passphrase and new passphrase to the wallet. - Indtast den gamle adgangskode og en ny adgangskode til tegnebogen. - - - Wallet encryption failed - Tegnebogskryptering mislykkedes - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Tegnebogskryptering mislykkedes på grund af en intern fejl. Din tegnebog blev ikke krypteret. - - - The supplied passphrases do not match. - De angivne adgangskoder stemmer ikke overens. - - - Wallet unlock failed - Tegnebogsoplåsning mislykkedes - - - The passphrase entered for the wallet decryption was incorrect. - Den angivne adgangskode for tegnebogsdekrypteringen er forkert. - - - Wallet decryption failed - Tegnebogsdekryptering mislykkedes - - - Wallet passphrase was successfully changed. - Tegnebogens adgangskode blev ændret. - BanTableModel @@ -269,6 +110,14 @@ Quit application Afslut program + + &About %1 + &Om %1 + + + Show information about %1 + Vis informationer om %1 + About &Qt Om &Qt @@ -281,6 +130,10 @@ &Options... &Indstillinger… + + Modify configuration options for %1 + Redigér konfigurationsindstillinger for %1 + &Encrypt Wallet... &Kryptér tegnebog… @@ -305,14 +158,6 @@ Open &URI... &Åbn URI… - - Bitcoin Core client - Bitcoin Core-klient - - - Importing blocks from disk... - Importerer blokke fra disken… - Reindexing blocks on disk... Genindekserer blokke på disken… @@ -357,10 +202,6 @@ &Receive &Modtag - - Show information about Bitcoin Core - Vis oplysninger om Bitcoin Core - &Show / Hide &Vis / skjul @@ -397,22 +238,10 @@ Tabs toolbar Faneværktøjslinje - - Bitcoin Core - Bitcoin Core - Request payments (generates QR codes and bitcoin: URIs) Anmod om betalinger (genererer QR-koder og "bitcoin:"-URI'er) - - &About Bitcoin Core - &Om Bitcoin Core - - - Modify configuration options for Bitcoin Core - Ændr opsætning af Bitcoin Core - Show the list of used sending addresses and labels Vis listen over brugte afsendelsesadresser og -mærkater @@ -429,14 +258,18 @@ &Command-line options Tilvalg for &kommandolinje - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Vis Bitcoin Core hjælpebesked for at få en liste over mulige tilvalg for Bitcoin kommandolinje - %n active connection(s) to Bitcoin network %n aktiv forbindelse til Bitcoin-netværket%n aktive forbindelser til Bitcoin-netværket + + Indexing blocks on disk... + Genindekserer blokke på disken… + + + Processing blocks on disk... + Bearbejder blokke på disken… + No block source available... Ingen blokkilde tilgængelig… @@ -493,6 +326,14 @@ Up to date Opdateret + + Show the %1 help message to get a list with possible Bitcoin command-line options + Vis %1 hjælpebesked for at få en liste over mulige tilvalg for Bitcoin kommandolinje + + + %1 client + %1-klient + Catching up... Indhenter… @@ -544,13 +385,6 @@ Tegnebog er <b>krypteret</b> og i øjeblikket <b>låst</b> - - ClientModel - - Network Alert - Netværksadvarsel - - CoinControlDialog @@ -629,150 +463,6 @@ Priority Prioritet - - Copy address - Kopiér adresse - - - Copy label - Kopiér mærkat - - - Copy amount - Kopiér beløb - - - Copy transaction ID - Kopiér transaktions-ID - - - Lock unspent - Fastlås ubrugte - - - Unlock unspent - Lås ubrugte op - - - Copy quantity - Kopiér mængde - - - Copy fee - Kopiér gebyr - - - Copy after fee - Kopiér efter-gebyr - - - Copy bytes - Kopiér byte - - - Copy priority - Kopiér prioritet - - - Copy dust - Kopiér støv - - - Copy change - Kopiér byttepenge - - - highest - højest - - - higher - højere - - - high - højt - - - medium-high - mellemhøj - - - medium - medium - - - low-medium - mellemlav - - - low - lav - - - lower - lavere - - - lowest - lavest - - - (%1 locked) - (%1 fastlåst) - - - none - ingen - - - This label turns red if the transaction size is greater than 1000 bytes. - Denne mærkat bliver rød, hvis transaktionsstørrelsen er større end 1000 byte. - - - This label turns red if the priority is smaller than "medium". - Denne mærkat bliver rød, hvis prioriteten er mindre end "medium". - - - This label turns red if any recipient receives an amount smaller than %1. - Denne mærkat bliver rød, hvis en eller flere modtagere modtager et beløb, der er mindre end %1. - - - Can vary +/- %1 satoshi(s) per input. - Kan variere med +/- %1 satoshi per input. - - - yes - ja - - - no - nej - - - This means a fee of at least %1 per kB is required. - Dette betyder, at et gebyr på mindst %1 pr. kB er nødvendigt. - - - Can vary +/- 1 byte per input. - Kan variere ±1 byte pr. input. - - - Transactions with higher priority are more likely to get included into a block. - Transaktioner med højere prioritet har højere sansynlighed for at blive inkluderet i en blok. - - - (no label) - (ingen mærkat) - - - change from %1 (%2) - byttepenge fra %1 (%2) - - - (change) - (byttepange) - EditAddressDialog @@ -796,38 +486,6 @@ &Address &Adresse - - New receiving address - Ny modtagelsesadresse - - - New sending address - Ny afsendelsesadresse - - - Edit receiving address - Redigér modtagelsesadresse - - - Edit sending address - Redigér afsendelsesadresse - - - The entered address "%1" is already in the address book. - Den indtastede adresse "%1" er allerede i adressebogen. - - - The entered address "%1" is not a valid Bitcoin address. - Den indtastede adresse "%1" er ikke en gyldig Bitcoin-adresse. - - - Could not unlock wallet. - Kunne ikke låse tegnebog op. - - - New key generation failed. - Ny nøglegenerering mislykkedes. - FreespaceChecker @@ -854,10 +512,6 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin Core - version version @@ -867,8 +521,8 @@ (%1-bit) - About Bitcoin Core - Om Bitcoin Core + About %1 + Om %1 Command-line options @@ -907,7 +561,7 @@ Vis startskærm under opstart (standard: %u) - Reset all settings changes made over the GUI + Reset all settings changed in the GUI Nulstil alle indstillinger, der er foretaget i den grafiske brugerflade @@ -918,16 +572,16 @@ Velkommen - Welcome to Bitcoin Core. - Velkommen til Bitcoin Core. + Welcome to %1. + Velkommen til %1. - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - Siden dette er første gang, programmet startes, kan du vælge, hvor Bitcoin Core skal gemme sin data. + As this is the first time the program is launched, you can choose where %1 will store its data. + Siden dette er første gang, programmet startes, kan du vælge, hvor %1 skal gemme sin data. - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - Bitcoin Core vil downloade og gemme et kopi af Bitcoin-blokkæden. Mindst %1 GB data vil blive gemt i denne mappe, og den vil vokse over tid. Tegnebogen vil også blive gemt i denne mappe. + %1 will download and store a copy of the Bitcoin block chain. At least %2GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. + %1 vil downloade og gemme et kopi af Bitcoin-blokkæden. Mindst %2 GB data vil blive gemt i denne mappe, og den vil vokse over tid. Tegnebogen vil også blive gemt i denne mappe. Use the default data directory @@ -937,10 +591,6 @@ Use a custom data directory: Brug tilpasset mappe for data: - - Bitcoin Core - Bitcoin Core - Error: Specified data directory "%1" cannot be created. Fejl: Angivet datamappe "%1" kan ikke oprettes. @@ -976,10 +626,6 @@ Select payment request file Vælg fil for betalingsanmodning - - Select payment request file to open - Vælg fil for betalingsanmodning til åbning - OptionsDialog @@ -991,6 +637,14 @@ &Main &Generelt + + Automatically start %1 after logging in to the system. + Start %1 automatisk, når der logges ind på systemet. + + + &Start %1 on system login + &Start %1 ved systemlogin + Size of &database cache Størrelsen på &databasens cache @@ -1019,10 +673,6 @@ 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. Minimér i stedet for at lukke applikationen, når vinduet lukkes. Når denne indstilling er aktiveret, vil applikationen først blive lukket, når Afslut vælges i menuen. - - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - Sproget for brugerfladen kan vælges her. Denne indstilling vil træde i kraft efter genstart af Bitcoin Core. - 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 |. Tredjeparts-URL'er (fx et blokhåndteringsværktøj), der vises i transaktionsfanen som genvejsmenupunkter. %s i URL'en erstattes med transaktionens hash. Flere URL'er separeres med en lodret streg |. @@ -1047,14 +697,6 @@ &Network &Netværk - - Automatically start Bitcoin Core after logging in to the system. - Start Bitcoin Core automatisk efter der logges ind på systemet. - - - &Start Bitcoin Core on system login - &Start Bitcoin Core ved system-login - (0 = auto, <0 = leave that many cores free) (0 = auto, <0 = efterlad så mange kerner fri) @@ -1139,6 +781,14 @@ &Window &Vindue + + &Hide the icon from the system tray. + &Skjul ikonet fra statusbaren. + + + Hide tray icon + Skjul statusikon + Show only a tray icon after minimizing the window. Vis kun et statusikon efter minimering af vinduet. @@ -1159,6 +809,10 @@ User Interface &language: &Sprog for brugergrænseflade: + + The user interface language can be set here. This setting will take effect after restarting %1. + Sproget for brugerfladen kan vælges her. Denne indstilling vil træde i kraft efter genstart af %1. + &Unit to show amounts in: &Enhed, som beløb vises i: @@ -1284,140 +938,49 @@ - PaymentServer + PeerTableModel - URI handling - URI-håndtering + User Agent + Brugeragent - Invalid payment address %1 - Ugyldig betalingsadresse %1 + Node/Service + Knude/tjeneste - Payment request rejected - Betalingsanmodning afvist + Ping Time + Ping-tid + + + QObject - Payment request network doesn't match client network. - Netværk for betalingsanmodning stemmer ikke overens med klientens netværk. + Amount + Beløb - Payment request is not initialized. - Betalingsanmodning er ikke klargjort. + Enter a Bitcoin address (e.g. %1) + Indtast en Bitcoin-adresse (fx %1) - Requested payment amount of %1 is too small (considered dust). - Anmodet betalingsbeløb på %1 er for lille (regnes som støv). + %1 d + %1 d - Payment request error - Fejl i betalingsanmodning + %1 h + %1 t - Cannot start bitcoin: click-to-pay handler - Kan ikke starte bitcoin: click-to-pay-håndtering + %1 m + %1 m - Payment request fetch URL is invalid: %1 - Hentnings-URL for betalingsanmodning er ugyldig: %1 + %1 s + %1 s - URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - URI kan ikke tolkes! Dette kan skyldes en ugyldig Bitcoin-adresse eller forkert udformede URL-parametre. - - - Payment request file handling - Filhåndtering for betalingsanmodninger - - - Payment request file cannot be read! This can be caused by an invalid payment request file. - Fil for betalingsanmodning kan ikke læses! Dette kan skyldes en ugyldig fil for betalingsanmodning. - - - Payment request expired. - Betalingsanmodning er udløbet. - - - Unverified payment requests to custom payment scripts are unsupported. - Ikke-verificerede betalingsanmodninger for tilpassede betalings-scripts understøttes ikke. - - - Invalid payment request. - Ugyldig betalingsanmodning. - - - Refund from %1 - Tilbagebetaling fra %1 - - - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - Betalingsanmodning %1 er for stor (%2 byte, %3 byte tilladt). - - - Error communicating with %1: %2 - Fejl under kommunikation med %1: %2 - - - Payment request cannot be parsed! - Betalingsanmodning kan ikke tolkes! - - - Bad response from server %1 - Fejlagtigt svar fra server %1 - - - Payment acknowledged - Betaling anerkendt - - - Network request error - Fejl i netværksforespørgsel - - - - PeerTableModel - - User Agent - Brugeragent - - - Node/Service - Knude/tjeneste - - - Ping Time - Ping-tid - - - - QObject - - Amount - Beløb - - - Enter a Bitcoin address (e.g. %1) - Indtast en Bitcoin-adresse (fx %1) - - - %1 d - %1 d - - - %1 h - %1 t - - - %1 m - %1 m - - - %1 s - %1 s - - - None - Ingen + None + Ingen N/A @@ -1428,25 +991,6 @@ %1 ms - - QRImageWidget - - &Save Image... - &Gem billede… - - - &Copy Image - &Kopiér foto - - - Save QR Code - Gem QR-kode - - - PNG Image (*.png) - PNG-billede (*.png) - - RPCConsole @@ -1477,6 +1021,10 @@ Using BerkeleyDB version Bruger BerkeleyDB version + + Datadir + Datamappe + Startup time Opstartstidspunkt @@ -1513,10 +1061,6 @@ Memory usage Hukommelsesforbrug - - Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. - Åbn Bitcoin Cores fejlsøgningslogfil fra den aktuelle datamappe. Dette kan tage nogle få sekunder for store logfiler. - Received Modtaget @@ -1565,6 +1109,18 @@ User Agent Brugeragent + + Open the %1 debug log file from the current data directory. This can take a few seconds for large log files. + Åbn %1s fejlsøgningslogfil fra den aktuelle datamappe. Dette kan tage nogle få sekunder for store logfiler. + + + Decrease font size + Formindsk skrifttypestørrelse + + + Increase font size + Forstør skrifttypestørrelse + Services Tjenester @@ -1633,10 +1189,6 @@ Out: Udgående: - - Build date - Byggedato - Debug log file Fejlsøgningslogfil @@ -1674,8 +1226,8 @@ &Fjern bandlysning af knude - Welcome to the Bitcoin Core RPC console. - Velkommen til Bitcoin Cores RPC-konsol. + Welcome to the %1 RPC console. + Velkommen til %1s RPC-konsol. Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. @@ -1804,18 +1356,6 @@ Remove Fjern - - Copy label - Kopiér mærkat - - - Copy message - Kopiér besked - - - Copy amount - Kopier beløb - ReceiveRequestDialog @@ -1835,73 +1375,6 @@ &Save Image... &Gem billede… - - Request payment to %1 - Anmod om betaling til %1 - - - Payment information - Betalingsinformation - - - URI - URI - - - Address - Adresse - - - Amount - Beløb - - - Label - Mærkat - - - Message - Besked - - - Resulting URI too long, try to reduce the text for label / message. - Resulterende URI var for lang; prøv at forkorte teksten til mærkaten/beskeden. - - - Error encoding URI into QR Code. - Fejl ved kodning fra URI til QR-kode. - - - - RecentRequestsTableModel - - Date - Dato - - - Label - Mærkat - - - Message - Besked - - - Amount - Beløb - - - (no label) - (ingen mærkat) - - - (no message) - (ingen besked) - - - (no amount) - (intet beløb) - SendCoinsDialog @@ -2021,14 +1494,6 @@ fast hurtig - - Send as zero-fee transaction if possible - Send som nul-gebyr-transaktion hvis muligt - - - (confirmation may take longer) - (bekræftelse kan tage længere) - Send to multiple recipients at once Send til flere modtagere på en gang @@ -2061,118 +1526,6 @@ S&end &Afsend - - Confirm send coins - Bekræft afsendelse af bitcoins - - - %1 to %2 - %1 til %2 - - - Copy quantity - Kopiér mængde - - - Copy amount - Kopier beløb - - - Copy fee - Kopiér gebyr - - - Copy after fee - Kopiér efter-gebyr - - - Copy bytes - Kopiér byte - - - Copy priority - Kopiér prioritet - - - Copy change - Kopiér byttepenge - - - Total Amount %1 - Totalbeløb %1 - - - or - eller - - - The amount to pay must be larger than 0. - Beløbet til betaling skal være større end 0. - - - The amount exceeds your balance. - Beløbet overstiger din saldo. - - - The total exceeds your balance when the %1 transaction fee is included. - Totalen overstiger din saldo, når transaktionsgebyret på %1 er inkluderet. - - - Transaction creation failed! - Oprettelse af transaktion mislykkedes! - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - Transaktionen blev afvist! Dette kan ske, hvis nogle af dine bitcoins i din tegnebog allerede er brugt, som hvis du brugte en kopi af wallet.dat og dine bitcoins er blevet brugt i kopien, men ikke er markeret som brugt her. - - - A fee higher than %1 is considered an absurdly high fee. - Et gebyr højere end %1 opfattes som et absurd højt gebyr. - - - Payment request expired. - Betalingsanmodning er udløbet. - - - Pay only the required fee of %1 - Betal kun det påkrævede gebyr på %1 - - - Estimated to begin confirmation within %n block(s). - Bekræftelse estimeres til at begynde inden for %n blok.Bekræftelse estimeres til at begynde inden for %n blokke. - - - The recipient address is not valid. Please recheck. - Modtageradressen er ikke gyldig. Tjek venligst igen. - - - Duplicate address found: addresses should only be used once each. - Adressegenganger fundet. Adresser bør kun bruges én gang hver. - - - Warning: Invalid Bitcoin address - Advarsel: Ugyldig Bitcoin-adresse - - - (no label) - (ingen mærkat) - - - Warning: Unknown change address - Advarsel: Ukendt byttepengeadresse - - - Copy dust - Kopiér støv - - - Are you sure you want to send? - Er du sikker på, at du vil sende? - - - added as transaction fee - tilføjet som transaktionsgebyr - SendCoinsEntry @@ -2184,10 +1537,6 @@ Pay &To: Betal &til: - - Enter a label for this address to add it to your address book - Indtast en mærkat for denne adresse for at føje den til din adressebog - &Label: &Mærkat: @@ -2198,707 +1547,189 @@ This is a normal payment. - Dette er en normal betaling. - - - The Bitcoin address to send the payment to - Bitcoin-adresse, som betalingen skal sendes til - - - Alt+A - Alt+A - - - Paste address from clipboard - Indsæt adresse fra udklipsholderen - - - Alt+P - Alt+P - - - Remove this entry - Fjern denne indgang - - - 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. - Gebyret vil blive trukket fra det sendte beløb. Modtageren vil modtage færre bitcoin, end du indtaster i beløbfeltet. Hvis flere modtagere vælges, vil gebyret deles ligeligt. - - - S&ubtract fee from amount - &Træk gebyr fra beløb - - - Message: - Besked: - - - This is an unauthenticated payment request. - Dette er en uautentificeret betalingsanmodning. - - - This is an authenticated payment request. - Dette er en autentificeret betalingsanmodning. - - - Enter a label for this address to add it to the list of used addresses - Indtast et mærkat for denne adresse for at føje den til listen over brugte adresser - - - 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. - En besked, som blev føjet til "bitcon:"-URI'en, som vil gemmes med transaktionen til din reference. Bemærk: Denne besked vil ikke blive sendt over Bitcoin-netværket. - - - Pay To: - Betal til: - - - Memo: - Memo: - - - - ShutdownWindow - - Bitcoin Core is shutting down... - Bitcoin Core lukker ned… - - - Do not shut down the computer until this window disappears. - Luk ikke computeren ned, før dette vindue forsvinder. - - - - SignVerifyMessageDialog - - Signatures - Sign / Verify a Message - Signature - Underskriv/verificér en besked - - - &Sign Message - &Underskriv besked - - - 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. - Du kan signere beskeder/aftaler med dine adresser for at bevise, at du kan modtage bitcoin, der bliver sendt til adresserne. Vær forsigtig med ikke at signere noget vagt eller tilfældigt, da eventuelle phishing-angreb kan snyde dig til at overlade din identitet til dem. Signér kun fuldt ud detaljerede udsagn, som du er enig i. - - - The Bitcoin address to sign the message with - Bitcoin-adresse, som beskeden skal signeres med - - - Choose previously used address - Vælg tidligere brugt adresse - - - Alt+A - Alt+A - - - Paste address from clipboard - Indsæt adresse fra udklipsholderen - - - Alt+P - Alt+P - - - Enter the message you want to sign here - Indtast her beskeden, du ønsker at underskrive - - - Signature - Underskrift - - - Copy the current signature to the system clipboard - Kopiér den nuværende underskrift til systemets udklipsholder - - - Sign the message to prove you own this Bitcoin address - Underskriv denne besked for at bevise, at Bitcoin-adressen tilhører dig - - - Sign &Message - Underskriv &besked - - - Reset all sign message fields - Nulstil alle "underskriv besked"-felter - - - Clear &All - Ryd &alle - - - &Verify Message - &Verificér besked - - - 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! - Indtast modtagerens adresse, besked (vær sikker på at kopiere linjeskift, mellemrum, tabuleringer, etc. præcist) og signatur herunder for at verificere beskeden. Vær forsigtig med ikke at læse noget ud fra signaturen, som ikke står i selve beskeden, for at undgå at blive snydt af et eventuelt man-in-the-middle-angreb. Bemærk, at dette kun beviser, at den signerende person kan modtage med adressen; det kan ikke bevise hvem der har sendt en given transaktion! - - - The Bitcoin address the message was signed with - Bitcoin-adressen, som beskeden blev signeret med - - - Verify the message to ensure it was signed with the specified Bitcoin address - Verificér beskeden for at sikre, at den er underskrevet med den angivne Bitcoin-adresse - - - Verify &Message - Verificér &besked - - - Reset all verify message fields - Nulstil alle "verificér besked"-felter - - - Click "Sign Message" to generate signature - Klik "Underskriv besked" for at generere underskriften - - - The entered address is invalid. - Den indtastede adresse er ugyldig. - - - Please check the address and try again. - Tjek venligst adressen og forsøg igen. - - - The entered address does not refer to a key. - Den indtastede adresse henviser ikke til en nøgle. - - - Wallet unlock was cancelled. - Tegnebogsoplåsning annulleret. - - - Private key for the entered address is not available. - Den private nøgle for den indtastede adresse er ikke tilgængelig. - - - Message signing failed. - Underskrivning af besked mislykkedes. - - - Message signed. - Besked underskrevet. - - - The signature could not be decoded. - Underskriften kunne ikke afkodes. - - - Please check the signature and try again. - Tjek venligst underskriften, og forsøg igen. - - - The signature did not match the message digest. - Underskriften matcher ikke beskedens indhold. - - - Message verification failed. - Verificering af besked mislykkedes. - - - Message verified. - Besked verificeret. - - - - SplashScreen - - Bitcoin Core - Bitcoin Core - - - The Bitcoin Core developers - Udviklerne af Bitcoin Core - - - [testnet] - [testnetværk] - - - - TrafficGraphWidget - - KB/s - KB/s - - - - TransactionDesc - - Open until %1 - Åben indtil %1 - - - conflicted - konflikt - - - %1/offline - %1/offline - - - %1/unconfirmed - %1/ubekræftet - - - %1 confirmations - %1 bekræftelser - - - Status - Status - - - , broadcast through %n node(s) - , transmitteret igennem %n knude, transmitteret igennem %n knuder - - - Date - Dato - - - Source - Kilde - - - Generated - Genereret - - - From - Fra - - - To - Til - - - own address - egen adresse - - - watch-only - kigge - - - label - mærkat - - - Credit - Kredit - - - matures in %n more block(s) - modner efter yderligere %n blokmodner efter yderligere %n blokke - - - not accepted - ikke accepteret - - - Debit - Debet - - - Total debit - Total debet - - - Total credit - Total kredit - - - Transaction fee - Transaktionsgebyr - - - Net amount - Nettobeløb - - - Message - Besked - - - Comment - Kommentar - - - Transaction ID - Transaktions-ID - - - Merchant - Forretningsdrivende - - - 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. - Minede bitcoins skal modne %1 blokke, før de kan bruges. Da du genererede denne blok, blev den transmitteret til netværket for at blive føjet til blokkæden. Hvis det ikke lykkes at få den i kæden, vil dens tilstand ændres til "ikke accepteret", og den vil ikke kunne bruges. Dette kan ske nu og da, hvis en anden knude udvinder en blok inden for nogle få sekunder fra din. - - - Debug information - Fejlsøgningsinformation - - - Transaction - Transaktion - - - Inputs - Input - - - Amount - Beløb - - - true - sand - - - false - falsk - - - , has not been successfully broadcast yet - , er ikke blevet transmitteret endnu - - - Open for %n more block(s) - Åbn yderligere %n blokÅbn yderligere %n blokke - - - unknown - ukendt - - - - TransactionDescDialog - - Transaction details - Transaktionsdetaljer - - - This pane shows a detailed description of the transaction - Denne rude viser en detaljeret beskrivelse af transaktionen - - - - TransactionTableModel - - Date - Dato - - - Type - Type - - - Immature (%1 confirmations, will be available after %2) - Umoden (%1 bekræftelser; vil være tilgængelig efter %2) - - - Open for %n more block(s) - Åbn yderligere %n blokÅbn yderligere %n blokke - - - Open until %1 - Åben indtil %1 - - - Confirmed (%1 confirmations) - Bekræftet (%1 bekræftelser) - - - This block was not received by any other nodes and will probably not be accepted! - Denne blok blev ikke modtaget af nogen andre knuder og vil formentlig ikke blive accepteret! - - - Generated but not accepted - Genereret, men ikke accepteret - - - Offline - Offline - - - Label - Mærkat - - - Unconfirmed - Ubekræftet - - - Confirming (%1 of %2 recommended confirmations) - Bekræfter (%1 af %2 anbefalede bekræftelser) - - - Conflicted - Konflikt - - - Received with - Modtaget med - - - Received from - Modtaget fra - - - Sent to - Sendt til - - - Payment to yourself - Betaling til dig selv - - - Mined - Minet - - - watch-only - kigge - - - (n/a) - (n/a) - - - Transaction status. Hover over this field to show number of confirmations. - Transaktionsstatus. Hold musen over dette felt for at vise antallet af bekræftelser. - - - Date and time that the transaction was received. - Dato og klokkeslæt for modtagelse af transaktionen. - - - Type of transaction. - Transaktionstype. - - - Whether or not a watch-only address is involved in this transaction. - Afgør hvorvidt en kigge-adresse er involveret i denne transaktion. - - - User-defined intent/purpose of the transaction. - Brugerdefineret hensigt/formål med transaktionen. + Dette er en normal betaling. - Amount removed from or added to balance. - Beløb trukket fra eller tilføjet balance. + The Bitcoin address to send the payment to + Bitcoin-adresse, som betalingen skal sendes til - - - TransactionView - All - Alle + Alt+A + Alt+A - Today - I dag + Paste address from clipboard + Indsæt adresse fra udklipsholderen - This week - Denne uge + Alt+P + Alt+P - This month - Denne måned + Remove this entry + Fjern denne indgang - Last month - Sidste måned + 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. + Gebyret vil blive trukket fra det sendte beløb. Modtageren vil modtage færre bitcoin, end du indtaster i beløbfeltet. Hvis flere modtagere vælges, vil gebyret deles ligeligt. - This year - Dette år + S&ubtract fee from amount + &Træk gebyr fra beløb - Range... - Interval… + Message: + Besked: - Received with - Modtaget med + This is an unauthenticated payment request. + Dette er en uautentificeret betalingsanmodning. - Sent to - Sendt til + This is an authenticated payment request. + Dette er en autentificeret betalingsanmodning. - To yourself - Til dig selv + Enter a label for this address to add it to the list of used addresses + Indtast et mærkat for denne adresse for at føje den til listen over brugte adresser - Mined - Minet + 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. + En besked, som blev føjet til "bitcon:"-URI'en, som vil gemmes med transaktionen til din reference. Bemærk: Denne besked vil ikke blive sendt over Bitcoin-netværket. - Other - Andet + Pay To: + Betal til: - Enter address or label to search - Indtast adresse eller mærkat for at søge + Memo: + Memo: + + + ShutdownWindow - Min amount - Minimumsbeløb + %1 is shutting down... + %1 lukker ned… - Copy address - Kopiér adresse + Do not shut down the computer until this window disappears. + Luk ikke computeren ned, før dette vindue forsvinder. + + + SignVerifyMessageDialog - Copy label - Kopiér mærkat + Signatures - Sign / Verify a Message + Signature - Underskriv/verificér en besked - Copy amount - Kopiér beløb + &Sign Message + &Underskriv besked - Copy transaction ID - Kopiér transaktions-ID + 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. + Du kan signere beskeder/aftaler med dine adresser for at bevise, at du kan modtage bitcoin, der bliver sendt til adresserne. Vær forsigtig med ikke at signere noget vagt eller tilfældigt, da eventuelle phishing-angreb kan snyde dig til at overlade din identitet til dem. Signér kun fuldt ud detaljerede udsagn, som du er enig i. - Copy raw transaction - Kopiér rå transaktion + The Bitcoin address to sign the message with + Bitcoin-adresse, som beskeden skal signeres med - Edit label - Redigér mærkat + Choose previously used address + Vælg tidligere brugt adresse - Show transaction details - Vis transaktionsdetaljer + Alt+A + Alt+A - Export Transaction History - Historik for eksport af transaktioner + Paste address from clipboard + Indsæt adresse fra udklipsholderen - Watch-only - Kigge + Alt+P + Alt+P - Exporting Failed - Eksport mislykkedes + Enter the message you want to sign here + Indtast her beskeden, du ønsker at underskrive - There was an error trying to save the transaction history to %1. - En fejl opstod under gemning af transaktionshistorik til %1. + Signature + Underskrift - Exporting Successful - Eksport problemfri + Copy the current signature to the system clipboard + Kopiér den nuværende underskrift til systemets udklipsholder - The transaction history was successfully saved to %1. - Transaktionshistorikken blev gemt til %1 med succes. + Sign the message to prove you own this Bitcoin address + Underskriv denne besked for at bevise, at Bitcoin-adressen tilhører dig - Comma separated file (*.csv) - Kommasepareret fil (*.csv) + Sign &Message + Underskriv &besked - Confirmed - Bekræftet + Reset all sign message fields + Nulstil alle "underskriv besked"-felter - Date - Dato + Clear &All + Ryd &alle - Type - Type + &Verify Message + &Verificér besked - Label - Mærkat + 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! + Indtast modtagerens adresse, besked (vær sikker på at kopiere linjeskift, mellemrum, tabuleringer, etc. præcist) og signatur herunder for at verificere beskeden. Vær forsigtig med ikke at læse noget ud fra signaturen, som ikke står i selve beskeden, for at undgå at blive snydt af et eventuelt man-in-the-middle-angreb. Bemærk, at dette kun beviser, at den signerende person kan modtage med adressen; det kan ikke bevise hvem der har sendt en given transaktion! - Address - Adresse + The Bitcoin address the message was signed with + Bitcoin-adressen, som beskeden blev signeret med - ID - ID + Verify the message to ensure it was signed with the specified Bitcoin address + Verificér beskeden for at sikre, at den er underskrevet med den angivne Bitcoin-adresse - Range: - Interval: + Verify &Message + Verificér &besked - to - til + Reset all verify message fields + Nulstil alle "verificér besked"-felter - UnitDisplayStatusBarControl + SplashScreen - Unit to show amounts in. Click to select another unit. - Enhed, som beløb vises i. Klik for at vælge en anden enhed. + [testnet] + [testnetværk] - WalletFrame + TrafficGraphWidget - No wallet has been loaded. - Ingen tegnebog er indlæst. + KB/s + KB/s - WalletModel + TransactionDescDialog - Send Coins - Send bitcoins + This pane shows a detailed description of the transaction + Denne rude viser en detaljeret beskrivelse af transaktionen - WalletView - - &Export - &Eksportér - - - Export the data in the current tab to a file - Eksportér den aktuelle visning til en fil - - - Backup Wallet - Sikkerhedskopiér tegnebog - - - Wallet Data (*.dat) - Tegnebogsdata (*.dat) - - - Backup Failed - Sikkerhedskopiering mislykkedes - - - There was an error trying to save the wallet data to %1. - Der skete en fejl under gemning af tegnebogsdata til %1. - - - The wallet data was successfully saved to %1. - Tegnebogsdata blev gemt til %1 med succes. - + UnitDisplayStatusBarControl - Backup Successful - Sikkerhedskopiering problemfri + Unit to show amounts in. Click to select another unit. + Enhed, som beløb vises i. Klik for at vælge en anden enhed. @@ -2927,14 +1758,6 @@ If <category> is not supplied or if <category> = 1, output all debugging information. Hvis <category> ikke angives eller hvis <category> = 1, udskriv al fejlretningsinformation. - - Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s) - Maksimalt totalgebyr (i %s) for brug i en enkelt tegnebogstransaktion; ved at sætte dette for lavt, kan store transaktioner afbrydes (standard: %s) - - - Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. - Kontrollér venligst, at din computers dato og tid er korrekt! Hvis uret ikke passer, vil Bitcoin Core ikke fungere korrekt. - Prune configured below the minimum of %d MiB. Please use a higher number. Beskæring er sat under minimumsgrænsen på %d MiB. Brug venligst et større tal. @@ -2975,6 +1798,14 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Acceptér forbindelser udefra (standard: 1 hvis hverken -proxy eller -connect) + + Bitcoin Core + Bitcoin Core + + + The %s developers + Udviklerne af %s + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. -fallbackfee er sat meget højt! Dette er transaktionsgebyret, du eventuelt betaler, hvis gebyrestimater ikke er tilgængelige. @@ -2991,6 +1822,10 @@ Bind to given address and always listen on it. Use [host]:port notation for IPv6 Tildel til den givne adresse og lyt altid på den. Brug [vært]:port-notation for IPv6 + + Cannot obtain a lock on data directory %s. %s is probably already running. + Kan ikke opnå en lås på datamappe %s. %s kører sansynligvis allerede. + Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup Slet alle transaktioner i tegnebogen og genskab kun disse dele af blokkæden gennem -rescan under opstart @@ -2999,6 +1834,14 @@ Distributed under the MIT software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>. Distribueret under MIT-softwarelicensen; se den vedlagte fil COPYING eller <http://www.opensource.org/licenses/mit-license.php>. + + Error loading %s: You can't enable HD on a already existing non-HD wallet + Fejl under indlæsning af %s: Du kan ikke aktivere HD på en allerede eksisterende ikke-HD-tegnebog + + + Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Fejl under læsning af %s! Alle nøgler blev læst korrekt, men transaktionsdata eller indgange i adressebogen kan mangle eller være ukorrekte. + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) Udfør kommando, når en transaktion i tegnebogen ændres (%s i kommandoen erstattes med TxID) @@ -3007,6 +1850,22 @@ Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) Gennemtving videresendelse af transaktioner fra hvidlistede knuder, selv om de overtræder lokal videresendelsespolitik (standard: %d) + + Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds) + Justering af maksimalt tilladt gennemsnitlig afvigelse fra peer-tid. Den lokale opfattelse af tid kan blive påvirket frem eller tilbage af peers med denne mængde tid. (standard: %u sekunder) + + + Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s) + Maksimalt totalgebyr (i %s) der må bruges i en enkelt tegnebogstransaktion eller rå transaktion; en for lav en værdi kan afbryde store transaktioner (standard: %s) + + + Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly. + Undersøg venligst at din computers dato og klokkeslet er korrekt indstillet! Hvis der er fejl i disse, vil %s ikke fungere korrekt. + + + Please contribute if you find %s useful. Visit %s for further information about the software. + Overvej venligst at bidrage til udviklingen, hvis du finder %s brugbar. Besøg %s for yderligere information om softwaren. + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) Sæt antallet af scriptverificeringstråde (%u til %d, 0 = auto, <0 = efterlad det antal kernet fri, standard: %d) @@ -3019,14 +1878,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Dette er en foreløbig testudgivelse - brug på eget ansvar - brug ikke til udvinding eller handelsprogrammer - - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - Ikke i stand til at tildele til %s på denne computer. Bitcoin Core kører sansynligvis allerede. - - - Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. - Argument -whitelistalwaysrelay understøttes ikke og ignoreres; brug -whitelistrelay og/eller -whitelistforcerelay. - Use UPnP to map the listening port (default: 1 when listening and no -proxy) Brug UPnP for at konfigurere den lyttende port (standard: 1 under lytning og ingen -proxy) @@ -3043,22 +1894,22 @@ Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Advarsel: Netværket ser ikke ud til at være fuldt ud enige! Enkelte minere ser ud til at opleve problemer. - - Warning: Unknown block versions being mined! It's possible unknown rules are in effect - Advarsel: Ukendte blokversioner bliver minet! Det er muligt, at ukendte regler er i brug - Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Advarsel: Vi ser ikke ud til at være fuldt ud enige med andre knuder! Du kan være nødt til at opgradere, eller andre knuder kan være nødt til at opgradere. - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Advarsel: wallet.dat ødelagt, data reddet! Oprindelig wallet.dat gemt som wallet.{timestamp}.bak i %s; hvis din saldo eller dine transaktioner er forkert, bør du genskabe fra en sikkerhedskopi. - Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. Sæt andre knuder, der forbinder fra den angivne netmaske eller IP, på hvidliste. Kan angives flere gange. + + You need to rebuild the database using -reindex-chainstate to change -txindex + Du er nødt til at genopbygge databasen ved hjælp af -reindex-chainstate for at ændre -txindex + + + %s corrupt, salvage failed + %s ødelagt, redning af data mislykkedes + -maxmempool must be at least %d MB -maxmempool skal være mindst %d MB @@ -3071,10 +1922,22 @@ Append comment to the user agent string Føj kommentar til brugeragentstrengen + + Attempt to recover private keys from a corrupt wallet on startup + Forsøg at genskabe private nøgler fra en ødelagt tegnebog under opstart + Block creation options: Blokoprettelsestilvalg: + + Cannot resolve -%s address: '%s' + Kan ikke finde -%s-adressen: "%s" + + + Change index out of range + Ændr indeks uden for interval + Connect only to the specified node(s) Tilslut kun til de(n) angivne knude(r) @@ -3083,6 +1946,10 @@ Connection options: Tilvalg for forbindelser: + + Copyright (C) %i-%i + Ophavsret © %i-%i + Corrupted block database detected Ødelagt blokdatabase opdaget @@ -3127,6 +1994,22 @@ Error initializing wallet database environment %s! Klargøring af tegnebogsdatabasemiljøet %s mislykkedes! + + Error loading %s + Fejl under indlæsning af %s + + + Error loading %s: Wallet corrupted + Fejl under indlæsning af %s: Tegnebog ødelagt + + + Error loading %s: Wallet requires newer version of %s + Fejl under indlæsning af %s: Tegnebog kræver nyere version af %s + + + Error loading %s: You can't disable HD on a already existing HD wallet + Fejl under indlæsning af %s: Du kan ikke deaktivere HD på en allerede eksisterende HD-tegnebog + Error loading block database Indlæsning af blokdatabase mislykkedes @@ -3151,10 +2034,18 @@ Incorrect or no genesis block found. Wrong datadir for network? Ukorrekt eller ingen tilblivelsesblok fundet. Forkert datamappe for netværk? + + Initialization sanity check failed. %s is shutting down. + Klargøring af sundhedstjek mislykkedes. %s lukker ned. + Invalid -onion address: '%s' Ugyldig -onion adresse: "%s" + + Invalid amount for -%s=<amount>: '%s' + Ugyldigt beløb for -%s=<beløb>: "%s" + Invalid amount for -fallbackfee=<amount>: '%s' Ugyldigt beløb for -fallbackfee=<beløb>: "%s" @@ -3163,6 +2054,10 @@ Keep the transaction memory pool below <n> megabytes (default: %u) Hold hukommelsespuljen med transaktioner under <n> megabyte (standard: %u) + + Loading banlist... + Indlæser bandlysningsliste… + Location of the auth cookie (default: data dir) Placering for autentificerings-cookie (standard: datamappe) @@ -3179,6 +2074,10 @@ Only connect to nodes in network <net> (ipv4, ipv6 or onion) Tilslut kun til knuder i netværk <net> (IPv4, IPv6 eller Onion) + + Print this help message and exit + Udskriv denne hjælpetekst og afslut + Print version and exit Udskriv version og afslut @@ -3191,6 +2090,14 @@ Prune mode is incompatible with -txindex. Beskæringstilstand er ikke kompatibel med -txindex. + + Rebuild chain state and block index from the blk*.dat files on disk + Genopbyg kædetilstand og blokindeks fra blk*.dat-filerne på disken + + + Rebuild chain state from the currently indexed blocks + Genopbyg kædetilstand ud fra de aktuelt indekserede blokke + Set database cache size in megabytes (%d to %d, default: %d) Sæt cache-størrelse for database i megabytes (%d til %d; standard: %d) @@ -3203,6 +2110,14 @@ Specify wallet file (within data directory) Angiv tegnebogsfil (inden for datamappe) + + The source code is available from %s. + Kildekoden er tilgængelig fra %s. + + + Unable to bind to %s on this computer. %s is probably already running. + Ikke i stand til at tildele til %s på denne computer. %s kører formodentlig allerede. + Unsupported argument -benchmark ignored, use -debug=bench. Argument -benchmark understøttes ikke og ignoreres; brug -debug=bench. @@ -3236,12 +2151,16 @@ Tegnebog %s findes uden for datamappe %s - Wallet options: - Tilvalg for tegnebog: + Wallet debugging/testing options: + Tilvalg for fejlfinding/test af tegnebog: + + + Wallet needed to be rewritten: restart %s to complete + Det var nødvendigt at genskrive tegnebogen: Genstart %s for at gennemføre - You need to rebuild the database using -reindex to change -txindex - Du er nødt til at genopbygge databasen ved hjælp af -reindex for at ændre -txindex + Wallet options: + Tilvalg for tegnebog: 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 @@ -3255,10 +2174,6 @@ Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces) Tildel til den givne adresse for at lytte efter JSON-RPC-forbindelser. Brug [vært]:port-notation for IPv6. Denne valgmulighed kan angives flere gange (standard: tildel til alle grænseflader) - - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - Kan ikke opnå en lås på datamappe %s. Bitcoin Core kører sansynligvis allerede. - Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) Opret nye filer med systemstandard for rettigheder i stedet for umask 077 (kun virksomt med tegnebogsfunktionalitet slået fra) @@ -3303,10 +2218,6 @@ Set maximum size of high-priority/low-fee transactions in bytes (default: %d) Sæt maksimumstørrelse for højprioritet/lavgebyr-transaktioner i byte (standard: %d) - - Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) - Sæt antaller af tråde for coin-generering, hvis aktiveret (-1 = alle kerner, standard: %d) - The transaction amount is too small to send after the fee has been deducted Transaktionsbeløbet er for lille til at sende, når gebyret er trukket fra @@ -3315,6 +2226,10 @@ This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard. Dette produkt indeholder software, der er udviklet af OpenSSL-projektet for brug i OpenSSL-værktøjskassen <https://www.openssl.org/>, samt kryptografisk software, der er skrevet af Eric Young, samt UPnP-software, der er skrevet af Thomas Bernard. + + Use hierarchical deterministic key generation (HD) after BIP32. Only has effect during wallet creation/first start + Brug hierarkisk deterministisk nøglegenerering (HD) efter BIP32. Har kun effekt ved generering af ny tegnebog og under første opstart + 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 Andre knuder på hvidliste kan ikke DoS-bandlyses, og deres transaktioner videresendes altid, selv hvis de allerede er i hukommelsespuljen. Brugbart til fx et adgangspunkt @@ -3331,34 +2246,14 @@ Accept public REST requests (default: %u) Acceptér offentlige REST-anmodninger (standard: %u) - - Activating best chain... - Aktiverer bedste kæde… - - - Attempt to recover private keys from a corrupt wallet.dat on startup - Forsøg at genskabe private nøgler fra en ødelagt wallet.dat under opstart - Automatically create Tor hidden service (default: %d) Opret automatisk skjult Tor-tjeneste (standard: %d) - - Cannot resolve -whitebind address: '%s' - Kan ikke løse -whitebind adresse: "%s" - Connect through SOCKS5 proxy Forbind gennem SOCKS5-proxy - - Copyright (C) 2009-%i The Bitcoin Core Developers - Ophavsret © 2009-%i Udviklerne af Bitcoin Core - - - Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - Fejl ved indlæsning af wallet.dat: Tegnebog kræver en nyere version af Bitcoin Core - Error reading from database, shutting down. Fejl under læsning fra database; lukker ned. @@ -3371,22 +2266,6 @@ Information Information - - Initialization sanity check failed. Bitcoin Core is shutting down. - Sundhedstjek under klargøring mislykkedes. Bitcoin Core lukker ned. - - - Invalid amount for -maxtxfee=<amount>: '%s' - Ugyldigt beløb for -maxtxfee=<beløb>: "%s" - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Ugyldigt beløb til -minrelaytxfee=<beløb>: "%s" - - - Invalid amount for -mintxfee=<amount>: '%s' - Ugyldigt beløb til -mintxfee=<beløb>: "%s" - Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) Ugyldigt beløb for -paytxfee=<beløb>: "%s" (skal være mindst %s) @@ -3411,14 +2290,6 @@ RPC server options: Tilvalg for RPC-server: - - Rebuild block chain index from current blk000??.dat files on startup - Genopbyg blokkædeindeks fra nuværende blk000??.dat-filer ved opstart - - - Receive and display P2P network alerts (default: %u) - Modtag og vis P2P-netværksadvarsler (standard: %u) - Reducing -maxconnections from %d to %d, because of system limitations. Reducerer -maxconnections fra %d til %d på grund af systembegrænsninger. @@ -3491,10 +2362,6 @@ Username for JSON-RPC connections Brugernavn til JSON-RPC-forbindelser - - Wallet needed to be rewritten: restart Bitcoin Core to complete - Det var nødvendigt at genskrive tegnebogen: genstart Bitcoin Core for at gennemføre - Warning Advarsel @@ -3515,10 +2382,6 @@ ZeroMQ notification options: ZeroMQ-notifikationsindstillinger: - - wallet.dat corrupt, salvage failed - wallet.dat ødelagt, redning af data mislykkedes - Password for JSON-RPC connections Adgangskode til JSON-RPC-forbindelser @@ -3527,10 +2390,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) Udfør kommando, når den bedste blok ændres (%s i kommandoen erstattes med blokhash) - - This help message - Denne hjælpebesked - Allow DNS lookups for -addnode, -seednode and -connect Tillad DNS-opslag for -addnode, -seednode og -connect @@ -3539,10 +2398,6 @@ Loading addresses... Indlæser adresser… - - Error loading wallet.dat: Wallet corrupted - Fejl ved indlæsning af wallet.dat: Tegnebog ødelagt - (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) (1 = behold metadata for transaktion, fx kontoindehaver og information om betalingsanmodning, 2 = drop metadata for transaktion) @@ -3559,10 +2414,6 @@ Do not keep transactions in the mempool longer than <n> hours (default: %u) Behold ikke transaktioner i hukommelsespuljen i mere end <n> timer (default: %u) - - Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. - Fejl under læsning af wallet.dat! Alle nøgler blev læst korrekt, men transaktionsdata eller indgange i adressebogen kan mangle eller være ukorrekte. - Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) Gebyrer (i %s/kB) mindre end dette opfattes som intet gebyr under oprettelse af transaktioner (standard: %s) @@ -3599,6 +2450,10 @@ Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported. Argument -socks understøttes ikke. Det er ikke længere muligt at sætte SOCKS-version; kun SOCKS5-proxier understøttes. + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + Argument -whitelistalwaysrelay understøttes ikke og ignoreres; brug -whitelistrelay og/eller -whitelistforcerelay. + Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s) Brug separat SOCS5-proxy for at nå knuder via skjulte Tor-tjenester (standard: %s) @@ -3608,20 +2463,20 @@ Brugernavn og hashet adgangskode for JSON-RPC-forbindelser. Feltet <userpw> er i formatet: <BRUGERNAVN>:<SALT>$<HASH>. Et kanonisk Python-skript inkluderes i share/rpcuser. Dette tilvalg kan angives flere gange - (default: %s) - (standard: %s) + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + Advarsel: Ukendte blokversioner bliver minet! Det er muligt, at ukendte regler er i brug - Always query for peer addresses via DNS lookup (default: %u) - Forespørg altid adresser på andre knuder via DNS-opslag (default: %u) + Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup. + Advarsel: Tegnebogsfil ødelagt, data reddet! Oprindelig %s gemt som %s i %s; hvis din saldo eller dine transaktioner er forkert, bør du genskabe fra en sikkerhedskopi. - Error loading wallet.dat - Fejl ved indlæsning af wallet.dat + (default: %s) + (standard: %s) - Generate coins (default: %u) - Generér bitcoins (standard: %u) + Always query for peer addresses via DNS lookup (default: %u) + Forespørg altid adresser på andre knuder via DNS-opslag (default: %u) How many blocks to check at startup (default: %u, 0 = all) @@ -3708,18 +2563,6 @@ Unknown network specified in -onlynet: '%s' Ukendt netværk anført i -onlynet: "%s" - - Cannot resolve -bind address: '%s' - Kan ikke finde -bind adressen: "%s" - - - Cannot resolve -externalip address: '%s' - Kan ikke finde -externalip adressen: "%s" - - - Invalid amount for -paytxfee=<amount>: '%s' - Ugyldigt beløb for -paytxfee=<beløb>: "%s" - Insufficient funds Manglende dækning diff --git a/src/qt/locale/bitcoin_de.ts b/src/qt/locale/bitcoin_de.ts index 947a471acd1dc..639bc3cf2f72e 100644 --- a/src/qt/locale/bitcoin_de.ts +++ b/src/qt/locale/bitcoin_de.ts @@ -25,10 +25,6 @@ C&lose &Schließen - - &Copy Address - Adresse &kopieren - Delete the currently selected address from the list Ausgewählte Adresse aus der Liste entfernen @@ -45,73 +41,6 @@ &Delete &Löschen - - Choose the address to send coins to - Wählen Sie die Adresse aus, an die Sie Bitcoins überweisen möchten - - - Choose the address to receive coins with - Wählen Sie die Adresse aus, über die Sie Bitcoins empfangen wollen - - - C&hoose - &Auswählen - - - Sending addresses - Zahlungsadressen - - - Receiving addresses - Empfangsadressen - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Dies sind Ihre Bitcoin-Adressen zum Tätigen von Überweisungen. Bitte prüfen Sie den Betrag und die Empfangsadresse, bevor Sie Bitcoins überweisen. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Dies sind Ihre Bitcoin-Adressen zum Empfangen von Zahlungen. Es wird empfohlen für jede Transaktion eine neue Empfangsadresse zu verwenden. - - - Copy &Label - &Bezeichnung kopieren - - - &Edit - &Editieren - - - Export Address List - Addressliste exportieren - - - Comma separated file (*.csv) - Kommagetrennte-Datei (*.csv) - - - Exporting Failed - Exportieren fehlgeschlagen - - - There was an error trying to save the address list to %1. Please try again. - Beim Speichern der Adressliste nach %1 ist ein Fehler aufgetreten. Bitte versuchen Sie es erneut. - - - - AddressTableModel - - Label - Bezeichnung - - - Address - Adresse - - - (no label) - (keine Bezeichnung) - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase Neue Passphrase bestätigen - - Encrypt wallet - Wallet verschlüsseln - - - This operation needs your wallet passphrase to unlock the wallet. - Dieser Vorgang benötigt Ihre Passphrase, um die Wallet zu entsperren. - - - Unlock wallet - Wallet entsperren - - - This operation needs your wallet passphrase to decrypt the wallet. - Dieser Vorgang benötigt Ihre Passphrase, um die Wallet zu entschlüsseln. - - - Decrypt wallet - Wallet entschlüsseln - - - Change passphrase - Passphrase ändern - - - Confirm wallet encryption - Wallet-Verschlüsselung bestätigen - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Warnung: Wenn Sie Ihre Wallet verschlüsseln und Ihre Passphrase verlieren, werden Sie <b>alle Ihre Bitcoins verlieren</b>! - - - Are you sure you wish to encrypt your wallet? - Sind Sie sich sicher, dass Sie Ihre Wallet verschlüsseln möchten? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Bitcoin Core wird jetzt beendet, um den Verschlüsselungsprozess abzuschließen. Vergessen Sie nicht, dass eine Wallet-Verschlüsselung nicht vollständig vor Diebstahl Ihrer Bitcoins durch Schadsoftware schützen kann, die Ihren Computer infiziert. - - - 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. - WICHTIG: Alle vorherigen Wallet-Sicherungen sollten durch die neu erzeugte, verschlüsselte Wallet ersetzt werden. Aus Sicherheitsgründen werden vorherige Sicherungen der unverschlüsselten Wallet nutzlos, sobald Sie die neue, verschlüsselte Wallet verwenden. - - - Warning: The Caps Lock key is on! - Warnung: Die Feststelltaste ist aktiviert! - - - Wallet encrypted - Wallet verschlüsselt - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Geben Sie die neue Passphrase für die Wallet ein.<br>Bitte benutzen Sie eine Passphrase bestehend aus <b>zehn oder mehr zufälligen Zeichen</b> oder <b>acht oder mehr Wörtern</b>. - - - Enter the old passphrase and new passphrase to the wallet. - Geben Sie die alte und neue Wallet-Passphrase ein. - - - Wallet encryption failed - Wallet-Verschlüsselung fehlgeschlagen - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Die Wallet-Verschlüsselung ist aufgrund eines internen Fehlers fehlgeschlagen. Ihre Wallet wurde nicht verschlüsselt. - - - The supplied passphrases do not match. - Die eingegebenen Passphrasen stimmen nicht überein. - - - Wallet unlock failed - Wallet-Entsperrung fehlgeschlagen - - - The passphrase entered for the wallet decryption was incorrect. - Die eingegebene Passphrase zur Wallet-Entschlüsselung war nicht korrekt. - - - Wallet decryption failed - Wallet-Entschlüsselung fehlgeschlagen - - - Wallet passphrase was successfully changed. - Die Wallet-Passphrase wurde erfolgreich geändert. - BanTableModel @@ -269,6 +110,14 @@ Quit application Anwendung beenden + + &About %1 + &Über %1 + + + Show information about %1 + Informationen über %1 anzeigen + About &Qt Über &Qt @@ -281,6 +130,10 @@ &Options... &Konfiguration... + + Modify configuration options for %1 + Konfiguration von %1 bearbeiten + &Encrypt Wallet... Wallet &verschlüsseln... @@ -305,14 +158,6 @@ Open &URI... &URI öffnen... - - Bitcoin Core client - "Bitcoin Core"-Client - - - Importing blocks from disk... - Importiere Blöcke von Datenträger... - Reindexing blocks on disk... Reindiziere Blöcke auf Datenträger... @@ -357,10 +202,6 @@ &Receive &Empfangen - - Show information about Bitcoin Core - Informationen über Bitcoin Core anzeigen - &Show / Hide &Anzeigen / Verstecken @@ -397,22 +238,10 @@ Tabs toolbar Registerkartenleiste - - Bitcoin Core - Bitcoin Core - Request payments (generates QR codes and bitcoin: URIs) Zahlungen anfordern (erzeugt QR-Codes und "bitcoin:"-URIs) - - &About Bitcoin Core - &Über Bitcoin Core - - - Modify configuration options for Bitcoin Core - Konfiguration von Bitcoin Core bearbeiten - Show the list of used sending addresses and labels Liste verwendeter Zahlungsadressen und Bezeichnungen anzeigen @@ -429,14 +258,18 @@ &Command-line options &Kommandozeilenoptionen - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Zeige den "Bitcoin Core"-Hilfetext, um eine Liste mit möglichen Kommandozeilenoptionen zu erhalten - %n active connection(s) to Bitcoin network %n aktive Verbindung zum Bitcoin-Netzwerk%n aktive Verbindungen zum Bitcoin-Netzwerk + + Indexing blocks on disk... + Reindiziere Blöcke auf Datenträger... + + + Processing blocks on disk... + Verarbeite Blöcke auf Datenträger... + No block source available... Keine Blockquelle verfügbar... @@ -493,6 +326,14 @@ Up to date Auf aktuellem Stand + + Show the %1 help message to get a list with possible Bitcoin command-line options + Zeige den "%1"-Hilfetext, um eine Liste mit möglichen Kommandozeilenoptionen zu erhalten + + + %1 client + %1 Client + Catching up... Hole auf... @@ -544,13 +385,6 @@ Wallet ist <b>verschlüsselt</b> und aktuell <b>gesperrt</b> - - ClientModel - - Network Alert - Netzwerkalarm - - CoinControlDialog @@ -629,150 +463,6 @@ Priority Priorität - - Copy address - Adresse kopieren - - - Copy label - Bezeichnung kopieren - - - Copy amount - Betrag kopieren - - - Copy transaction ID - Transaktions-ID kopieren - - - Lock unspent - Nicht ausgegebenen Betrag sperren - - - Unlock unspent - Nicht ausgegebenen Betrag entsperren - - - Copy quantity - Anzahl kopieren - - - Copy fee - Gebühr kopieren - - - Copy after fee - Abzüglich Gebühr kopieren - - - Copy bytes - Byte kopieren - - - Copy priority - Priorität kopieren - - - Copy dust - "Dust" kopieren - - - Copy change - Wechselgeld kopieren - - - highest - am höchsten - - - higher - höher - - - high - hoch - - - medium-high - mittel-hoch - - - medium - mittel - - - low-medium - niedrig-mittel - - - low - niedrig - - - lower - niedriger - - - lowest - am niedrigsten - - - (%1 locked) - (%1 gesperrt) - - - none - keine - - - This label turns red if the transaction size is greater than 1000 bytes. - Diese Bezeichnung wird rot, wenn die Transaktion größer als 1000 Byte ist. - - - This label turns red if the priority is smaller than "medium". - Diese Bezeichnung wird rot, wenn die Priorität niedriger als "mittel" ist. - - - This label turns red if any recipient receives an amount smaller than %1. - Diese Bezeichnung wird rot, wenn irgendein Empfänger einen Betrag kleiner als %1 erhält. - - - Can vary +/- %1 satoshi(s) per input. - Kann pro Eingabe um +/- %1 Satoshi(s) abweichen. - - - yes - ja - - - no - nein - - - This means a fee of at least %1 per kB is required. - Das bedeutet, dass eine Gebühr von mindestens %1 pro kB erforderlich ist. - - - Can vary +/- 1 byte per input. - Kann um +/- 1 Byte pro Eingabe variieren. - - - Transactions with higher priority are more likely to get included into a block. - Transaktionen mit höherer Priorität haben eine größere Chance in einen Block aufgenommen zu werden. - - - (no label) - (keine Bezeichnung) - - - change from %1 (%2) - Wechselgeld von %1 (%2) - - - (change) - (Wechselgeld) - EditAddressDialog @@ -796,38 +486,6 @@ &Address &Adresse - - New receiving address - Neue Empfangsadresse - - - New sending address - Neue Zahlungsadresse - - - Edit receiving address - Empfangsadresse bearbeiten - - - Edit sending address - Zahlungsadresse bearbeiten - - - The entered address "%1" is already in the address book. - Die eingegebene Adresse "%1" befindet sich bereits im Adressbuch. - - - The entered address "%1" is not a valid Bitcoin address. - Die eingegebene Adresse "%1" ist keine gültige Bitcoin-Adresse. - - - Could not unlock wallet. - Wallet konnte nicht entsperrt werden. - - - New key generation failed. - Erzeugung eines neuen Schlüssels fehlgeschlagen. - FreespaceChecker @@ -854,10 +512,6 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin Core - version Version @@ -867,8 +521,8 @@ (%1-Bit) - About Bitcoin Core - Über Bitcoin Core + About %1 + Über %1 Command-line options @@ -892,7 +546,7 @@ Set language, for example "de_DE" (default: system locale) - Sprache einstellen, zum Beispiel "de_DE" (Standard: Systemgebietsschema) + Sprache einstellen, zum Beispiel "de_DE" (default: system locale) Start minimized @@ -907,7 +561,7 @@ Startbildschirm beim Starten anzeigen (Standard: %u) - Reset all settings changes made over the GUI + Reset all settings changed in the GUI Setze alle Einstellungen zurück, die über die grafische Oberfläche geändert wurden. @@ -918,16 +572,16 @@ Willkommen - Welcome to Bitcoin Core. - Willkommen zu Bitcoin Core. + Welcome to %1. + Willkommen zu %1. - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - Da Sie das Programm gerade zum ersten Mal starten, können Sie nun auswählen wo Bitcoin Core seine Daten ablegen soll. + As this is the first time the program is launched, you can choose where %1 will store its data. + Da Sie das Programm gerade zum ersten Mal starten, können Sie nun auswählen wo %1 seine Daten ablegen wird. - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - Bitcoin Core wird eine Kopie der Blockkette herunterladen und speichern. Mindestens %1GB Daten werden in diesem Verzeichnis abgelegt und die Datenmenge wächst über die Zeit an. Auch die Wallet wird in diesem Verzeichnis abgelegt. + %1 will download and store a copy of the Bitcoin block chain. At least %2GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. + %1 wird eine Kopie der Blockkette herunterladen und speichern. Mindestens %2GB Daten werden in diesem Verzeichnis abgelegt und die Datenmenge wächst über die Zeit an. Auch die Wallet wird in diesem Verzeichnis abgelegt. Use the default data directory @@ -937,10 +591,6 @@ Use a custom data directory: Ein benutzerdefiniertes Datenverzeichnis verwenden: - - Bitcoin Core - Bitcoin Core - Error: Specified data directory "%1" cannot be created. Fehler: Angegebenes Datenverzeichnis "%1" kann nicht angelegt werden. @@ -976,10 +626,6 @@ Select payment request file Zahlungsanforderungsdatei auswählen - - Select payment request file to open - Zu öffnende Zahlungsanforderungsdatei auswählen - OptionsDialog @@ -991,6 +637,14 @@ &Main &Allgemein + + Automatically start %1 after logging in to the system. + %1 nach der Anmeldung am System automatisch ausführen. + + + &Start %1 on system login + &Starte %1 nach Systemanmeldung + Size of &database cache Größe des &Datenbankcaches @@ -1019,10 +673,6 @@ 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. Minimiert die Anwendung anstatt sie zu beenden wenn das Fenster geschlossen wird. Wenn dies aktiviert ist, müssen Sie die Anwendung über "Beenden" im Menü schließen. - - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - Legt die Sprache der Benutzeroberfläche fest. Diese Einstellung wird erst nach einem Neustart von Bitcoin Core aktiv. - 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 |. Externe URLs (z.B. ein Block-Explorer), die im Kontextmenü des Transaktionsverlaufs eingefügt werden. In der URL wird %s durch den Transaktionshash ersetzt. Bei Angabe mehrerer URLs müssen diese durch "|" voneinander getrennt werden. @@ -1047,14 +697,6 @@ &Network &Netzwerk - - Automatically start Bitcoin Core after logging in to the system. - Bitcoin Core nach der Anmeldung am System automatisch starten. - - - &Start Bitcoin Core on system login - &Bitcoin Core nach Systemanmeldung starten - (0 = auto, <0 = leave that many cores free) (0 = automatisch, <0 = so viele Kerne frei lassen) @@ -1284,171 +926,61 @@ - PaymentServer + PeerTableModel - URI handling - URI-Verarbeitung + User Agent + User-Agent - Invalid payment address %1 - Ungültige Zahlungsadresse %1 + Node/Service + Knoten/Dienst - Payment request rejected - Zahlungsanforderung abgelehnt + Ping Time + Pingzeit + + + QObject - Payment request network doesn't match client network. - Netzwerk der Zahlungsanforderung stimmt nicht mit dem Client-Netzwerk überein. + Amount + Betrag - Payment request is not initialized. - Zahlungsanforderung ist nicht initialisiert. + Enter a Bitcoin address (e.g. %1) + Bitcoin-Adresse eingeben (z.B. %1) - Requested payment amount of %1 is too small (considered dust). - Angeforderter Zahlungsbetrag in Höhe von %1 ist zu niedrig und wurde als "Dust" eingestuft. + %1 d + %1 d - Payment request error - fehlerhafte Zahlungsanforderung + %1 h + %1 h - Cannot start bitcoin: click-to-pay handler - "bitcoin: Klicken-zum-Bezahlen"-Handler konnte nicht gestartet werden + %1 m + %1 m - Payment request fetch URL is invalid: %1 - Abruf-URL der Zahlungsanforderung ist ungültig: %1 + %1 s + %1 s - URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - URI kann nicht analysiert werden! Dies kann durch eine ungültige Bitcoin-Adresse oder fehlerhafte URI-Parameter verursacht werden. + None + Keine - Payment request file handling - Zahlungsanforderungsdatei-Verarbeitung + N/A + k.A. - Payment request file cannot be read! This can be caused by an invalid payment request file. - Zahlungsanforderungsdatei kann nicht gelesen werden! Dies kann durch eine ungültige Zahlungsanforderungsdatei verursacht werden. + %1 ms + %1 ms - - Payment request expired. - Zahlungsanforderung abgelaufen. - - - Unverified payment requests to custom payment scripts are unsupported. - Unverifizierte Zahlungsanforderungen an benutzerdefinierte Zahlungsskripte werden nicht unterstützt. - - - Invalid payment request. - Ungültige Zahlungsanforderung. - - - Refund from %1 - Rücküberweisung von %1 - - - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - Zahlungsanforderung %1 ist zu groß (%2 Byte, erlaubt sind %3 Byte). - - - Error communicating with %1: %2 - Kommunikationsfehler mit %1: %2 - - - Payment request cannot be parsed! - Zahlungsanforderung kann nicht verarbeitet werden! - - - Bad response from server %1 - Fehlerhafte Antwort vom Server: %1 - - - Payment acknowledged - Zahlung bestätigt - - - Network request error - fehlerhafte Netzwerkanfrage - - - - PeerTableModel - - User Agent - User-Agent - - - Node/Service - Knoten/Dienst - - - Ping Time - Pingzeit - - - - QObject - - Amount - Betrag - - - Enter a Bitcoin address (e.g. %1) - Bitcoin-Adresse eingeben (z.B. %1) - - - %1 d - %1 d - - - %1 h - %1 h - - - %1 m - %1 m - - - %1 s - %1 s - - - None - Keine - - - N/A - k.A. - - - %1 ms - %1 ms - - - - QRImageWidget - - &Save Image... - Grafik &speichern... - - - &Copy Image - Grafik &kopieren - - - Save QR Code - QR-Code speichern - - - PNG Image (*.png) - PNG-Grafik (*.png) - - - - RPCConsole + + + RPCConsole Client name Clientname @@ -1513,10 +1045,6 @@ Memory usage Speichernutzung - - Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. - Öffnet die "Bitcoin Core"-Debugprotokolldatei aus dem aktuellen Datenverzeichnis. Dies kann bei großen Protokolldateien einige Sekunden dauern. - Received Empfangen @@ -1565,6 +1093,14 @@ User Agent User-Agent + + Decrease font size + Schrift verkleinern + + + Increase font size + Schrift vergrößern + Services Dienste @@ -1633,10 +1169,6 @@ Out: ausgehend: - - Build date - Erstellungsdatum - Debug log file Debugprotokolldatei @@ -1674,8 +1206,8 @@ &Node entsperren - Welcome to the Bitcoin Core RPC console. - Willkommen in der "Bitcoin Core"-RPC-Konsole. + Welcome to the %1 RPC console. + Willkommen in der %1 RPC Konsole. Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. @@ -1804,18 +1336,6 @@ Remove Entfernen - - Copy label - Bezeichnung kopieren - - - Copy message - Nachricht kopieren - - - Copy amount - Betrag kopieren - ReceiveRequestDialog @@ -1835,73 +1355,6 @@ &Save Image... Grafik &speichern... - - Request payment to %1 - Zahlung anfordern an %1 - - - Payment information - Zahlungsinformationen - - - URI - URI - - - Address - Adresse - - - Amount - Betrag - - - Label - Bezeichnung - - - Message - Nachricht - - - Resulting URI too long, try to reduce the text for label / message. - Resultierende URI ist zu lang, bitte den Text für Bezeichnung/Nachricht kürzen. - - - Error encoding URI into QR Code. - Beim Enkodieren der URI in den QR-Code ist ein Fehler aufgetreten. - - - - RecentRequestsTableModel - - Date - Datum - - - Label - Bezeichnung - - - Message - Nachricht - - - Amount - Betrag - - - (no label) - (keine Bezeichnung) - - - (no message) - (keine Nachricht) - - - (no amount) - (kein Betrag) - SendCoinsDialog @@ -1986,919 +1439,277 @@ Ausblenden - total at least - Mindestbetrag - - - Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process. - Nur die minimale Gebühr zu bezahlen ist so lange in Ordnung, wie weniger Transaktionsvolumen als Platz in den Blöcken vorhanden ist. Aber Vorsicht, diese Option kann dazu führen, dass Transaktionen nicht bestätigt werden, wenn mehr Bedarf an Bitcoin-Transaktionen besteht als das Netzwerk verarbeiten kann. - - - (read the tooltip) - (den Hinweistext lesen) - - - Recommended: - Empfehlungen: - - - Custom: - Benutzerdefiniert: - - - (Smart fee not initialized yet. This usually takes a few blocks...) - (Intelligente Gebührenlogik ist noch nicht verfügbar. Normalerweise dauert dies einige Blöcke lang...) - - - Confirmation time: - Bestätigungszeit: - - - normal - normal - - - fast - schnell - - - Send as zero-fee transaction if possible - Wenn möglich als gebührenfreie Transaktion senden - - - (confirmation may take longer) - (Bestätigung kann länger dauern) - - - Send to multiple recipients at once - An mehrere Empfänger auf einmal überweisen - - - Add &Recipient - Empfänger &hinzufügen - - - Clear all fields of the form. - Alle Formularfelder zurücksetzen. - - - Dust: - "Dust": - - - Clear &All - &Zurücksetzen - - - Balance: - Kontostand: - - - Confirm the send action - Überweisung bestätigen - - - S&end - &Überweisen - - - Confirm send coins - Überweisung bestätigen - - - %1 to %2 - %1 an %2 - - - Copy quantity - Anzahl kopieren - - - Copy amount - Betrag kopieren - - - Copy fee - Gebühr kopieren - - - Copy after fee - Abzüglich Gebühr kopieren - - - Copy bytes - Byte kopieren - - - Copy priority - Priorität kopieren - - - Copy change - Wechselgeld kopieren - - - Total Amount %1 - Gesamtbetrag %1 - - - or - oder - - - The amount to pay must be larger than 0. - Der zu zahlende Betrag muss größer als 0 sein. - - - The amount exceeds your balance. - Der angegebene Betrag übersteigt Ihren Kontostand. - - - The total exceeds your balance when the %1 transaction fee is included. - Der angegebene Betrag übersteigt aufgrund der Transaktionsgebühr in Höhe von %1 Ihren Kontostand. - - - Transaction creation failed! - Transaktionserstellung fehlgeschlagen! - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - Die Transaktion wurde abgelehnt! Dies kann passieren, wenn einige Bitcoins aus Ihrer Wallet bereits ausgegeben wurden. Beispielsweise weil Sie eine Kopie Ihrer wallet.dat genutzt, die Bitcoins dort ausgegeben haben und dies daher in der derzeit aktiven Wallet nicht vermerkt ist. - - - A fee higher than %1 is considered an absurdly high fee. - Eine höhere Gebühr als %1 wird als unsinnig hohe Gebühr angesehen. - - - Payment request expired. - Zahlungsanforderung abgelaufen. - - - Pay only the required fee of %1 - Nur die notwendige Gebühr in Höhe von %1 zahlen - - - Estimated to begin confirmation within %n block(s). - Voraussichtlicher Beginn der Bestätigung innerhalb von %n Block.Voraussichtlicher Beginn der Bestätigung innerhalb von %n Blöcken. - - - The recipient address is not valid. Please recheck. - Die Zahlungsadresse ist ungültig, bitte nochmals überprüfen. - - - Duplicate address found: addresses should only be used once each. - Doppelte Adresse entdeckt: Adressen dürfen jeweils nur einmal vorkommen. - - - Warning: Invalid Bitcoin address - Warnung: Ungültige Bitcoin-Adresse - - - (no label) - (keine Bezeichnung) - - - Warning: Unknown change address - Warnung: Unbekannte Wechselgeld-Adresse - - - Copy dust - "Dust" kopieren - - - Are you sure you want to send? - Wollen Sie die Überweisung ausführen? - - - added as transaction fee - als Transaktionsgebühr hinzugefügt - - - - SendCoinsEntry - - A&mount: - Betra&g: - - - Pay &To: - E&mpfänger: - - - Enter a label for this address to add it to your address book - Adressbezeichnung eingeben (diese wird zusammen mit der Adresse dem Adressbuch hinzugefügt) - - - &Label: - &Bezeichnung: - - - Choose previously used address - Bereits verwendete Adresse auswählen - - - This is a normal payment. - Dies ist eine normale Überweisung. - - - The Bitcoin address to send the payment to - Die Zahlungsadresse der Überweisung - - - Alt+A - Alt+A - - - Paste address from clipboard - Adresse aus der Zwischenablage einfügen - - - Alt+P - Alt+P - - - Remove this entry - Diesen Eintrag entfernen - - - 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. - Die Gebühr wird vom zu überweisenden Betrag abgezogen. Der Empfänger wird also weniger Bitcoins erhalten, als Sie im Betrags-Feld eingegeben haben. Falls mehrere Empfänger ausgewählt wurden, wird die Gebühr gleichmäßig verteilt. - - - S&ubtract fee from amount - Gebühr vom Betrag ab&ziehen - - - Message: - Nachricht: - - - This is an unauthenticated payment request. - Dies ist keine beglaubigte Zahlungsanforderung. - - - This is an authenticated payment request. - Dies ist eine beglaubigte Zahlungsanforderung. - - - Enter a label for this address to add it to the list of used addresses - Adressbezeichnung eingeben, die dann zusammen mit der Adresse der Liste bereits verwendeter Adressen hinzugefügt wird. - - - 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. - Eine an die "bitcoin:"-URI angefügte Nachricht, die zusammen mit der Transaktion gespeichert wird. Hinweis: Diese Nachricht wird nicht über das Bitcoin-Netzwerk gesendet. - - - Pay To: - Empfänger: - - - Memo: - Memo: - - - - ShutdownWindow - - Bitcoin Core is shutting down... - Bitcoin Core wird beendet... - - - Do not shut down the computer until this window disappears. - Fahren Sie den Computer nicht herunter, bevor dieses Fenster verschwindet. - - - - SignVerifyMessageDialog - - Signatures - Sign / Verify a Message - Signaturen - eine Nachricht signieren / verifizieren - - - &Sign Message - Nachricht &signieren - - - 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. - Sie können Nachrichten/Vereinbarungen mit Hilfe Ihrer Adressen signieren, um zu beweisen, dass Sie Bitcoins empfangen können, die an diese Adressen überwiesen werden. Seien Sie vorsichtig und signieren Sie nichts Vages oder Willkürliches, um Ihre Indentität vor Phishingangriffen zu schützen. Signieren Sie nur vollständig-detaillierte Aussagen, mit denen Sie auch einverstanden sind. - - - The Bitcoin address to sign the message with - Die Bitcoin-Adresse mit der die Nachricht signiert wird - - - Choose previously used address - Bereits verwendete Adresse auswählen - - - Alt+A - Alt+A - - - Paste address from clipboard - Adresse aus der Zwischenablage einfügen - - - Alt+P - Alt+P - - - Enter the message you want to sign here - Zu signierende Nachricht hier eingeben - - - Signature - Signatur - - - Copy the current signature to the system clipboard - Aktuelle Signatur in die Zwischenablage kopieren - - - Sign the message to prove you own this Bitcoin address - Die Nachricht signieren, um den Besitz dieser Bitcoin-Adresse zu beweisen - - - Sign &Message - &Nachricht signieren - - - Reset all sign message fields - Alle "Nachricht signieren"-Felder zurücksetzen - - - Clear &All - &Zurücksetzen - - - &Verify Message - Nachricht &verifizieren - - - 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! - Geben Sie die Zahlungsadresse des Empfängers, Nachricht (achten Sie darauf Zeilenumbrüche, Leerzeichen, Tabulatoren usw. exakt zu kopieren) und Signatur unten ein, um die Nachricht zu verifizieren. Vorsicht, interpretieren Sie nicht mehr in die Signatur hinein, als in der signierten Nachricht selber enthalten ist, um nicht von einem Man-in-the-middle-Angriff hinters Licht geführt zu werden. Beachten Sie dass dies nur beweißt, dass die signierende Partei über diese Adresse Überweisungen empfangen kann. - - - The Bitcoin address the message was signed with - Die Bitcoin-Adresse mit der die Nachricht signiert wurde - - - Verify the message to ensure it was signed with the specified Bitcoin address - Die Nachricht verifizieren, um sicherzustellen, dass diese mit der angegebenen Bitcoin-Adresse signiert wurde - - - Verify &Message - &Nachricht verifizieren - - - Reset all verify message fields - Alle "Nachricht verifizieren"-Felder zurücksetzen - - - Click "Sign Message" to generate signature - Auf "Nachricht signieren" klicken, um die Signatur zu erzeugen - - - The entered address is invalid. - Die eingegebene Adresse ist ungültig. - - - Please check the address and try again. - Bitte überprüfen Sie die Adresse und versuchen Sie es erneut. - - - The entered address does not refer to a key. - Die eingegebene Adresse verweist nicht auf einen Schlüssel. - - - Wallet unlock was cancelled. - Wallet-Entsperrung wurde abgebrochen. - - - Private key for the entered address is not available. - Privater Schlüssel zur eingegebenen Adresse ist nicht verfügbar. - - - Message signing failed. - Signierung der Nachricht fehlgeschlagen. - - - Message signed. - Nachricht signiert. - - - The signature could not be decoded. - Die Signatur konnte nicht dekodiert werden. - - - Please check the signature and try again. - Bitte überprüfen Sie die Signatur und versuchen Sie es erneut. - - - The signature did not match the message digest. - Die Signatur entspricht nicht dem "Message Digest". - - - Message verification failed. - Verifikation der Nachricht fehlgeschlagen. - - - Message verified. - Nachricht verifiziert. - - - - SplashScreen - - Bitcoin Core - Bitcoin Core - - - The Bitcoin Core developers - Die "Bitcoin Core"-Entwickler - - - [testnet] - [Testnetz] - - - - TrafficGraphWidget - - KB/s - KB/s - - - - TransactionDesc - - Open until %1 - Offen bis %1 - - - conflicted - in Konflikt stehend - - - %1/offline - %1/offline - - - %1/unconfirmed - %1/unbestätigt - - - %1 confirmations - %1 Bestätigungen - - - Status - Status - - - , broadcast through %n node(s) - , über %n Knoten übertragen, über %n Knoten übertragen - - - Date - Datum - - - Source - Quelle - - - Generated - Erzeugt - - - From - Von - - - To - An - - - own address - eigene Adresse - - - watch-only - beobachtet - - - label - Bezeichnung - - - Credit - Gutschrift - - - matures in %n more block(s) - reift noch %n weiteren Blockreift noch %n weitere Blöcke - - - not accepted - nicht angenommen - - - Debit - Belastung - - - Total debit - Gesamtbelastung - - - Total credit - Gesamtgutschrift - - - Transaction fee - Transaktionsgebühr - - - Net amount - Nettobetrag - - - Message - Nachricht - - - Comment - Kommentar - - - Transaction ID - Transaktions-ID - - - Merchant - Händler - - - 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. - Erzeugte Bitcoins müssen %1 Blöcke lang reifen, bevor sie ausgegeben werden können. Als Sie diesen Block erzeugten, wurde er an das Netzwerk übertragen, um ihn der Blockkette hinzuzufügen. Falls dies fehlschlägt wird der Status in "nicht angenommen" geändert und Sie werden keine Bitcoins gutgeschrieben bekommen. Das kann gelegentlich passieren, wenn ein anderer Knoten einen Block fast zeitgleich erzeugt. - - - Debug information - Debuginformationen - - - Transaction - Transaktion - - - Inputs - Eingaben - - - Amount - Betrag - - - true - wahr - - - false - falsch - - - , has not been successfully broadcast yet - , wurde noch nicht erfolgreich übertragen - - - Open for %n more block(s) - Offen für %n weiteren BlockOffen für %n weitere Blöcke - - - unknown - unbekannt - - - - TransactionDescDialog - - Transaction details - Transaktionsdetails - - - This pane shows a detailed description of the transaction - Dieser Bereich zeigt eine detaillierte Beschreibung der Transaktion an - - - - TransactionTableModel - - Date - Datum - - - Type - Typ - - - Immature (%1 confirmations, will be available after %2) - Unreif (%1 Bestätigungen, wird verfügbar sein nach %2) - - - Open for %n more block(s) - Offen für %n weiteren BlockOffen für %n weitere Blöcke + total at least + Mindestbetrag - Open until %1 - Offen bis %1 + Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process. + Nur die minimale Gebühr zu bezahlen ist so lange in Ordnung, wie weniger Transaktionsvolumen als Platz in den Blöcken vorhanden ist. Aber Vorsicht, diese Option kann dazu führen, dass Transaktionen nicht bestätigt werden, wenn mehr Bedarf an Bitcoin-Transaktionen besteht als das Netzwerk verarbeiten kann. - Confirmed (%1 confirmations) - Bestätigt (%1 Bestätigungen) + (read the tooltip) + (den Hinweistext lesen) - This block was not received by any other nodes and will probably not be accepted! - Dieser Block wurde von keinem anderen Knoten empfangen und wird wahrscheinlich nicht angenommen werden! + Recommended: + Empfehlungen: - Generated but not accepted - Erzeugt, jedoch nicht angenommen + Custom: + Benutzerdefiniert: - Offline - Offline + (Smart fee not initialized yet. This usually takes a few blocks...) + (Intelligente Gebührenlogik ist noch nicht verfügbar. Normalerweise dauert dies einige Blöcke lang...) - Label - Bezeichnung + Confirmation time: + Bestätigungszeit: - Unconfirmed - Unbestätigt + normal + normal - Confirming (%1 of %2 recommended confirmations) - Wird bestätigt (%1 von %2 empfohlenen Bestätigungen) + fast + schnell - Conflicted - in Konflikt stehend + Send to multiple recipients at once + An mehrere Empfänger auf einmal überweisen - Received with - Empfangen über + Add &Recipient + Empfänger &hinzufügen - Received from - Empfangen von + Clear all fields of the form. + Alle Formularfelder zurücksetzen. - Sent to - Überwiesen an + Dust: + "Dust": - Payment to yourself - Eigenüberweisung + Clear &All + &Zurücksetzen - Mined - Erarbeitet + Balance: + Kontostand: - watch-only - beobachtet + Confirm the send action + Überweisung bestätigen - (n/a) - (k.A.) + S&end + &Überweisen + + + SendCoinsEntry - Transaction status. Hover over this field to show number of confirmations. - Transaktionsstatus, fahren Sie mit der Maus über dieses Feld, um die Anzahl der Bestätigungen zu sehen. + A&mount: + Betra&g: - Date and time that the transaction was received. - Datum und Uhrzeit zu der die Transaktion empfangen wurde. + Pay &To: + E&mpfänger: - Type of transaction. - Art der Transaktion + &Label: + &Bezeichnung: - Whether or not a watch-only address is involved in this transaction. - Zeigt an, ob eine beobachtete Adresse in diese Transaktion involviert ist. + Choose previously used address + Bereits verwendete Adresse auswählen - User-defined intent/purpose of the transaction. - Benutzerdefinierte Absicht bzw. Verwendungszweck der Transaktion + This is a normal payment. + Dies ist eine normale Überweisung. - Amount removed from or added to balance. - Der Betrag, der dem Kontostand abgezogen oder hinzugefügt wurde. + The Bitcoin address to send the payment to + Die Zahlungsadresse der Überweisung - - - TransactionView - All - Alle + Alt+A + Alt+A - Today - Heute + Paste address from clipboard + Adresse aus der Zwischenablage einfügen - This week - Diese Woche + Alt+P + Alt+P - This month - Diesen Monat + Remove this entry + Diesen Eintrag entfernen - Last month - Letzten Monat + 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. + Die Gebühr wird vom zu überweisenden Betrag abgezogen. Der Empfänger wird also weniger Bitcoins erhalten, als Sie im Betrags-Feld eingegeben haben. Falls mehrere Empfänger ausgewählt wurden, wird die Gebühr gleichmäßig verteilt. - This year - Dieses Jahr + S&ubtract fee from amount + Gebühr vom Betrag ab&ziehen - Range... - Zeitraum + Message: + Nachricht: - Received with - Empfangen über + This is an unauthenticated payment request. + Dies ist keine beglaubigte Zahlungsanforderung. - Sent to - Überwiesen an + This is an authenticated payment request. + Dies ist eine beglaubigte Zahlungsanforderung. - To yourself - Eigenüberweisung + Enter a label for this address to add it to the list of used addresses + Adressbezeichnung eingeben, die dann zusammen mit der Adresse der Liste bereits verwendeter Adressen hinzugefügt wird. - Mined - Erarbeitet + 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. + Eine an die "bitcoin:"-URI angefügte Nachricht, die zusammen mit der Transaktion gespeichert wird. Hinweis: Diese Nachricht wird nicht über das Bitcoin-Netzwerk gesendet. - Other - Andere + Pay To: + Empfänger: - Enter address or label to search - Zu suchende Adresse oder Bezeichnung eingeben + Memo: + Memo: + + + ShutdownWindow - Min amount - Minimaler Betrag + %1 is shutting down... + %1 wird beendet... - Copy address - Adresse kopieren + Do not shut down the computer until this window disappears. + Fahren Sie den Computer nicht herunter, bevor dieses Fenster verschwindet. + + + SignVerifyMessageDialog - Copy label - Bezeichnung kopieren + Signatures - Sign / Verify a Message + Signaturen - eine Nachricht signieren / verifizieren - Copy amount - Betrag kopieren + &Sign Message + Nachricht &signieren - Copy transaction ID - Transaktions-ID kopieren + 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. + Sie können Nachrichten/Vereinbarungen mit Hilfe Ihrer Adressen signieren, um zu beweisen, dass Sie Bitcoins empfangen können, die an diese Adressen überwiesen werden. Seien Sie vorsichtig und signieren Sie nichts Vages oder Willkürliches, um Ihre Indentität vor Phishingangriffen zu schützen. Signieren Sie nur vollständig-detaillierte Aussagen, mit denen Sie auch einverstanden sind. - Copy raw transaction - Kopiere rohe Transaktion + The Bitcoin address to sign the message with + Die Bitcoin-Adresse mit der die Nachricht signiert wird - Edit label - Bezeichnung bearbeiten + Choose previously used address + Bereits verwendete Adresse auswählen - Show transaction details - Transaktionsdetails anzeigen + Alt+A + Alt+A - Export Transaction History - Transaktionsverlauf exportieren + Paste address from clipboard + Adresse aus der Zwischenablage einfügen - Watch-only - Beobachtet + Alt+P + Alt+P - Exporting Failed - Exportieren fehlgeschlagen + Enter the message you want to sign here + Zu signierende Nachricht hier eingeben - There was an error trying to save the transaction history to %1. - Beim Speichern des Transaktionsverlaufs nach %1 ist ein Fehler aufgetreten. + Signature + Signatur - Exporting Successful - Exportieren erfolgreich + Copy the current signature to the system clipboard + Aktuelle Signatur in die Zwischenablage kopieren - The transaction history was successfully saved to %1. - Speichern des Transaktionsverlaufs nach %1 war erfolgreich. + Sign the message to prove you own this Bitcoin address + Die Nachricht signieren, um den Besitz dieser Bitcoin-Adresse zu beweisen - Comma separated file (*.csv) - Kommagetrennte-Datei (*.csv) + Sign &Message + &Nachricht signieren - Confirmed - Bestätigt + Reset all sign message fields + Alle "Nachricht signieren"-Felder zurücksetzen - Date - Datum + Clear &All + &Zurücksetzen - Type - Typ + &Verify Message + Nachricht &verifizieren - Label - Bezeichnung + 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! + Geben Sie die Zahlungsadresse des Empfängers, Nachricht (achten Sie darauf Zeilenumbrüche, Leerzeichen, Tabulatoren usw. exakt zu kopieren) und Signatur unten ein, um die Nachricht zu verifizieren. Vorsicht, interpretieren Sie nicht mehr in die Signatur hinein, als in der signierten Nachricht selber enthalten ist, um nicht von einem Man-in-the-middle-Angriff hinters Licht geführt zu werden. Beachten Sie dass dies nur beweißt, dass die signierende Partei über diese Adresse Überweisungen empfangen kann. - Address - Adresse + The Bitcoin address the message was signed with + Die Bitcoin-Adresse mit der die Nachricht signiert wurde - ID - ID + Verify the message to ensure it was signed with the specified Bitcoin address + Die Nachricht verifizieren, um sicherzustellen, dass diese mit der angegebenen Bitcoin-Adresse signiert wurde - Range: - Zeitraum: + Verify &Message + &Nachricht verifizieren - to - bis + Reset all verify message fields + Alle "Nachricht verifizieren"-Felder zurücksetzen - UnitDisplayStatusBarControl + SplashScreen - Unit to show amounts in. Click to select another unit. - Die Einheit in der Beträge angezeigt werden. Klicken, um eine andere Einheit auszuwählen. + [testnet] + [Testnetz] - WalletFrame + TrafficGraphWidget - No wallet has been loaded. - Es wurde keine Wallet geladen. + KB/s + KB/s - WalletModel + TransactionDescDialog - Send Coins - Bitcoins überweisen + This pane shows a detailed description of the transaction + Dieser Bereich zeigt eine detaillierte Beschreibung der Transaktion an - WalletView - - &Export - E&xportieren - - - Export the data in the current tab to a file - Daten der aktuellen Ansicht in eine Datei exportieren - - - Backup Wallet - Wallet sichern - - - Wallet Data (*.dat) - Wallet-Daten (*.dat) - - - Backup Failed - Sicherung fehlgeschlagen - - - There was an error trying to save the wallet data to %1. - Beim Speichern der Wallet-Daten nach %1 ist ein Fehler aufgetreten. - - - The wallet data was successfully saved to %1. - Speichern der Wallet-Daten nach %1 war erfolgreich. - + UnitDisplayStatusBarControl - Backup Successful - Sicherung erfolgreich + Unit to show amounts in. Click to select another unit. + Die Einheit in der Beträge angezeigt werden. Klicken, um eine andere Einheit auszuwählen. @@ -2927,14 +1738,6 @@ If <category> is not supplied or if <category> = 1, output all debugging information. Wenn <category> nicht angegeben wird oder <category>=1, jegliche Debugginginformationen ausgeben. - - Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s) - Maximale Gesamtgebühr (in %s) in einer Börsentransaktion; wird dies zu niedrig gesetzten können große Transaktionen abgebrochen werden (Standard: %s) - - - Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. - Bitte korrigieren Sie die Datums- und Uhrzeiteinstellungen Ihres Computers, da Bitcoin Core ansonsten nicht ordnungsgemäß funktionieren wird. - Prune configured below the minimum of %d MiB. Please use a higher number. Kürzungsmodus wurde kleiner als das Minimum in Höhe von %d MiB konfiguriert. Bitte verwenden Sie einen größeren Wert. @@ -2967,6 +1770,10 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Eingehende Verbindungen annehmen (Standard: 1, wenn nicht -proxy oder -connect) + + Bitcoin Core + Bitcoin Core + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. -fallbackfee ist sehr hoch eingestellt! Das ist die Transaktionsgebühr, welche du zahlen müsstest, wenn die Gebührenschätzungen nicht verfügbar sind. @@ -3007,14 +1814,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Dies ist eine Vorab-Testversion - Verwendung auf eigene Gefahr - nicht für Mining- oder Handelsanwendungen nutzen! - - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - Kann auf diesem Computer nicht an %s binden, da Bitcoin Core wahrscheinlich bereits gestartet wurde. - - - Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. - Das Argument -whitelistalwaysrelay wird nicht unterstützt und deswegen ignoriert. Benutze -whitelistrelay und/oder -whitelistforcerelay. - Use UPnP to map the listening port (default: 1 when listening and no -proxy) UPnP verwenden, um eine Portweiterleitung einzurichten (Standard: 1, wenn abgehört wird und -proxy nicht gesetzt ist) @@ -3031,18 +1830,10 @@ Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Warnung: Das Netzwerk scheint nicht vollständig übereinzustimmen! Einige Miner scheinen Probleme zu haben. - - Warning: Unknown block versions being mined! It's possible unknown rules are in effect - Warnung: Unbekannte Blockversion wird durch Mining erzeugt! Es ist möglich, dass unbekannte Regeln in Kraft sind. - Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Warnung: Wir scheinen nicht vollständig mit unseren Gegenstellen übereinzustimmen! Sie oder die anderen Knoten müssen unter Umständen Ihre Client-Software aktualisieren. - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Warnung: wallet.dat beschädigt, Datenrettung erfolgreich! Original wallet.dat wurde als wallet.{Zeitstempel}.dat in %s gespeichert. Falls Ihr Kontostand oder Transaktionen nicht korrekt sind, sollten Sie von einer Datensicherung wiederherstellen. - Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. Gegenstellen die sich von der angegebenen Netzmaske oder IP-Adresse aus verbinden immer zulassen. Kann mehrmals angegeben werden. @@ -3063,6 +1854,10 @@ Block creation options: Blockerzeugungsoptionen: + + Cannot resolve -%s address: '%s' + Kann Adresse in -%s nicht auflösen: '%s' + Connect only to the specified node(s) Mit nur dem oder den angegebenen Knoten verbinden @@ -3071,6 +1866,10 @@ Connection options: Verbindungsoptionen: + + Copyright (C) %i-%i + Copyright (C) %i-%i + Corrupted block database detected Beschädigte Blockdatenbank erkannt @@ -3111,6 +1910,10 @@ Error initializing wallet database environment %s! Fehler beim Initialisieren der Wallet-Datenbankumgebung %s! + + Error loading %s + Fehler beim Laden von %s + Error loading block database Fehler beim Laden der Blockdatenbank @@ -3139,6 +1942,10 @@ Invalid -onion address: '%s' Ungültige "-onion"-Adresse: '%s' + + Invalid amount for -%s=<amount>: '%s' + Ungültiger Betrag für -%s=<amount>: '%s' + Invalid amount for -fallbackfee=<amount>: '%s' Ungültiger Betrag für -fallbackfee=<amount>: '%s' @@ -3147,6 +1954,10 @@ Keep the transaction memory pool below <n> megabytes (default: %u) Halten Sie den Transaktionsspeicherpool unter <n> Megabytes (Voreinstellung: %u) + + Loading banlist... + Lade Sperrliste... + Location of the auth cookie (default: data dir) Dateiort für das Auth-Cookie (Standard: Datenverzeichnis) @@ -3183,6 +1994,14 @@ Specify wallet file (within data directory) Wallet-Datei angeben (innerhalb des Datenverzeichnisses) + + The source code is available from %s. + Der Quellcode ist von %s verfügbar. + + + Unable to bind to %s on this computer. %s is probably already running. + Kann auf diesem Computer nicht an %s binden. Evtl. wurde %s bereits gestartet. + Unsupported argument -benchmark ignored, use -debug=bench. Nicht unterstütztes Argument -benchmark wurde ignoriert, bitte -debug=bench verwenden. @@ -3219,10 +2038,6 @@ Wallet options: Wallet-Optionen: - - You need to rebuild the database using -reindex to change -txindex - Sie müssen die Datenbank mit Hilfe von -reindex neu aufbauen, um -txindex zu verändern - 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 JSON-RPC-Verbindungen von der angegeben Quelle erlauben. Gültig für <ip> ist eine einzelne IP-Adresse (z.B. 1.2.3.4), ein Netzwerk bzw. eine Netzmaske (z.B. 1.2.3.4/255.255.255.0), oder die CIDR-Notation (z.B. 1.2.3.4/24). Kann mehrmals angegeben werden. @@ -3235,10 +2050,6 @@ Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces) An die angegebene Adresse binden und nach eingehenden JSON-RPC-Verbindungen abhören. Für IPv6 "[Host]:Port"-Notation verwenden. Kann mehrmals angegeben werden. (Standard: an alle Schnittstellen binden) - - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - Datenverzeichnis %s kann nicht gesperrt werden, da Bitcoin Core wahrscheinlich bereits gestartet wurde. - Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) Neue Dateien mit Standard-Systemrechten erzeugen, anstatt mit umask 077 (nur mit deaktivierter Walletfunktion nutzbar) @@ -3283,10 +2094,6 @@ Set maximum size of high-priority/low-fee transactions in bytes (default: %d) Maximale Größe in Byte von "high-priority/low-fee"-Transaktionen festlegen (Standard: %d) - - Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) - Maximale Anzahl an Threads zur Bitcoinerzeugung, wenn aktiviert, festlegen (-1 = alle Kerne, Standard: %d) - The transaction amount is too small to send after the fee has been deducted Der Transaktionsbetrag ist zum senden zu niedrig, nachdem die Gebühr abgezogen wurde. @@ -3311,34 +2118,14 @@ Accept public REST requests (default: %u) Öffentliche REST-Anfragen annehmen (Standard: %u) - - Activating best chain... - Aktiviere beste Blockkette... - - - Attempt to recover private keys from a corrupt wallet.dat on startup - Versuchen, private Schlüssel beim Starten aus einer beschädigten wallet.dat wiederherzustellen - Automatically create Tor hidden service (default: %d) Automatisch versteckten Tor-Dienst erstellen (Standard: %d) - - Cannot resolve -whitebind address: '%s' - Kann Adresse in -whitebind nicht auflösen: '%s' - Connect through SOCKS5 proxy Über einen SOCKS5-Proxy &verbinden - - Copyright (C) 2009-%i The Bitcoin Core Developers - Urheberrecht (C) 2009-%i Die "Bitcoin Core"-Entwickler - - - Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - Fehler beim Laden von wallet.dat: Wallet benötigt neuere Version von Bitcoin Core - Error reading from database, shutting down. Fehler beim lesen der Datenbank, Ausführung wird beendet. @@ -3351,22 +2138,6 @@ Information Hinweis - - Initialization sanity check failed. Bitcoin Core is shutting down. - Initialisierungsplausibilitätsprüfung fehlgeschlagen. Bitcoin Core wird beendet. - - - Invalid amount for -maxtxfee=<amount>: '%s' - Ungültiger Betrag für -maxtxfee=<amount>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Ungültiger Betrag für -minrelaytxfee=<amount>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - Ungültiger Betrag für -mintxfee=<amount>: '%s' - Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) Ungültiger Betrag für -paytxfee=<amount>: '%s' (muss mindestens %s sein) @@ -3391,14 +2162,6 @@ RPC server options: RPC-Serveroptionen: - - Rebuild block chain index from current blk000??.dat files on startup - Blockkettenindex aus aktuellen Dateien blk000??.dat beim Starten wiederaufbauen - - - Receive and display P2P network alerts (default: %u) - P2P-Netzwerk-Alarme empfangen und anzeigen (Standard: %u) - Reducing -maxconnections from %d to %d, because of system limitations. Reduziere -maxconnections von %d zu %d, aufgrund von Systemlimitierungen. @@ -3471,10 +2234,6 @@ Username for JSON-RPC connections Benutzername für JSON-RPC-Verbindungen - - Wallet needed to be rewritten: restart Bitcoin Core to complete - Wallet musste neu geschrieben werden: starten Sie Bitcoin Core zur Fertigstellung neu - Warning Warnung @@ -3495,10 +2254,6 @@ ZeroMQ notification options: ZeroMQ-Benachrichtigungsoptionen: - - wallet.dat corrupt, salvage failed - wallet.dat beschädigt, Datenrettung fehlgeschlagen - Password for JSON-RPC connections Passwort für JSON-RPC-Verbindungen @@ -3507,10 +2262,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) Befehl ausführen wenn der beste Block wechselt (%s im Befehl wird durch den Hash des Blocks ersetzt) - - This help message - Dieser Hilfetext - Allow DNS lookups for -addnode, -seednode and -connect Erlaube DNS-Abfragen für -addnode, -seednode und -connect @@ -3519,10 +2270,6 @@ Loading addresses... Lade Adressen... - - Error loading wallet.dat: Wallet corrupted - Fehler beim Laden von wallet.dat: Wallet beschädigt - (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) (1 = TX-Metadaten wie z.B. Accountbesitzer und Zahlungsanforderungsinformationen behalten, 2 = TX-Metadaten verwerfen) @@ -3539,10 +2286,6 @@ Do not keep transactions in the mempool longer than <n> hours (default: %u) Die Transaktion nicht länger im Speicherpool behalten als <n> Stunden (Standard: %u) - - Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. - Lesen von wallet.dat fehlgeschlagen! Alle Schlüssel wurden korrekt gelesen, Transaktionsdaten bzw. Adressbucheinträge fehlen aber möglicherweise oder sind inkorrekt. - Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) Niedrigere Gebühren (in %s/Kb) als diese werden bei der Transaktionserstellung als gebührenfrei angesehen (Standard: %s) @@ -3575,6 +2318,10 @@ Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported. Nicht unterstütztes Argument -socks gefunden. Das Festlegen der SOCKS-Version ist nicht mehr möglich, nur noch SOCKS5-Proxies werden unterstützt. + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + Das Argument -whitelistalwaysrelay wird nicht unterstützt und deswegen ignoriert. Benutze -whitelistrelay und/oder -whitelistforcerelay. + Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s) Separaten SOCKS5-Proxy verwenden, um Gegenstellen über versteckte Tor-Dienste zu erreichen (Standard: %s) @@ -3583,6 +2330,10 @@ Username and hashed password for JSON-RPC connections. The field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A canonical python script is included in share/rpcuser. This option can be specified multiple times Benutzername und gehashtes Passwort für JSON-RPC Verbindungen. Das Feld <userpw> kommt im Format: <USERNAME>:<SALT>$<HASH>. Ein kanonisches Pythonskript ist in share/rpcuser inbegriffen. Diese Option kann mehrere Male spezifiziert werden + + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + Warnung: Unbekannte Blockversion wird durch Mining erzeugt! Es ist möglich, dass unbekannte Regeln in Kraft sind. + (default: %s) (Standard: %s) @@ -3591,14 +2342,6 @@ Always query for peer addresses via DNS lookup (default: %u) Adressen von Gegenstellen immer über DNS-Namensauflösung abfragen (Standard: %u) - - Error loading wallet.dat - Fehler beim Laden von wallet.dat - - - Generate coins (default: %u) - Bitcoins erzeugen (Standard: %u) - How many blocks to check at startup (default: %u, 0 = all) Wieviele Blöcke beim Starten geprüft werden sollen (Standard: %u, 0 = alle) @@ -3683,18 +2426,6 @@ Unknown network specified in -onlynet: '%s' Unbekannter Netztyp in -onlynet angegeben: '%s' - - Cannot resolve -bind address: '%s' - Kann Adresse in -bind nicht auflösen: '%s' - - - Cannot resolve -externalip address: '%s' - Kann Adresse in -externalip nicht auflösen: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - Ungültiger Betrag für -paytxfee=<amount>: '%s' - Insufficient funds Unzureichender Kontostand diff --git a/src/qt/locale/bitcoin_el.ts b/src/qt/locale/bitcoin_el.ts index 6777961cbc309..de76a110cfc4a 100644 --- a/src/qt/locale/bitcoin_el.ts +++ b/src/qt/locale/bitcoin_el.ts @@ -6,17 +6,6 @@ Δημιουργία νέου λογαριασμού - - AddressTableModel - - Label - Ετικέτα - - - Address - Διεύθυνση - - AskPassphraseDialog @@ -31,11 +20,7 @@ Repeat new passphrase Επαναλάβετε νέο συνθηματικό - - Change passphrase - Αλλαγή συνθηματικού - - + BanTableModel @@ -54,31 +39,12 @@ Σφάλμα - - ClientModel - CoinControlDialog Date Ημερομηνία - - Copy address - Αντιγραφή διεύθυνσης - - - Copy amount - Αντιγραφή ποσού - - - Copy quantity - Αντιγραφή ποσότητας - - - Copy change - Αντιγραφή αλλαγής - EditAddressDialog @@ -90,7 +56,7 @@ &Address Διεύθυνση - + FreespaceChecker @@ -125,18 +91,12 @@ OverviewPage - - PaymentServer - PeerTableModel QObject - - QRImageWidget - RPCConsole @@ -150,48 +110,9 @@ Remove Αφαίρεση - - Copy message - Αντιγραφή μηνύματος - - - Copy amount - Αντιγραφή ποσού - ReceiveRequestDialog - - Address - Διεύθυνση - - - Label - Ετικέτα - - - Message - Μήνυμα - - - - RecentRequestsTableModel - - Date - Ημερομηνία - - - Label - Ετικέτα - - - Message - Μήνυμα - - - (no message) - (κανένα μήνυμα) - SendCoinsDialog @@ -203,18 +124,6 @@ Recommended: Συνίσταται: - - Copy quantity - Αντιγραφή ποσότητας - - - Copy amount - Αντιγραφή ποσού - - - Copy change - Αντιγραφή αλλαγής - SendCoinsEntry @@ -235,66 +144,12 @@ TrafficGraphWidget - - TransactionDesc - - Date - Ημερομηνία - - - Message - Μήνυμα - - TransactionDescDialog - - TransactionTableModel - - Date - Ημερομηνία - - - Label - Ετικέτα - - - - TransactionView - - Copy address - Αντιγραφή διεύθυνσης - - - Copy amount - Αντιγραφή ποσού - - - Date - Ημερομηνία - - - Label - Ετικέτα - - - Address - Διεύθυνση - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - - WalletView - bitcoin-core diff --git a/src/qt/locale/bitcoin_el_GR.ts b/src/qt/locale/bitcoin_el_GR.ts index b5fb22f9739bf..59779692d9028 100644 --- a/src/qt/locale/bitcoin_el_GR.ts +++ b/src/qt/locale/bitcoin_el_GR.ts @@ -25,10 +25,6 @@ C&lose Κ&λείσιμο - - &Copy Address - &Αντιγραφή διεύθυνσης - Delete the currently selected address from the list Αντιγραφη της επιλεγμενης διεύθυνσης στο πρόχειρο του συστηματος @@ -45,73 +41,6 @@ &Delete &Διαγραφή - - Choose the address to send coins to - Επιλογή διεύθυνσης όπου θα σταλθούν νομίσματα - - - Choose the address to receive coins with - Επιλογή διεύθυνσης απ' όπου θα ληφθούν νομίσματα - - - C&hoose - Ε&πιλογή - - - Sending addresses - Διευθύνσεις αποστολής - - - Receiving addresses - Διευθύνσεις λήψης - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Αυτές είναι οι Bitcoin διευθύνσεις σας για να λαμβάνετε πληρωμές. Δίνοντας μία ξεχωριστή διεύθυνση σε κάθε αποστολέα, θα μπορείτε να ελέγχετε ποιος σας πληρώνει. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Αυτές είναι οι Bitcoin διευθύνσεις σας για να λαμβάνετε πληρωμές. Δίνοντας μία ξεχωριστή διεύθυνση σε κάθε αποστολέα, θα μπορείτε να ελέγχετε ποιος σας πληρώνει. - - - Copy &Label - Αντιγραφή &επιγραφής - - - &Edit - &Επεξεργασία - - - Export Address List - Εξαγωγή της λίστας διευθύνσεων - - - Comma separated file (*.csv) - Αρχείο οριοθετημένο με κόμματα (*.csv) - - - Exporting Failed - Η Εξαγωγή Απέτυχε - - - There was an error trying to save the address list to %1. Please try again. - Παρουσιάστηκε σφάλμα κατά την αποθήκευση της λίστας πορτοφολιών στο %1. Παρακαλώ δοκιμάστε ξανά - - - - AddressTableModel - - Label - Επιγραφή - - - Address - Διεύθυνση - - - (no label) - (χωρίς ετικέτα) - AskPassphraseDialog @@ -131,96 +60,6 @@ Repeat new passphrase Επανέλαβε τον νέο κωδικό πρόσβασης - - Encrypt wallet - &Κρυπτογράφηση πορτοφολιού - - - This operation needs your wallet passphrase to unlock the wallet. - Αυτη η ενεργεία χρειάζεται τον κωδικό του πορτοφολιού για να ξεκλειδώσει το πορτοφόλι. - - - Unlock wallet - Ξεκλειδωσε το πορτοφολι - - - This operation needs your wallet passphrase to decrypt the wallet. - Αυτη η ενεργεια χρειάζεται τον κωδικο του πορτοφολιου για να αποκρυπτογραφησειι το πορτοφολι. - - - Decrypt wallet - Αποκρυπτογράφησε το πορτοφολι - - - Change passphrase - Άλλαξε κωδικο πρόσβασης - - - Confirm wallet encryption - Επιβεβαίωσε την κρυπτογραφηση του πορτοφολιού - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Προσοχη: Εαν κρυπτογραφησεις το πορτοφολι σου και χάσεις τον κωδικο σου θα χάσεις <b> ΟΛΑ ΣΟΥ ΤΑ BITCOINS</b>! -Είσαι σίγουρος ότι θέλεις να κρυπτογραφησεις το πορτοφολι; - - - Are you sure you wish to encrypt your wallet? - Είστε σίγουροι ότι θέλετε να κρυπτογραφήσετε το πορτοφόλι σας; - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Το Bitcoin Core θα κλεισει τώρα για να τελειώσει την διαδικασία κρυπτογράφησης. Θυμήσου ότι κρυπτογραφώντας το πορτοφόλι σου δεν μπορείς να προστατέψεις πλήρως τα bitcoins σου από κλοπή στην περίπτωση που μολυνθεί ο υπολογιστής σου με κακόβουλο λογισμικό. - - - - 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. - ΣΗΜΑΝΤΙΚΟ: Τα προηγούμενα αντίγραφα ασφαλείας που έχετε κάνει από το αρχείο του πορτοφόλιου σας θα πρέπει να αντικατασταθουν με το νέο που δημιουργείται, κρυπτογραφημένο αρχείο πορτοφόλιου. Για λόγους ασφαλείας, τα προηγούμενα αντίγραφα ασφαλείας του μη κρυπτογραφημένου αρχείου πορτοφόλιου θα καταστουν άχρηστα μόλις αρχίσετε να χρησιμοποιείτε το νέο κρυπτογραφημένο πορτοφόλι. - - - Warning: The Caps Lock key is on! - Προσοχη: το πλήκτρο Caps Lock είναι ενεργο. - - - Wallet encrypted - Κρυπτογραφημενο πορτοφολι - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Εισάγετε τον νέο κωδικό πρόσβασης στον πορτοφόλι <br/> Παρακαλώ χρησιμοποιείστε ένα κωδικό με <b> 10 ή περισσότερους τυχαίους χαρακτήρες</b> ή <b> οχτώ ή παραπάνω λέξεις</b>. - - - Enter the old passphrase and new passphrase to the wallet. - Πληκτρολόγησε τον παλιό και τον νέο κωδικό στο πορτοφολι. - - - Wallet encryption failed - Η κρυπτογραφηση του πορτοφολιού απέτυχε - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Η κρυπτογράφηση του πορτοφολιού απέτυχε λογω εσωτερικού σφάλματος. Το πορτοφολι δεν κρυπτογραφηθηκε. - - - The supplied passphrases do not match. - Οι εισαχθέντες κωδικοί δεν ταιριάζουν. - - - Wallet unlock failed - το ξεκλείδωμα του πορτοφολιού απέτυχε - - - The passphrase entered for the wallet decryption was incorrect. - Ο κωδικος που εισήχθη για την αποκρυπτογραφηση του πορτοφολιού ήταν λαθος. - - - Wallet decryption failed - Η αποκρυπτογραφηση του πορτοφολιού απέτυχε - - - Wallet passphrase was successfully changed. - Ο κωδικος του πορτοφολιού άλλαξε με επιτυχία. - BanTableModel @@ -263,6 +102,10 @@ Quit application Εξοδος από την εφαρμογή + + &About %1 + &Περί %1 + About &Qt Σχετικά με &Qt @@ -299,14 +142,6 @@ Open &URI... 'Ανοιγμα &URI - - Bitcoin Core client - Εφαρμογή Bitcoin Core - - - Importing blocks from disk... - Εισαγωγή μπλοκ από τον σκληρο δίσκο ... - Reindexing blocks on disk... Φόρτωση ευρετηρίου μπλοκ στον σκληρο δισκο... @@ -351,10 +186,6 @@ &Receive &Παραλαβή - - Show information about Bitcoin Core - Σχετικά με το Bitcoin Core - &Show / Hide &Εμφάνισε/Κρύψε @@ -391,18 +222,10 @@ Tabs toolbar Εργαλειοθήκη καρτελών - - Bitcoin Core - Bitcoin Core - Request payments (generates QR codes and bitcoin: URIs) Αίτηση πληρωμών (δημιουργεί QR codes και διευθύνσεις bitcoin: ) - - &About Bitcoin Core - &Σχετικά με το Bitcoin Core - Show the list of used sending addresses and labels Προβολή της λίστας των χρησιμοποιημένων διευθύνσεων και ετικετών αποστολής @@ -419,10 +242,6 @@ &Command-line options &Επιλογές γραμμής εντολών - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Εμφανιση του Bitcoin-Qt μήνυματος βοήθειας για να πάρετε μια λίστα με τις πιθανές επιλογές Bitcoin γραμμής εντολών. - No block source available... Η πηγή του μπλοκ δεν ειναι διαθέσιμη... @@ -510,13 +329,6 @@ Το πορτοφόλι είναι <b>κρυπτογραφημένο</b> και <b>κλειδωμένο</b> - - ClientModel - - Network Alert - Ειδοποίηση Δικτύου - - CoinControlDialog @@ -595,151 +407,6 @@ Priority Προτεραιότητα - - Copy address - Αντιγραφή διεύθυνσης - - - Copy label - Αντιγραφή επιγραφής - - - Copy amount - Αντιγραφή ποσού - - - Copy transaction ID - Αντιγραφη του ID Συναλλαγής - - - Lock unspent - Κλείδωμα αξόδευτων - - - Unlock unspent - Ξεκλείδωμα αξόδευτων - - - Copy quantity - Αντιγραφή ποσότητας - - - Copy fee - Αντιγραφή ταρίφας - - - Copy after fee - Αντιγραφή μετα-ταρίφας - - - Copy bytes - Αντιγραφή των byte - - - Copy priority - Αντιγραφή προτεραιότητας - - - Copy dust - Αντιγραφή 'σκόνης' - - - Copy change - Αντιγραφή των ρέστων - - - highest - ύψιστη - - - higher - υψηλότερη - - - high - ψηλή - - - medium-high - μεσαία-ψηλή - - - medium - μεσαία - - - low-medium - μεσαία-χαμηλή - - - low - χαμηλή - - - lower - χαμηλότερη - - - lowest - χαμηλότατη - - - (%1 locked) - (%1 κλειδωμένο) - - - none - κανένα - - - This label turns red if the transaction size is greater than 1000 bytes. - Αυτή η ετικέτα γίνεται κόκκινη αν το μέγεθος της συναλλαγής είναι μεγαλύτερο από 1000 bytes. - - - This label turns red if the priority is smaller than "medium". - Αυτή η ετικέτα γίνεται κόκκινη αν η προτεραιότητα είναι μικρότερη από "μεσαία". - - - This label turns red if any recipient receives an amount smaller than %1. - Αυτή η ετικέτα γίνεται κόκκινη αν οποιοσδήποτε παραλήπτης λάβει ποσό μικρότερο από %1. - - - Can vary +/- %1 satoshi(s) per input. - Μπορεί να διαφέρει +/- %1 Satoshi (ες) ανά εγγραφή. - - - yes - ναι - - - no - όχι - - - This means a fee of at least %1 per kB is required. - Ελάχιστο χρεώσιμο ποσό τουλάχιστο %1 ανα kB - - - Can vary +/- 1 byte per input. - Μπορεί να διαφέρει +/- 1 byte ανά εγγραφή. - - - Transactions with higher priority are more likely to get included into a block. - Συναλλαγές με υψηλότερη προτεραιότητα είναι πιο πιθανό να περιλαμβάνονται σε ένα μπλοκ. - - - (no label) - (χωρίς ετικέτα) - - - change from %1 (%2) - ρέστα από %1 (%2) - - - (change) - (ρέστα) - - EditAddressDialog @@ -763,38 +430,6 @@ &Address &Διεύθυνση - - New receiving address - Νέα διεύθυνση λήψης - - - New sending address - Νέα διεύθυνση αποστολής - - - Edit receiving address - Επεξεργασία διεύθυνσης λήψης - - - Edit sending address - Επεξεργασία διεύθυνσης αποστολής - - - The entered address "%1" is already in the address book. - Η διεύθυνση "%1" βρίσκεται ήδη στο βιβλίο διευθύνσεων. - - - The entered address "%1" is not a valid Bitcoin address. - Η διεύθυνση "%1" δεν είναι έγκυρη Bitcoin διεύθυνση. - - - Could not unlock wallet. - Δεν είναι δυνατό το ξεκλείδωμα του πορτοφολιού. - - - New key generation failed. - Η δημιουργία νέου κλειδιού απέτυχε. - FreespaceChecker @@ -821,10 +456,6 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin Core - version έκδοση @@ -833,10 +464,6 @@ (%1-bit) (%1-bit) - - About Bitcoin Core - Σχετικά με το Bitcoin Core - Command-line options επιλογής γραμμής εντολών @@ -856,18 +483,6 @@ Welcome Καλώς ήρθατε - - Welcome to Bitcoin Core. - Καλώς ήρθατε στο Bitcoin Core. - - - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - Καθώς αυτή είναι η πρώτη φορά που εκκινείται το πρόγραμμα, μπορείτε να διαλέξετε πού θα αποθηκεύει το Bitcoin Core τα δεδομένα του. - - - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - O πυρήνας Bitcoin θα κατεβάσει και να αποθηκεύσει ένα αντίγραφο της αλυσίδας μπλοκ Bitcoin. Τουλάχιστον %1GB δεδομένων θα αποθηκευτούν σε αυτόν τον κατάλογο, και θα αυξηθεί με την πάροδο του χρόνου. Το πορτοφόλι θα αποθηκευτεί σε αυτόν τον κατάλογο. - Use the default data directory Χρήση του προεπιλεγμένου φακέλου δεδομένων @@ -876,10 +491,6 @@ Use a custom data directory: Προσαρμογή του φακέλου δεδομένων: - - Bitcoin Core - Bitcoin Core - Error: Specified data directory "%1" cannot be created. Σφάλμα: Ο καθορισμένος φάκελος δεδομένων "%1" δεν μπορεί να δημιουργηθεί. @@ -915,10 +526,6 @@ Select payment request file Επιλέξτε πληρωμή αρχείου αίτησης - - Select payment request file to open - Επιλέξτε αρχείο πληρωμής για άνοιγμα. - OptionsDialog @@ -1179,69 +786,6 @@ Το τρέχον συνολικό υπόλοιπο σε διευθύνσεις παρακολούθησης μόνο - - PaymentServer - - URI handling - Χειρισμός URI - - - Invalid payment address %1 - Μη έγκυρη διεύθυνση πληρωμής %1 - - - Payment request rejected - Η αίτηση πληρωμής έχει αρνηθεί. - - - Payment request is not initialized. - Η αίτηση πληρωμής δεν έχει αρχίζει ακόμα. - - - Requested payment amount of %1 is too small (considered dust). - Το ζητούμενο ποσό πληρωμής του %1 είναι πολύ μικρό (θεωρείται σκόνη) - - - Payment request error - Σφάλμα αιτήματος πληρωμής - - - Cannot start bitcoin: click-to-pay handler - Δεν είναι δυνατή η εκκίνηση του Bitcoin: click-to-pay handler - - - Payment request fetch URL is invalid: %1 - Η διεύθυνση πληρωμής (URL) δεν είναι έγκυρη: %1 - - - Payment request file handling - Επιλέξτε αρχείο πληρωμής για άνοιγμα. - - - Refund from %1 - Επιστροφή ποσού από %1 - - - Error communicating with %1: %2 - Σφάλμα επικοινωνίας με %1: %2 - - - Payment request cannot be parsed! - Η αίτηση πληρωμής δεν μπορεί να αναλυθεί! - - - Bad response from server %1 - Κακή απάντηση από διακομιστή %1 - - - Payment acknowledged - Πληρωμή αναγνωρίστηκε - - - Network request error - Σφάλμα αιτήματος δικτύου - - PeerTableModel @@ -1288,25 +832,6 @@ %1 ms - - QRImageWidget - - &Save Image... - &Αποθήκευση εικόνας... - - - &Copy Image - &Αντιγραφή εικόνας - - - Save QR Code - Αποθήκευση κώδικα QR - - - PNG Image (*.png) - Εικόνες PNG (*.png) - - RPCConsole @@ -1437,10 +962,6 @@ Out: Εξερχόμενα: - - Build date - Ημερομηνία κατασκευής - Debug log file Αρχείο καταγραφής εντοπισμού σφαλμάτων @@ -1536,18 +1057,6 @@ Remove Αφαίρεση - - Copy label - Αντιγραφή επιγραφής - - - Copy message - Αντιγραφή μηνύματος - - - Copy amount - Αντιγραφή ποσού - ReceiveRequestDialog @@ -1567,73 +1076,6 @@ &Save Image... &Αποθήκευση εικόνας... - - Request payment to %1 - Αίτηση πληρωμής για %1 - - - Payment information - Πληροφορίες πληρωμής - - - URI - URI: - - - Address - Διεύθυνση - - - Amount - Ποσό - - - Label - Επιγραφή - - - Message - Μήνυμα - - - Resulting URI too long, try to reduce the text for label / message. - Το αποτέλεσμα της διεύθυνσης είναι πολύ μεγάλο. Μειώστε το μέγεθος για το κείμενο της ετικέτας/ μηνύματος. - - - Error encoding URI into QR Code. - Σφάλμα κατά την κωδικοποίηση του URI σε κώδικα QR - - - - RecentRequestsTableModel - - Date - Ημερομηνία - - - Label - Επιγραφή - - - Message - Μήνυμα - - - Amount - Ποσό - - - (no label) - (χωρίς ετικέτα) - - - (no message) - (κανένα μήνυμα) - - - (no amount) - (κανένα ποσό) - SendCoinsDialog @@ -1733,10 +1175,6 @@ fast Γρήγορο - - (confirmation may take longer) - (η επικύρωση ίσως χρειαστεί περισσότερο χρόνο) - Send to multiple recipients at once Αποστολή σε πολλούς αποδέκτες ταυτόχρονα @@ -1769,82 +1207,6 @@ S&end Αποστολη - - Confirm send coins - Επιβεβαίωση αποστολής νομισμάτων - - - %1 to %2 - %1 σε %2 - - - Copy quantity - Αντιγραφή ποσότητας - - - Copy amount - Αντιγραφή ποσού - - - Copy fee - Αντιγραφή ταρίφας - - - Copy after fee - Αντιγραφή μετα-ταρίφας - - - Copy bytes - Αντιγραφή των byte - - - Copy priority - Αντιγραφή προτεραιότητας - - - Copy change - Αντιγραφή των ρέστων - - - or - ή - - - The amount to pay must be larger than 0. - Το ποσό πληρωμής πρέπει να είναι μεγαλύτερο από 0. - - - The amount exceeds your balance. - Το ποσό ξεπερνάει το διαθέσιμο υπόλοιπο - - - The total exceeds your balance when the %1 transaction fee is included. - Το σύνολο υπερβαίνει το υπόλοιπό σας όταν συμπεριληφθεί και η αμοιβή %1 - - - Transaction creation failed! - Η δημιουργία της συναλλαγής απέτυχε! - - - Warning: Invalid Bitcoin address - Προειδοποίηση: Μη έγκυρη διεύθυνση Bitcoin - - - (no label) - (χωρίς ετικέτα) - - - Copy dust - Αντιγραφή 'σκόνης' - - - Are you sure you want to send? - Είστε βέβαιοι για την αποστολή; - - - added as transaction fee - προστέθηκαν ως αμοιβή συναλλαγής - SendCoinsEntry @@ -1856,10 +1218,6 @@ Pay &To: Πληρωμή &σε: - - Enter a label for this address to add it to your address book - Εισάγετε μια επιγραφή για αυτή τη διεύθυνση ώστε να καταχωρηθεί στο βιβλίο διευθύνσεων - &Label: &Επιγραφή @@ -1911,10 +1269,6 @@ ShutdownWindow - - Bitcoin Core is shutting down... - Το Bitcoin Core τερματίζεται... - Do not shut down the computer until this window disappears. Μην απενεργοποιήσετε τον υπολογιστή μέχρι να κλείσει αυτό το παράθυρο. @@ -1998,69 +1352,9 @@ Reset all verify message fields Επαναφορά όλων επαλήθευμενων πεδίων μήνυματος - - Click "Sign Message" to generate signature - Κάντε κλικ στο "Υπογραφή Μηνύματος" για να λάβετε την υπογραφή - - - The entered address is invalid. - Η διεύθυνση που εισήχθη είναι λάθος. - - - Please check the address and try again. - Παρακαλούμε ελέγξτε την διεύθυνση και δοκιμάστε ξανά. - - - The entered address does not refer to a key. - Η διεύθυνση που έχει εισαχθεί δεν αναφέρεται σε ένα πλήκτρο. - - - Wallet unlock was cancelled. - το ξεκλείδωμα του πορτοφολιού απέτυχε - - - Private key for the entered address is not available. - Το προσωπικό κλειδί εισαγμενης διευθυνσης δεν είναι διαθέσιμο. - - - Message signing failed. - Η υπογραφή του μηνύματος απέτυχε. - - - Message signed. - Μήνυμα υπεγράφη. - - - The signature could not be decoded. - Η υπογραφή δεν μπόρεσε να αποκρυπτογραφηθεί. - - - Please check the signature and try again. - Παρακαλούμε ελέγξτε την υπογραφή και δοκιμάστε ξανά. - - - The signature did not match the message digest. - Η υπογραφή δεν ταιριάζει με το μήνυμα. - - - Message verification failed. - Η επιβεβαίωση του μηνύματος απέτυχε - - - Message verified. - Μήνυμα επιβεβαιώθηκε. - SplashScreen - - Bitcoin Core - Bitcoin Core - - - The Bitcoin Core developers - Οι προγραμματιστές του Bitcoin Core - [testnet] [testnet] @@ -2073,386 +1367,13 @@ KB/s - - TransactionDesc - - Open until %1 - Ανοιχτό μέχρι %1 - - - conflicted - σύγκρουση - - - %1/offline - %1/χωρίς σύνδεση; - - - %1/unconfirmed - %1/χωρίς επιβεβαίωση - - - %1 confirmations - %1 επιβεβαιώσεις - - - Status - Κατάσταση - - - Date - Ημερομηνία - - - Source - Πηγή - - - Generated - Δημιουργία - - - From - Από - - - To - Προς - - - own address - δική σας διεύθυνση - - - watch-only - Επίβλεψη μόνο: - - - label - eπιγραφή - - - Credit - Πίστωση - - - not accepted - μη αποδεκτό - - - Debit - Debit - - - Total debit - Σύνολο χρέωσης - - - Total credit - Συνολική πίστωση - - - Transaction fee - Τέλος συναλλαγής - - - Net amount - Καθαρό ποσό - - - Message - Μήνυμα - - - Comment - Σχόλιο: - - - Transaction ID - ID Συναλλαγής: - - - Merchant - Έμπορος - - - 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. - Πρέπει να περιμένετε %1 μπλοκ πριν μπορέσετε να χρησιμοποιήσετε τα νομίσματα που έχετε δημιουργήσει. Το μπλοκ που δημιουργήσατε μεταδόθηκε στο δίκτυο για να συμπεριληφθεί στην αλυσίδα των μπλοκ. Αν δεν μπει σε αυτή θα μετατραπεί σε "μη αποδεκτό" και δε θα μπορεί να καταναλωθεί. Αυτό συμβαίνει σπάνια όταν κάποιος άλλος κόμβος δημιουργήσει ένα μπλοκ λίγα δευτερόλεπτα πριν από εσάς. - - - Debug information - Πληροφορίες αποσφαλμάτωσης - - - Transaction - Συναλλαγή - - - Inputs - εισροές - - - Amount - Ποσό - - - true - αληθής - - - false - αναληθής - - - , has not been successfully broadcast yet - , δεν έχει ακόμα μεταδοθεί μ' επιτυχία - - - unknown - άγνωστο - - TransactionDescDialog - - Transaction details - Λεπτομέρειες συναλλαγής - This pane shows a detailed description of the transaction Αυτό το παράθυρο δείχνει μια λεπτομερή περιγραφή της συναλλαγής - - TransactionTableModel - - Date - Ημερομηνία - - - Type - Τύπος - - - Open until %1 - Ανοιχτό μέχρι %1 - - - Confirmed (%1 confirmations) - Επικυρωμένη (%1 επικυρώσεις) - - - This block was not received by any other nodes and will probably not be accepted! - Αυτό το μπλοκ δεν έχει παραληφθεί από κανέναν άλλο κόμβο και κατά πάσα πιθανότητα θα απορριφθεί! - - - Generated but not accepted - Δημιουργήθηκε αλλά απορρίφθηκε - - - Offline - Offline - - - Label - Επιγραφή - - - Unconfirmed - Ανεπιβεβαίωτες - - - Conflicted - Σύγκρουση - - - Received with - Ελήφθη με - - - Received from - Ελήφθη από - - - Sent to - Απεστάλη προς - - - Payment to yourself - Πληρωμή προς εσάς - - - Mined - Εξόρυξη - - - watch-only - Επίβλεψη μόνο: - - - (n/a) - (δ/α) - - - Transaction status. Hover over this field to show number of confirmations. - Κατάσταση συναλλαγής. Πηγαίνετε το ποντίκι πάνω από αυτό το πεδίο για να δείτε τον αριθμό των επικυρώσεων - - - Date and time that the transaction was received. - Ημερομηνία κι ώρα λήψης της συναλλαγής. - - - Type of transaction. - Είδος συναλλαγής. - - - Amount removed from or added to balance. - Ποσό που αφαιρέθηκε ή προστέθηκε στο υπόλοιπο. - - - - TransactionView - - All - Όλα - - - Today - Σήμερα - - - This week - Αυτή την εβδομάδα - - - This month - Αυτόν τον μήνα - - - Last month - Τον προηγούμενο μήνα - - - This year - Αυτό το έτος - - - Range... - Έκταση... - - - Received with - Ελήφθη με - - - Sent to - Απεστάλη προς - - - To yourself - Προς εσάς - - - Mined - Εξόρυξη - - - Other - Άλλο - - - Enter address or label to search - Αναζήτηση με βάση τη διεύθυνση ή την επιγραφή - - - Min amount - Ελάχιστο ποσό - - - Copy address - Αντιγραφή διεύθυνσης - - - Copy label - Αντιγραφή επιγραφής - - - Copy amount - Αντιγραφή ποσού - - - Copy transaction ID - Αντιγραφη του ID Συναλλαγής - - - Edit label - Επεξεργασία επιγραφής - - - Show transaction details - Εμφάνιση λεπτομερειών συναλλαγής - - - Export Transaction History - Εξαγωγή Ιστορικού Συναλλαγών - - - Watch-only - Επίβλεψη μόνο: - - - Exporting Failed - Η Εξαγωγή Απέτυχε - - - There was an error trying to save the transaction history to %1. - Yπήρξε σφάλμα κατά την προσπάθεια αποθήκευσης του ιστορικού συναλλαγών στο %1. - - - Exporting Successful - Επιτυχής εξαγωγή - - - The transaction history was successfully saved to %1. - Το ιστορικό συναλλαγών αποθηκεύτηκε επιτυχώς στο %1. - - - Comma separated file (*.csv) - Αρχείο οριοθετημένο με κόμματα (*.csv) - - - Confirmed - Επικυρωμένες - - - Date - Ημερομηνία - - - Type - Τύπος - - - Label - Επιγραφή - - - Address - Διεύθυνση - - - ID - ID - - - Range: - Έκταση: - - - to - έως - - UnitDisplayStatusBarControl @@ -2460,55 +1381,6 @@ Μονάδα μέτρησης προβολής ποσών. Κάντε κλικ για επιλογή άλλης μονάδας. - - WalletFrame - - No wallet has been loaded. - Δεν έχει φορτωθεί πορτοφόλι - - - - WalletModel - - Send Coins - Αποστολή νομισμάτων - - - - WalletView - - &Export - &Εξαγωγή - - - Export the data in the current tab to a file - Εξαγωγή δεδομένων καρτέλας σε αρχείο - - - Backup Wallet - Αντίγραφο ασφαλείας του πορτοφολιού - - - Wallet Data (*.dat) - Αρχεία δεδομένων πορτοφολιού (*.dat) - - - Backup Failed - Αποτυχία κατά τη δημιουργία αντιγράφου - - - There was an error trying to save the wallet data to %1. - Παρουσιάστηκε σφάλμα κατά την αποθήκευση των δεδομένων πορτοφολιού στο %1. - - - The wallet data was successfully saved to %1. - Τα δεδομένα πορτοφολιού αποθηκεύτηκαν με επιτυχία στο %1. - - - Backup Successful - Η δημιουργια αντιγραφου ασφαλειας πετυχε - - bitcoin-core @@ -2539,6 +1411,10 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Να δέχεσαι συνδέσεις από έξω(προεπιλογή:1) + + Bitcoin Core + Bitcoin Core + Bind to given address and always listen on it. Use [host]:port notation for IPv6 Αποθηκευση σε συγκεκριμένη διεύθυνση. Χρησιμοποιήστε τα πλήκτρα [Host] : συμβολισμός θύρα για IPv6 @@ -2551,10 +1427,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Αυτό είναι ένα προ-τεστ κυκλοφορίας - χρησιμοποιήστε το με δική σας ευθύνη - δεν χρησιμοποιείτε για εξόρυξη ή για αλλες εφαρμογές - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Προειδοποίηση : το αρχειο wallet.dat ειναι διεφθαρμένο, τα δεδομένα σώζονται ! Original wallet.dat αποθηκεύονται ως wallet.{timestamp}.bak στο %s . Αν το υπόλοιπο του ή τις συναλλαγές σας, είναι λάθος θα πρέπει να επαναφέρετε από ένα αντίγραφο ασφαλείας - Block creation options: Αποκλεισμός επιλογων δημιουργίας: @@ -2639,22 +1511,10 @@ Wallet options: Επιλογές πορτοφολιού: - - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - Αδυναμία κλειδώματος του φακέλου δεδομένων %s. Πιθανώς το Bitcoin να είναι ήδη ενεργό. - Connect through SOCKS5 proxy Σύνδεση μέσω διαμεσολαβητή SOCKS5 - - Copyright (C) 2009-%i The Bitcoin Core Developers - Πνευματικά δικαιώματα 2009-%i Οι προγραμματιστές του Bitcoin Core - - - Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - Σφάλμα φόρτωσης wallet.dat: Το Πορτοφόλι απαιτεί μια νεότερη έκδοση του Bitcoin - Error reading from database, shutting down. Σφάλμα ανάγνωσης από τη βάση δεδομένων, γίνεται τερματισμός. @@ -2663,22 +1523,6 @@ Information Πληροφορία - - Initialization sanity check failed. Bitcoin Core is shutting down. - Η εκκίνηση ελέγχου ορθότητας απέτυχε. Γίνεται τερματισμός του Bitcoin Core. - - - Invalid amount for -maxtxfee=<amount>: '%s' - Μη έγκυρο ποσό για την παράμετρο -maxtxfee=<amount>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Μη έγκυρο ποσό για την παράμετρο -paytxfee=<amount>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - Μη έγκυρο ποσό για την παράμετρο -paytxfee=<amount>: '%s' - Node relay options: Επιλογές αναμετάδοσης κόμβου: @@ -2731,10 +1575,6 @@ Zapping all transactions from wallet... Μεταφορά όλων των συναλλαγών απο το πορτοφόλι - - wallet.dat corrupt, salvage failed - Το αρχειο wallet.dat ειναι διεφθαρμένο, η διάσωση απέτυχε - Password for JSON-RPC connections Κωδικός για τις συνδέσεις JSON-RPC @@ -2743,10 +1583,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) Εκτέλεσε την εντολή όταν το καλύτερο μπλοκ αλλάξει(%s στην εντολή αντικαθίσταται από το hash του μπλοκ) - - This help message - Αυτό το κείμενο βοήθειας - Allow DNS lookups for -addnode, -seednode and -connect Να επιτρέπονται οι έλεγχοι DNS για προσθήκη και σύνδεση κόμβων @@ -2755,10 +1591,6 @@ Loading addresses... Φόρτωση διευθύνσεων... - - Error loading wallet.dat: Wallet corrupted - Σφάλμα φόρτωσης wallet.dat: Κατεστραμμένο Πορτοφόλι - How thorough the block verification of -checkblocks is (0-4, default: %u) Πόσο εξονυχιστική να είναι η επιβεβαίωση του μπλοκ (0-4, προεπιλογή: %u) @@ -2771,14 +1603,6 @@ Number of seconds to keep misbehaving peers from reconnecting (default: %u) Δευτερόλεπτα πριν επιτραπεί ξανά η σύνδεση των προβληματικών peers (προεπιλογή: %u) - - Error loading wallet.dat - Σφάλμα φόρτωσης αρχείου wallet.dat - - - Generate coins (default: %u) - Δημιουργία νομισμάτων (προκαθορισμος: %u) - How many blocks to check at startup (default: %u, 0 = all) Πόσα μπλοκ να ελέγχθουν κατά την εκκίνηση (προεπιλογή: %u, 0 = όλα) @@ -2815,18 +1639,6 @@ Unknown network specified in -onlynet: '%s' Άγνωστo δίκτυο ορίζεται σε onlynet: '%s' - - Cannot resolve -bind address: '%s' - Δεν μπορώ να γράψω την προεπιλεγμένη διεύθυνση: '%s' - - - Cannot resolve -externalip address: '%s' - Δεν μπορώ να γράψω την προεπιλεγμένη διεύθυνση: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - Μη έγκυρο ποσό για την παράμετρο -paytxfee=<amount>: '%s' - Insufficient funds Ανεπαρκές κεφάλαιο diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts index 4e4c9f45e6ccd..9723ffa3949ba 100644 --- a/src/qt/locale/bitcoin_en.ts +++ b/src/qt/locale/bitcoin_en.ts @@ -1239,7 +1239,7 @@ - + %1 s @@ -2224,7 +2224,7 @@ UnitDisplayStatusBarControl - + Unit to show amounts in. Click to select another unit. @@ -2232,32 +2232,32 @@ bitcoin-core - + Options: Options: - + Specify data directory Specify data directory - + Connect to a node to retrieve peer addresses, and disconnect Connect to a node to retrieve peer addresses, and disconnect - + Specify your own public address Specify your own public address - + Accept command line and JSON-RPC commands Accept command line and JSON-RPC commands - + If <category> is not supplied or if <category> = 1, output all debugging information. @@ -2282,7 +2282,7 @@ - + Error: A fatal internal error occurred, see debug.log for details @@ -2297,22 +2297,22 @@ - + Run in the background as a daemon and accept commands Run in the background as a daemon and accept commands - + Unable to start HTTP server. See debug log for details. - + Accept connections from outside (default: 1 if no -proxy or -connect) Accept connections from outside (default: 1 if no -proxy or -connect) - + Bitcoin Core Bitcoin Core @@ -2412,7 +2412,12 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications - + + Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain + + + + Use UPnP to map the listening port (default: 1 when listening and no -proxy) @@ -2687,12 +2692,22 @@ - + + Rewinding blocks... + + + + Set database cache size in megabytes (%d to %d, default: %d) + Set maximum block cost (default: %d) + + + + Set maximum block size in bytes (default: %d) @@ -2767,7 +2782,7 @@ - + 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 @@ -2847,7 +2862,7 @@ - + Use hierarchical deterministic key generation (HD) after BIP32. Only has effect during wallet creation/first start @@ -2937,7 +2952,7 @@ - + Send trace/debug info to console instead of debug.log file Send trace/debug info to console instead of debug.log file @@ -2947,7 +2962,7 @@ - + Show all debugging options (usage: --help -help-debug) @@ -3042,17 +3057,17 @@ - + Password for JSON-RPC connections Password for JSON-RPC connections - + Execute command when the best block changes (%s in cmd is replaced by block hash) Execute command when the best block changes (%s in cmd is replaced by block hash) - + Allow DNS lookups for -addnode, -seednode and -connect Allow DNS lookups for -addnode, -seednode and -connect @@ -3062,7 +3077,7 @@ Loading addresses... - + (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) @@ -3122,7 +3137,7 @@ - + Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported. @@ -3222,12 +3237,12 @@ - + Set key pool size to <n> (default: %u) - + Set minimum block size in bytes (default: %u) @@ -3267,7 +3282,7 @@ Unknown network specified in -onlynet: '%s' - + Insufficient funds Insufficient funds diff --git a/src/qt/locale/bitcoin_en_GB.ts b/src/qt/locale/bitcoin_en_GB.ts index b9c0c82814a54..89653e7aafd69 100644 --- a/src/qt/locale/bitcoin_en_GB.ts +++ b/src/qt/locale/bitcoin_en_GB.ts @@ -25,10 +25,6 @@ C&lose C&lose - - &Copy Address - &Copy Address - Delete the currently selected address from the list Delete the currently selected address from the list @@ -45,73 +41,6 @@ &Delete &Delete - - Choose the address to send coins to - Choose the address to send coins to - - - Choose the address to receive coins with - Choose the address to receive coins with - - - C&hoose - C&hoose - - - Sending addresses - Sending addresses - - - Receiving addresses - Receiving addresses - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - - - Copy &Label - Copy &Label - - - &Edit - &Edit - - - Export Address List - Export Address List - - - Comma separated file (*.csv) - Comma separated file (*.csv) - - - Exporting Failed - Exporting Failed - - - There was an error trying to save the address list to %1. Please try again. - There was an error trying to save the address list to %1. Please try again. - - - - AddressTableModel - - Label - Label - - - Address - Address - - - (no label) - (no label) - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase Repeat new passphrase - - Encrypt wallet - Encrypt wallet - - - This operation needs your wallet passphrase to unlock the wallet. - This operation needs your wallet passphrase to unlock the wallet. - - - Unlock wallet - Unlock wallet - - - This operation needs your wallet passphrase to decrypt the wallet. - This operation needs your wallet passphrase to decrypt the wallet. - - - Decrypt wallet - Decrypt wallet - - - Change passphrase - Change passphrase - - - Confirm wallet encryption - Confirm wallet encryption - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - - - Are you sure you wish to encrypt your wallet? - Are you sure you wish to encrypt your wallet? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - - - 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. - 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. - - - Warning: The Caps Lock key is on! - Warning: The Caps Lock key is on! - - - Wallet encrypted - Wallet encrypted - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - - - Enter the old passphrase and new passphrase to the wallet. - Enter the old passphrase and new passphrase to the wallet. - - - Wallet encryption failed - Wallet encryption failed - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - - - The supplied passphrases do not match. - The supplied passphrases do not match. - - - Wallet unlock failed - Wallet unlock failed - - - The passphrase entered for the wallet decryption was incorrect. - The passphrase entered for the wallet decryption was incorrect. - - - Wallet decryption failed - Wallet decryption failed - - - Wallet passphrase was successfully changed. - Wallet passphrase was successfully changed. - BanTableModel @@ -269,6 +110,14 @@ Quit application Quit application + + &About %1 + &About %1 + + + Show information about %1 + Show information about %1 + About &Qt About &Qt @@ -281,6 +130,10 @@ &Options... &Options... + + Modify configuration options for %1 + Modify configuration options for %1 + &Encrypt Wallet... &Encrypt Wallet... @@ -305,14 +158,6 @@ Open &URI... Open &URI... - - Bitcoin Core client - Bitcoin Core client - - - Importing blocks from disk... - Importing blocks from disk... - Reindexing blocks on disk... Reindexing blocks on disk... @@ -357,10 +202,6 @@ &Receive &Receive - - Show information about Bitcoin Core - Show information about Bitcoin Core - &Show / Hide &Show / Hide @@ -397,22 +238,10 @@ Tabs toolbar Tabs toolbar - - Bitcoin Core - Bitcoin Core - Request payments (generates QR codes and bitcoin: URIs) Request payments (generates QR codes and bitcoin: URIs) - - &About Bitcoin Core - &About Bitcoin Core - - - Modify configuration options for Bitcoin Core - Modify configuration options for Bitcoin Core - Show the list of used sending addresses and labels Show the list of used sending addresses and labels @@ -429,14 +258,18 @@ &Command-line options &Command-line options - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - %n active connection(s) to Bitcoin network %n active connection to Bitcoin network%n active connections to Bitcoin network + + Indexing blocks on disk... + Indexing blocks on disk... + + + Processing blocks on disk... + Processing blocks on disk... + No block source available... No block source available... @@ -493,6 +326,14 @@ Up to date Up to date + + Show the %1 help message to get a list with possible Bitcoin command-line options + Show the %1 help message to get a list with possible Bitcoin command-line options + + + %1 client + %1 client + Catching up... Catching up... @@ -544,13 +385,6 @@ Wallet is <b>encrypted</b> and currently <b>locked</b> - - ClientModel - - Network Alert - Network Alert - - CoinControlDialog @@ -629,150 +463,6 @@ Priority Priority - - Copy address - Copy address - - - Copy label - Copy label - - - Copy amount - Copy amount - - - Copy transaction ID - Copy transaction ID - - - Lock unspent - Lock unspent - - - Unlock unspent - Unlock unspent - - - Copy quantity - Copy quantity - - - Copy fee - Copy fee - - - Copy after fee - Copy after fee - - - Copy bytes - Copy bytes - - - Copy priority - Copy priority - - - Copy dust - Copy dust - - - Copy change - Copy change - - - highest - highest - - - higher - higher - - - high - high - - - medium-high - medium-high - - - medium - medium - - - low-medium - low-medium - - - low - low - - - lower - lower - - - lowest - lowest - - - (%1 locked) - (%1 locked) - - - none - none - - - This label turns red if the transaction size is greater than 1000 bytes. - This label turns red if the transaction size is greater than 1000 bytes. - - - This label turns red if the priority is smaller than "medium". - This label turns red if the priority is smaller than "medium". - - - This label turns red if any recipient receives an amount smaller than %1. - This label turns red if any recipient receives an amount smaller than %1. - - - Can vary +/- %1 satoshi(s) per input. - Can vary +/- %1 satoshi(s) per input. - - - yes - yes - - - no - no - - - This means a fee of at least %1 per kB is required. - This means a fee of at least %1 per kB is required. - - - Can vary +/- 1 byte per input. - Can vary +/- 1 byte per input. - - - Transactions with higher priority are more likely to get included into a block. - Transactions with higher priority are more likely to get included into a block. - - - (no label) - (no label) - - - change from %1 (%2) - change from %1 (%2) - - - (change) - (change) - EditAddressDialog @@ -796,38 +486,6 @@ &Address &Address - - New receiving address - New receiving address - - - New sending address - New sending address - - - Edit receiving address - Edit receiving address - - - Edit sending address - Edit sending address - - - The entered address "%1" is already in the address book. - The entered address "%1" is already in the address book. - - - The entered address "%1" is not a valid Bitcoin address. - The entered address "%1" is not a valid Bitcoin address. - - - Could not unlock wallet. - Could not unlock wallet. - - - New key generation failed. - New key generation failed. - FreespaceChecker @@ -854,10 +512,6 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin Core - version version @@ -867,8 +521,8 @@ (%1-bit) - About Bitcoin Core - About Bitcoin Core + About %1 + About %1 Command-line options @@ -907,8 +561,8 @@ Show splash screen on startup (default: %u) - Reset all settings changes made over the GUI - Reset all setting changes made via the GUI + Reset all settings changed in the GUI + Reset all settings changed in the GUI @@ -918,16 +572,16 @@ Welcome - Welcome to Bitcoin Core. - Welcome to Bitcoin Core. + Welcome to %1. + Welcome to %1. - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. + As this is the first time the program is launched, you can choose where %1 will store its data. + As this is the first time the program is launched, you can choose where %1 will store its data. - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. + %1 will download and store a copy of the Bitcoin block chain. At least %2GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. + %1 will download and store a copy of the Bitcoin block chain. At least %2GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. Use the default data directory @@ -937,10 +591,6 @@ Use a custom data directory: Use a custom data directory: - - Bitcoin Core - Bitcoin Core - Error: Specified data directory "%1" cannot be created. Error: Specified data directory "%1" cannot be created. @@ -976,10 +626,6 @@ Select payment request file Select payment request file - - Select payment request file to open - Select payment request file to open - OptionsDialog @@ -991,6 +637,14 @@ &Main &Main + + Automatically start %1 after logging in to the system. + Automatically start %1 after logging in to the system. + + + &Start %1 on system login + &Start %1 on system login + Size of &database cache Size of &database cache @@ -1019,10 +673,6 @@ 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. Minimise instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu. - - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - 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 |. 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 |. @@ -1047,14 +697,6 @@ &Network &Network - - Automatically start Bitcoin Core after logging in to the system. - Automatically start Bitcoin Core after logging in to the system. - - - &Start Bitcoin Core on system login - &Start Bitcoin Core on system login - (0 = auto, <0 = leave that many cores free) (0 = auto, <0 = leave that many cores free) @@ -1139,6 +781,14 @@ &Window &Window + + &Hide the icon from the system tray. + &Hide the icon from the system tray. + + + Hide tray icon + Hide tray icon + Show only a tray icon after minimizing the window. Show on a tray icon after minimising the window. @@ -1159,6 +809,10 @@ User Interface &language: User Interface &language: + + The user interface language can be set here. This setting will take effect after restarting %1. + The user interface language can be set here. This setting will take effect after restarting %1. + &Unit to show amounts in: &Unit to show amounts in: @@ -1284,169 +938,59 @@ - PaymentServer + PeerTableModel - URI handling - URI handling + User Agent + User Agent - Invalid payment address %1 - Invalid payment address %1 + Node/Service + Node/Service - Payment request rejected - Payment request rejected + Ping Time + Ping Time + + + QObject - Payment request network doesn't match client network. - Payment request network doesn't match client network. + Amount + Amount - Payment request is not initialized. - Payment request is not initialised. + Enter a Bitcoin address (e.g. %1) + Enter a Bitcoin address (e.g. %1) - Requested payment amount of %1 is too small (considered dust). - Requested payment amount of %1 is too small (considered dust). + %1 d + %1 d - Payment request error - Payment request error + %1 h + %1 h - Cannot start bitcoin: click-to-pay handler - Cannot start bitcoin: click-to-pay handler + %1 m + %1 m - Payment request fetch URL is invalid: %1 - Payment request fetch URL is invalid: %1 + %1 s + %1 s - URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. + None + None - Payment request file handling - Payment request file handling - - - Payment request file cannot be read! This can be caused by an invalid payment request file. - Payment request file cannot be read! This can be caused by an invalid payment request file. - - - Payment request expired. - Payment request expired. - - - Unverified payment requests to custom payment scripts are unsupported. - Unverified payment requests to custom payment scripts are unsupported. - - - Invalid payment request. - Invalid payment request. - - - Refund from %1 - Refund from %1 - - - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - - - Error communicating with %1: %2 - Error communicating with %1: %2 - - - Payment request cannot be parsed! - Payment request cannot be parsed! - - - Bad response from server %1 - Bad response from server %1 - - - Payment acknowledged - Payment acknowledged - - - Network request error - Network request error - - - - PeerTableModel - - User Agent - User Agent - - - Node/Service - Node/Service - - - Ping Time - Ping Time - - - - QObject - - Amount - Amount - - - Enter a Bitcoin address (e.g. %1) - Enter a Bitcoin address (e.g. %1) - - - %1 d - %1 d - - - %1 h - %1 h - - - %1 m - %1 m - - - %1 s - %1 s - - - None - None - - - N/A - N/A + N/A + N/A %1 ms %1 ms - - QRImageWidget - - &Save Image... - &Save Image... - - - &Copy Image - &Copy Image - - - Save QR Code - Save QR Code - - - PNG Image (*.png) - PNG Image (*.png) - - RPCConsole @@ -1477,6 +1021,10 @@ Using BerkeleyDB version Using BerkeleyDB version + + Datadir + Datadir + Startup time Startup time @@ -1513,10 +1061,6 @@ Memory usage Memory usage - - Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. - Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. - Received Received @@ -1565,6 +1109,18 @@ User Agent User Agent + + Open the %1 debug log file from the current data directory. This can take a few seconds for large log files. + Open the %1 debug log file from the current data directory. This can take a few seconds for large log files. + + + Decrease font size + Decrease font size + + + Increase font size + Increase font size + Services Services @@ -1633,10 +1189,6 @@ Out: Out: - - Build date - Build date - Debug log file Debug log file @@ -1674,8 +1226,8 @@ &Unban Node - Welcome to the Bitcoin Core RPC console. - Welcome to the Bitcoin Core RPC console. + Welcome to the %1 RPC console. + Welcome to the %1 RPC console. Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. @@ -1804,18 +1356,6 @@ Remove Remove - - Copy label - Copy label - - - Copy message - Copy message - - - Copy amount - Copy amount - ReceiveRequestDialog @@ -1835,73 +1375,6 @@ &Save Image... &Save Image... - - Request payment to %1 - Request payment to %1 - - - Payment information - Payment information - - - URI - URI - - - Address - Address - - - Amount - Amount - - - Label - Label - - - Message - Message - - - Resulting URI too long, try to reduce the text for label / message. - Resulting URI too long, try to reduce the text for label / message. - - - Error encoding URI into QR Code. - Error encoding URI into QR Code. - - - - RecentRequestsTableModel - - Date - Date - - - Label - Label - - - Message - Message - - - Amount - Amount - - - (no label) - (no label) - - - (no message) - (no message) - - - (no amount) - (no amount) - SendCoinsDialog @@ -2021,14 +1494,6 @@ fast fast - - Send as zero-fee transaction if possible - Send as zero-fee transaction if possible - - - (confirmation may take longer) - (confirmation may take longer) - Send to multiple recipients at once Send to multiple recipients at once @@ -2061,118 +1526,6 @@ S&end S&end - - Confirm send coins - Confirm send coins - - - %1 to %2 - %1 to %2 - - - Copy quantity - Copy quantity - - - Copy amount - Copy amount - - - Copy fee - Copy fee - - - Copy after fee - Copy after fee - - - Copy bytes - Copy bytes - - - Copy priority - Copy priority - - - Copy change - Copy change - - - Total Amount %1 - Total Amount %1 - - - or - or - - - The amount to pay must be larger than 0. - The amount to pay must be larger than 0. - - - The amount exceeds your balance. - The amount exceeds your balance. - - - The total exceeds your balance when the %1 transaction fee is included. - The total exceeds your balance when the %1 transaction fee is included. - - - Transaction creation failed! - Transaction creation failed! - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - - - A fee higher than %1 is considered an absurdly high fee. - A fee higher than %1 is considered an absurdly high fee. - - - Payment request expired. - Payment request expired. - - - Pay only the required fee of %1 - Pay only the required fee of %1 - - - Estimated to begin confirmation within %n block(s). - Estimated to begin confirmation within %n block.Estimated to begin confirmation within %n blocks. - - - The recipient address is not valid. Please recheck. - The recipient address is not valid. Please recheck. - - - Duplicate address found: addresses should only be used once each. - Duplicate address found: addresses should only be used once each. - - - Warning: Invalid Bitcoin address - Warning: Invalid Bitcoin address - - - (no label) - (no label) - - - Warning: Unknown change address - Warning: Unknown change address - - - Copy dust - Copy dust - - - Are you sure you want to send? - Are you sure you want to send? - - - added as transaction fee - added as transaction fee - SendCoinsEntry @@ -2184,10 +1537,6 @@ Pay &To: Pay &To: - - Enter a label for this address to add it to your address book - Enter a label for this address to add it to your address book - &Label: &Label: @@ -2198,707 +1547,189 @@ This is a normal payment. - This is a normal payment. - - - The Bitcoin address to send the payment to - The Bitcoin address to send the payment to - - - Alt+A - Alt+A - - - Paste address from clipboard - Paste address from clipboard - - - Alt+P - Alt+P - - - Remove this entry - Remove this entry - - - 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. - 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. - - - S&ubtract fee from amount - S&ubtract fee from amount - - - Message: - Message: - - - This is an unauthenticated payment request. - This is an unauthenticated payment request. - - - This is an authenticated payment request. - This is an authenticated payment request. - - - Enter a label for this address to add it to the list of used addresses - Enter a label for this address to add it to the list of used addresses - - - 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. - 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. - - - Pay To: - Pay To: - - - Memo: - Memo: - - - - ShutdownWindow - - Bitcoin Core is shutting down... - Bitcoin Core is shutting down... - - - Do not shut down the computer until this window disappears. - Do not shut down the computer until this window disappears. - - - - SignVerifyMessageDialog - - Signatures - Sign / Verify a Message - Signatures - Sign / Verify a Message - - - &Sign Message - &Sign Message - - - 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. - 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. - - - The Bitcoin address to sign the message with - The Bitcoin address to sign the message with - - - Choose previously used address - Choose previously used address - - - Alt+A - Alt+A - - - Paste address from clipboard - Paste address from clipboard - - - Alt+P - Alt+P - - - Enter the message you want to sign here - Enter the message you want to sign here - - - Signature - Signature - - - Copy the current signature to the system clipboard - Copy the current signature to the system clipboard - - - Sign the message to prove you own this Bitcoin address - Sign the message to prove you own this Bitcoin address - - - Sign &Message - Sign &Message - - - Reset all sign message fields - Reset all sign message fields - - - Clear &All - Clear &All - - - &Verify Message - &Verify Message - - - 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! - 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! - - - The Bitcoin address the message was signed with - The Bitcoin address the message was signed with - - - Verify the message to ensure it was signed with the specified Bitcoin address - Verify the message to ensure it was signed with the specified Bitcoin address - - - Verify &Message - Verify &Message - - - Reset all verify message fields - Reset all verify message fields - - - Click "Sign Message" to generate signature - Click "Sign Message" to generate signature - - - The entered address is invalid. - The entered address is invalid. - - - Please check the address and try again. - Please check the address and try again. - - - The entered address does not refer to a key. - The entered address does not refer to a key. - - - Wallet unlock was cancelled. - Wallet unlock was cancelled. - - - Private key for the entered address is not available. - Private key for the entered address is not available. - - - Message signing failed. - Message signing failed. - - - Message signed. - Message signed. - - - The signature could not be decoded. - The signature could not be decoded. - - - Please check the signature and try again. - Please check the signature and try again. - - - The signature did not match the message digest. - The signature did not match the message digest. - - - Message verification failed. - Message verification failed. - - - Message verified. - Message verified. - - - - SplashScreen - - Bitcoin Core - Bitcoin Core - - - The Bitcoin Core developers - The Bitcoin Core developers - - - [testnet] - [testnet] - - - - TrafficGraphWidget - - KB/s - KB/s - - - - TransactionDesc - - Open until %1 - Open until %1 - - - conflicted - conflicted - - - %1/offline - %1/offline - - - %1/unconfirmed - %1/unconfirmed - - - %1 confirmations - %1 confirmations - - - Status - Status - - - , broadcast through %n node(s) - , broadcast through %n node, broadcast through %n nodes - - - Date - Date - - - Source - Source - - - Generated - Generated - - - From - From - - - To - To - - - own address - own address - - - watch-only - watch-only - - - label - label - - - Credit - Credit - - - matures in %n more block(s) - matures in %n more blockmatures in %n more blocks - - - not accepted - not accepted - - - Debit - Debit - - - Total debit - Total debit - - - Total credit - Total credit - - - Transaction fee - Transaction fee - - - Net amount - Net amount - - - Message - Message - - - Comment - Comment - - - Transaction ID - Transaction ID - - - Merchant - Merchant - - - 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. - 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. - - - Debug information - Debug information - - - Transaction - Transaction - - - Inputs - Inputs - - - Amount - Amount - - - true - true - - - false - false - - - , has not been successfully broadcast yet - , has not been successfully broadcast yet - - - Open for %n more block(s) - Open for %n more blockOpen for %n more blocks - - - unknown - unknown - - - - TransactionDescDialog - - Transaction details - Transaction details - - - This pane shows a detailed description of the transaction - This pane shows a detailed description of the transaction - - - - TransactionTableModel - - Date - Date - - - Type - Type - - - Immature (%1 confirmations, will be available after %2) - Immature (%1 confirmations, will be available after %2) - - - Open for %n more block(s) - Open for %n more blockOpen for %n more blocks - - - Open until %1 - Open until %1 - - - Confirmed (%1 confirmations) - Confirmed (%1 confirmations) - - - This block was not received by any other nodes and will probably not be accepted! - This block was not received by any other nodes and will probably not be accepted! - - - Generated but not accepted - Generated but not accepted - - - Offline - Offline - - - Label - Label - - - Unconfirmed - Unconfirmed - - - Confirming (%1 of %2 recommended confirmations) - Confirming (%1 of %2 recommended confirmations) - - - Conflicted - Conflicted - - - Received with - Received with - - - Received from - Received from - - - Sent to - Sent to - - - Payment to yourself - Payment to yourself - - - Mined - Mined - - - watch-only - watch-only - - - (n/a) - (n/a) - - - Transaction status. Hover over this field to show number of confirmations. - Transaction status. Hover over this field to show number of confirmations. - - - Date and time that the transaction was received. - Date and time that the transaction was received. - - - Type of transaction. - Type of transaction. - - - Whether or not a watch-only address is involved in this transaction. - Whether or not a watch-only address is involved in this transaction. - - - User-defined intent/purpose of the transaction. - User-defined intent/purpose of the transaction. + This is a normal payment. - Amount removed from or added to balance. - Amount removed from or added to balance. + The Bitcoin address to send the payment to + The Bitcoin address to send the payment to - - - TransactionView - All - All + Alt+A + Alt+A - Today - Today + Paste address from clipboard + Paste address from clipboard - This week - This week + Alt+P + Alt+P - This month - This month + Remove this entry + Remove this entry - Last month - Last month + 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. + 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. - This year - This year + S&ubtract fee from amount + S&ubtract fee from amount - Range... - Range... + Message: + Message: - Received with - Received with + This is an unauthenticated payment request. + This is an unauthenticated payment request. - Sent to - Sent to + This is an authenticated payment request. + This is an authenticated payment request. - To yourself - To yourself + Enter a label for this address to add it to the list of used addresses + Enter a label for this address to add it to the list of used addresses - Mined - Mined + 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. + 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. - Other - Other + Pay To: + Pay To: - Enter address or label to search - Enter address or label to search + Memo: + Memo: + + + ShutdownWindow - Min amount - Min amount + %1 is shutting down... + %1 is shutting down... - Copy address - Copy address + Do not shut down the computer until this window disappears. + Do not shut down the computer until this window disappears. + + + SignVerifyMessageDialog - Copy label - Copy label + Signatures - Sign / Verify a Message + Signatures - Sign / Verify a Message - Copy amount - Copy amount + &Sign Message + &Sign Message - Copy transaction ID - Copy transaction ID + 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. + 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. - Copy raw transaction - Copy raw transaction + The Bitcoin address to sign the message with + The Bitcoin address to sign the message with - Edit label - Edit label + Choose previously used address + Choose previously used address - Show transaction details - Show transaction details + Alt+A + Alt+A - Export Transaction History - Export Transaction History + Paste address from clipboard + Paste address from clipboard - Watch-only - Watch-only + Alt+P + Alt+P - Exporting Failed - Exporting Failed + Enter the message you want to sign here + Enter the message you want to sign here - There was an error trying to save the transaction history to %1. - There was an error trying to save the transaction history to %1. + Signature + Signature - Exporting Successful - Exporting Successful + Copy the current signature to the system clipboard + Copy the current signature to the system clipboard - The transaction history was successfully saved to %1. - The transaction history was successfully saved to %1. + Sign the message to prove you own this Bitcoin address + Sign the message to prove you own this Bitcoin address - Comma separated file (*.csv) - Comma separated file (*.csv) + Sign &Message + Sign &Message - Confirmed - Confirmed + Reset all sign message fields + Reset all sign message fields - Date - Date + Clear &All + Clear &All - Type - Type + &Verify Message + &Verify Message - Label - Label + 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! + 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! - Address - Address + The Bitcoin address the message was signed with + The Bitcoin address the message was signed with - ID - ID + Verify the message to ensure it was signed with the specified Bitcoin address + Verify the message to ensure it was signed with the specified Bitcoin address - Range: - Range: + Verify &Message + Verify &Message - to - to + Reset all verify message fields + Reset all verify message fields - UnitDisplayStatusBarControl + SplashScreen - Unit to show amounts in. Click to select another unit. - Unit to show amounts in. Click to select another unit. + [testnet] + [testnet] - WalletFrame + TrafficGraphWidget - No wallet has been loaded. - No wallet has been loaded. + KB/s + KB/s - WalletModel + TransactionDescDialog - Send Coins - Send Coins + This pane shows a detailed description of the transaction + This pane shows a detailed description of the transaction - WalletView - - &Export - &Export - - - Export the data in the current tab to a file - Export the data in the current tab to a file - - - Backup Wallet - Backup Wallet - - - Wallet Data (*.dat) - Wallet Data (*.dat) - - - Backup Failed - Backup Failed - - - There was an error trying to save the wallet data to %1. - There was an error trying to save the wallet data to %1. - - - The wallet data was successfully saved to %1. - The wallet data was successfully saved to %1. - + UnitDisplayStatusBarControl - Backup Successful - Backup Successful + Unit to show amounts in. Click to select another unit. + Unit to show amounts in. Click to select another unit. @@ -2927,14 +1758,6 @@ If <category> is not supplied or if <category> = 1, output all debugging information. If <category> is not supplied or if <category> = 1, output all debugging information. - - Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s) - Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s) - - - Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. - Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. - Prune configured below the minimum of %d MiB. Please use a higher number. Prune configured below the minimum of %d MiB. Please use a higher number. @@ -2975,6 +1798,14 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Accept connections from outside (default: 1 if no -proxy or -connect) + + Bitcoin Core + Bitcoin Core + + + The %s developers + The %s developers + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. @@ -2991,6 +1822,10 @@ Bind to given address and always listen on it. Use [host]:port notation for IPv6 Bind to given address and always listen on it. Use [host]:port notation for IPv6 + + Cannot obtain a lock on data directory %s. %s is probably already running. + Cannot obtain a lock on data directory %s. %s is probably already running. + Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup @@ -2999,6 +1834,14 @@ Distributed under the MIT software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>. Distributed under the MIT software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>. + + Error loading %s: You can't enable HD on a already existing non-HD wallet + Error loading %s: You can't enable HD on a already existing non-HD wallet + + + Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) @@ -3007,6 +1850,22 @@ Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) + + Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds) + Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds) + + + Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s) + Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s) + + + Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly. + Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly. + + + Please contribute if you find %s useful. Visit %s for further information about the software. + Please contribute if you find %s useful. Visit %s for further information about the software. + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) @@ -3019,14 +1878,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications This is a pre-release test build - use at your own risk - do not use for mining or merchant applications - - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - - - Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. - Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. - Use UPnP to map the listening port (default: 1 when listening and no -proxy) Use UPnP to map the listening port (default: 1 when listening and no -proxy) @@ -3043,22 +1894,22 @@ Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. - - Warning: Unknown block versions being mined! It's possible unknown rules are in effect - Warning: Unknown block versions being mined! It's possible unknown rules are in effect - Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. + + You need to rebuild the database using -reindex-chainstate to change -txindex + You need to rebuild the database using -reindex-chainstate to change -txindex + + + %s corrupt, salvage failed + %s corrupt, salvage failed + -maxmempool must be at least %d MB -maxmempool must be at least %d MB @@ -3071,10 +1922,22 @@ Append comment to the user agent string Append comment to the user agent string + + Attempt to recover private keys from a corrupt wallet on startup + Attempt to recover private keys from a corrupt wallet on startup + Block creation options: Block creation options: + + Cannot resolve -%s address: '%s' + Cannot resolve -%s address: '%s' + + + Change index out of range + Change index out of range + Connect only to the specified node(s) Connect only to the specified node(s) @@ -3083,6 +1946,10 @@ Connection options: Connection options: + + Copyright (C) %i-%i + Copyright (C) %i-%i + Corrupted block database detected Corrupted block database detected @@ -3127,6 +1994,22 @@ Error initializing wallet database environment %s! Error initialising wallet database environment %s! + + Error loading %s + Error loading %s + + + Error loading %s: Wallet corrupted + Error loading %s: Wallet corrupted + + + Error loading %s: Wallet requires newer version of %s + Error loading %s: Wallet requires newer version of %s + + + Error loading %s: You can't disable HD on a already existing HD wallet + Error loading %s: You can't disable HD on a already existing HD wallet + Error loading block database Error loading block database @@ -3151,10 +2034,18 @@ Incorrect or no genesis block found. Wrong datadir for network? Incorrect or no genesis block found. Wrong datadir for network? + + Initialization sanity check failed. %s is shutting down. + Initialisation sanity check failed. %s is shutting down. + Invalid -onion address: '%s' Invalid -onion address: '%s' + + Invalid amount for -%s=<amount>: '%s' + Invalid amount for -%s=<amount>: '%s' + Invalid amount for -fallbackfee=<amount>: '%s' Invalid amount for -fallbackfee=<amount>: '%s' @@ -3163,6 +2054,10 @@ Keep the transaction memory pool below <n> megabytes (default: %u) Keep the transaction memory pool below <n> megabytes (default: %u) + + Loading banlist... + Loading banlist... + Location of the auth cookie (default: data dir) Location of the auth cookie (default: data dir) @@ -3179,6 +2074,10 @@ Only connect to nodes in network <net> (ipv4, ipv6 or onion) Only connect to nodes in network <net> (ipv4, ipv6 or onion) + + Print this help message and exit + Print this help message and exit + Print version and exit Print version and exit @@ -3191,6 +2090,14 @@ Prune mode is incompatible with -txindex. Prune mode is incompatible with -txindex. + + Rebuild chain state and block index from the blk*.dat files on disk + Rebuild chain state and block index from the blk*.dat files on disk + + + Rebuild chain state from the currently indexed blocks + Rebuild chain state from the currently indexed blocks + Set database cache size in megabytes (%d to %d, default: %d) Set database cache size in megabytes (%d to %d, default: %d) @@ -3203,6 +2110,14 @@ Specify wallet file (within data directory) Specify wallet file (within data directory) + + The source code is available from %s. + The source code is available from %s. + + + Unable to bind to %s on this computer. %s is probably already running. + Unable to bind to %s on this computer. %s is probably already running. + Unsupported argument -benchmark ignored, use -debug=bench. Unsupported argument -benchmark ignored, use -debug=bench. @@ -3236,12 +2151,16 @@ Wallet %s resides outside data directory %s - Wallet options: - Wallet options: + Wallet debugging/testing options: + Wallet debugging/testing options: + + + Wallet needed to be rewritten: restart %s to complete + Wallet needed to be rewritten: restart %s to complete - You need to rebuild the database using -reindex to change -txindex - You need to rebuild the database using -reindex to change -txindex + Wallet options: + Wallet options: 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 @@ -3255,10 +2174,6 @@ Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces) Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces) - - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) @@ -3303,10 +2218,6 @@ Set maximum size of high-priority/low-fee transactions in bytes (default: %d) Set maximum size of high-priority/low-fee transactions in bytes (default: %d) - - Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) - Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) - The transaction amount is too small to send after the fee has been deducted The transaction amount is too small to send after the fee has been deducted @@ -3315,6 +2226,10 @@ This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard. This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard. + + Use hierarchical deterministic key generation (HD) after BIP32. Only has effect during wallet creation/first start + Use hierarchical deterministic key generation (HD) after BIP32. Only has effect during wallet creation/first start + 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 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 @@ -3331,34 +2246,14 @@ Accept public REST requests (default: %u) Accept public REST requests (default: %u) - - Activating best chain... - Activating best chain... - - - Attempt to recover private keys from a corrupt wallet.dat on startup - Attempt to recover private keys from a corrupt wallet.dat on startup - Automatically create Tor hidden service (default: %d) Automatically create Tor hidden service (default: %d) - - Cannot resolve -whitebind address: '%s' - Cannot resolve -whitebind address: '%s' - Connect through SOCKS5 proxy Connect through SOCKS5 proxy - - Copyright (C) 2009-%i The Bitcoin Core Developers - Copyright (C) 2009-%i The Bitcoin Core Developers - - - Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - Error reading from database, shutting down. Error reading from database, shutting down. @@ -3371,22 +2266,6 @@ Information Information - - Initialization sanity check failed. Bitcoin Core is shutting down. - Initialisation sanity check failed. Bitcoin Core is shutting down. - - - Invalid amount for -maxtxfee=<amount>: '%s' - Invalid amount for -maxtxfee=<amount>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Invalid amount for -minrelaytxfee=<amount>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - Invalid amount for -mintxfee=<amount>: '%s' - Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) @@ -3411,14 +2290,6 @@ RPC server options: RPC server options: - - Rebuild block chain index from current blk000??.dat files on startup - Rebuild block chain index from current blk000??.dat files on startup - - - Receive and display P2P network alerts (default: %u) - Receive and display P2P network alerts (default: %u) - Reducing -maxconnections from %d to %d, because of system limitations. Reducing -maxconnections from %d to %d, because of system limitations. @@ -3491,10 +2362,6 @@ Username for JSON-RPC connections Username for JSON-RPC connections - - Wallet needed to be rewritten: restart Bitcoin Core to complete - Wallet needed to be rewritten: restart Bitcoin Core to complete - Warning Warning @@ -3515,10 +2382,6 @@ ZeroMQ notification options: ZeroMQ notification options: - - wallet.dat corrupt, salvage failed - wallet.dat corrupt, salvage failed - Password for JSON-RPC connections Password for JSON-RPC connections @@ -3527,10 +2390,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) Execute command when the best block changes (%s in cmd is replaced by block hash) - - This help message - This help message - Allow DNS lookups for -addnode, -seednode and -connect Allow DNS lookups for -addnode, -seednode and -connect @@ -3539,10 +2398,6 @@ Loading addresses... Loading addresses... - - Error loading wallet.dat: Wallet corrupted - Error loading wallet.dat: Wallet corrupted - (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) @@ -3559,10 +2414,6 @@ Do not keep transactions in the mempool longer than <n> hours (default: %u) Do not keep transactions in the mempool longer than <n> hours (default: %u) - - Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. - Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. - Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) @@ -3599,6 +2450,10 @@ Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported. Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported. + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s) Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s) @@ -3608,20 +2463,20 @@ Username and hashed password for JSON-RPC connections. The field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A canonical python script is included in share/rpcuser. This option can be specified multiple times - (default: %s) - (default: %s) + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + Warning: Unknown block versions being mined! It's possible unknown rules are in effect - Always query for peer addresses via DNS lookup (default: %u) - Always query for peer addresses via DNS lookup (default: %u) + Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup. + Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup. - Error loading wallet.dat - Error loading wallet.dat + (default: %s) + (default: %s) - Generate coins (default: %u) - Generate coins (default: %u) + Always query for peer addresses via DNS lookup (default: %u) + Always query for peer addresses via DNS lookup (default: %u) How many blocks to check at startup (default: %u, 0 = all) @@ -3707,18 +2562,6 @@ Unknown network specified in -onlynet: '%s' Unknown network specified in -onlynet: '%s' - - Cannot resolve -bind address: '%s' - Cannot resolve -bind address: '%s' - - - Cannot resolve -externalip address: '%s' - Cannot resolve -externalip address: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - Invalid amount for -paytxfee=<amount>: '%s' - Insufficient funds Insufficient funds diff --git a/src/qt/locale/bitcoin_eo.ts b/src/qt/locale/bitcoin_eo.ts index 2095db34bf32e..043b28abc6ac6 100644 --- a/src/qt/locale/bitcoin_eo.ts +++ b/src/qt/locale/bitcoin_eo.ts @@ -25,10 +25,6 @@ C&lose &Fermi - - &Copy Address - &Kopii Adreson - Delete the currently selected address from the list Forigi la elektitan adreson el la listo @@ -45,73 +41,6 @@ &Delete &Forigi - - Choose the address to send coins to - Elektu la alsendotan adreson - - - Choose the address to receive coins with - Elektu la ricevontan adreson - - - C&hoose - &Elekti - - - Sending addresses - Sendaj adresoj - - - Receiving addresses - Ricevaj adresoj - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Jen viaj Bitmon-adresoj por sendi pagojn. Zorge kontrolu la sumon kaj la alsendan adreson antaŭ ol sendi. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Jen viaj bitmonaj adresoj por ricevi pagojn. Estas konsilinde uzi apartan ricevan adreson por ĉiu transakcio. - - - Copy &Label - Kopii &Etikedon - - - &Edit - &Redakti - - - Export Address List - Eksporti Adresliston - - - Comma separated file (*.csv) - Perkome disigita dosiero (*.csv) - - - Exporting Failed - ekspotado malsukcesinta - - - There was an error trying to save the address list to %1. Please try again. - Okazis eraron dum konservo de adreslisto al %1. Bonvolu provi denove. - - - - AddressTableModel - - Label - Etikedo - - - Address - Adreso - - - (no label) - (neniu etikedo) - AskPassphraseDialog @@ -131,86 +60,6 @@ Repeat new passphrase Ripetu la novan pasfrazon - - Encrypt wallet - Ĉifri la monujon - - - This operation needs your wallet passphrase to unlock the wallet. - Ĉi tiu operacio bezonas vian monujan pasfrazon, por malŝlosi la monujon. - - - Unlock wallet - Malŝlosi la monujon - - - This operation needs your wallet passphrase to decrypt the wallet. - Ĉi tiu operacio bezonas vian monujan pasfrazon, por malĉifri la monujon. - - - Decrypt wallet - Malĉifri la monujon - - - Change passphrase - Ŝanĝi la pasfrazon - - - Confirm wallet encryption - Konfirmo de ĉifrado de la monujo - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Atentu! Se vi ĉifras vian monujon kaj perdas la pasfrazon, vi <b>PERDOS LA TUTON DE VIA BITMONO<b>! - - - Are you sure you wish to encrypt your wallet? - Ĉu vi certas, ke vi volas ĉifri la monujon? - - - 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. - GRAVE: antaŭaj sekur-kopioj de via monujo-dosiero estas forigindaj kiam vi havas nove kreitan ĉifritan monujo-dosieron. Pro sekureco, antaŭaj kopioj de la neĉifrita dosiero ne plu funkcios tuj kiam vi ekuzos la novan ĉifritan dosieron. - - - Warning: The Caps Lock key is on! - Atentu: la majuskla baskulo estas ŝaltita! - - - Wallet encrypted - La monujo estas ĉifrita - - - Enter the old passphrase and new passphrase to the wallet. - Tajpu la malnovan pasvorton kaj la novan pasvorton por la monujo. - - - Wallet encryption failed - Ĉifrado de la monujo fiaskis - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Ĉifrado de monujo fiaskis pro interna eraro. Via monujo ne estas ĉifrita. - - - The supplied passphrases do not match. - La pasfrazoj entajpitaj ne samas. - - - Wallet unlock failed - Malŝloso de la monujo fiaskis - - - The passphrase entered for the wallet decryption was incorrect. - La pasfrazo enigita por ĉifrado de monujo ne ĝustas. - - - Wallet decryption failed - Malĉifrado de la monujo fiaskis - - - Wallet passphrase was successfully changed. - Vi sukcese ŝanĝis la pasfrazon de la monujo. - BanTableModel @@ -289,14 +138,6 @@ Open &URI... Malfermi &URI-on... - - Bitcoin Core client - kliento de bitmon-kerno - - - Importing blocks from disk... - Importado de blokoj el disko... - Reindexing blocks on disk... Reindeksado de blokoj sur disko... @@ -341,10 +182,6 @@ &Receive &Ricevi - - Show information about Bitcoin Core - Vidigi informon pri Bitmona Kerno - &Show / Hide &Montri / Kaŝi @@ -381,18 +218,10 @@ Tabs toolbar Langeto-breto - - Bitcoin Core - Kerno de Bitmono - Request payments (generates QR codes and bitcoin: URIs) Peti pagon (kreas QR-kodojn kaj URI-ojn kun prefikso bitcoin:) - - &About Bitcoin Core - &Pri la Bitmona Kerno - Show the list of used sending addresses and labels Vidigi la liston de uzitaj sendaj adresoj kaj etikedoj @@ -512,13 +341,6 @@ Monujo estas <b>ĉifrita</b> kaj aktuale <b>ŝlosita</b> - - ClientModel - - Network Alert - Reta Averto - - CoinControlDialog @@ -593,134 +415,6 @@ Priority Prioritato - - Copy address - Kopii adreson - - - Copy label - Kopii etikedon - - - Copy amount - Kopii sumon - - - Copy transaction ID - Kopii transakcian ID-on - - - Lock unspent - Ŝlosi la neelspezitajn - - - Unlock unspent - Malŝlosi la neelspezitajn - - - Copy quantity - Kopii kvanton - - - Copy fee - Kopii krompagon - - - Copy after fee - Kopii post krompago - - - Copy bytes - Kopii bajtojn - - - Copy priority - Kopii prioritaton - - - Copy dust - Kopii polvon - - - Copy change - Kopii restmonon - - - highest - plej alta - - - higher - pli alta - - - high - alta - - - medium-high - mezalta - - - medium - meza - - - low-medium - mezmalalta - - - low - malalta - - - lower - pli malalta - - - lowest - plej malalta - - - (%1 locked) - (%1 ŝlosita) - - - none - neniu - - - yes - jes - - - no - ne - - - This means a fee of at least %1 per kB is required. - Tio signifas, ke krompago de almenaŭ po %1 por ĉiu kB estas deviga. - - - Can vary +/- 1 byte per input. - Povas varii po +/- 1 bajton por ĉiu enigo. - - - Transactions with higher priority are more likely to get included into a block. - Transakcioj kun pli alta prioritato havas pli altan ŝancon inkluziviĝi en bloko. - - - (no label) - (neniu etikedo) - - - change from %1 (%2) - restmono de %1 (%2) - - - (change) - (restmono) - EditAddressDialog @@ -744,38 +438,6 @@ &Address &Adreso - - New receiving address - Nova adreso por ricevi - - - New sending address - Nova adreso por sendi - - - Edit receiving address - Redakti adreson por ricevi - - - Edit sending address - Redakti adreson por sendi - - - The entered address "%1" is already in the address book. - La adreso enigita "%1" jam ekzistas en la adresaro. - - - The entered address "%1" is not a valid Bitcoin address. - La adreso enigita "%1" ne estas valida Bitmon-adreso. - - - Could not unlock wallet. - Ne eblis malŝlosi monujon. - - - New key generation failed. - Fiaskis kreo de nova ŝlosilo. - FreespaceChecker @@ -802,18 +464,10 @@ HelpMessageDialog - - Bitcoin Core - Kerno de Bitmono - version versio - - About Bitcoin Core - Pri la Bitmona Kerno - Command-line options Komandliniaj agordaĵoj @@ -837,18 +491,6 @@ Welcome Bonvenon - - Welcome to Bitcoin Core. - Bonvenon al la bitmona kerno, Bitcoin Core. - - - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - Dum tiu ĉi unua uzo de la programo, vi povas elekti lokon, kie Bitcoin Core stokos siajn datumojn. - - - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - Bitcoin Core elŝutos kaj konservos kopion de la bitmona blokĉeno. Almenaŭ %1GB da datumoj konserviĝos en tiu loko, kaj tio poiome kreskos. Ankaŭ via monujo konserviĝos en tiu dosierujo. - Use the default data directory Uzi la defaŭltan dosierujon por datumoj @@ -857,10 +499,6 @@ Use a custom data directory: Uzi alian dosierujon por datumoj: - - Bitcoin Core - Kerno de Bitmono - Error Eraro @@ -888,10 +526,6 @@ Select payment request file Elektu la dosieron de la pagpeto - - Select payment request file to open - Elektu la malfermotan dosieron de la pagpeto - OptionsDialog @@ -1075,49 +709,6 @@ Lastaj transakcioj - - PaymentServer - - URI handling - Traktado de URI-oj - - - Invalid payment address %1 - Nevalida pagadreso %1 - - - Requested payment amount of %1 is too small (considered dust). - La petita pagosumo de %1 estas tro malgranda (konsiderata kiel polvo). - - - Payment request error - Eraro dum pagopeto - - - Cannot start bitcoin: click-to-pay handler - Ne eblas lanĉi la ilon 'klaki-por-pagi' - - - Refund from %1 - Repago de %1 - - - Error communicating with %1: %2 - Eraro dum komunikado kun %1: %2 - - - Bad response from server %1 - Malbona respondo de la servilo %1 - - - Payment acknowledged - Pago agnoskita - - - Network request error - Eraro dum ret-peto - - PeerTableModel @@ -1148,25 +739,6 @@ neaplikebla - - QRImageWidget - - &Save Image... - &Konservi Bildon... - - - &Copy Image - &Kopii Bildon - - - Save QR Code - Konservi QR-kodon - - - PNG Image (*.png) - PNG-bildo (*.png) - - RPCConsole @@ -1277,10 +849,6 @@ Out: El: - - Build date - Dato de kompilado - Debug log file Sencimiga protokoldosiero @@ -1356,18 +924,6 @@ Remove Forigi - - Copy label - Kopii etikedon - - - Copy message - Kopiu mesaĝon - - - Copy amount - Kopii sumon - ReceiveRequestDialog @@ -1387,103 +943,40 @@ &Save Image... &Konservi Bildon... + + + SendCoinsDialog - Request payment to %1 - Peti pagon al %1 + Send Coins + Sendi Bitmonon - Payment information - Paginformoj + Coin Control Features + Monregaj Opcioj - URI - URI + Inputs... + Enigoj... - Address - Adreso + Insufficient funds! + Nesufiĉa mono! - Amount - Sumo + Quantity: + Kvanto: - Label - Etikedo + Bytes: + Bajtoj: - Message - Mesaĝo + Amount: + Sumo: - Resulting URI too long, try to reduce the text for label / message. - La rezultanta URI estas tro longa. Provu malplilongigi la tekston de la etikedo / mesaĝo. - - - Error encoding URI into QR Code. - Eraro de kodigo de URI en la QR-kodon. - - - - RecentRequestsTableModel - - Date - Dato - - - Label - Etikedo - - - Message - Mesaĝo - - - Amount - Sumo - - - (no label) - (neniu etikedo) - - - (no message) - (neniu mesaĝo) - - - - SendCoinsDialog - - Send Coins - Sendi Bitmonon - - - Coin Control Features - Monregaj Opcioj - - - Inputs... - Enigoj... - - - Insufficient funds! - Nesufiĉa mono! - - - Quantity: - Kvanto: - - - Bytes: - Bajtoj: - - - Amount: - Sumo: - - - Priority: - Prioritato: + Priority: + Prioritato: Fee: @@ -1533,82 +1026,6 @@ S&end Ŝendi - - Confirm send coins - Konfirmi sendon de bitmono - - - %1 to %2 - %1 al %2 - - - Copy quantity - Kopii kvanton - - - Copy amount - Kopii sumon - - - Copy fee - Kopii krompagon - - - Copy after fee - Kopii post krompago - - - Copy bytes - Kopii bajtojn - - - Copy priority - Kopii prioritaton - - - Copy change - Kopii restmonon - - - or - - - - The amount to pay must be larger than 0. - La pagenda sumo devas esti pli ol 0. - - - The amount exceeds your balance. - La sumo estas pli granda ol via saldo. - - - The total exceeds your balance when the %1 transaction fee is included. - La sumo kun la %1 krompago estas pli granda ol via saldo. - - - Transaction creation failed! - Kreo de transakcio fiaskis! - - - Warning: Invalid Bitcoin address - Averto: Nevalida Bitmon-adreso - - - (no label) - (neniu etikedo) - - - Copy dust - Kopii polvon - - - Are you sure you want to send? - Ĉu vi certas, ke vi volas sendi? - - - added as transaction fee - aldonita kiel krompago - SendCoinsEntry @@ -1620,10 +1037,6 @@ Pay &To: &Ricevonto: - - Enter a label for this address to add it to your address book - Tajpu etikedon por tiu ĉi adreso kaj aldonu ĝin al via adresaro - &Label: &Etikedo: @@ -1746,69 +1159,9 @@ Reset all verify message fields Reagordigi ĉiujn prikontrolajn kampojn - - Click "Sign Message" to generate signature - Klaku "Subskribi Mesaĝon" por krei subskribon - - - The entered address is invalid. - La adreso, kiun vi enmetis, estas nevalida. - - - Please check the address and try again. - Bonvolu kontroli la adreson kaj reprovi. - - - The entered address does not refer to a key. - La adreso, kiun vi enmetis, referencas neniun ŝlosilon. - - - Wallet unlock was cancelled. - Malŝloso de monujo estas nuligita. - - - Private key for the entered address is not available. - La privata ŝlosilo por la enigita adreso ne disponeblas. - - - Message signing failed. - Subskribo de mesaĝo fiaskis. - - - Message signed. - Mesaĝo estas subskribita. - - - The signature could not be decoded. - Ne eblis malĉifri la subskribon. - - - Please check the signature and try again. - Bonvolu kontroli la subskribon kaj reprovu. - - - The signature did not match the message digest. - La subskribo ne kongruis kun la mesaĝ-kompilaĵo. - - - Message verification failed. - Kontrolo de mesaĝo malsukcesis. - - - Message verified. - Mesaĝo sukcese kontrolita. - SplashScreen - - Bitcoin Core - Kerno de Bitmono - - - The Bitcoin Core developers - La programistoj de Bitmona Kerno - [testnet] [testnet] @@ -1821,382 +1174,16 @@ KB/s - - TransactionDesc - - Open until %1 - Malferma ĝis %1 - - - %1/offline - %1/senkonekte - - - %1/unconfirmed - %1/nekonfirmite - - - %1 confirmations - %1 konfirmoj - - - Status - Stato - - - Date - Dato - - - Source - Fonto - - - Generated - Kreita - - - From - De - - - To - Al - - - own address - propra adreso - - - label - etikedo - - - Credit - Kredito - - - not accepted - ne akceptita - - - Debit - Debeto - - - Transaction fee - Krompago - - - Net amount - Neta sumo - - - Message - Mesaĝo - - - Comment - Komento - - - Transaction ID - Transakcia ID - - - Merchant - Vendisto - - - 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. - Kreitaj moneroj devas esti maturaj je %1 blokoj antaŭ ol eblas elspezi ilin. Kiam vi generis tiun ĉi blokon, ĝi estis elsendita al la reto por aldono al la blokĉeno. Se tiu aldono malsukcesas, ĝia stato ŝanĝiĝos al "neakceptita" kaj ne eblos elspezi ĝin. Tio estas malofta, sed povas okazi se alia bloko estas kreita je preskaŭ la sama momento kiel la via. - - - Debug information - Sencimigaj informoj - - - Transaction - Transakcio - - - Inputs - Enigoj - - - Amount - Sumo - - - true - vera - - - false - malvera - - - , has not been successfully broadcast yet - , ankoraŭ ne elsendita sukcese - - - unknown - nekonata - - TransactionDescDialog - - Transaction details - Transakciaj detaloj - This pane shows a detailed description of the transaction Tiu ĉi panelo montras detalan priskribon de la transakcio - - TransactionTableModel - - Date - Dato - - - Type - Tipo - - - Open until %1 - Malferma ĝis %1 - - - Confirmed (%1 confirmations) - Konfirmita (%1 konfirmoj) - - - This block was not received by any other nodes and will probably not be accepted! - Tiun ĉi blokon ne ricevis ajna alia nodo, kaj ĝi verŝajne ne akceptiĝos! - - - Generated but not accepted - Kreita sed ne akceptita - - - Offline - Senkonekte - - - Label - Etikedo - - - Unconfirmed - Nekonfirmita - - - Received with - Ricevita kun - - - Received from - Ricevita de - - - Sent to - Sendita al - - - Payment to yourself - Pago al vi mem - - - Mined - Minita - - - (n/a) - neaplikebla - - - Transaction status. Hover over this field to show number of confirmations. - Transakcia stato. Ŝvebi super tiu ĉi kampo por montri la nombron de konfirmoj. - - - Date and time that the transaction was received. - Dato kaj horo kiam la transakcio alvenis. - - - Type of transaction. - Tipo de transakcio. - - - Amount removed from or added to balance. - Sumo elprenita de aŭ aldonita al la saldo. - - - - TransactionView - - All - Ĉiuj - - - Today - Hodiaŭ - - - This week - Ĉi-semajne - - - This month - Ĉi-monate - - - Last month - Pasintmonate - - - This year - Ĉi-jare - - - Range... - Intervalo... - - - Received with - Ricevita kun - - - Sent to - Sendita al - - - To yourself - Al vi mem - - - Mined - Minita - - - Other - Aliaj - - - Enter address or label to search - Tajpu adreson aŭ etikedon por serĉi - - - Min amount - Minimuma sumo - - - Copy address - Kopii adreson - - - Copy label - Kopii etikedon - - - Copy amount - Kopii sumon - - - Copy transaction ID - Kopii transakcian ID-on - - - Edit label - Redakti etikedon - - - Show transaction details - Montri detalojn de transakcio - - - Exporting Failed - ekspotado malsukcesinta - - - Comma separated file (*.csv) - Perkome disigita dosiero (*.csv) - - - Confirmed - Konfirmita - - - Date - Dato - - - Type - Tipo - - - Label - Etikedo - - - Address - Adreso - - - ID - ID - - - Range: - Intervalo: - - - to - al - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - Send Coins - Sendi Bitmonon - - - - WalletView - - &Export - &Eksporti - - - Export the data in the current tab to a file - Eksporti la datumojn el la aktuala langeto al dosiero - - - Backup Wallet - Krei sekurkopion de monujo - - - Wallet Data (*.dat) - Monuj-datumoj (*.dat) - - - Backup Failed - Malsukcesis sekurkopio - - - Backup Successful - Sukcesis krei sekurkopion - - bitcoin-core @@ -2227,6 +1214,10 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Akcepti konektojn el ekstere (defaŭlte: 1 se ne estas -proxy nek -connect) + + Bitcoin Core + Kerno de Bitmono + Bind to given address and always listen on it. Use [host]:port notation for IPv6 Bindi al donita adreso kaj ĉiam aŭskulti per ĝi. Uzu la formaton [gastigo]:pordo por IPv6 @@ -2247,10 +1238,6 @@ Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Averto: ŝajne ni ne tute konsentas kun niaj samtavolanoj! Eble vi devas ĝisdatigi vian klienton, aŭ eble aliaj nodoj faru same. - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Averto: via wallet.dat estas difektita, sed la datumoj sukcese saviĝis! La originala wallet.dat estas nun konservita kiel wallet.{timestamp}.bak en %s; se via saldo aŭ transakcioj estas malĝustaj vi devus restaŭri per alia sekurkopio. - <category> can be: <category> povas esti: @@ -2327,34 +1314,14 @@ Wallet options: Monujaj opcioj: - - You need to rebuild the database using -reindex to change -txindex - Vi devas rekontrui la datumbazon kun -reindex por ŝanĝi -txindex - Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message) Plenumi komandon kiam rilata alerto riceviĝas, aŭ kiam ni vidas tre longan forkon (%s en cms anstataŭiĝas per mesaĝo) - - Cannot resolve -whitebind address: '%s' - Ne eblas trovi la adreson -whitebind: '%s' - Information Informoj - - Invalid amount for -maxtxfee=<amount>: '%s' - Nevalida sumo por -maxtxfee=<amount>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Nevalida sumo por -minrelaytxfee=<amount>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - Nevalida sumo por -mintxfee=<amount>: '%s' - Send trace/debug info to console instead of debug.log file Sendi spurajn/sencimigajn informojn al la konzolo anstataŭ al dosiero debug.log @@ -2391,10 +1358,6 @@ Warning Averto - - wallet.dat corrupt, salvage failed - wallet.dat estas difektita, riparo malsukcesis - Password for JSON-RPC connections Pasvorto por konektoj JSON-RPC @@ -2403,10 +1366,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) Plenumi komandon kiam plej bona bloko ŝanĝiĝas (%s en cmd anstataŭiĝas per bloka haketaĵo) - - This help message - Tiu ĉi helpmesaĝo - Allow DNS lookups for -addnode, -seednode and -connect Permesi DNS-elserĉojn por -addnote, -seednote kaj -connect @@ -2415,14 +1374,6 @@ Loading addresses... Ŝarĝante adresojn... - - Error loading wallet.dat: Wallet corrupted - Eraro dum ŝargado de wallet.dat: monujo difektita - - - Error loading wallet.dat - Eraro dum ŝargado de wallet.dat - Invalid -proxy address: '%s' Nevalid adreso -proxy: '%s' @@ -2431,18 +1382,6 @@ Unknown network specified in -onlynet: '%s' Nekonata reto specifita en -onlynet: '%s' - - Cannot resolve -bind address: '%s' - Ne eblas trovi la adreson -bind: '%s' - - - Cannot resolve -externalip address: '%s' - Ne eblas trovi la adreson -externalip: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - Nevalida sumo por -paytxfee=<amount>: '%s' - Insufficient funds Nesufiĉa mono diff --git a/src/qt/locale/bitcoin_es.ts b/src/qt/locale/bitcoin_es.ts index 5322634c5db98..fc430e86b3c04 100644 --- a/src/qt/locale/bitcoin_es.ts +++ b/src/qt/locale/bitcoin_es.ts @@ -25,10 +25,6 @@ C&lose C&errar - - &Copy Address - &Copiar dirección - Delete the currently selected address from the list Eliminar la dirección seleccionada de la lista @@ -45,73 +41,6 @@ &Delete &Eliminar - - Choose the address to send coins to - Elija la dirección para enviar monedas a - - - Choose the address to receive coins with - Elija la dirección para recibir monedas con - - - C&hoose - E&scoger - - - Sending addresses - Direcciones de envío - - - Receiving addresses - Direcciones de recepción - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Estas son tus direcciones Bitcoin para enviar los pagos. Comprueba siempre la cantidad y la dirección receptora antes de enviar las monedas. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Estas son tus direcciones de Bitcoin para recibir los pagos. Se recomienda utilizar una nueva dirección de recepción para cada transacción. - - - Copy &Label - Copiar &Etiqueta - - - &Edit - &Editar - - - Export Address List - Exportar la lista de direcciones - - - Comma separated file (*.csv) - Archivos separados por coma (*.csv) - - - Exporting Failed - Fallo al exportar - - - There was an error trying to save the address list to %1. Please try again. - Hubo un error al tratar de guardar en la lista de direcciones a %1 . Por favor, vuelve a intentarlo . - - - - AddressTableModel - - Label - Etiqueta - - - Address - Dirección - - - (no label) - (sin etiqueta) - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase Repita la nueva contraseña - - Encrypt wallet - Cifrar el monedero - - - This operation needs your wallet passphrase to unlock the wallet. - Esta operación requiere su contraseña para desbloquear el monedero. - - - Unlock wallet - Desbloquear monedero - - - This operation needs your wallet passphrase to decrypt the wallet. - Esta operación requiere su contraseña para descifrar el monedero. - - - Decrypt wallet - Descifrar el monedero - - - Change passphrase - Cambiar contraseña - - - Confirm wallet encryption - Confirmar cifrado del monedero - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Atencion: ¡Si cifra su monedero y pierde la contraseña perderá <b>TODOS SUS BITCOINS</b>!" - - - Are you sure you wish to encrypt your wallet? - ¿Estás seguro que deseas cifrar tu monedero ? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Bitcoin Core se cerrará ahora para completar el procedo de encriptación. Recuerda que encriptar tu cartera no te protegerá completamente de la pérdida de bitcoins por infección de malware en tu computadora. - - - 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. - IMPORTANTE: Cualquier copia de seguridad que haya realizado previamente de su archivo de monedero debe reemplazarse con el nuevo archivo de monedero cifrado. Por razones de seguridad, las copias de seguridad previas del archivo de monedero no cifradas serán inservibles en cuanto comience a usar el nuevo monedero cifrado. - - - Warning: The Caps Lock key is on! - Aviso: ¡La tecla de Mayúsculas está activada! - - - Wallet encrypted - Monedero cifrado - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Introduzca la nueva contraseña para el monedero.<br/>Utilice por favor una contraseña con <b>diez o más caracteres aleatorios</b> o con <b>ocho o más palabras</b>. - - - Enter the old passphrase and new passphrase to the wallet. - Introduce la antigua y la nueva contraseña de la cartera. - - - Wallet encryption failed - Ha fallado el cifrado del monedero - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Ha fallado el cifrado del monedero debido a un error interno. El monedero no ha sido cifrado. - - - The supplied passphrases do not match. - Las contraseñas no coinciden. - - - Wallet unlock failed - Ha fallado el desbloqueo del monedero - - - The passphrase entered for the wallet decryption was incorrect. - La contraseña introducida para descifrar el monedero es incorrecta. - - - Wallet decryption failed - Ha fallado el descifrado del monedero - - - Wallet passphrase was successfully changed. - Se ha cambiado correctamente la contraseña del monedero. - BanTableModel @@ -269,6 +110,14 @@ Quit application Salir de la aplicación + + &About %1 + &Acerca de %1 + + + Show information about %1 + Mostrar información acerca de %1 + About &Qt Acerca de &Qt @@ -281,6 +130,10 @@ &Options... &Opciones... + + Modify configuration options for %1 + Modificar las opciones de configuración para %1 + &Encrypt Wallet... &Cifrar monedero… @@ -305,14 +158,6 @@ Open &URI... Abrir &URI... - - Bitcoin Core client - Cliente Bitcoin Core - - - Importing blocks from disk... - Importando bloques de disco... - Reindexing blocks on disk... Reindexando bloques en disco... @@ -357,10 +202,6 @@ &Receive &Recibir - - Show information about Bitcoin Core - Mostrar información acerca de Bitcoin Core - &Show / Hide &Mostrar / Ocultar @@ -397,22 +238,10 @@ Tabs toolbar Barra de pestañas - - Bitcoin Core - Bitcoin Core - Request payments (generates QR codes and bitcoin: URIs) Solicitar pagos (generando códigos QR e identificadores URI "bitcoin:") - - &About Bitcoin Core - &Acerca de Bitcoin Core - - - Modify configuration options for Bitcoin Core - Modificar las opciones de configuración de Bitcoin - Show the list of used sending addresses and labels Mostrar la lista de direcciones de envío y etiquetas @@ -429,14 +258,18 @@ &Command-line options &Opciones de consola de comandos - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Mostrar el mensaje de ayuda de Bitcoin Core con una lista de las posibles opciones de la consola de comandos de Bitcoin - %n active connection(s) to Bitcoin network %n conexión activa hacia la red Bitcoin%n conexiones activas hacia la red Bitcoin + + Indexing blocks on disk... + Indexando bloques en disco... + + + Processing blocks on disk... + Procesando bloques en disco... + No block source available... Ninguna fuente de bloques disponible ... @@ -493,6 +326,14 @@ Up to date Actualizado + + Show the %1 help message to get a list with possible Bitcoin command-line options + Mostrar el mensaje de ayuda %1 para obtener una lista de los posibles comandos de linea de comandos de Bitcoin + + + %1 client + %1 cliente + Catching up... Actualizando... @@ -544,13 +385,6 @@ El monedero está <b>cifrado</b> y actualmente <b>bloqueado</b> - - ClientModel - - Network Alert - Alerta de red - - CoinControlDialog @@ -629,150 +463,6 @@ Priority Prioridad - - Copy address - Copiar dirección - - - Copy label - Copiar etiqueta - - - Copy amount - Copiar cuantía - - - Copy transaction ID - Copiar identificador de transacción - - - Lock unspent - Bloquear lo no gastado - - - Unlock unspent - Desbloquear lo no gastado - - - Copy quantity - Copiar cantidad - - - Copy fee - Copiar comisión - - - Copy after fee - Copiar después de aplicar comisión - - - Copy bytes - Copiar bytes - - - Copy priority - Copiar prioridad - - - Copy dust - Copiar polvo - - - Copy change - Copiar cambio - - - highest - lo más alto - - - higher - más alto - - - high - alto - - - medium-high - medio-alto - - - medium - medio - - - low-medium - bajo-medio - - - low - bajo - - - lower - más bajo - - - lowest - lo más bajo - - - (%1 locked) - (%1 bloqueado) - - - none - ninguna - - - This label turns red if the transaction size is greater than 1000 bytes. - Esta etiqueta se mostrará en rojo si el tamaño de la transacción es mayor de 1000 bytes. - - - This label turns red if the priority is smaller than "medium". - Esta etiqueta se mostrará en rojo si la prioridad es menor a "media" - - - This label turns red if any recipient receives an amount smaller than %1. - Esta etiqueta se vuelve roja si el cambio es menor que %1 - - - Can vary +/- %1 satoshi(s) per input. - Puede variar en +/- %1 satoshi(s) por entrada. - - - yes - si - - - no - no - - - This means a fee of at least %1 per kB is required. - Esto implica que se requiere una comisión de al menos %1 por kB - - - Can vary +/- 1 byte per input. - Puede variar en +/- 1 byte por entrada. - - - Transactions with higher priority are more likely to get included into a block. - Las transacciones con mayor prioridad tienen mayor probabilidad de ser incluidas en un bloque. - - - (no label) - (sin etiqueta) - - - change from %1 (%2) - Cambio desde %1 (%2) - - - (change) - (cambio) - EditAddressDialog @@ -796,38 +486,6 @@ &Address &Dirección - - New receiving address - Nueva dirección de recepción - - - New sending address - Nueva dirección de envío - - - Edit receiving address - Editar dirección de recepción - - - Edit sending address - Editar dirección de envío - - - The entered address "%1" is already in the address book. - La dirección introducida "%1" ya está presente en la libreta de direcciones. - - - The entered address "%1" is not a valid Bitcoin address. - La dirección introducida "%1" no es una dirección Bitcoin válida. - - - Could not unlock wallet. - No se pudo desbloquear el monedero. - - - New key generation failed. - Ha fallado la generación de la nueva clave. - FreespaceChecker @@ -854,10 +512,6 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin Core - version versión @@ -867,8 +521,8 @@ (%1-bit) - About Bitcoin Core - Acerca de Bitcoin Core + About %1 + Acerda de %1 Command-line options @@ -903,8 +557,8 @@ Establecer los certificados raíz SSL para solicitudes de pago (predeterminado: -system-) - Reset all settings changes made over the GUI - Resetear los cambios de configuracion hechos por el GUI + Reset all settings changed in the GUI + Reiniciar todos los ajustes modificados en el GUI @@ -914,16 +568,16 @@ Bienvenido - Welcome to Bitcoin Core. - Bienvenido a Bitcoin Core + Welcome to %1. + Bienvenido a %1 - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - Al ser la primera vez que se ejecuta el programa, puede elegir dónde almacenará sus datos Bitcoin Core. + As this is the first time the program is launched, you can choose where %1 will store its data. + Al ser la primera vez que se ejecuta el programa, puede elegir donde %1 almacenara sus datos - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - Bitcoin Core va a descargar y guardar una copia de la cadena de bloques de Bitcoin. Se almacenará al menos %1GB de datos en este directorio, que irá creciendo con el tiempo. El monedero se guardará también en este directorio. + %1 will download and store a copy of the Bitcoin block chain. At least %2GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. + %1 va a descargar y almacenar una copia de la cadena de bloques de Bitcoin. Al menos %2GB de datos seran almacenados en este directorio, que ira creciendo con el tiempo. El monedero se guardara tambien en ese directorio. Use the default data directory @@ -933,10 +587,6 @@ Use a custom data directory: Utilizar un directorio de datos personalizado: - - Bitcoin Core - Bitcoin Core - Error: Specified data directory "%1" cannot be created. Error: no ha podido crearse el directorio de datos especificado "%1". @@ -972,10 +622,6 @@ Select payment request file Seleccionar archivo de sulicitud de pago - - Select payment request file to open - Seleccionar el archivo de solicitud de pago para abrir - OptionsDialog @@ -987,6 +633,14 @@ &Main &Principal + + Automatically start %1 after logging in to the system. + Iniciar automaticamente %1 al encender el sistema. + + + &Start %1 on system login + &Iniciar %1 al iniciar el sistema + Size of &database cache Tamaño de cache de la &base de datos @@ -1015,10 +669,6 @@ 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. Minimizar en lugar de salir de la aplicación cuando la ventana está cerrada. Cuando se activa esta opción, la aplicación sólo se cerrará después de seleccionar Salir en el menú. - - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - El idioma de la interfaz de usuario puede establecerse aquí. Este ajuste se aplicará cuando se reinicie Bitcoin. - 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 |. Identificadores URL de terceros (por ejemplo, un explorador de bloques) que aparecen en la pestaña de transacciones como elementos del menú contextual. El %s en la URL es reemplazado por el valor hash de la transacción. Se pueden separar URL múltiples por una barra vertical |. @@ -1043,14 +693,6 @@ &Network &Red - - Automatically start Bitcoin Core after logging in to the system. - Iniciar automáticamente Bitcoin Core al iniciar el sistema. - - - &Start Bitcoin Core on system login - &Iniciar Bitcoin Core al inicio del sistema - (0 = auto, <0 = leave that many cores free) (0 = automático, <0 = dejar libres ese número de núcleos) @@ -1135,6 +777,14 @@ &Window &Ventana + + &Hide the icon from the system tray. + &Ocultar el icono de la barra de tareas + + + Hide tray icon + Ocultar barra de tareas + Show only a tray icon after minimizing the window. Minimizar la ventana a la bandeja de iconos del sistema. @@ -1155,6 +805,10 @@ User Interface &language: I&dioma de la interfaz de usuario + + The user interface language can be set here. This setting will take effect after restarting %1. + El idioma de la interfaz de usuario puede establecerse aquí. Esta configuración tendrá efecto tras reiniciar %1. + &Unit to show amounts in: Mostrar las cantidades en la &unidad: @@ -1280,140 +934,49 @@ - PaymentServer + PeerTableModel - URI handling - Gestión de URI + User Agent + User Agent - Invalid payment address %1 - Dirección de pago no válida %1 + Node/Service + Nodo/Servicio - Payment request rejected - Solicitud de pago rechazada + Ping Time + Ping + + + QObject - Payment request network doesn't match client network. - La red de solicitud de pago no coincide con la red cliente + Amount + Cantidad - Payment request is not initialized. - La solicitud de pago no está inicializada + Enter a Bitcoin address (e.g. %1) + Introducir una dirección Bitcoin (p. ej. %1) - Requested payment amount of %1 is too small (considered dust). - La cantidad del pago solicitado (%1) es demasiado pequeña (considerada polvo). + %1 d + %1 d - Payment request error - Error en solicitud de pago + %1 h + %1 h - Cannot start bitcoin: click-to-pay handler - No se puede iniciar el gestor de identificadores "bitcoin:" de clic-para-pagar + %1 m + %1 m - Payment request fetch URL is invalid: %1 - La URL de obtención de la solicitud de pago es inválida: %1 + %1 s + %1 s - URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - ¡No se puede leer el identificador URI! Esto puede deberse a una dirección Bitcoin inválida o a parámetros de la URI mal formados - - - Payment request file handling - Procesado del archivo de solicitud de pago - - - Payment request file cannot be read! This can be caused by an invalid payment request file. - ¡No puede leerse el archivo de solicitud de pago! Esto puede deberse a un archivo inválido de solicitud de pago. - - - Payment request expired. - Solicitud de pago caducada. - - - Unverified payment requests to custom payment scripts are unsupported. - No están soportadas las peticiones inseguras a scripts de pago personalizados - - - Invalid payment request. - Petición de pago no válida. - - - Refund from %1 - Devolución desde %1 - - - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - La petición de pago %1 es demasiado grande (%2 bytes, permitidos %3 bytes). - - - Error communicating with %1: %2 - Error en la comunicación con %1: %2 - - - Payment request cannot be parsed! - ¡No puede leerse la solicitud de pago! - - - Bad response from server %1 - Respuesta errónea del servidor %1 - - - Payment acknowledged - Pago aceptado - - - Network request error - Error en petición de red - - - - PeerTableModel - - User Agent - User Agent - - - Node/Service - Nodo/Servicio - - - Ping Time - Ping - - - - QObject - - Amount - Cantidad - - - Enter a Bitcoin address (e.g. %1) - Introducir una dirección Bitcoin (p. ej. %1) - - - %1 d - %1 d - - - %1 h - %1 h - - - %1 m - %1 m - - - %1 s - %1 s - - - None - Ninguno + None + Ninguno N/A @@ -1424,25 +987,6 @@ %1 ms - - QRImageWidget - - &Save Image... - Guardar Imagen... - - - &Copy Image - Copiar imagen - - - Save QR Code - Guardar código QR - - - PNG Image (*.png) - Imágenes PNG (*.png) - - RPCConsole @@ -1473,6 +1017,10 @@ Using BerkeleyDB version Utilizando la versión de BerkeleyDB + + Datadir + Datadir + Startup time Hora de inicio @@ -1509,10 +1057,6 @@ Memory usage Uso de memoria - - Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. - Abre el archivo de registro de depuración de Bitcoin desde el directorio de datos actual. Esto puede tardar unos segundos para ficheros de registro de gran tamaño. - Received Recibido @@ -1561,6 +1105,18 @@ User Agent User Agent + + Open the %1 debug log file from the current data directory. This can take a few seconds for large log files. + Abrir el archivo de depuración %1 desde el directorio de datos actual. Puede tardar unos segundos para ficheros de gran tamaño. + + + Decrease font size + Disminuir tamaño de letra + + + Increase font size + Aumentar tamaño de letra + Services Servicios @@ -1629,10 +1185,6 @@ Out: Saliente: - - Build date - Fecha de compilación - Debug log file Archivo de registro de depuración @@ -1670,8 +1222,8 @@ &Desbanear Nodo - Welcome to the Bitcoin Core RPC console. - Bienvenido a la consola RPC de Bitcoin Core. + Welcome to the %1 RPC console. + Bienvenido a la consola RPC %1. Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. @@ -1800,18 +1352,6 @@ Remove Eliminar - - Copy label - Copiar etiqueta - - - Copy message - Mensaje - - - Copy amount - Copiar cuantía - ReceiveRequestDialog @@ -1831,73 +1371,6 @@ &Save Image... Guardar Imagen... - - Request payment to %1 - Solicitar pago a %1 - - - Payment information - Información de pago - - - URI - URI - - - Address - Dirección - - - Amount - Cantidad - - - Label - Etiqueta - - - Message - Mensaje - - - Resulting URI too long, try to reduce the text for label / message. - URI resultante demasiado larga. Intente reducir el texto de la etiqueta / mensaje. - - - Error encoding URI into QR Code. - Error al codificar la URI en el código QR. - - - - RecentRequestsTableModel - - Date - Fecha - - - Label - Etiqueta - - - Message - Mensaje - - - Amount - Cantidad - - - (no label) - (sin etiqueta) - - - (no message) - (Ningun mensaje) - - - (no amount) - (sin cantidad) - SendCoinsDialog @@ -2017,14 +1490,6 @@ fast rápido - - Send as zero-fee transaction if possible - Enviar transacción, si es posible, sin comisión - - - (confirmation may take longer) - (confirmación puede tardar más tiempo) - Send to multiple recipients at once Enviar a múltiples destinatarios de una vez @@ -2057,118 +1522,6 @@ S&end &Enviar - - Confirm send coins - Confirmar el envío de bitcoins - - - %1 to %2 - %1 a %2 - - - Copy quantity - Copiar cantidad - - - Copy amount - Copiar cuantía - - - Copy fee - Copiar donación - - - Copy after fee - Copiar después de aplicar donación - - - Copy bytes - Copiar bytes - - - Copy priority - Copiar prioridad - - - Copy change - Copiar Cambio - - - Total Amount %1 - Monto Total %1 - - - or - o - - - The amount to pay must be larger than 0. - La cantidad por pagar tiene que ser mayor de 0. - - - The amount exceeds your balance. - La cantidad sobrepasa su saldo. - - - The total exceeds your balance when the %1 transaction fee is included. - El total sobrepasa su saldo cuando se incluye la tasa de envío de %1 - - - Transaction creation failed! - ¡Ha fallado la creación de la transacción! - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - ¡La transacción fue rechazada! Esto puede haber ocurrido si alguno de los bitcoins de su monedero ya estaba gastado o si ha usado una copia de wallet.dat y los bitcoins estaban gastados en la copia pero no se habían marcado como gastados aqui. - - - A fee higher than %1 is considered an absurdly high fee. - Una comisión mayor al %1 se considera demasiado alta. - - - Payment request expired. - Solicitud de pago caducada. - - - Pay only the required fee of %1 - Paga sólo la cuota mínima de %1 - - - Estimated to begin confirmation within %n block(s). - Estimado para empezar la confirmación dentro de %n bloque.Estimado para empezar la confirmación dentro de %n bloques. - - - The recipient address is not valid. Please recheck. - La dirección del destinatario no es válida. Por favor, compruébela de nuevo. - - - Duplicate address found: addresses should only be used once each. - Se ha encontrado una dirección duplicada. Solo se puede enviar a cada dirección una vez por operación de envío. - - - Warning: Invalid Bitcoin address - Alerta: Dirección de Bitcoin inválida - - - (no label) - (sin etiqueta) - - - Warning: Unknown change address - Alerta: Dirección de Bitcoin inválida - - - Copy dust - Copiar polvo - - - Are you sure you want to send? - ¿Está seguro que desea enviar? - - - added as transaction fee - añadido como comisión de transacción - SendCoinsEntry @@ -2180,10 +1533,6 @@ Pay &To: &Pagar a: - - Enter a label for this address to add it to your address book - Etiquete esta dirección para añadirla a la libreta - &Label: &Etiqueta: @@ -2201,700 +1550,182 @@ Dirección Bitcoin a la que enviar el pago - Alt+A - Alt+A - - - Paste address from clipboard - Pegar dirección desde portapapeles - - - Alt+P - Alt+P - - - Remove this entry - Eliminar esta transacción - - - 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. - La cuota será deducida de la cantidad que sea mandada. El destinatario recibirá menos bitcoins de los que entres en el - - - S&ubtract fee from amount - Restar comisiones a la cantidad - - - Message: - Mensaje: - - - This is an unauthenticated payment request. - Esta es una petición de pago no autentificada. - - - This is an authenticated payment request. - Esta es una petición de pago autentificada. - - - Enter a label for this address to add it to the list of used addresses - Introduce una etiqueta para esta dirección para añadirla a la lista de direcciones utilizadas - - - 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. - Un mensaje que se adjuntó a la bitcoin: URL que será almacenada con la transacción para su referencia. Nota: Este mensaje no se envía a través de la red Bitcoin. - - - Pay To: - Paga a: - - - Memo: - Memo: - - - - ShutdownWindow - - Bitcoin Core is shutting down... - Bitcoin Core se está cerrando... - - - Do not shut down the computer until this window disappears. - No apague el equipo hasta que desaparezca esta ventana. - - - - SignVerifyMessageDialog - - Signatures - Sign / Verify a Message - Firmas - Firmar / verificar un mensaje - - - &Sign Message - &Firmar mensaje - - - 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. - Puede firmar los mensajes con sus direcciones para demostrar que las posee. Tenga cuidado de no firmar cualquier cosa de manera vaga o aleatoria, pues los ataques de phishing pueden tratar de engañarle firmando su identidad a través de ellos. Sólo firme declaraciones totalmente detalladas con las que usted esté de acuerdo. - - - The Bitcoin address to sign the message with - Dirección Bitcoin con la que firmar el mensaje - - - Choose previously used address - Escoger dirección previamente usada - - - Alt+A - Alt+A - - - Paste address from clipboard - Pegar dirección desde portapapeles - - - Alt+P - Alt+P - - - Enter the message you want to sign here - Introduzca el mensaje que desea firmar aquí - - - Signature - Firma - - - Copy the current signature to the system clipboard - Copiar la firma actual al portapapeles del sistema - - - Sign the message to prove you own this Bitcoin address - Firmar el mensaje para demostrar que se posee esta dirección Bitcoin - - - Sign &Message - Firmar &mensaje - - - Reset all sign message fields - Vaciar todos los campos de la firma de mensaje - - - Clear &All - Vaciar &todo - - - &Verify Message - &Verificar mensaje - - - 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! - Introduzca la dirección para la firma, el mensaje (asegurándose de copiar tal cual los saltos de línea, espacios, tabulaciones, etc.) y la firma a continuación para verificar el mensaje. Tenga cuidado de no asumir más información de lo que dice el propio mensaje firmado para evitar fraudes basados en ataques de tipo man-in-the-middle. - - - The Bitcoin address the message was signed with - La dirección Bitcoin con la que se firmó el mensaje - - - Verify the message to ensure it was signed with the specified Bitcoin address - Verificar el mensaje para comprobar que fue firmado con la dirección Bitcoin indicada - - - Verify &Message - Verificar &mensaje - - - Reset all verify message fields - Vaciar todos los campos de la verificación de mensaje - - - Click "Sign Message" to generate signature - Haga clic en "Firmar mensaje" para generar la firma - - - The entered address is invalid. - La dirección introducida es inválida. - - - Please check the address and try again. - Verifique la dirección e inténtelo de nuevo. - - - The entered address does not refer to a key. - La dirección introducida no corresponde a una clave. - - - Wallet unlock was cancelled. - Se ha cancelado el desbloqueo del monedero. - - - Private key for the entered address is not available. - No se dispone de la clave privada para la dirección introducida. - - - Message signing failed. - Ha fallado la firma del mensaje. - - - Message signed. - Mensaje firmado. - - - The signature could not be decoded. - No se puede decodificar la firma. - - - Please check the signature and try again. - Compruebe la firma e inténtelo de nuevo. - - - The signature did not match the message digest. - La firma no coincide con el resumen del mensaje. - - - Message verification failed. - La verificación del mensaje ha fallado. - - - Message verified. - Mensaje verificado. - - - - SplashScreen - - Bitcoin Core - Bitcoin Core - - - The Bitcoin Core developers - Los desarrolladores de Bitcoin Core - - - [testnet] - [testnet] - - - - TrafficGraphWidget - - KB/s - KB/s - - - - TransactionDesc - - Open until %1 - Abierto hasta %1 - - - conflicted - en conflicto - - - %1/offline - %1/fuera de línea - - - %1/unconfirmed - %1/no confirmado - - - %1 confirmations - %1 confirmaciones - - - Status - Estado - - - , broadcast through %n node(s) - , transmitir a través de %n nodo, transmitir a través de %n nodos - - - Date - Fecha - - - Source - Fuente - - - Generated - Generado - - - From - De - - - To - Para - - - own address - dirección propia - - - watch-only - de observación - - - label - etiqueta - - - Credit - Crédito - - - matures in %n more block(s) - disponible en %n bloque másdisponible en %n bloques más - - - not accepted - no aceptada - - - Debit - Débito - - - Total debit - Débito total - - - Total credit - Crédito total - - - Transaction fee - Comisión de transacción - - - Net amount - Cantidad neta - - - Message - Mensaje - - - Comment - Comentario - - - Transaction ID - Identificador de transacción - - - Merchant - Vendedor - - - 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. - Los bitcoins generados deben madurar %1 bloques antes de que puedan gastarse. Cuando generó este bloque, se transmitió a la red para que se añadiera a la cadena de bloques. Si no consigue entrar en la cadena, su estado cambiará a "no aceptado" y ya no se podrá gastar. Esto puede ocurrir ocasionalmente si otro nodo genera un bloque a pocos segundos del suyo. - - - Debug information - Información de depuración - - - Transaction - Transacción - - - Inputs - entradas - - - Amount - Cantidad - - - true - verdadero - - - false - falso - - - , has not been successfully broadcast yet - , todavía no se ha sido difundido satisfactoriamente - - - Open for %n more block(s) - Abrir para %n bloque másAbrir para %n bloques más - - - unknown - desconocido - - - - TransactionDescDialog - - Transaction details - Detalles de transacción - - - This pane shows a detailed description of the transaction - Esta ventana muestra información detallada sobre la transacción - - - - TransactionTableModel - - Date - Fecha - - - Type - Tipo - - - Immature (%1 confirmations, will be available after %2) - No vencidos (%1 confirmaciones. Estarán disponibles al cabo de %2) - - - Open for %n more block(s) - Abrir para %n bloque másAbrir para %n bloques más - - - Open until %1 - Abierto hasta %1 - - - Confirmed (%1 confirmations) - Confirmado (%1 confirmaciones) - - - This block was not received by any other nodes and will probably not be accepted! - Este bloque no ha sido recibido por otros nodos y probablemente no sea aceptado! - - - Generated but not accepted - Generado pero no aceptado - - - Offline - Sin conexión - - - Label - Etiqueta - - - Unconfirmed - Sin confirmar - - - Confirming (%1 of %2 recommended confirmations) - Confirmando (%1 de %2 confirmaciones recomendadas) - - - Conflicted - En conflicto - - - Received with - Recibido con - - - Received from - Recibidos de - - - Sent to - Enviado a - - - Payment to yourself - Pago propio - - - Mined - Minado - - - watch-only - de observación - - - (n/a) - (nd) - - - Transaction status. Hover over this field to show number of confirmations. - Estado de transacción. Pasa el ratón sobre este campo para ver el número de confirmaciones. - - - Date and time that the transaction was received. - Fecha y hora en que se recibió la transacción. - - - Type of transaction. - Tipo de transacción. - - - Whether or not a watch-only address is involved in this transaction. - Sea o no una dirección sólo está involucrada en esta transacción. - - - User-defined intent/purpose of the transaction. - intento/propósito de la transacción definido por el usuario. - - - Amount removed from or added to balance. - Cantidad retirada o añadida al saldo. - - - - TransactionView - - All - Todo + Alt+A + Alt+A - Today - Hoy + Paste address from clipboard + Pegar dirección desde portapapeles - This week - Esta semana + Alt+P + Alt+P - This month - Este mes + Remove this entry + Eliminar esta transacción - Last month - Mes pasado + 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. + La cuota será deducida de la cantidad que sea mandada. El destinatario recibirá menos bitcoins de los que entres en el - This year - Este año + S&ubtract fee from amount + Restar comisiones a la cantidad - Range... - Rango... + Message: + Mensaje: - Received with - Recibido con + This is an unauthenticated payment request. + Esta es una petición de pago no autentificada. - Sent to - Enviado a + This is an authenticated payment request. + Esta es una petición de pago autentificada. - To yourself - A usted mismo + Enter a label for this address to add it to the list of used addresses + Introduce una etiqueta para esta dirección para añadirla a la lista de direcciones utilizadas - Mined - Minado + 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. + Un mensaje que se adjuntó a la bitcoin: URL que será almacenada con la transacción para su referencia. Nota: Este mensaje no se envía a través de la red Bitcoin. - Other - Otra + Pay To: + Paga a: - Enter address or label to search - Introduzca una dirección o etiqueta que buscar + Memo: + Memo: + + + ShutdownWindow - Min amount - Cantidad mínima + %1 is shutting down... + %1 se esta cerrando... - Copy address - Copiar dirección + Do not shut down the computer until this window disappears. + No apague el equipo hasta que desaparezca esta ventana. + + + SignVerifyMessageDialog - Copy label - Copiar etiqueta + Signatures - Sign / Verify a Message + Firmas - Firmar / verificar un mensaje - Copy amount - Copiar cuantía + &Sign Message + &Firmar mensaje - Copy transaction ID - Copiar identificador de transacción + 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. + Puede firmar los mensajes con sus direcciones para demostrar que las posee. Tenga cuidado de no firmar cualquier cosa de manera vaga o aleatoria, pues los ataques de phishing pueden tratar de engañarle firmando su identidad a través de ellos. Sólo firme declaraciones totalmente detalladas con las que usted esté de acuerdo. - Copy raw transaction - Copiar traducción en crudo + The Bitcoin address to sign the message with + Dirección Bitcoin con la que firmar el mensaje - Edit label - Editar etiqueta + Choose previously used address + Escoger dirección previamente usada - Show transaction details - Mostrar detalles de la transacción + Alt+A + Alt+A - Export Transaction History - Exportar historial de transacciones + Paste address from clipboard + Pegar dirección desde portapapeles - Watch-only - De observación + Alt+P + Alt+P - Exporting Failed - Error exportando + Enter the message you want to sign here + Introduzca el mensaje que desea firmar aquí - There was an error trying to save the transaction history to %1. - Ha habido un error al intentar guardar la transacción con %1. + Signature + Firma - Exporting Successful - Exportación finalizada + Copy the current signature to the system clipboard + Copiar la firma actual al portapapeles del sistema - The transaction history was successfully saved to %1. - La transacción ha sido guardada en %1. + Sign the message to prove you own this Bitcoin address + Firmar el mensaje para demostrar que se posee esta dirección Bitcoin - Comma separated file (*.csv) - Archivos de columnas separadas por coma (*.csv) + Sign &Message + Firmar &mensaje - Confirmed - Confirmado + Reset all sign message fields + Vaciar todos los campos de la firma de mensaje - Date - Fecha + Clear &All + Vaciar &todo - Type - Tipo + &Verify Message + &Verificar mensaje - Label - Etiqueta + 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! + Introduzca la dirección para la firma, el mensaje (asegurándose de copiar tal cual los saltos de línea, espacios, tabulaciones, etc.) y la firma a continuación para verificar el mensaje. Tenga cuidado de no asumir más información de lo que dice el propio mensaje firmado para evitar fraudes basados en ataques de tipo man-in-the-middle. - Address - Dirección + The Bitcoin address the message was signed with + La dirección Bitcoin con la que se firmó el mensaje - ID - ID + Verify the message to ensure it was signed with the specified Bitcoin address + Verificar el mensaje para comprobar que fue firmado con la dirección Bitcoin indicada - Range: - Rango: + Verify &Message + Verificar &mensaje - to - para + Reset all verify message fields + Vaciar todos los campos de la verificación de mensaje - UnitDisplayStatusBarControl + SplashScreen - Unit to show amounts in. Click to select another unit. - Unidad en la que se muestran las cantidades. Haga clic para seleccionar otra unidad. + [testnet] + [testnet] - WalletFrame + TrafficGraphWidget - No wallet has been loaded. - No se ha cargado ningún monedero + KB/s + KB/s - WalletModel + TransactionDescDialog - Send Coins - Enviar bitcoins + This pane shows a detailed description of the transaction + Esta ventana muestra información detallada sobre la transacción - WalletView - - &Export - &Exportar - - - Export the data in the current tab to a file - Exportar a un archivo los datos de esta pestaña - - - Backup Wallet - Copia de seguridad del monedero - - - Wallet Data (*.dat) - Datos de monedero (*.dat) - - - Backup Failed - Ha fallado el respaldo - - - There was an error trying to save the wallet data to %1. - Ha habido un error al intentar guardar los datos del monedero en %1. - - - The wallet data was successfully saved to %1. - Los datos del monedero se han guardado con éxito en %1. - + UnitDisplayStatusBarControl - Backup Successful - Se ha completado la copia de seguridad del monedero + Unit to show amounts in. Click to select another unit. + Unidad en la que se muestran las cantidades. Haga clic para seleccionar otra unidad. @@ -2925,14 +1756,6 @@ If <category> is not supplied or if <category> = 1, output all debugging information. Si <category> no es proporcionado o si <category> =1, muestra toda la información de depuración. - - Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s) - Máximas comisiones totales (en %s) para utilizar en una sola transacción de la cartera; establecer esto demasiado bajo puede abortar grandes transacciones (predeterminado: %s) - - - Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. - Por favor, mira si la fecha y la hora en tu computador son correctas! Si tu hara es errónea Bitcoin Core no funcionará correctamente. - Prune configured below the minimum of %d MiB. Please use a higher number. La Poda se ha configurado por debajo del minimo de %d MiB. Por favor utiliza un valor mas alto. @@ -2974,6 +1797,14 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Aceptar conexiones desde el exterior (predeterminado: 1 si no -proxy o -connect) + + Bitcoin Core + Bitcoin Core + + + The %s developers + Los %s desarrolladores + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. -fallbackfee tiene un ajuste muy alto! Esta es la comisión de transacción que pagarás cuando las estimaciones de comisiones no estén disponibles. @@ -2990,6 +1821,10 @@ Bind to given address and always listen on it. Use [host]:port notation for IPv6 Vincular a la dirección dada y escuchar siempre en ella. Utilice la notación [host]:port para IPv6 + + Cannot obtain a lock on data directory %s. %s is probably already running. + No se puede bloquear el directorio %s. %s ya se está ejecutando. + Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup Borrar todas las transacciones del monedero y sólo recuperar aquellas partes de la cadena de bloques por medio de -rescan on startup. @@ -2998,6 +1833,14 @@ Distributed under the MIT software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>. Distribuido bajo la licencia de software MIT, vea la copia del archivo adjunto o <http://www.opensource.org/licenses/mit-license.php>. + + Error loading %s: You can't enable HD on a already existing non-HD wallet + Error cargando %s: No puede habilitar HD en un monedero existente que no es HD + + + Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Error leyendo %s!. Todas las claves se han leido correctamente, pero los datos de transacciones o la libreta de direcciones pueden faltar o ser incorrectos. + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) Ejecutar comando cuando una transacción del monedero cambia (%s en cmd se remplazará por TxID) @@ -3006,6 +1849,22 @@ Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) Fuerza la retransmisión de transacciones desde nodos en la lista blanca incluso si violan la política de retransmisiones local (predeterminado: %d) + + Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds) + Ajuste máximo permitido del tiempo offset medio de pares. La perspectiva local de tiempo se verá influenciada por los pares anteriores y posteriores a esta cantidad. (Por defecto: %u segundos) + + + Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s) + Máximas comisiones totales (en %s) para utilizar en una sola transacción de la cartera; establecer esto demasiado bajo puede abortar grandes transacciones (predeterminado: %s) + + + Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly. + Por favor, compruebe si la fecha y hora en su computadora son correctas! Si su reloj esta mal, %s no trabajara correctamente. + + + Please contribute if you find %s useful. Visit %s for further information about the software. + Contribuya si encuentra %s de utilidad. Visite %s para mas información acerca del programa. + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) Establecer el número de hilos (threads) de verificación de scripts (entre %u y %d, 0 = automático, <0 = dejar libres ese número de núcleos; predeterminado: %d) @@ -3018,14 +1877,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Esta es una versión de pre-prueba - utilícela bajo su propio riesgo. No la utilice para usos comerciales o de minería. - - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - No se ha podido acceder a %s en esta máquina. Probablemente ya se está ejecutando Bitcoin Core. - - - Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. - El argumento no soportado -whitelistalwaysrelay ha sido ignorado, utiliza -whitelistrelay y/o -whitelistforcerelay. - Use UPnP to map the listening port (default: 1 when listening and no -proxy) Utiliza UPnP para asignar el puerto de escucha (predeterminado: 1 cuando esta escuchando sin -proxy) @@ -3042,22 +1893,22 @@ Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Atención: ¡Parece que la red no está totalmente de acuerdo! Algunos mineros están presentando inconvenientes. - - Warning: Unknown block versions being mined! It's possible unknown rules are in effect - Advertencia: Se están minando versiones de bloques desconocidas! Es posible que normas desconocidas estén activas - Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Atención: ¡Parece que no estamos completamente de acuerdo con nuestros pares! Podría necesitar una actualización, u otros nodos podrían necesitarla. - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Aviso: ¡Recuperados datos de wallet.dat corrupto! El wallet.dat original se ha guardado como wallet.{timestamp}.bak en %s; si hubiera errores en su saldo o transacciones, deberá restaurar una copia de seguridad. - Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. Poner en lista blanca a los equipos que se conecten desde la máscara de subred o dirección IP especificada. Se puede especificar múltiples veces. + + You need to rebuild the database using -reindex-chainstate to change -txindex + Necesita reconstruir la base de datos usando -reindex-chainstate para cambiar -txindex + + + %s corrupt, salvage failed + %s corrupto. Fracasó la recuperacion + -maxmempool must be at least %d MB -maxmempool debe ser por lo menos de %d MB @@ -3070,10 +1921,22 @@ Append comment to the user agent string Adjunta un comentario a la linea de agente de usuario + + Attempt to recover private keys from a corrupt wallet on startup + Intento de recuperar claves privadas de un monedero corrupto en arranque + Block creation options: Opciones de creación de bloques: + + Cannot resolve -%s address: '%s' + No se puede resolver -%s direccion: '%s' + + + Change index out of range + Cambio de indice fuera de rango + Connect only to the specified node(s) Conectar sólo a los nodos (o nodo) especificados @@ -3082,6 +1945,10 @@ Connection options: Opciones de conexión: + + Copyright (C) %i-%i + Copyright (C) %i-%i + Corrupted block database detected Corrupción de base de datos de bloques detectada. @@ -3126,6 +1993,22 @@ Error initializing wallet database environment %s! Error al inicializar el entorno de la base de datos del monedero %s + + Error loading %s + Error cargando %s + + + Error loading %s: Wallet corrupted + Error cargando %s: Monedero dañado + + + Error loading %s: Wallet requires newer version of %s + Error cargando %s: Monedero requiere un versión mas reciente de %s + + + Error loading %s: You can't disable HD on a already existing HD wallet + Error cargando %s: No puede deshabilitar HD en un monedero existente que ya es HD + Error loading block database Error cargando base de datos de bloques @@ -3150,10 +2033,18 @@ Incorrect or no genesis block found. Wrong datadir for network? Incorrecto o bloque de génesis no encontrado. Datadir equivocada para la red? + + Initialization sanity check failed. %s is shutting down. + La inicialización de la verificación de validez falló. Se está apagando %s. + Invalid -onion address: '%s' Dirección -onion inválida: '%s' + + Invalid amount for -%s=<amount>: '%s' + Cantidad no valida para -%s=<amount>: '%s' + Invalid amount for -fallbackfee=<amount>: '%s' Cantidad inválida para -fallbackfee=<amount>: '%s' @@ -3162,6 +2053,10 @@ Keep the transaction memory pool below <n> megabytes (default: %u) Mantener la memoria de transacciones por debajo de <n> megabytes (predeterminado: %u) + + Loading banlist... + Cargando banlist... + Location of the auth cookie (default: data dir) Ubicación de la cookie de autenticación (default: data dir) @@ -3178,6 +2073,10 @@ Only connect to nodes in network <net> (ipv4, ipv6 or onion) Sólo conectar a nodos en redes <net> (ipv4, ipv6 o onion) + + Print this help message and exit + Imprimir este mensaje de ayuda y salir + Print version and exit Imprimir versión y salir @@ -3190,6 +2089,14 @@ Prune mode is incompatible with -txindex. El modo recorte es incompatible con -txindex. + + Rebuild chain state and block index from the blk*.dat files on disk + Reconstruir el estado de la cadena e indice de bloques a partir de los ficheros blk*.dat en disco + + + Rebuild chain state from the currently indexed blocks + Reconstruir el estado de la cadena a partir de los bloques indexados + Set database cache size in megabytes (%d to %d, default: %d) Asignar tamaño de cache en megabytes (entre %d y %d; predeterminado: %d) @@ -3202,6 +2109,14 @@ Specify wallet file (within data directory) Especificar archivo de monedero (dentro del directorio de datos) + + The source code is available from %s. + El código fuente esta disponible desde %s. + + + Unable to bind to %s on this computer. %s is probably already running. + No se ha podido conectar con %s en este equipo. %s es posible que este todavia en ejecución. + Unsupported argument -benchmark ignored, use -debug=bench. El argumento -benchmark no es soportado y ha sido ignorado, utiliza -debug=bench @@ -3235,12 +2150,16 @@ El monedero %s se encuentra fuera del directorio de datos %s - Wallet options: - Opciones de monedero: + Wallet debugging/testing options: + Opciones de depuración/pruebas de monedero: + + + Wallet needed to be rewritten: restart %s to complete + Es necesario reescribir el monedero: reiniciar %s para completar - You need to rebuild the database using -reindex to change -txindex - Usted necesita reconstruir la base de datos utilizando -reindex para cambiar -txindex + Wallet options: + Opciones de monedero: 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 @@ -3254,10 +2173,6 @@ Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces) Ligar a las direcciones especificadas para escuchar por conexiones JSON-RPC. Usar la notación para IPv6 [host]:puerto. Esta opción se puede especificar múltiples veces (por defecto: ligar a todas las interfaces) - - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - No se ha podido bloquear el directorio de datos %s. Probablemente ya se está ejecutando Bitcoin Core. - Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) Crear nuevos archivos con permisos por defecto del sistema, en lugar de umask 077 (sólo efectivo con la funcionalidad de monedero desactivada) @@ -3302,10 +2217,6 @@ Set maximum size of high-priority/low-fee transactions in bytes (default: %d) Establecer tamaño máximo de las transacciones de alta prioridad/baja comisión en bytes (predeterminado: %d) - - Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) - Ajuste el número de hilos para la generación de moneda si está habilitado (-1 = all cores, default: %d) - The transaction amount is too small to send after the fee has been deducted Monto de transacción muy pequeña luego de la deducción por comisión @@ -3314,6 +2225,10 @@ This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard. Este producto incluye software desarrollado por el OpenSSL Project para su uso en OpenSSL Toolkit <https://www.openssl.org/>, software de cifrado escrito por Eric Young y software UPnP escrito por Thomas Bernard. + + Use hierarchical deterministic key generation (HD) after BIP32. Only has effect during wallet creation/first start + Usar tras BIP32 la generación de llave determinística jerárquica (HD) . Solo tiene efecto durante el primer inicio/generación del monedero + 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 A los equipos en lista blanca no se les pueden prohibir los ataques DoS y sus transacciones siempre son retransmitidas, incluso si ya están en el mempool, es útil por ejemplo para un gateway. @@ -3330,34 +2245,14 @@ Accept public REST requests (default: %u) Aceptar solicitudes públicas en FERIADOS (por defecto: %u) - - Activating best chain... - Activando la mejor cadena... - - - Attempt to recover private keys from a corrupt wallet.dat on startup - Intento de recuperar claves privadas de un wallet.dat corrupto - Automatically create Tor hidden service (default: %d) Automáticamente crea el servicio Tor oculto (por defecto: %d) - - Cannot resolve -whitebind address: '%s' - No se puede resolver -whitebind address: '%s' - Connect through SOCKS5 proxy Conectar usando SOCKS5 proxy - - Copyright (C) 2009-%i The Bitcoin Core Developers - Copyright (C) 2009-%i The Bitcoin Core Developers - - - Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - Error al cargar wallet.dat: El monedero requiere una versión más reciente de Bitcoin Core - Error reading from database, shutting down. Error al leer la base de datos, cerrando. @@ -3370,22 +2265,6 @@ Information Información - - Initialization sanity check failed. Bitcoin Core is shutting down. - La inicialización de la verificación de validez falló. Se está apagando Bitcoin Core. - - - Invalid amount for -maxtxfee=<amount>: '%s' - Monto inválido para -maxtxfee=<amount>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Cantidad inválida para -minrelaytxfee=<amount>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - Cantidad inválida para -mintxfee=<amount>: '%s' - Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) Cantidad inválida para -paytxfee=<amount>: '%s' (debe ser por lo menos %s) @@ -3410,14 +2289,6 @@ RPC server options: Opciones de servidor RPC: - - Rebuild block chain index from current blk000??.dat files on startup - Reconstruir el índice de la cadena de bloques en el arranque desde los actuales ficheros blk000??.dat - - - Receive and display P2P network alerts (default: %u) - Recibir y mostrar alertas de red P2P (default: %u) - Reducing -maxconnections from %d to %d, because of system limitations. Reduciendo -maxconnections de %d a %d, debido a limitaciones del sistema. @@ -3491,10 +2362,6 @@ Nombre de usuario para las conexiones JSON-RPC - - Wallet needed to be rewritten: restart Bitcoin Core to complete - Monedero es necesario volver a escribir: reiniciar Bitcoin Core para completar - Warning Aviso @@ -3515,10 +2382,6 @@ ZeroMQ notification options: Opciones de notificación ZeroQM: - - wallet.dat corrupt, salvage failed - wallet.dat corrupto. Ha fallado la recuperación. - Password for JSON-RPC connections Contraseña para las conexiones JSON-RPC @@ -3528,11 +2391,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) Ejecutar un comando cuando cambia el mejor bloque (%s en cmd se sustituye por el hash de bloque) - - This help message - Este mensaje de ayuda - - Allow DNS lookups for -addnode, -seednode and -connect Permitir búsquedas DNS para -addnode, -seednode y -connect @@ -3541,10 +2399,6 @@ Loading addresses... Cargando direcciones... - - Error loading wallet.dat: Wallet corrupted - Error al cargar wallet.dat: el monedero está dañado - (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) @@ -3561,10 +2415,6 @@ Do not keep transactions in the mempool longer than <n> hours (default: %u) No mantener transacciones en la memoria mas de <n> horas (predeterminado: %u) - - Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. - Error al leer wallet.dat! Todas las llaves se leyeron correctamente, pero los datos de transacciones o la libreta de direcciones pueden faltar o ser incorrectos. - Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) Las comisiones (en %s/kB) menores que esto son consideradas de cero comision para la creacion de transacciones (predeterminado: %s) @@ -3589,6 +2439,10 @@ Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported. Error: Unsupported argumento -socks encontrados. SOCKS versión ajuste ya no es posible, sólo SOCKS5 proxies son compatibles. + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + El argumento no soportado -whitelistalwaysrelay ha sido ignorado, utiliza -whitelistrelay y/o -whitelistforcerelay. + Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s) Usar distintos proxys SOCKS5 para comunicarse vía Tor de forma anónima (Por defecto: %s) @@ -3598,20 +2452,20 @@ Nombre de usuario y hash de la contraseña para las conexiones JSON-RPC. El campo <userpw> tiene el formato: <USERNAME>:<SALT>$<HASH>. Se incluye un script python convencional en share/rpcuser. Esta opción puede ser especificada multiples veces - (default: %s) - (predeterminado: %s) + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + Advertencia: Se están minando versiones de bloques desconocidas! Es posible que normas desconocidas estén activas - Always query for peer addresses via DNS lookup (default: %u) - Siempre consultar direcciones de otros equipos por medio de DNS lookup (por defecto: %u) + Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup. + Aviso: fichero de monedero corrupto, datos recuperados! Original %s guardado como %s en %s; si su balance de transacciones es incorrecto, debe restaurar desde una copia de seguridad. - Error loading wallet.dat - Error al cargar wallet.dat + (default: %s) + (predeterminado: %s) - Generate coins (default: %u) - Generar monedas (por defecto: %u) + Always query for peer addresses via DNS lookup (default: %u) + Siempre consultar direcciones de otros equipos por medio de DNS lookup (por defecto: %u) How many blocks to check at startup (default: %u, 0 = all) @@ -3697,18 +2551,6 @@ Unknown network specified in -onlynet: '%s' La red especificada en -onlynet '%s' es desconocida - - Cannot resolve -bind address: '%s' - No se puede resolver la dirección de -bind: '%s' - - - Cannot resolve -externalip address: '%s' - No se puede resolver la dirección de -externalip: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - Cantidad inválida para -paytxfee=<amount>: '%s' - Insufficient funds Fondos insuficientes diff --git a/src/qt/locale/bitcoin_es_419.ts b/src/qt/locale/bitcoin_es_419.ts deleted file mode 100644 index b76915662c114..0000000000000 --- a/src/qt/locale/bitcoin_es_419.ts +++ /dev/null @@ -1,173 +0,0 @@ - - - AddressBookPage - - Right-click to edit address or label - Haga clic para editar la dirección o etiqueta - - - Create a new address - Crear una nueva dirección - - - &New - &New - - - Copy the currently selected address to the system clipboard - Copia la dirección seleccionada al portapapeles del sistema - - - Choose the address to send coins to - Seleccione la Direccion a la que enviara dinero - - - Choose the address to receive coins with - Seleccione la direccion de la que recibira dinero - - - Export Address List - Exportar Lista de Direcciones - - - - AddressTableModel - - Address - Direccion - - - - AskPassphraseDialog - - Decrypt wallet - Desencriptar Monedero - - - Confirm wallet encryption - Confirmar Encriptacion de Monedero - - - Warning: The Caps Lock key is on! - Advertencia: La Tecla Caps Lock esta habilitada! - - - Wallet encrypted - Monedero ha sido encriptado - - - Wallet encryption failed - La encriptacion del monedero ha fallado - - - - BanTableModel - - - BitcoinGUI - - - ClientModel - - - CoinControlDialog - - - EditAddressDialog - - - FreespaceChecker - - - HelpMessageDialog - - - Intro - - - OpenURIDialog - - - OptionsDialog - - - OverviewPage - - - PaymentServer - - - PeerTableModel - - - QObject - - - QRImageWidget - - - RPCConsole - - - ReceiveCoinsDialog - - - ReceiveRequestDialog - - Address - Direccion - - - - RecentRequestsTableModel - - - SendCoinsDialog - - - SendCoinsEntry - - - ShutdownWindow - - - SignVerifyMessageDialog - - - SplashScreen - - - TrafficGraphWidget - - - TransactionDesc - - - TransactionDescDialog - - - TransactionTableModel - - - TransactionView - - Address - Direccion - - - - UnitDisplayStatusBarControl - - - WalletFrame - - - WalletModel - - - WalletView - - - bitcoin-core - - \ No newline at end of file diff --git a/src/qt/locale/bitcoin_es_AR.ts b/src/qt/locale/bitcoin_es_AR.ts index fb9ac895be830..40ebaf88560ad 100644 --- a/src/qt/locale/bitcoin_es_AR.ts +++ b/src/qt/locale/bitcoin_es_AR.ts @@ -25,10 +25,6 @@ C&lose C&lose - - &Copy Address - &Copiar Dirección - Delete the currently selected address from the list Borrar de la lista la dirección seleccionada @@ -45,73 +41,6 @@ &Delete &Borrar - - Choose the address to send coins to - Elegir la dirección a donde enviar las monedas (coins) - - - Choose the address to receive coins with - Elegí la dirección donde recibir las monedas - - - C&hoose - E&legir - - - Sending addresses - Direcciones de envío - - - Receiving addresses - Direcciones de recepción - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Estas son tus direcciones Bitcoin para enviar pagos. Siempre chequeá el monto y la dirección de recepción antes de mandar monedas. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Estas son tus direcciones para recibir pagos. Te recomendamos que uses una dirección de recibir para cada transacción. - - - Copy &Label - Copiar &Etiqueta - - - &Edit - &Editar - - - Export Address List - Exportar lista de direcciones - - - Comma separated file (*.csv) - Archivo separado por coma (*.csv) - - - Exporting Failed - Falló la exportación - - - There was an error trying to save the address list to %1. Please try again. - Hubo un error al tratar de guardar la lista de direcciones a %1. Por favor tratá de nuevo. - - - - AddressTableModel - - Label - Etiqueta - - - Address - Dirección - - - (no label) - (sin etiqueta) - AskPassphraseDialog @@ -131,106 +60,15 @@ Repeat new passphrase Repetí la nueva Frase de Contraseña - - Encrypt wallet - Encriptar la billetera - - - This operation needs your wallet passphrase to unlock the wallet. - Esta operación necesita tu frase de contraseña para desbloquear tu billetera. - - - Unlock wallet - Desbloquear la billetera - - - This operation needs your wallet passphrase to decrypt the wallet. - Esta operación necesita tu Frase de Contraseña de billetera para desencriptar la billetera. - - - Decrypt wallet - Desencriptar la billetera - - - Change passphrase - Cambiar la Frase de Contraseña - - - Confirm wallet encryption - Confirmá la encriptación de la billetera - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Atención: Si encriptás tu billetera y perdés tu frase de contraseña, vas a <b>PERDER TODOS TUS BITCOINS</b>! - - - Are you sure you wish to encrypt your wallet? - ¿Estás seguro que querés encriptar tu billetera? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Bitcoin Core ahora se va a cerrar para terminar el proceso de encriptación. Acordate que encriptar tu billetera no te protege completamente de que algún malware que pueda infectar tu computadora te robe tus bitcoins. - - - 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. - IMPORTANTE: Todos los backups que hayas hecho de tu billetera tendrían que ser reemplazados por el archivo encriptado de billetera que generaste. Por razones de seguridad, los backups anteriores del archivo de billetera no encriptado se inutilizan en el momento en que empezás a usar la nueva billetera encriptada - - - Warning: The Caps Lock key is on! - Atención: Tenés puestas las mayúsculas! - - - Wallet encrypted - Billetera encriptada - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Ingresá una nueva frase de contraseña para la billetera.<br/>Por favor, fijate de usar una frase de contraseña de <b>diez o más caracteres aleatorios</b>, o de <b>ocho o más palabras</b>. - - - Enter the old passphrase and new passphrase to the wallet. - Ingresá la frase de contraseña vieja y la nueva para la billetera. - - - Wallet encryption failed - Falló la encriptación de la billetera - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Falló la encriptación de la billetera por un error interno. Tu billetera no está encriptada. - - - The supplied passphrases do not match. - Las frases de contraseña no son iguales. - - - Wallet unlock failed - Falló el desbloqueo de la billetera - - - The passphrase entered for the wallet decryption was incorrect. - La frase de contraseña que ingresaste para desencriptar la billetera es incorrecta. - - - Wallet decryption failed - Falló la desencriptación de la billetera - - + BanTableModel BitcoinGUI - - ClientModel - CoinControlDialog - - (no label) - (sin etiqueta) - EditAddressDialog @@ -253,18 +91,12 @@ OverviewPage - - PaymentServer - PeerTableModel QObject - - QRImageWidget - RPCConsole @@ -273,32 +105,9 @@ ReceiveRequestDialog - - Address - Dirección - - - Label - Etiqueta - - - - RecentRequestsTableModel - - Label - Etiqueta - - - (no label) - (sin etiqueta) - SendCoinsDialog - - (no label) - (sin etiqueta) - SendCoinsEntry @@ -315,58 +124,12 @@ TrafficGraphWidget - - TransactionDesc - TransactionDescDialog - - TransactionTableModel - - Label - Etiqueta - - - - TransactionView - - Exporting Failed - Falló la exportación - - - Comma separated file (*.csv) - Archivo separado por coma (*.csv) - - - Label - Etiqueta - - - Address - Dirección - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - - WalletView - - &Export - &Exportar - - - Export the data in the current tab to a file - Exportar los datos de la pestaña actual a un archivo - - bitcoin-core diff --git a/src/qt/locale/bitcoin_es_CL.ts b/src/qt/locale/bitcoin_es_CL.ts index 742dee29d0374..ff0fce61192f7 100644 --- a/src/qt/locale/bitcoin_es_CL.ts +++ b/src/qt/locale/bitcoin_es_CL.ts @@ -25,10 +25,6 @@ C&lose C y perder - - &Copy Address - &Copia dirección - Delete the currently selected address from the list Eliminar la dirección seleccionada de la lista @@ -45,57 +41,6 @@ &Delete &Borrar - - Choose the address to send coins to - Selecciona la direccion para enviar coins - - - Choose the address to receive coins with - Selecciona la dirección para recibir coins - - - Sending addresses - Dirección de envio - - - Receiving addresses - Dirección para recibir - - - Copy &Label - Copia &etiqueta - - - &Edit - &Editar - - - Export Address List - Exportar lista de direcciones - - - Comma separated file (*.csv) - Archivos separados por coma (*.csv) - - - Exporting Failed - Exportado fallo - - - - AddressTableModel - - Label - Etiqueta - - - Address - Dirección - - - (no label) - (sin etiqueta) - AskPassphraseDialog @@ -111,82 +56,6 @@ Repeat new passphrase Repite nueva contraseña - - Encrypt wallet - Codificar billetera - - - This operation needs your wallet passphrase to unlock the wallet. - Esta operación necesita la contraseña para desbloquear la billetera. - - - Unlock wallet - Desbloquea billetera - - - This operation needs your wallet passphrase to decrypt the wallet. - Esta operación necesita la contraseña para decodificar la billetara. - - - Decrypt wallet - Decodificar cartera - - - Change passphrase - Cambia contraseña - - - Confirm wallet encryption - Confirma la codificación de cartera - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Atención: ¡Si codificas tu billetera y pierdes la contraseña perderás <b>TODOS TUS BITCOINS</b>! - - - Are you sure you wish to encrypt your wallet? - ¿Seguro que quieres seguir codificando la billetera? - - - 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. - IMPORTANTE: Cualquier versión anterior que hayas realizado de tu archivo de billetera será reemplazada por el nuevo archivo de billetera encriptado. Por razones de seguridad, los respaldos anteriores de los archivos de billetera se volverán inútiles en tanto comiences a usar la nueva billetera encriptada. - - - Warning: The Caps Lock key is on! - Precaucion: Mayúsculas Activadas - - - Wallet encrypted - Billetera codificada - - - Wallet encryption failed - Falló la codificación de la billetera - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - La codificación de la billetera falló debido a un error interno. Tu billetera no ha sido codificada. - - - The supplied passphrases do not match. - Las contraseñas no coinciden. - - - Wallet unlock failed - Ha fallado el desbloqueo de la billetera - - - The passphrase entered for the wallet decryption was incorrect. - La contraseña introducida para decodificar la billetera es incorrecta. - - - Wallet decryption failed - Ha fallado la decodificación de la billetera - - - Wallet passphrase was successfully changed. - La contraseña de billetera ha sido cambiada con éxito. - BanTableModel @@ -225,6 +94,10 @@ Quit application Salir del programa + + &About %1 + S&obre %1 + About &Qt Acerca de @@ -261,10 +134,6 @@ Open &URI... Abrir y url... - - Bitcoin Core client - cliente bitcoin core - Reindexing blocks on disk... Cargando el index de bloques... @@ -309,10 +178,6 @@ &Receive y recibir - - Show information about Bitcoin Core - Mostrar informacion sobre Bitcoin Core - &Show / Hide &Mostrar/Ocultar @@ -337,22 +202,10 @@ Tabs toolbar Barra de pestañas - - Bitcoin Core - bitcoin core - Request payments (generates QR codes and bitcoin: URIs) Pide pagos (genera codigos QR and bitcoin: URls) - - &About Bitcoin Core - &Sobre Bitcoin Core - - - Modify configuration options for Bitcoin Core - Modifica las opciones para BitCoin Core - %1 and %2 %1 y %2 @@ -394,13 +247,6 @@ La billetera esta <b>codificada</b> y actualmente <b>bloqueda</b> - - ClientModel - - Network Alert - Alerta de Red - - CoinControlDialog @@ -436,51 +282,7 @@ Priority prioridad - - Copy address - Copia dirección - - - Copy label - Copia etiqueta - - - Copy amount - Copiar Cantidad - - - Copy quantity - copiar cantidad - - - Copy fee - copiar comision - - - Copy bytes - copiar bytes - - - medium - medio - - - low - bajo - - - yes - si - - - no - no - - - (no label) - (sin etiqueta) - - + EditAddressDialog @@ -495,38 +297,6 @@ &Address &Dirección - - New receiving address - Nueva dirección para recibir - - - New sending address - Nueva dirección para enviar - - - Edit receiving address - Editar dirección de recepción - - - Edit sending address - Editar dirección de envio - - - The entered address "%1" is already in the address book. - La dirección introducida "%1" ya esta guardada en la libreta de direcciones. - - - The entered address "%1" is not a valid Bitcoin address. - La dirección introducida "%1" no es una dirección Bitcoin valida. - - - Could not unlock wallet. - No se pudo desbloquear la billetera. - - - New key generation failed. - La generación de nueva clave falló. - FreespaceChecker @@ -537,10 +307,6 @@ HelpMessageDialog - - Bitcoin Core - bitcoin core - version versión @@ -560,10 +326,6 @@ Welcome bienvenido - - Bitcoin Core - bitcoin core - Error Error @@ -679,13 +441,6 @@ Total: - - PaymentServer - - Payment acknowledged - Pago completado - - PeerTableModel @@ -700,17 +455,6 @@ N/A - - QRImageWidget - - &Save Image... - Guardar imagen... - - - &Copy Image - Copiar Imagen - - RPCConsole @@ -793,15 +537,7 @@ &Message: &mensaje - - Copy label - Copia etiqueta - - - Copy amount - Copiar Cantidad - - + ReceiveRequestDialog @@ -816,46 +552,7 @@ &Save Image... Guardar imagen... - - Address - Dirección - - - Amount - Cantidad - - - Label - Etiqueta - - - Message - Mensaje - - - - RecentRequestsTableModel - - Date - Fecha - - - Label - Etiqueta - - - Message - Mensaje - - - Amount - Cantidad - - - (no label) - (sin etiqueta) - - + SendCoinsDialog @@ -915,43 +612,7 @@ S&end &Envía - - Confirm send coins - Confirmar el envio de monedas - - - Copy quantity - copiar cantidad - - - Copy amount - Copiar Cantidad - - - Copy fee - copiar comision - - - Copy bytes - copiar bytes - - - The amount to pay must be larger than 0. - La cantidad por pagar tiene que ser mayor 0. - - - The amount exceeds your balance. - La cantidad sobrepasa tu saldo. - - - The total exceeds your balance when the %1 transaction fee is included. - El total sobrepasa tu saldo cuando se incluyen %1 como tasa de envio. - - - (no label) - (sin etiqueta) - - + SendCoinsEntry @@ -962,10 +623,6 @@ Pay &To: &Pagar a: - - Enter a label for this address to add it to your address book - Introduce una etiqueta a esta dirección para añadirla a tu guia - &Label: &Etiqueta: @@ -1040,41 +697,9 @@ Verify &Message &Firmar Mensaje - - Click "Sign Message" to generate signature - Click en "Firmar Mensage" para conseguir firma - - - The entered address is invalid. - La dirección introducida no es una valida. - - - Please check the address and try again. - Por favor, revise la dirección Bitcoin e inténtelo denuevo - - - Wallet unlock was cancelled. - Ha fallado el desbloqueo de la billetera - - - Message signing failed. - Firma fallida - - - Message signed. - Mensaje firmado - - - Message verified. - Mensaje comprobado - - + SplashScreen - - Bitcoin Core - bitcoin core - [testnet] [red-de-pruebas] @@ -1087,346 +712,16 @@ KB/s - - TransactionDesc - - Open until %1 - Abierto hasta %1 - - - %1/offline - %1/fuera de linea - - - %1/unconfirmed - %1/no confirmado - - - %1 confirmations - %1 confirmaciónes - - - Status - Estado - - - Date - Fecha - - - Generated - Generado - - - From - De - - - To - A - - - own address - propia dirección - - - label - etiqueta - - - Credit - Credito - - - not accepted - no aceptada - - - Debit - Debito - - - Transaction fee - Comisión transacción - - - Net amount - Cantidad total - - - Message - Mensaje - - - Comment - Comentario - - - Transaction ID - ID de Transacción - - - Transaction - Transacción - - - Amount - Cantidad - - - , has not been successfully broadcast yet - , no ha sido emitido satisfactoriamente todavía - - - unknown - desconocido - - TransactionDescDialog - - Transaction details - Detalles de transacción - This pane shows a detailed description of the transaction Esta ventana muestra información detallada sobre la transacción - - TransactionTableModel - - Date - Fecha - - - Type - Tipo - - - Open until %1 - Abierto hasta %1 - - - Confirmed (%1 confirmations) - Confirmado (%1 confirmaciones) - - - This block was not received by any other nodes and will probably not be accepted! - Este bloque no ha sido recibido por otros nodos y probablemente no sea aceptado ! - - - Generated but not accepted - Generado pero no acceptado - - - Offline - fuera de linea - - - Label - Etiqueta - - - Unconfirmed - no confirmado - - - Received with - Recibido con - - - Received from - Recibido de - - - Sent to - Enviado a - - - Payment to yourself - Pagar a usted mismo - - - Mined - Minado - - - (n/a) - (n/a) - - - Transaction status. Hover over this field to show number of confirmations. - Estado de transacción. Pasa el raton sobre este campo para ver el numero de confirmaciónes. - - - Date and time that the transaction was received. - Fecha y hora cuando se recibió la transaccion - - - Type of transaction. - Tipo de transacción. - - - Amount removed from or added to balance. - Cantidad restada o añadida al balance - - - - TransactionView - - All - Todo - - - Today - Hoy - - - This week - Esta semana - - - This month - Esta mes - - - Last month - Mes pasado - - - This year - Este año - - - Range... - Rango... - - - Received with - Recibido con - - - Sent to - Enviado a - - - To yourself - A ti mismo - - - Mined - Minado - - - Other - Otra - - - Enter address or label to search - Introduce una dirección o etiqueta para buscar - - - Min amount - Cantidad minima - - - Copy address - Copia dirección - - - Copy label - Copia etiqueta - - - Copy amount - Copiar Cantidad - - - Edit label - Edita etiqueta - - - Show transaction details - Mostrar detalles de la transacción - - - Exporting Failed - Exportado fallo - - - Comma separated file (*.csv) - Archivos separados por coma (*.csv) - - - Confirmed - Confirmado - - - Date - Fecha - - - Type - Tipo - - - Label - Etiqueta - - - Address - Dirección - - - ID - ID - - - Range: - Rango: - - - to - para - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - Send Coins - Enviar monedas - - - - WalletView - - &Export - y exportar - - - Export the data in the current tab to a file - Exportar los datos de la pestaña actual a un archivo - - - Backup Wallet - Respaldar billetera - - - Wallet Data (*.dat) - Datos de billetera (*.dat) - - - Backup Failed - Ha fallado el respaldo - - bitcoin-core @@ -1449,6 +744,10 @@ Correr como demonio y acepta comandos + + Bitcoin Core + bitcoin core + Connect only to the specified node(s) Conecta solo al nodo especificado @@ -1466,18 +765,6 @@ Information Información - - Invalid amount for -maxtxfee=<amount>: '%s' - Cantidad inválida para -maxtxfee=<amount>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Cantidad inválida para -minrelaytxfee=<amount>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - Cantidad inválida para -mintxfee=<amount>: '%s' - Send trace/debug info to console instead of debug.log file Enviar informacion de seguimiento a la consola en vez del archivo debug.log @@ -1491,18 +778,9 @@ Warning Atención - - wallet.dat corrupt, salvage failed - wallet.dat corrompió, guardado fallido - Password for JSON-RPC connections Contraseña para las conexiones JSON-RPC - - - - This help message - Este mensaje de ayuda @@ -1514,30 +792,10 @@ Loading addresses... Cargando direcciónes... - - Error loading wallet.dat: Wallet corrupted - Error cargando wallet.dat: Billetera corrupta - - - Error loading wallet.dat - Error cargando wallet.dat - Invalid -proxy address: '%s' Dirección -proxy invalida: '%s' - - Cannot resolve -bind address: '%s' - No se pudo resolver la dirección fija: '%s' - - - Cannot resolve -externalip address: '%s' - No se pudo resolver la dirección ip: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - Cantidad inválida para -paytxfee=<amount>: '%s' - Insufficient funds Fondos insuficientes diff --git a/src/qt/locale/bitcoin_es_CO.ts b/src/qt/locale/bitcoin_es_CO.ts index ea0664636d2d6..df189190f602b 100644 --- a/src/qt/locale/bitcoin_es_CO.ts +++ b/src/qt/locale/bitcoin_es_CO.ts @@ -25,10 +25,6 @@ C&lose C&errar - - &Copy Address - &Copiar dirección - Delete the currently selected address from the list Borrar la dirección actualmente seleccionada de la lista @@ -41,74 +37,6 @@ &Delete &Borrar - - Choose the address to send coins to - Escoje la dirección para enviar monedas a - - - Choose the address to receive coins with - Escoje la dirección para recibir monedas con - - - C&hoose - E&scojer - - - Sending addresses - Enviando direcciones - - - Receiving addresses - Recibiendo direcciones - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - -Estas son las direcciones de Bitcoin para enviar pagos . Siempre verifique la cantidad y la dirección de recepción antes de enviar monedas. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Estas son las direcciones de Bitcoin para recibir los pagos . Se recomienda el uso de una nueva dirección de recepción para cada transacción. - - - Copy &Label - Copiar &Etiqueta - - - &Edit - &Editar - - - Export Address List - Exportar lista de direcciones - - - Comma separated file (*.csv) - Coma(,) archivo separado (*.csv) - - - Exporting Failed - Exportación Fallida - - - There was an error trying to save the address list to %1. Please try again. - Hubo un error intentando guardar la lista de direcciones a %1 Inténtelo otravez - - - - AddressTableModel - - Label - Etiqueta - - - Address - Dirección - - - (no label) - (ninguna dirección) - AskPassphraseDialog @@ -128,90 +56,6 @@ Estas son las direcciones de Bitcoin para enviar pagos . Siempre verifique la ca Repeat new passphrase Repetir nueva contraseña - - Encrypt wallet - Billetera Encriptada - - - This operation needs your wallet passphrase to unlock the wallet. - Esta operación necesita tu contraseña de la billetera para desbloquear la billetera - - - Unlock wallet - Billetera Desbloqueada - - - This operation needs your wallet passphrase to decrypt the wallet. - Esta operación necesita tu contraseña de la billetera para desencriptar la billetera. - - - Decrypt wallet - Billetera Desencriptada - - - Change passphrase - Cambiar contraseña - - - Confirm wallet encryption - Confirmar encriptación de la billetera - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Precaución: Si tú has encriptado tu billetera y has perdido tu contraseña, usted <b>PERDERÁ TODOS TUS BITCOINS</b> - - - Are you sure you wish to encrypt your wallet? - Estas seguro de que deseas encriptar tu billetera? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Bitcoin Core se cerrará ahora para finalizar el proceso de encriptación. Recuerda que encriptando tu billetera no protegera por completo tus bitcoins desde robos por malware que infectan tu computadora. - - - 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. - IMPORTANTE : Cualquier copias de seguridad anteriores que han hecho de su archivo cartera debe ser reemplazado por el archivo de la carpeta recién generado , encriptado . Por razones de seguridad , las copias de seguridad anteriores del archivo cartera sin cifrar se vuelven inútiles , tan pronto como empiece a utilizar el nuevo , carpeta cifrada . - - - Warning: The Caps Lock key is on! - Ojo: El bloqueo de MAYUSCULAS esta activado! - - - Wallet encrypted - Billetera encriptada - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Poner la nueva contraseña a la billetera.<br/>Por favor usa una contraseña de <b>diez o más palabras aleatorias</b>, o <b>nueve o más letras</b>. - - - Enter the old passphrase and new passphrase to the wallet. - Poner la antigua contraseña y nueva contraseña a la billetera. - - - Wallet encryption failed - Encriptación de la billetera fallida - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Encriptación de la billetera fallida por un error interno. Tu billetera no ha sido encriptada. - - - Wallet unlock failed - Falló el desbloqueo de la billetera - - - The passphrase entered for the wallet decryption was incorrect. - La contraseña tecleada de la desencriptación de la billetera ha sido incorrecta. - - - Wallet decryption failed - Encriptación de la billetera fallida - - - Wallet passphrase was successfully changed. - La contraseña de la billetera a sido cambiada exitosamente. - BanTableModel @@ -278,14 +122,6 @@ Estas son las direcciones de Bitcoin para enviar pagos . Siempre verifique la ca Open &URI... Abrir &URL... - - Bitcoin Core client - Bitcoin Core cliente - - - Importing blocks from disk... - Importando bloques desde el disco... - Send coins to a Bitcoin address Enviando monedas a una dirección de Bitcoin @@ -322,10 +158,6 @@ Estas son las direcciones de Bitcoin para enviar pagos . Siempre verifique la ca &Receive &Recibir - - Show information about Bitcoin Core - Mostrar información sobre Bitcoin Core - &Show / Hide &Mostrar / Ocultar @@ -346,24 +178,13 @@ Estas son las direcciones de Bitcoin para enviar pagos . Siempre verifique la ca &Help &Ayuda - - Bitcoin Core - Bitcoin Core - Error Error - - ClientModel - CoinControlDialog - - (no label) - (ninguna dirección) - EditAddressDialog @@ -373,17 +194,9 @@ Estas son las direcciones de Bitcoin para enviar pagos . Siempre verifique la ca HelpMessageDialog - - Bitcoin Core - Bitcoin Core - Intro - - Bitcoin Core - Bitcoin Core - Error Error @@ -398,18 +211,12 @@ Estas son las direcciones de Bitcoin para enviar pagos . Siempre verifique la ca OverviewPage - - PaymentServer - PeerTableModel QObject - - QRImageWidget - RPCConsole @@ -418,32 +225,9 @@ Estas son las direcciones de Bitcoin para enviar pagos . Siempre verifique la ca ReceiveRequestDialog - - Address - Dirección - - - Label - Etiqueta - - - - RecentRequestsTableModel - - Label - Etiqueta - - - (no label) - (ninguna dirección) - SendCoinsDialog - - (no label) - (ninguna dirección) - SendCoinsEntry @@ -456,64 +240,22 @@ Estas son las direcciones de Bitcoin para enviar pagos . Siempre verifique la ca SplashScreen - - Bitcoin Core - Bitcoin Core - TrafficGraphWidget - - TransactionDesc - TransactionDescDialog - - TransactionTableModel - - Label - Etiqueta - - - - TransactionView - - Exporting Failed - Exportación Fallida - - - Comma separated file (*.csv) - Coma(,) archivo separado (*.csv) - - - Label - Etiqueta - - - Address - Dirección - - UnitDisplayStatusBarControl - WalletFrame - - - WalletModel - - - WalletView + bitcoin-core - &Export - &Exportar + Bitcoin Core + Bitcoin Core - - - bitcoin-core Insufficient funds Fondos Insuficientes diff --git a/src/qt/locale/bitcoin_es_DO.ts b/src/qt/locale/bitcoin_es_DO.ts index b4841ca9b8682..3f4380840a068 100644 --- a/src/qt/locale/bitcoin_es_DO.ts +++ b/src/qt/locale/bitcoin_es_DO.ts @@ -21,10 +21,6 @@ C&lose &Cerrar - - &Copy Address - &Copiar dirección - Delete the currently selected address from the list Borrar de la lista la dirección seleccionada @@ -41,69 +37,6 @@ &Delete &Eliminar - - Choose the address to send coins to - Escoja la dirección para enviar monedas - - - Choose the address to receive coins with - Escoja la dirección para recibir monedas - - - C&hoose - &Escoger - - - Sending addresses - Enviando dirección - - - Receiving addresses - Recibiendo dirección - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Estas son sus direcciones Bitcoin para enviar pagos. Compruebe siempre la cantidad y la dirección receptora antes de transferir monedas. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Estas son sus direcciones de Bitcoin para recibir pagos. Se recomienda utilizar una nueva dirección de recepción para cada transacción. - - - Copy &Label - Copiar &etiqueta - - - &Edit - &Editar - - - Export Address List - Exportar la lista de direcciones - - - Comma separated file (*.csv) - Archivos de columnas separadas por coma (*.csv) - - - Exporting Failed - Error exportando - - - - AddressTableModel - - Label - Etiqueta - - - Address - Dirección - - - (no label) - (sin etiqueta) - AskPassphraseDialog @@ -123,82 +56,6 @@ Repeat new passphrase Repita la nueva contraseña - - Encrypt wallet - Cifrar la cartera - - - This operation needs your wallet passphrase to unlock the wallet. - Esta operación requiere su contraseña para desbloquear la cartera - - - Unlock wallet - Desbloquear cartera - - - This operation needs your wallet passphrase to decrypt the wallet. - Esta operación requiere su contraseña para descifrar la cartera. - - - Decrypt wallet - Descifrar la certare - - - Change passphrase - Cambiar contraseña - - - Confirm wallet encryption - Confirmar cifrado de la cartera - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Atencion: ¡Si cifra su monedero y pierde la contraseña perderá <b>TODOS SUS BITCOINS</b>!" - - - Are you sure you wish to encrypt your wallet? - ¿Seguro que desea cifrar su monedero? - - - 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. - IMPORTANTE: Cualquier copia de seguridad que haya realizado previamente de su archivo de monedero debe reemplazarse con el nuevo archivo de monedero cifrado. Por razones de seguridad, las copias de seguridad previas del archivo de monedero no cifradas serán inservibles en cuanto comience a usar el nuevo monedero cifrado. - - - Warning: The Caps Lock key is on! - Aviso: ¡La tecla de bloqueo de mayúsculas está activada! - - - Wallet encrypted - Monedero cifrado - - - Wallet encryption failed - Ha fallado el cifrado del monedero - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Ha fallado el cifrado del monedero debido a un error interno. El monedero no ha sido cifrado. - - - The supplied passphrases do not match. - Las contraseñas no coinciden. - - - Wallet unlock failed - Ha fallado el desbloqueo del monedero - - - The passphrase entered for the wallet decryption was incorrect. - La contraseña introducida para descifrar el monedero es incorrecta. - - - Wallet decryption failed - Ha fallado el descifrado del monedero - - - Wallet passphrase was successfully changed. - Se ha cambiado correctamente la contraseña del monedero. - BanTableModel @@ -277,10 +134,6 @@ Open &URI... Abrir URI... - - Importing blocks from disk... - Importando bloques de disco... - Reindexing blocks on disk... Reindexando bloques en disco... @@ -361,18 +214,10 @@ Tabs toolbar Barra de pestañas - - Bitcoin Core - Núcleo de Bitcoin - Request payments (generates QR codes and bitcoin: URIs) Solicitar pagos (genera codigo QR y URL's de Bitcoin) - - &About Bitcoin Core - &Acerca del Núcleo de Bitcoin - Show the list of used sending addresses and labels Mostrar la lista de direcciones de envío y etiquetas @@ -442,13 +287,6 @@ El monedero está <b>cifrado</b> y actualmente <b>bloqueado</b> - - ClientModel - - Network Alert - Alerta de red - - CoinControlDialog @@ -511,130 +349,6 @@ Priority Prioridad - - Copy address - Copiar dirección - - - Copy label - Copiar etiqueta - - - Copy amount - Copiar cantidad - - - Copy transaction ID - Copiar identificador de transacción - - - Lock unspent - Bloquear lo no gastado - - - Unlock unspent - Desbloquear lo no gastado - - - Copy quantity - Copiar cantidad - - - Copy fee - Copiar donación - - - Copy after fee - Copiar después de aplicar donación - - - Copy bytes - Copiar bytes - - - Copy priority - Copiar prioridad - - - Copy change - Copiar Cambio - - - highest - lo más alto - - - higher - más alto - - - high - alto - - - medium-high - medio-alto - - - medium - medio - - - low-medium - bajo-medio - - - low - bajo - - - lower - más bajo - - - lowest - lo más bajo - - - (%1 locked) - (%1 bloqueado) - - - none - ninguno - - - yes - si - - - no - no - - - This means a fee of at least %1 per kB is required. - Esto implica que se requiere una tarifa de al menos %1 por kB - - - Can vary +/- 1 byte per input. - Puede variar +/- 1 byte por entrada. - - - Transactions with higher priority are more likely to get included into a block. - Las transacciones con alta prioridad son más propensas a ser incluidas dentro de un bloque. - - - (no label) - (sin etiqueta) - - - change from %1 (%2) - Enviar desde %1 (%2) - - - (change) - (cambio) - EditAddressDialog @@ -658,38 +372,6 @@ &Address &Dirección - - New receiving address - Nueva dirección de recepción - - - New sending address - Nueva dirección de envío - - - Edit receiving address - Editar dirección de recepción - - - Edit sending address - Editar dirección de envío - - - The entered address "%1" is already in the address book. - La dirección introducida "%1" ya está presente en la libreta de direcciones. - - - The entered address "%1" is not a valid Bitcoin address. - La dirección introducida "%1" no es una dirección Bitcoin válida. - - - Could not unlock wallet. - No se pudo desbloquear el monedero. - - - New key generation failed. - Ha fallado la generación de la nueva clave. - FreespaceChecker @@ -716,18 +398,10 @@ HelpMessageDialog - - Bitcoin Core - Núcleo de Bitcoin - version versión - - About Bitcoin Core - Acerca del Núcleo de Bitcoin - Command-line options Opciones de la línea de órdenes @@ -747,18 +421,6 @@ Welcome Bienvenido - - Welcome to Bitcoin Core. - Bienvenido al Núcleo de Bitcoin - - - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - Al ser la primera vez que se ejecuta el programa, puede elegir dónde almacenará sus datos Bitcoin-Qt. - - - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - Bitcoin-Qt va a descargar y guardar una copia de la cadena de bloques de Bitcoin. Se almacenará al menos %1GB de datos en este directorio, que irá creciendo con el tiempo. El monedero se guardará también en este directorio. - Use the default data directory Utilizar el directorio de datos predeterminado @@ -767,10 +429,6 @@ Use a custom data directory: Utilice un directorio de datos personalizado: - - Bitcoin Core - Núcleo de Bitcoin - Error Error @@ -794,10 +452,6 @@ Select payment request file Seleccione archivo de sulicitud de pago - - Select payment request file to open - Abrir archivo de solicitud de pago - OptionsDialog @@ -961,53 +615,6 @@ Su balance actual total - - PaymentServer - - URI handling - Gestión de URI - - - Invalid payment address %1 - Dirección de pago no válida %1 - - - Requested payment amount of %1 is too small (considered dust). - La cantidad del pago solicitado (%1) es demasiado pequeña (considerada polvo). - - - Payment request error - Error en petición de pago - - - Cannot start bitcoin: click-to-pay handler - No se pudo iniciar bitcoin: manejador de pago-al-clic - - - Unverified payment requests to custom payment scripts are unsupported. - No están soportadas las peticiones inseguras a scripts de pago personalizados - - - Refund from %1 - Devolución de %1 - - - Error communicating with %1: %2 - Error en la comunicación con %1: %2 - - - Bad response from server %1 - Respuesta errónea del servidor %1 - - - Payment acknowledged - Pago aceptado - - - Network request error - Error en petición de red - - PeerTableModel @@ -1030,25 +637,6 @@ N/D - - QRImageWidget - - &Save Image... - Guardar Imagen... - - - &Copy Image - Copiar imagen - - - Save QR Code - Guardar código QR - - - PNG Image (*.png) - Imágenes PNG (*.png) - - RPCConsole @@ -1131,10 +719,6 @@ Out: Fuera: - - Build date - Fecha de compilación - Debug log file Archivo de registro de depuración @@ -1218,14 +802,6 @@ Remove Eliminar - - Copy label - Copiar etiqueta - - - Copy amount - Copiar cantidad - ReceiveRequestDialog @@ -1245,115 +821,52 @@ &Save Image... Guardar Imagen... + + + SendCoinsDialog - Request payment to %1 - Solicitar pago a %1 + Send Coins + Enviar monedas - Payment information - Información de pago + Coin Control Features + Características de control de la moneda - URI - URI + Inputs... + Entradas... - Address - Dirección + automatically selected + Seleccionado automaticamente - Amount - Cantidad + Insufficient funds! + Fondos insuficientes! - Label - Etiqueta + Quantity: + Cantidad: - Message - Mensaje + Bytes: + Bytes: - Resulting URI too long, try to reduce the text for label / message. - URI resultante demasiado larga. Intente reducir el texto de la etiqueta / mensaje. + Amount: + Cuantía: - Error encoding URI into QR Code. - Error al codificar la URI en el código QR. + Priority: + Prioridad: - - - RecentRequestsTableModel - Date - Fecha + Fee: + Tasa: - Label - Etiqueta - - - Message - Mensaje - - - Amount - Cantidad - - - (no label) - (sin etiqueta) - - - (no message) - (Ningun mensaje) - - - - SendCoinsDialog - - Send Coins - Enviar monedas - - - Coin Control Features - Características de control de la moneda - - - Inputs... - Entradas... - - - automatically selected - Seleccionado automaticamente - - - Insufficient funds! - Fondos insuficientes! - - - Quantity: - Cantidad: - - - Bytes: - Bytes: - - - Amount: - Cuantía: - - - Priority: - Prioridad: - - - Fee: - Tasa: - - - After Fee: - Después de tasas: + After Fee: + Después de tasas: Change: @@ -1399,86 +912,6 @@ S&end &Enviar - - Confirm send coins - Confirmar el envío de monedas - - - %1 to %2 - %1 a %2 - - - Copy quantity - Copiar cantidad - - - Copy amount - Copiar cantidad - - - Copy fee - Copiar donación - - - Copy after fee - Copiar después de aplicar donación - - - Copy bytes - Copiar bytes - - - Copy priority - Copiar prioridad - - - Copy change - Copiar Cambio - - - or - o - - - The amount to pay must be larger than 0. - La cantidad por pagar tiene que ser mayor de 0. - - - The amount exceeds your balance. - La cantidad sobrepasa su saldo. - - - The total exceeds your balance when the %1 transaction fee is included. - El total sobrepasa su saldo cuando se incluye la tasa de envío de %1 - - - Transaction creation failed! - ¡Ha fallado la creación de la transacción! - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - La transacción fue rechazada. Esto puede haber ocurrido si alguna de las monedas ya estaba gastada o si ha usado una copia de wallet.dat y las monedas se gastaron en la copia pero no se han marcado como gastadas aqui. - - - Warning: Invalid Bitcoin address - Alerta: Dirección de Bitcoin inválida - - - (no label) - (sin etiqueta) - - - Warning: Unknown change address - Alerta: Dirección de Bitcoin inválida - - - Are you sure you want to send? - ¿Está seguro que desea enviar? - - - added as transaction fee - añadido como comisión de transacción - SendCoinsEntry @@ -1490,10 +923,6 @@ Pay &To: &Pagar a: - - Enter a label for this address to add it to your address book - Etiquete esta dirección para añadirla a la libreta - &Label: &Etiqueta: @@ -1612,69 +1041,9 @@ Reset all verify message fields Limpiar todos los campos de la verificación de mensaje - - Click "Sign Message" to generate signature - Haga clic en "Firmar mensaje" para generar la firma - - - The entered address is invalid. - La dirección introducida es inválida. - - - Please check the address and try again. - Verifique la dirección e inténtelo de nuevo. - - - The entered address does not refer to a key. - La dirección introducida no corresponde a una clave. - - - Wallet unlock was cancelled. - Se ha cancelado el desbloqueo del monedero. - - - Private key for the entered address is not available. - No se dispone de la clave privada para la dirección introducida. - - - Message signing failed. - Ha fallado la firma del mensaje. - - - Message signed. - Mensaje firmado. - - - The signature could not be decoded. - No se puede decodificar la firma. - - - Please check the signature and try again. - Compruebe la firma e inténtelo de nuevo. - - - The signature did not match the message digest. - La firma no coincide con el resumen del mensaje. - - - Message verification failed. - La verificación del mensaje ha fallado. - - - Message verified. - Mensaje verificado. - SplashScreen - - Bitcoin Core - Núcleo de Bitcoin - - - The Bitcoin Core developers - Los desarrolladores del Núcleo de Bitcoin - [testnet] [testnet] @@ -1687,402 +1056,16 @@ KB/s - - TransactionDesc - - Open until %1 - Abierto hasta %1 - - - %1/offline - %1/fuera de línea - - - %1/unconfirmed - %1/no confirmado - - - %1 confirmations - %1 confirmaciones - - - Status - Estado - - - Date - Fecha - - - Source - Fuente - - - Generated - Generado - - - From - De - - - To - Para - - - own address - dirección propia - - - label - etiqueta - - - Credit - Crédito - - - not accepted - no aceptada - - - Debit - Débito - - - Transaction fee - Comisión de transacción - - - Net amount - Cantidad neta - - - Message - Mensaje - - - Comment - Comentario - - - Transaction ID - ID - - - Merchant - Vendedor - - - 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. - Las monedas generadas deben madurar %1 bloques antes de que puedan ser gastadas. Una vez que generas este bloque, es propagado por la red para ser añadido a la cadena de bloques. Si falla el intento de meterse en la cadena, su estado cambiará a "no aceptado" y ya no se puede gastar. Esto puede ocurrir ocasionalmente si otro nodo genera un bloque a pocos segundos del tuyo. - - - Debug information - Información de depuración - - - Transaction - Transacción - - - Inputs - entradas - - - Amount - Cantidad - - - true - verdadero - - - false - falso - - - , has not been successfully broadcast yet - , todavía no se ha sido difundido satisfactoriamente - - - unknown - desconocido - - TransactionDescDialog - - Transaction details - Detalles de transacción - This pane shows a detailed description of the transaction Esta ventana muestra información detallada sobre la transacción - - TransactionTableModel - - Date - Fecha - - - Type - Tipo - - - Open until %1 - Abierto hasta %1 - - - Confirmed (%1 confirmations) - Confirmado (%1 confirmaciones) - - - This block was not received by any other nodes and will probably not be accepted! - Este bloque no ha sido recibido por otros nodos y probablemente no sea aceptado! - - - Generated but not accepted - Generado pero no aceptado - - - Label - Etiqueta - - - Received with - Recibido con - - - Received from - Recibidos de - - - Sent to - Enviado a - - - Payment to yourself - Pago propio - - - Mined - Minado - - - (n/a) - (nd) - - - Transaction status. Hover over this field to show number of confirmations. - Estado de transacción. Pasa el ratón sobre este campo para ver el número de confirmaciones. - - - Date and time that the transaction was received. - Fecha y hora en que se recibió la transacción. - - - Type of transaction. - Tipo de transacción. - - - Amount removed from or added to balance. - Cantidad retirada o añadida al saldo. - - - - TransactionView - - All - Todo - - - Today - Hoy - - - This week - Esta semana - - - This month - Este mes - - - Last month - Mes pasado - - - This year - Este año - - - Range... - Rango... - - - Received with - Recibido con - - - Sent to - Enviado a - - - To yourself - A usted mismo - - - Mined - Minado - - - Other - Otra - - - Enter address or label to search - Introduzca una dirección o etiqueta que buscar - - - Min amount - Cantidad mínima - - - Copy address - Copiar dirección - - - Copy label - Copiar etiqueta - - - Copy amount - Copiar cantidad - - - Copy transaction ID - Copiar identificador de transacción - - - Edit label - Editar etiqueta - - - Show transaction details - Mostrar detalles de la transacción - - - Export Transaction History - Exportar historial de transacciones - - - Exporting Failed - Error exportando - - - There was an error trying to save the transaction history to %1. - Ha habido un error al intentar guardar la transacción con %1. - - - Exporting Successful - Exportación finalizada - - - The transaction history was successfully saved to %1. - La transacción ha sido guardada en %1. - - - Comma separated file (*.csv) - Archivos de columnas separadas por coma (*.csv) - - - Confirmed - Confirmado - - - Date - Fecha - - - Type - Tipo - - - Label - Etiqueta - - - Address - Dirección - - - ID - ID - - - Range: - Rango: - - - to - para - - UnitDisplayStatusBarControl - - WalletFrame - - No wallet has been loaded. - No se ha cargado ningún monedero - - - - WalletModel - - Send Coins - Enviar monedas - - - - WalletView - - &Export - &Exportar - - - Export the data in the current tab to a file - Exportar a un archivo los datos de esta pestaña - - - Backup Wallet - Respaldo de monedero - - - Wallet Data (*.dat) - Datos de monedero (*.dat) - - - Backup Failed - Ha fallado el respaldo - - - There was an error trying to save the wallet data to %1. - Ha habido un error al intentar guardar los datos del monedero en %1. - - - The wallet data was successfully saved to %1. - Los datos del monedero se han guardado con éxito en %1. - - - Backup Successful - Se ha completado con éxito la copia de respaldo - - bitcoin-core @@ -2116,6 +1099,10 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Aceptar conexiones desde el exterior (predeterminado: 1 si no -proxy o -connect) + + Bitcoin Core + Núcleo de Bitcoin + Bind to given address and always listen on it. Use [host]:port notation for IPv6 Vincular a la dirección dada y escuchar siempre en ella. Utilice la notación [host]:port para IPv6 @@ -2136,10 +1123,6 @@ Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Atención: ¡Parece que no estamos completamente de acuerdo con nuestros pares! Podría necesitar una actualización, u otros nodos podrían necesitarla. - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Aviso: ¡Recuperados datos de wallet.dat corrupto! El wallet.dat original se ha guardado como wallet.{timestamp}.bak en %s; si hubiera errores en su saldo o transacciones, deberá restaurar una copia de seguridad. - <category> can be: <category> puede ser: @@ -2216,10 +1199,6 @@ Wallet %s resides outside data directory %s El monedero %s se encuentra fuera del directorio de datos %s - - You need to rebuild the database using -reindex to change -txindex - Usted necesita reconstruir la base de datos utilizando -reindex para cambiar -txindex - Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message) Ejecutar un comando cuando se reciba una alerta importante o cuando veamos un fork demasiado largo (%s en cmd se reemplazará por el mensaje) @@ -2228,26 +1207,10 @@ Set maximum size of high-priority/low-fee transactions in bytes (default: %d) Establecer tamaño máximo de las transacciones de alta prioridad/comisión baja en bytes (por defecto: %d) - - Cannot resolve -whitebind address: '%s' - No se puede resolver la dirección de -whitebind: '%s' - Information Información - - Invalid amount for -maxtxfee=<amount>: '%s' - Inválido por el monto -maxtxfee=<amount>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Inválido por el monto -minrelaytxfee=<amount>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - Inválido por el monto -mintxfee=<amount>: '%s' - RPC server options: Opciones del sservidor RPC: @@ -2289,10 +1252,6 @@ Warning Aviso - - wallet.dat corrupt, salvage failed - wallet.dat corrupto. Ha fallado la recuperación. - Password for JSON-RPC connections Contraseña para las conexiones JSON-RPC @@ -2302,11 +1261,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) Ejecutar un comando cuando cambia el mejor bloque (%s en cmd se sustituye por el hash de bloque) - - This help message - Este mensaje de ayuda - - Allow DNS lookups for -addnode, -seednode and -connect Permitir búsquedas DNS para -addnode, -seednode y -connect @@ -2315,14 +1269,6 @@ Loading addresses... Cargando direcciones... - - Error loading wallet.dat: Wallet corrupted - Error al cargar wallet.dat: el monedero está dañado - - - Error loading wallet.dat - Error al cargar wallet.dat - Invalid -proxy address: '%s' Dirección -proxy inválida: '%s' @@ -2331,18 +1277,6 @@ Unknown network specified in -onlynet: '%s' La red especificada en -onlynet '%s' es desconocida - - Cannot resolve -bind address: '%s' - No se puede resolver la dirección de -bind: '%s' - - - Cannot resolve -externalip address: '%s' - No se puede resolver la dirección de -externalip: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - Cantidad inválida para -paytxfee=<amount>: '%s' - Insufficient funds Fondos insuficientes diff --git a/src/qt/locale/bitcoin_es_ES.ts b/src/qt/locale/bitcoin_es_ES.ts index bdbfed4ec634f..c66a477cc2994 100644 --- a/src/qt/locale/bitcoin_es_ES.ts +++ b/src/qt/locale/bitcoin_es_ES.ts @@ -25,10 +25,6 @@ C&lose C&errar - - &Copy Address - &Copiar Direccón - Delete the currently selected address from the list Elimina la dirección seleccionada de la lista @@ -45,73 +41,6 @@ &Delete &Eliminar - - Choose the address to send coins to - Elige la dirección a la que enviar las monedas - - - Choose the address to receive coins with - Elige la direccón con la que recibir monedas - - - C&hoose - E&legir - - - Sending addresses - Enviando direcciones - - - Receiving addresses - Recibiendo direcciones - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Estas son tus direcciones de Bitcoin para enviar pagos. Comprueba siempre la cantidad y la dirección receptora antes de enviar monedas. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Estas son tus direcciones de Bitcoin para recibir pagos. Se recomienda usar una nueva dirección receptora para cada transacción - - - Copy &Label - Copiar &Etiqueta - - - &Edit - &Editar - - - Export Address List - Exportar Lista de Direcciones - - - Comma separated file (*.csv) - Archivo separado por comas (*.csv) - - - Exporting Failed - Exportacón Fallida - - - There was an error trying to save the address list to %1. Please try again. - Ha ocurrido un error intentando guardar la lista de direcciones en %1. Por favor intentalo de nuevo. - - - - AddressTableModel - - Label - Etiqueta - - - Address - Dirección - - - (no label) - (sin etiqueta) - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase Repite la nueva contraseña - - Encrypt wallet - Encriptar cartera - - - This operation needs your wallet passphrase to unlock the wallet. - Esta operacón necesita tu contraseña de la cartera para desbloquear la cartera. - - - Unlock wallet - Desbloquear cartera - - - This operation needs your wallet passphrase to decrypt the wallet. - Esta operación requiere tu contraseña de la cartera para desencriptar la cartera. - - - Decrypt wallet - Desencriptar cartera - - - Change passphrase - Cambiar contraseña - - - Confirm wallet encryption - Confirmar encriptación de la cartera - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Advertencia: Si encriptas tu cartera y pierdes tu contraseña, <b>PERDERÁS TODOS TUS BITCOINS</B> - - - Are you sure you wish to encrypt your wallet? - Estás seguro ue deseas encriptar tu cartera? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Bitcoin Core se cerrará ahora para finalizar el proceso de encriptación. Recuerda que encriptar tu cartera no protege completamente tus bitcoins de ser robados por malware infectando tu ordenador. - - - 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. - IMPORTANTE: Cualquier copia de seguridad anterior del archivo de tu cartera debería ser remplazado con el nuevo archivo encriptado. Por motivos de seguridad, las copias de seguridad anteriores de la cartera desencriptada quedaran inusables tan pronto como empieces a usar la nueva cartera encriptada. - - - Warning: The Caps Lock key is on! - Advertencia: La Tecla de Bloqueo de Mayusculas esta activada! - - - Wallet encrypted - Cartera encriptada - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Introduzca la nueva contraseña de la cartera. <br/>Por favor utilice una contraseña de <b>diez o mas caracteres aleatorios</b>, o <b>ocho o mas palabras</b>. - - - Enter the old passphrase and new passphrase to the wallet. - Introduzca la antigua contraseña y la nueva contraseña en la cartera. - - - Wallet encryption failed - Encriptación de la cartera fallida - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - La encriptación de la cartera ha fallado debido a un error interno. Tu cartera no ha sido encriptada. - - - The supplied passphrases do not match. - Las contraseñas proporcianadas no se corresponden. - - - Wallet unlock failed - Desbloqueo de la cartera fallido - - - The passphrase entered for the wallet decryption was incorrect. - La contraseña introducida para desencriptar la cartera es incorrecta. - - - Wallet decryption failed - Desencriptación de la cartera fallida - - - Wallet passphrase was successfully changed. - Contraseña de la cartera cambiada correctamente - BanTableModel @@ -297,14 +138,6 @@ Open &URI... Abrir &URI... - - Bitcoin Core client - Cliente Bitcoin Core - - - Importing blocks from disk... - Importando bloques desde disco... - Reindexing blocks on disk... Reindexando bloques en el disco... @@ -318,15 +151,8 @@ Crea una copia de seguridad de tu cartera en otra ubicación - - ClientModel - CoinControlDialog - - (no label) - (sin etiqueta) - EditAddressDialog @@ -338,7 +164,7 @@ &Address Dirección - + FreespaceChecker @@ -357,18 +183,12 @@ OverviewPage - - PaymentServer - PeerTableModel QObject - - QRImageWidget - RPCConsole @@ -381,32 +201,9 @@ Copy &Address &Copiar Direccón - - Address - Dirección - - - Label - Etiqueta - - - - RecentRequestsTableModel - - Label - Etiqueta - - - (no label) - (sin etiqueta) - SendCoinsDialog - - (no label) - (sin etiqueta) - SendCoinsEntry @@ -423,58 +220,12 @@ TrafficGraphWidget - - TransactionDesc - TransactionDescDialog - - TransactionTableModel - - Label - Etiqueta - - - - TransactionView - - Exporting Failed - Exportacón Fallida - - - Comma separated file (*.csv) - Archivo separado por comas (*.csv) - - - Label - Etiqueta - - - Address - Dirección - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - - WalletView - - &Export - &Exportar - - - Export the data in the current tab to a file - Exporta los datos de la pestaña actual a un archivo - - bitcoin-core diff --git a/src/qt/locale/bitcoin_es_MX.ts b/src/qt/locale/bitcoin_es_MX.ts index b0dfa4ab7c54c..26432190a27cd 100644 --- a/src/qt/locale/bitcoin_es_MX.ts +++ b/src/qt/locale/bitcoin_es_MX.ts @@ -25,10 +25,6 @@ C&lose Cerrar - - &Copy Address - &Copiar dirección - Delete the currently selected address from the list Eliminar la dirección actualmente seleccionada de la lista @@ -45,69 +41,6 @@ &Delete &Borrar - - Choose the address to send coins to - Elija una dirección a la cual enviar monedas - - - Choose the address to receive coins with - Elija la dirección con la cual recibir monedas - - - C&hoose - Elegir - - - Sending addresses - Enviando direcciones - - - Receiving addresses - Recibiendo direcciones - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Estas son tus direcciones de Bitcoin para enviar pagos. Siempre revise la cantidad y la dirección receptora antes de enviar monedas - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Estas son tus direcciones Bitcoin para recibir pagos. Es recomendado usar una nueva dirección receptora para cada transacción. - - - Copy &Label - Copiar &Etiqueta - - - &Edit - &Editar - - - Export Address List - Exportar Lista de direcciones - - - Comma separated file (*.csv) - Archivo separado por comas (*.CSV) - - - Exporting Failed - Exportación fallida - - - - AddressTableModel - - Label - Etiqueta - - - Address - Dirección - - - (no label) - (sin etiqueta) - AskPassphraseDialog @@ -123,78 +56,6 @@ Repeat new passphrase Repita la nueva contraseña - - Encrypt wallet - Encriptar cartera. - - - This operation needs your wallet passphrase to unlock the wallet. - Esta operación necesita la contraseña de su cartera para desbloquear su cartera. - - - Unlock wallet - Desbloquear cartera. - - - This operation needs your wallet passphrase to decrypt the wallet. - Esta operación necesita la contraseña de su cartera para desencriptar su cartera. - - - Decrypt wallet - Desencriptar cartera - - - Change passphrase - Cambiar contraseña - - - Confirm wallet encryption - Confirmar la encriptación de cartera - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Advertencia: Si encripta su cartera y pierde su contraseña, <b>PERDERÁ TODOS SUS BITCOINS</b>! - - - Are you sure you wish to encrypt your wallet? - ¿Está seguro que desea encriptar su cartera? - - - Warning: The Caps Lock key is on! - Advertencia: ¡La tecla Bloq Mayus está activada! - - - Wallet encrypted - Cartera encriptada - - - Wallet encryption failed - La encriptación de la cartera fallo - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - La encriptación de la cartera falló debido a un error interno. Su cartera no fue encriptada. - - - The supplied passphrases do not match. - Las contraseñas dadas no coinciden - - - Wallet unlock failed - El desbloqueo de la cartera falló - - - The passphrase entered for the wallet decryption was incorrect. - La contraseña ingresada para la desencriptación de la cartera es incorrecta - - - Wallet decryption failed - La desencriptación de la cartera fallo - - - Wallet passphrase was successfully changed. - La contraseña de la cartera ha sido exitosamente cambiada. - BanTableModel @@ -273,14 +134,6 @@ Open &URI... Abrir &URL... - - Bitcoin Core client - cliente Bitcoin Core - - - Importing blocks from disk... - Importando bloques desde el disco... - Reindexing blocks on disk... Reindexando bloques en el disco... @@ -341,26 +194,10 @@ Tabs toolbar Pestañas - - Bitcoin Core - nucleo Bitcoin - - - &About Bitcoin Core - Acerca de Bitcoin Core - - - Modify configuration options for Bitcoin Core - Modificar las opciones de configuración de Bitcoin Core - &Command-line options opciones de la &Linea de comandos - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Mostrar mensaje de ayuda del nucleo de Bitcoin para optener una lista con los posibles comandos de Bitcoin - Error Error @@ -398,9 +235,6 @@ La cartera esta <b>encriptada</b> y <b>bloqueada</b> actualmente - - ClientModel - CoinControlDialog @@ -447,70 +281,6 @@ Priority Prioridad - - Copy address - Copiar dirección - - - Copy label - Copiar etiqueta - - - Copy amount - Copiar monto - - - Copy transaction ID - Copiar identificación de la transacción. - - - Copy quantity - Copiar cantidad - - - Copy fee - Copiar cuota - - - Copy after fee - Copiar después de cuota - - - Copy bytes - Copiar bytes - - - Copy priority - Copiar prioridad - - - Copy change - Copiar cambio - - - low - Bajo - - - none - Ninguno - - - yes - si - - - no - no - - - (no label) - (sin etiqueta) - - - (change) - cambio - EditAddressDialog @@ -526,34 +296,6 @@ &Address &Dirección - - New receiving address - Nueva dirección de recepción - - - New sending address - Nueva dirección de envío - - - Edit receiving address - Editar dirección de recepción - - - Edit sending address - Editar dirección de envío - - - The entered address "%1" is already in the address book. - La dirección ingresada "%1" ya existe en la libreta de direcciones - - - Could not unlock wallet. - No se puede desbloquear la cartera - - - New key generation failed. - La generación de la nueva clave fallo - FreespaceChecker @@ -564,10 +306,6 @@ HelpMessageDialog - - Bitcoin Core - nucleo Bitcoin - version versión @@ -576,10 +314,6 @@ (%1-bit) (%1-bit) - - About Bitcoin Core - Acerca de Bitcoin Core - Command-line options opciones de la Linea de comandos @@ -595,10 +329,6 @@ Intro - - Bitcoin Core - nucleo Bitcoin - Error Error @@ -633,9 +363,6 @@ Formulario - - PaymentServer - PeerTableModel @@ -646,9 +373,6 @@ Monto - - QRImageWidget - RPCConsole @@ -682,60 +406,13 @@ An optional amount to request. Leave this empty or zero to not request a specific amount. Monto opcional a solicitar. Dejarlo vacion o en cero no solicita un monto especifico. - - Copy label - Copiar etiqueta - - - Copy amount - Copiar monto - - + ReceiveRequestDialog Copy &Address &Copiar dirección - - Address - Dirección - - - Amount - Monto - - - Label - Etiqueta - - - Message - Mensaje - - - - RecentRequestsTableModel - - Date - Fecha - - - Label - Etiqueta - - - Message - Mensaje - - - Amount - Monto - - - (no label) - (sin etiqueta) - SendCoinsDialog @@ -787,66 +464,6 @@ Confirm the send action Confirme la acción de enviar - - Confirm send coins - Confirme para enviar monedas - - - Copy quantity - Copiar cantidad - - - Copy amount - Copiar monto - - - Copy fee - Copiar cuota - - - Copy after fee - Copiar después de cuota - - - Copy bytes - Copiar bytes - - - Copy priority - Copiar prioridad - - - Copy change - Copiar cambio - - - or - o - - - The amount to pay must be larger than 0. - El monto a pagar debe ser mayor a 0 - - - Transaction creation failed! - ¡La creación de la transación falló! - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - ¡La transación fue rechazada! Esto puede ocurrir si algunas de tus monedas en tu cartera han sido gastadas, al igual que si usas una cartera copiada y la monedas fueron gastadas en la copia pero no se marcaron como gastadas. - - - Warning: Invalid Bitcoin address - Advertencia: Dirección de Bitcoin invalida - - - (no label) - (sin etiqueta) - - - Warning: Unknown change address - Advertencia: Cambio de dirección desconocido - SendCoinsEntry @@ -858,10 +475,6 @@ Pay &To: Pagar &a: - - Enter a label for this address to add it to your address book - Ingrese una etiqueta para esta dirección para agregarlo en su libreta de direcciones. - &Label: &Etiqueta @@ -897,10 +510,6 @@ ShutdownWindow - - Bitcoin Core is shutting down... - Apagando el nucleo de Bitcoin... - Do not shut down the computer until this window disappears. No apague su computadora hasta que esta ventana desaparesca. @@ -927,324 +536,30 @@ SplashScreen - - Bitcoin Core - Bitcoin Core - - - The Bitcoin Core developers - Los desarrolladores de Bitcoin Core - TrafficGraphWidget - - TransactionDesc - - Open until %1 - Abrir hasta %1 - - - %1/unconfirmed - %1/No confirmado - - - %1 confirmations - %1 confirmaciones - - - Status - Estado - - - Date - Fecha - - - From - De - - - To - Para - - - label - etiqueta - - - Message - Mensaje - - - Comment - Comentario - - - Transaction ID - ID - - - Transaction - Transacción - - - Amount - Monto - - - , has not been successfully broadcast yet - , no ha sido transmitido aun - - - unknown - desconocido - - TransactionDescDialog - - Transaction details - Detalles de la transacción - This pane shows a detailed description of the transaction Este panel muestras una descripción detallada de la transacción - - TransactionTableModel - - Date - Fecha - - - Type - Tipo - - - Open until %1 - Abrir hasta %1 - - - Confirmed (%1 confirmations) - Confimado (%1 confirmaciones) - - - This block was not received by any other nodes and will probably not be accepted! - Este bloque no fue recibido por ningun nodo y probablemente no fue aceptado ! - - - Generated but not accepted - Generado pero no aprovado - - - Label - Etiqueta - - - Received with - Recibido con - - - Sent to - Enviar a - - - Payment to yourself - Pagar a si mismo - - - Mined - Minado - - - (n/a) - (n/a) - - - Date and time that the transaction was received. - Fecha y hora en que la transacción fue recibida - - - Type of transaction. - Escriba una transacción - - - Amount removed from or added to balance. - Cantidad removida del saldo o agregada - - - - TransactionView - - All - Todo - - - Today - Hoy - - - This week - Esta semana - - - This month - Este mes - - - Last month - El mes pasado - - - This year - Este año - - - Received with - Recibido con - - - Sent to - Enviar a - - - To yourself - Para ti mismo - - - Mined - Minado - - - Other - Otro - - - Enter address or label to search - Ingrese dirección o capa a buscar - - - Min amount - Monto minimo - - - Copy address - Copiar dirección - - - Copy label - Copiar capa - - - Copy amount - copiar monto - - - Copy transaction ID - Copiar identificación de la transacción. - - - Edit label - Editar capa - - - Export Transaction History - Exportar el historial de transacción - - - Exporting Failed - Exportación fallida - - - There was an error trying to save the transaction history to %1. - Ocurrio un error intentando guardar el historial de transaciones a %1 - - - Exporting Successful - Exportacion satisfactoria - - - The transaction history was successfully saved to %1. - el historial de transaciones ha sido guardado exitosamente en %1 - - - Comma separated file (*.csv) - Arhchivo separado por comas (*.CSV) - - - Confirmed - Confirmado - - - Date - Fecha - - - Type - Tipo - - - Label - Etiqueta - - - Address - Domicilio - - - ID - ID - - - to - Para - - UnitDisplayStatusBarControl - - WalletFrame - - No wallet has been loaded. - No se há cargado la cartera. - - - - WalletModel - - Send Coins - Mandar monedas - - - - WalletView - - &Export - &Exportar - - - Export the data in the current tab to a file - Exportar la información en la tabla actual a un archivo - - - There was an error trying to save the wallet data to %1. - Ocurrio un error tratando de guardar la información de la cartera %1 - - - The wallet data was successfully saved to %1. - La información de la cartera fué guardada exitosamente a %1 - - bitcoin-core Options: Opciones: + + Bitcoin Core + nucleo Bitcoin + <category> can be: <categoria> puede ser: diff --git a/src/qt/locale/bitcoin_es_UY.ts b/src/qt/locale/bitcoin_es_UY.ts index 32d433d6ec3d6..8d361620de1b3 100644 --- a/src/qt/locale/bitcoin_es_UY.ts +++ b/src/qt/locale/bitcoin_es_UY.ts @@ -25,10 +25,6 @@ C&lose Cerrar - - &Copy Address - Copiar Dirección - &Export Exportar @@ -37,50 +33,6 @@ &Delete &Borrar - - Choose the address to send coins to - Elige una dirección donde enviar monedas a - - - Sending addresses - Enviando direcciones - - - Receiving addresses - Recibiendo direcciones - - - - &Edit - Editar - - - Export Address List - Exportar Lista de Direcciones - - - Comma separated file (*.csv) - Archivos separados por coma (*.csv) - - - Exporting Failed - Exportación fallida - - - - AddressTableModel - - Label - Etiqueta - - - Address - Direccion - - - (no label) - (Sin etiqueta) - AskPassphraseDialog @@ -96,71 +48,7 @@ Repeat new passphrase Repetir nueva contraseña - - Encrypt wallet - Monedero cifrado - - - This operation needs your wallet passphrase to unlock the wallet. - Esta operacion necesita la contraseña del monedero para desbloquear el mismo - - - Unlock wallet - Monedero destrabado - - - This operation needs your wallet passphrase to decrypt the wallet. - Esta operacion necesita la contraseña del monedero para descifrar el mismo - - - Decrypt wallet - Monedero descifrado - - - Change passphrase - Cambiar contraseña - - - Confirm wallet encryption - Confirme el cifrado del monedero - - - Are you sure you wish to encrypt your wallet? - Estas seguro que deseas encriptar tu billetera? - - - Warning: The Caps Lock key is on! - Atención: la tecla Mayusculas esta activa! - - - Wallet encrypted - Monedero cifrado - - - Wallet encryption failed - Fallo en el cifrado del monedero - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Fallo en el cifrado del monedero a causa de un error interno. Su monedero no esta cifrado - - - The supplied passphrases do not match. - Las contraseñas suministradas no coinciden. - - - Wallet unlock failed - Fallo en el desbloqueo del mondero - - - The passphrase entered for the wallet decryption was incorrect. - La contraseña introducida para el descifrado del monedero es incorrecta. - - - Wallet decryption failed - Fallo en el descifrado del monedero - - + BanTableModel @@ -302,9 +190,6 @@ El Monedero esta <b>cifrado</b> y actualmente <b>bloqueado</b> - - ClientModel - CoinControlDialog @@ -339,11 +224,7 @@ Priority Prioridad - - (no label) - (Sin etiqueta) - - + EditAddressDialog @@ -358,34 +239,6 @@ &Address &Direccion - - New receiving address - Nueva dirección de recepción - - - New sending address - Nueva dirección de envío - - - Edit receiving address - Editar dirección de recepcion - - - Edit sending address - Editar dirección de envío - - - The entered address "%1" is already in the address book. - La dirección introducida "%1" ya está en la libreta de direcciones. - - - Could not unlock wallet. - No se puede abrir el monedero. - - - New key generation failed. - Fallo en la nueva clave generada. - FreespaceChecker @@ -421,18 +274,12 @@ Formulario - - PaymentServer - PeerTableModel QObject - - QRImageWidget - RPCConsole @@ -453,29 +300,6 @@ Copy &Address Copiar Dirección - - Address - Direccion - - - Label - Etiqueta - - - - RecentRequestsTableModel - - Date - Fecha - - - Label - Etiqueta - - - (no label) - (Sin etiqueta) - SendCoinsDialog @@ -515,18 +339,6 @@ Confirm the send action Confirmar el envío - - Confirm send coins - Confirmar el envio de monedas - - - The amount to pay must be larger than 0. - La cantidad a pagar debe ser mayor que 0. - - - (no label) - (Sin etiqueta) - SendCoinsEntry @@ -538,10 +350,6 @@ Pay &To: Pagar &A: - - Enter a label for this address to add it to your address book - Introduzca una etiqueta para esta dirección para añadirla a su libreta de direcciones - &Label: &Etiqueta: @@ -591,90 +399,12 @@ TrafficGraphWidget - - TransactionDesc - - Open until %1 - Abrir hasta %1 - - - Date - Fecha - - - Transaction - Transaccion - - - unknown - desconocido - - TransactionDescDialog - - TransactionTableModel - - Date - Fecha - - - Open until %1 - Abrir hasta %1 - - - Label - Etiqueta - - - - TransactionView - - Exporting Failed - Exportación fallida - - - Comma separated file (*.csv) - Archivos separados por coma (*.csv) - - - Confirmed - Confirmado - - - Date - Fecha - - - Label - Etiqueta - - - Address - Direccion - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - Send Coins - Enviar monedas - - - - WalletView - - &Export - Exportar - - bitcoin-core diff --git a/src/qt/locale/bitcoin_es_VE.ts b/src/qt/locale/bitcoin_es_VE.ts index 582e72884607f..432adc57eeaa0 100644 --- a/src/qt/locale/bitcoin_es_VE.ts +++ b/src/qt/locale/bitcoin_es_VE.ts @@ -22,8 +22,8 @@ &Copiar - &Copy Address - &Copiar Dirección + C&lose + C&errar Delete the currently selected address from the list @@ -41,69 +41,6 @@ &Delete &Borrar - - Choose the address to send coins to - Elige la dirección para enviar monedas - - - Choose the address to receive coins with - Elige la dirección para recibir monedas - - - Sending addresses - Envío de direcciones - - - Receiving addresses - Recepción de direcciones - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Estas son tus direcciones Bitcoin para realizar pagos. Siempre checa el monto y la dirección de recepción antes de enviar monedas. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Estas son tus direcciones Bitcoin para recibir pagos. Es recomendable usar una nueva dirección para cada transacción. - - - Copy &Label - Copiar &Etiqueta - - - &Edit - &Editar - - - Export Address List - Exportar lista de direcciones - - - Comma separated file (*.csv) - Archivo separado por comas (*.csv) - - - Exporting Failed - Exportación fallida - - - There was an error trying to save the address list to %1. Please try again. - Hubo un error intentando guardar la lista de direcciones al %1. Por favor intente nuevamente. - - - - AddressTableModel - - Label - Etiqueta - - - Address - Dirección - - - (no label) - (sin etiqueta) - AskPassphraseDialog @@ -123,86 +60,6 @@ Repeat new passphrase Repetir nueva frase de contraseña - - Encrypt wallet - Encriptar billetera - - - This operation needs your wallet passphrase to unlock the wallet. - Esta operación necesita tu frase de contraseña de la billetera para desbloquearla. - - - Unlock wallet - Desbloquear billetera - - - This operation needs your wallet passphrase to decrypt the wallet. - Esta operacción necesita tu frase de contraseña para desepcriptar la billetera - - - Decrypt wallet - Desencriptar billetera - - - Change passphrase - Cambiar frase secreta - - - Confirm wallet encryption - Confirmar encriptación de billetera - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Aviso: Si encriptas tu billetera y pierdes tu frase secreta, ¡PERDERÁS TODOS TUS BITCOINS! - - - Are you sure you wish to encrypt your wallet? - ¿Está seguro que desea encriptar su billetera? - - - 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. - 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. - - - Warning: The Caps Lock key is on! - Aviso: El bloqueo de mayúsculas está activado. - - - Wallet encrypted - Billetera encriptada - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Introduce la nueva frase secreta a la billetera. Por favor use una frase secreta de diez o más caracteres aleatorios, u ocho o más palabras. - - - Wallet encryption failed - Encriptación de billetera fallida - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Encriptación de billetera fallida debido a un error interno. Tu billetera no fue encriptada. - - - The supplied passphrases do not match. - Las frases secretas introducidas no concuerdan. - - - Wallet unlock failed - Desbloqueo de billetera fallido - - - The passphrase entered for the wallet decryption was incorrect. - La frase secreta introducida para la desencriptación de la billetera fué incorrecta. - - - Wallet decryption failed - Desencriptación de billetera fallida - - - Wallet passphrase was successfully changed. - La frase secreta de la billetera fué cambiada exitosamente. - BanTableModel @@ -234,20 +91,20 @@ Buscar historial de transacciones - Quit application - Quitar aplicación + E&xit + S&alir - &Receiving addresses... - Recepción de direcciones + Quit application + Quitar aplicación - Bitcoin Core client - Cliente Bitcoin Core + &Options... + &Opciones... - Importing blocks from disk... - Importando bloques desde el disco... + &Receiving addresses... + Recepción de direcciones Reindexing blocks on disk... @@ -285,10 +142,6 @@ &Receive &Recibir - - Show information about Bitcoin Core - Mostrar información acerca de Bitcoin Core - &Show / Hide &Mostar / Ocultar @@ -317,14 +170,6 @@ &Settings &Configuración - - Bitcoin Core - Bitcoin Core - - - &About Bitcoin Core - Acerca de Bitcoin Core - &Command-line options Opciones de línea de comandos @@ -382,13 +227,6 @@ La billetera está encriptada y bloqueada recientemente - - ClientModel - - Network Alert - Alerta de red - - CoinControlDialog @@ -463,134 +301,6 @@ Priority Prioridad - - Copy address - Copiar dirección - - - Copy label - Copiar etiqueta - - - Copy amount - Copiar monto - - - Copy transaction ID - Copiar ID de la transacción - - - Lock unspent - Bloqueo no gastado - - - Unlock unspent - Desbloqueo no gastado - - - Copy quantity - Copiar cantidad - - - Copy fee - Copiar comisión - - - Copy bytes - Copiar bytes - - - Copy priority - Copiar prioridad - - - Copy dust - Copiar dust - - - Copy change - Copiar cambio - - - highest - Más alto - - - higher - superior - - - high - alto - - - medium-high - medio-alto - - - medium - medio - - - low-medium - bajo-medio - - - low - bajo - - - lower - inferior - - - lowest - más bajo - - - (%1 locked) - (%1 bloqueado) - - - none - ninguno - - - Can vary +/- %1 satoshi(s) per input. - Puede variar +/- %1 satoshi(s) por entrada. - - - yes - si - - - no - no - - - This means a fee of at least %1 per kB is required. - Esto significa que se requiere al menos de una comisión de %1 por kB - - - Can vary +/- 1 byte per input. - Puede variar +/- 1 byte por entrada. - - - Transactions with higher priority are more likely to get included into a block. - Transacciones con mayor prioridad son más probables de ser incluidas en un bloque. - - - (no label) - (sin etiqueta) - - - change from %1 (%2) - Cambio desde %1 (%2) - - - (change) - (cambio) - EditAddressDialog @@ -614,38 +324,6 @@ &Address &Dirección - - New receiving address - Nueva dirección de recibo - - - New sending address - Nueva dirección de envío - - - Edit receiving address - Editar dirección de envío - - - Edit sending address - Editar dirección de envío - - - The entered address "%1" is already in the address book. - La dirección introducida "%1" ya está en el libro de direcciones. - - - The entered address "%1" is not a valid Bitcoin address. - La dirección introducida "%1" no es una dirección Bitcoin válida. - - - Could not unlock wallet. - No se pudo desbloquear la billetera. - - - New key generation failed. - Creación de la nueva llave fallida - FreespaceChecker @@ -672,10 +350,6 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin Core - version versión @@ -684,10 +358,6 @@ (%1-bit) (%1-bit) - - About Bitcoin Core - Acerca de Bitcoin Core - Command-line options Opciones de línea de comandos @@ -703,10 +373,6 @@ Intro - - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - Bitcoin Core descargará y almacenará una copia de la cadena de bloques Bitcoin. Al menos %1GB de datos serán almacenados en este directorio, y crecerá con el tiempo. La billetera será también almacenada en este directorio. - Use the default data directory Usar el directorio de datos por defecto @@ -715,10 +381,6 @@ Use a custom data directory: Usa un directorio de datos personalizado: - - Bitcoin Core - Bitcoin Core - Error: Specified data directory "%1" cannot be created. Error: Directorio de datos especificado "%1" no puede ser creado. @@ -746,10 +408,6 @@ Select payment request file Seleccionar archivo de solicitud de pago - - Select payment request file to open - Seleccionar archivo de solicitud de pago para abrir - OptionsDialog @@ -761,10 +419,18 @@ &Main &Main + + &Network + &Red + W&allet Billetera + + Expert + Experto + none ninguno @@ -772,9 +438,14 @@ OverviewPage - - - PaymentServer + + Available: + Disponible: + + + Pending: + Pendiente: + PeerTableModel @@ -786,15 +457,20 @@ Monto - - QRImageWidget - RPCConsole &Information Información + + In: + Entrada: + + + Out: + Salida: + ReceiveCoinsDialog @@ -807,51 +483,16 @@ &Etiqueta: - Copy label - Copiar etiqueta - - - Copy amount - Copiar monto + Show + Mostrar - + ReceiveRequestDialog Copy &Address &Copiar Dirección - - Address - Dirección - - - Amount - Monto - - - Label - Etiqueta - - - - RecentRequestsTableModel - - Date - Fecha - - - Label - Etiqueta - - - Amount - Monto - - - (no label) - (sin etiqueta) - SendCoinsDialog @@ -883,38 +524,6 @@ Dust: Polvo: - - Copy quantity - Copiar cantidad - - - Copy amount - Copiar monto - - - Copy fee - Copiar comisión - - - Copy bytes - Copiar bytes - - - Copy priority - Copiar prioridad - - - Copy change - Copiar cambio - - - (no label) - (sin etiqueta) - - - Copy dust - Copiar dust - SendCoinsEntry @@ -935,122 +544,16 @@ SplashScreen - - Bitcoin Core - Bitcoin Core - TrafficGraphWidget - - TransactionDesc - - Date - Fecha - - - Transaction - Transacción - - - Amount - Monto - - TransactionDescDialog - - TransactionTableModel - - Date - Fecha - - - Label - Etiqueta - - - - TransactionView - - Copy address - Copiar dirección - - - Copy label - Copiar etiqueta - - - Copy amount - Copiar monto - - - Copy transaction ID - Copiar ID de la transacción - - - Exporting Failed - Exportación fallida - - - Comma separated file (*.csv) - Archivo separado por comas (*.csv) - - - Confirmed - Confirmado - - - Date - Fecha - - - Label - Etiqueta - - - Address - Dirección - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - - WalletView - - &Export - &Exportar - - - Export the data in the current tab to a file - Exportar los datos en la pestaña actual a un archivo - - - Backup Failed - Copia de seguridad fallida - - - There was an error trying to save the wallet data to %1. - Hubo un error intentando guardar los datos de la billetera al %1 - - - The wallet data was successfully saved to %1. - Los datos de la billetera fueron guardados exitosamente al %1 - - - Backup Successful - Copia de seguridad completada - - bitcoin-core @@ -1077,6 +580,10 @@ Run in the background as a daemon and accept commands Correr en segundo plano como daemon y aceptar comandos + + Bitcoin Core + Bitcoin Core + Bind to given address and always listen on it. Use [host]:port notation for IPv6 Enlazar dirección dada y siempre escuchar en ella. Usar [host]:port notación para IPv6 @@ -1101,10 +608,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Esta es una compilación de prueba pre-lanzamiento - use bajo su propio riesgo - no utilizar para aplicaciones de minería o mercantes - - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - Deshabilitar para enlezar a %s en esta computadora. Bitcoin Core probablemente ya está ejecutándose. - Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Aviso: ¡La red no parece estar totalmente de acuerdo! Algunos mineros parecen estar teniendo inconvenientes. @@ -1113,10 +616,6 @@ Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Aviso: ¡No parecen estar totalmente de acuerdo con nuestros compañeros! Puede que tengas que actualizar, u otros nodos tengan que actualizarce. - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Aviso: wallet.dat está corrupto, ¡datos salvados! wallet.dat original guardado como wallet.{timestamp}.bak en %s; si tus transacciones o balance está incorrecto deberías restaurarlo desde una copia de seguridad. - Information Información diff --git a/src/qt/locale/bitcoin_et.ts b/src/qt/locale/bitcoin_et.ts index 089f01035d89d..e861d4e472312 100644 --- a/src/qt/locale/bitcoin_et.ts +++ b/src/qt/locale/bitcoin_et.ts @@ -21,10 +21,6 @@ C&lose S&ulge - - &Copy Address - &Kopeeri Aadress - Delete the currently selected address from the list Kustuta märgistatud aadress loetelust @@ -41,45 +37,6 @@ &Delete &Kustuta - - C&hoose - V&ali - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Need on sinu Bitcoini aadressid maksete saatmiseks. Müntide saatmisel kontrolli alati summat ning saaja aadressi. - - - Copy &Label - &Märgise kopeerimine - - - &Edit - &Muuda - - - Comma separated file (*.csv) - Komaeraldatud fail (*.csv) - - - Exporting Failed - Eksportimine Ebaõnnestus - - - - AddressTableModel - - Label - Silt - - - Address - Aadress - - - (no label) - (silti pole) - AskPassphraseDialog @@ -99,82 +56,6 @@ Repeat new passphrase Korda salafraasi - - Encrypt wallet - Krüpteeri rahakott - - - This operation needs your wallet passphrase to unlock the wallet. - See toiming nõuab sinu rahakoti salafraasi. - - - Unlock wallet - Tee rahakott lukust lahti. - - - This operation needs your wallet passphrase to decrypt the wallet. - See toiming nõuab sinu rahakoti salafraasi. - - - Decrypt wallet - Dekrüpteeri rahakott. - - - Change passphrase - Muuda salafraasi - - - Confirm wallet encryption - Kinnita rahakoti krüpteering - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Hoiatus: Kui sa kaotad oma, rahakoti krüpteerimisel kasutatud, salafraasi, siis <b>KAOTAD KA KÕIK OMA BITCOINID</b>! - - - Are you sure you wish to encrypt your wallet? - Kas soovid oma rahakoti krüpteerida? - - - 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. - TÄHTIS: Kõik varasemad rahakoti varundfailid tuleks üle kirjutada äsja loodud krüpteeritud rahakoti failiga. Turvakaalutlustel tühistatakse krüpteerimata rahakoti failid alates uue, krüpteeritud rahakoti, kasutusele võtust. - - - Warning: The Caps Lock key is on! - Hoiatus: Caps Lock on sisse lülitatud! - - - Wallet encrypted - Rahakott krüpteeritud - - - Wallet encryption failed - Tõrge rahakoti krüpteerimisel - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Rahakoti krüpteering ebaõnnestus tõrke tõttu. Sinu rahakotti ei krüpteeritud. - - - The supplied passphrases do not match. - Salafraasid ei kattu. - - - Wallet unlock failed - Rahakoti avamine ebaõnnestus - - - The passphrase entered for the wallet decryption was incorrect. - Rahakoti salafraas ei ole õige. - - - Wallet decryption failed - Rahakoti dekrüpteerimine ei õnnestunud - - - Wallet passphrase was successfully changed. - Rahakoti salafraasi muutmine õnnestus. - BanTableModel @@ -241,10 +122,6 @@ Open &URI... Ava &URI... - - Importing blocks from disk... - Impordi blokid kettalt... - Reindexing blocks on disk... Kettal olevate blokkide re-indekseerimine... @@ -325,14 +202,6 @@ Tabs toolbar Vahelehe tööriistariba - - Bitcoin Core - Bitcoini tuumik - - - &About Bitcoin Core - Kirjeldus Bitcoini Tuumast - &Command-line options Käsurea valikud @@ -436,13 +305,6 @@ Rahakott on <b>krüpteeritud</b> ning hetkel <b>suletud</b> - - ClientModel - - Network Alert - Võrgu Häire - - CoinControlDialog @@ -469,70 +331,6 @@ Confirmed Kinnitatud - - Copy address - Aadressi kopeerimine - - - Copy label - Märgise kopeerimine - - - Copy amount - Kopeeri summa - - - Copy transaction ID - Kopeeri tehingu ID - - - Copy fee - Kopeeri tasu - - - highest - kõrgeim - - - higher - kõrgem - - - high - kõrge - - - medium - keskmine - - - low - madal - - - lower - madalam - - - lowest - madalaim - - - (%1 locked) - (%1 lukustatud) - - - yes - jah - - - no - ei - - - (no label) - (silti pole) - EditAddressDialog @@ -548,38 +346,6 @@ &Address &Aadress - - New receiving address - Uus sissetulev aadress - - - New sending address - Uus väljaminev aadress - - - Edit receiving address - Sissetulevate aadresside muutmine - - - Edit sending address - Väljaminevate aadresside muutmine - - - The entered address "%1" is already in the address book. - Selline aadress on juba olemas: "%1" - - - The entered address "%1" is not a valid Bitcoin address. - Sisestatud aadress "%1" ei ole Bitcoinis kehtiv. - - - Could not unlock wallet. - Rahakotti ei avatud - - - New key generation failed. - Tõrge uue võtme loomisel. - FreespaceChecker @@ -590,18 +356,10 @@ HelpMessageDialog - - Bitcoin Core - Bitcoini tuumik - version versioon - - About Bitcoin Core - Kirjeldus Bitcoini Tuumast - Command-line options Käsurea valikud @@ -621,10 +379,6 @@ Welcome Teretulemast - - Bitcoin Core - Bitcoini tuumik - Error Tõrge @@ -771,17 +525,6 @@ Hiljutised tehingud - - PaymentServer - - URI handling - URI käsitsemine - - - Cannot start bitcoin: click-to-pay handler - Bitcoin ei käivitu: vajuta-maksa toiming - - PeerTableModel @@ -796,13 +539,6 @@ N/A - - QRImageWidget - - Save QR Code - Salvesta QR kood - - RPCConsole @@ -885,10 +621,6 @@ &Console &Konsool - - Build date - Valmistusaeg - Debug log file Debugimise logifail @@ -944,18 +676,6 @@ Remove Eemalda - - Copy label - Märgise kopeerimine - - - Copy message - Kopeeri sõnum - - - Copy amount - Kopeeri summa - ReceiveRequestDialog @@ -963,62 +683,7 @@ Copy &Address &Kopeeri Aadress - - Address - Aadress - - - Amount - Kogus - - - Label - Silt - - - Message - Sõnum - - - Resulting URI too long, try to reduce the text for label / message. - Tulemuseks on liiga pikk URL, püüa lühendada märgise/teate teksti. - - - Error encoding URI into QR Code. - Tõrge URI'st QR koodi loomisel - - - - RecentRequestsTableModel - - Date - Kuupäev - - - Label - Silt - - - Message - Sõnum - - - Amount - Kogus - - - (no label) - (silti pole) - - - (no message) - (sõnum puudub) - - - (no amount) - (summa puudub) - - + SendCoinsDialog @@ -1089,39 +754,7 @@ S&end S&aada - - Confirm send coins - Müntide saatmise kinnitamine - - - Copy amount - Kopeeri summa - - - Copy fee - Kopeeri tasu - - - or - või - - - The amount to pay must be larger than 0. - Makstav summa peab olema suurem kui 0. - - - The amount exceeds your balance. - Summa ületab jäägi. - - - The total exceeds your balance when the %1 transaction fee is included. - Summa koos tehingu tasuga %1 ületab sinu jääki. - - - (no label) - (silti pole) - - + SendCoinsEntry @@ -1132,10 +765,6 @@ Pay &To: Maksa &: - - Enter a label for this address to add it to your address book - Aadressiraamatusse sisestamiseks märgista aadress - &Label: &Märgis @@ -1230,69 +859,9 @@ Reset all verify message fields Tühjenda kõik sõnumi kinnitamise väljad - - Click "Sign Message" to generate signature - Signatuuri genereerimiseks vajuta "Allkirjasta Sõnum" - - - The entered address is invalid. - Sisestatud aadress ei kehti. - - - Please check the address and try again. - Palun kontrolli aadressi ning proovi uuesti. - - - The entered address does not refer to a key. - Sisestatud aadress ei viita võtmele. - - - Wallet unlock was cancelled. - Rahakoti avamine katkestati. - - - Private key for the entered address is not available. - Sisestatud aadressi privaatvõti ei ole saadaval. - - - Message signing failed. - Sõnumi signeerimine ebaõnnestus. - - - Message signed. - Sõnum signeeritud. - - - The signature could not be decoded. - Signatuuri ei õnnestunud dekodeerida. - - - Please check the signature and try again. - Palun kontrolli signatuuri ning proovi uuesti. - - - The signature did not match the message digest. - Signatuur ei kattunud sõnumi kokkuvõttega. - - - Message verification failed. - Sõnumi kontroll ebaõnnestus. - - - Message verified. - Sõnum kontrollitud. - SplashScreen - - Bitcoin Core - Bitcoini tuumik - - - The Bitcoin Core developers - Bitcoini Tuuma arendajad - [testnet] [testnet] @@ -1305,366 +874,16 @@ KB/s - - TransactionDesc - - Open until %1 - Avatud kuni %1 - - - %1/offline - %1/offline'is - - - %1/unconfirmed - %1/kinnitamata - - - %1 confirmations - %1 kinnitust - - - Status - Staatus - - - Date - Kuupäev - - - Source - Allikas - - - Generated - Genereeritud - - - From - Saatja - - - To - Saaja - - - own address - oma aadress - - - label - märgis - - - Credit - Krediit - - - not accepted - mitte aktsepteeritud - - - Debit - Deebet - - - Transaction fee - Tehingu tasu - - - Net amount - Neto summa - - - Message - Sõnum - - - Comment - Kommentaar - - - Transaction ID - Tehingu ID - - - Debug information - Debug'imise info - - - Transaction - Tehing - - - Inputs - Sisendid - - - Amount - Kogus - - - true - õige - - - false - vale - - - , has not been successfully broadcast yet - , veel esitlemata - - - unknown - tundmatu - - TransactionDescDialog - - Transaction details - Tehingu üksikasjad - This pane shows a detailed description of the transaction Paan kuvab tehingu detailid - - TransactionTableModel - - Date - Kuupäev - - - Type - Tüüp - - - Open until %1 - Avatud kuni %1 - - - Confirmed (%1 confirmations) - Kinnitatud (%1 kinnitust) - - - This block was not received by any other nodes and will probably not be accepted! - Antud klotsi pole saanud ükski osapool ning tõenäoliselt seda ei aktsepteerita! - - - Generated but not accepted - Loodud, kuid aktsepteerimata - - - Label - Silt - - - Received with - Saadud koos - - - Received from - Kellelt saadud - - - Sent to - Saadetud - - - Payment to yourself - Makse iseendale - - - Mined - Mine'itud - - - (n/a) - (n/a) - - - Transaction status. Hover over this field to show number of confirmations. - Tehingu staatus. Kinnituste arvu kuvamiseks liigu hiire noolega selle peale. - - - Date and time that the transaction was received. - Tehingu saamise kuupäev ning kellaaeg. - - - Type of transaction. - Tehingu tüüp. - - - Amount removed from or added to balance. - Jäägile lisatud või eemaldatud summa. - - - - TransactionView - - All - Kõik - - - Today - Täna - - - This week - Jooksev nädal - - - This month - Jooksev kuu - - - Last month - Eelmine kuu - - - This year - Jooksev aasta - - - Range... - Ulatus... - - - Received with - Saadud koos - - - Sent to - Saadetud - - - To yourself - Iseendale - - - Mined - Mine'itud - - - Other - Muu - - - Enter address or label to search - Otsimiseks sisesta märgis või aadress - - - Min amount - Vähim summa - - - Copy address - Aadressi kopeerimine - - - Copy label - Märgise kopeerimine - - - Copy amount - Kopeeri summa - - - Copy transaction ID - Kopeeri tehingu ID - - - Edit label - Märgise muutmine - - - Show transaction details - Kuva tehingu detailid - - - Exporting Failed - Eksportimine Ebaõnnestus - - - Comma separated file (*.csv) - Komaeraldatud fail (*.csv) - - - Confirmed - Kinnitatud - - - Date - Kuupäev - - - Type - Tüüp - - - Label - Silt - - - Address - Aadress - - - ID - ID - - - Range: - Ulatus: - - - to - saaja - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - Send Coins - Müntide saatmine - - - - WalletView - - &Export - &Ekspordi - - - Export the data in the current tab to a file - Ekspordi kuvatava vahelehe sisu faili - - - Backup Wallet - Varundatud Rahakott - - - Wallet Data (*.dat) - Rahakoti andmed (*.dat) - - - Backup Failed - Varundamine nurjus - - - Backup Successful - Varundamine õnnestus - - bitcoin-core @@ -1695,6 +914,10 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Luba välisühendusi (vaikeväärtus: 1 kui puudub -proxy või -connect) + + Bitcoin Core + Bitcoini tuumik + Bind to given address and always listen on it. Use [host]:port notation for IPv6 Määratud aadressiga sidumine ning sellelt kuulamine. IPv6 jaoks kasuta vormingut [host]:port @@ -1707,10 +930,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications See on test-versioon - kasutamine omal riisikol - ära kasuta mining'uks ega kaupmeeste programmides - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Hoiatus: toimus wallet.dat faili andmete päästmine! Originaal wallet.dat nimetati kaustas %s ümber wallet.{ajatempel}.bak'iks, jäägi või tehingute ebakõlade puhul tuleks teha backup'ist taastamine. - Block creation options: Blokeeri loomise valikud: @@ -1767,26 +986,10 @@ (default: %u) (vaikimisi: %u) - - Cannot resolve -whitebind address: '%s' - Tundmatu -whitebind aadress: '%s' - Information Informatsioon - - Invalid amount for -maxtxfee=<amount>: '%s' - -maxtxfee=<amount> jaoks vigane kogus: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - -minrelaytxfee=<amount> jaoks vigane kogus: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - -mintxfee=<amount> jaoks vigane kogus: '%s' - RPC server options: RPC serveri valikud: @@ -1823,10 +1026,6 @@ Warning Hoiatus - - wallet.dat corrupt, salvage failed - wallet.dat fail on katki, päästmine ebaõnnestus - Password for JSON-RPC connections JSON-RPC ühenduste salasõna @@ -1835,10 +1034,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) Käivita käsklus, kui parim plokk muutub (käskluse %s asendatakse ploki hash'iga) - - This help message - Käesolev abitekst - Allow DNS lookups for -addnode, -seednode and -connect -addnode, -seednode ja -connect tohivad kasutada DNS lookup'i @@ -1847,18 +1042,10 @@ Loading addresses... Aadresside laadimine... - - Error loading wallet.dat: Wallet corrupted - Viga wallet.dat käivitamisel. Vigane rahakkott - (default: %s) (vaikimisi: %s) - - Error loading wallet.dat - Viga wallet.dat käivitamisel - Invalid -proxy address: '%s' Vigane -proxi aadress: '%s' @@ -1867,18 +1054,6 @@ Unknown network specified in -onlynet: '%s' Kirjeldatud tundmatu võrgustik -onlynet'is: '%s' - - Cannot resolve -bind address: '%s' - Tundmatu -bind aadress: '%s' - - - Cannot resolve -externalip address: '%s' - Tundmatu -externalip aadress: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - -paytxfee=<amount> jaoks vigane kogus: '%s' - Insufficient funds Liiga suur summa diff --git a/src/qt/locale/bitcoin_eu_ES.ts b/src/qt/locale/bitcoin_eu_ES.ts index ca6b6489d17c8..cbe246f443814 100644 --- a/src/qt/locale/bitcoin_eu_ES.ts +++ b/src/qt/locale/bitcoin_eu_ES.ts @@ -25,10 +25,6 @@ C&lose &Itxi - - &Copy Address - &Kopiatu helbidea - Delete the currently selected address from the list Ezabatu aukeratutako helbideak listatik @@ -45,73 +41,6 @@ &Delete &Ezabatu - - Choose the address to send coins to - Aukeratu helbidea txanponak bidaltzeko - - - Choose the address to receive coins with - Aukeratu helbidea txanponak jasotzeko - - - C&hoose - &Aukeratu - - - Sending addresses - Helbideak bidaltzen - - - Receiving addresses - Helbideak jasotzen - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Hauek dira zure Bitcoin helbideak dirua bidaltzeko. Beti egiaztatu diru-kantitatea eta jasotzeko helbidea bidali baino lehen. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Hauek dira zure Bitcoin helbideak dirua jasotzeko. Gomendagarria da erabiltzea jasotzeko helbide berri bat operazio bakoitzeko. - - - Copy &Label - Kopiatu &Etiketa - - - &Edit - &Editatu - - - Export Address List - Esportatu helbide lista - - - Comma separated file (*.csv) - Komaz bereizitako artxiboa (*.csv) - - - Exporting Failed - Esportatua okerra - - - There was an error trying to save the address list to %1. Please try again. - Errakuntza bat egon da gordetzen %1 helbide listan. Mesedez, saiatu berriro. - - - - AddressTableModel - - Label - Etiketa - - - Address - Helbidea - - - (no label) - (etiketarik ez) - AskPassphraseDialog @@ -131,79 +60,7 @@ Repeat new passphrase Errepikatu pasahitz berria - - Encrypt wallet - Enkriptatu zorroa - - - This operation needs your wallet passphrase to unlock the wallet. - Eragiketa honek zorroaren pasahitza behar du zorroa desblokeatzeko. - - - Unlock wallet - Desblokeatu zorroa - - - This operation needs your wallet passphrase to decrypt the wallet. - Eragiketa honek zure zorroaren pasahitza behar du, zorroa desenkriptatzeko. - - - Decrypt wallet - Desenkriptatu zorroa - - - Change passphrase - Aldatu pasahitza - - - Confirm wallet encryption - Berretsi zorroaren enkriptazioa - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Abisua: Zuk enkriptatzen baduzu zure diruzorroa eta zure pasahitza galtzen baduzu, <b>BITCOIN GUZTIAK GALDUKO DITUZU</b>! - - - Are you sure you wish to encrypt your wallet? - Seguru zaude nahi duzula zure diruzorroa enkriptatu? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Bitcoin Core orain itxiko da enkriptazio prozezua amaitzeko. Gogoratu enkriptatzean zure diruzorroa ez duzula guztiz babesten zure Bitcoinak lapurretatik infektatzen zure ordenagailua Malwareekin. - - - 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. - GARRANTZITSUA: Aurreko seguritate-kopiak ordeztuko dire berriekin, enkriptatutak. Segurtasun arrazoigaitik, aurreko kopiak ezin dira erabili hasiko zarenean zure diruzorro enkriptatu berriarekin. - - - Wallet encrypted - Zorroa enkriptatuta - - - Wallet encryption failed - Zorroaren enkriptazioak huts egin du - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Zorroaren enkriptazioak huts egin du barne-errore baten ondorioz. Zure zorroa ez da enkriptatu. - - - The supplied passphrases do not match. - Eman dituzun pasahitzak ez datoz bat. - - - Wallet unlock failed - Zorroaren desblokeoak huts egin du - - - The passphrase entered for the wallet decryption was incorrect. - Zorroa desenkriptatzeko sartutako pasahitza okerra da. - - - Wallet decryption failed - Zorroaren desenkriptazioak huts egin du - - + BanTableModel @@ -298,9 +155,6 @@ Zorroa <b>enkriptatuta</b> eta <b>blokeatuta</b> dago une honetan - - ClientModel - CoinControlDialog @@ -315,18 +169,6 @@ Date Data - - Copy address - Kopiatu helbidea - - - Copy label - Kopiatu etiketa - - - (no label) - (etiketarik ez) - EditAddressDialog @@ -342,34 +184,6 @@ &Address &Helbidea - - New receiving address - Jasotzeko helbide berria - - - New sending address - Bidaltzeko helbide berria - - - Edit receiving address - Editatu jasotzeko helbidea - - - Edit sending address - Editatu bidaltzeko helbidea - - - The entered address "%1" is already in the address book. - Sartu berri den helbidea, "%1", helbide-liburuan dago jadanik. - - - Could not unlock wallet. - Ezin desblokeatu zorroa. - - - New key generation failed. - Gako berriaren sorrerak huts egin du. - FreespaceChecker @@ -397,9 +211,6 @@ Inprimakia - - PaymentServer - PeerTableModel @@ -410,9 +221,6 @@ Kopurua - - QRImageWidget - RPCConsole @@ -430,10 +238,6 @@ &Message: Mezua - - Copy label - Kopiatu etiketa - ReceiveRequestDialog @@ -441,45 +245,6 @@ Copy &Address &Kopiatu helbidea - - Address - Helbidea - - - Amount - Kopurua - - - Label - Etiketa - - - Message - Mezua - - - - RecentRequestsTableModel - - Date - Data - - - Label - Etiketa - - - Message - Mezua - - - Amount - Kopurua - - - (no label) - (etiketarik ez) - SendCoinsDialog @@ -503,18 +268,6 @@ Confirm the send action Berretsi bidaltzeko ekintza - - Confirm send coins - Berretsi txanponak bidaltzea - - - The amount to pay must be larger than 0. - Ordaintzeko kopurua 0 baino handiagoa izan behar du. - - - (no label) - (etiketarik ez) - SendCoinsEntry @@ -526,10 +279,6 @@ Pay &To: Ordaindu &honi: - - Enter a label for this address to add it to your address book - Sartu etiketa bat helbide honetarako, eta gehitu zure helbide-liburuan - &Label: &Etiketa: @@ -583,248 +332,22 @@ TrafficGraphWidget - - TransactionDesc - - Open until %1 - Zabalik %1 arte - - - %1/unconfirmed - %1/konfirmatu gabe - - - %1 confirmations - %1 konfirmazioak - - - Date - Data - - - Message - Mezua - - - Transaction - Transakzioaren - - - Amount - Kopurua - - - , has not been successfully broadcast yet - , ez da arrakastaz emititu oraindik - - - unknown - ezezaguna - - TransactionDescDialog - - Transaction details - Transakzioaren xehetasunak - This pane shows a detailed description of the transaction Panel honek transakzioaren deskribapen xehea erakusten du - - TransactionTableModel - - Date - Data - - - Type - Mota - - - Open until %1 - Zabalik %1 arte - - - Confirmed (%1 confirmations) - Konfirmatuta (%1 konfirmazio) - - - This block was not received by any other nodes and will probably not be accepted! - Bloke hau ez du beste inongo nodorik jaso, eta seguruenik ez da onartuko! - - - Generated but not accepted - Sortua, baina ez onartua - - - Label - Etiketa - - - Received with - Jasota honekin: - - - Sent to - Hona bidalia: - - - Payment to yourself - Ordainketa zeure buruari - - - Mined - Bildua - - - (n/a) - (n/a) - - - Transaction status. Hover over this field to show number of confirmations. - Transakzioaren egoera. Pasatu sagua gainetik konfirmazio kopurua ikusteko. - - - Date and time that the transaction was received. - Transakzioa jasotako data eta ordua. - - - Type of transaction. - Transakzio mota. - - - Amount removed from or added to balance. - Saldoan kendu edo gehitutako kopurua. - - - - TransactionView - - All - Denak - - - Today - Gaur - - - This week - Aste honetan - - - This month - Hil honetan - - - Last month - Azken hilean - - - This year - Aurten - - - Range... - Muga... - - - Received with - Jasota honekin: - - - Sent to - Hona bidalia: - - - To yourself - Zeure buruari - - - Mined - Bildua - - - Other - Beste - - - Enter address or label to search - Sartu bilatzeko helbide edo etiketa - - - Min amount - Kopuru minimoa - - - Copy address - Kopiatu helbidea - - - Copy label - Kopiatu etiketa - - - Exporting Failed - Esportatua okerra - - - Comma separated file (*.csv) - Komaz bereizitako artxiboa (*.csv) - - - Date - Data - - - Type - Mota - - - Label - Etiketa - - - Address - Helbidea - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - Send Coins - Bidali txanponak - - - - WalletView - - &Export - &Esportatu - - - Export the data in the current tab to a file - Esportatu datuak uneko fitxategian - - bitcoin-core Options: Aukerak - - This help message - Laguntza mezu hau - Rescanning... Birbilatzen... diff --git a/src/qt/locale/bitcoin_fa.ts b/src/qt/locale/bitcoin_fa.ts index 02c216765ce83..5bebb35822c23 100644 --- a/src/qt/locale/bitcoin_fa.ts +++ b/src/qt/locale/bitcoin_fa.ts @@ -15,27 +15,23 @@ Copy the currently selected address to the system clipboard - کپی نشانی انتخاب شده به حافظهٔ سیستم + کپی نشانی انتخاب شده کنونی به حافظه‌ی سیستم &Copy - &رونوشت + &کپی C&lose &بستن - - &Copy Address - &کپی نشانی - Delete the currently selected address from the list - حذف نشانی انتخاب‌شده از لیست + حذف نشانی انتخاب‌شده کنونی از لیست Export the data in the current tab to a file - خروجی گرفتن داده‌های برگهٔ فعلی به یک پرونده + خروجی گرفتن داده‌های برگه‌ی فعلی به یک فایل &Export @@ -45,69 +41,6 @@ &Delete &حذف - - Choose the address to send coins to - آدرس مورد نظر برای ارسال کوین ها را انتخاب کنید - - - Choose the address to receive coins with - آدرس موردنظر برای دریافت کوین ها را انتخاب کنید. - - - Sending addresses - آدرس های ارسال کننده - - - Receiving addresses - آدرس های دریافت کننده - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - این‌ها نشانی‌های بیت‌کوین شما برای ارسال وجود هستند. همیشه قبل از ارسال سکه‌ها، نشانی دریافت‌کننده و مقدار ارسالی را بررسی کنید. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - این‌ها نشانی‌های بیت‌کوین شما برای دریافت وجوه هستند. توصیه می‌شود یک نشانی دریافت جدید برای هر تبادل استفاده کنید. - - - Copy &Label - کپی و برچسب‌&گذاری - - - &Edit - &ویرایش - - - Export Address List - استخراج لیست آدرس - - - Comma separated file (*.csv) - پروندهٔ نوع CSV جداشونده با کاما (*.csv) - - - Exporting Failed - استخراج انجام نشد - - - There was an error trying to save the address list to %1. Please try again. - خطایی هنگام تلاش برای ذخیرهٔ لیست آدرس ها در %1 رخ داد. - - - - AddressTableModel - - Label - برچسب - - - Address - آدرس - - - (no label) - (بدون برچسب) - AskPassphraseDialog @@ -127,97 +60,13 @@ Repeat new passphrase تکرار گذرواژهٔ جدید - - Encrypt wallet - رمزنگاری کیف پول - - - This operation needs your wallet passphrase to unlock the wallet. - انجام این عملیات نیازمند گذرواژهٔ کیف پول شما برای باز کردن قفل آن است. - - - Unlock wallet - باز کردن قفل کیف پول - - - This operation needs your wallet passphrase to decrypt the wallet. - انجام این عملیات نیازمند گذرواژهٔ کیف پول شما برای رمزگشایی کردن آن است. - - - Decrypt wallet - رمزگشایی کیف پول - - - Change passphrase - تغییر گذرواژه - - - Confirm wallet encryption - تأیید رمزنگاری کیف پول - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - هشدار: اگر کیف پول خود را رمزنگاری کنید و گذرواژه را فراموش کنید، <b>تمام دارایی بیت‌کوین خود را از دست خواهید داد</b>! - - - Are you sure you wish to encrypt your wallet? - آیا مطمئن هستید که می‌خواهید کیف پول خود را رمزنگاری کنید؟ - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - هسته بیت‌کوین هم اکنون بسته می‌شود تا فرایند رمزگذاری را تمام کند. به خاطر داشته باشید که رمزگذاری کردن کیف پول‌تان نمی‌تواند به طور کامل بیت‌کوین‌های شما را در برابر دزدیده شدن توسط بدافزارهایی که رایانه‌ی شما را آلوده می‌کنند، محافظت نماید. - - - 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. - مهم: هر نسخهٔ پشتیبانی که تا کنون از کیف پول خود تهیه کرده‌اید، باید با کیف پول رمزنگاری شدهٔ جدید جایگزین شود. به دلایل امنیتی، پروندهٔ قدیمی کیف پول بدون رمزنگاری، تا زمانی که از کیف پول رمزنگاری‌شدهٔ جدید استفاده نکنید، غیرقابل استفاده خواهد بود. - - - Warning: The Caps Lock key is on! - هشدار: کلید Caps Lock روشن است! - - - Wallet encrypted - کیف پول رمزنگاری شد - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - رمز جدید کیف پول خود را وارد کنید.<br/>از رمز عبوری استفاده کنید که<b> حداقل 10 کاراکتر تصادفی </b> و یا <b> حداقل 8 حرف داشته باشد.</b> - - - Enter the old passphrase and new passphrase to the wallet. - رمز عبور قدیمی و رمز عبور جدید کیف پول خود را وارد گنید. - - - Wallet encryption failed - رمزنگاری کیف پول با شکست مواجه شد - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - رمزنگاری کیف پول بنا به یک خطای داخلی با شکست مواجه شد. کیف پول شما رمزنگاری نشد. - - - The supplied passphrases do not match. - گذرواژه‌های داده شده با هم تطابق ندارند. - - - Wallet unlock failed - بازگشایی قفل کیف‌پول با شکست مواجه شد - - - The passphrase entered for the wallet decryption was incorrect. - گذرواژهٔ وارد شده برای رمزگشایی کیف پول نادرست بود. - - - Wallet decryption failed - رمزگشایی ناموفق کیف پول - - - Wallet passphrase was successfully changed. - گذرواژهٔ کیف پول با موفقیت عوض شد. - BanTableModel + + IP/Netmask + آی‌پی/نت‌ماسک + BitcoinGUI @@ -257,6 +106,10 @@ Quit application خروج از برنامه + + &About %1 + &حدود%1 + About &Qt دربارهٔ &کیوت @@ -293,10 +146,6 @@ Open &URI... باز کردن &آدرس - - Importing blocks from disk... - دریافت بلوک‌ها از دیسک... - Reindexing blocks on disk... بازنشانی بلوک‌ها روی دیسک... @@ -341,10 +190,6 @@ &Receive &دریافت - - Show information about Bitcoin Core - نمایش اطلاعات در مورد بیت‌کوین - &Show / Hide &نمایش/ عدم نمایش @@ -381,14 +226,6 @@ Tabs toolbar نوارابزار برگه‌ها - - Bitcoin Core - هسته Bitcoin - - - &About Bitcoin Core - درباره هسته ی بیت کوین - Show the list of used sending addresses and labels نمایش لیست آدرس های ارسال و لیبل ها @@ -461,6 +298,36 @@ Catching up... به‌روز رسانی... + + Date: %1 + + تاریخ: %1 + + + + Amount: %1 + + مقدار: %1 + + + + Type: %1 + + نوع: %1 + + + + Label: %1 + + برچسب: %1 + + + + Address: %1 + + نشانی: %1 + + Sent transaction تراکنش ارسال شد @@ -478,13 +345,6 @@ کیف پول <b>رمزنگاری شده</b> است و هم‌اکنون <b>قفل</b> است - - ClientModel - - Network Alert - پیام شبکه - - CoinControlDialog @@ -519,6 +379,10 @@ Change: پول خورد: + + (un)select all + (لغو)انتخاب همه + Tree mode مدل درختی @@ -555,78 +419,6 @@ Priority اولویت - - Copy address - کپی نشانی - - - Copy label - کپی برچسب - - - Copy amount - کپی مقدار - - - Copy transaction ID - کپی شناسهٔ تراکنش - - - highest - بیشترین - - - higher - بیشتر - - - high - زیاد - - - medium-high - متوسط متمایل به زیاد - - - medium - متوسط - - - low-medium - متوسط متمایل به کم - - - low - کم - - - lower - کمتر - - - lowest - کمترین - - - none - هیچکدام - - - yes - بله - - - no - خیر - - - (no label) - (بدون برچسب) - - - (change) - (تغییر) - EditAddressDialog @@ -642,38 +434,6 @@ &Address &نشانی - - New receiving address - نشانی دریافتی جدید - - - New sending address - نشانی ارسالی جدید - - - Edit receiving address - ویرایش نشانی دریافتی - - - Edit sending address - ویرایش نشانی ارسالی - - - The entered address "%1" is already in the address book. - نشانی وارد شده «%1» در حال حاضر در دفترچه وجود دارد. - - - The entered address "%1" is not a valid Bitcoin address. - نشانی وارد شده «%1» یک نشانی معتبر بیت‌کوین نیست. - - - Could not unlock wallet. - نمی‌توان کیف پول را رمزگشایی کرد. - - - New key generation failed. - ایجاد کلید جدید با شکست مواجه شد. - FreespaceChecker @@ -700,17 +460,13 @@ HelpMessageDialog - - Bitcoin Core - هسته Bitcoin - version نسخه - About Bitcoin Core - درباره هسته ی بیت کوین + About %1 + درباره %1 Command-line options @@ -732,12 +488,8 @@ خوش‌آمدید - Welcome to Bitcoin Core. - به هسته بیت کوین خوش آمدید. - - - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - از آنجایی که این اولین اجرای برنامه است، شما می‌توانید مسیر ذخیرهٔ داده‌ها را انتخاب کنید. + Welcome to %1. + به %1 خوش‌آمدید. Use the default data directory @@ -747,10 +499,6 @@ Use a custom data directory: استفاده از یک مسیر سفارشی: - - Bitcoin Core - هسته Bitcoin - Error خطا @@ -773,6 +521,10 @@ &Main &عمومی + + Accept connections from outside + پذیرش اتصالات از بیرون + Reset all client options to default. بازنشانی تمام تنظیمات به پیش‌فرض. @@ -813,6 +565,18 @@ Port of the proxy (e.g. 9050) درگاه پراکسی (مثال 9050) + + IPv4 + آی‌پی نسخه 4 + + + IPv6 + آی‌پی نسخه 6 + + + Tor + تور + &Window &پنجره @@ -926,40 +690,29 @@ - PaymentServer - - URI handling - مدیریت URI - - - Payment request rejected - درخواست پرداخت رد شد. - + PeerTableModel + + + QObject - Payment request error - خطای درخواست پرداخت + Amount + مبلغ - Cannot start bitcoin: click-to-pay handler - نمی‌توان بیت‌کوین را اجرا کرد: کنترل‌کنندهٔ کلیک-و-پرداخت + %1 d + %1 روز - Payment request expired. - درخواست پرداخت منقضی شد. + %1 h + %1 ساعت - Invalid payment request. - درخواست پرداخت نامعتبر + %1 m + %1 دقیقه - - - PeerTableModel - - - QObject - Amount - مبلغ + %1 s + %1 ثانیه None @@ -969,14 +722,11 @@ N/A ناموجود - - - QRImageWidget - Save QR Code - ذخیرهٔ کد QR + %1 ms + %1 میلیونم ثانیه - + RPCConsole @@ -999,6 +749,10 @@ Debug window پنجرهٔ اشکالزدایی + + General + عمومی + Startup time زمان آغاز به کار @@ -1023,6 +777,10 @@ Current number of blocks تعداد فعلی بلوک‌ها + + Memory usage + مصرف حافظه + Received دریافتی @@ -1039,6 +797,10 @@ Services سرویس ها + + Last Receive + آخرین دریافتی + Last block time زمان آخرین بلوک @@ -1056,8 +818,8 @@ جمع کل: - Build date - ساخت تاریخ + In: + در: Debug log file @@ -1067,10 +829,6 @@ Clear console پاکسازی کنسول - - Welcome to the Bitcoin Core RPC console. - به کنسول RPC هسته بیت کوین خوش آمدید. - Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. دکمه‌های بالا و پایین برای پیمایش تاریخچه و <b>Ctrl-L</b> برای پاک کردن صفحه. @@ -1079,6 +837,18 @@ Type <b>help</b> for an overview of available commands. برای نمایش یک مرور کلی از دستورات ممکن، عبارت <b>help</b> را بنویسید. + + never + هرگز + + + Yes + بله + + + No + خیر + Unknown ناشناخته @@ -1098,6 +868,10 @@ &Message: پیام: + + Clear + پاک‌کردن + Show نمایش @@ -1106,14 +880,6 @@ Remove حذف کردن - - Copy label - کپی برچسب - - - Copy amount - کپی مقدار - ReceiveRequestDialog @@ -1125,95 +891,56 @@ Copy &Address &کپی نشانی + + + SendCoinsDialog - Address - نشانی + Send Coins + ارسال سکه - Amount - مبلغ + Insufficient funds! + بود جه نا کافی - Label - برچسب + Quantity: + تعداد: - Message - پیام + Bytes: + بایت ها: - Resulting URI too long, try to reduce the text for label / message. - URL ایجاد شده خیلی طولانی است. سعی کنید طول برچسب و یا پیام را کمتر کنید. + Amount: + مبلغ: - Error encoding URI into QR Code. - خطا در تبدیل نشانی اینترنتی به صورت کد QR. + Priority: + اولویت: - - - RecentRequestsTableModel - Date - تاریخ + Fee: + هزینه: - Label - برچسب + After Fee: + هزینه ی پسین: - Message - پیام + Change: + پول خورد: - Amount - مبلغ - - - (no label) - (بدون برچسب) - - - - SendCoinsDialog - - Send Coins - ارسال سکه - - - Insufficient funds! - بود جه نا کافی - - - Quantity: - تعداد: - - - Bytes: - بایت ها: - - - Amount: - مبلغ: - - - Priority: - اولویت: - - - Fee: - هزینه: + Transaction Fee: + هزینهٔ تراکنش: - After Fee: - هزینه ی پسین: + Hide + پنهان کردن - Change: - پول خورد: - - - Transaction Fee: - هزینهٔ تراکنش: + normal + نرمال fast @@ -1243,43 +970,7 @@ S&end &ارسال - - Confirm send coins - ارسال سکه را تأیید کنید - - - Copy amount - کپی مقدار - - - or - یا - - - The amount to pay must be larger than 0. - مبلغ پرداخت باید بیشتر از ۰ باشد. - - - The amount exceeds your balance. - میزان پرداخت از تراز شما بیشتر است. - - - The total exceeds your balance when the %1 transaction fee is included. - با احتساب هزینهٔ %1 برای هر تراکنش، مجموع میزان پرداختی از مبلغ تراز شما بیشتر می‌شود. - - - Payment request expired. - درخواست پرداخت منقضی شد. - - - (no label) - (بدون برچسب) - - - Are you sure you want to send? - آیا مطمئن هستید که می خواهید ارسال کنید؟ - - + SendCoinsEntry @@ -1290,10 +981,6 @@ Pay &To: پرداخ&ت به: - - Enter a label for this address to add it to your address book - برای این نشانی یک برچسب وارد کنید تا در دفترچهٔ آدرس ذخیره شود - &Label: &برچسب: @@ -1334,7 +1021,11 @@ Pay To: پرداخت به: - + + Memo: + یادداشت: + + ShutdownWindow @@ -1416,69 +1107,9 @@ Reset all verify message fields بازنشانی تمام فیلدهای پیام - - Click "Sign Message" to generate signature - برای ایجاد یک امضای جدید روی «امضای پیام» کلیک کنید - - - The entered address is invalid. - نشانی وارد شده نامعتبر است. - - - Please check the address and try again. - لطفاً نشانی را بررسی کنید و دوباره تلاش کنید. - - - The entered address does not refer to a key. - نشانی وارد شده به هیچ کلیدی اشاره نمی‌کند. - - - Wallet unlock was cancelled. - عملیات باز کرن قفل کیف پول لغو شد. - - - Private key for the entered address is not available. - کلید خصوصی برای نشانی وارد شده در دسترس نیست. - - - Message signing failed. - امضای پیام با شکست مواجه شد. - - - Message signed. - پیام امضا شد. - - - The signature could not be decoded. - امضا نمی‌تواند کدگشایی شود. - - - Please check the signature and try again. - لطفاً امضا را بررسی نموده و دوباره تلاش کنید. - - - The signature did not match the message digest. - امضا با خلاصهٔ پیام مطابقت ندارد. - - - Message verification failed. - شناسایی پیام با شکست مواجه شد. - - - Message verified. - پیام شناسایی شد. - SplashScreen - - Bitcoin Core - هسته Bitcoin - - - The Bitcoin Core developers - توسعه‌دهندگان هسته بیت‌کوین - [testnet] آزمایش شبکه @@ -1491,394 +1122,16 @@ کیلوبایت - - TransactionDesc - - Open until %1 - باز تا %1 - - - %1/offline - %1/آفلاین - - - %1/unconfirmed - %1/تأیید نشده - - - %1 confirmations - %1 تأییدیه - - - Status - وضعیت - - - , broadcast through %n node(s) - ، پخش از طریق %n گره - - - Date - تاریخ - - - Source - منبع - - - Generated - تولید شده - - - From - فرستنده - - - To - گیرنده - - - own address - آدرس شما - - - label - برچسب - - - Credit - بدهی - - - matures in %n more block(s) - بلوغ در %n بلوک دیگر - - - not accepted - پذیرفته نشد - - - Debit - اعتبار - - - Transaction fee - هزینهٔ تراکنش - - - Net amount - مبلغ خالص - - - Message - پیام - - - Comment - نظر - - - Transaction ID - شناسهٔ تراکنش - - - Debug information - اطلاعات اشکال‌زدایی - - - Transaction - تراکنش - - - Inputs - ورودی‌ها - - - Amount - مبلغ - - - true - درست - - - false - نادرست - - - , has not been successfully broadcast yet - ، هنوز با موفقیت ارسال نشده - - - Open for %n more block(s) - باز برای %n بلوک دیگر - - - unknown - ناشناس - - TransactionDescDialog - - Transaction details - جزئیات تراکنش - This pane shows a detailed description of the transaction این پانل شامل توصیف کاملی از جزئیات تراکنش است - - TransactionTableModel - - Date - تاریخ - - - Type - نوع - - - Open for %n more block(s) - باز برای %n بلوک دیگر - - - Open until %1 - باز شده تا %1 - - - Confirmed (%1 confirmations) - تأیید شده (%1 تأییدیه) - - - This block was not received by any other nodes and will probably not be accepted! - این بلوک از هیچ همتای دیگری دریافت نشده است و احتمال می‌رود پذیرفته نشود! - - - Generated but not accepted - تولید شده ولی قبول نشده - - - Offline - آفلاین - - - Label - برچسب - - - Unconfirmed - تایید نشده - - - Received with - دریافت‌شده با - - - Received from - دریافت‌شده از - - - Sent to - ارسال‌شده به - - - Payment to yourself - پر داخت به خودتان - - - Mined - استخراج‌شده - - - (n/a) - (ناموجود) - - - Transaction status. Hover over this field to show number of confirmations. - وضعیت تراکنش. نشانگر را روی این فیلد نگه دارید تا تعداد تأییدیه‌ها نشان داده شود. - - - Date and time that the transaction was received. - تاریخ و ساعت دریافت تراکنش. - - - Type of transaction. - نوع تراکنش. - - - Amount removed from or added to balance. - مبلغ کسر شده و یا اضافه شده به تراز. - - - - TransactionView - - All - همه - - - Today - امروز - - - This week - این هفته - - - This month - این ماه - - - Last month - ماه گذشته - - - This year - امسال - - - Range... - محدوده... - - - Received with - دریافت‌شده با - - - Sent to - ارسال به - - - To yourself - به خودتان - - - Mined - استخراج‌شده - - - Other - دیگر - - - Enter address or label to search - برای جست‌‌وجو نشانی یا برچسب را وارد کنید - - - Min amount - مبلغ حداقل - - - Copy address - کپی نشانی - - - Copy label - کپی برچسب - - - Copy amount - کپی مقدار - - - Copy transaction ID - کپی شناسهٔ تراکنش - - - Edit label - ویرایش برچسب - - - Show transaction details - نمایش جزئیات تراکنش - - - Exporting Failed - استخراج انجام نشد - - - Exporting Successful - استخراج موفق - - - Comma separated file (*.csv) - پروندهٔ نوع CSV جداشونده با کاما (*.csv) - - - Confirmed - تأیید شده - - - Date - تاریخ - - - Type - نوع - - - Label - برچسب - - - Address - نشانی - - - ID - شناسه - - - Range: - محدوده: - - - to - به - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - Send Coins - ارسال وجه - - - - WalletView - - &Export - &صدور - - - Export the data in the current tab to a file - داده ها نوارِ جاری را به فایل انتقال دهید - - - Backup Wallet - نسخهٔ پشتیبان کیف پول - - - Wallet Data (*.dat) - دادهٔ کیف پول (*.dat) - - - Backup Failed - خطا در پشتیبان‌گیری - - - Backup Successful - پشتیبان‌گیری موفق - - bitcoin-core @@ -1909,6 +1162,10 @@ Accept connections from outside (default: 1 if no -proxy or -connect) پذیرش اتصالات از بیرون (پیش فرض:1 بدون پراکسی یا اتصال) + + Bitcoin Core + هسته Bitcoin + Bind to given address and always listen on it. Use [host]:port notation for IPv6 مقید به نشانی داده شده باشید و همیشه از آن پیروی کنید. از نشانه گذاری استاندار IPv6 به صورت Host]:Port] استفاده کنید. @@ -1929,6 +1186,14 @@ Connect only to the specified node(s) تنها در گره (های) مشخص شده متصل شوید + + Connection options: + گزینه‌های اتصال: + + + Copyright (C) %i-%i + حق تألیف (C) %i-%i + Corrupted block database detected یک پایگاه داده ی بلوک خراب یافت شد @@ -1941,6 +1206,10 @@ Error initializing block database خطا در آماده سازی پایگاه داده ی بلوک + + Error loading %s + خطا در بارگیری %s + Error loading block database خطا در بارگذاری پایگاه داده ها @@ -1961,37 +1230,53 @@ Importing... در حال پیاده‌سازی... + + Loading banlist... + بارگذاری لیست‌سیاه... + + + Print this help message and exit + چاپ ایت پیام کمک و خروج + + + Print version and exit + چاپ نسخه و خروج + Verifying blocks... - در حال بازبینی بلوک ها... + در حال بازبینی بلوک‌ها... Verifying wallet... در حال بازبینی کیف پول... + + Wallet options: + گزینه‌های کیف پول: + Information اطلاعات - Invalid amount for -maxtxfee=<amount>: '%s' - میزان وجه اشتباه برای maxtxfee=<میزان وجه>: %s + Send trace/debug info to console instead of debug.log file + اطلاعات ردگیری/اشکال‌زدایی را به جای فایل لاگ اشکال‌زدایی به کنسول بفرستید - Invalid amount for -minrelaytxfee=<amount>: '%s' - میزان وجه اشتباه برای minrelaytxfee=<میزان وجه>: %s + Shrink debug.log file on client startup (default: 1 when no -debug) + فایل debug.log را در startup مشتری کوچک کن (پیش فرض:1 اگر اشکال زدایی روی نداد) - Invalid amount for -mintxfee=<amount>: '%s' - میزان وجه اشتباه برای mintxfee=<میزان وجه>: %s + Transaction amount too small + مقدار تراکنش بسیار کم است - Send trace/debug info to console instead of debug.log file - اطلاعات ردگیری/اشکال‌زدایی را به جای فایل لاگ اشکال‌زدایی به کنسول بفرستید + Transaction amounts must be positive + مقادیر تراکنش باید مثبت باشد - Shrink debug.log file on client startup (default: 1 when no -debug) - فایل debug.log را در startup مشتری کوچک کن (پیش فرض:1 اگر اشکال زدایی روی نداد) + Transaction too large + تراکنش بسیار بزرگ است Username for JSON-RPC connections @@ -2001,6 +1286,10 @@ Warning هشدار + + Warning: unknown new rules activated (versionbit %i) + هشدار: قوانین جدید ناشناخته‌ای فعال شده‌اند (نسخه‌بیت %i) + Password for JSON-RPC connections JSON-RPC عبارت عبور برای ارتباطات @@ -2009,10 +1298,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) زمانی که بهترین بلاک تغییر کرد، دستور را اجرا کن (%s در cmd با block hash جایگزین شده است) - - This help message - پیام کمکی - Allow DNS lookups for -addnode, -seednode and -connect به DNS اجازه بده تا برای addnode ، seednode و اتصال جستجو کند @@ -2021,14 +1306,6 @@ Loading addresses... بار گیری آدرس ها - - Error loading wallet.dat: Wallet corrupted - خطا در بارگیری wallet.dat: کیف پول خراب شده است - - - Error loading wallet.dat - خطا در بارگیری wallet.dat - Invalid -proxy address: '%s' آدرس پراکسی اشتباه %s @@ -2037,18 +1314,6 @@ Unknown network specified in -onlynet: '%s' شبکه مشخص شده غیرقابل شناسایی در onlynet: '%s' - - Cannot resolve -bind address: '%s' - آدرس قابل اتصال- شناسایی نیست %s - - - Cannot resolve -externalip address: '%s' - آدرس خارجی قابل اتصال- شناسایی نیست %s - - - Invalid amount for -paytxfee=<amount>: '%s' - میزان وجه اشتباه برای paytxfee=<میزان وجه>: %s - Insufficient funds بود جه نا کافی diff --git a/src/qt/locale/bitcoin_fa_IR.ts b/src/qt/locale/bitcoin_fa_IR.ts index 8bbfc724243bc..b329612ded011 100644 --- a/src/qt/locale/bitcoin_fa_IR.ts +++ b/src/qt/locale/bitcoin_fa_IR.ts @@ -21,10 +21,6 @@ C&lose بستن - - &Copy Address - کپی آدرس - Delete the currently selected address from the list حذف آدرس های انتخاب شده از لیست @@ -41,65 +37,6 @@ &Delete حذف - - Choose the address to send coins to - انتخاب آدرس جهت ارسال کوین ها به آن آدرس - - - Choose the address to receive coins with - انتخاب آدرس جهت دریافت کوین ها از آن آدرس - - - C&hoose - انتخاب - - - Sending addresses - ارسال آدرس ها - - - Receiving addresses - دریافت آدرس ها - - - Copy &Label - کپی برچسب - - - &Edit - ویرایش - - - Export Address List - صدور لیست آدرس - - - Comma separated file (*.csv) - فایل سی اس وی (*.csv) - - - Exporting Failed - صدور با شکست مواجه شد - - - There was an error trying to save the address list to %1. Please try again. - خطایی به هنگام ذخیره لیست آدرس در %1 رخ داده است. لطفا دوباره تلاش کنید. - - - - AddressTableModel - - Label - برچسب - - - Address - حساب - - - (no label) - (برچسب ندارد) - AskPassphraseDialog @@ -119,74 +56,6 @@ Repeat new passphrase رمز/پَس فرِیز را دوباره وارد کنید - - Encrypt wallet - wallet را رمزگذاری کنید - - - This operation needs your wallet passphrase to unlock the wallet. - برای انجام این عملکرد به رمز/پَس فرِیزِwallet نیاز است تا آن را از حالت قفل درآورد. - - - Unlock wallet - باز کردن قفل wallet - - - This operation needs your wallet passphrase to decrypt the wallet. - برای کشف رمز wallet، به رمز/پَس فرِیزِwallet نیاز است. - - - Decrypt wallet - کشف رمز wallet - - - Change passphrase - تغییر رمز/پَس فرِیز - - - Confirm wallet encryption - رمزگذاری wallet را تایید کنید - - - Warning: The Caps Lock key is on! - اخطار: کلید Caps Lock فعال است! - - - Wallet encrypted - تایید رمزگذاری - - - Enter the old passphrase and new passphrase to the wallet. - رمز قدیمی و جدید کیف پول را وارد کنید. - - - Wallet encryption failed - رمزگذاری تایید نشد - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - رمزگذاری به علت خطای داخلی تایید نشد. wallet شما رمزگذاری نشد - - - The supplied passphrases do not match. - رمزهای/پَس فرِیزهایِ وارد شده با هم تطابق ندارند - - - Wallet unlock failed - قفل wallet باز نشد - - - The passphrase entered for the wallet decryption was incorrect. - رمزهای/پَس فرِیزهایِ وارد شده wallet برای کشف رمز اشتباه است. - - - Wallet decryption failed - کشف رمز wallet انجام نشد - - - Wallet passphrase was successfully changed. - رمز عبور کیف پول با موفقیت تغییر کرد. - BanTableModel @@ -322,13 +191,6 @@ wallet رمزگذاری شد و در حال حاضر قفل است - - ClientModel - - Network Alert - هشدار شبکه - - CoinControlDialog @@ -347,22 +209,6 @@ Confirmed تایید شده - - Copy address - آدرس را کپی کنید - - - Copy label - برچسب را کپی کنید - - - Copy amount - میزان وجه کپی شود - - - (no label) - (برچسب ندارد) - EditAddressDialog @@ -378,39 +224,6 @@ &Address حساب& - - New receiving address - حساب دریافت کننده جدید - - - - New sending address - حساب ارسال کننده جدید - - - Edit receiving address - ویرایش حساب دریافت کننده - - - Edit sending address - ویرایش حساب ارسال کننده - - - The entered address "%1" is already in the address book. - حساب وارد شده «%1» از پیش در دفترچه حساب ها موجود است. - - - The entered address "%1" is not a valid Bitcoin address. - آدرس وارد شده "%1" یک آدرس صحیح برای bitcoin نسشت - - - Could not unlock wallet. - عدم توانیی برای قفل گشایی wallet - - - New key generation failed. - عدم توانیی در ایجاد کلید جدید - FreespaceChecker @@ -474,9 +287,6 @@ اطلاعات نمایش داده شده ممکن است روزآمد نباشد. wallet شما به صورت خودکار بعد از برقراری اتصال با شبکه bitcoin به روز می شود اما این فرایند هنوز تکمیل نشده است. - - PaymentServer - PeerTableModel @@ -487,9 +297,6 @@ میزان - - QRImageWidget - RPCConsole @@ -531,68 +338,13 @@ &Message: پیام: - - Copy label - برچسب را کپی کنید - - - Copy amount - میزان وجه کپی شود - - + ReceiveRequestDialog Copy &Address کپی آدرس - - Address - حساب - - - Amount - میزان - - - Label - برچسب - - - Message - پیام - - - Resulting URI too long, try to reduce the text for label / message. - متن وارد شده طولانی است، متنِ برچسب/پیام را کوتاه کنید - - - Error encoding URI into QR Code. - خطای تبدیل URI به کد QR - - - - RecentRequestsTableModel - - Date - تاریخ - - - Label - برچسب - - - Message - پیام - - - Amount - میزان - - - (no label) - (برچسب ندارد) - SendCoinsDialog @@ -624,27 +376,7 @@ S&end و ارسال - - Confirm send coins - تایید ارسال بیت کوین ها - - - Copy amount - میزان وجه کپی شود - - - The amount to pay must be larger than 0. - میزان پرداخت باید بیشتر از 0 باشد - - - The amount exceeds your balance. - مقدار مورد نظر از مانده حساب بیشتر است. - - - (no label) - (برچسب ندارد) - - + SendCoinsEntry @@ -655,10 +387,6 @@ Pay &To: پرداخت و به چه کسی - - Enter a label for this address to add it to your address book - یک برچسب برای این آدرس بنویسید تا به دفترچه آدرسهای شما اضافه شود - &Label: و برچسب @@ -690,10 +418,6 @@ ShutdownWindow - - Bitcoin Core is shutting down... - هسته بیت کوین در حال خاموش شدن است... - Do not shut down the computer until this window disappears. تا پیش از بسته شدن این پنجره کامپیوتر خود را خاموش نکنید. @@ -732,287 +456,16 @@ TrafficGraphWidget - - TransactionDesc - - Open until %1 - باز کن تا %1 - - - %1/unconfirmed - %1 / تایید نشده - - - %1 confirmations - %1 تایید - - - Date - تاریخ - - - label - برچسب - - - Message - پیام - - - Transaction ID - شناسه کاربری - - - Amount - میزان - - - , has not been successfully broadcast yet - ، هنوز با موفقیت ارسال نگردیده است - - - unknown - ناشناس - - TransactionDescDialog - - Transaction details - جزئیات تراکنش - This pane shows a detailed description of the transaction این بخش جزئیات تراکنش را نشان می دهد - - TransactionTableModel - - Date - تاریخ - - - Type - گونه - - - Open until %1 - باز کن تا %1 - - - Confirmed (%1 confirmations) - تایید شده (%1 تاییدها) - - - This block was not received by any other nodes and will probably not be accepted! - این block توسط گره های دیگری دریافت نشده است و ممکن است قبول نشود - - - Generated but not accepted - تولید شده اما قبول نشده است - - - Label - برچسب - - - Received with - دریافت با - - - Received from - دریافت شده از - - - Sent to - ارسال به - - - Payment to yourself - وجه برای شما - - - Mined - استخراج شده - - - (n/a) - خالی - - - Transaction status. Hover over this field to show number of confirmations. - وضعیت تراکنش. با اشاره به این بخش تعداد تاییدها نمایش داده می شود - - - Date and time that the transaction was received. - زمان و تاریخی که تراکنش دریافت شده است - - - Type of transaction. - نوع تراکنش - - - Amount removed from or added to balance. - میزان وجه کم شده یا اضافه شده به حساب - - - - TransactionView - - All - همه - - - Today - امروز - - - This week - این هفته - - - This month - این ماه - - - Last month - ماه گذشته - - - This year - این سال - - - Range... - حدود.. - - - Received with - دریافت با - - - Sent to - ارسال به - - - To yourself - به شما - - - Mined - استخراج شده - - - Other - دیگر - - - Enter address or label to search - آدرس یا برچسب را برای جستجو وارد کنید - - - Min amount - حداقل میزان وجه - - - Copy address - آدرس را کپی کنید - - - Copy label - برچسب را کپی کنید - - - Copy amount - میزان وجه کپی شود - - - Edit label - برچسب را ویرایش کنید - - - Exporting Failed - صدور با شکست مواجه شد - - - Exporting Successful - صدور با موفقیت انجام شد - - - Comma separated file (*.csv) - Comma separated file (*.csv) فایل جداگانه دستوری - - - Confirmed - تایید شده - - - Date - تاریخ - - - Type - گونه - - - Label - برچسب - - - Address - حساب - - - ID - شناسه کاربری - - - Range: - دامنه: - - - to - به - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - Send Coins - سکه های ارسالی - - - - WalletView - - &Export - صدور - - - Export the data in the current tab to a file - صدور داده نوار جاری به یک فایل - - - Backup Wallet - گرفتن نسخه پیشتیبان از Wallet - - - Wallet Data (*.dat) - داده های Wallet -(*.dat) - - - Backup Failed - عملیات گرفتن نسخه پیشتیبان انجام نشد - - bitcoin-core @@ -1035,18 +488,6 @@ The transaction amount is too small to send after the fee has been deducted مبلغ تراکنش کمتر از آن است که پس از کسر هزینه تراکنش قابل ارسال باشد - - Invalid amount for -maxtxfee=<amount>: '%s' - میزان اشتباه است for -maxtxfee=<amount>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - میزان اشتباه است for -minrelaytxfee=<amount>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - میزان اشتباه است for -mintxfee=<amount>: '%s' - RPC server options: گزینه های سرویس دهنده RPC: @@ -1071,22 +512,10 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) دستور را وقتی بهترین بلاک تغییر کرد اجرا کن (%s در دستور توسط block hash جایگزین شده است) - - This help message - این پیام راهنما - Loading addresses... لود شدن آدرسها.. - - Error loading wallet.dat: Wallet corrupted - خطا در هنگام لود شدن wallet.dat: Wallet corrupted - - - Error loading wallet.dat - خطا در هنگام لود شدن wallet.dat - Set minimum block size in bytes (default: %u) تنظیم کمینه اندازه بلاک بر حسب بایت (پیش فرض: %u) @@ -1103,10 +532,6 @@ Specify pid file (default: %s) فایل pid را مشخص کنید (پیش فرض: %s) - - Invalid amount for -paytxfee=<amount>: '%s' - میزان اشتباه است for -paytxfee=<amount>: '%s' - Insufficient funds وجوه ناکافی diff --git a/src/qt/locale/bitcoin_fi.ts b/src/qt/locale/bitcoin_fi.ts index 0fb6aebb9fe9a..c2226e9b985f2 100644 --- a/src/qt/locale/bitcoin_fi.ts +++ b/src/qt/locale/bitcoin_fi.ts @@ -25,10 +25,6 @@ C&lose S&ulje - - &Copy Address - &Kopioi osoite - Delete the currently selected address from the list Poista valittu osoite listalta @@ -45,73 +41,6 @@ &Delete &Poista - - Choose the address to send coins to - Valitse osoite johon kolikot lähetetään - - - Choose the address to receive coins with - Valitse osoite johon vastaanotetaan kolikoita - - - C&hoose - V&alitse - - - Sending addresses - Lähettävä osoite - - - Receiving addresses - Vastaanottava osoite - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Nämä ovat sinun Bitcoin osoitteita maksujen lähetykseen. Tarkista aina summa ja vastaanottajan osoite ennenkuin lähetät kolikkoja. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Nämä ovat sinun Bitcoin-osoitteesi suoritusten vastaanottamiseen. Suositellaan että annat uuden osoitteen kullekin transaktiolle. - - - Copy &Label - Kopioi &nimike - - - &Edit - &Muokkaa - - - Export Address List - Vie osoitekirja - - - Comma separated file (*.csv) - Comma separated file (*.csv) - - - Exporting Failed - Vienti epäonnistui - - - There was an error trying to save the address list to %1. Please try again. - Virhe tallentaessa osoitelistaa %1. Yritä uudelleen. - - - - AddressTableModel - - Label - Nimi - - - Address - Osoite - - - (no label) - (ei nimikettä) - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase Toista uusi tunnuslause - - Encrypt wallet - Salaa lompakko - - - This operation needs your wallet passphrase to unlock the wallet. - Tätä toimintoa varten sinun täytyy antaa lompakon tunnuslause sen avaamiseksi. - - - Unlock wallet - Avaa lompakko - - - This operation needs your wallet passphrase to decrypt the wallet. - Tätä toimintoa varten sinun täytyy antaa lompakon tunnuslause salauksen purkuun. - - - Decrypt wallet - Pura lompakon salaus - - - Change passphrase - Vaihda tunnuslause - - - Confirm wallet encryption - Vahvista lompakon salaus - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Varoitus: Jos salaat lompakkosi ja menetät tunnuslauseesi, <b>MENETÄT KAIKKI BITCOINISI</b>! - - - Are you sure you wish to encrypt your wallet? - Haluatko varmasti salata lompakkosi? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Bitcoin Core sammuu nyt viimeistelläkseen kryptaamisen. Muista että lompakon kryptaaminen ei voi täysin suojata bitcoinejasi varkaudelta malwaren saastuttamalla tietokoneella. - - - 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. - TÄRKEÄÄ: Kaikki vanhat lompakon varmuuskopiot pitäisi korvata uusilla suojatuilla varmuuskopioilla. Turvallisuussyistä edelliset varmuuskopiot muuttuvat turhiksi, kun aloitat suojatun lompakon käytön. - - - Warning: The Caps Lock key is on! - Varoitus: Caps Lock on käytössä! - - - Wallet encrypted - Lompakko salattu - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Anna salauslause lompakkoon. <br/>Ole hyvä ja käytä lausetta jossa on <b>kymmenen tai enemmän satunnaista merkkiä</b> tai <b>kahdeksan tai useampi sanaa</b>. - - - Enter the old passphrase and new passphrase to the wallet. - Syötä vanha ja uusi salasana lompakolle. - - - Wallet encryption failed - Lompakon salaus epäonnistui - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Lompakon salaaminen epäonnistui sisäisen virheen vuoksi. Lompakkoasi ei salattu. - - - The supplied passphrases do not match. - Annetut tunnuslauseet eivät täsmää. - - - Wallet unlock failed - Lompakon avaaminen epäonnistui. - - - The passphrase entered for the wallet decryption was incorrect. - Annettu tunnuslause oli väärä. - - - Wallet decryption failed - Lompakon salauksen purku epäonnistui. - - - Wallet passphrase was successfully changed. - Lompakon tunnuslause vaihdettiin onnistuneesti. - BanTableModel @@ -269,6 +110,10 @@ Quit application Sulje ohjelma + + &About %1 + &Tietoja %1 + About &Qt Tietoja &Qt @@ -305,14 +150,6 @@ Open &URI... Avaa &URI... - - Bitcoin Core client - Bitcoin Core ohjelma - - - Importing blocks from disk... - Tuodaan lohkoja levyltä - Reindexing blocks on disk... Ladataan lohkoindeksiä... @@ -357,10 +194,6 @@ &Receive &Vastaanota - - Show information about Bitcoin Core - Näytä tietoja Bitcoin Core:sta - &Show / Hide &Näytä / Piilota @@ -397,22 +230,10 @@ Tabs toolbar Välilehtipalkki - - Bitcoin Core - Bitcoin-ydin - Request payments (generates QR codes and bitcoin: URIs) Pyydä maksuja (Luo QR koodit ja bitcoin: URIt) - - &About Bitcoin Core - &Tietoja Bitcoin Core - - - Modify configuration options for Bitcoin Core - Muokkaa kokoonpanoasetuksia Bitcoin Corelle - Show the list of used sending addresses and labels Näytä lähettämiseen käytettyjen osoitteiden ja nimien lista @@ -429,10 +250,6 @@ &Command-line options &Komentorivin valinnat - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Näytä Bitcoin Core ohjeet saadaksesi listan mahdollisista Bitcoinin komentorivivalinnoista - %n active connection(s) to Bitcoin network %n aktiivinen yhteys Bitcoin-verkkoon%n aktiivista yhteyttä Bitcoin-verkkoon @@ -544,13 +361,6 @@ Lompakko on <b>salattu</b> ja tällä hetkellä <b>lukittuna</b> - - ClientModel - - Network Alert - Verkkohälytys - - CoinControlDialog @@ -629,150 +439,6 @@ Priority Prioriteetti - - Copy address - Kopioi osoite - - - Copy label - Kopioi nimi - - - Copy amount - Kopioi määrä - - - Copy transaction ID - Kopioi siirtotunnus - - - Lock unspent - Lukitse käyttämättömät - - - Unlock unspent - Avaa käyttämättömät - - - Copy quantity - Kopioi määrä - - - Copy fee - Kopioi palkkio - - - Copy after fee - Kopioi palkkion jälkeen - - - Copy bytes - Kopioi tavut - - - Copy priority - Kopioi prioriteetti - - - Copy dust - Kopioi tomu - - - Copy change - Kopioi vaihtoraha - - - highest - korkein - - - higher - korkeampi - - - high - korkea - - - medium-high - keski-korkea - - - medium - keskisuuri - - - low-medium - pieni-keskisuuri - - - low - pieni - - - lower - pienempi - - - lowest - pienin - - - (%1 locked) - (%1 lukittu) - - - none - ei mitään - - - This label turns red if the transaction size is greater than 1000 bytes. - Tämä nimi muuttuu punaiseksi mikäli rahansiirron koko on suurempi kuin 1000 tavua. - - - This label turns red if the priority is smaller than "medium". - Tämä nimi muuttuu punaiseksi mikäli prioriteetti on pienempi kuin "medium". - - - This label turns red if any recipient receives an amount smaller than %1. - Tämä nimike muuttuu punaiseksi mikäli mikä tahansa saaja vastaanottaa pienemmän määrän kuin %1. - - - Can vary +/- %1 satoshi(s) per input. - Saattaa vaihdella +/- %1 satoshia per syöte. - - - yes - kyllä - - - no - ei - - - This means a fee of at least %1 per kB is required. - Tämä tarkoittaa että vähintään %1 per kB palkkio on pakollinen. - - - Can vary +/- 1 byte per input. - Voi vaihdella +/- 1 tavu per syöte - - - Transactions with higher priority are more likely to get included into a block. - Rahansiirrot korkeammalla prioriteetilla sisällytetään varmemmin lohkoon. - - - (no label) - (ei nimeä) - - - change from %1 (%2) - Vaihda %1 (%2) - - - (change) - (vaihtoraha) - EditAddressDialog @@ -796,38 +462,6 @@ &Address &Osoite - - New receiving address - Uusi vastaanottava osoite - - - New sending address - Uusi lähettävä osoite - - - Edit receiving address - Muokkaa vastaanottajan osoitetta - - - Edit sending address - Muokkaa lähtevää osoitetta - - - The entered address "%1" is already in the address book. - Osoite "%1" on jo osoitekirjassa. - - - The entered address "%1" is not a valid Bitcoin address. - Antamasi osoite "%1" ei ole validi Bitcoin-osoite. - - - Could not unlock wallet. - Lompakkoa ei voitu avata. - - - New key generation failed. - Uuden avaimen luonti epäonnistui. - FreespaceChecker @@ -854,10 +488,6 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin-ydin - version versio @@ -866,10 +496,6 @@ (%1-bit) (%1-bit) - - About Bitcoin Core - Tietoja Bitcoin Core - Command-line options Komentorivi parametrit @@ -906,29 +532,13 @@ Show splash screen on startup (default: %u) Näytä aloitusruutu käynnistyksen yhteydessä (oletus: %u) - - Reset all settings changes made over the GUI - Nollaa kaikki graafisen käyttöliittymän kautta tehdyt muutokset - - + Intro Welcome Tervetuloa - - Welcome to Bitcoin Core. - Tervetuloa Bitcoin Core - - - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - Tämän on ensimmäinen kerta kun Bitcoin Core on käynnistetty joten voit valita data-hakemiston paikan. - - - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - Bitcoin Core lataa ja tallentaa kopion Bitcoinin lohkoketjusta. Vähintään %1GB dataa tullaan tallentamaan tähän hakemistoon ja tarve kasvaa ajan myötä. Lomakko tullaan myös tallentamaan tähän hakemistoon. - Use the default data directory Käytä oletuskansiota @@ -937,10 +547,6 @@ Use a custom data directory: Määritä oma kansio: - - Bitcoin Core - Bitcoin-ydin - Error: Specified data directory "%1" cannot be created. Virhe: Annettu datahakemistoa "%1" ei voida luoda. @@ -976,10 +582,6 @@ Select payment request file Valitse maksupyynnön tiedosto - - Select payment request file to open - Valitse maksypyynnön tiedosto avattavaksi - OptionsDialog @@ -1019,10 +621,6 @@ 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. Minimoi ikkuna ohjelman sulkemisen sijasta kun ikkuna suljetaan. Kun tämä asetus on käytössä, ohjelma suljetaan vain valittaessa valikosta Poistu. - - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - Käyttöliittymän kieli voidaan asettaa tässä. Tämä asetus tulee käyttöön vasta kun Bitcoin Core käynnistetään uudelleen. - 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 |. Ulkopuoliset URL-osoitteet (esim. block explorer,) jotka esiintyvät siirrot-välilehdellä valikossa. %s URL-osoitteessa korvataan siirtotunnuksella. Useampi URL-osoite on eroteltu pystyviivalla |. @@ -1047,14 +645,6 @@ &Network &Verkko - - Automatically start Bitcoin Core after logging in to the system. - Käynnistä Bitcoin Core automaattisesti järjestelmään kirjautumisen jälkeen. - - - &Start Bitcoin Core on system login - &Käynnistä Bitcoin Core järjestelmään kirjautuessa - (0 = auto, <0 = leave that many cores free) (0 = auto, <0 = jätä näin monta ydintä vapaaksi) @@ -1284,178 +874,68 @@ - PaymentServer + PeerTableModel - URI handling - URI käsittely + User Agent + Käyttöliittymä - Invalid payment address %1 - Virheellinen maksuosoite %1 + Node/Service + Noodi/Palvelu - Payment request rejected - Maksupyyntö hylätty + Ping Time + Vasteaika + + + QObject - Payment request network doesn't match client network. - Maksypyyntö verkossa ei täsmää asiakasohjelman verkkoon. + Amount + Määrä - Payment request is not initialized. - Maksupyyntöä ei ole alustettu. + Enter a Bitcoin address (e.g. %1) + Syötä Bitcoin-osoite (esim. %1) - Requested payment amount of %1 is too small (considered dust). - Maksupyyntö %1 on liian pieni (huomioidaan tomuna). + %1 d + %1 d - Payment request error - Maksupyyntövirhe + %1 h + %1 h - Cannot start bitcoin: click-to-pay handler - Ei voida käynnistää bitcoin: klikkaa-maksu käsittelijää + %1 m + %1 m - Payment request fetch URL is invalid: %1 - Maksupyynnön haku URL on virheellinen: %1 + %1 s + %1 s - URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - URIa ei voitu jäsentää! Tämä voi johtua kelvottomasta Bitcoin-osoitteesta tai virheellisistä URI parametreista. + None + Ei yhtään - Payment request file handling - Maksupyynnön tiedoston käsittely + N/A + Ei saatavilla - Payment request file cannot be read! This can be caused by an invalid payment request file. - Maksupyynnön tiedostoa ei voida lukea! Tämä voi aiheutua sopimattomasta maksupyyntötiedostosta. + %1 ms + %1 ms + + + RPCConsole - Payment request expired. - Maksupyyntö on vanhentunut. + Client name + Pääteohjelman nimi - Unverified payment requests to custom payment scripts are unsupported. - Varmistamattomia maksupyyntöjä kustomoituun maksupalveluun ei tueta. - - - Invalid payment request. - Epäkelpo maksupyyntö. - - - Refund from %1 - Maksupalautus %1:sta - - - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - Maksupyyntö %1 on liian suuri (%2 tavua, sallittu %3 tavua). - - - Error communicating with %1: %2 - Virhe kommunikoidessa %1n kanssa: %2 - - - Payment request cannot be parsed! - Maksupyyntöä ei voida jäsentää! - - - Bad response from server %1 - Huono vastaus palvelimelta %1 - - - Payment acknowledged - Rahansiirto tunnistettu - - - Network request error - Tietoverkon pyyntövirhe - - - - PeerTableModel - - User Agent - Käyttöliittymä - - - Node/Service - Noodi/Palvelu - - - Ping Time - Vasteaika - - - - QObject - - Amount - Määrä - - - Enter a Bitcoin address (e.g. %1) - Syötä Bitcoin-osoite (esim. %1) - - - %1 d - %1 d - - - %1 h - %1 h - - - %1 m - %1 m - - - %1 s - %1 s - - - None - Ei yhtään - - - N/A - Ei saatavilla - - - %1 ms - %1 ms - - - - QRImageWidget - - &Save Image... - &Tallenna kuva - - - &Copy Image - &Kopioi kuva - - - Save QR Code - Tallenna QR-koodi - - - PNG Image (*.png) - PNG kuva (*.png) - - - - RPCConsole - - Client name - Pääteohjelman nimi - - - N/A - Ei saatavilla + N/A + Ei saatavilla Client version @@ -1513,10 +993,6 @@ Memory usage Muistin käyttö - - Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. - Avaa Bitcoin Coren debug-loki tämänhetkisestä datahakemistosta. Tämä voi viedä muutaman sekunnin suurille lokitiedostoille. - Received Vastaanotetut @@ -1633,10 +1109,6 @@ Out: Ulos: - - Build date - Kääntöpäiväys - Debug log file Debug lokitiedosto @@ -1673,10 +1145,6 @@ &Unban Node &Poista solmukohdan esto - - Welcome to the Bitcoin Core RPC console. - Tervetuloa Bitcoin Coren RPC-konsoliin. - Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. Ylös- ja alas-nuolet selaavat historiaa ja <b>Ctrl-L</b> tyhjentää ruudun. @@ -1804,18 +1272,6 @@ Remove Poista - - Copy label - Kopioi nimi - - - Copy message - Kopioi viesti - - - Copy amount - Kopioi määrä - ReceiveRequestDialog @@ -1835,73 +1291,6 @@ &Save Image... &Tallenna kuva - - Request payment to %1 - Vastaanota maksu %1 - - - Payment information - Maksutiedot - - - URI - URI - - - Address - Osoite - - - Amount - Määrä - - - Label - Nimi - - - Message - Viesti - - - Resulting URI too long, try to reduce the text for label / message. - Tuloksen URI liian pitkä, yritä lyhentää otsikon tekstiä / viestiä. - - - Error encoding URI into QR Code. - Virhe käännettäessä URI:a QR-koodiksi. - - - - RecentRequestsTableModel - - Date - Aika - - - Label - Nimi - - - Message - Viesti - - - Amount - Määrä - - - (no label) - (ei nimeä) - - - (no message) - (ei viestiä) - - - (no amount) - (ei määrää) - SendCoinsDialog @@ -2013,14 +1402,6 @@ fast nopea - - Send as zero-fee transaction if possible - Lähetä siirtokuluttomana jos mahdollista - - - (confirmation may take longer) - (vahvistaminen voi viedä kauemmin) - Send to multiple recipients at once Lähetä usealla vastaanottajalle samanaikaisesti @@ -2053,118 +1434,6 @@ S&end &Lähetä - - Confirm send coins - Hyväksy Bitcoinien lähettäminen - - - %1 to %2 - %1 to %2 - - - Copy quantity - Kopioi määrä - - - Copy amount - Kopioi määrä - - - Copy fee - Kopioi palkkio - - - Copy after fee - Kopioi palkkion jälkeen - - - Copy bytes - Kopioi tavut - - - Copy priority - Kopioi prioriteetti - - - Copy change - Kopioi vaihtoraha - - - Total Amount %1 - Kokonaismäärä %1 - - - or - tai - - - The amount to pay must be larger than 0. - Maksettavan summan tulee olla suurempi kuin 0 Bitcoinia. - - - The amount exceeds your balance. - Määrä ylittää käytettävissä olevan saldon. - - - The total exceeds your balance when the %1 transaction fee is included. - Kokonaismäärä ylittää saldosi kun %1 maksukulu lisätään summaan. - - - Transaction creation failed! - Rahansiirron luonti epäonnistui! - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - Rahansiirto hylättiin! Tämä saattaa tapahtua jos lompakossa olevat kolikot on jo kulutettu, kuten jos käytät kopioita wallet.dat tiedostosta ja kolikot oli jos käytetty mutta ei merkattu täällä. - - - A fee higher than %1 is considered an absurdly high fee. - Rahansiirtokulua %1 ja sitä suurempia määriä pidetään järjenvastaisen korkeana kuluna. - - - Payment request expired. - Maksupyyntö on vanhentunut. - - - Pay only the required fee of %1 - Maksa vain vaadittu kulu kooltaan %1 - - - Estimated to begin confirmation within %n block(s). - Vahvistuminen alkaa arviolta %n lohkon päästä.Vahvistuminen alkaa arviolta %n lohkon päästä. - - - The recipient address is not valid. Please recheck. - Vastaanottajan osoite ei ole kelvollinen. Tarkistathan uudelleen. - - - Duplicate address found: addresses should only be used once each. - Duplikaattiosoite löytyi: kutakin osoitetta pitäisi käyttää vain kerran. - - - Warning: Invalid Bitcoin address - Varoitus: Virheellinen Bitcoin osoite - - - (no label) - (ei nimeä) - - - Warning: Unknown change address - Varoitus: Tuntematon vaihtorahan osoite - - - Copy dust - Kopioi tomu - - - Are you sure you want to send? - Haluatko varmasti lähettää? - - - added as transaction fee - lisätty rahansiirtomaksuna - SendCoinsEntry @@ -2176,10 +1445,6 @@ Pay &To: Maksun saaja: - - Enter a label for this address to add it to your address book - Anna nimi tälle osoitteelle, jos haluat lisätä sen osoitekirjaan - &Label: &Nimi: @@ -2247,10 +1512,6 @@ ShutdownWindow - - Bitcoin Core is shutting down... - Bitcoin core sulkeutuu... - Do not shut down the computer until this window disappears. Älä sammuta tietokonetta ennenkuin tämä ikkuna katoaa. @@ -2334,594 +1595,72 @@ Reset all verify message fields Tyhjennä kaikki varmista-viesti-kentät + + + SplashScreen - Click "Sign Message" to generate signature - Klikkaa "Allekirjoita Viesti luodaksesi allekirjoituksen + [testnet] + [testnet] + + + TrafficGraphWidget - The entered address is invalid. - Syötetty osoite on virheellinen. + KB/s + KB/s + + + TransactionDescDialog - Please check the address and try again. - Tarkista osoite ja yritä uudelleen. + This pane shows a detailed description of the transaction + Tämä ruutu näyttää yksityiskohtaisen tiedon rahansiirrosta + + + UnitDisplayStatusBarControl - The entered address does not refer to a key. - Syötetyn osoitteen avainta ei löydy. + Unit to show amounts in. Click to select another unit. + Yksikkö jossa määrät näytetään. Klikkaa valitaksesi toisen yksikön. + + + bitcoin-core - Wallet unlock was cancelled. - Lompakon avaaminen peruttiin. + Options: + Asetukset: - Private key for the entered address is not available. - Yksityistä avainta syötetylle osoitteelle ei ole saatavilla. + Specify data directory + Määritä data-hakemisto - Message signing failed. - Viestin allekirjoitus epäonnistui. + Connect to a node to retrieve peer addresses, and disconnect + Yhdistä noodiin hakeaksesi naapurien osoitteet ja katkaise yhteys - Message signed. - Viesti allekirjoitettu. + Specify your own public address + Määritä julkinen osoitteesi - The signature could not be decoded. - Allekirjoitusta ei pystytty tulkitsemaan. + Accept command line and JSON-RPC commands + Hyväksy merkkipohjaiset- ja JSON-RPC-käskyt - Please check the signature and try again. - Tarkista allekirjoitus ja yritä uudelleen. + If <category> is not supplied or if <category> = 1, output all debugging information. + Jos <category> on toimittamatta tai jos <category> = 1, tulosta kaikki debug-tieto. - The signature did not match the message digest. - Allekirjoitus ei täsmää viestin tiivisteeseen. + Prune configured below the minimum of %d MiB. Please use a higher number. + Karsinta konfiguroitu alle minimin %d MiB. Käytä surempaa numeroa. - Message verification failed. - Viestin varmistus epäonnistui. + Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node) + Karsinta: viime lompakon synkronisointi menee karsitun datan taakse. Sinun tarvitsee ajaa -reindex (lataa koko lohkoketju uudelleen tapauksessa jossa karsiva noodi) - Message verified. - Viesti varmistettu. - - - - SplashScreen - - Bitcoin Core - Bitcoin-ydin - - - The Bitcoin Core developers - Bitcoin Core kehittäjät - - - [testnet] - [testnet] - - - - TrafficGraphWidget - - KB/s - KB/s - - - - TransactionDesc - - Open until %1 - Avoinna %1 asti - - - conflicted - ristiriitainen - - - %1/offline - %1/offline - - - %1/unconfirmed - %1/vahvistamaton - - - %1 confirmations - %1 vahvistusta - - - Status - Tila - - - , broadcast through %n node(s) - lähetetty %n noodin läpilähetetty %n noodin läpi - - - Date - Päivämäärä - - - Source - Lähde - - - Generated - Generoitu - - - From - Lähettäjä - - - To - Saaja - - - own address - oma osoite - - - watch-only - vain katseltava - - - label - nimi - - - Credit - Credit - - - matures in %n more block(s) - kypsyy %n lohkon kuluttuakypsyy %n lohkon kuluttua - - - not accepted - ei hyväksytty - - - Debit - Debit - - - Total debit - Yhteensä debit - - - Total credit - Yhteensä credit - - - Transaction fee - Maksukulu - - - Net amount - Netto määrä - - - Message - Viesti - - - Comment - Viesti - - - Transaction ID - Siirtotunnus - - - Merchant - Kauppias - - - 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. - Luodut kolikot täytyy kypsyttää %1 lohkoa kunnes ne voidaan käyttää. Kun loit tämän lohkon, se lähetettiin verkkoon lisänä lohkoketjuun. Jos se epäonnistuu pääsemään ketjuun sen tila tulee muuttumaan "ei hyväksytty" ja sitä ei voida käyttää. Tämä voi ajoittain tapahtua kun toisen solmun lohko luodaan samanaikaisesti omasi kanssa. - - - Debug information - Debug tiedot - - - Transaction - Rahansiirto - - - Inputs - Sisääntulot - - - Amount - Määrä - - - true - tosi - - - false - epätosi - - - , has not been successfully broadcast yet - , ei ole vielä onnistuneesti lähetetty - - - Open for %n more block(s) - Avoinna %n lisälohkolleAvoinna %n lisälohkolle - - - unknown - tuntematon - - - - TransactionDescDialog - - Transaction details - Rahansiirron yksityiskohdat - - - This pane shows a detailed description of the transaction - Tämä ruutu näyttää yksityiskohtaisen tiedon rahansiirrosta - - - - TransactionTableModel - - Date - Päivämäärä - - - Type - Laatu - - - Immature (%1 confirmations, will be available after %2) - Epäkypsä (%1 varmistusta, saatavilla %2 jälkeen) - - - Open for %n more block(s) - Avoinna %n lisälohkolleAvoinna %n lisälohkolle - - - Open until %1 - Avoinna %1 asti - - - Confirmed (%1 confirmations) - Vahvistettu (%1 vahvistusta) - - - This block was not received by any other nodes and will probably not be accepted! - Tätä lohkoa ei vastaanotettu mistään muusta solmusta ja sitä ei mahdollisesti hyväksytä! - - - Generated but not accepted - Generoitu mutta ei hyväksytty - - - Offline - Offline - - - Label - Nimi - - - Unconfirmed - Varmistamaton - - - Confirming (%1 of %2 recommended confirmations) - Varmistetaan (%1 kehoitetusta %2 varmistuksesta) - - - Conflicted - Ristiriitainen - - - Received with - Vastaanotettu osoitteella - - - Received from - Vastaanotettu - - - Sent to - Saaja - - - Payment to yourself - Maksu itsellesi - - - Mined - Louhittu - - - watch-only - vain katseltava - - - (n/a) - (ei saatavilla) - - - Transaction status. Hover over this field to show number of confirmations. - Rahansiirron tila. Siirrä osoitin kentän päälle nähdäksesi vahvistusten lukumäärä. - - - Date and time that the transaction was received. - Rahansiirron vastaanottamisen päivämäärä ja aika. - - - Type of transaction. - Rahansiirron laatu. - - - Whether or not a watch-only address is involved in this transaction. - Onko rahansiirrossa mukana ainoastaan katseltava osoite vai ei. - - - User-defined intent/purpose of the transaction. - Käyttäjän määrittämä käyttötarkoitus rahansiirrolle. - - - Amount removed from or added to balance. - Saldoon lisätty tai siitä vähennetty määrä. - - - - TransactionView - - All - Kaikki - - - Today - Tänään - - - This week - Tällä viikolla - - - This month - Tässä kuussa - - - Last month - Viime kuussa - - - This year - Tänä vuonna - - - Range... - Alue... - - - Received with - Vastaanotettu osoitteella - - - Sent to - Saaja - - - To yourself - Itsellesi - - - Mined - Louhittu - - - Other - Muu - - - Enter address or label to search - Anna etsittävä osoite tai tunniste - - - Min amount - Minimimäärä - - - Copy address - Kopioi osoite - - - Copy label - Kopioi nimi - - - Copy amount - Kopioi määrä - - - Copy transaction ID - Kopioi siirtotunnus - - - Copy raw transaction - Kopioi rahansiirron raakavedos - - - Edit label - Muokkaa nimeä - - - Show transaction details - Näytä rahansiirron yksityiskohdat - - - Export Transaction History - Vie rahansiirtohistoria - - - Watch-only - Vain katseltava - - - Exporting Failed - Vienti epäonnistui - - - There was an error trying to save the transaction history to %1. - Rahansiirron historian tallentamisessa tapahtui virhe paikkaan %1. - - - Exporting Successful - Vienti onnistui - - - The transaction history was successfully saved to %1. - Rahansiirron historia tallennettiin onnistuneesti paikkaan %1. - - - Comma separated file (*.csv) - Comma separated file (*.csv) - - - Confirmed - Vahvistettu - - - Date - Aika - - - Type - Laatu - - - Label - Nimi - - - Address - Osoite - - - ID - ID - - - Range: - Alue: - - - to - kenelle - - - - UnitDisplayStatusBarControl - - Unit to show amounts in. Click to select another unit. - Yksikkö jossa määrät näytetään. Klikkaa valitaksesi toisen yksikön. - - - - WalletFrame - - No wallet has been loaded. - Lomakkoa ei ole ladattu. - - - - WalletModel - - Send Coins - Lähetä Bitcoineja - - - - WalletView - - &Export - &Vie... - - - Export the data in the current tab to a file - Vie auki olevan välilehden tiedot tiedostoon - - - Backup Wallet - Varmuuskopioi lompakko - - - Wallet Data (*.dat) - Lompakkodata (*.dat) - - - Backup Failed - Varmuuskopio epäonnistui - - - There was an error trying to save the wallet data to %1. - Lompakon tallennuksessa tapahtui virhe %1. - - - The wallet data was successfully saved to %1. - Lompakko tallennettiin onnistuneesti tiedostoon %1. - - - Backup Successful - Varmuuskopio Onnistui - - - - bitcoin-core - - Options: - Asetukset: - - - Specify data directory - Määritä data-hakemisto - - - Connect to a node to retrieve peer addresses, and disconnect - Yhdistä noodiin hakeaksesi naapurien osoitteet ja katkaise yhteys - - - Specify your own public address - Määritä julkinen osoitteesi - - - Accept command line and JSON-RPC commands - Hyväksy merkkipohjaiset- ja JSON-RPC-käskyt - - - If <category> is not supplied or if <category> = 1, output all debugging information. - Jos <category> on toimittamatta tai jos <category> = 1, tulosta kaikki debug-tieto. - - - Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. - Tarkistathan että tietokoneesi päivämäärä ja kellonaika ovat oikeassa! Jos kellosi on väärässä, Bitcoin Core ei toimi oikein. - - - Prune configured below the minimum of %d MiB. Please use a higher number. - Karsinta konfiguroitu alle minimin %d MiB. Käytä surempaa numeroa. - - - Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node) - Karsinta: viime lompakon synkronisointi menee karsitun datan taakse. Sinun tarvitsee ajaa -reindex (lataa koko lohkoketju uudelleen tapauksessa jossa karsiva noodi) - - - Reduce storage requirements by pruning (deleting) old blocks. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, >%u = target size in MiB to use for block files) - Vähennä levytilan tarvetta karsimalla (poistamalla) vanhoja lohkoja. Tämä tila ei ole yhteensopiva -txindex ja -rescan -parametrien kanssa. Varoitus: Tämän asetuksen peruutus vaatii koko lohkoketjun uudelleenlataamisen. (oletus: 0 = poista karsinta käytöstä, >%u = kohdekoko muodossa MiB jota käytetään lohkotiedostoille) + Reduce storage requirements by pruning (deleting) old blocks. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, >%u = target size in MiB to use for block files) + Vähennä levytilan tarvetta karsimalla (poistamalla) vanhoja lohkoja. Tämä tila ei ole yhteensopiva -txindex ja -rescan -parametrien kanssa. Varoitus: Tämän asetuksen peruutus vaatii koko lohkoketjun uudelleenlataamisen. (oletus: 0 = poista karsinta käytöstä, >%u = kohdekoko muodossa MiB jota käytetään lohkotiedostoille) Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again. @@ -2951,6 +1690,10 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Hyväksy yhteyksiä ulkopuolelta (vakioasetus: 1 jos -proxy tai -connect ei määritelty) + + Bitcoin Core + Bitcoin-ydin + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. -fallbackfee on asetettu erittäin suureksi! Tämä on rahansiirtokulu jonka voit maksaa kun arvioitu rahansirtokulu ei ole saatavilla. @@ -2971,10 +1714,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Tämä on esi-julkaistu testiversio - Käytä omalla riskillä - Ei saa käytää louhimiseen tai kauppasovelluksiin. - - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - Ei voida yhdistää %s tässä tietokoneessa. Bitcoin Core on luultavasti jo käynnissä. - Use UPnP to map the listening port (default: 1 when listening and no -proxy) Käytä UPnP:ta kuuntelevan portin kartoitukseen (oletus: 1 kun kuunnellaan ja -proxy ei käytössä) @@ -2995,10 +1734,6 @@ Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Varoitus: Olemme vertaisverkon kanssa ristiriidassa! Sinun tulee päivittää tai toisten solmujen tulee päivitää. - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Varoitus: wallet.dat -lompakkotiedosto on korruptoitunut, tiedot pelastettu. Alkuperäinen wallet.dat -lompakkotiedosto on tallennettu wallet.{timestamp}.bak kansioon %s; jos balanssisi tai siirtohistoria on virheellinen, sinun tulisi palauttaa lompakkotiedosto varmuuskopiosta. - Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. Salli vertaisten yhdistää annetusta verkkomaskista tai IP-osoitteesta. Voidaan määrittää useampia kertoja. @@ -3123,18 +1858,10 @@ Wallet options: Lompakon valinnat: - - You need to rebuild the database using -reindex to change -txindex - Sinun tulee uudelleenrakentaa tietokanta käyttäen -reindex vaihtaen -txindex - 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 Salli JSON-RPC-yhteydet määritetystä lähteestä. Kelvolliset arvot <ip> ovat yksittäinen IP (esim. 1.2.3.4), verkko/verkkomaski (esim. 1.2.3.4/255.255.255.0) tai verkko/luokaton reititys (esim. 1.2.3.4/24). Tätä valintatapaa voidaan käyttää useita kertoja - - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - Ei voida lukita data-hakemistoa %s. Bitcoin Core on luultavasti jo käynnissä. - Discover own IP addresses (default: 1 when listening and no -externalip or -proxy) Paljasta omat IP-osoitteet (oletus: 1 kun kuunnellaan ja -externalip tai -proxy ei ole käytössä) @@ -3147,10 +1874,6 @@ Set maximum size of high-priority/low-fee transactions in bytes (default: %d) Aseta maksimikoko korkea prioriteetti/pieni palkkio rahansiirtoihin tavuissa (oletus: %d) - - Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) - Aseta kolikoiden luomiseen tarkoitettujen säikeiden lukumäärä (-1 = kaikki ytimet, oletus: %d) - (default: %u) (oletus: %u) @@ -3159,30 +1882,10 @@ Accept public REST requests (default: %u) Hyväksy julkisia REST-pyyntöjä (oletus: %u) - - Activating best chain... - Aktivoidaan parhainta ketjua... - - - Attempt to recover private keys from a corrupt wallet.dat on startup - Yritä palauttaa yksityiset avaimet korruptoituneesta wallet.dat-tiedostosta käynnistyksen yhteydessä - - - Cannot resolve -whitebind address: '%s' - -whitebind -osoitetta '%s' ei voida jäsentää - Connect through SOCKS5 proxy Yhdistä SOCKS5 proxin kautta - - Copyright (C) 2009-%i The Bitcoin Core Developers - Copyright (C) 2009-%i Bitcoin kehittäjät - - - Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - Virhe ladattaessa wallet.dat-tiedostoa: Tarvitset uudemman version Bitcoinista - Error reading from database, shutting down. Virheitä tietokantaa luettaessa, ohjelma pysäytetään. @@ -3191,18 +1894,6 @@ Information Tietoa - - Invalid amount for -maxtxfee=<amount>: '%s' - Virheellinen määrä -maxtxfee=<amount>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Virheellinen määrä -minrelaytxfee=<amount>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - Virheellinen määrä -mintxfee=<amount>: '%s' - Keep at most <n> unconnectable transactions in memory (default: %u) Pidä enimmillään <n> yhdistämiskelvotonta rahansiirtoa muistissa (oletus: %u) @@ -3215,10 +1906,6 @@ RPC server options: RPC-palvelimen valinnat: - - Receive and display P2P network alerts (default: %u) - Vastaanota ja näytä P2P-verkon hälytyksiä (oletus: %u) - Rescan the block chain for missing wallet transactions on startup Uudelleenskannaa lohkoketju käynnistyksen yhteydessä puuttuvien lompakon rahansiirtojen vuoksi @@ -3279,10 +1966,6 @@ Username for JSON-RPC connections Käyttäjätunnus JSON-RPC-yhteyksille - - Wallet needed to be rewritten: restart Bitcoin Core to complete - Lompakko tarvitsee uudelleenkirjoittaa: käynnistä Bitcoin uudelleen - Warning Varoitus @@ -3299,10 +1982,6 @@ ZeroMQ notification options: ZeroMQ-ilmoitusasetukset: - - wallet.dat corrupt, salvage failed - wallet.dat -lompakkotiedosto korruptoitunut, korjaaminen epäonnistui - Password for JSON-RPC connections Salasana JSON-RPC-yhteyksille @@ -3311,10 +1990,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) Suorita käsky kun paras lohko muuttuu (%s cmd on vaihdettu block hashin kanssa) - - This help message - Tämä ohjeviesti - Allow DNS lookups for -addnode, -seednode and -connect Salli DNS kyselyt -addnode, -seednode ja -connect yhteydessä @@ -3323,10 +1998,6 @@ Loading addresses... Ladataan osoitteita... - - Error loading wallet.dat: Wallet corrupted - Virhe ladattaessa wallet.dat-tiedostoa: Lompakko vioittunut - -maxtxfee is set very high! Fees this large could be paid on a single transaction. -maxtxfee on asetettu erittäin suureksi! Tämänkokoisia kuluja saatetaan maksaa yhdessä rahansiirrossa. @@ -3339,10 +2010,6 @@ Do not keep transactions in the mempool longer than <n> hours (default: %u) Älä pidä rahansiirtoja muistivarannoissa kauemmin kuin <n> tuntia (oletus: %u) - - Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. - Virhe lukiessa wallet.dat-tiedostoa! Kaikki avaimet luettiin onnistuneesti, mutta rahansiirtotiedot tai osoitekirjan sisältö saattavat olla muuttuneita tai vääriä. - How thorough the block verification of -checkblocks is (0-4, default: %u) Kuinka läpikäyvä lohkojen -checkblocks -todennus on (0-4, oletus: %u) @@ -3359,14 +2026,6 @@ Always query for peer addresses via DNS lookup (default: %u) Pyydä vertaisten osoitteita aina DNS-kyselyjen avulla (oletus: %u) - - Error loading wallet.dat - Virhe ladattaessa wallet.dat-tiedostoa - - - Generate coins (default: %u) - Luo kolikoita (oletus: %u) - How many blocks to check at startup (default: %u, 0 = all) Kuinka monta lohkoa tarkistetaan käynnistyksessä (oletus: %u, 0 = kaikki) @@ -3451,18 +2110,6 @@ Unknown network specified in -onlynet: '%s' Tuntematon verkko -onlynet parametrina: '%s' - - Cannot resolve -bind address: '%s' - -bind osoitteen '%s' selvittäminen epäonnistui - - - Cannot resolve -externalip address: '%s' - -externalip osoitteen '%s' selvittäminen epäonnistui - - - Invalid amount for -paytxfee=<amount>: '%s' - -paytxfee=<amount>: '%s' on virheellinen - Insufficient funds Lompakon saldo ei riitä diff --git a/src/qt/locale/bitcoin_fil.ts b/src/qt/locale/bitcoin_fil.ts deleted file mode 100644 index fba823837112b..0000000000000 --- a/src/qt/locale/bitcoin_fil.ts +++ /dev/null @@ -1,157 +0,0 @@ - - - AddressBookPage - - Create a new address - Gumawa ng bagong address - - - Copy the currently selected address to the system clipboard - Kopyahin ang napiling tahanan sa clipboard - - - &Copy - Kumopya - - - C&lose - Isarado - - - &Copy Address - Tumulad ng kinatatahanan - - - Delete the currently selected address from the list - Alisin ang napiling address sa pagpipilian - - - Choose the address to send coins to - Pumili ng pagpapadalahang address - - - Choose the address to receive coins with - Piliin ang address ng nagpadala - - - C&hoose - Piliin - - - Sending addresses - Address pagpapadala - - - Receiving addresses - Address bilang pagtanggap - - - - AddressTableModel - - - AskPassphraseDialog - - - BanTableModel - - - BitcoinGUI - - - ClientModel - - - CoinControlDialog - - - EditAddressDialog - - - FreespaceChecker - - - HelpMessageDialog - - - Intro - - - OpenURIDialog - - - OptionsDialog - - - OverviewPage - - - PaymentServer - - - PeerTableModel - - - QObject - - - QRImageWidget - - - RPCConsole - - - ReceiveCoinsDialog - - - ReceiveRequestDialog - - - RecentRequestsTableModel - - - SendCoinsDialog - - - SendCoinsEntry - - - ShutdownWindow - - - SignVerifyMessageDialog - - - SplashScreen - - - TrafficGraphWidget - - - TransactionDesc - - - TransactionDescDialog - - - TransactionTableModel - - - TransactionView - - - UnitDisplayStatusBarControl - - - WalletFrame - - - WalletModel - - - WalletView - - - bitcoin-core - - \ No newline at end of file diff --git a/src/qt/locale/bitcoin_fr.ts b/src/qt/locale/bitcoin_fr.ts index 65808c77406b7..fe745f99bf181 100644 --- a/src/qt/locale/bitcoin_fr.ts +++ b/src/qt/locale/bitcoin_fr.ts @@ -15,7 +15,7 @@ Copy the currently selected address to the system clipboard - Copier l'adresse courante sélectionnée dans le presse-papiers + Copier l'adresse sélectionnée actuellement dans le presse-papiers &Copy @@ -25,17 +25,13 @@ C&lose &Fermer - - &Copy Address - &Copier l'adresse - Delete the currently selected address from the list - Supprimer l'adresse actuellement sélectionnée de la liste + Supprimer de la liste l'adresse sélectionnée actuellement Export the data in the current tab to a file - Exporter les données de l'onglet courant vers un fichier + Exporter les données de l'onglet actuel vers un fichier &Export @@ -45,73 +41,6 @@ &Delete &Supprimer - - Choose the address to send coins to - Choisir l'adresse à laquelle envoyer des pièces - - - Choose the address to receive coins with - Choisir l'adresse avec laquelle recevoir des pièces - - - C&hoose - C&hoisir - - - Sending addresses - Adresses d'envoi - - - Receiving addresses - Adresses de réception - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Voici vos adresses Bitcoin pour envoyer des paiements. Vérifiez toujours le montant et l'adresse du destinataire avant d'envoyer des pièces. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Voici vos adresses Bitcoin pour recevoir des paiements. Il est recommandé d'utiliser une nouvelle adresse de réception pour chaque transaction. - - - Copy &Label - Copier l'é&tiquette - - - &Edit - &Modifier - - - Export Address List - Exporter la liste d'adresses - - - Comma separated file (*.csv) - Valeurs séparées par des virgules (*.csv) - - - Exporting Failed - L'exportation a échoué - - - There was an error trying to save the address list to %1. Please try again. - Une erreur est survenue lors de l'enregistrement de la liste d'adresses vers %1. Veuillez ressayer plus tard. - - - - AddressTableModel - - Label - Étiquette - - - Address - Adresse - - - (no label) - (aucune étiquette) - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase Répéter la phrase de passe - - Encrypt wallet - Chiffrer le portefeuille - - - This operation needs your wallet passphrase to unlock the wallet. - Cette opération nécessite votre phrase de passe pour déverrouiller le portefeuille. - - - Unlock wallet - Déverrouiller le portefeuille - - - This operation needs your wallet passphrase to decrypt the wallet. - Cette opération nécessite votre phrase de passe pour déchiffrer le portefeuille. - - - Decrypt wallet - Déchiffrer le portefeuille - - - Change passphrase - Changer la phrase de passe - - - Confirm wallet encryption - Confirmer le chiffrement du portefeuille - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Avertissement : si vous chiffrez votre portefeuille et perdez votre phrase de passe, vous <b>PERDREZ TOUS VOS BITCOINS</b> ! - - - Are you sure you wish to encrypt your wallet? - Êtes-vous sûr de vouloir chiffrer votre portefeuille ? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Bitcoin Core va maintenant se fermer pour terminer le processus de chiffrement. Souvenez-vous que le chiffrement de votre portefeuille ne peut pas vous protéger complètement contre le vol de vos bitcoins par des programmes malveillants infectant votre ordinateur. - - - 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. - IMPORTANT : Toute sauvegarde précédente de votre fichier de portefeuille devrait être remplacée par le nouveau fichier de portefeuille chiffré. Pour des raisons de sécurité, les sauvegardes précédentes de votre fichier de portefeuille non chiffré deviendront inutilisables dès que vous commencerez à utiliser le nouveau portefeuille chiffré. - - - Warning: The Caps Lock key is on! - Avertissement : la touche Verr. Maj. est activée ! - - - Wallet encrypted - Portefeuille chiffré - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Saisissez une nouvelle phrase de passe pour le portefeuille.<br/>Veuillez utiliser une phrase composée de <b>dix caractères aléatoires ou plus</b>, ou bien de <b>huit mots ou plus</b>. - - - Enter the old passphrase and new passphrase to the wallet. - Saisir l'ancienne phrase de passe puis la nouvelle phrase de passe du portefeuille. - - - Wallet encryption failed - Le chiffrement du portefeuille a échoué - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Le chiffrement du portefeuille a échoué en raison d'une erreur interne. Votre portefeuille n'a pas été chiffré. - - - The supplied passphrases do not match. - Les phrases de passe saisies ne correspondent pas. - - - Wallet unlock failed - Le déverrouillage du portefeuille a échoué - - - The passphrase entered for the wallet decryption was incorrect. - La phrase de passe saisie pour déchiffrer le portefeuille était incorrecte. - - - Wallet decryption failed - Le déchiffrage du portefeuille a échoué - - - Wallet passphrase was successfully changed. - La phrase de passe du portefeuille a été modifiée avec succès. - BanTableModel @@ -251,7 +92,7 @@ Show general overview of wallet - Afficher une vue d’ensemble du portefeuille + Afficher une vue d’ensemble du porte-monnaie &Transactions @@ -269,6 +110,14 @@ Quit application Quitter l’application + + &About %1 + À &propos de %1 + + + Show information about %1 + Afficher des informations à propos de %1 + About &Qt À propos de &Qt @@ -281,13 +130,17 @@ &Options... &Options… + + Modify configuration options for %1 + Modifier les options de configuration de %1 + &Encrypt Wallet... - &Chiffrer le portefeuille... + &Chiffrer le porte-monnaie... &Backup Wallet... - Sauvegarder le &portefeuille... + Sauvegarder le &porte-monnaie... &Change Passphrase... @@ -305,14 +158,6 @@ Open &URI... Ouvrir un &URI... - - Bitcoin Core client - Client Bitcoin Core - - - Importing blocks from disk... - Importation des blocs à partir du disque... - Reindexing blocks on disk... Réindexation des blocs sur le disque... @@ -323,11 +168,11 @@ Backup wallet to another location - Sauvegarder le portefeuille vers un autre emplacement + Sauvegarder le porte-monnaie vers un autre emplacement Change the passphrase used for wallet encryption - Modifier la phrase de passe utilisée pour le chiffrement du portefeuille + Modifier la phrase de passe utilisée pour le chiffrement du porte-monnaie &Debug window @@ -347,7 +192,7 @@ Wallet - Portefeuille + Porte-monnaie &Send @@ -357,10 +202,6 @@ &Receive &Recevoir - - Show information about Bitcoin Core - Montrer des informations à propos de Bitcoin Core - &Show / Hide &Afficher / Cacher @@ -371,7 +212,7 @@ Encrypt the private keys that belong to your wallet - Chiffrer les clefs privées de votre portefeuille + Chiffrer les clefs privées de votre porte-monnaie Sign messages with your Bitcoin addresses to prove you own them @@ -397,22 +238,10 @@ Tabs toolbar Barre d'outils des onglets - - Bitcoin Core - Bitcoin Core - Request payments (generates QR codes and bitcoin: URIs) Demander des paiements (génère des codes QR et des URIs bitcoin:) - - &About Bitcoin Core - À &propos de Bitcoin Core - - - Modify configuration options for Bitcoin Core - Modifier les options de configuration de Bitcoin Core - Show the list of used sending addresses and labels Afficher la liste d'adresses d'envoi et d'étiquettes utilisées @@ -429,14 +258,18 @@ &Command-line options Options de ligne de &commande - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Afficher le message d'aide de Bitcoin Core pour obtenir une liste des options de ligne de commande Bitcoin possibles. - %n active connection(s) to Bitcoin network %n connexion active avec le réseau Bitcoin%n connexions actives avec le réseau Bitcoin + + Indexing blocks on disk... + Indexation des blocs sur le disque... + + + Processing blocks on disk... + Traitement des blocs sur le disque... + No block source available... Aucune source de blocs disponible... @@ -493,6 +326,14 @@ Up to date À jour + + Show the %1 help message to get a list with possible Bitcoin command-line options + Afficher le message d'aide de %1 pour obtenir la liste des options de ligne de commande Bitcoin possibles. + + + %1 client + Client %1 + Catching up... Rattrapage en cours… @@ -537,18 +378,11 @@ Wallet is <b>encrypted</b> and currently <b>unlocked</b> - Le portefeuille est <b>chiffré</b> et est actuellement <b>déverrouillé</b> + Le porte-monnaie est <b>chiffré</b> et est actuellement <b>déverrouillé</b> Wallet is <b>encrypted</b> and currently <b>locked</b> - Le portefeuille est <b>chiffré</b> et actuellement <b>verrouillé</b> - - - - ClientModel - - Network Alert - Alerte réseau + Le porte-monnaie est <b>chiffré</b> et actuellement <b>verrouillé</b> @@ -629,150 +463,6 @@ Priority Priorité - - Copy address - Copier l’adresse - - - Copy label - Copier l’étiquette - - - Copy amount - Copier le montant - - - Copy transaction ID - Copier l'ID de la transaction - - - Lock unspent - Verrouiller ce qui n'est pas dépensé - - - Unlock unspent - Déverrouiller ce qui n'est pas dépensé - - - Copy quantity - Copier la quantité - - - Copy fee - Copier les frais - - - Copy after fee - Copier le montant après les frais - - - Copy bytes - Copier les octets - - - Copy priority - Copier la priorité - - - Copy dust - Copier la poussière - - - Copy change - Copier la monnaie - - - highest - la plus élevée - - - higher - plus élevée - - - high - élevée - - - medium-high - moyennement-élevée - - - medium - moyenne - - - low-medium - moyennement-basse - - - low - basse - - - lower - plus basse - - - lowest - la plus basse - - - (%1 locked) - (%1 verrouillé) - - - none - aucun - - - This label turns red if the transaction size is greater than 1000 bytes. - Cette étiquette devient rouge si la taille de la transaction est plus grande que 1 000 octets. - - - This label turns red if the priority is smaller than "medium". - Cette étiquette devient rouge si la priorité est plus basse que « moyenne ». - - - This label turns red if any recipient receives an amount smaller than %1. - Cette étiquette devient rouge si un destinataire reçoit un montant inférieur à %1. - - - Can vary +/- %1 satoshi(s) per input. - Peut varier +/- %1 satoshi(s) par entrée. - - - yes - oui - - - no - non - - - This means a fee of at least %1 per kB is required. - Ceci signifie que des frais d'au moins %1 par ko sont exigés. - - - Can vary +/- 1 byte per input. - Peut varier +/- 1 octet par entrée. - - - Transactions with higher priority are more likely to get included into a block. - Les transactions à priorité plus haute sont plus à même d'être incluses dans un bloc. - - - (no label) - (aucune étiquette) - - - change from %1 (%2) - monnaie de %1 (%2) - - - (change) - (monnaie) - EditAddressDialog @@ -796,38 +486,6 @@ &Address &Adresse - - New receiving address - Nouvelle adresse de réception - - - New sending address - Nouvelle adresse d’envoi - - - Edit receiving address - Modifier l’adresse de réception - - - Edit sending address - Modifier l’adresse d'envoi - - - The entered address "%1" is already in the address book. - L’adresse fournie « %1 » est déjà présente dans le carnet d'adresses. - - - The entered address "%1" is not a valid Bitcoin address. - L'adresse fournie « %1 » n'est pas une adresse Bitcoin valide. - - - Could not unlock wallet. - Impossible de déverrouiller le portefeuille. - - - New key generation failed. - Échec de génération de la nouvelle clef. - FreespaceChecker @@ -854,10 +512,6 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin Core - version version @@ -867,8 +521,8 @@ (%1-bit) - About Bitcoin Core - À propos de Bitcoin Core + About %1 + À propos de %1 Command-line options @@ -907,8 +561,8 @@ Afficher l'écran d'accueil au démarrage (par défaut : %u) - Reset all settings changes made over the GUI - Réinitialiser tous les changements de paramètres appliqués à l'IUG + Reset all settings changed in the GUI + Réinitialiser tous les paramètres changés dans l'IUG @@ -918,16 +572,16 @@ Bienvenue - Welcome to Bitcoin Core. - Bienvenue à Bitcoin Core. + Welcome to %1. + Bienvenue à %1. - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - Comme c'est la première fois que le logiciel est lancé, vous pouvez choisir où Bitcoin Core stockera ses données. + As this is the first time the program is launched, you can choose where %1 will store its data. + Puisque c'est la première fois que le logiciel est lancé, vous pouvez choisir où %1 stockera ses données. - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - Bitcoin Core va télécharger et stocker une copie de la chaîne de blocs Bitcoin. Au moins %1Go de données seront stockées dans ce répertoire et cela augmentera avec le temps. Le portefeuille sera également stocké dans ce répertoire. + %1 will download and store a copy of the Bitcoin block chain. At least %2GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. + %1 téléchargera et stockera une copie de la chaîne de blocs de Bitcoin. Au moins %2 Go de données seront stockés dans ce répertoire et sa taille augmentera avec le temps. Le porte-monnaie sera également stocké dans ce répertoire. Use the default data directory @@ -937,10 +591,6 @@ Use a custom data directory: Utiliser un répertoire de données personnalisé : - - Bitcoin Core - Bitcoin Core - Error: Specified data directory "%1" cannot be created. Erreur : le répertoire de données spécifié « %1 » ne peut pas être créé. @@ -976,10 +626,6 @@ Select payment request file Choisir le fichier de demande de paiement - - Select payment request file to open - Choisir le fichier de demande de paiement à ouvrir - OptionsDialog @@ -991,6 +637,14 @@ &Main Réglages &principaux + + Automatically start %1 after logging in to the system. + Démarrer %1 automatiquement après avoir ouvert une session sur l'ordinateur. + + + &Start %1 on system login + &Démarrer %1 lors de l'ouverture d'une session + Size of &database cache Taille du cache de la base de &données @@ -1019,10 +673,6 @@ 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. Minimiser au lieu de quitter l'application lorsque la fenêtre est fermée. Si cette option est activée, l'application ne sera fermée qu'en sélectionnant Quitter dans le menu. - - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - La langue de l'interface utilisateur peut être définie ici. Ce réglage sera pris en compte après redémarrage de Bitcoin. - 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 |. URL de tiers (par ex. un explorateur de blocs) apparaissant dans l'onglet des transactions comme éléments du menu contextuel. %s dans l'URL est remplacé par le hachage de la transaction. Les URL multiples sont séparées par une barre verticale |. @@ -1047,21 +697,13 @@ &Network &Réseau - - Automatically start Bitcoin Core after logging in to the system. - Démarrer Bitcoin Core automatiquement après avoir ouvert une session sur le système. - - - &Start Bitcoin Core on system login - &Démarrer Bitcoin Core lors de l'ouverture d'une session - (0 = auto, <0 = leave that many cores free) (0 = auto, < 0 = laisser ce nombre de cœurs inutilisés) W&allet - &Portefeuille + &Porte-monnaie Expert @@ -1139,6 +781,14 @@ &Window &Fenêtre + + &Hide the icon from the system tray. + &Cacher l'icône dans la zone de notification. + + + Hide tray icon + Cacher l'icône de la zone de notification + Show only a tray icon after minimizing the window. Afficher uniquement une icône système après minimisation. @@ -1159,6 +809,10 @@ User Interface &language: &Langue de l'interface utilisateur : + + The user interface language can be set here. This setting will take effect after restarting %1. + La langue de l'interface utilisateur peut être définie ici. Ce réglage sera pris en compte après redémarrage de %1. + &Unit to show amounts in: &Unité d'affichage des montants : @@ -1216,7 +870,7 @@ 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. - Les informations affichées peuvent être obsolètes. Votre portefeuille est automatiquement synchronisé avec le réseau Bitcoin lorsque la connexion s'établit, or ce processus n'est pas encore terminé. + Les informations affichées peuvent être obsolètes. Votre porte-monnaie est automatiquement synchronisé avec le réseau Bitcoin lorsque la connexion s'établit, or ce processus n'est pas encore terminé. Watch-only: @@ -1284,169 +938,59 @@ - PaymentServer + PeerTableModel - URI handling - Gestion des URIs + User Agent + Agent utilisateur - Invalid payment address %1 - Adresse de paiement invalide %1 + Node/Service + Nœud/service - Payment request rejected - La demande de paiement est rejetée + Ping Time + Temps de ping + + + QObject - Payment request network doesn't match client network. - Le réseau de la demande de paiement ne correspond pas au réseau du client. + Amount + Montant - Payment request is not initialized. - La demande de paiement n'est pas initialisée. + Enter a Bitcoin address (e.g. %1) + Saisir une adresse Bitcoin (p. ex. %1) - Requested payment amount of %1 is too small (considered dust). - Le paiement demandé d'un montant de %1 est trop faible (considéré comme de la poussière). + %1 d + %1 j - Payment request error - Erreur de demande de paiement + %1 h + %1 h - Cannot start bitcoin: click-to-pay handler - Impossible de démarrer le gestionnaire de cliquer-pour-payer bitcoin : + %1 m + %1 min - Payment request fetch URL is invalid: %1 - L'URL de récupération de la demande de paiement est invalide : %1 + %1 s + %1 s - URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - L'URI ne peut pas être analysé ! Ceci peut être causé par une adresse Bitcoin invalide ou par des paramètres d'URI mal formés. + None + Aucun - Payment request file handling - Gestion des fichiers de demande de paiement - - - Payment request file cannot be read! This can be caused by an invalid payment request file. - Le fichier de demande de paiement ne peut pas être lu ! Ceci peut être causé par un fichier de demande de paiement invalide. - - - Payment request expired. - Demande de paiement expirée. - - - Unverified payment requests to custom payment scripts are unsupported. - Les demandes de paiements non vérifiées à des scripts de paiement personnalisés ne sont pas prises en charge. - - - Invalid payment request. - Demande de paiement invalide. - - - Refund from %1 - Remboursement de %1 - - - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - La demande de paiement %1 est trop grande (%2 octets, %3 octets permis). - - - Error communicating with %1: %2 - Erreur de communication avec %1 : %2 - - - Payment request cannot be parsed! - La demande de paiement ne peut pas être analysée ! - - - Bad response from server %1 - Mauvaise réponse du serveur %1 - - - Payment acknowledged - Le paiement a été confirmé - - - Network request error - Erreur de demande réseau - - - - PeerTableModel - - User Agent - Agent utilisateur - - - Node/Service - Nœud/service - - - Ping Time - Temps de ping - - - - QObject - - Amount - Montant - - - Enter a Bitcoin address (e.g. %1) - Saisir une adresse Bitcoin (p. ex. %1) - - - %1 d - %1 j - - - %1 h - %1 h - - - %1 m - %1 min - - - %1 s - %1 s - - - None - Aucun - - - N/A - N.D. + N/A + N.D. %1 ms %1 ms - - QRImageWidget - - &Save Image... - &Sauvegarder l'image... - - - &Copy Image - &Copier l'image - - - Save QR Code - Sauvegarder le code QR - - - PNG Image (*.png) - Image PNG (*.png) - - RPCConsole @@ -1477,6 +1021,10 @@ Using BerkeleyDB version Version BerkeleyDB utilisée + + Datadir + Datadir + Startup time Heure de démarrage @@ -1513,10 +1061,6 @@ Memory usage Utilisation de la mémoire - - Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. - Ouvrir le journal de débogage du répertoire de données actuel. Ceci pourrait prendre quelques secondes pour les gros fichiers de journalisation. - Received Reçu @@ -1565,6 +1109,18 @@ User Agent Agent utilisateur + + Open the %1 debug log file from the current data directory. This can take a few seconds for large log files. + Ouvrir le journal de débogage de %1 depuis le répertoire de données actuel. Ceci peut prendre quelques secondes pour les journaux de grande taille. + + + Decrease font size + Diminuer la taille de police + + + Increase font size + Augmenter la taille de police + Services Services @@ -1633,10 +1189,6 @@ Out: Sortant : - - Build date - Date de compilation - Debug log file Journal de débogage @@ -1674,8 +1226,8 @@ &Réhabiliter le nœud - Welcome to the Bitcoin Core RPC console. - Bienvenue dans le console RPC de Bitcoin Core. + Welcome to the %1 RPC console. + Bienvenue sur la console RPC de %1. Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. @@ -1804,18 +1356,6 @@ Remove Enlever - - Copy label - Copier l’étiquette - - - Copy message - Copier le message - - - Copy amount - Copier le montant - ReceiveRequestDialog @@ -1835,73 +1375,6 @@ &Save Image... &Sauvegarder l'image... - - Request payment to %1 - Demande de paiement à %1 - - - Payment information - Informations de paiement - - - URI - URI - - - Address - Adresse - - - Amount - Montant - - - Label - Étiquette - - - Message - Message - - - Resulting URI too long, try to reduce the text for label / message. - L'URI résultant est trop long, essayez de réduire le texte d'étiquette / de message. - - - Error encoding URI into QR Code. - Erreur d'encodage de l'URI en code QR. - - - - RecentRequestsTableModel - - Date - Date - - - Label - Étiquette - - - Message - Message - - - Amount - Montant - - - (no label) - (pas d'étiquette) - - - (no message) - (pas de message) - - - (no amount) - (aucun montant) - SendCoinsDialog @@ -2021,14 +1494,6 @@ fast rapide - - Send as zero-fee transaction if possible - Envoyer si possible une transaction sans frais - - - (confirmation may take longer) - (la confirmation pourrait prendre plus longtemps) - Send to multiple recipients at once Envoyer à plusieurs destinataires à la fois @@ -2050,855 +1515,221 @@ &Tout nettoyer - Balance: - Solde : - - - Confirm the send action - Confirmer l’action d'envoi - - - S&end - E&nvoyer - - - Confirm send coins - Confirmer l’envoi des pièces - - - %1 to %2 - %1 à %2 - - - Copy quantity - Copier la quantité - - - Copy amount - Copier le montant - - - Copy fee - Copier les frais - - - Copy after fee - Copier le montant après les frais - - - Copy bytes - Copier les octets - - - Copy priority - Copier la priorité - - - Copy change - Copier la monnaie - - - Total Amount %1 - Montant total %1 - - - or - ou - - - The amount to pay must be larger than 0. - Le montant à payer doit être supérieur à 0. - - - The amount exceeds your balance. - Le montant dépasse votre solde. - - - The total exceeds your balance when the %1 transaction fee is included. - Le montant dépasse votre solde lorsque les frais de transaction de %1 sont inclus. - - - Transaction creation failed! - La création de la transaction a échoué ! - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - La transaction a été rejetée ! Ceci peut arriver si certaines pièces de votre portefeuille étaient déjà dépensées, par exemple si vous avez utilisé une copie de wallet.dat et que des pièces ont été dépensées dans la copie sans être marquées comme telles ici. - - - A fee higher than %1 is considered an absurdly high fee. - Des frais supérieurs à %1 sont considérés comme ridiculement élevés. - - - Payment request expired. - Demande de paiement expirée. - - - Pay only the required fee of %1 - Payer seulement les frais exigés de %1 - - - Estimated to begin confirmation within %n block(s). - Il est estimé que la confirmation commencera dans %n bloc.Il est estimé que la confirmation commencera dans %n blocs. - - - The recipient address is not valid. Please recheck. - L'adresse du destinataire est invalide. Veuillez la vérifier. - - - Duplicate address found: addresses should only be used once each. - Adresse identique trouvée : chaque adresse ne devrait être utilisée qu'une fois. - - - Warning: Invalid Bitcoin address - Avertissement : adresse Bitcoin invalide - - - (no label) - (pas d'étiquette) - - - Warning: Unknown change address - Avertissement : adresse de monnaie rendue inconnue - - - Copy dust - Copier la poussière - - - Are you sure you want to send? - Êtes-vous sûr de vouloir envoyer ? - - - added as transaction fee - ajouté en tant que frais de transaction - - - - SendCoinsEntry - - A&mount: - &Montant : - - - Pay &To: - &Payer à : - - - Enter a label for this address to add it to your address book - Saisir une étiquette pour cette adresse afin de l’ajouter à votre carnet d’adresses - - - &Label: - É&tiquette : - - - Choose previously used address - Choisir une adresse déjà utilisée - - - This is a normal payment. - Ceci est un paiement normal. - - - The Bitcoin address to send the payment to - L'adresse Bitcoin à laquelle envoyer le paiement - - - Alt+A - Alt+A - - - Paste address from clipboard - Coller l'adresse depuis le presse-papiers - - - Alt+P - Alt+P - - - Remove this entry - Enlever cette entrée - - - 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. - 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.. - - - S&ubtract fee from amount - S&oustraire les frais du montant - - - Message: - Message : - - - This is an unauthenticated payment request. - Cette demande de paiement n'est pas authentifiée. - - - This is an authenticated payment request. - Cette demande de paiement est authentifiée. - - - Enter a label for this address to add it to the list of used addresses - Saisir une étiquette pour cette adresse afin de l'ajouter à la liste d'adresses utilisées - - - 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. - Un message qui était joint à l'URI Bitcoin et qui sera stocké avec la transaction pour référence. Note : ce message ne sera pas envoyé par le réseau Bitcoin. - - - Pay To: - Payer à : - - - Memo: - Mémo : - - - - ShutdownWindow - - Bitcoin Core is shutting down... - Arrêt de Bitcoin Core... - - - Do not shut down the computer until this window disappears. - Ne pas fermer l'ordinateur jusqu'à la disparition de cette fenêtre. - - - - SignVerifyMessageDialog - - Signatures - Sign / Verify a Message - Signatures - Signer / Vérifier un message - - - &Sign Message - &Signer un message - - - 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. - Vous pouvez signer des messages/accords avec vos adresses pour prouver que vous pouvez recevoir des bitcoins à ces dernières. Faites attention de ne rien signer de vague ou au hasard, car des attaques d'hameçonnage pourraient essayer de vous faire signer avec votre identité afin de l'usurper. Ne signez que des déclarations entièrement détaillées et avec lesquelles vous êtes d'accord. - - - The Bitcoin address to sign the message with - L'adresse Bitcoin avec laquelle signer le message - - - Choose previously used address - Choisir une adresse précédemment utilisée - - - Alt+A - Alt+A - - - Paste address from clipboard - Coller une adresse depuis le presse-papiers - - - Alt+P - Alt+P - - - Enter the message you want to sign here - Saisir ici le message que vous désirez signer - - - Signature - Signature - - - Copy the current signature to the system clipboard - Copier la signature actuelle dans le presse-papiers - - - Sign the message to prove you own this Bitcoin address - Signer le message pour prouver que vous détenez cette adresse Bitcoin - - - Sign &Message - Signer le &message - - - Reset all sign message fields - Réinitialiser tous les champs de signature de message - - - Clear &All - &Tout nettoyer - - - &Verify Message - &Vérifier un message - - - 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! - Saisissez ci-dessous l'adresse de destinataire, le message (assurez-vous de copier exactement 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 d'homme du milieu. Notez que ceci ne fait que prouver que le signataire reçoit l'adresse et ne peut pas prouver la provenance d'une transaction. - - - The Bitcoin address the message was signed with - L'adresse Bitcoin avec laquelle le message a été signé - - - Verify the message to ensure it was signed with the specified Bitcoin address - Vérifier le message pour vous assurer qu'il a bien été signé par l'adresse Bitcoin spécifiée - - - Verify &Message - Vérifier le &message - - - Reset all verify message fields - Réinitialiser tous les champs de vérification de message - - - Click "Sign Message" to generate signature - Cliquez sur « Signer le message » pour générer la signature - - - The entered address is invalid. - L'adresse saisie est invalide. - - - Please check the address and try again. - Veuillez vérifier l'adresse et réessayer. - - - The entered address does not refer to a key. - L'adresse saisie ne fait pas référence à une clef. - - - Wallet unlock was cancelled. - Le déverrouillage du portefeuille a été annulé. - - - Private key for the entered address is not available. - La clef privée n'est pas disponible pour l'adresse indiquée. - - - Message signing failed. - La signature du message a échoué. - - - Message signed. - Le message a été signé. - - - The signature could not be decoded. - La signature n'a pu être décodée. - - - Please check the signature and try again. - Veuillez vérifier la signature et réessayer. - - - The signature did not match the message digest. - La signature ne correspond pas à l'empreinte du message. - - - Message verification failed. - Échec de la vérification du message. - - - Message verified. - Message vérifié. - - - - SplashScreen - - Bitcoin Core - Bitcoin Core - - - The Bitcoin Core developers - Les développeurs Bitcoin Core - - - [testnet] - [testnet] - - - - TrafficGraphWidget - - KB/s - Ko/s - - - - TransactionDesc - - Open until %1 - Ouvert jusqu'à %1 - - - conflicted - en conflit - - - %1/offline - %1/hors ligne - - - %1/unconfirmed - %1/non confirmée - - - %1 confirmations - %1 confirmations - - - Status - État - - - , broadcast through %n node(s) - , diffusée à travers %n nœud, diffusée à travers %n nœuds - - - Date - Date - - - Source - Source - - - Generated - Généré - - - From - De - - - To - À - - - own address - votre propre adresse - - - watch-only - juste-regarder - - - label - étiquette - - - Credit - Crédit - - - matures in %n more block(s) - arrive à maturité dans %n bloc de plusarrive à maturité dans %n blocs de plus - - - not accepted - refusé - - - Debit - Débit - - - Total debit - Débit total - - - Total credit - Crédit total - - - Transaction fee - Frais de transaction - - - Net amount - Montant net - - - Message - Message - - - Comment - Commentaire - - - Transaction ID - ID de la transaction - - - Merchant - Marchand - - - 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. - Les pièces générées doivent mûrir pendant %1 blocs avant de pouvoir être dépensées. Lorsque vous avez généré ce bloc, il a été diffusé sur le réseau pour être ajouté à la chaîne de blocs. S’il échoue a intégrer la chaîne, son état sera modifié en « non accepté » et il ne sera pas possible de le dépenser. Ceci peut arriver occasionnellement si un autre nœud génère un bloc à quelques secondes du votre. - - - Debug information - Informations de débogage - - - Transaction - Transaction - - - Inputs - Entrants - - - Amount - Montant - - - true - vrai - - - false - faux - - - , has not been successfully broadcast yet - , n’a pas encore été diffusée avec succès - - - Open for %n more block(s) - Ouvert pour %n bloc de plusOuvert pour %n blocs de plus - - - unknown - inconnu - - - - TransactionDescDialog - - Transaction details - Détails de la transaction - - - This pane shows a detailed description of the transaction - Ce panneau affiche une description détaillée de la transaction - - - - TransactionTableModel - - Date - Date - - - Type - Type - - - Immature (%1 confirmations, will be available after %2) - Immature (%1 confirmations, sera disponible après %2) - - - Open for %n more block(s) - Ouvert pour %n bloc de plusOuvert pour %n blocs de plus - - - Open until %1 - Ouvert jusqu'à %1 - - - Confirmed (%1 confirmations) - Confirmée (%1 confirmations) - - - This block was not received by any other nodes and will probably not be accepted! - Ce bloc n’a été reçu par aucun autre nœud et ne sera probablement pas accepté ! - - - Generated but not accepted - Généré mais pas accepté - - - Offline - Hors ligne - - - Label - Étiquette - - - Unconfirmed - Non confirmé - - - Confirming (%1 of %2 recommended confirmations) - Confirmation (%1 sur %2 confirmations recommandées) - - - Conflicted - En conflit - - - Received with - Reçue avec - - - Received from - Reçue de - - - Sent to - Envoyée à - - - Payment to yourself - Paiement à vous-même - - - Mined - Miné + Balance: + Solde : - watch-only - juste-regarder + Confirm the send action + Confirmer l’action d'envoi - (n/a) - (n.d) + S&end + E&nvoyer + + + SendCoinsEntry - Transaction status. Hover over this field to show number of confirmations. - État de la transaction. Laissez le pointeur de la souris sur ce champ pour voir le nombre de confirmations. + A&mount: + &Montant : - Date and time that the transaction was received. - Date et heure de réception de la transaction. + Pay &To: + &Payer à : - Type of transaction. - Type de transaction. + &Label: + É&tiquette : - Whether or not a watch-only address is involved in this transaction. - Une adresse juste-regarder est-elle impliquée dans cette transaction. + Choose previously used address + Choisir une adresse déjà utilisée - User-defined intent/purpose of the transaction. - Intention/but de la transaction défini par l'utilisateur. + This is a normal payment. + Ceci est un paiement normal. - Amount removed from or added to balance. - Montant ajouté ou enlevé au solde. + The Bitcoin address to send the payment to + L'adresse Bitcoin à laquelle envoyer le paiement - - - TransactionView - All - Toutes + Alt+A + Alt+A - Today - Aujourd’hui + Paste address from clipboard + Coller l'adresse depuis le presse-papiers - This week - Cette semaine + Alt+P + Alt+P - This month - Ce mois-ci + Remove this entry + Enlever cette entrée - Last month - Le mois dernier + 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. + 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.. - This year - Cette année + S&ubtract fee from amount + S&oustraire les frais du montant - Range... - Intervalle… + Message: + Message : - Received with - Reçue avec + This is an unauthenticated payment request. + Cette demande de paiement n'est pas authentifiée. - Sent to - Envoyée à + This is an authenticated payment request. + Cette demande de paiement est authentifiée. - To yourself - À vous-même + Enter a label for this address to add it to the list of used addresses + Saisir une étiquette pour cette adresse afin de l'ajouter à la liste d'adresses utilisées - Mined - Miné + 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. + Un message qui était joint à l'URI Bitcoin et qui sera stocké avec la transaction pour référence. Note : ce message ne sera pas envoyé par le réseau Bitcoin. - Other - Autres + Pay To: + Payer à : - Enter address or label to search - Saisir une adresse ou une étiquette à rechercher + Memo: + Mémo : + + + ShutdownWindow - Min amount - Montant min. + %1 is shutting down... + Arrêt de %1... - Copy address - Copier l’adresse + Do not shut down the computer until this window disappears. + Ne pas fermer l'ordinateur jusqu'à la disparition de cette fenêtre. + + + SignVerifyMessageDialog - Copy label - Copier l’étiquette + Signatures - Sign / Verify a Message + Signatures - Signer / Vérifier un message - Copy amount - Copier le montant + &Sign Message + &Signer un message - Copy transaction ID - Copier l'ID de la transaction + 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. + Vous pouvez signer des messages/accords avec vos adresses pour prouver que vous pouvez recevoir des bitcoins à ces dernières. Faites attention de ne rien signer de vague ou au hasard, car des attaques d'hameçonnage pourraient essayer de vous faire signer avec votre identité afin de l'usurper. Ne signez que des déclarations entièrement détaillées et avec lesquelles vous êtes d'accord. - Copy raw transaction - Copier la transaction brute + The Bitcoin address to sign the message with + L'adresse Bitcoin avec laquelle signer le message - Edit label - Modifier l’étiquette + Choose previously used address + Choisir une adresse précédemment utilisée - Show transaction details - Afficher les détails de la transaction + Alt+A + Alt+A - Export Transaction History - Exporter l'historique des transactions + Paste address from clipboard + Coller une adresse depuis le presse-papiers - Watch-only - Juste-regarder : + Alt+P + Alt+P - Exporting Failed - L'exportation a échoué + Enter the message you want to sign here + Saisir ici le message que vous désirez signer - There was an error trying to save the transaction history to %1. - Une erreur est survenue lors de l'enregistrement de l'historique des transactions vers %1. + Signature + Signature - Exporting Successful - Exportation réussie + Copy the current signature to the system clipboard + Copier la signature actuelle dans le presse-papiers - The transaction history was successfully saved to %1. - L'historique des transactions a été sauvegardée avec succès vers %1. + Sign the message to prove you own this Bitcoin address + Signer le message pour prouver que vous détenez cette adresse Bitcoin - Comma separated file (*.csv) - Valeurs séparées par des virgules (*.csv) + Sign &Message + Signer le &message - Confirmed - Confirmée + Reset all sign message fields + Réinitialiser tous les champs de signature de message - Date - Date + Clear &All + &Tout nettoyer - Type - Type + &Verify Message + &Vérifier un message - Label - Étiquette + 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! + Saisissez ci-dessous l'adresse de destinataire, le message (assurez-vous de copier exactement 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 d'homme du milieu. Notez que ceci ne fait que prouver que le signataire reçoit l'adresse et ne peut pas prouver la provenance d'une transaction. - Address - Adresse + The Bitcoin address the message was signed with + L'adresse Bitcoin avec laquelle le message a été signé - ID - ID + Verify the message to ensure it was signed with the specified Bitcoin address + Vérifier le message pour vous assurer qu'il a bien été signé par l'adresse Bitcoin spécifiée - Range: - Intervalle : + Verify &Message + Vérifier le &message - to - à + Reset all verify message fields + Réinitialiser tous les champs de vérification de message - UnitDisplayStatusBarControl + SplashScreen - Unit to show amounts in. Click to select another unit. - Unité d'affichage des montants. Cliquer pour choisir une autre unité. + [testnet] + [testnet] - WalletFrame + TrafficGraphWidget - No wallet has been loaded. - Aucun portefeuille de chargé. + KB/s + Ko/s - WalletModel + TransactionDescDialog - Send Coins - Envoyer des pièces + This pane shows a detailed description of the transaction + Ce panneau affiche une description détaillée de la transaction - WalletView - - &Export - &Exporter - - - Export the data in the current tab to a file - Exporter les données de l'onglet courant vers un fichier - - - Backup Wallet - Sauvegarder le portefeuille - - - Wallet Data (*.dat) - Données de portefeuille (*.dat) - - - Backup Failed - Échec de la sauvegarde - - - There was an error trying to save the wallet data to %1. - Une erreur est survenue lors de l'enregistrement des données de portefeuille vers %1. - - - The wallet data was successfully saved to %1. - Les données de portefeuille ont été enregistrées avec succès vers %1 - + UnitDisplayStatusBarControl - Backup Successful - Sauvegarde réussie + Unit to show amounts in. Click to select another unit. + Unité d'affichage des montants. Cliquer pour choisir une autre unité. @@ -2927,21 +1758,13 @@ If <category> is not supplied or if <category> = 1, output all debugging information. Si <category> n'est pas indiqué ou si <category> = 1, extraire toutes les données de débogage. - - Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s) - Frais totaux maximaux (en %s) à utiliser en une seule transaction de portefeuille. Les définir trop bas pourrait interrompre les grosses transactions (par défaut : %s) - - - Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. - Veuillez vérifier que l'heure et la date de votre ordinateur sont justes ! Si votre horloge n'est pas à l'heure, Bitcoin Core ne fonctionnera pas correctement. - Prune configured below the minimum of %d MiB. Please use a higher number. L'élagage est configuré au-dessous du minimum de %d Mio. Veuillez utiliser un nombre plus élevé. Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node) - Élagage : la dernière synchronisation de portefeuille va par-delà les données élaguées. Vous devez -reindex (réindexer, télécharger de nouveau toute la chaîne de blocs en cas de nœud élagué) + Élagage : la dernière synchronisation de porte-monnaie va par-delà les données élaguées. Vous devez -reindex (réindexer, télécharger de nouveau toute la chaîne de blocs en cas de nœud élagué) Reduce storage requirements by pruning (deleting) old blocks. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, >%u = target size in MiB to use for block files) @@ -2975,6 +1798,10 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Accepter les connexions entrantes (par défaut : 1 si aucun -proxy ou -connect ) + + Bitcoin Core + Bitcoin Core + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. La valeur -fallbackfee est très élevée ! Elle représente les frais de transaction que vous pourriez acquitter si aucune estimation de frais n'est proposée. @@ -2993,15 +1820,31 @@ Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup - Supprimer toutes les transactions du portefeuille et ne récupérer que ces parties de la chaîne de blocs avec -rescan au démarrage + Supprimer toutes les transactions du porte-monnaie et ne récupérer que ces parties de la chaîne de blocs avec -rescan au démarrage Distributed under the MIT software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>. Distribué sous la licence MIT d'utilisation d'un logiciel. Consultez le fichier joint COPYING ou <http://www.opensource.org/licenses/mit-license.php>. + + Error loading %s: You can't enable HD on a already existing non-HD wallet + Erreur de chargement de %s : vous ne pouvez pas activer HD sur un porte-monnaie non HD existant + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) - Exécuter la commande lorsqu'une transaction de portefeuille change (%s dans la commande est remplacée par TxID) + Exécuter la commande lorsqu'une transaction de porte-monnaie change (%s dans la commande est remplacée par TxID) + + + Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds) + Réglage moyen maximal autorisé de décalage de l'heure d'un pair. La perspective locale du temps peut être influencée par les pairs, en avance ou en retard, de cette valeur. (Par défaut : %u secondes) + + + Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s) + Frais totaux maximaux (en %s) à utiliser en une seule transaction de porte-monnaie ou transaction brute ; les définir trop bas pourrait interrompre les grosses transactions (par défaut : %s) + + + Please contribute if you find %s useful. Visit %s for further information about the software. + Si vous trouvez %s utile, vous pouvez y contribuer. Vous trouverez davantage d'informations à propos du logiciel sur %s. Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) @@ -3015,14 +1858,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Ceci est une pré-version de test - l'utiliser à vos risques et périls - ne pas l'utiliser pour miner ou pour des applications marchandes - - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - Impossible de se lier à %s sur cet ordinateur. Bitcoin Core fonctionne probablement déjà. - - - Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. - Argument non pris charge -whitelistalwaysrelay ignoré, utiliser -whitelistrelay et/ou -whitelistforcerelay. - Use UPnP to map the listening port (default: 1 when listening and no -proxy) Utiliser l'UPnP pour mapper le port d'écoute (par défaut : 1 lors de l'écoute et pas de mandataire -proxy) @@ -3039,22 +1874,22 @@ Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Avertissement : le réseau ne semble pas totalement d'accord ! Quelques mineurs semblent éprouver des difficultés. - - Warning: Unknown block versions being mined! It's possible unknown rules are in effect - Avertissement : des versions de blocs inconnues sont minées ! Il est possible que des règles inconnues soient en vigeur - Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Avertissement : nous ne semblons pas être en accord complet avec nos pairs ! Vous pourriez avoir besoin d'effectuer une mise à niveau, ou d'autres nœuds du réseau pourraient avoir besoin d'effectuer une mise à niveau. - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Avertissement : wallet.dat corrompu, données récupérées ! Le fichier wallet.dat original a été enregistré en tant que wallet.{timestamp}.bak dans %s ; si votre solde ou transactions sont incorrects vous devriez effectuer une restauration depuis une sauvegarde. - Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. Pairs de la liste blanche se connectant à partir du masque réseau ou de l'IP donné. Peut être spécifié plusieurs fois. + + You need to rebuild the database using -reindex-chainstate to change -txindex + Vous devez reconstruire la base de données avec -reindex-chainstate pour changer -txindex + + + %s corrupt, salvage failed + %s corrompu, la récupération a échoué + -maxmempool must be at least %d MB -maxmempool doit être d'au moins %d Mo @@ -3067,10 +1902,22 @@ Append comment to the user agent string Ajouter un commentaire à la chaîne d'agent utilisateur + + Attempt to recover private keys from a corrupt wallet on startup + Tenter de récupérer les clefs privées d'un porte-monnaie corrompu lors du démarrage + Block creation options: Options de création de bloc : + + Cannot resolve -%s address: '%s' + Impossible de résoudre l'adresse -%s : « %s » + + + Change index out of range + L'index de changement est hors échelle + Connect only to the specified node(s) Ne se connecter qu'au(x) nœud(s) spécifié(s) @@ -3079,17 +1926,21 @@ Connection options: Options de connexion : + + Copyright (C) %i-%i + Tous droits réservés (C) %i-%i + Corrupted block database detected Base corrompue de données des blocs détectée Debugging/Testing options: - Options de test/de débogage : + Options de débogage/de test : Do not load the wallet and disable wallet RPC calls - Ne pas charger le portefeuille et désactiver les appels RPC + Ne pas charger le porte-monnaie et désactiver les appels RPC Do you want to rebuild the block database now? @@ -3117,7 +1968,23 @@ Error initializing wallet database environment %s! - Erreur lors de l'initialisation de l'environnement de la base de données du portefeuille %s ! + Erreur lors de l'initialisation de l'environnement de la base de données du porte-monnaie %s ! + + + Error loading %s + Erreur lors du chargement de %s + + + Error loading %s: Wallet corrupted + Erreur lors du chargement de %s : porte-monnaie corrompu + + + Error loading %s: Wallet requires newer version of %s + Erreur lors du chargement de %s : le porte-monnaie exige une version plus récente de %s + + + Error loading %s: You can't disable HD on a already existing HD wallet + Erreur de chargement de %s : vous ne pouvez pas désactiver HD sur un porte-monnaie HD existant Error loading block database @@ -3147,6 +2014,10 @@ Invalid -onion address: '%s' Adresse -onion invalide : « %s » + + Invalid amount for -%s=<amount>: '%s' + Montant invalide pour -%s=<amount> : « %s » + Invalid amount for -fallbackfee=<amount>: '%s' Montant invalide pour -fallbackfee=<amount> : « %s » @@ -3155,6 +2026,10 @@ Keep the transaction memory pool below <n> megabytes (default: %u) Garder la réserve de mémoire transactionnelle sous <n> mégaoctets (par défaut : %u) + + Loading banlist... + Chargement de la liste d'interdiction... + Location of the auth cookie (default: data dir) Emplacement du fichier témoin auth (par défaut : data dir) @@ -3171,6 +2046,10 @@ Only connect to nodes in network <net> (ipv4, ipv6 or onion) Seulement se connecter aux nœuds du réseau <net> (IPv4, IPv6 ou oignon) + + Print this help message and exit + Imprimer ce message d'aide et quitter + Print version and exit Imprimer la version et quitter @@ -3183,6 +2062,14 @@ Prune mode is incompatible with -txindex. Le mode élagage n'est pas compatible avec -txindex. + + Rebuild chain state and block index from the blk*.dat files on disk + Reconstruire l'état de la chaîne et l'index des blocs à partir des fichiers blk*.dat sur le disque + + + Rebuild chain state from the currently indexed blocks + Reconstruire l'état de la chaîne à partir des blocs indexés actuellement + Set database cache size in megabytes (%d to %d, default: %d) Définir la taille du cache de la base de données en mégaoctets (%d to %d, default: %d) @@ -3193,7 +2080,11 @@ Specify wallet file (within data directory) - Spécifiez le fichier de portefeuille (dans le répertoire de données) + Spécifiez le fichier de porte-monnaie (dans le répertoire de données) + + + The source code is available from %s. + Le code source est disponible sur %s. Unsupported argument -benchmark ignored, use -debug=bench. @@ -3221,19 +2112,19 @@ Verifying wallet... - Vérification du portefeuille en cours... + Vérification du porte-monnaie en cours... Wallet %s resides outside data directory %s - Le portefeuille %s réside en dehors du répertoire de données %s + Le porte-monnaie %s réside en dehors du répertoire de données %s - Wallet options: - Options du portefeuille : + Wallet debugging/testing options: + Options de débogage/de test du porte-monnaie : - You need to rebuild the database using -reindex to change -txindex - Vous devez reconstruire la base de données en utilisant -reindex afin de modifier -txindex + Wallet options: + Options du porte-monnaie : 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 @@ -3247,13 +2138,9 @@ Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces) Se lier à l'adresse donnée pour écouter des connexions JSON-RPC. Utiliser la notation [host]:port pour l'IPv6. Cette option peut être spécifiée plusieurs fois (par défaut : se lier à toutes les interfaces) - - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - Impossible d’obtenir un verrou sur le répertoire de données %s. Bitcoin Core fonctionne probablement déjà. - Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) - Créer de nouveaux fichiers avec les permissions système par défaut, au lieu de umask 077 (effectif seulement avec la fonction du portefeuille désactivée) + Créer de nouveaux fichiers avec les permissions système par défaut, au lieu de umask 077 (effectif seulement avec la fonction du porte-monnaie désactivée) Discover own IP addresses (default: 1 when listening and no -externalip or -proxy) @@ -3295,10 +2182,6 @@ Set maximum size of high-priority/low-fee transactions in bytes (default: %d) Définir la taille maximale en octets des transactions prioritaires/à frais modiques (par défaut : %d) - - Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) - Définir le nombre de fils de génération de pièces, si elle est activée (-1 = tous les cœurs, par défaut : %d) - The transaction amount is too small to send after the fee has been deducted Le montant de la transaction est trop bas pour être envoyé une fois que les frais ont été déduits @@ -3323,34 +2206,14 @@ Accept public REST requests (default: %u) Accepter les demandes REST publiques (par défaut : %u) - - Activating best chain... - Activation de la meilleure chaîne... - - - Attempt to recover private keys from a corrupt wallet.dat on startup - Tenter de récupérer les clefs privées d'un wallet.dat corrompu lors du démarrage - Automatically create Tor hidden service (default: %d) Créer automatiquement un service caché Tor (par défaut : %d) - - Cannot resolve -whitebind address: '%s' - Impossible de résoudre l'adresse -whitebind : « %s » - Connect through SOCKS5 proxy Se connecter par un mandataire SOCKS5 - - Copyright (C) 2009-%i The Bitcoin Core Developers - Copyright © 2009-%i Les développeurs de Bitcoin Core - - - Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - Erreur lors du chargement de wallet.dat : le portefeuille exige une version plus récente de Bitcoin Core - Error reading from database, shutting down. Erreur de lecture de la base de données, fermeture en cours. @@ -3363,22 +2226,6 @@ Information Informations - - Initialization sanity check failed. Bitcoin Core is shutting down. - L'initialisation du test de cohérence a échoué. Bitcoin est en cours de fermeture. - - - Invalid amount for -maxtxfee=<amount>: '%s' - Montant invalide pour -maxtxfee=<amount> : « %s » - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Montant invalide pour -minrelayfee=<montant> : « %s » - - - Invalid amount for -mintxfee=<amount>: '%s' - Montant invalide pour -mintxfee=<montant> : « %s » - Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) Montant invalide pour -paytxfee=<montant> : « %s » (doit être au moins %s) @@ -3403,21 +2250,13 @@ RPC server options: Options du serveur RPC : - - Rebuild block chain index from current blk000??.dat files on startup - Reconstruire au démarrage l'index de la chaîne de blocs à partir des fichiers blk000??.dat actuels - - - Receive and display P2P network alerts (default: %u) - Recevoir et afficher les alertes du réseau poste à poste (par défaut : %u) - Reducing -maxconnections from %d to %d, because of system limitations. Réduction de -maxconnections de %d à %d, due aux restrictions du système Rescan the block chain for missing wallet transactions on startup - Réanalyser la chaîne de blocs au démarrage, à la recherche de transactions de portefeuille manquantes + Réanalyser la chaîne de blocs au démarrage, à la recherche de transactions de porte-monnaie manquantes Send trace/debug info to console instead of debug.log file @@ -3477,16 +2316,12 @@ Upgrade wallet to latest format on startup - Mettre à niveau le portefeuille au démarrage vers le format le plus récent + Mettre à niveau le porte-monnaie au démarrage vers le format le plus récent Username for JSON-RPC connections Nom d'utilisateur pour les connexions JSON-RPC - - Wallet needed to be rewritten: restart Bitcoin Core to complete - Le portefeuille avait besoin d'être réécrit : veuillez redémarrer Bitcoin Core pour terminer - Warning Avertissement @@ -3501,16 +2336,12 @@ Zapping all transactions from wallet... - Supprimer toutes les transactions du portefeuille... + Supprimer toutes les transactions du porte-monnaie... ZeroMQ notification options: Options de notification ZeroMQ - - wallet.dat corrupt, salvage failed - wallet.dat corrompu, la récupération a échoué - Password for JSON-RPC connections Mot de passe pour les connexions JSON-RPC @@ -3519,10 +2350,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) Exécuter la commande lorsque le meilleur bloc change (%s dans cmd est remplacé par le hachage du bloc) - - This help message - Ce message d'aide - Allow DNS lookups for -addnode, -seednode and -connect Autoriser les recherches DNS pour -addnode, -seednode et -connect @@ -3531,10 +2358,6 @@ Loading addresses... Chargement des adresses… - - Error loading wallet.dat: Wallet corrupted - Erreur lors du chargement de wallet.dat : portefeuille corrompu - (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) (1 = conserver les métadonnées de transmission, par ex. les informations du propriétaire du compte et de la demande de paiement, 2 = abandonner les métadonnées de transmission) @@ -3551,10 +2374,6 @@ Do not keep transactions in the mempool longer than <n> hours (default: %u) Ne pas conserver de transactions dans la réserve de mémoire plus de <n> heures (par défaut : %u) - - Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. - Une erreur est survenue lors de la lecture de wallet.dat ! Toutes les clefs ont été lues correctement, mais les données transactionnelles ou les entrées du carnet d'adresses sont peut-être manquantes ou incorrectes. - Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) Les frais (en %s/Ko) inférieurs à ce seuil sont considérés comme étant nuls pour la création de transactions (par défaut : %s) @@ -3591,6 +2410,10 @@ Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported. L'argument non pris en charge -socks a été trouvé. Il n'est plus possible de définir la version de SOCKS, seuls les mandataires SOCKS5 sont pris en charge. + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + Argument non pris charge -whitelistalwaysrelay ignoré, utiliser -whitelistrelay et/ou -whitelistforcerelay. + Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s) Utiliser un serveur mandataire SOCKS5 séparé pour atteindre les pairs par les services cachés de Tor (par défaut : %s) @@ -3600,20 +2423,20 @@ Nom d'utilisateur et mot de passe haché pour les connexions JSON-RPC. Le champ <userpw> vient au format : <USERNAME>:<SALT>$<HASH>. Un script python canonique est inclus dans share/rpcuser. Cette option peut être spécifiée plusieurs fois. - (default: %s) - (par défaut : %s) + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + Avertissement : des versions de blocs inconnues sont minées ! Il est possible que des règles inconnues soient en vigeur - Always query for peer addresses via DNS lookup (default: %u) - Toujours demander les adresses des pairs par recherche DNS (par défaut : %u) + Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup. + Avertissement : le fichier du porte-monnaie est corrompu, les données ont été récupérées ! Le fichier %s original a été enregistré en tant que %s dans %s ; si votre solde ou vos transactions sont incorrects, vous devriez restaurer une sauvegarde. - Error loading wallet.dat - Erreur lors du chargement de wallet.dat + (default: %s) + (par défaut : %s) - Generate coins (default: %u) - Générer des pièces (défaut : %u) + Always query for peer addresses via DNS lookup (default: %u) + Toujours demander les adresses des pairs par recherche DNS (par défaut : %u) How many blocks to check at startup (default: %u, 0 = all) @@ -3641,7 +2464,7 @@ Make the wallet broadcast transactions - Obliger le portefeuille à diffuser les transactions + Obliger le porte-monnaie à diffuser les transactions Maximum per-connection receive buffer, <n>*1000 bytes (default: %u) @@ -3699,18 +2522,6 @@ Unknown network specified in -onlynet: '%s' Réseau inconnu spécifié sur -onlynet : « %s » - - Cannot resolve -bind address: '%s' - Impossible de résoudre l'adresse -bind : « %s » - - - Cannot resolve -externalip address: '%s' - Impossible de résoudre l'adresse -externalip : « %s » - - - Invalid amount for -paytxfee=<amount>: '%s' - Montant invalide pour -paytxfee=<montant> : « %s » - Insufficient funds Fonds insuffisants @@ -3725,11 +2536,11 @@ Loading wallet... - Chargement du portefeuille… + Chargement du porte-monnaie… Cannot downgrade wallet - Impossible de revenir à une version inférieure du portefeuille + Impossible de revenir à une version inférieure du porte-monnaie Cannot write default address diff --git a/src/qt/locale/bitcoin_fr_CA.ts b/src/qt/locale/bitcoin_fr_CA.ts index 7e6925f96f683..fca1e62883dbd 100644 --- a/src/qt/locale/bitcoin_fr_CA.ts +++ b/src/qt/locale/bitcoin_fr_CA.ts @@ -13,29 +13,6 @@ &Delete &Supprimer - - Sending addresses - envoyer adresse de reception - - - Comma separated file (*.csv) - Fichier séparé par une virgule (*.csv) - - - - AddressTableModel - - Label - Record - - - Address - Addresse - - - (no label) - (pas de record) - AskPassphraseDialog @@ -51,46 +28,19 @@ Repeat new passphrase Répéter Mot de Passe - - Encrypt wallet - Encrypter Porte-Feuille - - - This operation needs your wallet passphrase to unlock the wallet. - Cette opération nécessite le mot de passe de votre porte-feuille pour débarrer le porte-feuille. - - - Unlock wallet - Débarrer Porte-Feuille - - - This operation needs your wallet passphrase to decrypt the wallet. - Cette opération nécessite le mot de passe de votre porte-feuille pour le décrypter. - - + BanTableModel BitcoinGUI - - ClientModel - CoinControlDialog (un)select all Toute sélectionner - - Copy address - copier l'adresse - - - (no label) - (pas de record) - EditAddressDialog @@ -102,7 +52,7 @@ &Address Addresse - + FreespaceChecker @@ -125,18 +75,12 @@ OverviewPage - - PaymentServer - PeerTableModel QObject - - QRImageWidget - RPCConsole @@ -145,32 +89,9 @@ ReceiveRequestDialog - - Address - Addresse - - - Label - Record - - - - RecentRequestsTableModel - - Label - Record - - - (no label) - (pas de record) - SendCoinsDialog - - (no label) - (pas de record) - SendCoinsEntry @@ -187,50 +108,12 @@ TrafficGraphWidget - - TransactionDesc - TransactionDescDialog - - TransactionTableModel - - Label - Record - - - - TransactionView - - Copy address - copier l'adresse - - - Comma separated file (*.csv) - Fichier séparé par une virgule (*.csv) - - - Label - Record - - - Address - Addresse - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - - WalletView - bitcoin-core diff --git a/src/qt/locale/bitcoin_fr_FR.ts b/src/qt/locale/bitcoin_fr_FR.ts index 9a2ac551c63eb..f7fd7e6a18e50 100644 --- a/src/qt/locale/bitcoin_fr_FR.ts +++ b/src/qt/locale/bitcoin_fr_FR.ts @@ -25,10 +25,6 @@ C&lose F&ermer - - &Copy Address - &Adresse de copie - Delete the currently selected address from the list Supprimer l'adresse sélectionnée de la liste @@ -45,74 +41,6 @@ &Delete &Supprimer - - Choose the address to send coins to - Choisissez une adresse où envoyer les bitcoins - - - Choose the address to receive coins with - Choisissez une adresse où recevoir les bitcoins - - - C&hoose - C&oisir - - - Sending addresses - Adresses d'envoi - - - Receiving addresses - Adresses de réception - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Voici vos adresses Bitcoin qui vous permettent d'envoyer des paiements. Vérifiez toujours le montant et l'adresse de réception avant d'envoyer des pièces. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Voici vos adresses Bitcoin qui vous permettent de recevoir des paiements. Il est recommandé d'utiliser une nouvelle adresse de réception pour chaque transaction - - - Copy &Label - Copier &Étiquette - - - &Edit - &Éditer - - - Export Address List - Exporter la liste d'adresses - - - Comma separated file (*.csv) - Valeurs séparées par des virgules (*.csv) - - - Exporting Failed - Échec de l'export - - - There was an error trying to save the address list to %1. Please try again. - Il y a eu une erreur durant la tentative de sauvegarde de la liste d’adresse vers %1. -Réessayez. - - - - AddressTableModel - - Label - Étiquette - - - Address - Adresse - - - (no label) - (aucune étiquette) - AskPassphraseDialog @@ -132,86 +60,6 @@ Réessayez. Repeat new passphrase Répétez la phrase de passe - - Encrypt wallet - Chiffrer le porte-monnaie - - - This operation needs your wallet passphrase to unlock the wallet. - Cette opération nécessite votre phrase de passe pour déverrouiller le porte-monnaie. - - - Unlock wallet - Déverrouiller le porte-monnaie - - - This operation needs your wallet passphrase to decrypt the wallet. - Cette opération nécessite votre phrase de passe pour décrypter le porte-monnaie. - - - Decrypt wallet - Décrypter le porte-monnaie - - - Change passphrase - Changer la phrase de passe - - - Confirm wallet encryption - Confirmer le chiffrement du porte-monnaie - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Attention: Si vous cryptez votre portefeuille et que vous perdez votre mot de passe vous <b> PERDREZ TOUS VOS BITCOINS</b>! - - - Are you sure you wish to encrypt your wallet? - Êtes-vous sûr de de vouloir crypter votre portefeuille ? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Bitcoin Core fermera maintenant pour finir le processus de chiffrement. Rappelez-vous que crypter votre portefeuille ne protége pas totalement vos bitcoins d'être volé par un malware ayant infecté votre ordinateur. - - - Warning: The Caps Lock key is on! - Attention : La touche majuscule est enfoncé. - - - Wallet encrypted - Porte-monnaie chiffré - - - Enter the old passphrase and new passphrase to the wallet. - Entrez l'ancien mot de passe et le nouveau mot de passe pour le portefeuille - - - Wallet encryption failed - Le chiffrement du porte-monnaie a échoué - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Le chiffrement du porte-monnaie a échoué en raison d'une erreur interne. Votre porte-monnaie n'a pas été chiffré. - - - The supplied passphrases do not match. - Les phrases de passe entrées ne correspondent pas. - - - Wallet unlock failed - Le déverrouillage du porte-monnaie a échoué - - - The passphrase entered for the wallet decryption was incorrect. - La phrase de passe entrée pour décrypter le porte-monnaie était erronée. - - - Wallet decryption failed - Le décryptage du porte-monnaie a échoué - - - Wallet passphrase was successfully changed. - Le changement du mot de passe du portefeuille à été effectué avec succès. - BanTableModel @@ -262,6 +110,14 @@ Réessayez. Quit application Quitter l'application + + &About %1 + &À propos de %1 + + + Show information about %1 + Afficher les informations sur %1 + About &Qt À propos de &Qt @@ -274,6 +130,10 @@ Réessayez. &Options... &Options... + + Modify configuration options for %1 + Modifier les options de configuration pour %1 + &Encrypt Wallet... &Chiffrer le portefeuille @@ -298,14 +158,6 @@ Réessayez. Open &URI... Ouvrir &URI - - Bitcoin Core client - Client Bitcoin Core - - - Importing blocks from disk... - Importer les blocs depuis le disque... - Reindexing blocks on disk... Réindexer les blocs sur le disque... @@ -350,10 +202,6 @@ Réessayez. &Receive &Réception - - Show information about Bitcoin Core - Montrer les informations à propos de Bitcoin Core - &Show / Hide &Montrer / Cacher @@ -386,22 +234,10 @@ Réessayez. Tabs toolbar Barre d'outils des onglets - - Bitcoin Core - Bitcoin Core - Request payments (generates QR codes and bitcoin: URIs) Demander des paiements (générer QR codes et bitcoin: URIs) - - &About Bitcoin Core - &À propos de Bitcoin - - - Modify configuration options for Bitcoin Core - Modifier les options de configuration de Bitcoin Core - Show the list of used sending addresses and labels Montrer la liste des adresses d'envois utilisées et les étiquettes @@ -521,13 +357,6 @@ Réessayez. Le porte-monnaie est <b>chiffré</b> et est actuellement <b>verrouillé</b> - - ClientModel - - Network Alert - Alerte réseau - - CoinControlDialog @@ -606,142 +435,6 @@ Réessayez. Priority Priorité - - Copy address - Copier l'adresse - - - Copy label - Copier l'étiquette - - - Copy amount - Copier le montant - - - Copy transaction ID - Copie ID transaction - - - Lock unspent - Verrouiller les non dépensés - - - Unlock unspent - Déverrouiller les non dépensés - - - Copy quantity - Copier la quantité - - - Copy fee - Copier les frais - - - Copy after fee - Copier après les frais - - - Copy bytes - Copier les octets - - - Copy priority - Copier la priorité - - - Copy dust - Copier la poussière - - - Copy change - Copier changement - - - highest - le plus élevé - - - higher - plus haute - - - high - haut - - - medium-high - moyen-élevé - - - medium - moyen - - - low-medium - bas-moyen - - - low - bas - - - lower - inférieur - - - lowest - le plus bas - - - (%1 locked) - (%1 verrouillé) - - - none - aucun - - - This label turns red if the transaction size is greater than 1000 bytes. - Cette étiquette devient rouge si la taille de la transaction est plus grande que 1000 octets - - - This label turns red if the priority is smaller than "medium". - Cette étiquette devient rouge si la priorité est plus petite que "moyen" - - - Can vary +/- %1 satoshi(s) per input. - Peut varier de +/- %1 satoshi(s) par entrée. - - - yes - oui - - - no - non - - - This means a fee of at least %1 per kB is required. - Cela signifie que des frais d'au moins %1 par kO sont requis. - - - Can vary +/- 1 byte per input. - Peut varier de +/- 1 octet par entrée. - - - (no label) - (aucune étiquette) - - - change from %1 (%2) - changement de %1 (%2) - - - (change) - (changement) - EditAddressDialog @@ -757,38 +450,6 @@ Réessayez. &Address &Adresse - - New receiving address - Nouvelle adresse de réception - - - New sending address - Nouvelle adresse d'envoi - - - Edit receiving address - Éditer l'adresse de réception - - - Edit sending address - Éditer l'adresse d'envoi - - - The entered address "%1" is already in the address book. - L'adresse fournie « %1 » est déjà présente dans le carnet d'adresses. - - - The entered address "%1" is not a valid Bitcoin address. - L'adresse entrée "%1" n'est pas une adresse Bitcoin valide. - - - Could not unlock wallet. - Impossible de déverrouiller le porte-monnaie. - - - New key generation failed. - Échec de la génération de la nouvelle clef. - FreespaceChecker @@ -811,10 +472,6 @@ Réessayez. HelpMessageDialog - - Bitcoin Core - Bitcoin Core - version version @@ -824,8 +481,8 @@ Réessayez. (%1-bit) - About Bitcoin Core - À propos de Bitcoin Core + About %1 + A propos %1 Command-line options @@ -854,10 +511,6 @@ Réessayez. Welcome Bienvenue - - Welcome to Bitcoin Core. - Bienvenue sur Bitcoin Core. - Use the default data directory Utiliser le répertoire par défaut @@ -866,10 +519,6 @@ Réessayez. Use a custom data directory: Utiliser votre propre répertoire - - Bitcoin Core - Bitcoin Core - Error: Specified data directory "%1" cannot be created. Erreur: Le répertoire de données "%1" n'a pas pu être créé. @@ -905,10 +554,6 @@ Réessayez. Select payment request file Sélectionner un fichier de demande de paiement - - Select payment request file to open - Sélectionnez le fichier de demande de paiement à ouvrir - OptionsDialog @@ -952,10 +597,6 @@ Réessayez. &Network &Réseau - - Automatically start Bitcoin Core after logging in to the system. - Démarrer automatiquement Bitcoin Core après s'être connecté au système. - Expert Expert @@ -1092,45 +733,6 @@ Réessayez. Transactions récentes - - PaymentServer - - Invalid payment address %1 - Adresse de paiement invalide %1 - - - Payment request rejected - Requête de paiement rejetée - - - Payment request is not initialized. - La demande de paiement n'a pas été initialisée. - - - Payment request error - Erreur lors de la requête de paiement - - - Payment request expired. - Demande de paiement expirée. - - - Invalid payment request. - Demande de paiement invalide. - - - Refund from %1 - Remboursement de %1 - - - Bad response from server %1 - Mauvaise réponse du serveur %1 - - - Network request error - Erreur de demande de réseau - - PeerTableModel @@ -1185,25 +787,6 @@ Réessayez. %1 ms - - QRImageWidget - - &Save Image... - &Sauvegarder image - - - &Copy Image - &Copier image - - - Save QR Code - Sauvegarder QR code - - - PNG Image (*.png) - Image PNG (*.png) - - RPCConsole @@ -1366,10 +949,6 @@ Réessayez. Out: Sortie: - - Build date - Date de création - Debug log file Fichier du journal de débogage @@ -1469,18 +1048,6 @@ Réessayez. Remove Retirer - - Copy label - Copier l'étiquette - - - Copy message - Copier message - - - Copy amount - Copier le montant - ReceiveRequestDialog @@ -1500,87 +1067,28 @@ Réessayez. &Save Image... &Sauvegarder image + + + SendCoinsDialog - Request payment to %1 - Demande de paiement à %1 + Send Coins + Envoyer des pièces - Payment information - Informations de paiement + Inputs... + Sorties... - URI - URI + automatically selected + Automatiquement sélectionné - Address - Adresse + Insufficient funds! + Fonds insuffisants - Amount - Montant - - - Label - Étiquette - - - Message - Message - - - - RecentRequestsTableModel - - Date - Date - - - Label - Étiquette - - - Message - Message - - - Amount - Montant - - - (no label) - (aucune étiquette) - - - (no message) - (pas de message) - - - (no amount) - (pas de montant) - - - - SendCoinsDialog - - Send Coins - Envoyer des pièces - - - Inputs... - Sorties... - - - automatically selected - Automatiquement sélectionné - - - Insufficient funds! - Fonds insuffisants - - - Quantity: - Quantité: + Quantity: + Quantité: Bytes: @@ -1666,91 +1174,7 @@ Réessayez. Confirm the send action Confirmer l'action d'envoi - - Confirm send coins - Confirmer l'envoi des pièces - - - %1 to %2 - %1 à %2 - - - Copy quantity - Copier la quantité - - - Copy amount - Copier le montant - - - Copy fee - Copier les frais - - - Copy after fee - Copier après les frais - - - Copy bytes - Copier les octets - - - Copy priority - Copier la priorité - - - Copy change - Copier changement - - - Total Amount %1 - Montant Total %1 - - - or - ou - - - The amount to pay must be larger than 0. - Le montant à payer doit être supérieur à 0. - - - The amount exceeds your balance. - Le montant excède votre balance. - - - Transaction creation failed! - Échec de la création de la transaction - - - Payment request expired. - Demande de paiement expirée. - - - Pay only the required fee of %1 - Payer seulement les frais obligatoire de %1 - - - Warning: Invalid Bitcoin address - Attention: Adresse Bitcoin Invalide - - - (no label) - (aucune étiquette) - - - Copy dust - Copier la poussière - - - Are you sure you want to send? - Êtes-vous sûr de vouloir envoyer ? - - - added as transaction fee - Ajoute en tant que frais de transaction - - + SendCoinsEntry @@ -1761,10 +1185,6 @@ Réessayez. Pay &To: Payer &à : - - Enter a label for this address to add it to your address book - Entrez une étiquette pour cette adresse afin de l'ajouter à votre carnet d'adresses - &Label: &Étiquette : @@ -1859,41 +1279,9 @@ Réessayez. Verify &Message Vérifier &Message - - The entered address is invalid. - L'adresse entrée est invalide. - - - Please check the address and try again. - Vérifiez l'adresse et réessayer. - - - Message signed. - Message signé. - - - Please check the signature and try again. - Vérifiez la signature et réessayer. - - - Message verification failed. - Vérification du message échouée. - - - Message verified. - Message vérifié. - - + SplashScreen - - Bitcoin Core - Bitcoin Core - - - The Bitcoin Core developers - Les développeurs de Bitcoin Core - [testnet] [testnet] @@ -1906,410 +1294,16 @@ Réessayez. KO/s - - TransactionDesc - - Open until %1 - Ouvert jusqu'à %1 - - - %1/unconfirmed - %1/non confirmée - - - %1 confirmations - %1 confirmations - - - Status - État - - - Date - Date - - - Source - Source - - - Generated - Généré - - - From - De - - - To - Á - - - own address - Votre adresse - - - watch-only - Lecture uniquement - - - label - Étiquette - - - Credit - Crédit - - - not accepted - Pas accepté - - - Debit - Débit - - - Total debit - Débit total - - - Total credit - Crédit total - - - Transaction fee - Frais de transaction - - - Net amount - Montant net - - - Message - Message - - - Comment - Commentaire - - - Transaction ID - ID de transaction - - - Merchant - Marchant - - - Debug information - Information de débogage - - - Transaction - Transaction - - - Inputs - Entrées - - - Amount - Montant - - - true - vrai - - - false - faux - - - , has not been successfully broadcast yet - , n'a pas encore été diffusée avec succès - - - Open for %n more block(s) - Ouvert pour %n bloc de plusOuvert pour %n blocs de plus - - - unknown - inconnue - - TransactionDescDialog - - Transaction details - Détails de la transaction - This pane shows a detailed description of the transaction Ce panneau affiche une description détaillée de la transaction - - TransactionTableModel - - Date - Date - - - Type - Type - - - Open for %n more block(s) - Ouvert pour %n bloc de plusOuvert pour %n blocs de plus - - - Open until %1 - Ouvert jusqu'à %1 - - - Confirmed (%1 confirmations) - Confirmée (%1 confirmations) - - - This block was not received by any other nodes and will probably not be accepted! - Ce bloc n'a été reçu par aucun autre nœud et ne sera probablement pas accepté ! - - - Generated but not accepted - Généré mais pas accepté - - - Offline - Hors ligne - - - Label - Étiquette - - - Unconfirmed - Non Confirmé - - - Received with - Reçues avec - - - Received from - Reçue de - - - Sent to - Envoyées à - - - Payment to yourself - Paiement à vous-même - - - Mined - Extraction - - - watch-only - Lecture uniquement - - - (n/a) - (indisponible) - - - Transaction status. Hover over this field to show number of confirmations. - État de la transaction. Laissez le pointeur de la souris sur ce champ pour voir le nombre de confirmations. - - - Date and time that the transaction was received. - Date et heure de réception de la transaction. - - - Type of transaction. - Type de transaction. - - - Amount removed from or added to balance. - Montant ajouté au ou enlevé du solde. - - - - TransactionView - - All - Toutes - - - Today - Aujourd'hui - - - This week - Cette semaine - - - This month - Ce mois - - - Last month - Mois dernier - - - This year - Cette année - - - Range... - Intervalle... - - - Received with - Reçues avec - - - Sent to - Envoyées à - - - To yourself - À vous-même - - - Mined - Extraction - - - Other - Autres - - - Enter address or label to search - Entrez une adresse ou une étiquette à rechercher - - - Min amount - Montant min - - - Copy address - Copier l'adresse - - - Copy label - Copier l'étiquette - - - Copy amount - Copier le montant - - - Copy transaction ID - Copie ID transaction - - - Edit label - Éditer l'étiquette - - - Show transaction details - Afficher les détails de la transaction - - - Export Transaction History - Exporter l'historique des transactions - - - Exporting Failed - Échec de l'export - - - Exporting Successful - Export réalisé avec sucés - - - Comma separated file (*.csv) - Valeurs séparées par des virgules (*.csv) - - - Confirmed - Confirmée - - - Date - Date - - - Type - Type - - - Label - Étiquette - - - Address - Adresse - - - ID - ID - - - Range: - Intervalle : - - - to - à - - UnitDisplayStatusBarControl - - WalletFrame - - No wallet has been loaded. - Aucun portefeuille a été chargé. - - - - WalletModel - - Send Coins - Envoyer des pièces - - - - WalletView - - &Export - &Exporter... - - - Export the data in the current tab to a file - Exporter les données de l'onglet courant vers un fichier - - - Backup Wallet - Sauvegarder le porte-monnaie - - - Wallet Data (*.dat) - Données de porte-monnaie (*.dat) - - - Backup Failed - La sauvegarde a échoué - - - Backup Successful - Sauvegarde réussie - - bitcoin-core @@ -2332,6 +1326,10 @@ Réessayez. Run in the background as a daemon and accept commands Fonctionner en arrière-plan en tant que démon et accepter les commandes + + Bitcoin Core + Bitcoin Core + <category> can be: <category> peut être: @@ -2425,30 +1423,14 @@ Importation ... Password for JSON-RPC connections Mot de passe pour les connexions JSON-RPC - - This help message - Ce message d'aide - Loading addresses... Chargement des adresses... - - Error loading wallet.dat: Wallet corrupted - Erreur lors du chargement de wallet.dat : porte-monnaie corrompu - (default: %s) (défaut: %s) - - Error loading wallet.dat - Erreur lors du chargement de wallet.dat - - - Generate coins (default: %u) - Générer des pièces (défaut: %u) - Invalid -proxy address: '%s' Adresse -proxy invalide: '%s' diff --git a/src/qt/locale/bitcoin_gl.ts b/src/qt/locale/bitcoin_gl.ts index 50b081d20562a..f3673b6dc74f8 100644 --- a/src/qt/locale/bitcoin_gl.ts +++ b/src/qt/locale/bitcoin_gl.ts @@ -21,10 +21,6 @@ C&lose &Pechar - - &Copy Address - &Copiar Dirección - Delete the currently selected address from the list Borrar a dirección actualmente seleccionada da listaxe @@ -41,69 +37,6 @@ &Delete &Borrar - - Choose the address to send coins to - Escolle a dirección á que enviar moedas - - - Choose the address to receive coins with - Escolle a dirección da que recibir moedas - - - C&hoose - &Escoller - - - Sending addresses - Direccións para enviar - - - Receiving addresses - Direccións para recibir - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Estas son as túas direccións Bitcoin para enviar pagos. Revisa sempre a cantidade e a dirección receptora antes de enviar moedas. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Estas son as túas direccións Bitcoin para recibir pagos. Recoméndase empregar unha nova dirección de recepción por cada transacción. - - - Copy &Label - Copiar &Etiqueta - - - &Edit - &Modificar - - - Export Address List - Exportar Lista de Direccións - - - Comma separated file (*.csv) - Arquivo separado por comas (*.csv) - - - Exporting Failed - Exportación falida - - - - AddressTableModel - - Label - Etiqueta - - - Address - Dirección - - - (no label) - (sen etiqueta) - AskPassphraseDialog @@ -123,82 +56,6 @@ Repeat new passphrase Repite novo contrasinal - - Encrypt wallet - Encriptar moedeiro - - - This operation needs your wallet passphrase to unlock the wallet. - Esta operación precisa o contrasinal do teu moedeiro para desbloquear o moedeiro. - - - Unlock wallet - Desbloquear moedeiro - - - This operation needs your wallet passphrase to decrypt the wallet. - Esta operación precisa o contrasinal do teu moedeiro para desencriptar o moedeiro. - - - Decrypt wallet - Desencriptar moedeiro - - - Change passphrase - Cambiar contrasinal - - - Confirm wallet encryption - Confirmar encriptación de moedeiro - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Precaución: Se encriptas o teu moedeiro e perdes o teu contrasinal, ti <b>PERDERÁS TÓDOLOS TEUS BITCOINS</b>! - - - Are you sure you wish to encrypt your wallet? - Estás seguro de que desexas encriptar o teu moedeiro? - - - 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. - IMPORTANTE: Calquera copia de seguridade previa que fixeses do teu arquivo de moedeiro debería ser substituída polo recén xerado arquivo encriptado de moedeiro. Por razóns de seguridade, as copias de seguridade previas de un arquivo de moedeiro desencriptado tornaránse inútiles no momento no que comeces a emprega-lo novo, encriptado, moedeiro. - - - Warning: The Caps Lock key is on! - Precaución: A tecla de Bloqueo de Maiúsculas está activada! - - - Wallet encrypted - Moedeiro encriptado - - - Wallet encryption failed - Encriptación de moedeiro fallida - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - A encriptación do moedeiro fallou por mor dun erro interno. O teu moedeiro non foi encriptado. - - - The supplied passphrases do not match. - Os contrasinais suministrados non coinciden. - - - Wallet unlock failed - Desbloqueo de moedeiro fallido - - - The passphrase entered for the wallet decryption was incorrect. - O contrasinal introducido para a desencriptación do moedeiro foi incorrecto. - - - Wallet decryption failed - Desencriptación de moedeiro fallida - - - Wallet passphrase was successfully changed. - Cambiouse con éxito o contrasinal do moedeiro. - BanTableModel @@ -265,10 +122,6 @@ &Receiving addresses... Direccións para recibir - - Importing blocks from disk... - Importando bloques de disco... - Reindexing blocks on disk... Reindexando bloques no disco... @@ -349,18 +202,10 @@ Tabs toolbar Barra de ferramentas - - Bitcoin Core - Core de Bitcoin - Request payments (generates QR codes and bitcoin: URIs) Solicitar pagos (xenera códigos QR e bitcoin: URIs) - - &About Bitcoin Core - &Sobre Bitcoin Core - Show the list of used sending addresses and labels Amosar a listaxe de direccións e etiquetas para enviar empregadas @@ -430,13 +275,6 @@ O moedeiro está <b>encriptado</b> e actualmente <b>bloqueado</b> - - ClientModel - - Network Alert - Alerta de Rede - - CoinControlDialog @@ -495,110 +333,6 @@ Priority Prioridade - - Copy address - Copiar dirección - - - Copy label - Copiar etiqueta - - - Copy amount - Copiar cantidade - - - Copy transaction ID - Copiar ID de transacción - - - Lock unspent - Bloquear o aforrado - - - Unlock unspent - Desbloquear o aforrado - - - Copy quantity - Copiar cantidade - - - Copy fee - Copiar pago - - - Copy after fee - Copiar despóis do pago - - - Copy bytes - Copiar bytes - - - Copy priority - Copiar prioridade - - - Copy change - Copiar cambio - - - highest - O máis alto - - - higher - Máis alto que - - - high - alto - - - medium-high - medio-alto - - - low-medium - medio-baixo - - - low - baixo - - - lower - máis baixo que - - - lowest - o máis baixo - - - (%1 locked) - (%1 bloqueado) - - - yes - Si - - - no - non - - - Transactions with higher priority are more likely to get included into a block. - As transacción con maior prioridade teñen máis posibilidades de ser incluidas nun bloque - - - (no label) - (sen etiqueta) - - - (change) - (cambio) - EditAddressDialog @@ -622,38 +356,6 @@ &Address &Dirección - - New receiving address - Nova dirección para recibir - - - New sending address - Nova dirección para enviar - - - Edit receiving address - Modificar dirección para recibir - - - Edit sending address - Modificar dirección para enviar - - - The entered address "%1" is already in the address book. - A dirección introducida "%1" xa está no libro de direccións. - - - The entered address "%1" is not a valid Bitcoin address. - A dirección introducida '%1' non é unha dirección Bitcoin válida. - - - Could not unlock wallet. - Non se puido desbloquear o moedeiro. - - - New key generation failed. - A xeración de nova clave fallou. - FreespaceChecker @@ -680,18 +382,10 @@ HelpMessageDialog - - Bitcoin Core - Core de Bitcoin - version versión - - About Bitcoin Core - Sobre Bitcoin core - Command-line options Opcións da liña de comandos @@ -719,10 +413,6 @@ Use a custom data directory: Empregar un directorio de datos personalizado - - Bitcoin Core - Core de Bitcoin - Error Erro @@ -746,10 +436,6 @@ Select payment request file Seleccionar ficheiro de solicitude de pago - - Select payment request file to open - Seleccione ficheiro de solicitude de pago para abrir - OptionsDialog @@ -885,45 +571,6 @@ O teu balance actual total - - PaymentServer - - URI handling - Manexo de URI - - - Invalid payment address %1 - Dirección de pago %1 inválida - - - Requested payment amount of %1 is too small (considered dust). - A cantidade de %1 na solicitude de pado é moi pequena (considerada po). - - - Payment request error - Erro na petición de pago - - - Refund from %1 - Devolución dende %1 - - - Error communicating with %1: %2 - Erro comunicando con %1: %2 - - - Bad response from server %1 - Responsa errónea do servidor %1 - - - Payment acknowledged - Pago admitido - - - Network request error - Erro de solicitude de rede - - PeerTableModel @@ -946,21 +593,6 @@ N/A - - QRImageWidget - - &Save Image... - &Gardar Imaxe... - - - &Copy Image - &Copiar Imaxe - - - Save QR Code - Gardar Código QR - - RPCConsole @@ -1035,10 +667,6 @@ Out: Fóra: - - Build date - Data de construción - Debug log file Arquivo de log de depuración @@ -1106,15 +734,7 @@ &Request payment &Solicitar pago - - Copy label - Copiar etiqueta - - - Copy amount - Copiar cantidade - - + ReceiveRequestDialog @@ -1133,66 +753,7 @@ &Save Image... &Gardar Imaxe... - - Request payment to %1 - Solicitar pago a %1 - - - Payment information - Información de Pago - - - URI - URI - - - Address - Dirección - - - Amount - Cantidade - - - Label - Etiqueta - - - Message - Mensaxe - - - Resulting URI too long, try to reduce the text for label / message. - A URI resultante é demasiado larga, tenta reducir o texto para a etiqueta / mensaxe. - - - Error encoding URI into QR Code. - Erro codificando URI nun Código QR. - - - RecentRequestsTableModel - - Date - Data - - - Label - Etiqueta - - - Message - Mensaxe - - - Amount - Cantidade - - - (no label) - (sen etiqueta) - - SendCoinsDialog @@ -1259,108 +820,36 @@ S&end &Enviar + + + SendCoinsEntry - Confirm send coins - Confirmar envío de moedas + A&mount: + &Cantidade: - %1 to %2 - %1 a %2 + Pay &To: + Pagar &A: - Copy quantity - Copiar cantidade + &Label: + &Etiqueta: - Copy amount - Copiar cantidade + Choose previously used address + Escoller dirección previamente empregada - Copy fee - Copiar pago + This is a normal payment. + Este é un pago normal - Copy after fee - Copiar despóis do pago + Alt+A + Alt+A - Copy bytes - Copiar bytes - - - Copy priority - Copiar prioridade - - - Copy change - Copiar cambio - - - The amount to pay must be larger than 0. - A cantidade a pagar debe ser maior que 0. - - - The amount exceeds your balance. - A cantidade sobrepasa o teu balance. - - - The total exceeds your balance when the %1 transaction fee is included. - O total sobrepasa o teu balance cando se inclúe a tarifa de transacción %1. - - - Warning: Invalid Bitcoin address - Atención: Enderezo Bitcoin non válido - - - (no label) - (sen etiqueta) - - - Warning: Unknown change address - Atención: Enderezo de cambio desconocido - - - Are you sure you want to send? - Seguro que queres enviar? - - - added as transaction fee - engadido como tarifa de transacción - - - - SendCoinsEntry - - A&mount: - &Cantidade: - - - Pay &To: - Pagar &A: - - - Enter a label for this address to add it to your address book - Introduce unha etiqueta para esta dirección para engadila ao teu libro de direccións - - - &Label: - &Etiqueta: - - - Choose previously used address - Escoller dirección previamente empregada - - - This is a normal payment. - Este é un pago normal - - - Alt+A - Alt+A - - - Paste address from clipboard - Pegar dirección dende portapapeis + Paste address from clipboard + Pegar dirección dende portapapeis Alt+P @@ -1460,69 +949,9 @@ Reset all verify message fields Restaurar todos os campos de verificación de mensaxe - - Click "Sign Message" to generate signature - Click en "Asinar Mensaxe" para xerar sinatura - - - The entered address is invalid. - A dirección introducida é inválida. - - - Please check the address and try again. - Por favor comproba a dirección e proba de novo. - - - The entered address does not refer to a key. - A dirección introducida non se refire a ninguna clave. - - - Wallet unlock was cancelled. - Cancelouse o desbloqueo do moedeiro. - - - Private key for the entered address is not available. - A clave privada da dirección introducida non está dispoñible. - - - Message signing failed. - Fallou a sinatura da mensaxe. - - - Message signed. - Mensaxe asinada. - - - The signature could not be decoded. - A sinatura non puido ser decodificada. - - - Please check the signature and try again. - Por favor revise a sinatura e probe de novo. - - - The signature did not match the message digest. - A sinatura non coincide co resumo da mensaxe. - - - Message verification failed. - A verificación da mensaxe fallou. - - - Message verified. - Mensaxe verificada. - SplashScreen - - Bitcoin Core - Core de Bitcoin - - - The Bitcoin Core developers - Os desarrolladores de Bitcoin Core - [testnet] [testnet] @@ -1535,402 +964,16 @@ KB/s - - TransactionDesc - - Open until %1 - Aberto ata %1 - - - %1/offline - %1/fóra de liña - - - %1/unconfirmed - %1/sen confirmar - - - %1 confirmations - %1 confirmacións - - - Status - Estado - - - Date - Data - - - Source - Orixe - - - Generated - Xerado - - - From - Dende - - - To - A - - - own address - dirección propia - - - label - etiqueta - - - Credit - Crédito - - - not accepted - non aceptado - - - Debit - Débito - - - Transaction fee - Tarifa de transacción - - - Net amount - Cantidade neta - - - Message - Mensaxe - - - Comment - Comentario - - - Transaction ID - ID de Transacción - - - Merchant - Comerciante - - - 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. - As moedas xeradas deben madurar %1 bloques antes de que poidan ser gastadas. Cando xeraste este bloque, foi propagado á rede para ser engadido á cadeas de bloques. Se falla ao tentar meterse na cadea, o seu estado cambiará a "non aceptado" e non poderá ser gastado. Esto pode ocorrir ocasionalmente se outro nodo xera un bloque en poucos segundos de diferencia co teu. - - - Debug information - Información de depuración - - - Transaction - Transacción - - - Inputs - Entradas - - - Amount - Cantidade - - - true - verdadeiro - - - false - falso - - - , has not been successfully broadcast yet - , non foi propagado con éxito todavía - - - unknown - descoñecido - - TransactionDescDialog - - Transaction details - Detalles de transacción - This pane shows a detailed description of the transaction Este panel amosa unha descripción detallada da transacción - - TransactionTableModel - - Date - Data - - - Type - Tipo - - - Open until %1 - Aberto ata %1 - - - Confirmed (%1 confirmations) - Confirmado (%1 confirmacións) - - - This block was not received by any other nodes and will probably not be accepted! - Este bloque non foi recibido por ningún outro nodo e probablemente non será aceptado! - - - Generated but not accepted - Xerado pero non aceptado - - - Label - Etiqueta - - - Received with - Recibido con - - - Received from - Recibido de - - - Sent to - Enviado a - - - Payment to yourself - Pago a ti mesmo - - - Mined - Minado - - - (n/a) - (n/a) - - - Transaction status. Hover over this field to show number of confirmations. - Estado da transacción. Pasa por riba deste campo para amosar o número de confirmacións. - - - Date and time that the transaction was received. - Data e hora na que foi recibida a transacción. - - - Type of transaction. - Tipo de transacción. - - - Amount removed from or added to balance. - Cantidade borrada ou engadida no balance. - - - - TransactionView - - All - Todo - - - Today - Hoxe - - - This week - Esta semana - - - This month - Este mes - - - Last month - O último mes - - - This year - Este ano - - - Range... - Periodo... - - - Received with - Recibido con - - - Sent to - Enviado a - - - To yourself - A ti mesmo - - - Mined - Minado - - - Other - Outro - - - Enter address or label to search - Introduce dirección ou etiqueta para buscar - - - Min amount - Cantidade mínima - - - Copy address - Copiar dirección - - - Copy label - Copiar etiqueta - - - Copy amount - Copiar cantidade - - - Copy transaction ID - Copiar ID de transacción - - - Edit label - Modificar etiqueta - - - Show transaction details - Amosar detalles da transacción - - - Export Transaction History - Exportar Historial de Transaccións - - - Exporting Failed - Exportación falida - - - There was an error trying to save the transaction history to %1. - Houbo un erro intentando salvar o historial de transaccións a %1. - - - Exporting Successful - Exportado correctamente - - - The transaction history was successfully saved to %1. - O historial de transaccións foi salvado correctamente en %1. - - - Comma separated file (*.csv) - Arquivo separado por comas (*.csv) - - - Confirmed - Confirmado - - - Date - Data - - - Type - Tipo - - - Label - Etiqueta - - - Address - Dirección - - - ID - ID - - - Range: - Periodo: - - - to - a - - UnitDisplayStatusBarControl - - WalletFrame - - No wallet has been loaded. - Ningún moedeiro cargado - - - - WalletModel - - Send Coins - Moedas Enviadas - - - - WalletView - - &Export - &Exportar - - - Export the data in the current tab to a file - Exportar os datos da pestaña actual a un arquivo. - - - Backup Wallet - Copia de Seguridade de Moedeiro - - - Wallet Data (*.dat) - Datos de Moedeiro (*.dat) - - - Backup Failed - Copia de Seguridade Fallida - - - There was an error trying to save the wallet data to %1. - Houbo un erro intentando gardar os datos de moedeiro en %1. - - - The wallet data was successfully saved to %1. - Os datos do moedeiro foron gardados correctamente en %1. - - - Backup Successful - Copia de Seguridade Correcta - - bitcoin-core @@ -1961,6 +1004,10 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Aceptar conexións de fóra (por defecto: 1 se non -proxy ou -connect) + + Bitcoin Core + Core de Bitcoin + Bind to given address and always listen on it. Use [host]:port notation for IPv6 Enlazar a unha dirección dada e escoitar sempre nela. Emprega a notación [host]:post para IPv6 @@ -1981,10 +1028,6 @@ Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Precaución: Non parece que esteamos totalmente de acordo cos nosos pares! Pode que precises actualizar, ou outros nodos poden precisar actualizarse. - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Precaución: wallet.dat corrupto, datos salvagardados! O wallet.dat orixinal foi gardado como wallet.{timestamp}.bak en %s; se o teu balance ou transaccións son incorrectas deberías restauralas dende unha copia de seguridade. - <category> can be: <categoría> pode ser: @@ -2057,34 +1100,14 @@ Wallet %s resides outside data directory %s O moedeiro %s reside fóra do directorio de datos %s - - You need to rebuild the database using -reindex to change -txindex - Precisas reconstruír a base de datos empregando -reindex para cambiar -txindex - Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message) Executar comando cando se recibe unha alerta relevante ou vemos un fork realmente longo (%s no cmd é substituído pola mensaxe) - - Cannot resolve -whitebind address: '%s' - Non se pode resolver dirección -whitebind: '%s' - Information Información - - Invalid amount for -maxtxfee=<amount>: '%s' - Cantidade inválida para -maxtxfee=<cantidade>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Cantidade inválida para -minrelaytxfee=<cantidade>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - Cantidade inválida para -mintxfee=<cantidade>: '%s' - Send trace/debug info to console instead of debug.log file Enviar traza/información de depuración á consola en lugar de ao arquivo debug.log @@ -2117,10 +1140,6 @@ Warning Precaución - - wallet.dat corrupt, salvage failed - wallet.dat corrupto, fallou o gardado - Password for JSON-RPC connections Contrasinal para conexións JSON-RPC @@ -2129,10 +1148,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) Executar comando cando o mellor bloque cambie (%s no comando é sustituído polo hash do bloque) - - This help message - Esta mensaxe de axuda - Allow DNS lookups for -addnode, -seednode and -connect Permitir lookup de DNS para -addnote, -seednote e -connect @@ -2141,14 +1156,6 @@ Loading addresses... Cargando direccións... - - Error loading wallet.dat: Wallet corrupted - Erro cargando wallet.dat: Moedeiro corrupto - - - Error loading wallet.dat - Erro cargando wallet.dat - Invalid -proxy address: '%s' Dirección -proxy inválida: '%s' @@ -2157,18 +1164,6 @@ Unknown network specified in -onlynet: '%s' Rede descoñecida especificada en -onlynet: '%s' - - Cannot resolve -bind address: '%s' - Non se pode resolver a dirección -bind: '%s' - - - Cannot resolve -externalip address: '%s' - Non se pode resolver dirección -externalip: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - Cantidade inválida para -paytxfee=<cantidade>: '%s' - Insufficient funds Fondos insuficientes diff --git a/src/qt/locale/bitcoin_he.ts b/src/qt/locale/bitcoin_he.ts index d937e211b0f1a..fbe16364eb82a 100644 --- a/src/qt/locale/bitcoin_he.ts +++ b/src/qt/locale/bitcoin_he.ts @@ -3,7 +3,7 @@ AddressBookPage Right-click to edit address or label - לחץ משק ימני כדי לערוך כתובת או חברה + לחץ מקש ימני כדי לערוך כתובת או תווית Create a new address @@ -11,7 +11,7 @@ &New - &חדשה + &חדש Copy the currently selected address to the system clipboard @@ -25,10 +25,6 @@ C&lose סגירה - - &Copy Address - העתקת כתובת - Delete the currently selected address from the list מחיקת הכתובת שנבחרה מהרשימה @@ -45,73 +41,6 @@ &Delete מ&חיקה - - Choose the address to send coins to - נא לבחור את הכתובת המבוקשת לשליחת המטבעות - - - Choose the address to receive coins with - נא לבחור את הכתובת המבוקשת לקבלת המטבעות - - - C&hoose - בחירה - - - Sending addresses - כתובות לשליחה - - - Receiving addresses - כתובות לקבלה - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - אלה כתובת הביטקוין שלך לצורך שליחת תשלומים. תמיד יש לבדוק את הכמות ואת כתובות מקבלי התשלומים לפני שליחת מטבעות. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - אלה כתובות הביטקוין שלך לצורך קבלת תשלומים. מומלץ להשתמש בכתובת קבלה חדשה לכל העברה. - - - Copy &Label - העתקת &תווית - - - &Edit - ע&ריכה - - - Export Address List - יצוא רשימת כתובות - - - Comma separated file (*.csv) - קובץ מופרד בפסיקים (‎*.csv) - - - Exporting Failed - היצוא נכשל - - - There was an error trying to save the address list to %1. Please try again. - אירעה שגיאה בעת הניסיון לשמור את רשימת הכתובת אל %1. נא לנסות שוב. - - - - AddressTableModel - - Label - תווית - - - Address - כתובת - - - (no label) - (אין תווית) - AskPassphraseDialog @@ -131,98 +60,14 @@ Repeat new passphrase נא לחזור על מילת הצופן החדשה - - Encrypt wallet - הצפנת הארנק - - - This operation needs your wallet passphrase to unlock the wallet. - פעולה זו דורשת את מילת הצופן של הארנק שלך כדי לפתוח את הארנק. - - - Unlock wallet - פתיחת ארנק - - - This operation needs your wallet passphrase to decrypt the wallet. - פעולה זו דורשת את מילת הצופן של הארנק שלך כדי לפענח את הארנק. - - - Decrypt wallet - פענוח ארנק - - - Change passphrase - שינוי מילת צופן - - - Confirm wallet encryption - אישור הצפנת הארנק - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - אזהרה: הצפנת הארנק ואיבוד מילת הצופן עשויה להוביל <b>לאיבוד כל הביטקוינים שלך</b>! - - - Are you sure you wish to encrypt your wallet? - האם אכן להצפין את הארנק? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - ליבת ביטקוין תיסגר עכשיו כדי לסיים את תליך ההצפנה. זכור כי הצפנה אינה יכולה להגן עלייך באופן מלא מגניבה שמקורה בתוכנות זדוניות המצויות במחשב שלך. - - - 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. - לתשומת לבך: כל גיבוי קודם שביצעת לארנק שלך יש להחליף בקובץ הארנק המוצפן שזה עתה נוצר. מטעמי אבטחה, גיבויים קודמים של קובץ הארנק הבלתי-מוצפן יהפכו לחסרי תועלת עם התחלת השימוש בארנק החדש המוצפן. - - - Warning: The Caps Lock key is on! - זהירות: מקש Caps Lock פעיל! - - - Wallet encrypted - הארנק הוצפן - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - נא להזין את מילת הצופן החדשה לארנק.<br/>כדאי להשתמש במילת צופן המורכבת מ<b>עשרה תווים אקראיים ומעלה</b>, או <b>שמונה מילים ומעלה</b>. - - - Enter the old passphrase and new passphrase to the wallet. - הכנס את מילת הצופן הישנה ומילת צופן חדשה לארנק שלך. - - - Wallet encryption failed - הצפנת הארנק נכשלה - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - הצפנת הארנק נכשלה עקב שגיאה פנימית. הארנק שלך לא הוצפן. - - - The supplied passphrases do not match. - מילות הצופן שסופקו אינן תואמות. - - - Wallet unlock failed - פתיחת הארנק נכשלה - - - The passphrase entered for the wallet decryption was incorrect. - מילת הצופן שהוכנסה לפענוח הארנק שגויה. - - - Wallet decryption failed - פענוח הארנק נכשל - - - Wallet passphrase was successfully changed. - מילת הצופן של הארנק שונתה בהצלחה. - BanTableModel - + + Banned Until + חסום עד + + BitcoinGUI @@ -261,6 +106,14 @@ Quit application יציאה מהתכנית + + &About %1 + &אודות %1 + + + Show information about %1 + הצג מידע על %1 + About &Qt על אודות Qt @@ -297,14 +150,6 @@ Open &URI... פתיחת &כתובת משאב… - - Bitcoin Core client - לקוח ליבה של ביטקוין - - - Importing blocks from disk... - מקטעים מיובאים מהכונן… - Reindexing blocks on disk... המקטעים נוספים למפתח בכונן… @@ -349,10 +194,6 @@ &Receive &קבלה - - Show information about Bitcoin Core - הצגת מידע על ליבת ביטקוין - &Show / Hide ה&צגה / הסתרה @@ -389,18 +230,10 @@ Tabs toolbar סרגל כלים לשוניות - - Bitcoin Core - ליבת ביטקוין - Request payments (generates QR codes and bitcoin: URIs) בקשת תשלומים (יצירה של קודים מסוג QR וסכימות כתובות משאב של :bitcoin) - - &About Bitcoin Core - על &אודות ליבת ביטקוין - Show the list of used sending addresses and labels הצג את רשימת הכתובות לשליחה שהיו בשימוש לרבות התוויות @@ -418,8 +251,8 @@ אפשרויות &שורת הפקודה - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - הצגת הודעות העזרה של ליבת ביטקוין כדי לקבל רשימה עם אפשרויות שורת הפקודה האפשריות של ביטקוין + Processing blocks on disk... + מעבד בלוקים על הדיסק... No block source available... @@ -479,14 +312,11 @@ - ClientModel + CoinControlDialog - Network Alert - אזעקת רשת + Coin Selection + בחירת מטבע - - - CoinControlDialog Quantity: כמות: @@ -535,6 +365,14 @@ Amount כמות + + Received with label + התקבל עם תווית + + + Received with address + התקבל עם כתובת + Date תאריך @@ -551,138 +389,6 @@ Priority עדיפות - - Copy address - העתקת כתובת - - - Copy label - העתקת תווית - - - Copy amount - העתקת כמות - - - Copy transaction ID - העתקת מזהה העברה - - - Lock unspent - נעילת יתרה - - - Unlock unspent - פתיחת יתרה - - - Copy quantity - העתקת כמות - - - Copy fee - העתקת עמלה - - - Copy after fee - העתקת אחרי עמלה - - - Copy bytes - העתקת בתים - - - Copy priority - העתקת עדיפות - - - Copy dust - העתקת אבק - - - Copy change - העתקת עודף - - - highest - הגבוה ביותר - - - higher - גבוה יותר - - - high - גבוה - - - medium-high - בינוני - גבוה - - - medium - בינוני - - - low-medium - בינוני - נמוך - - - low - נמוך - - - lower - נמוך יותר - - - lowest - הנמוך ביותר - - - (%1 locked) - (%1 נעול) - - - none - ללא - - - Can vary +/- %1 satoshi(s) per input. - יכולה להשתנות ב+/- %1 סטושי לקלט. - - - yes - כן - - - no - לא - - - This means a fee of at least %1 per kB is required. - זאת אומרת שנחוצה עמלה של לא פחות מ־%1 לכל קילו בית. - - - Can vary +/- 1 byte per input. - הערך יכול להיות +/- בית אחד לכל קלט. - - - Transactions with higher priority are more likely to get included into a block. - העברות עם עדיפות גבוהה, יותר סיכוי שיכנסו לתוך המקטע. - - - (no label) - (אין תווית) - - - change from %1 (%2) - עודף מ־%1 (%2) - - - (change) - (עודף) - EditAddressDialog @@ -706,38 +412,6 @@ &Address &כתובת - - New receiving address - כתובת חדשה לקבלה - - - New sending address - כתובת חדשה לשליחה - - - Edit receiving address - עריכת כתובת לקבלה - - - Edit sending address - עריכת כתובת לשליחה - - - The entered address "%1" is already in the address book. - הכתובת שהוכנסה „%1“ כבר נמצאת בפנקס הכתובות. - - - The entered address "%1" is not a valid Bitcoin address. - הכתובת שהוכנסה „%1“ אינה כתובת ביטקוין תקנית. - - - Could not unlock wallet. - פתיחת הארנק נכשלה. - - - New key generation failed. - יצירת מפתח חדש נכשלה. - FreespaceChecker @@ -764,10 +438,6 @@ HelpMessageDialog - - Bitcoin Core - ליבת ביטקוין - version גרסה @@ -776,10 +446,6 @@ (%1-bit) (%1-סיביות) - - About Bitcoin Core - על אודות ליבת ביטקוין - Command-line options אפשרויות שורת פקודה @@ -792,24 +458,28 @@ command-line options אפשרויות שורת פקודה - - - Intro - Welcome - ברוך בואך + UI Options: + אפשרויות ממשק + + + Start minimized + התחל ממוזער - Welcome to Bitcoin Core. - ברוך בואך לליבת ביטקוין + Reset all settings changed in the GUI + איפוס כל שינויי הגדרות התצוגה + + + Intro - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - מכיוון שזאת הפעם הראשונה שהתכנית פועלת ניתן לבחור איפה ליבת ביטקוין תאחסן את הנתונים שלה. + Welcome + ברוך בואך - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - לקוח ביטקוין יוריד וישמור העתק של שרשרת המקטעים של ביטקוין. לפחות %1 ג״ב מהנתונים יאוחסנו בתיקייה זו, והיא תגדל עם הזמן. הארנק גם יאוחסן בתיקייה הזו. + Welcome to %1. + ברוך הבא ל %1. Use the default data directory @@ -819,10 +489,6 @@ Use a custom data directory: שימוש בתיקיית נתונים מותאמת אישית: - - Bitcoin Core - ליבת ביטקוין - Error: Specified data directory "%1" cannot be created. שגיאה: לא ניתן ליצור את תיקיית הנתונים שצוינה „%1“. @@ -850,10 +516,6 @@ Select payment request file בחירת קובץ בקשת תשלום - - Select payment request file to open - בחירת קובץ בקשת תשלום לפתיחה - OptionsDialog @@ -957,6 +619,18 @@ Port of the proxy (e.g. 9050) הפתחה של המתווך (למשל 9050) + + IPv4 + IPv4 + + + IPv6 + IPv6 + + + Tor + Tor + &Window &חלון @@ -1080,6 +754,10 @@ Your current balance in watch-only addresses המאזן הנוכחי שלך בכתובות לקריאה בלבד + + Spendable: + ניתנים לבזבוז + Recent transactions העברות אחרונות @@ -1098,155 +776,57 @@ - PaymentServer + PeerTableModel - URI handling - תפעול כתובות משאב + User Agent + סוכן משתמש - Invalid payment address %1 - כתובת תשלום שגויה %1 + Ping Time + זמן המענה + + + QObject - Payment request rejected - בקשת התשלום נדחתה + Amount + כמות - Payment request network doesn't match client network. - רשת בקשת התשלום אינה תואמת לרשת הלקוח. + Enter a Bitcoin address (e.g. %1) + נא להזין כתובת ביטקוין (למשל: %1) - Payment request is not initialized. - בקשת התשלום לא החלה. + %1 d + %1 ימים - Requested payment amount of %1 is too small (considered dust). - הסכום על סך %1 הנדרש לתשלום קטן מדי (נחשב לאבק) + %1 h + %1 שעות - Payment request error - שגיאה בבקשת תשלום + %1 m + %1 דקות - Cannot start bitcoin: click-to-pay handler - לא ניתן להתחיל את ביטקוין: טיפול בלחיצה–לתשלום + %1 s + %1 שניות - Payment request fetch URL is invalid: %1 - כתובת אחזור בקשת התשלום שגויה: %1 + None + ללא - URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - לא ניתן לנתח את כתובת המשאב! מצב זה יכול לקרות עקב כתובת ביטקוין שגויה או פרמטרים שגויים בכתובת המשאב. + N/A + לא זמין - Payment request file handling - טיפול בקובצי בקשות תשלום + %1 ms + %1 מילישניות - - Payment request file cannot be read! This can be caused by an invalid payment request file. - לא ניתן לקרוא את קובץ בקשת התשלום! מצב כזה יכול לקרות בעקבות קובץ בקשת תשלום פגום. - - - Unverified payment requests to custom payment scripts are unsupported. - בקשות תשלום בלתי מאומתות לסקריפטים לתשלום מותאמים אישית אינן נתמכות. - - - Refund from %1 - החזר מ־%1 - - - Error communicating with %1: %2 - שגיאה בתקשורת עם %1: %2 - - - Payment request cannot be parsed! - לא ניתן לפענח את בקשת התשלום! - - - Bad response from server %1 - מענה שגוי משרת %1 - - - Payment acknowledged - התשלום התקבל - - - Network request error - שגיאת בקשת שרת - - - - PeerTableModel - - User Agent - סוכן משתמש - - - Ping Time - זמן המענה - - - - QObject - - Amount - כמות - - - Enter a Bitcoin address (e.g. %1) - נא להזין כתובת ביטקוין (למשל: %1) - - - %1 d - %1 ימים - - - %1 h - %1 שעות - - - %1 m - %1 דקות - - - %1 s - %1 שניות - - - None - ללא - - - N/A - לא זמין - - - %1 ms - %1 מילישניות - - - - QRImageWidget - - &Save Image... - &שמירת תמונה… - - - &Copy Image - ה&עתקת תמונה - - - Save QR Code - שמירת קוד QR - - - PNG Image (*.png) - תמונת PNG ‏(‎*.png) - - - - RPCConsole + + + RPCConsole Client name שם לקוח @@ -1275,6 +855,10 @@ Using BerkeleyDB version שימוש ב־BerkeleyDB גרסה + + Datadir + Datadir + Startup time זמן עלייה @@ -1299,6 +883,18 @@ Current number of blocks מספר המקטעים הנוכחי + + Memory Pool + מאגר זכרון + + + Current number of transactions + מספר הפעולה הנוכחי + + + Memory usage + שימוש בזכרון + Received התקבלו @@ -1311,10 +907,18 @@ &Peers &עמיתים + + Banned peers + משתמשים חסומים + Select a peer to view detailed information. נא לבחור בעמית כדי להציג מידע מפורט. + + Whitelisted + ברשימה הלבנה + Direction כיוון @@ -1323,10 +927,26 @@ Version גרסה + + Starting Block + בלוק התחלה + + + Synced Blocks + בלוקים מסונכרנים + User Agent סוכן משתמש + + Decrease font size + הקטן גודל גופן + + + Increase font size + הגדל גודל גופן + Services שירותים @@ -1351,6 +971,10 @@ Ping Time זמן המענה + + Time Offset + הפרש זמן + Last block time זמן המקטע האחרון @@ -1383,10 +1007,6 @@ Out: יוצא: - - Build date - תאריך בנייה - Debug log file קובץ יומן ניפוי @@ -1395,6 +1015,22 @@ Clear console ניקוי מסוף הבקרה + + Ban Node for + חסום משתמש ל + + + 1 &day + 1& יום + + + 1 &week + 1 & שבוע + + + 1 &year + 1 & שנה + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. יש להשתמש בחצים למעלה ולמטה כדי לנווט בהיסטוריה, וב־<b>Ctrl-L</b> כדי לנקות את המסך. @@ -1518,18 +1154,6 @@ Remove הסרה - - Copy label - העתקת תווית - - - Copy message - העתקת הודעה - - - Copy amount - העתקת כמות - ReceiveRequestDialog @@ -1549,73 +1173,6 @@ &Save Image... &שמירת תמונה… - - Request payment to %1 - בקשת תשלום לטובת %1 - - - Payment information - מידע על תשלום - - - URI - כתובת משאב - - - Address - כתובת - - - Amount - כמות - - - Label - תווית - - - Message - הודעה - - - Resulting URI too long, try to reduce the text for label / message. - כתובת המשאב המתקבלת ארוכה מדי, כדאי לנסות לצמצם את הטקסט בתווית / הודעה. - - - Error encoding URI into QR Code. - שגיאה בקידוד כתובת משאב לקוד QR - - - - RecentRequestsTableModel - - Date - תאריך - - - Label - תווית - - - Message - הודעה - - - Amount - כמות - - - (no label) - (אין תווית) - - - (no message) - (אין הודעה) - - - (no amount) - (אין סכום) - SendCoinsDialog @@ -1680,120 +1237,72 @@ עמלת העברה: - Send to multiple recipients at once - שליחה למספר מוטבים בו־זמנית - - - Add &Recipient - הוספת &מוטב - - - Clear all fields of the form. - ניקוי של כל השדות בטופס. - - - Dust: - אבק: - - - Clear &All - &ניקוי הכול - - - Balance: - מאזן: - - - Confirm the send action - אישור פעולת השליחה - - - S&end - &שליחה - - - Confirm send coins - אישור שליחת מטבעות - - - %1 to %2 - %1 אל %2 + Choose... + בחר... - Copy quantity - העתקת כמות + per kilobyte + עבור קילו-בית - Copy amount - העתקת כמות + Hide + הסתר - Copy fee - העתקת עמלה + total at least + סה''כ לפחות - Copy after fee - העתקת אחרי עמלה + Recommended: + מומלץ: - Copy bytes - העתקת בתים + Custom: + מותאם אישית: - Copy priority - העתקת עדיפות + Confirmation time: + זמן האישור: - Copy change - העתקת עודף + normal + רגיל - or - או + fast + מהיר - The amount to pay must be larger than 0. - הכמות לתשלום חייבת להיות גדולה מ־0. - - - The amount exceeds your balance. - הכמות עולה על המאזן שלך. - - - The total exceeds your balance when the %1 transaction fee is included. - הכמות הכוללת, ובכללה עמלת העברה בסך %1, עולה על המאזן שלך. - - - Transaction creation failed! - יצירת ההעברה נכשלה! + Send to multiple recipients at once + שליחה למספר מוטבים בו־זמנית - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - ההעברה נדחתה! מצב כזה עשוי לקרות אם חלק מהמטבעות בארנק שלך כבר הושקעו, כמו למשל עקב שימוש בעותק של wallet.dat והמטבעות הושקעו בעותק אבל לא סומנו כאילו הושקעו דרך כאן. + Add &Recipient + הוספת &מוטב - Warning: Invalid Bitcoin address - אזהרה: כתובת ביטקוין שגויה + Clear all fields of the form. + ניקוי של כל השדות בטופס. - (no label) - (אין תווית) + Dust: + אבק: - Warning: Unknown change address - אזהרה: כתובת עודף בלתי ידועה + Clear &All + &ניקוי הכול - Copy dust - העתקת אבק + Balance: + מאזן: - Are you sure you want to send? - האם אכן לשלוח? + Confirm the send action + אישור פעולת השליחה - added as transaction fee - נוסף כעמלת העברה + S&end + &שליחה @@ -1806,10 +1315,6 @@ Pay &To: לשלם ל&טובת: - - Enter a label for this address to add it to your address book - נא להכניס תווית לכתובת הזאת כדי להוסיף לפנקס הכתובות - &Label: ת&ווית: @@ -1846,6 +1351,10 @@ Message: הודעה: + + This is an authenticated payment request. + זוהי בקשה מאומתת לתשלום. + Enter a label for this address to add it to the list of used addresses יש להזין תווית עבור כתובת זו כדי להוסיף אותה לרשימת הכתובות בשימוש @@ -1865,10 +1374,6 @@ ShutdownWindow - - Bitcoin Core is shutting down... - ליבת ביטקוין נסגרת… - Do not shut down the computer until this window disappears. אין לכבות את המחשב עד שחלון זה נעלם. @@ -1952,558 +1457,76 @@ Reset all verify message fields איפוס כל שדות אימות ההודעה + + + SplashScreen - Click "Sign Message" to generate signature - יש ללחוץ על „חתימה על ההודעה“ כדי לחולל חתימה + [testnet] + [רשת-בדיקה] + + + TrafficGraphWidget - The entered address is invalid. - הכתובת שהוכנסה אינה תקינה. + KB/s + ק״ב/ש׳ + + + TransactionDescDialog - Please check the address and try again. - נא לבדוק את הכתובת לנסות שנית. + This pane shows a detailed description of the transaction + חלונית זו מציגה תיאור מפורט של ההעברה + + + UnitDisplayStatusBarControl - The entered address does not refer to a key. - הכתובת שהוכנסה אינה מתייחסת למפתח. + Unit to show amounts in. Click to select another unit. + יחידת המידה להצגת הסכומים. יש ללחוץ כדי לבחור ביחידת מידה אחרת. + + + bitcoin-core - Wallet unlock was cancelled. - פתיחת הארנק בוטלה. + Options: + אפשרויות: - Private key for the entered address is not available. - המפתח הפרטי עבור הכתובת שהוכנסה אינו זמין. + Specify data directory + ציון תיקיית נתונים - Message signing failed. - החתימה על ההודעה נכשלה. + Connect to a node to retrieve peer addresses, and disconnect + יש להתחבר למפרק כדי לדלות כתובות עמיתים ואז להתנתק - Message signed. - ההודעה נחתמה. + Specify your own public address + נא לציין את הכתובת הפומבית שלך - The signature could not be decoded. - לא ניתן לפענח את החתימה. + Accept command line and JSON-RPC commands + קבלת פקודות משורת הפקודה ומ־JSON-RPC - Please check the signature and try again. - נא לבדוק את החתימה ולנסות שנית. + Error: A fatal internal error occurred, see debug.log for details + שגיאה: סניה קלמה קריטית פנימית קרטה, פנה ל debug.log לפרטים - The signature did not match the message digest. - החתימה לא תואמת את תקציר ההודעה. + Run in the background as a daemon and accept commands + ריצה כסוכן ברקע וקבלת פקודות - Message verification failed. - אימות ההודעה נכשל. - - - Message verified. - ההודעה אומתה. + Accept connections from outside (default: 1 if no -proxy or -connect) + קבלת חיבורים מבחוץ (בררת מחדל: 1 ללא ‎-proxy או ‎-connect) - - - SplashScreen Bitcoin Core ליבת ביטקוין - The Bitcoin Core developers - מתכנתי ליבת ביטקוין - - - [testnet] - [רשת-בדיקה] - - - - TrafficGraphWidget - - KB/s - ק״ב/ש׳ - - - - TransactionDesc - - Open until %1 - פתוחה עד %1 - - - conflicted - מתנגש - - - %1/offline - %1/מנותק - - - %1/unconfirmed - %1/המתנה לאישור - - - %1 confirmations - %1 אישורים - - - Status - מצב - - - Date - תאריך - - - Source - מקור - - - Generated - נוצר - - - From - מאת - - - To - אל - - - own address - כתובת עצמית - - - watch-only - צפייה בלבד - - - label - תווית - - - Credit - זיכוי - - - not accepted - לא התקבל - - - Debit - חיוב - - - Total debit - סך כל החיוב - - - Total credit - סך כל האשראי - - - Transaction fee - עמלת העברה - - - Net amount - כמות נקייה - - - Message - הודעה - - - Comment - הערה - - - Transaction ID - מזהה העברה - - - Merchant - סוחר - - - 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. - מטבעות חדשים שנוצרו חייבים להבשיל במשך %1 מקטעים לפני שניתן לנצל אותם. כשמקטע זה נוצר הוא משודר ברשת על מנת שייכנס לשרשרת המקטעים. אם הוא לא ייכנס לשרשרת, מצבו ישתנה ל„לא התקבל“ ולא ניתן יהיה לנצלו. מצב כזה יכול לקרות מדי פעם אם במקרה מפרק אחר יצר מקטע בהבדל של שניות בודדות ממך. - - - Debug information - מידע ניפוי - - - Transaction - העברה - - - Inputs - קלטים - - - Amount - כמות - - - true - אמת - - - false - שקר - - - , has not been successfully broadcast yet - , טרם שודר בהצלחה - - - unknown - לא ידוע - - - - TransactionDescDialog - - Transaction details - פרטי ההעברה - - - This pane shows a detailed description of the transaction - חלונית זו מציגה תיאור מפורט של ההעברה - - - - TransactionTableModel - - Date - תאריך - - - Type - סוג - - - Immature (%1 confirmations, will be available after %2) - לא בשל (%1 אישורים, יהיו זמינים לאחר %2) - - - Open until %1 - פתוחה עד %1 - - - Confirmed (%1 confirmations) - מאושר (%1 אישורים) - - - This block was not received by any other nodes and will probably not be accepted! - המקטע הזה לא נקלט על ידי אף מפרק אחר, וכנראה לא יתקבל! - - - Generated but not accepted - נוצר אך לא התקבל - - - Offline - מנותק - - - Label - תווית - - - Unconfirmed - ללא אישור - - - Confirming (%1 of %2 recommended confirmations) - מתקבל אישור (%1 מתוך %2 אישורים מומלצים) - - - Conflicted - מתנגש - - - Received with - התקבל עם - - - Received from - התקבל מאת - - - Sent to - נשלח אל - - - Payment to yourself - תשלום לעצמך - - - Mined - נכרה - - - watch-only - צפייה בלבד - - - (n/a) - (לא זמין) - - - Transaction status. Hover over this field to show number of confirmations. - מצב ההעברה. יש להמתין עם הסמן מעל שדה זה כדי לראות את מספר האישורים. - - - Date and time that the transaction was received. - התאריך והשעה בה ההעברה הזאת התקבלה. - - - Type of transaction. - סוג ההעברה. - - - Whether or not a watch-only address is involved in this transaction. - האם כתובות לצפייה בלבד מעורבות בהעברה זאת או שלא. - - - Amount removed from or added to balance. - הכמות שהתווספה או הוסרה מהיתרה. - - - - TransactionView - - All - הכול - - - Today - היום - - - This week - השבוע - - - This month - החודש - - - Last month - החודש שעבר - - - This year - השנה - - - Range... - טווח… - - - Received with - התקבל עם - - - Sent to - נשלח אל - - - To yourself - לעצמך - - - Mined - נכרה - - - Other - אחר - - - Enter address or label to search - נא להכניס כתובת או תווית לחיפוש - - - Min amount - כמות מזערית - - - Copy address - העתקת כתובת - - - Copy label - העתקת תווית - - - Copy amount - העתקת כמות - - - Copy transaction ID - העתקת מזהה העברה - - - Edit label - עריכת תווית - - - Show transaction details - הצגת פרטי העברה - - - Export Transaction History - יצוא היסטוריית העברות - - - Watch-only - צפייה בלבד - - - Exporting Failed - היצוא נכשל - - - There was an error trying to save the transaction history to %1. - אירעה שגיאה בעת ניסיון לשמור את היסטוריית ההעברות אל %1. - - - Exporting Successful - היצוא בוצע בהצלחה - - - The transaction history was successfully saved to %1. - היסטוריית ההעברות נשמרה ל־%1 בהצלחה. - - - Comma separated file (*.csv) - קובץ מופרד בפסיקים (‎*.csv) - - - Confirmed - מאושר - - - Date - תאריך - - - Type - סוג - - - Label - תווית - - - Address - כתובת - - - ID - מזהה - - - Range: - טווח: - - - to - אל - - - - UnitDisplayStatusBarControl - - Unit to show amounts in. Click to select another unit. - יחידת המידה להצגת הסכומים. יש ללחוץ כדי לבחור ביחידת מידה אחרת. - - - - WalletFrame - - No wallet has been loaded. - לא נטען ארנק - - - - WalletModel - - Send Coins - שליחת מטבעות - - - - WalletView - - &Export - י&צוא - - - Export the data in the current tab to a file - יצוא הנתונים מהלשונית הנוכחית לקובץ - - - Backup Wallet - גיבוי ארנק - - - Wallet Data (*.dat) - נתוני ארנק (‎*.dat) - - - Backup Failed - גיבוי נכשל - - - There was an error trying to save the wallet data to %1. - אירעה שגיאה בעת ניסיון לשמירת נתוני הארנק אל %1. - - - The wallet data was successfully saved to %1. - נתוני הארנק נשמרו בהצלחה אל %1. - - - Backup Successful - הגיבוי הושלם בהצלחה - - - - bitcoin-core - - Options: - אפשרויות: - - - Specify data directory - ציון תיקיית נתונים - - - Connect to a node to retrieve peer addresses, and disconnect - יש להתחבר למפרק כדי לדלות כתובות עמיתים ואז להתנתק - - - Specify your own public address - נא לציין את הכתובת הפומבית שלך - - - Accept command line and JSON-RPC commands - קבלת פקודות משורת הפקודה ומ־JSON-RPC - - - Run in the background as a daemon and accept commands - ריצה כסוכן ברקע וקבלת פקודות - - - Accept connections from outside (default: 1 if no -proxy or -connect) - קבלת חיבורים מבחוץ (בררת מחדל: 1 ללא ‎-proxy או ‎-connect) + The %s developers + ה %s מפתחים Bind to given address and always listen on it. Use [host]:port notation for IPv6 @@ -2521,10 +1544,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications זוהי בניית ניסיון טרום-שחרור - השימוש בה על אחריותך - אין להשתמש לצורך כריה או יישומי מסחר - - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - לא ניתן להתאגד אל %s במחשב זה. כנראה שליבת ביטקוין כבר פועלת. - Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. אזהרה: נראה שלא כל הרשת מסכימה! נראה שישנם כורים שנתקלים בבעיות. @@ -2533,10 +1552,6 @@ Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. אזהרה: נראה שישנה אי־הסכמה בינינו לבין שאר העמיתים שלנו! יתכן שעדיף לשדרג או שכל שאר העמיתים צריכים לשדרג. - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - אזהרה: הקובץ wallet.dat הושחת, המידע חולץ! קובץ ה־wallet.dat המקורי נשמר בשם wallet.{timestamp}.bak במיקום %s; אם המאזן או ההעברות שגויים עליך לשחזר גיבוי. - <category> can be: <קטגוריה> יכולה להיות: @@ -2545,6 +1560,10 @@ Block creation options: אפשרויות יצירת מקטע: + + Change index out of range + אינדקס העודף מחוץ לתחום + Connect only to the specified node(s) התחבר רק לצמתים המצוינים @@ -2577,6 +1596,10 @@ Error initializing wallet database environment %s! שגיאה באתחול סביבת מסד נתוני הארנקים %s! + + Error loading %s + שגיאה בטעינת %s + Error loading block database שגיאה בטעינת מסד נתוני המקטעים @@ -2605,6 +1628,10 @@ Invalid -onion address: '%s' כתובת onion- שגויה: '%s' + + Loading banlist... + טוען רשימת חסומים... + Not enough file descriptors available. אין מספיק מידע על הקובץ @@ -2613,6 +1640,10 @@ Only connect to nodes in network <net> (ipv4, ipv6 or onion) תמיד להתחבר למפרקים ברשת <net>‏ (ipv4,‏ ipv6 או onion) + + Print version and exit + הדפס גירסא וצא + Set database cache size in megabytes (%d to %d, default: %d) הגדרת גודל מטמון מסדי הנתונים במגה בתים (%d עד %d, בררת מחדל: %d) @@ -2638,53 +1669,29 @@ הארנק %s יושב מחוץ לתיקיית הנתונים %s - Wallet options: - אפשרויות הארנק: + Wallet debugging/testing options: + אפשרות דיבוג/בדיקת ארנק: - You need to rebuild the database using -reindex to change -txindex - עליך לבנות מחדש את מסד הנתונים תוך שימוש ב־‎-reindex על מנת לשנות את ‎-txindex + Wallet options: + אפשרויות הארנק: Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message) הרץ פקודה כאשר ההתראה הרלוונטית מתקבלת או כשאנחנו עדים לפיצול ארוך מאוד (%s בשורת הפקודה יוחלף ע"י ההודעה) - Cannot resolve -whitebind address: '%s' - לא ניתן לפתור את הכתובת ‎-whitebind:‏ '%s' + The transaction amount is too small to send after the fee has been deducted + סכום העברה נמוך מדי לשליחה אחרי גביית העמלה Connect through SOCKS5 proxy התחברות דרך מתווך SOCKS5 - - Copyright (C) 2009-%i The Bitcoin Core Developers - כל הזכויות שמורות (C)‏ 2009‏-%i מתכנתי ליבת ביטקוין - - - Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - אירעה שגיאה בטעינת wallet.dat: הארנק דורש גרסה חדשה יותר של ליבת ביטקוין - Information מידע - - Initialization sanity check failed. Bitcoin Core is shutting down. - בדיקת התקינות ההתחלתית נכשלה. ליבת ביטקוין תיסגר כעת. - - - Invalid amount for -maxtxfee=<amount>: '%s' - כמות לא תקינה עבור -maxtxfee=<amount>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - כמות לא תקינה עבור -paytxfee=<amount>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - כמות לא תקינה עבור ‎-mintxfee=<amount>‎:‏ '%s' - Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) כמות לא תקינה עבור ‎-paytxfee=<amount>‎:‏ '%s' (חייבת להיות לפחות %s) @@ -2721,6 +1728,10 @@ Signing transaction failed החתימה על ההעברה נכשלה + + The transaction amount is too small to pay the fee + סכום ההעברה נמוך מכדי לשלם את העמלה + This is experimental software. זוהי תכנית נסיונית. @@ -2733,6 +1744,10 @@ Transaction amounts must be positive סכומי ההעברות חייבים להיות חיוביים + + Transaction too large for fee policy + ההעברה גבוהה מדי עבור מדיניות העמלות + Transaction too large סכום ההעברה גדול מדי @@ -2742,21 +1757,17 @@ לא ניתן להתאגד עם הפתחה %s במחשב זה (פעולת האיגוד החזירה את השגיאה %s) - Username for JSON-RPC connections - שם משתמש לחיבורי JSON-RPC + Upgrade wallet to latest format on startup + עדכן ארק לפורמט העדכני בהפעלה - Wallet needed to be rewritten: restart Bitcoin Core to complete - יש לכתוב את הארנק מחדש: נא להפעיל את ליבת ביטקוין מחדש כדי להשלים את הפעולה + Username for JSON-RPC connections + שם משתמש לחיבורי JSON-RPC Warning אזהרה - - wallet.dat corrupt, salvage failed - קובץ wallet.dat מושחת, החילוץ נכשל - Password for JSON-RPC connections ססמה לחיבורי JSON-RPC @@ -2765,10 +1776,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) יש לבצע פקודה זו כשהמקטע הטוב ביותר משתנה (%s בפקודה יוחלף בגיבוב המקטע) - - This help message - הודעת העזרה הזו - Allow DNS lookups for -addnode, -seednode and -connect הפעלת בדיקת DNS עבור ‎-addnode,‏ ‎-seednode ו־‎-connect @@ -2778,12 +1785,8 @@ הכתובות בטעינה… - Error loading wallet.dat: Wallet corrupted - שגיאה בטעינת הקובץ wallet.dat: הארנק מושחת - - - Error loading wallet.dat - שגיאה בטעינת הקובץ wallet.dat + (default: %s) + (ברירת מחדל: %s) Invalid -proxy address: '%s' @@ -2793,18 +1796,6 @@ Unknown network specified in -onlynet: '%s' רשת לא ידועה צוינה דרך ‎-onlynet:‏ '%s' - - Cannot resolve -bind address: '%s' - לא ניתן לפתור את הכתובת ‎-bind:‏ '%s' - - - Cannot resolve -externalip address: '%s' - לא ניתן לפתור את הכתובת ‎-externalip:‏ '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - כמות לא תקינה עבור ‎-paytxfee=<amount>‎:‏ '%s' - Insufficient funds אין מספיק כספים diff --git a/src/qt/locale/bitcoin_hi_IN.ts b/src/qt/locale/bitcoin_hi_IN.ts index 377ff3a3faf10..86c53b4ce3dfd 100644 --- a/src/qt/locale/bitcoin_hi_IN.ts +++ b/src/qt/locale/bitcoin_hi_IN.ts @@ -9,41 +9,10 @@ Copy the currently selected address to the system clipboard चुनिन्दा पते को सिस्टम क्लिपबोर्ड पर कापी करे ! - - &Copy Address - &पता कॉपी करे - &Delete &मिटाए !! - - Copy &Label - &लेबल कॉपी करे - - - &Edit - &एडिट - - - Comma separated file (*.csv) - Comma separated file (*.csv) - - - - AddressTableModel - - Label - लेबल - - - Address - पता - - - (no label) - (कोई लेबल नही !) - AskPassphraseDialog @@ -59,63 +28,7 @@ Repeat new passphrase दोबारा नया पहचान शब्द/अक्षर डालिए ! - - Encrypt wallet - एनक्रिप्ट वॉलेट ! - - - This operation needs your wallet passphrase to unlock the wallet. - वॉलेट खोलने के आपका वॉलेट पहचान शब्द्‌/अक्षर चाईए ! - - - Unlock wallet - वॉलेट खोलिए - - - This operation needs your wallet passphrase to decrypt the wallet. - वॉलेट डीक्रिप्ट( विकोड) करने के लिए आपका वॉलेट पहचान शब्द्‌/अक्षर चाईए ! - - - Decrypt wallet - डीक्रिप्ट वॉलेट - - - Change passphrase - पहचान शब्द/अक्षर बदलिये ! - - - Confirm wallet encryption - वॉलेट एनक्रिपशन को प्रमाणित कीजिए ! - - - Wallet encrypted - वॉलेट एनक्रिप्ट हो गया ! - - - Wallet encryption failed - वॉलेट एनक्रिप्ट नही हुआ! - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - वॉलेट एनक्रिपशन नाकाम हो गया इंटर्नल एरर की वजह से! आपका वॉलेट एनक्रीपत नही हुआ है! - - - The supplied passphrases do not match. - आपके द्वारा डाले गये पहचान शब्द/अक्षर मिलते नही है ! - - - Wallet unlock failed - वॉलेट का लॉक नही खुला ! - - - The passphrase entered for the wallet decryption was incorrect. - वॉलेट डीक्रिप्ट करने के लिए जो पहचान शब्द/अक्षर डाले गये है वो सही नही है! - - - Wallet decryption failed - वॉलेट का डीक्रिप्ट-ष्ण असफल ! - - + BanTableModel @@ -223,9 +136,6 @@ वॉलेट एन्क्रिप्टेड है तथा अभी लॉक्ड है - - ClientModel - CoinControlDialog @@ -244,22 +154,6 @@ Confirmed पक्का - - Copy address - पता कॉपी करे - - - Copy label - लेबल कॉपी करे - - - Copy amount - कॉपी राशि - - - (no label) - (कोई लेबल नही !) - EditAddressDialog @@ -275,34 +169,6 @@ &Address &पता - - New receiving address - नया स्वीकार्य पता - - - New sending address - नया भेजने वाला पता - - - Edit receiving address - एडिट स्वीकार्य पता - - - Edit sending address - एडिट भेजने वाला पता - - - The entered address "%1" is already in the address book. - डाला गया पता "%1" एड्रेस बुक में पहले से ही मोजूद है| - - - Could not unlock wallet. - वॉलेट को unlock नहीं किया जा सकता| - - - New key generation failed. - नयी कुंजी का निर्माण असफल रहा| - FreespaceChecker @@ -354,9 +220,6 @@ फार्म - - PaymentServer - PeerTableModel @@ -372,9 +235,6 @@ - - QRImageWidget - RPCConsole @@ -397,52 +257,13 @@ &Label: लेबल: - - Copy label - लेबल कॉपी करे - - - Copy amount - कॉपी राशि - - + ReceiveRequestDialog Copy &Address &पता कॉपी करे - - Address - पता - - - Amount - राशि - - - Label - लेबल - - - - RecentRequestsTableModel - - Date - taareek - - - Label - लेबल - - - Amount - राशि - - - (no label) - (कोई लेबल नही !) - SendCoinsDialog @@ -466,22 +287,6 @@ Confirm the send action भेजने की पुष्टि करें - - Confirm send coins - सिक्के भेजने की पुष्टि करें - - - Copy amount - कॉपी राशि - - - The amount to pay must be larger than 0. - भेजा गया अमाउंट शुन्य से अधिक होना चाहिए| - - - (no label) - (कोई लेबल नही !) - SendCoinsEntry @@ -493,10 +298,6 @@ Pay &To: प्राप्तकर्ता: - - Enter a label for this address to add it to your address book - आपकी एड्रेस बुक में इस एड्रेस के लिए एक लेबल लिखें - &Label: लेबल: @@ -550,274 +351,16 @@ TrafficGraphWidget - - TransactionDesc - - Open until %1 - खुला है जबतक %1 - - - %1/unconfirmed - %1/अपुष्ट - - - %1 confirmations - %1 पुष्टियाँ - - - Date - taareek - - - Transaction ID - ID - - - Amount - राशि - - - true - सही - - - false - ग़लत - - - , has not been successfully broadcast yet - , अभी तक सफलतापूर्वक प्रसारित नहीं किया गया है - - - unknown - अज्ञात - - TransactionDescDialog - - Transaction details - लेन-देन का विवरण - This pane shows a detailed description of the transaction ये खिड़की आपको लेन-देन का विस्तृत विवरण देगी ! - - TransactionTableModel - - Date - taareek - - - Type - टाइप - - - Open until %1 - खुला है जबतक %1 - - - Confirmed (%1 confirmations) - पक्के ( %1 पक्का करना) - - - This block was not received by any other nodes and will probably not be accepted! - यह ब्लॉक किसी भी और नोड को मिला नही है ! शायद यह ब्लॉक कोई भी नोड स्वीकारे गा नही ! - - - Generated but not accepted - जेनरेट किया गया किंतु स्वीकारा नही गया ! - - - Label - लेबल - - - Received with - स्वीकार करना - - - Received from - स्वीकार्य ओर से - - - Sent to - भेजा गया - - - Payment to yourself - भेजा खुद को भुगतान - - - Mined - माइंड - - - (n/a) - (लागू नहीं) - - - Transaction status. Hover over this field to show number of confirmations. - ट्रांसेक्शन स्तिथि| पुष्टियों की संख्या जानने के लिए इस जगह पर माउस लायें| - - - Date and time that the transaction was received. - तारीख तथा समय जब ये ट्रांसेक्शन प्राप्त हुई थी| - - - Type of transaction. - ट्रांसेक्शन का प्रकार| - - - Amount removed from or added to balance. - अमाउंट बैलेंस से निकला या जमा किया गया | - - - - TransactionView - - All - सभी - - - Today - आज - - - This week - इस हफ्ते - - - This month - इस महीने - - - Last month - पिछले महीने - - - This year - इस साल - - - Range... - विस्तार... - - - Received with - स्वीकार करना - - - Sent to - भेजा गया - - - To yourself - अपनेआप को - - - Mined - माइंड - - - Other - अन्य - - - Enter address or label to search - ढूँदने के लिए कृपा करके पता या लेबल टाइप करे ! - - - Min amount - लघुत्तम राशि - - - Copy address - पता कॉपी करे - - - Copy label - लेबल कॉपी करे - - - Copy amount - कॉपी राशि - - - Edit label - एडिट लेबल - - - Comma separated file (*.csv) - Comma separated file (*.csv) - - - Confirmed - पक्का - - - Date - taareek - - - Type - टाइप - - - Label - लेबल - - - Address - पता - - - ID - ID - - - Range: - विस्तार: - - - to - तक - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - Send Coins - सिक्के भेजें| - - - - WalletView - - Backup Wallet - बैकप वॉलेट - - - Wallet Data (*.dat) - वॉलेट डेटा (*.dat) - - - Backup Failed - बैकप असफल - - - Backup Successful - बैकप सफल - - bitcoin-core diff --git a/src/qt/locale/bitcoin_hr.ts b/src/qt/locale/bitcoin_hr.ts index f9d744aa3ec37..0d8d3d5c99e78 100644 --- a/src/qt/locale/bitcoin_hr.ts +++ b/src/qt/locale/bitcoin_hr.ts @@ -25,10 +25,6 @@ C&lose &Zatvori - - &Copy Address - &Kopiraj adresu - Delete the currently selected address from the list Brisanje trenutno odabrane adrese s popisa. @@ -45,73 +41,6 @@ &Delete Iz&briši - - Choose the address to send coins to - Odaberi adresu na koju šalješ novac - - - Choose the address to receive coins with - Odaberi adresu na koju primaš novac - - - C&hoose - &Odaberi - - - Sending addresses - Adresa za slanje - - - Receiving addresses - Adresa za primanje - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Ovo su vaše Bitcoin adrese za slanje novca. Uvijek provjerite iznos i adresu primatelja prije slanja novca. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Ovo su vaše Bitcoin adrese za primanje novca. Preporučamo da koristite novu adresu za primanje za svaku transakciju. - - - Copy &Label - Kopiraj &oznaku - - - &Edit - &Uredi - - - Export Address List - Izvezi listu adresa - - - Comma separated file (*.csv) - Datoteka podataka odvojenih zarezima (*.csv) - - - Exporting Failed - Izvoz neuspješan - - - There was an error trying to save the address list to %1. Please try again. - Došlo je do pogreške kod spremanja liste adresa na %1. Molimo pokušajte ponovno. - - - - AddressTableModel - - Label - Oznaka - - - Address - Adresa - - - (no label) - (bez oznake) - AskPassphraseDialog @@ -131,90 +60,6 @@ Repeat new passphrase Ponovite novu lozinku - - Encrypt wallet - Šifriranje novčanika - - - This operation needs your wallet passphrase to unlock the wallet. - Ova operacija treba lozinku vašeg novčanika kako bi se novčanik otključao. - - - Unlock wallet - Otključaj novčanik - - - This operation needs your wallet passphrase to decrypt the wallet. - Ova operacija treba lozinku vašeg novčanika kako bi se novčanik dešifrirao. - - - Decrypt wallet - Dešifriranje novčanika. - - - Change passphrase - Promjena lozinke - - - Confirm wallet encryption - Potvrdi šifriranje novčanika - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Upozorenje: Ako šifrirate vaš novčanik i izgubite lozinku, <b>IZGUBIT ĆETE SVE SVOJE BITCOINE!</b> - - - Are you sure you wish to encrypt your wallet? - Jeste li sigurni da želite šifrirati svoj novčanik? - - - 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. - VAŽNO: Sve prethodne pričuve vašeg novčanika trebale bi biti zamijenjene novo stvorenom, šifriranom datotekom novčanika. Zbog sigurnosnih razloga, prethodne pričuve nešifriranog novčanika će postati beskorisne čim počnete koristiti novi, šifrirani novčanik. - - - Warning: The Caps Lock key is on! - Upozorenje: Tipka Caps Lock je uključena! - - - Wallet encrypted - Novčanik šifriran - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Unesite novu lozinku za novčanik. <br/>Molimo Vas da koristite zaporku od <b>deset ili više slučajnih znakova</b>, ili <b>osam ili više riječi.</b> - - - Enter the old passphrase and new passphrase to the wallet. - Unesite staru i novu lozinku za novčanik. - - - Wallet encryption failed - Šifriranje novčanika nije uspjelo - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Šifriranje novčanika nije uspjelo zbog interne pogreške. Vaš novčanik nije šifriran. - - - The supplied passphrases do not match. - Priložene lozinke se ne podudaraju. - - - Wallet unlock failed - Otključavanje novčanika nije uspjelo - - - The passphrase entered for the wallet decryption was incorrect. - Lozinka za dešifriranje novčanika nije točna. - - - Wallet decryption failed - Dešifriranje novčanika nije uspjelo - - - Wallet passphrase was successfully changed. - Lozinka novčanika je uspješno promijenjena. - BanTableModel @@ -257,6 +102,10 @@ Quit application Izlazak iz programa + + &About %1 + &Više o %1 + About &Qt Više o &Qt @@ -293,14 +142,6 @@ Open &URI... Otvori &URI... - - Bitcoin Core client - Bitcoin Core klijent - - - Importing blocks from disk... - Importiranje blokova sa diska... - Reindexing blocks on disk... Re-indeksiranje blokova na disku... @@ -345,10 +186,6 @@ &Receive Pri&mi - - Show information about Bitcoin Core - Prikaži informacije o programu Bitcoin Core - &Show / Hide Po&kaži / Sakrij @@ -385,22 +222,10 @@ Tabs toolbar Traka kartica - - Bitcoin Core - Bitcoin Core - Request payments (generates QR codes and bitcoin: URIs) Zatraži uplatu (stvara QR kod i bitcoin: URI adresu) - - &About Bitcoin Core - &O programu Bitcoin Core - - - Modify configuration options for Bitcoin Core - Promijeni postavke programa - Show the list of used sending addresses and labels Prikaži popis korištenih adresa i oznaka za slanje novca @@ -417,10 +242,6 @@ &Command-line options Opcije &naredbene linije - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Ispis svih opcija naredbene linije programa sa kratkim opisom - %n active connection(s) to Bitcoin network %n aktivna veza na Bitcoin mrežu%n aktivnih veza na Bitcoin mrežu%n aktivnih veza na Bitcoin mrežu @@ -524,9 +345,6 @@ Novčanik je <b>šifriran</b> i trenutno <b>zaključan</b> - - ClientModel - CoinControlDialog @@ -593,87 +411,7 @@ Priority Prioriteta - - Copy address - Kopiraj adresu - - - Copy label - Kopiraj oznaku - - - Copy amount - Kopiraj iznos - - - Copy transaction ID - Kopiraj ID transakcije - - - highest - najviša - - - higher - viša - - - high - visoka - - - medium-high - srednje visoka - - - medium - srednja - - - low-medium - srednje niska - - - low - niska - - - lower - niža - - - lowest - najniža - - - This label turns red if the transaction size is greater than 1000 bytes. - Oznaka postane crvene boje ako je transakcija veća od 1000 bajtova. - - - This label turns red if the priority is smaller than "medium". - Oznaka postane crvene boje ako je prioriteta transakcije niža od "srednja" - - - This label turns red if any recipient receives an amount smaller than %1. - Oznaka postane crvene boje ako je iznos manji od %1 - - - yes - da - - - no - ne - - - Transactions with higher priority are more likely to get included into a block. - Transakcije više prioritete imaju veću vjerojatnost da budu prije dodane u novi blok. - - - (no label) - (bez oznake) - - + EditAddressDialog @@ -696,38 +434,6 @@ &Address &Adresa - - New receiving address - Nova adresa za primanje - - - New sending address - Nova adresa za slanje - - - Edit receiving address - Uredi adresu za primanje - - - Edit sending address - Uredi adresu za slanje - - - The entered address "%1" is already in the address book. - Upisana adresa "%1" je već u adresaru. - - - The entered address "%1" is not a valid Bitcoin address. - Upisana adresa "%1" nije valjana bitcoin adresa. - - - Could not unlock wallet. - Ne mogu otključati novčanik. - - - New key generation failed. - Stvaranje novog ključa nije uspjelo. - FreespaceChecker @@ -746,10 +452,6 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin Core - version verzija @@ -758,10 +460,6 @@ (%1-bit) (%1-bit) - - About Bitcoin Core - O programu Bitcoin Core - Command-line options Opcije programa u naredbenoj liniji @@ -781,14 +479,6 @@ Welcome Dobrodošli - - Welcome to Bitcoin Core. - Dobrodošli u programu Bitcoin Core. - - - Bitcoin Core - Bitcoin Core - Error Greška @@ -812,10 +502,6 @@ Select payment request file Izaberi datoteku zahtjeva za plaćanje - - Select payment request file to open - Izaberi datoteku zahtjeva za plaćanje - OptionsDialog @@ -863,14 +549,6 @@ &Network &Mreža - - Automatically start Bitcoin Core after logging in to the system. - Program se automatski pokrene po prijavi u sustav. - - - &Start Bitcoin Core on system login - &Pokreni program kod prijave u sustav - W&allet &Novčanik @@ -963,13 +641,6 @@ Ukupno: - - PaymentServer - - URI handling - URI upravljanje - - PeerTableModel @@ -984,17 +655,6 @@ N/A - - QRImageWidget - - &Save Image... - &Spremi sliku... - - - Save QR Code - Spremi QR kod - - RPCConsole @@ -1081,10 +741,6 @@ Clear console Očisti konzolu - - Welcome to the Bitcoin Core RPC console. - Dobrodošli u Bitcoin RPC konzolu. - Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. Koristite tipke gore i dolje za izbor već korištenih naredbi. <b>Ctrl-L</b> kako bi očistili ekran i povijest naredbi. @@ -1120,15 +776,7 @@ Show Pokaži - - Copy label - Kopiraj oznaku - - - Copy amount - Kopiraj iznos - - + ReceiveRequestDialog @@ -1147,65 +795,6 @@ &Save Image... &Spremi sliku... - - URI - URI - - - Address - Adresa - - - Amount - Iznos - - - Label - Oznaka - - - Message - Poruka - - - Resulting URI too long, try to reduce the text for label / message. - URI je predug, probajte skratiti tekst za naslov / poruku. - - - Error encoding URI into QR Code. - Greška kod kodiranja URI adrese u QR kod. - - - - RecentRequestsTableModel - - Date - Datum - - - Label - Oznaka - - - Message - Poruka - - - Amount - Iznos - - - (no label) - (bez oznake) - - - (no message) - (bez poruke) - - - (no amount) - (bez iznosa) - SendCoinsDialog @@ -1277,35 +866,7 @@ S&end &Pošalji - - Confirm send coins - Potvrdi slanje novca - - - Copy amount - Kopiraj iznos - - - or - ili - - - The amount to pay must be larger than 0. - Iznos mora biti veći od 0. - - - The amount exceeds your balance. - Iznos je veći od raspoložljivog stanja novčanika. - - - The total exceeds your balance when the %1 transaction fee is included. - Iznos je veći od stanja novčanika kad se doda naknada za transakcije od %1. - - - (no label) - (bez oznake) - - + SendCoinsEntry @@ -1316,10 +877,6 @@ Pay &To: &Primatelj plaćanja: - - Enter a label for this address to add it to your address book - Unesite oznaku za ovu adresu kako bi ju dodali u vaš adresar - &Label: &Oznaka: @@ -1390,21 +947,9 @@ Verify &Message &Potvrdite poruku - - Wallet unlock was cancelled. - Otključavanje novčanika je otkazano. - - - Message signed. - Poruka je potpisana. - SplashScreen - - Bitcoin Core - Bitcoin Core - [testnet] [testnet] @@ -1413,350 +958,16 @@ TrafficGraphWidget - - TransactionDesc - - Open until %1 - Otvoren do %1 - - - %1/offline - %1 nije dostupan - - - %1/unconfirmed - %1/nepotvrđeno - - - %1 confirmations - %1 potvrda - - - Status - Status - - - Date - Datum - - - Source - Izvor - - - Generated - Generiran - - - From - Od - - - To - Za - - - own address - vlastita adresa - - - label - oznaka - - - Credit - Uplaćeno - - - not accepted - Nije prihvaćeno - - - Debit - Zaduženje - - - Transaction fee - Naknada za transakciju - - - Net amount - Neto iznos - - - Message - Poruka - - - Comment - Komentar - - - Transaction ID - ID transakcije - - - Transaction - Transakcija - - - Inputs - Unosi - - - Amount - Iznos - - - , has not been successfully broadcast yet - , još nije bio uspješno emitiran - - - unknown - nepoznato - - TransactionDescDialog - - Transaction details - Detalji transakcije - This pane shows a detailed description of the transaction Ovaj prozor prikazuje detaljni opis transakcije - - TransactionTableModel - - Date - Datum - - - Type - Tip - - - Open until %1 - Otvoren do %1 - - - Confirmed (%1 confirmations) - Potvrđen (%1 potvrda) - - - This block was not received by any other nodes and will probably not be accepted! - Ovaj blok nije bio primljen od strane bilo kojeg drugog čvora i vjerojatno neće biti prihvaćen! - - - Generated but not accepted - Generirano, ali nije prihvaćeno - - - Label - Oznaka - - - Received with - Primljeno s - - - Received from - Primljeno od - - - Sent to - Poslano za - - - Payment to yourself - Plaćanje samom sebi - - - Mined - Rudareno - - - (n/a) - (n/d) - - - Transaction status. Hover over this field to show number of confirmations. - Status transakcije - - - Date and time that the transaction was received. - Datum i vrijeme kad je transakcija primljena - - - Type of transaction. - Vrsta transakcije. - - - Amount removed from or added to balance. - Iznos odbijen od ili dodan k saldu. - - - - TransactionView - - All - Sve - - - Today - Danas - - - This week - Ovaj tjedan - - - This month - Ovaj mjesec - - - Last month - Prošli mjesec - - - This year - Ove godine - - - Range... - Raspon... - - - Received with - Primljeno s - - - Sent to - Poslano za - - - To yourself - Samom sebi - - - Mined - Rudareno - - - Other - Ostalo - - - Enter address or label to search - Unesite adresu ili oznaku za pretraživanje - - - Min amount - Min iznos - - - Copy address - Kopiraj adresu - - - Copy label - Kopiraj oznaku - - - Copy amount - Kopiraj iznos - - - Copy transaction ID - Kopiraj ID transakcije - - - Edit label - Izmjeni oznaku - - - Show transaction details - Prikaži detalje transakcije - - - Exporting Failed - Izvoz neuspješan - - - Comma separated file (*.csv) - Datoteka podataka odvojenih zarezima (*.csv) - - - Confirmed - Potvrđeno - - - Date - Datum - - - Type - Tip - - - Label - Oznaka - - - Address - Adresa - - - ID - ID - - - Range: - Raspon: - - - to - za - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - Send Coins - Slanje novca - - - - WalletView - - &Export - &Izvoz - - - Export the data in the current tab to a file - Izvoz podataka iz trenutnog taba u datoteku - - - Backup Wallet - Arhiviranje novčanika - - - Wallet Data (*.dat) - Podaci novčanika (*.dat) - - - Backup Failed - Arhiviranje nije uspjelo - - bitcoin-core @@ -1779,6 +990,10 @@ Run in the background as a daemon and accept commands Izvršavaj u pozadini kao uslužnik i prihvaćaj komande + + Bitcoin Core + Bitcoin Core + Block creation options: Opcije za kreiranje bloka: @@ -1795,18 +1010,6 @@ Information Informacija - - Invalid amount for -maxtxfee=<amount>: '%s' - Nevaljali iznos za opciju -maxtxfee=<iznos>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Nevaljali iznos za opciju -minrelaytxfee=<iznos>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - Nevaljali iznos za opciju -mintxfee=<iznos>: '%s' - Send trace/debug info to console instead of debug.log file Šalji trace/debug informacije na konzolu umjesto u debug.log datoteku @@ -1827,10 +1030,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) Izvršite naredbu kada se najbolji blok promjeni (%s u cmd je zamjenjen sa block hash) - - This help message - Ova poruka za pomoć - Allow DNS lookups for -addnode, -seednode and -connect Dozvoli DNS upite za -addnode, -seednode i -connect @@ -1839,22 +1038,10 @@ Loading addresses... Učitavanje adresa... - - Error loading wallet.dat: Wallet corrupted - Greška kod učitavanja datoteke wallet.dat: Novčanik pokvaren - - - Error loading wallet.dat - Greška kod učitavanja datoteke wallet.dat - Invalid -proxy address: '%s' Nevaljala -proxy adresa: '%s' - - Invalid amount for -paytxfee=<amount>: '%s' - Nevaljali iznos za opciju -paytxfee=<iznos>: '%s' - Insufficient funds Nedovoljna sredstva diff --git a/src/qt/locale/bitcoin_hu.ts b/src/qt/locale/bitcoin_hu.ts index 839ee883bd356..bddc430f22312 100644 --- a/src/qt/locale/bitcoin_hu.ts +++ b/src/qt/locale/bitcoin_hu.ts @@ -25,10 +25,6 @@ C&lose &Bezárás - - &Copy Address - &Cím másolása - Delete the currently selected address from the list Kiválasztott cím törlése a listából @@ -45,73 +41,6 @@ &Delete &Törlés - - Choose the address to send coins to - Válaszd ki a címet, ahová küldesz - - - Choose the address to receive coins with - Válaszd ki a címet, amivel fogadsz - - - C&hoose - &Kiválaszt - - - Sending addresses - Küldési címek - - - Receiving addresses - Fogadó címek - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Ezekről a címekről küldhetsz bitcoint. Mindig ellenőrizd a fogadó címet és a fizetendő összeget, mielőtt elküldöd. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Ezekkel a címekkel fogadhatsz bitcoint. Ajánlott minden tranzakcióhoz egy új fogadó címet használni. - - - Copy &Label - &Címke másolása - - - &Edit - Sz&erkesztés - - - Export Address List - Címjegyzék exportálása - - - Comma separated file (*.csv) - Vesszővel elválasztott fájl (*.csv) - - - Exporting Failed - Az exportálás sikertelen volt - - - There was an error trying to save the address list to %1. Please try again. - Hiba történt a címjegyzék %1 helyre való mentésekor. Kérlek próbáld újra. - - - - AddressTableModel - - Label - Címke - - - Address - Cím - - - (no label) - (nincs címke) - AskPassphraseDialog @@ -131,90 +60,6 @@ Repeat new passphrase Új jelszó újra - - Encrypt wallet - Tárca titkosítása - - - This operation needs your wallet passphrase to unlock the wallet. - A tárca megnyitásához a műveletnek szüksége van a tárcád jelszavára. - - - Unlock wallet - Tárca megnyitása - - - This operation needs your wallet passphrase to decrypt the wallet. - A tárca dekódolásához a műveletnek szüksége van a tárcád jelszavára. - - - Decrypt wallet - Tárca dekódolása - - - Change passphrase - Jelszó megváltoztatása - - - Confirm wallet encryption - Biztosan titkosítani akarod a tárcát? - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Figyelem: ha titkosítod a tárcát és elveszted a jelszavad, akkor <b>AZ ÖSSZES BITCOINOD ELVESZIK!</b> - - - Are you sure you wish to encrypt your wallet? - Biztosan titkosítani akarod a tárcád? - - - 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. - FONTOS: A tárca-fájl minden korábbi mentését cseréld le ezzel az új, titkosított tárca-fájllal. Biztonsági okokból a tárca-fájl korábbi, titkosítás nélküli mentései használhatatlanná válnak, amint elkezded használni az új, titkosított tárcát. - - - Warning: The Caps Lock key is on! - Vigyázat: a Caps Lock be van kapcsolva! - - - Wallet encrypted - Tárca titkosítva - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Add meg a tárca új jelszavát.<br/>Olyan jelszót válassz, ami <b>legalább tíz véletlenszerű karakterből</b> vagy <b>legalább 8 véletlenszerű szóból</b> áll. - - - Enter the old passphrase and new passphrase to the wallet. - Add meg a tárcához a régi jelszavad és az új jelszavad. - - - Wallet encryption failed - A tárca titkosítása sikertelen. - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Tárca titkosítása belső hiba miatt sikertelen. A tárcád nem lett titkosítva. - - - The supplied passphrases do not match. - A megadott jelszavak nem egyeznek. - - - Wallet unlock failed - Tárca megnyitása sikertelen - - - The passphrase entered for the wallet decryption was incorrect. - Hibás jelszó. - - - Wallet decryption failed - Dekódolás sikertelen. - - - Wallet passphrase was successfully changed. - Jelszó megváltoztatva. - BanTableModel @@ -257,6 +102,10 @@ Quit application Kilépés az alkalmazásból + + &About %1 + &A %1-ról + About &Qt A &Qt-ról @@ -293,14 +142,6 @@ Open &URI... &URI azonosító megnyitása... - - Bitcoin Core client - Bitcoin Core kliens - - - Importing blocks from disk... - A blokkok importálása lemezről... - Reindexing blocks on disk... Lemezen lévő blokkok újraindexelése... @@ -345,10 +186,6 @@ &Receive &Fogadás - - Show information about Bitcoin Core - Bitcoin Core információ megjelenítése - &Show / Hide &Mutat / Elrejt @@ -385,22 +222,10 @@ Tabs toolbar Fül eszköztár - - Bitcoin Core - Bitcoin Core - Request payments (generates QR codes and bitcoin: URIs) Fizetési kérelem (QR-kódot és "bitcoin:" URI azonosítót hoz létre) - - &About Bitcoin Core - &A Bitcoin Core-ról - - - Modify configuration options for Bitcoin Core - Konfigurációs opciók módosítása a Bitcoin Core-hoz - Show the list of used sending addresses and labels A használt küldési címek és címkék megtekintése @@ -417,10 +242,6 @@ &Command-line options Paran&cssor kapcsolók - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - A Bitcoin Core súgóüzenet megjelenítése a Bitcoin lehetséges parancssori kapcsolóival. - %n active connection(s) to Bitcoin network %n aktív kapcsolat a Bitcoin hálózathoz%n aktív kapcsolat a Bitcoin hálózathoz @@ -532,13 +353,6 @@ Tárca <b>kódolva</b> és jelenleg <b>zárva</b>. - - ClientModel - - Network Alert - Hálózati figyelmeztetés - - CoinControlDialog @@ -617,150 +431,6 @@ Priority Prioritás - - Copy address - Cím másolása - - - Copy label - Címke másolása - - - Copy amount - Összeg másolása - - - Copy transaction ID - Tranzakcióazonosító másolása - - - Lock unspent - Megmaradt zárolása - - - Unlock unspent - Zárolás feloldása - - - Copy quantity - Mennyiség másolása - - - Copy fee - Díj másolása - - - Copy after fee - Utólagos díj másolása - - - Copy bytes - Byte-ok másolása - - - Copy priority - Prioritás másolása - - - Copy dust - Visszajáró másolása - - - Copy change - Visszajáró másolása - - - highest - legmagasabb - - - higher - magasabb - - - high - magas - - - medium-high - közepesen-magas - - - medium - közepes - - - low-medium - alacsony-közepes - - - low - alacsony - - - lower - alacsonyabb - - - lowest - legalacsonyabb - - - (%1 locked) - (%1 zárolva) - - - none - semmi - - - This label turns red if the transaction size is greater than 1000 bytes. - Ez a címke pirosra változik, ha a tranzakció mérete nagyobb mint 1000 bájt. - - - This label turns red if the priority is smaller than "medium". - Ez a címke pirosra változik, ha a prioritás kisebb mint "közepes". - - - This label turns red if any recipient receives an amount smaller than %1. - Ez a címke pirosra változik, ha bármely fogadónak %1-nál kevesebb összeg érkezik. - - - Can vary +/- %1 satoshi(s) per input. - Bemenetenként +/- %1 satoshi-val változhat - - - yes - igen - - - no - nem - - - This means a fee of at least %1 per kB is required. - Legalább %1 díj szüksége kB-onként. - - - Can vary +/- 1 byte per input. - Bemenetenként +/- 1 byte-al változhat. - - - Transactions with higher priority are more likely to get included into a block. - Nagyobb prioritású tranzakciók nagyobb valószínűséggel kerülnek be egy blokkba. - - - (no label) - (nincs címke) - - - change from %1 (%2) - visszajáró %1-ből (%2) - - - (change) - (visszajáró) - EditAddressDialog @@ -784,38 +454,6 @@ &Address &Cím - - New receiving address - Új fogadó cím - - - New sending address - Új küldő cím - - - Edit receiving address - Fogadó cím szerkesztése - - - Edit sending address - Küldő cím szerkesztése - - - The entered address "%1" is already in the address book. - A megadott "%1" cím már szerepel a címjegyzékben. - - - The entered address "%1" is not a valid Bitcoin address. - A megadott "%1" cím nem egy érvényes Bitcoin-cím. - - - Could not unlock wallet. - Tárca feloldása sikertelen - - - New key generation failed. - Új kulcs generálása sikertelen - FreespaceChecker @@ -838,10 +476,6 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin Core - version verzió @@ -850,10 +484,6 @@ (%1-bit) (%1-bit) - - About Bitcoin Core - A Bitcoin Core-ról - Command-line options Parancssoros opciók @@ -873,14 +503,6 @@ Welcome Üdvözlünk - - Welcome to Bitcoin Core. - Üdvözlünk a Bitcoin Core-ban. - - - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - A Bitcoin Core le fogja tölteni és tárolni fogja a Bitcoin blokklánc egy másolatát. Legalább %1GB adat lesz tárolva ebben a mappában, és ez folyamatosan nőni fog. A tárca szintén itt lesz tárolva. - Use the default data directory Az alapértelmezett adat könyvtár használata @@ -889,10 +511,6 @@ Use a custom data directory: Saját adatkönyvtár használata: - - Bitcoin Core - Bitcoin Core - Error: Specified data directory "%1" cannot be created. Hiba: A megadott "%1" adatkönyvtár nem hozható létre. @@ -924,10 +542,6 @@ Select payment request file Fizetési kérelmi fájl kiválasztása - - Select payment request file to open - Fizetés kérelmi fájl kiválasztása - OptionsDialog @@ -959,10 +573,6 @@ IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) A proxy IP címe (pl.: IPv4: 127.0.0.1 / IPv6: ::1) - - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - Itt beállíthatod a kezelőfelület nyelvét. A beállítás a Bitcoin újraindítása után lép érvénybe. - Third party transaction URLs Harmadik fél tranzakció URL-ek @@ -979,10 +589,6 @@ &Network &Hálózat - - &Start Bitcoin Core on system login - A Bitcoin elindítása bejelentkezéskor - W&allet T&árca @@ -1147,25 +753,6 @@ A legutóbbi tranzakciók - - PaymentServer - - URI handling - URI kezelés - - - Cannot start bitcoin: click-to-pay handler - A bitcoint nem lehet elindítani: click-to-pay handler - - - Payment request expired. - A fizetési kérelem lejárt - - - Invalid payment request. - Érvénytelen fizetési kérelem - - PeerTableModel @@ -1216,25 +803,6 @@ %1 ms - - QRImageWidget - - &Save Image... - &Kép mentése - - - &Copy Image - &Kép másolása - - - Save QR Code - QR kód mentése - - - PNG Image (*.png) - PNG kép (*.png) - - RPCConsole @@ -1369,10 +937,6 @@ Out: Ki: - - Build date - Fordítás dátuma - Debug log file Debug naplófájl @@ -1492,18 +1056,6 @@ Remove Eltávolítás - - Copy label - Címke másolása - - - Copy message - Üzenet másolása - - - Copy amount - Összeg másolása - ReceiveRequestDialog @@ -1523,91 +1075,24 @@ &Save Image... &Kép mentése + + + SendCoinsDialog - Request payment to %1 - Fizetés kérése a %1-hez + Send Coins + Érmék küldése - Payment information - Kifizetés információ + Inputs... + Bemenetek... - URI - URI: + automatically selected + automatikusan kiválasztva - Address - Cím - - - Amount - Összeg - - - Label - Címke - - - Message - Üzenet - - - Resulting URI too long, try to reduce the text for label / message. - A keletkezett URI túl hosszú, próbálja meg csökkenteni a cimkeszöveg / üzenet méretét. - - - Error encoding URI into QR Code. - Hiba lépett fel az URI QR kóddá alakításakor - - - - RecentRequestsTableModel - - Date - Dátum - - - Label - Címke - - - Message - Üzenet - - - Amount - Összeg - - - (no label) - (nincs címke) - - - (no message) - (nincs üzenet) - - - (no amount) - (nincs összeg) - - - - SendCoinsDialog - - Send Coins - Érmék küldése - - - Inputs... - Bemenetek... - - - automatically selected - automatikusan kiválasztva - - - Insufficient funds! - Fedezethiány! + Insufficient funds! + Fedezethiány! Quantity: @@ -1701,75 +1186,7 @@ S&end &Küldés - - Confirm send coins - Küldés megerősítése - - - Copy quantity - Mennyiség másolása - - - Copy amount - Összeg másolása - - - Copy fee - Díj másolása - - - Copy after fee - Utólagos díj másolása - - - Copy bytes - Byte-ok másolása - - - Copy priority - Prioritás másolása - - - Copy change - Visszajáró másolása - - - or - vagy - - - The amount to pay must be larger than 0. - A fizetendő összegnek nagyobbnak kell lennie 0-nál. - - - The amount exceeds your balance. - Nincs ennyi bitcoin az egyenlegeden. - - - The total exceeds your balance when the %1 transaction fee is included. - A küldeni kívánt összeg és a %1 tranzakciós díj együtt meghaladja az egyenlegeden rendelkezésedre álló összeget. - - - Payment request expired. - A fizetési kérelem lejárt - - - Warning: Invalid Bitcoin address - Figyelmeztetés: Érvénytelen Bitcoin cím - - - (no label) - (nincs címke) - - - Copy dust - Visszajáró másolása - - - Are you sure you want to send? - Biztos, hogy el akarod küldeni? - - + SendCoinsEntry @@ -1780,11 +1197,6 @@ Pay &To: Címzett: - - Enter a label for this address to add it to your address book - Milyen címkével kerüljön be ez a cím a címtáradba? - - &Label: Címke: @@ -1824,10 +1236,6 @@ ShutdownWindow - - Bitcoin Core is shutting down... - A Bitcoin Core leáll... - Do not shut down the computer until this window disappears. Ne állítsd le a számítógépet amíg ez az ablak el nem tűnik. @@ -1891,53 +1299,9 @@ Verify &Message Üzenet ellenőrzése - - The entered address is invalid. - A megadott cím nem érvényes. - - - Please check the address and try again. - Ellenőrizze a címet és próbálja meg újra. - - - Private key for the entered address is not available. - A megadott cím privát kulcsa nem található. - - - Message signing failed. - Üzenet aláírása nem sikerült. - - - Message signed. - Üzenet aláírva. - - - The signature could not be decoded. - Az aláírást nem sikerült dekódolni. - - - Please check the signature and try again. - Ellenőrizd az aláírást és próbáld újra. - - - Message verification failed. - Az üzenet ellenőrzése nem sikerült. - - - Message verified. - Üzenet ellenőrizve. - - + SplashScreen - - Bitcoin Core - Bitcoin Core - - - The Bitcoin Core developers - A Bitcoin Core fejlesztői - [testnet] [teszthálózat] @@ -1950,378 +1314,16 @@ KB/s - - TransactionDesc - - Open until %1 - %1-ig megnyitva - - - %1/unconfirmed - %1/megerősítetlen - - - %1 confirmations - %1 megerősítés - - - Status - Állapot - - - Date - Dátum - - - Source - Forrás - - - Generated - Legenerálva - - - From - Űrlap - - - To - Címzett - - - own address - saját cím - - - label - címke - - - Credit - Jóváírás - - - not accepted - elutasítva - - - Debit - Terhelés - - - Transaction fee - Tranzakciós díj - - - Net amount - Nettó összeg - - - Message - Üzenet - - - Comment - Megjegyzés - - - Transaction ID - Tranzakcióazonosító - - - Debug information - Debug információ - - - Transaction - Tranzakció - - - Inputs - Bemenetek - - - Amount - Összeg - - - true - igaz - - - false - hamis - - - , has not been successfully broadcast yet - , még nem sikerült elküldeni. - - - unknown - ismeretlen - - TransactionDescDialog - - Transaction details - Tranzakció részletei - This pane shows a detailed description of the transaction Ez a mező a tranzakció részleteit mutatja - - TransactionTableModel - - Date - Dátum - - - Type - Típus - - - Open until %1 - %1-ig megnyitva - - - Confirmed (%1 confirmations) - Megerősítve (%1 megerősítés) - - - This block was not received by any other nodes and will probably not be accepted! - Ezt a blokkot egyetlen másik csomópont sem kapta meg, így valószínűleg nem lesz elfogadva! - - - Generated but not accepted - Legenerálva, de még el nem fogadva. - - - Offline - Offline - - - Label - Címke - - - Unconfirmed - Megerősítetlen: - - - Received with - Erre a címre - - - Received from - Erről az - - - Sent to - Erre a címre - - - Payment to yourself - Magadnak kifizetve - - - Mined - Kibányászva - - - (n/a) - (nincs) - - - Transaction status. Hover over this field to show number of confirmations. - Tranzakció állapota. Húzd ide a kurzort, hogy lásd a megerősítések számát. - - - Date and time that the transaction was received. - Tranzakció fogadásának dátuma és időpontja. - - - Type of transaction. - Tranzakció típusa. - - - Amount removed from or added to balance. - Az egyenleghez jóváírt vagy ráterhelt összeg. - - - - TransactionView - - All - Mind - - - Today - Mai - - - This week - Ezen a héten - - - This month - Ebben a hónapban - - - Last month - Múlt hónapban - - - This year - Ebben az évben - - - Range... - Tartomány ... - - - Received with - Erre a címre - - - Sent to - Erre a címre - - - To yourself - Magadnak - - - Mined - Kibányászva - - - Other - Más - - - Enter address or label to search - Írd be a keresendő címet vagy címkét - - - Min amount - Minimális összeg - - - Copy address - Cím másolása - - - Copy label - Címke másolása - - - Copy amount - Összeg másolása - - - Copy transaction ID - Tranzakcióazonosító másolása - - - Edit label - Címke szerkesztése - - - Show transaction details - Tranzakciós részletek megjelenítése - - - Watch-only - Csak megfigyelés - - - Exporting Failed - Az exportálás sikertelen volt - - - Exporting Successful - Sikeres exportálás - - - Comma separated file (*.csv) - Vesszővel elválasztott fájl (*.csv) - - - Confirmed - Megerősítve - - - Date - Dátum - - - Type - Típus - - - Label - Címke - - - Address - Cím - - - ID - Azonosító - - - Range: - Tartomány: - - - to - meddig - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - Send Coins - Érmék küldése - - - - WalletView - - &Export - &Exportálás - - - Export the data in the current tab to a file - Jelenlegi nézet exportálása fájlba - - - Backup Wallet - Biztonsági másolat készítése a Tárcáról - - - Wallet Data (*.dat) - Tárca fájl (*.dat) - - - Backup Failed - Biztonsági másolat készítése sikertelen - - - Backup Successful - Sikeres biztonsági mentés - - bitcoin-core @@ -2356,6 +1358,10 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Kívülről érkező kapcsolatok elfogadása (alapértelmezett: 1, ha nem használt a -proxy vagy a -connect) + + Bitcoin Core + Bitcoin Core + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) Parancs, amit akkor hajt végre, amikor egy tárca-tranzakció megváltozik (%s a parancsban lecserélődik a blokk TxID-re) @@ -2420,18 +1426,6 @@ Wallet options: Tárca beállítások: - - You need to rebuild the database using -reindex to change -txindex - Az adatbázist újra kell építeni -reindex használatával (módosítás -tindex). - - - Cannot resolve -whitebind address: '%s' - Külső cím (-whitebind address) feloldása nem sikerült: '%s' - - - Copyright (C) 2009-%i The Bitcoin Core Developers - Copyright (C) 2009-%i A Bitcoin Core Fejlesztői - Error reading from database, shutting down. Hiba az adatbázis olvasásakor, leállítás @@ -2440,18 +1434,6 @@ Information Információ - - Invalid amount for -maxtxfee=<amount>: '%s' - Érvénytelen -maxtxfee=<amount>: '%s' összeg - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Érvénytelen -minrelaytxfee=<amount>: '%s' összeg - - - Invalid amount for -mintxfee=<amount>: '%s' - Érvénytelen -mintxfee=<amount>: '%s' összeg - Send trace/debug info to console instead of debug.log file trace/debug információ küldése a konzolra a debog.log fájl helyett @@ -2494,11 +1476,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) Parancs, amit akkor hajt végre, amikor a legjobb blokk megváltozik (%s a cmd-ban lecserélődik a blokk hash-re) - - This help message - Ez a súgó-üzenet - - Allow DNS lookups for -addnode, -seednode and -connect DNS-kikeresés engedélyezése az addnode-nál és a connect-nél @@ -2507,14 +1484,6 @@ Loading addresses... Címek betöltése... - - Error loading wallet.dat: Wallet corrupted - Hiba a wallet.dat betöltése közben: meghibásodott tárca - - - Error loading wallet.dat - Hiba az wallet.dat betöltése közben - Invalid -proxy address: '%s' Érvénytelen -proxy cím: '%s' @@ -2523,18 +1492,6 @@ Unknown network specified in -onlynet: '%s' Ismeretlen hálózat lett megadva -onlynet: '%s' - - Cannot resolve -bind address: '%s' - Csatlakozási cím (-bind address) feloldása nem sikerült: '%s' - - - Cannot resolve -externalip address: '%s' - Külső cím (-externalip address) feloldása nem sikerült: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - Étvénytelen -paytxfee=<összeg> összeg: '%s' - Insufficient funds Nincs elég bitcoinod. diff --git a/src/qt/locale/bitcoin_id_ID.ts b/src/qt/locale/bitcoin_id_ID.ts index e1ec7ae7fa24a..fe07ab7a29045 100644 --- a/src/qt/locale/bitcoin_id_ID.ts +++ b/src/qt/locale/bitcoin_id_ID.ts @@ -25,10 +25,6 @@ C&lose T&utup - - &Copy Address - &Salin Alamat - Delete the currently selected address from the list Hapus alamat yang sementara dipilih dari daftar @@ -45,73 +41,6 @@ &Delete &Hapus - - Choose the address to send coins to - Pilihlah alamat kemana koin Anda akan dikirim - - - Choose the address to receive coins with - Pilihlah alamat dimana Anda akan menerima koin - - - C&hoose - P&ilihlah - - - Sending addresses - Alamat pengirim - - - Receiving addresses - Alamat penerima - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Alamat-alamat Anda untuk mengirim pembayaran. Periksalah jumlah dan alamat penerima setiap kali Anda mengirim Bitcoin. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Alamat-alamat Anda untuk menerima pembayaran. Dianjurkan agar Anda menggunakan alamat yang baru untuk setiap transaksi. - - - Copy &Label - Salin &Label - - - &Edit - &Ubah - - - Export Address List - Ekspor Daftar Alamat - - - Comma separated file (*.csv) - Berkas CSV (*.csv) - - - Exporting Failed - Proses Ekspor Gagal - - - There was an error trying to save the address list to %1. Please try again. - Terjadi kesalahan saat menyimpan daftar alamat ke %1. Silakan coba lagi. - - - - AddressTableModel - - Label - Label - - - Address - Alamat - - - (no label) - (tidak ada label) - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase Ulangi kata kunci baru - - Encrypt wallet - Enkripsi dompet - - - This operation needs your wallet passphrase to unlock the wallet. - Operasi ini memerlukan kata kunci dompet Anda untuk membuka dompet. - - - Unlock wallet - Buka dompet - - - This operation needs your wallet passphrase to decrypt the wallet. - Operasi ini memerlukan kata kunci dompet Anda untuk mendekripsi dompet. - - - Decrypt wallet - Dekripsi dompet - - - Change passphrase - Ubah kata kunci - - - Confirm wallet encryption - Konfirmasi enkripsi dompet - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Perhatian: Jika anda mengenkripsi dompet anda dan lupa kata kuncinya, anda akan <b>KEHILANGAN SELURUH BITCOIN ANDA</b>! - - - Are you sure you wish to encrypt your wallet? - Apakah Anda yakin ingin mengenkripsi dompet Anda? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Bitcoin Core akan ditutup untuk menyelesaikan proses enkripsi. Mohon diingat bahwa mengenkripsi dompet Anda tidak akan sepenuhnya melindungi bitcoin Anda dari virus atau malware yang menginfeksi komputer Anda. - - - 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. - PENTING: Setiap back up yang sudah Anda buat sebaiknya diganti dengan data dompet Anda yang baru dan terenkripsi. Untuk alasan keamanan, data back up tidak terenkripsi yang sudah Anda buat sebelumnya tidak akan dapat digunakan setelah Anda mulai menggunakan dompet yang baru dan terenkripsi. - - - Warning: The Caps Lock key is on! - Perhatian: tombol Caps Lock sementara aktif! - - - Wallet encrypted - Dompet terenkripsi - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Masukkan kata kunci untuk dompet Anda.<br/>Mohon gunakan kata kunci <b>yang terdiri dari 10 karakter acak</b>, atau <b>delapan atau beberapa kata lagi</b>. - - - Enter the old passphrase and new passphrase to the wallet. - Masukkan kata kunci lama dan kata kunci baru dompet Anda. - - - Wallet encryption failed - Enkripsi dompet gagal - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Enkripsi dompet gagal karena kesalahan internal. Dompet Anda tidak dienkripsi. - - - The supplied passphrases do not match. - Kata kunci yang dimasukkan tidak cocok. - - - Wallet unlock failed - Gagal buka dompet - - - The passphrase entered for the wallet decryption was incorrect. - Kata kunci yang dimasukkan untuk dekripsi dompet tidak cocok. - - - Wallet decryption failed - Dekripsi dompet gagal - - - Wallet passphrase was successfully changed. - Kata kunci dompet Anda berhasil diubah. - BanTableModel @@ -305,14 +146,6 @@ Open &URI... Buka &URI - - Bitcoin Core client - Klien Bitcoin Core - - - Importing blocks from disk... - Mengimpor blok dari disk... - Reindexing blocks on disk... Mengindex ulang blok di dalam disk... @@ -357,10 +190,6 @@ &Receive &Menerima - - Show information about Bitcoin Core - Tampilkan informasi tentang Bitcoin Core - &Show / Hide &Tampilkan / Sembunyikan @@ -397,22 +226,10 @@ Tabs toolbar Baris tab - - Bitcoin Core - Bitcoin Core - Request payments (generates QR codes and bitcoin: URIs) Permintaan pembayaran (membuat kode QR dan bitcoin: URIs) - - &About Bitcoin Core - &Mengenai Bitcoin Core - - - Modify configuration options for Bitcoin Core - Modifikasi pengaturan konfigurasi untuk Bitcoin Core - Show the list of used sending addresses and labels Tampilkan daftar alamat dan label yang terkirim @@ -429,10 +246,6 @@ &Command-line options &pilihan Command-line - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Tampilkan pesan bantuan Bitcoin Core untuk mendapatkan daftar pilihan Command-line - %n active connection(s) to Bitcoin network %n koneksi aktif ke jaringan Bitcoin @@ -544,13 +357,6 @@ Dompet saat ini <b>terenkripsi</b> dan <b>terkunci</b> - - ClientModel - - Network Alert - Notifikasi Jaringan - - CoinControlDialog @@ -629,150 +435,6 @@ Priority Prioritas - - Copy address - Salin alamat - - - Copy label - Salin label - - - Copy amount - Salin jumlah - - - Copy transaction ID - Salin ID transaksi - - - Lock unspent - Kunci unspent. - - - Unlock unspent - Buka unspent - - - Copy quantity - Salin kuantitas - - - Copy fee - Salin biaya - - - Copy after fee - Salin dengan biaya - - - Copy bytes - Salin bytes - - - Copy priority - Salin prioritas - - - Copy dust - Salin dust - - - Copy change - Salin kembalian - - - highest - terbesar - - - higher - lebih besar - - - high - besar - - - medium-high - sedang-sampai-besar - - - medium - sedang - - - low-medium - sedikit-sampai-sedang - - - low - sedikit - - - lower - lebih sedikit - - - lowest - tersedikit - - - (%1 locked) - (%1 terkunci) - - - none - tidak satupun - - - This label turns red if the transaction size is greater than 1000 bytes. - Label ini akan menjadi merah apabila ukuran transaksi melebihi 1000 bytes. - - - This label turns red if the priority is smaller than "medium". - Label ini akan menjadi merah apabila prioritasnya lebih kecil dari "sedang" - - - This label turns red if any recipient receives an amount smaller than %1. - Label ini akan menjadi merah apabila penerima menerima jumlah yang lebih kecil dari %1. - - - Can vary +/- %1 satoshi(s) per input. - Dapat beragam +/- %1 satoshi per input. - - - yes - ya - - - no - tidak - - - This means a fee of at least %1 per kB is required. - Perlu biaya lebih dari %1 untuk setiap kB. - - - Can vary +/- 1 byte per input. - Dapat beragam +/- 1 byte per input. - - - Transactions with higher priority are more likely to get included into a block. - Transaksi dengan prioritas lebih tinggi akan lebih cepat dimasukkan kedalam blok. - - - (no label) - (tidak ada label) - - - change from %1 (%2) - kembalian dari %1 (%2) - - - (change) - (kembalian) - EditAddressDialog @@ -796,38 +458,6 @@ &Address &Alamat - - New receiving address - Alamat menerima baru - - - New sending address - Alamat mengirim baru - - - Edit receiving address - Ubah alamat menerima - - - Edit sending address - Ubah alamat mengirim - - - The entered address "%1" is already in the address book. - Alamat yang dimasukkan "%1" sudah ada di dalam buku alamat. - - - The entered address "%1" is not a valid Bitcoin address. - Alamat yang dimasukkan "%1" bukan alamat Bitcoin yang benar. - - - Could not unlock wallet. - Tidak dapat membuka dompet. - - - New key generation failed. - Pembuatan kunci baru gagal. - FreespaceChecker @@ -854,10 +484,6 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin Core - version versi @@ -866,10 +492,6 @@ (%1-bit) (%1-bit) - - About Bitcoin Core - Mengenai Bitcoin Core - Command-line options Pilihan Command-line @@ -906,29 +528,13 @@ Show splash screen on startup (default: %u) Tampilkan layar kilat saat memulai (default: %u) - - Reset all settings changes made over the GUI - Reset semua pengaturan yang dibuat dari GUI - - + Intro Welcome Selamat Datang - - Welcome to Bitcoin Core. - Selamat Datang ke Bitcoin Core - - - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - Ini adalah pertama kali program ini dijalankan, Anda dapat memilih dimana Bitcoin Core menyimpan data. - - - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - Bitcoin Core akan mengunduh dan menyimpan salinan dari block chain Bitcoin. Setidaknya %1GB data akan disimpan di direktori ini, dan akan terus bertambah. Dompet Anda juga akan disimpan di direktori ini. - Use the default data directory Gunakan direktori data default. @@ -937,10 +543,6 @@ Use a custom data directory: Gunakan direktori pilihan Anda: - - Bitcoin Core - Bitcoin Core - Error: Specified data directory "%1" cannot be created. Kesalahan: Direktori data "%1" tidak dapat dibuat. @@ -976,10 +578,6 @@ Select payment request file Pilih data permintaan pembayaran - - Select payment request file to open - Pilih data permintaan pembayaran yang akan dibuka - OptionsDialog @@ -1019,10 +617,6 @@ 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. Minimalisasi aplikasi ketika jendela ditutup. Ketika pilihan ini dipilih, aplikasi akan menutup seluruhnya jika anda memilih Keluar di menu yang tersedia. - - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - Bahasa interface pengguna bisa diubah disini. Pengaturan ini akan memberikan efek setelah Bitcoin Core di-restart. - 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 |. URL pihak ketika (misalnya sebuah block explorer) yang mumcul dalam tab transaksi sebagai konteks menu. %s dalam URL diganti dengan kode transaksi. URL dipisahkan dengan tanda vertikal |. @@ -1047,14 +641,6 @@ &Network &Jaringan - - Automatically start Bitcoin Core after logging in to the system. - Buka Bitcoin Core secara otomatis setelah Anda log-in ke sistem Anda. - - - &Start Bitcoin Core on system login - &Mulai Bitcoin Core saat log-in sistem - (0 = auto, <0 = leave that many cores free) (0 = auto, <0 = leave that many cores free) @@ -1235,53 +821,6 @@ Jumlah saldo Anda sekarang - - PaymentServer - - URI handling - Penanganan URI - - - Invalid payment address %1 - Alamat pembayaran salah %1 - - - Payment request rejected - Permintaan pembayaran ditolak - - - Requested payment amount of %1 is too small (considered dust). - Nilai pembayaran %1 yang diminta oleh Anda terlalu sedikit (dianggap debu). - - - Payment request error - Gagalan permintaan pembayaran - - - Payment request expired. - Permintaan pembayaran telah kadaluarsa - - - Refund from %1 - Pembayaran kembali dari %1 - - - Error communicating with %1: %2 - Masalah berkomunikasi dengan %1: %2 - - - Bad response from server %1 - Jawaban salah dari server %1 - - - Payment acknowledged - Pembayaran diakui - - - Network request error - Gagalan permintaan dari jaringan - - PeerTableModel @@ -1312,25 +851,6 @@ T/S - - QRImageWidget - - &Save Image... - &Simpan Gambaran... - - - &Copy Image - &Salin Gambaran - - - Save QR Code - Simpan Kode QR - - - PNG Image (*.png) - Gambar PNG (*.png) - - RPCConsole @@ -1431,10 +951,6 @@ Out: Keluar: - - Build date - Tanggal pembuatan - Debug log file Berkas catatan debug @@ -1459,10 +975,6 @@ 1 &year 1 &tahun - - Welcome to the Bitcoin Core RPC console. - Selamat datang di konsol RPC Bitcoin. - Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. Gunakan panah keatas dan kebawah untuk menampilkan sejarah, dan <b>Ctrl-L</b> untuk bersihkan layar. @@ -1562,18 +1074,6 @@ Remove Menghapus - - Copy label - Salin label - - - Copy message - Salin Pesan - - - Copy amount - Salin nilai - ReceiveRequestDialog @@ -1593,73 +1093,6 @@ &Save Image... &Simpan Gambaran... - - Request payment to %1 - Minta pembayaran ke %1 - - - Payment information - Informasi pembayaran - - - URI - URI - - - Address - Alamat - - - Amount - Nilai - - - Label - Label - - - Message - Pesan - - - Resulting URI too long, try to reduce the text for label / message. - Hasil URI terlalu panjang, coba kurangi label / pesan. - - - Error encoding URI into QR Code. - Gagal mengubah URI ke kode QR. - - - - RecentRequestsTableModel - - Date - Tanggal - - - Label - Label - - - Message - Pesan: - - - Amount - Nilai - - - (no label) - (tidak ada label) - - - (no message) - (tidak ada pesan) - - - (no amount) - (tidak ada nilai) - SendCoinsDialog @@ -1771,98 +1204,6 @@ S&end K&irim - - Confirm send coins - Konfirmasi pengiriman koin - - - %1 to %2 - %1 ke %2 - - - Copy quantity - Salin kuantitas - - - Copy amount - Salin nilai - - - Copy fee - Salin biaya - - - Copy after fee - Salin dengan biaya - - - Copy bytes - Salin bytes - - - Copy priority - Salin prioritas - - - Copy change - Salin uang kembali - - - Total Amount %1 - Jumlah Total %1 - - - or - atau - - - The amount to pay must be larger than 0. - Nilai yang dibayar harus lebih besar dari 0. - - - The amount exceeds your balance. - Nilai melebihi saldo Anda. - - - The total exceeds your balance when the %1 transaction fee is included. - Jumlah melebihi saldo Anda ketika biaya transaksi %1 ditambahkan. - - - Transaction creation failed! - Gagal membuat transaksi! - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - Gagal: Transaksi ditolak. Ini mungkin terjadi jika beberapa dari koin dalam dompet Anda telah digunakan, seperti ketika Anda menggunakan salinan wallet.dat dan beberapa koin telah dibelanjakan dalam salinan tersebut tetapi disini tidak tertandai sebagai terpakai. - - - A fee higher than %1 is considered an absurdly high fee. - Biaya yang lebih tinggi dari %1 dianggap biaya tak masuk akal. - - - Payment request expired. - Permintaan pembayaran telah kadaluarsa - - - Warning: Invalid Bitcoin address - Awas: Alamat Bitcoin tidak sah - - - (no label) - (tidak ada label) - - - Copy dust - Salin dust - - - Are you sure you want to send? - Apakah Anda yakin ingin kirim? - - - added as transaction fee - ditambahkan sebagai biaya transaksi - SendCoinsEntry @@ -1874,10 +1215,6 @@ Pay &To: Kirim &Ke: - - Enter a label for this address to add it to your address book - Masukkan label bagi alamat ini untuk menambahkannya ke buku alamat Anda - &Label: &Label: @@ -1925,10 +1262,6 @@ ShutdownWindow - - Bitcoin Core is shutting down... - Bitcoin Core sementara dimatikan... - Do not shut down the computer until this window disappears. Kamu tidak dapat mematikan komputer sebelum jendela ini tertutup sendiri. @@ -2000,69 +1333,9 @@ Reset all verify message fields Hapus semua bidang verifikasi pesan - - Click "Sign Message" to generate signature - Tekan "Tandatangan Pesan" untuk menghasilan tanda tangan - - - The entered address is invalid. - Alamat yang dimasukkan tidak sesuai. - - - Please check the address and try again. - Silahkan periksa alamat dan coba lagi. - - - The entered address does not refer to a key. - Alamat itu tidak menghubungkan kunci. - - - Wallet unlock was cancelled. - Membuka kunci dompet dibatalkan. - - - Private key for the entered address is not available. - Kunci pribadi untuk alamat itu tidak tersedia. - - - Message signing failed. - Menandai pesan gagal. - - - Message signed. - Pesan ditandai. - - - The signature could not be decoded. - Tanda tangan tidak bisa diterjemahkan. - - - Please check the signature and try again. - Mohon periksa tanda tangan dan coba kembali - - - The signature did not match the message digest. - Tanda tangan tidak cocok dengan intisari pesan. - - - Message verification failed. - Verifikasi pesan gagal. - - - Message verified. - Pesan terverifikasi. - SplashScreen - - Bitcoin Core - Bitcoin Core - - - The Bitcoin Core developers - Pembangun Bitcoin Core - [testnet] [testnet] @@ -2075,430 +1348,16 @@ KB/s - - TransactionDesc - - Open until %1 - Buka hingga %1 - - - conflicted - Terkonflik - - - %1/offline - %1/tidak terhubung - - - %1/unconfirmed - %1/belum dikonfirmasi - - - %1 confirmations - %1 konfirmasi - - - Status - Status - - - , broadcast through %n node(s) - kirim lewat %n node - - - Date - Tanggal - - - Source - Sumber - - - Generated - Dibuat - - - From - Dari - - - To - Untuk - - - own address - Alamat saya sendiri - - - label - label - - - Credit - Kredit - - - matures in %n more block(s) - cukup tua sesudah %n blok lagi - - - not accepted - tidak diterima - - - Debit - Debet - - - Transaction fee - Biaya Transaksi - - - Net amount - Nilai bersih - - - Message - Pesan: - - - Comment - Komentar - - - Transaction ID - ID Transaksi - - - Merchant - Pedagang - - - Debug information - Informasi debug - - - Transaction - Transaksi - - - Inputs - Masukan - - - Amount - Nilai - - - true - benar - - - false - salah - - - , has not been successfully broadcast yet - , belum berhasil disiarkan - - - Open for %n more block(s) - Buka untuk %n blok lagi - - - unknown - tidak diketahui - - TransactionDescDialog - - Transaction details - Rincian transaksi - This pane shows a detailed description of the transaction Jendela ini menampilkan deskripsi rinci dari transaksi tersebut - - TransactionTableModel - - Date - Tanggal - - - Type - Jenis - - - Immature (%1 confirmations, will be available after %2) - Terlalu muda (cuma %1 konfirmasi, akan siap sesudah %2) - - - Open for %n more block(s) - Buka untuk %n blok lagi - - - Open until %1 - Buka hingga %1 - - - Confirmed (%1 confirmations) - Terkonfirmasi (%1 konfirmasi) - - - This block was not received by any other nodes and will probably not be accepted! - Blok ini tidak diterima oleh node lainnya dan kemungkinan tidak akan diterima! - - - Generated but not accepted - Terbuat tetapi tidak diterima - - - Offline - Tidak terhubung - - - Label - Label - - - Unconfirmed - Belum dikonfirmasi - - - Confirming (%1 of %2 recommended confirmations) - Sedang dikonfirmasi (%1 dari %2 konfirmasi disarankan) - - - Conflicted - Terkonflik - - - Received with - Diterima dengan - - - Received from - Diterima dari - - - Sent to - Terkirim ke - - - Payment to yourself - Pembayaran ke Anda sendiri - - - Mined - Tertambang - - - (n/a) - (t/s) - - - Transaction status. Hover over this field to show number of confirmations. - Status transaksi. Arahkan ke bagian ini untuk menampilkan jumlah konfrimasi. - - - Date and time that the transaction was received. - Tanggal dan waktu transaksi tersebut diterima. - - - Type of transaction. - Jenis transaksi. - - - Amount removed from or added to balance. - Nilai dihapus dari atau ditambahkan ke saldo. - - - - TransactionView - - All - Semua - - - Today - Hari ini - - - This week - Minggu ini - - - This month - Bulan ini - - - Last month - Bulan kemarin - - - This year - Tahun ini - - - Range... - Jarak... - - - Received with - DIterima dengan - - - Sent to - Terkirim ke - - - To yourself - Ke Anda sendiri - - - Mined - Ditambang - - - Other - Lainnya - - - Enter address or label to search - Masukkan alamat atau label untuk mencari - - - Min amount - Nilai min - - - Copy address - Salin alamat - - - Copy label - Salin label - - - Copy amount - Salin Nilai - - - Copy transaction ID - Menyalinkan ID transaksi - - - Edit label - Ubah label - - - Show transaction details - Tampilkan rincian transaksi - - - Export Transaction History - Expor Histori Transaksi - - - Exporting Failed - Proses Ekspor Gagal - - - Exporting Successful - Proses Ekspor Berhasil - - - The transaction history was successfully saved to %1. - Riwayat transaksi berhasil disimpan di %1. - - - Comma separated file (*.csv) - Berkas CSV (*.csv) - - - Confirmed - Terkonfirmasi - - - Date - Tanggal - - - Type - Jenis - - - Label - Label - - - Address - Alamat - - - ID - ID - - - Range: - Jarak: - - - to - ke - - UnitDisplayStatusBarControl - - WalletFrame - - No wallet has been loaded. - Tidak ada dompet yang dibuka - - - - WalletModel - - Send Coins - Kirim Koin - - - - WalletView - - &Export - &Ekspor - - - Export the data in the current tab to a file - Ekspor data dalam tab sekarang ke sebuah berkas - - - Backup Wallet - Cadangkan Dompet - - - Wallet Data (*.dat) - Data Dompet (*.dat) - - - Backup Failed - Cadangkgan Gagal - - - The wallet data was successfully saved to %1. - Informasi dalam dompet berhasil disimpan di %1. - - - Backup Successful - Cadangkan Berhasil - - bitcoin-core @@ -2530,12 +1389,12 @@ Terima hubungan dari luar (standar: 1 kalau -proxy atau -connect tidak dipilih) - Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) - Jalankan perintah ketika perubahan transaksi dompet (%s di cmd digantikan oleh TxID) + Bitcoin Core + Bitcoin Core - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - Tidak bisa mengikat dengan %s di computer ini. Kemungkinan Bitcoin Core sudah mulai. + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + Jalankan perintah ketika perubahan transaksi dompet (%s di cmd digantikan oleh TxID) Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. @@ -2629,18 +1488,6 @@ Wallet options: Opsi dompet: - - You need to rebuild the database using -reindex to change -txindex - Harus membangun ulang database menggunakan -reindex supaya mengubah -txindex - - - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - Tidak bisa mengunci data directory %s. Kemungkinan Bitcoin Core sudah mulai. - - - Cannot resolve -whitebind address: '%s' - Tidak dapat menyelesaikan alamat -whitebind: '%s' - Connect through SOCKS5 proxy Hubungkan melalui proxy SOCKS5 @@ -2649,18 +1496,6 @@ Information Informasi - - Invalid amount for -maxtxfee=<amount>: '%s' - Nilai salah untuk -maxtxfee=<amount>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Nilai yang salah untuk -minrelaytxfee=<amount>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - Nilai yang salah untuk -mintxfee=<amount>: '%s' - RPC server options: Opsi server RPC: @@ -2701,10 +1536,6 @@ Zapping all transactions from wallet... Setiap transaksi dalam dompet sedang di-'Zap'... - - wallet.dat corrupt, salvage failed - wallet.dat rusak, tidak bisa diperbaiki - Password for JSON-RPC connections Kata sandi untuk hubungan JSON-RPC @@ -2713,10 +1544,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) Menjalankan perintah ketika perubahan blok terbaik (%s dalam cmd digantikan oleh hash blok) - - This help message - Pesan bantuan ini - Allow DNS lookups for -addnode, -seednode and -connect Izinkan peninjauan DNS untuk -addnote, -seednode dan -connect @@ -2725,14 +1552,6 @@ Loading addresses... Memuat alamat... - - Error loading wallet.dat: Wallet corrupted - Gagal memuat wallet.dat: Dompet rusak - - - Error loading wallet.dat - Gagal memuat wallet.dat - Invalid -proxy address: '%s' Alamat -proxy salah: '%s' @@ -2741,18 +1560,6 @@ Unknown network specified in -onlynet: '%s' Jaringan tidak diketahui yang ditentukan dalam -onlynet: '%s' - - Cannot resolve -bind address: '%s' - Tidak dapat menyelesaikan alamat -bind: '%s' - - - Cannot resolve -externalip address: '%s' - Tidak dapat menyelesaikan alamat -externalip: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - Nilai salah untuk -paytxfee=<amount>: '%s' - Insufficient funds Saldo tidak mencukupi diff --git a/src/qt/locale/bitcoin_it.ts b/src/qt/locale/bitcoin_it.ts index 2f14c420146c6..b92dbb2cb3b34 100644 --- a/src/qt/locale/bitcoin_it.ts +++ b/src/qt/locale/bitcoin_it.ts @@ -25,10 +25,6 @@ C&lose C&hiudi - - &Copy Address - &Copia l'indirizzo - Delete the currently selected address from the list Rimuove dalla lista l'indirizzo attualmente selezionato @@ -45,73 +41,6 @@ &Delete &Elimina - - Choose the address to send coins to - Scegli l'indirizzo a cui inviare bitcoin - - - Choose the address to receive coins with - Scegli l'indirizzo con cui ricevere bitcoin - - - C&hoose - Sc&egli - - - Sending addresses - Indirizzi d'invio - - - Receiving addresses - Indirizzi di ricezione - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Questo è un elenco di indirizzi Bitcoin a cui puoi inviare pagamenti. Controlla sempre l'importo e l'indirizzo del beneficiario prima di inviare bitcoin. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Questi sono i tuoi indirizzi Bitcoin che puoi usare per ricevere pagamenti. Si raccomanda di generare un nuovo indirizzo per ogni transazione. - - - Copy &Label - Copia &l'etichetta - - - &Edit - &Modifica - - - Export Address List - Esporta Lista Indirizzi - - - Comma separated file (*.csv) - Testo CSV (*.csv) - - - Exporting Failed - Esportazione Fallita. - - - There was an error trying to save the address list to %1. Please try again. - Si è verificato un errore tentando di salvare la lista degli indirizzi su %1. Si prega di riprovare. - - - - AddressTableModel - - Label - Etichetta - - - Address - Indirizzo - - - (no label) - (nessuna etichetta) - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase Ripeti la nuova passphrase - - Encrypt wallet - Cifra il portamonete - - - This operation needs your wallet passphrase to unlock the wallet. - Questa operazione necessita della passphrase per sbloccare il portamonete. - - - Unlock wallet - Sblocca il portamonete - - - This operation needs your wallet passphrase to decrypt the wallet. - Quest'operazione necessita della passphrase per decifrare il portamonete, - - - Decrypt wallet - Decifra il portamonete - - - Change passphrase - Cambia la passphrase - - - Confirm wallet encryption - Conferma la cifratura del portamonete - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Attenzione: perdendo la passphrase di un portamonete cifrato <b>TUTTI I PROPRI BITCOIN ANDRANNO PERSI</b>! - - - Are you sure you wish to encrypt your wallet? - Si è sicuri di voler cifrare il portamonete? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Bitcoin Core si chiuderà per portare a termine il processo di cifratura. Si ricorda che la cifratura del portamonete non garantisce protezione totale contro i furti causati da infezioni malware. - - - 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. - IMPORTANTE: qualsiasi backup del file portamonete effettuato in precedenza dovrà essere sostituito con il file del portamonete cifrato appena generato. Per ragioni di sicurezza, i precedenti backup del file del portamonete non cifrato diventeranno inservibili non appena si inizierà ad utilizzare il nuovo portamonete cifrato. - - - Warning: The Caps Lock key is on! - Attenzione: il tasto Blocco maiuscole è attivo! - - - Wallet encrypted - Portamonete cifrato - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Inserisci la nuova passphrase per il portamonete.<br/>Si consiglia di utilizzare <b>almeno dieci caratteri casuali</b> oppure <b>otto o più parole</b>. - - - Enter the old passphrase and new passphrase to the wallet. - Inserisci la vecchia e la nuova passphrase per il portamonete. - - - Wallet encryption failed - Cifratura del portamonete fallita - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Cifratura del portamonete fallita a causa di un errore interno. Il portamonete non è stato cifrato. - - - The supplied passphrases do not match. - Le passphrase inserite non corrispondono. - - - Wallet unlock failed - Sblocco del portamonete fallito - - - The passphrase entered for the wallet decryption was incorrect. - La passphrase inserita per la decifrazione del portamonete è errata. - - - Wallet decryption failed - Decifrazione del portamonete fallita - - - Wallet passphrase was successfully changed. - Passphrase del portamonete modificata con successo. - BanTableModel @@ -269,6 +110,10 @@ Quit application Chiudi applicazione + + &About %1 + &Informazioni su %1 + About &Qt Informazioni su &Qt @@ -305,14 +150,6 @@ Open &URI... Apri &URI... - - Bitcoin Core client - Bitcoin Core client - - - Importing blocks from disk... - Importazione blocchi dal disco... - Reindexing blocks on disk... Re-indicizzazione blocchi su disco... @@ -357,10 +194,6 @@ &Receive &Ricevi - - Show information about Bitcoin Core - Mostra le informazioni su Bitcoin Core - &Show / Hide &Mostra / Nascondi @@ -397,22 +230,10 @@ Tabs toolbar Barra degli strumenti - - Bitcoin Core - Bitcoin Core - Request payments (generates QR codes and bitcoin: URIs) Richiedi pagamenti (genera codici QR e bitcoin: URI) - - &About Bitcoin Core - &Informazioni su Bitcoin Core - - - Modify configuration options for Bitcoin Core - Modifica opzioni di configurazione per Bitcoin Core - Show the list of used sending addresses and labels Mostra la lista degli indirizzi di invio utilizzati @@ -429,10 +250,6 @@ &Command-line options Opzioni della riga di &comando - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Mostra il messaggio di aiuto di Bitcoin Core per ottenere la lista delle opzioni della riga di comando valide. - %n active connection(s) to Bitcoin network %n connessione attiva alla rete Bitcoin%n connessioni alla rete Bitcoin attive @@ -544,13 +361,6 @@ Il portamonete è <b>cifrato</b> ed attualmente <b>bloccato</b> - - ClientModel - - Network Alert - Avviso di rete - - CoinControlDialog @@ -629,150 +439,6 @@ Priority Priorità - - Copy address - Copia l'indirizzo - - - Copy label - Copia l'etichetta - - - Copy amount - Copia importo - - - Copy transaction ID - Copia l'ID transazione - - - Lock unspent - Bloccare non spesi - - - Unlock unspent - Sbloccare non spesi - - - Copy quantity - Copia quantità - - - Copy fee - Copia commissione - - - Copy after fee - Copia dopo commissione - - - Copy bytes - Copia byte - - - Copy priority - Copia priorità - - - Copy dust - Copia trascurabile - - - Copy change - Copia resto - - - highest - massima - - - higher - molto alta - - - high - alta - - - medium-high - medio-alta - - - medium - media - - - low-medium - medio-bassa - - - low - bassa - - - lower - molto bassa - - - lowest - minima - - - (%1 locked) - (%1 bloccato) - - - none - nessuno - - - This label turns red if the transaction size is greater than 1000 bytes. - Questa etichetta diventerà rossa se la dimensione della transazione supererà i 1000 byte. - - - This label turns red if the priority is smaller than "medium". - Questa etichetta diventerà rossa se la priorità sarà inferiore a "media". - - - This label turns red if any recipient receives an amount smaller than %1. - Questa etichetta diventerà rossa se uno qualsiasi dei destinatari riceverà un importo inferiore a %1. - - - Can vary +/- %1 satoshi(s) per input. - Può variare di +/- %1 satoshi per input. - - - yes - - - - no - no - - - This means a fee of at least %1 per kB is required. - In tal caso sarà necessaria una commissione di almeno %1 per ogni kB. - - - Can vary +/- 1 byte per input. - Può variare di +/- 1 byte per input. - - - Transactions with higher priority are more likely to get included into a block. - Le transazioni con priorità più alta hanno più probabilità di essere incluse in un blocco. - - - (no label) - (nessuna etichetta) - - - change from %1 (%2) - resto da %1 (%2) - - - (change) - (resto) - EditAddressDialog @@ -796,38 +462,6 @@ &Address &Indirizzo - - New receiving address - Nuovo indirizzo di ricezione - - - New sending address - Nuovo indirizzo d'invio - - - Edit receiving address - Modifica indirizzo di ricezione - - - Edit sending address - Modifica indirizzo d'invio - - - The entered address "%1" is already in the address book. - L'indirizzo "%1" è già presente in rubrica. - - - The entered address "%1" is not a valid Bitcoin address. - L'indirizzo "%1" non è un indirizzo bitcoin valido. - - - Could not unlock wallet. - Impossibile sbloccare il portamonete. - - - New key generation failed. - Generazione della nuova chiave non riuscita. - FreespaceChecker @@ -854,10 +488,6 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin Core - version versione @@ -866,10 +496,6 @@ (%1-bit) (%1-bit) - - About Bitcoin Core - Informazioni su Bitcoin Core - Command-line options Opzioni della riga di comando @@ -906,29 +532,13 @@ Show splash screen on startup (default: %u) Mostra schermata iniziale all'avvio (default: %u) - - Reset all settings changes made over the GUI - Reset di tutte le modifiche alle impostazioni eseguite da interfaccia grafica - - + Intro Welcome Benvenuto - - Welcome to Bitcoin Core. - Benvenuti su Bitcoin Core. - - - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - Visto che questa è la prima volta che il programma viene lanciato, puoi scegliere dove Bitcoin Core salverà i propri dati. - - - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - Bitcoin Core scaricherà e salverà una copia della block chain di Bitcoin. Il portamonete ed almeno %1GB di dati saranno salvati in questa cartella. Si ricorda che lo spazio occupato andrà ad aumentare nel tempo. - Use the default data directory Usa la cartella dati predefinita @@ -937,10 +547,6 @@ Use a custom data directory: Usa una cartella dati personalizzata: - - Bitcoin Core - Bitcoin Core - Error: Specified data directory "%1" cannot be created. Errore: La cartella dati "%1" specificata non può essere creata. @@ -976,10 +582,6 @@ Select payment request file Seleziona il file di richiesta di pagamento - - Select payment request file to open - Seleziona il file di richiesta di pagamento da aprire - OptionsDialog @@ -1019,10 +621,6 @@ 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. Riduci ad icona invece di uscire dall'applicazione quando la finestra viene chiusa. Attivando questa opzione l'applicazione terminerà solo dopo aver selezionato Esci dal menu File. - - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - La lingua dell'interfaccia utente può essere impostata qui. L'applicazione delle modifiche avrà effetto dopo il riavvio di Bitcoin Core. - 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 |. URL di terze parti (ad es. un block explorer) che appaiono nella tabella delle transazioni come voci nel menu contestuale. "%s" nell'URL è sostituito dall'hash della transazione. @@ -1048,14 +646,6 @@ Per specificare più URL separarli con una barra verticale "|". &Network Rete - - Automatically start Bitcoin Core after logging in to the system. - Avvia automaticamente Bitcoin Core una volta effettuato l'accesso al sistema. - - - &Start Bitcoin Core on system login - &Avvia Bitcoin Core all'accesso al sistema - (0 = auto, <0 = leave that many cores free) (0 = automatico, <0 = lascia questo numero di core liberi) @@ -1285,182 +875,72 @@ Per specificare più URL separarli con una barra verticale "|". - PaymentServer + PeerTableModel - URI handling - Gestione URI + User Agent + User Agent - Invalid payment address %1 - Indirizzo di pagamento non valido %1 + Node/Service + Nodo/Servizio - Payment request rejected - Richiesta di pagamento respinta + Ping Time + Tempo di ping + + + QObject - Payment request network doesn't match client network. - La rete della richiesta di pagamento non corrisponde alla rete del client. + Amount + Importo - Payment request is not initialized. - La richiesta di pagamento non è stata inizializzata. + Enter a Bitcoin address (e.g. %1) + Inserisci un indirizzo Bitcoin (ad es. %1) - Requested payment amount of %1 is too small (considered dust). - L'importo di pagamento di %1 richiesto è troppo basso (considerato come trascurabile). + %1 d + %1 d - Payment request error - Errore di richiesta di pagamento + %1 h + %1 h - Cannot start bitcoin: click-to-pay handler - Impossibile avviare bitcoin: gestore click-to-pay + %1 m + %1 m - Payment request fetch URL is invalid: %1 - URL di recupero della Richiesta di pagamento non valido: %1 + %1 s + %1 s - URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - Impossibile interpretare l'URI! I parametri URI o l'indirizzo Bitcoin potrebbero non essere corretti. + None + Nessuno - Payment request file handling - Gestione del file di richiesta del pagamento + N/A + N/D - Payment request file cannot be read! This can be caused by an invalid payment request file. - Impossibile leggere il file della richiesta di pagamento! Il file della richiesta di pagamento potrebbe non essere valido. + %1 ms + %1 ms + + + RPCConsole - Payment request expired. - Richiesta di pagamento scaduta. + Client name + Nome del client - Unverified payment requests to custom payment scripts are unsupported. - Le richieste di pagamento non verificate verso script di pagamento personalizzati non sono supportate. + N/A + N/D - Invalid payment request. - Richiesta di pagamento non valida. - - - Refund from %1 - Rimborso da %1 - - - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - La richiesta di pagamento %1 (%2 byte) supera la dimensione massima di %3 byte. - - - Error communicating with %1: %2 - Errore di comunicazione con %1: %2 - - - Payment request cannot be parsed! - La richiesta di pagamento non può essere analizzata! - - - Bad response from server %1 - Risposta errata da parte del server %1 - - - Payment acknowledged - Pagamento riconosciuto - - - Network request error - Errore di richiesta di rete - - - - PeerTableModel - - User Agent - User Agent - - - Node/Service - Nodo/Servizio - - - Ping Time - Tempo di ping - - - - QObject - - Amount - Importo - - - Enter a Bitcoin address (e.g. %1) - Inserisci un indirizzo Bitcoin (ad es. %1) - - - %1 d - %1 d - - - %1 h - %1 h - - - %1 m - %1 m - - - %1 s - %1 s - - - None - Nessuno - - - N/A - N/D - - - %1 ms - %1 ms - - - - QRImageWidget - - &Save Image... - &Salva Immagine... - - - &Copy Image - &Copia Immagine - - - Save QR Code - Salva codice QR - - - PNG Image (*.png) - Immagine PNG (*.png) - - - - RPCConsole - - Client name - Nome del client - - - N/A - N/D - - - Client version - Versione client + Client version + Versione client &Information @@ -1514,10 +994,6 @@ Per specificare più URL separarli con una barra verticale "|". Memory usage Utilizzo memoria - - Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. - Apre il file log di debug di Bitcoin Core dalla cartella dati attuale. Questa azione può richiedere alcuni secondi per file log di grandi dimensioni. - Received Ricevuto @@ -1634,10 +1110,6 @@ Per specificare più URL separarli con una barra verticale "|". Out: Uscita: - - Build date - Data di creazione - Debug log file File log del Debug @@ -1674,10 +1146,6 @@ Per specificare più URL separarli con una barra verticale "|". &Unban Node &Elimina Ban Nodo - - Welcome to the Bitcoin Core RPC console. - Benvenuto nella console RPC di Bitcoin Core. - Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. Usa le frecce direzionali per scorrere la cronologia, e <b>Ctrl-L</b> per cancellarla. @@ -1805,18 +1273,6 @@ Per specificare più URL separarli con una barra verticale "|". Remove Rimuovi - - Copy label - Copia l'etichetta - - - Copy message - Copia il messaggio - - - Copy amount - Copia l'importo - ReceiveRequestDialog @@ -1836,73 +1292,6 @@ Per specificare più URL separarli con una barra verticale "|". &Save Image... &Salva Immagine... - - Request payment to %1 - Richiesta di pagamento a %1 - - - Payment information - Informazioni pagamento - - - URI - URI - - - Address - Indirizzo - - - Amount - Importo - - - Label - Etichetta - - - Message - Messaggio - - - Resulting URI too long, try to reduce the text for label / message. - L'URI risultante è troppo lungo, prova a ridurre il testo nell'etichetta / messaggio. - - - Error encoding URI into QR Code. - Errore nella codifica dell'URI nel codice QR. - - - - RecentRequestsTableModel - - Date - Data - - - Label - Etichetta - - - Message - Messaggio - - - Amount - Importo - - - (no label) - (nessuna etichetta) - - - (no message) - (nessun messaggio) - - - (no amount) - (nessun importo) - SendCoinsDialog @@ -1952,954 +1341,308 @@ Per specificare più URL separarli con una barra verticale "|". Change: - Resto: - - - If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address. - In caso di abilitazione con indirizzo vuoto o non valido, il resto sarà inviato ad un nuovo indirizzo generato appositamente. - - - Custom change address - Personalizza indirizzo di resto - - - Transaction Fee: - Commissione di Transazione: - - - Choose... - Scegli... - - - collapse fee-settings - minimizza le impostazioni di commissione - - - per kilobyte - per kilobyte - - - If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte. - Se la commissione personalizzata è impostata su 1000 satoshi e la transazione è di soli 250 byte, allora "per kilobyte" paga solo 250 satoshi di commissione, mentre "somma almeno" paga 1000 satoshi. Per transazioni più grandi di un kilobyte, entrambe le opzioni pagano al kilobyte. - - - Hide - Nascondi - - - total at least - somma almeno - - - Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process. - Non vi è alcuna controindicazione a pagare la commissione minima, a patto che il volume delle transazioni sia inferiore allo spazio disponibile nei blocchi. Occorre comunque essere consapevoli che ciò potrebbe impedire la conferma delle transazioni nel caso in cui la rete risultasse satura. - - - (read the tooltip) - (leggi il suggerimento) - - - Recommended: - Raccomandata: - - - Custom: - Personalizzata: - - - (Smart fee not initialized yet. This usually takes a few blocks...) - (Commissione intelligente non ancora inizializzata. Normalmente richiede un'attesa di alcuni blocchi...) - - - Confirmation time: - Tempo di conferma: - - - normal - normale - - - fast - veloce - - - Send as zero-fee transaction if possible - Invia come transazione a zero commissioni se possibile - - - (confirmation may take longer) - (la conferma potrebbe richiedere più tempo) - - - Send to multiple recipients at once - Invia simultaneamente a più beneficiari - - - Add &Recipient - &Aggiungi beneficiario - - - Clear all fields of the form. - Cancellare tutti i campi del modulo. - - - Dust: - Trascurabile: - - - Clear &All - Cancella &tutto - - - Balance: - Saldo: - - - Confirm the send action - Conferma l'azione di invio - - - S&end - &Invia - - - Confirm send coins - Conferma l'invio di bitcoin - - - %1 to %2 - %1 a %2 - - - Copy quantity - Copia quantità - - - Copy amount - Copia importo - - - Copy fee - Copia commissione - - - Copy after fee - Copia dopo commissione - - - Copy bytes - Copia byte - - - Copy priority - Copia priorità - - - Copy change - Copia resto - - - Total Amount %1 - Ammontare Totale %1 - - - or - o - - - The amount to pay must be larger than 0. - L'importo da pagare deve essere maggiore di 0. - - - The amount exceeds your balance. - L'importo è superiore al tuo saldo attuale. - - - The total exceeds your balance when the %1 transaction fee is included. - Il totale è superiore al tuo saldo attuale includendo la commissione di %1. - - - Transaction creation failed! - Creazione transazione fallita! - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - La transazione è stata respinta! Questo può accadere se alcuni bitcoin nel tuo portamonete sono già stati spesi, come nel caso in cui tu avessi utilizzato una copia del file wallet.dat per spendere bitcoin e questi non fossero stati considerati come spesi dal portamonete corrente. - - - A fee higher than %1 is considered an absurdly high fee. - Una commissione maggiore di %1 è considerata irragionevolmente elevata. - - - Payment request expired. - Richiesta di pagamento scaduta. - - - Pay only the required fee of %1 - Paga solamente la commissione richiesta di %1 - - - Estimated to begin confirmation within %n block(s). - Inizio delle conferme stimato entro %n blocco.Inizio delle conferme stimato entro %n blocchi. - - - The recipient address is not valid. Please recheck. - L'indirizzo del beneficiario non è valido. Si prega di ricontrollare. - - - Duplicate address found: addresses should only be used once each. - Rilevato un indirizzo duplicato Ciascun indirizzo dovrebbe essere utilizzato una sola volta. - - - Warning: Invalid Bitcoin address - Attenzione: Indirizzo Bitcoin non valido - - - (no label) - (nessuna etichetta) - - - Warning: Unknown change address - Attenzione: Indirizzo per il resto sconosciuto - - - Copy dust - Copia trascurabile - - - Are you sure you want to send? - Sei sicuro di voler inviare? - - - added as transaction fee - aggiunto come tassa di transazione - - - - SendCoinsEntry - - A&mount: - &Importo: - - - Pay &To: - Paga &a: - - - Enter a label for this address to add it to your address book - Inserisci un'etichetta per questo indirizzo, per aggiungerlo alla rubrica - - - &Label: - &Etichetta: - - - Choose previously used address - Scegli un indirizzo usato precedentemente - - - This is a normal payment. - Questo è un normale pagamento. - - - The Bitcoin address to send the payment to - L'indirizzo Bitcoin a cui vuoi inviare il pagamento - - - Alt+A - Alt+A - - - Paste address from clipboard - Incollare l'indirizzo dagli appunti - - - Alt+P - Alt+P - - - Remove this entry - Rimuovi questa voce - - - 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. - La commissione sarà sottratta dall'importo che si sta inviando. Il beneficiario riceverà un totale di bitcoin inferiore al valore digitato. Nel caso in cui siano stati selezionati più beneficiari la commissione sarà suddivisa in parti uguali. - - - S&ubtract fee from amount - S&ottrae la commissione dall'importo - - - Message: - Messaggio: - - - This is an unauthenticated payment request. - Questa è una richiesta di pagamento non autenticata. - - - This is an authenticated payment request. - Questa è una richiesta di pagamento autenticata. - - - Enter a label for this address to add it to the list of used addresses - Inserisci un'etichetta per questo indirizzo per aggiungerlo alla lista degli indirizzi utilizzati - - - 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. - Messaggio incluso nel bitcoin URI e che sarà memorizzato con la transazione per vostro riferimento. Nota: Questo messaggio non sarà inviato attraverso la rete Bitcoin. - - - Pay To: - Pagare a: - - - Memo: - Memo: - - - - ShutdownWindow - - Bitcoin Core is shutting down... - Arresto di Bitcoin Core in corso... - - - Do not shut down the computer until this window disappears. - Non spegnere il computer fino a quando questa finestra non si sarà chiusa. - - - - SignVerifyMessageDialog - - Signatures - Sign / Verify a Message - Firme - Firma / Verifica un messaggio - - - &Sign Message - &Firma Messaggio - - - 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. - È possibile firmare messaggi/accordi con i propri indirizzi in modo da dimostrare di poter ricevere bitcoin attraverso di essi. Si consiglia di prestare attenzione a non firmare dichiarazioni vaghe o casuali, attacchi di phishing potrebbero cercare di indurre ad apporre la firma su di esse. Si raccomanda di firmare esclusivamente dichiarazioni completamente dettagliate e delle quali si condivide in pieno il contenuto. - - - The Bitcoin address to sign the message with - L'indirizzo Bitcoin da utilizzare per firmare il messaggio - - - Choose previously used address - Scegli un indirizzo usato precedentemente - - - Alt+A - Alt+A - - - Paste address from clipboard - Incolla l'indirizzo dagli appunti - - - Alt+P - Alt+P - - - Enter the message you want to sign here - Inserisci qui il messaggio che vuoi firmare - - - Signature - Firma - - - Copy the current signature to the system clipboard - Copia la firma corrente nella clipboard - - - Sign the message to prove you own this Bitcoin address - Firma un messaggio per dimostrare di possedere questo indirizzo Bitcoin - - - Sign &Message - Firma &Messaggio - - - Reset all sign message fields - Reimposta tutti i campi della firma messaggio - - - Clear &All - Cancella &Tutto - - - &Verify Message - &Verifica Messaggio - - - 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! - Per verificare il messaggio inserire l'indirizzo del firmatario, il messaggio e la firma nei campi sottostanti, assicurandosi di copiare esattamente anche ritorni a capo, spazi, tabulazioni, etc.. Si raccomanda di non lasciarsi fuorviare dalla firma a leggere più di quanto non sia riportato nel testo del messaggio stesso, in modo da evitare di cadere vittima di attacchi di tipo man-in-the-middle. Si ricorda che la verifica della firma dimostra soltanto che il firmatario può ricevere pagamenti con l'indirizzo corrispondente, non prova l'invio di alcuna transazione. - - - The Bitcoin address the message was signed with - L'indirizzo Bitcoin con cui è stato contrassegnato il messaggio - - - Verify the message to ensure it was signed with the specified Bitcoin address - Verifica il messaggio per accertare che sia stato firmato con l'indirizzo specificato - - - Verify &Message - Verifica &Messaggio - - - Reset all verify message fields - Reimposta tutti i campi della verifica messaggio - - - Click "Sign Message" to generate signature - Clicca "Firma il messaggio" per ottenere la firma - - - The entered address is invalid. - L'indirizzo inserito non è valido. - - - Please check the address and try again. - Per favore controlla l'indirizzo e prova di nuovo. - - - The entered address does not refer to a key. - L'indirizzo bitcoin inserito non è associato a nessuna chiave. - - - Wallet unlock was cancelled. - Sblocco del portamonete annullato. - - - Private key for the entered address is not available. - La chiave privata per l'indirizzo inserito non è disponibile. - - - Message signing failed. - Firma messaggio fallita. - - - Message signed. - Messaggio firmato. - - - The signature could not be decoded. - Non è stato possibile decodificare la firma. - - - Please check the signature and try again. - Per favore controlla la firma e prova di nuovo. - - - The signature did not match the message digest. - La firma non corrisponde al digest del messaggio. - - - Message verification failed. - Verifica messaggio fallita. - - - Message verified. - Messaggio verificato. - - - - SplashScreen - - Bitcoin Core - Bitcoin Core - - - The Bitcoin Core developers - Gli sviluppatori di Bitcoin Core - - - [testnet] - [testnet] - - - - TrafficGraphWidget - - KB/s - KB/s - - - - TransactionDesc - - Open until %1 - Aperto fino a %1 - - - conflicted - in conflitto - - - %1/offline - %1/offline - - - %1/unconfirmed - %1/non confermata - - - %1 confirmations - %1 conferme - - - Status - Stato - - - , broadcast through %n node(s) - , trasmesso attraverso %n nodo, trasmessa attraverso %n nodi - - - Date - Data - - - Source - Sorgente - - - Generated - Generato - - - From - Da - - - To - A - - - own address - proprio indirizzo - - - watch-only - sola lettura - - - label - etichetta - - - Credit - Credito - - - matures in %n more block(s) - matura tra %n bloccomatura tra %n blocchi - - - not accepted - non accettate - - - Debit - Debito - - - Total debit - Debito totale - - - Total credit - Credito totale - - - Transaction fee - Commissione transazione - - - Net amount - Importo netto - - - Message - Messaggio - - - Comment - Commento - - - Transaction ID - ID della transazione - - - Merchant - Commerciante - - - 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. - È necessario attendere %1 blocchi prima che i bitcoin generati possano essere spesi. Al momento della generazione questo blocco è stato trasmesso alla rete in modo da poter essere aggiunto alla block chain. Se l'inserimento avrà esito negativo lo stato del blocco sarà modificato in "non accettato" ed esso risulterà non spendibile. Ciò può verificarsi occasionalmente nel caso in cui un altro blocco sia stato generato entro pochi secondi dal tuo. - - - Debug information - Informazione di debug - - - Transaction - Transazione - - - Inputs - Input - - - Amount - Importo - - - true - vero + Resto: - false - falso + If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address. + In caso di abilitazione con indirizzo vuoto o non valido, il resto sarà inviato ad un nuovo indirizzo generato appositamente. - , has not been successfully broadcast yet - , non è ancora stata trasmessa con successo - - - Open for %n more block(s) - Aperto per %n altro bloccoAperto per altri %n blocchi + Custom change address + Personalizza indirizzo di resto - unknown - sconosciuto + Transaction Fee: + Commissione di Transazione: - - - TransactionDescDialog - Transaction details - Dettagli sulla transazione + Choose... + Scegli... - This pane shows a detailed description of the transaction - Questo pannello mostra una descrizione dettagliata della transazione + collapse fee-settings + minimizza le impostazioni di commissione - - - TransactionTableModel - Date - Data + per kilobyte + per kilobyte - Type - Tipo + If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte. + Se la commissione personalizzata è impostata su 1000 satoshi e la transazione è di soli 250 byte, allora "per kilobyte" paga solo 250 satoshi di commissione, mentre "somma almeno" paga 1000 satoshi. Per transazioni più grandi di un kilobyte, entrambe le opzioni pagano al kilobyte. - Immature (%1 confirmations, will be available after %2) - Immaturo (%1 conferme, sarà disponibile fra %2) - - - Open for %n more block(s) - Aperto per %n altro bloccoAperto per altri %n blocchi + Hide + Nascondi - Open until %1 - Aperto fino a %1 + total at least + somma almeno - Confirmed (%1 confirmations) - Confermata (%1 conferme) + Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process. + Non vi è alcuna controindicazione a pagare la commissione minima, a patto che il volume delle transazioni sia inferiore allo spazio disponibile nei blocchi. Occorre comunque essere consapevoli che ciò potrebbe impedire la conferma delle transazioni nel caso in cui la rete risultasse satura. - This block was not received by any other nodes and will probably not be accepted! - Questo blocco non è stato ricevuto da alcun altro nodo e probabilmente non sarà accettato! + (read the tooltip) + (leggi il suggerimento) - Generated but not accepted - Generati, ma non accettati + Recommended: + Raccomandata: - Offline - Offline + Custom: + Personalizzata: - Label - Etichetta + (Smart fee not initialized yet. This usually takes a few blocks...) + (Commissione intelligente non ancora inizializzata. Normalmente richiede un'attesa di alcuni blocchi...) - Unconfirmed - Non confermata + Confirmation time: + Tempo di conferma: - Confirming (%1 of %2 recommended confirmations) - In conferma (%1 di %2 conferme raccomandate) + normal + normale - Conflicted - In conflitto + fast + veloce - Received with - Ricevuto tramite + Send to multiple recipients at once + Invia simultaneamente a più beneficiari - Received from - Ricevuto da + Add &Recipient + &Aggiungi beneficiario - Sent to - Inviato a + Clear all fields of the form. + Cancellare tutti i campi del modulo. - Payment to yourself - Pagamento a te stesso + Dust: + Trascurabile: - Mined - Ottenuto dal mining + Clear &All + Cancella &tutto - watch-only - sola lettura + Balance: + Saldo: - (n/a) - (n/d) + Confirm the send action + Conferma l'azione di invio - Transaction status. Hover over this field to show number of confirmations. - Stato della transazione. Passare con il mouse su questo campo per visualizzare il numero di conferme. + S&end + &Invia + + + SendCoinsEntry - Date and time that the transaction was received. - Data e ora in cui la transazione è stata ricevuta. + A&mount: + &Importo: - Type of transaction. - Tipo di transazione. + Pay &To: + Paga &a: - Whether or not a watch-only address is involved in this transaction. - Indica se un indirizzo di sola lettura sia o meno coinvolto in questa transazione. + &Label: + &Etichetta: - User-defined intent/purpose of the transaction. - Intento/scopo della transazione definito dall'utente. + Choose previously used address + Scegli un indirizzo usato precedentemente - Amount removed from or added to balance. - Importo rimosso o aggiunto al saldo. + This is a normal payment. + Questo è un normale pagamento. - - - TransactionView - All - Tutti + The Bitcoin address to send the payment to + L'indirizzo Bitcoin a cui vuoi inviare il pagamento - Today - Oggi + Alt+A + Alt+A - This week - Questa settimana + Paste address from clipboard + Incollare l'indirizzo dagli appunti - This month - Questo mese + Alt+P + Alt+P - Last month - Il mese scorso + Remove this entry + Rimuovi questa voce - This year - Quest'anno + 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. + La commissione sarà sottratta dall'importo che si sta inviando. Il beneficiario riceverà un totale di bitcoin inferiore al valore digitato. Nel caso in cui siano stati selezionati più beneficiari la commissione sarà suddivisa in parti uguali. - Range... - Intervallo... + S&ubtract fee from amount + S&ottrae la commissione dall'importo - Received with - Ricevuto tramite + Message: + Messaggio: - Sent to - Inviato a + This is an unauthenticated payment request. + Questa è una richiesta di pagamento non autenticata. - To yourself - A te stesso + This is an authenticated payment request. + Questa è una richiesta di pagamento autenticata. - Mined - Ottenuto dal mining + Enter a label for this address to add it to the list of used addresses + Inserisci un'etichetta per questo indirizzo per aggiungerlo alla lista degli indirizzi utilizzati - Other - Altro + 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. + Messaggio incluso nel bitcoin URI e che sarà memorizzato con la transazione per vostro riferimento. Nota: Questo messaggio non sarà inviato attraverso la rete Bitcoin. - Enter address or label to search - Inserisci un indirizzo o un'etichetta da cercare + Pay To: + Pagare a: - Min amount - Importo minimo + Memo: + Memo: + + + ShutdownWindow - Copy address - Copia l'indirizzo + Do not shut down the computer until this window disappears. + Non spegnere il computer fino a quando questa finestra non si sarà chiusa. + + + SignVerifyMessageDialog - Copy label - Copia l'etichetta + Signatures - Sign / Verify a Message + Firme - Firma / Verifica un messaggio - Copy amount - Copia l'importo + &Sign Message + &Firma Messaggio - Copy transaction ID - Copia l'ID transazione + 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. + È possibile firmare messaggi/accordi con i propri indirizzi in modo da dimostrare di poter ricevere bitcoin attraverso di essi. Si consiglia di prestare attenzione a non firmare dichiarazioni vaghe o casuali, attacchi di phishing potrebbero cercare di indurre ad apporre la firma su di esse. Si raccomanda di firmare esclusivamente dichiarazioni completamente dettagliate e delle quali si condivide in pieno il contenuto. - Copy raw transaction - Copia la transazione raw + The Bitcoin address to sign the message with + L'indirizzo Bitcoin da utilizzare per firmare il messaggio - Edit label - Modifica l'etichetta + Choose previously used address + Scegli un indirizzo usato precedentemente - Show transaction details - Mostra i dettagli della transazione + Alt+A + Alt+A - Export Transaction History - Esporta lo storico delle transazioni + Paste address from clipboard + Incolla l'indirizzo dagli appunti - Watch-only - Sola lettura + Alt+P + Alt+P - Exporting Failed - Esportazione Fallita. + Enter the message you want to sign here + Inserisci qui il messaggio che vuoi firmare - There was an error trying to save the transaction history to %1. - Si è verificato un errore durante il salvataggio dello storico delle transazioni in %1. + Signature + Firma - Exporting Successful - Esportazione Riuscita + Copy the current signature to the system clipboard + Copia la firma corrente nella clipboard - The transaction history was successfully saved to %1. - Lo storico delle transazioni e' stato salvato con successo in %1. + Sign the message to prove you own this Bitcoin address + Firma un messaggio per dimostrare di possedere questo indirizzo Bitcoin - Comma separated file (*.csv) - Testo CSV (*.csv) + Sign &Message + Firma &Messaggio - Confirmed - Confermato + Reset all sign message fields + Reimposta tutti i campi della firma messaggio - Date - Data + Clear &All + Cancella &Tutto - Type - Tipo + &Verify Message + &Verifica Messaggio - Label - Etichetta + 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! + Per verificare il messaggio inserire l'indirizzo del firmatario, il messaggio e la firma nei campi sottostanti, assicurandosi di copiare esattamente anche ritorni a capo, spazi, tabulazioni, etc.. Si raccomanda di non lasciarsi fuorviare dalla firma a leggere più di quanto non sia riportato nel testo del messaggio stesso, in modo da evitare di cadere vittima di attacchi di tipo man-in-the-middle. Si ricorda che la verifica della firma dimostra soltanto che il firmatario può ricevere pagamenti con l'indirizzo corrispondente, non prova l'invio di alcuna transazione. - Address - Indirizzo + The Bitcoin address the message was signed with + L'indirizzo Bitcoin con cui è stato contrassegnato il messaggio - ID - ID + Verify the message to ensure it was signed with the specified Bitcoin address + Verifica il messaggio per accertare che sia stato firmato con l'indirizzo specificato - Range: - Intervallo: + Verify &Message + Verifica &Messaggio - to - a + Reset all verify message fields + Reimposta tutti i campi della verifica messaggio - UnitDisplayStatusBarControl + SplashScreen - Unit to show amounts in. Click to select another unit. - Unità con cui visualizzare gli importi. Clicca per selezionare un'altra unità. + [testnet] + [testnet] - WalletFrame + TrafficGraphWidget - No wallet has been loaded. - Non è stato caricato alcun portamonete. + KB/s + KB/s - WalletModel + TransactionDescDialog - Send Coins - Invia Bitcoin + This pane shows a detailed description of the transaction + Questo pannello mostra una descrizione dettagliata della transazione - WalletView - - &Export - &Esporta - - - Export the data in the current tab to a file - Esporta su file i dati contenuti nella tabella corrente - - - Backup Wallet - Backup Portamonete - - - Wallet Data (*.dat) - Dati Portamonete (*.dat) - - - Backup Failed - Backup Fallito - - - There was an error trying to save the wallet data to %1. - Si è verificato un errore durante il salvataggio dei dati del portamonete in %1. - - - The wallet data was successfully saved to %1. - Il portamonete è stato correttamente salvato in %1. - + UnitDisplayStatusBarControl - Backup Successful - Backup eseguito con successo + Unit to show amounts in. Click to select another unit. + Unità con cui visualizzare gli importi. Clicca per selezionare un'altra unità. @@ -2928,14 +1671,6 @@ Per specificare più URL separarli con una barra verticale "|". If <category> is not supplied or if <category> = 1, output all debugging information. Se <category> non è specificato oppure se <category> = 1, mostra tutte le informazioni di debug. - - Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s) - Totale massimo di commissioni (in %s) da usare in una singola transazione del wallet; valori troppo bassi possono abortire grandi transazioni (default: %s) - - - Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. - Per favore controllate che la data del computer e l'ora siano corrette. Se il vostro orologio è sbagliato Bitcoin non funzionerà correttamente. - Prune configured below the minimum of %d MiB. Please use a higher number. La modalità prune è configurata al di sotto del minimo di %d MB. Si prega di utilizzare un valore più elevato. @@ -2976,6 +1711,10 @@ Per specificare più URL separarli con una barra verticale "|". Accept connections from outside (default: 1 if no -proxy or -connect) Accetta connessioni dall'esterno (predefinito: 1 se -proxy o -connect non sono utilizzati) + + Bitcoin Core + Bitcoin Core + Bind to given address and always listen on it. Use [host]:port notation for IPv6 Associa all'indirizzo indicato e resta permanentemente in ascolto su di esso. Usa la notazione [host]:porta per l'IPv6 @@ -3004,10 +1743,6 @@ Per specificare più URL separarli con una barra verticale "|". This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Questa versione è una compilazione pre-rilascio - usala a tuo rischio - non utilizzarla per la generazione o per applicazioni di commercio - - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - Impossibile associarsi a %s su questo computer. Probabilmente Bitcoin Core è già in esecuzione. - Use UPnP to map the listening port (default: 1 when listening and no -proxy) Utilizza UPnP per mappare la porta in ascolto (default: 1 quando in ascolto e -proxy non è specificato) @@ -3028,10 +1763,6 @@ Per specificare più URL separarli con una barra verticale "|". Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Attenzione: Sembra che non vi sia pieno consenso con i nostri peer! Un aggiornamento da parte tua o degli altri nodi potrebbe essere necessario. - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Attenzione: wallet.dat corrotto, dati recuperati! Il wallet.dat originale è stato salvato come wallet.{timestamp}.bak in %s. Se i dati relativi a saldo o transazioni non dovessero risultare corretti si consiglia di procedere al ripristino da un backup. - Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. Inserisce in whitelist i peer che si connettono da un dato indirizzo IP o netmask. Può essere specificato più volte. @@ -3192,10 +1923,6 @@ Per specificare più URL separarli con una barra verticale "|". Wallet options: Opzioni portamonete: - - You need to rebuild the database using -reindex to change -txindex - È necessario ricostruire il database usando -reindex per cambiare -txindex - 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 Permette connessioni JSON-RPC dall'origine specificata. I valori validi per <ip> sono un singolo IP (ad es. 1.2.3.4), una network/netmask (ad es. 1.2.3.4/255.255.255.0) oppure una network/CIDR (ad es. 1.2.3.4/24). Questa opzione può essere specificata più volte. @@ -3208,10 +1935,6 @@ Per specificare più URL separarli con una barra verticale "|". Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces) Resta in attesa di connessioni JSON-RPC sull'indirizzo indicato. Usa la notazione [host]:porta per IPv6. Questa opzione può essere specificata più volte (predefinito: associa a tutte le interfacce) - - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - Non è possibile ottenere un lock sulla cartella %s. Probabilmente Bitcoin Core è già in esecuzione. - Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) Crea nuovi file con i permessi di default del sistema, invece che con umask 077 (ha effetto solo con funzionalità di portamonete disabilitate) @@ -3256,10 +1979,6 @@ Per specificare più URL separarli con una barra verticale "|". Set maximum size of high-priority/low-fee transactions in bytes (default: %d) Imposta la dimensione massima in byte delle transazioni ad alta-priorità/basse-commissioni (predefinito: %d) - - Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) - Specifica il numero di thread per la generazione di bitcoin, se abilitata (-1 = tutti i core, predefinito: %d) - The transaction amount is too small to send after the fee has been deducted L'importo della transazione risulta troppo basso per l'invio una volta dedotte le commissioni. @@ -3284,34 +2003,14 @@ Per specificare più URL separarli con una barra verticale "|". Accept public REST requests (default: %u) Accetta richieste REST pubbliche (predefinito: %u) - - Activating best chain... - Attivazione della blockchain migliore... - - - Attempt to recover private keys from a corrupt wallet.dat on startup - Prova a recuperare le chiavi private da un wallet corrotto all'avvio - Automatically create Tor hidden service (default: %d) Crea automaticamente il servizio Tor (default: %d) - - Cannot resolve -whitebind address: '%s' - Impossibile risolvere indirizzo -whitebind: '%s' - Connect through SOCKS5 proxy Connessione attraverso un proxy SOCKS5 - - Copyright (C) 2009-%i The Bitcoin Core Developers - Copyright (C) 2009-%i Gli sviluppatori di Bitcoin Core - - - Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - Errore durante il caricamento del file wallet.dat: il portamonete richiede una versione di Bitcoin Core più recente - Error reading from database, shutting down. Errore durante lalettura del database. Arresto in corso. @@ -3324,22 +2023,6 @@ Per specificare più URL separarli con una barra verticale "|". Information Informazioni - - Initialization sanity check failed. Bitcoin Core is shutting down. - Test di integrità iniziale fallito. Bitcoin Core si arresterà. - - - Invalid amount for -maxtxfee=<amount>: '%s' - Importo non valido per -maxtxfee=<amount>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Importo non valido per -minrelaytxfee=<amount>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - Importo non valido per -mintxfee=<amount>: '%s' - Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) Importo non valido per -paytxfee=<amount>: '%s' (deve essere almeno %s) @@ -3364,14 +2047,6 @@ Per specificare più URL separarli con una barra verticale "|". RPC server options: Opzioni server RPC: - - Rebuild block chain index from current blk000??.dat files on startup - Ricostruzione dell'indice della block chain dai file blk000??.dat correnti all'avvio - - - Receive and display P2P network alerts (default: %u) - Ricevi e visualizza gli alerts della rete P2P (default: %u) - Reducing -maxconnections from %d to %d, because of system limitations. Riduzione -maxconnections da %d a %d a causa di limitazioni di sistema. @@ -3444,10 +2119,6 @@ Per specificare più URL separarli con una barra verticale "|". Username for JSON-RPC connections Nome utente per connessioni JSON-RPC - - Wallet needed to be rewritten: restart Bitcoin Core to complete - Il portamonete necessitava di essere riscritto: riavviare Bitcoin Core per completare l'operazione - Warning Attenzione @@ -3464,10 +2135,6 @@ Per specificare più URL separarli con una barra verticale "|". ZeroMQ notification options: Opzioni di notifica ZeroMQ - - wallet.dat corrupt, salvage failed - wallet.dat corrotto, recupero fallito - Password for JSON-RPC connections Password per connessioni JSON-RPC @@ -3476,10 +2143,6 @@ Per specificare più URL separarli con una barra verticale "|". Execute command when the best block changes (%s in cmd is replaced by block hash) Esegue un comando quando il miglior blocco cambia (%s nel cmd è sostituito dall'hash del blocco) - - This help message - Questo messaggio di aiuto - Allow DNS lookups for -addnode, -seednode and -connect Consente interrogazioni DNS per -addnode, -seednode e -connect @@ -3488,10 +2151,6 @@ Per specificare più URL separarli con una barra verticale "|". Loading addresses... Caricamento indirizzi... - - Error loading wallet.dat: Wallet corrupted - Errore caricamento wallet.dat: Portamonete corrotto - (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) (1 = mantiene metadati tx, ad es. proprietario account ed informazioni di richiesta di pagamento, 2 = scarta metadati tx) @@ -3508,10 +2167,6 @@ Per specificare più URL separarli con una barra verticale "|". Do not keep transactions in the mempool longer than <n> hours (default: %u) Non mantenere le transazioni nella mempool più a lungo di <n> ore (default: %u) - - Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. - Errore di lettura di wallet.dat! Tutte le chiavi sono state lette correttamente, ma i dati delle transazioni o della rubrica potrebbero essere mancanti o non corretti. - Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) Le commissioni (in %s/kB) inferiori a questo valore sono considerate pari a zero per la creazione della transazione (default: %s) @@ -3564,14 +2219,6 @@ Per specificare più URL separarli con una barra verticale "|". Always query for peer addresses via DNS lookup (default: %u) Interroga sempre i DNS per ottenere gli indirizzi dei peer (predefinito: %u) - - Error loading wallet.dat - Errore caricamento wallet.dat - - - Generate coins (default: %u) - Genera bitcoin (predefinito: %u) - How many blocks to check at startup (default: %u, 0 = all) Numero di blocchi da controllare all'avvio (predefinito: %u, 0 = tutti) @@ -3656,18 +2303,6 @@ Per specificare più URL separarli con una barra verticale "|". Unknown network specified in -onlynet: '%s' Rete sconosciuta specificata in -onlynet: '%s' - - Cannot resolve -bind address: '%s' - Impossibile risolvere indirizzo -bind: '%s' - - - Cannot resolve -externalip address: '%s' - Impossibile risolvere indirizzo -externalip: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - Importo non valido per -paytxfee=<amount>: '%s' - Insufficient funds Fondi insufficienti diff --git a/src/qt/locale/bitcoin_it_IT.ts b/src/qt/locale/bitcoin_it_IT.ts index 46ad0e9339df0..f89f4bdc48d11 100644 --- a/src/qt/locale/bitcoin_it_IT.ts +++ b/src/qt/locale/bitcoin_it_IT.ts @@ -25,10 +25,6 @@ C&lose chiudi - - &Copy Address - copia indirizzo - Delete the currently selected address from the list Cancella l'indirizzo attualmente selezionato dalla lista. @@ -45,70 +41,6 @@ &Delete Cancella - - Choose the address to send coins to - Scegli l'indirizzo a cui inviare denaro - - - Choose the address to receive coins with - Scegli l'indirizzo con cui ricevere i coin - - - C&hoose - Scegli - - - Sending addresses - Indirizzi mittenti - - - Receiving addresses - Indirizzi destinatari - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Questi sono gli indirizzi Bitcoin per l'invio di pagamenti. Controlla sempre la quantità e l'indirizzo di ricezione prima di inviare monete. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Questi sono i tuoi indirizzi Bitcoin per ricevere pagamenti. Si raccomanda di generare un nuovo indirizzo per ogni transazione - - - Copy &Label - copia etichetta - - - &Edit - Modifica - - - Export Address List - Esporta lista degli indirizzi - - - Comma separated file (*.csv) - Contenuto del file separato da virgole (*.csv) - - - Exporting Failed - Esportazione fallita - - - - AddressTableModel - - Label - Etichetta - - - Address - Indirizzo - - - (no label) - (nessuna etichetta) - - AskPassphraseDialog @@ -124,39 +56,7 @@ Repeat new passphrase Ripeti nuova passphrase - - Encrypt wallet - Cifra portagoflio - - - This operation needs your wallet passphrase to unlock the wallet. - Questa operazione richiede la passphrase del tuo portafoglio per sbloccare il portafoglio. - - - Unlock wallet - Sblocca portafoglio - - - Decrypt wallet - decifra portafoglio - - - Change passphrase - cambia passphrase - - - Confirm wallet encryption - conferma cifrazione del portagoglio - - - Wallet encrypted - portafoglio cifrato - - - Wallet unlock failed - sblocco portafoglio fallito - - + BanTableModel @@ -171,16 +71,8 @@ Transazioni - - ClientModel - CoinControlDialog - - (no label) - (nessuna etichetta) - - EditAddressDialog @@ -203,18 +95,12 @@ OverviewPage - - PaymentServer - PeerTableModel QObject - - QRImageWidget - RPCConsole @@ -223,34 +109,9 @@ ReceiveRequestDialog - - Address - Indirizzo - - - Label - Etichetta - - - - RecentRequestsTableModel - - Label - Etichetta - - - (no label) - (nessuna etichetta) - - SendCoinsDialog - - (no label) - (nessuna etichetta) - - SendCoinsEntry @@ -267,58 +128,12 @@ TrafficGraphWidget - - TransactionDesc - TransactionDescDialog - - TransactionTableModel - - Label - Etichetta - - - - TransactionView - - Exporting Failed - Esportazione fallita - - - Comma separated file (*.csv) - Contenuto del file separato da virgole (*.csv) - - - Label - Etichetta - - - Address - Indirizzo - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - - WalletView - - &Export - Esporta - - - Export the data in the current tab to a file - Esportare i dati nella scheda corrente in un file - - bitcoin-core diff --git a/src/qt/locale/bitcoin_ja.ts b/src/qt/locale/bitcoin_ja.ts index 06fd27fa161a5..b2dae186d97c9 100644 --- a/src/qt/locale/bitcoin_ja.ts +++ b/src/qt/locale/bitcoin_ja.ts @@ -25,10 +25,6 @@ C&lose 閉じる(&C) - - &Copy Address - アドレスをコピー (&C) - Delete the currently selected address from the list 選択されたアドレスを一覧から削除する @@ -45,73 +41,6 @@ &Delete 削除(&D) - - Choose the address to send coins to - 送信先のアドレスを選択 - - - Choose the address to receive coins with - 支払いを受け取るアドレスを指定する - - - C&hoose - 選択(&C) - - - Sending addresses - アドレス送信中 - - - Receiving addresses - アドレス受信中 - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - これらは支払いを送信するためのあなたの Bitcoin アドレスです。コインを送信する前に、常に額と受信アドレスを確認してください。 - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - これらは支払いを受け取るためのビットコインアドレスです。トランザクションごとに新しい受け取り用アドレスを作成することが推奨されます。 - - - Copy &Label - ラベルをコピー (&L) - - - &Edit - 編集 (&E) - - - Export Address List - アドレス帳をエクスポート - - - Comma separated file (*.csv) - CSVファイル (*.csv) - - - Exporting Failed - エクスポート失敗 - - - There was an error trying to save the address list to %1. Please try again. - トランザクション履歴を %1 へ保存する際にエラーが発生しました。再試行してください。 - - - - AddressTableModel - - Label - ラベル - - - Address - アドレス - - - (no label) - (ラベル無し) - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase 新しいパスフレーズをもう一度 - - Encrypt wallet - ウォレットを暗号化する - - - This operation needs your wallet passphrase to unlock the wallet. - この操作はウォレットをアンロックするためにパスフレーズが必要です。 - - - Unlock wallet - ウォレットをアンロックする - - - This operation needs your wallet passphrase to decrypt the wallet. - この操作はウォレットの暗号化解除のためにパスフレーズが必要です。 - - - Decrypt wallet - ウォレットの暗号化を解除する - - - Change passphrase - パスフレーズの変更 - - - Confirm wallet encryption - ウォレットの暗号化を確認する - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - 警告: もしもあなたのウォレットを暗号化してパスフレーズを失ってしまったなら、<b>あなたの Bitcoin はすべて失われます</b>! - - - Are you sure you wish to encrypt your wallet? - 本当にウォレットを暗号化しますか? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - 暗号化処理を完了させるため Bitcoin Core をいますぐ終了します。ウォレットの暗号化では、コンピュータに感染したマルウェアなどによるビットコインの盗難から完全に守ることはできないことにご注意ください。 - - - 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. - 重要: 過去のウォレット ファイルのバックアップは、暗号化された新しいウォレット ファイルに取り替える必要があります。セキュリティ上の理由により、暗号化された新しいウォレットを使い始めると、暗号化されていないウォレット ファイルのバックアップはすぐに使えなくなります。 - - - Warning: The Caps Lock key is on! - 警告: Caps Lock キーがオンになっています! - - - Wallet encrypted - ウォレットは暗号化されました - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - ウォレットの新しいパスフレーズを入力してください。<br/><b>10文字以上のランダムな文字</b>で構成されたものか、<b>8単語以上の単語</b>で構成されたパスフレーズを使用してください。 - - - Enter the old passphrase and new passphrase to the wallet. - ウォレットの古いパスフレーズおよび新しいパスフレーズを入力してください。 - - - Wallet encryption failed - ウォレットの暗号化に失敗しました - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - 内部エラーによりウォレットの暗号化が失敗しました。ウォレットは暗号化されませんでした。 - - - The supplied passphrases do not match. - パスフレーズが同じではありません。 - - - Wallet unlock failed - ウォレットのアンロックに失敗しました - - - The passphrase entered for the wallet decryption was incorrect. - ウォレットの暗号化解除のパスフレーズが正しくありません。 - - - Wallet decryption failed - ウォレットの暗号化解除に失敗しました - - - Wallet passphrase was successfully changed. - ウォレットのパスフレーズの変更が成功しました。 - BanTableModel @@ -269,6 +110,14 @@ Quit application アプリケーションを終了 + + &About %1 + %1 について (&A) + + + Show information about %1 + %1 の情報を表示 + About &Qt Qt について(&Q) @@ -281,6 +130,10 @@ &Options... オプション... (&O) + + Modify configuration options for %1 + %1 の設定を変更する + &Encrypt Wallet... ウォレットの暗号化... (&E) @@ -305,14 +158,6 @@ Open &URI... URI を開く (&U)... - - Bitcoin Core client - Bitcoinコア クライアント - - - Importing blocks from disk... - ディスクからブロックをインポートしています... - Reindexing blocks on disk... ディスク上のブロックのインデックスを再作成中... @@ -357,10 +202,6 @@ &Receive 入金 (&R) - - Show information about Bitcoin Core - Bitcoinコアに関する情報を表示 - &Show / Hide 見る/隠す (&S) @@ -397,22 +238,10 @@ Tabs toolbar タブツールバー - - Bitcoin Core - Bitcoin のコア - Request payments (generates QR codes and bitcoin: URIs) 支払いを要求する (QRコードとbitcoin:ではじまるURIを生成する) - - &About Bitcoin Core - ビットコインコアについて (&A) - - - Modify configuration options for Bitcoin Core - Bitcoin Core の設定を編集する - Show the list of used sending addresses and labels 使用済みの送金用アドレスとラベルの一覧を表示する @@ -429,14 +258,18 @@ &Command-line options コマンドラインオプション (&C) - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - 有効な Bitcoin のコマンドライン オプションを見るために Bitcoin Core のヘルプメッセージを表示します。 - %n active connection(s) to Bitcoin network %n の Bitcoin ネットワークへのアクティブな接続 + + Indexing blocks on disk... + ディスク上のブロックのインデックスを作成しています... + + + Processing blocks on disk... + ディスク上のブロックを処理しています... + No block source available... 利用可能なブロックがありません... @@ -493,6 +326,14 @@ Up to date バージョンは最新です + + Show the %1 help message to get a list with possible Bitcoin command-line options + 有効な Bitcoin のコマンドライン オプションを見るために %1 のヘルプメッセージを表示します。 + + + %1 client + %1 クライアント + Catching up... 追跡中... @@ -544,13 +385,6 @@ ウォレットは<b>暗号化されて、ロックされています</b> - - ClientModel - - Network Alert - ネットワーク警告 - - CoinControlDialog @@ -629,150 +463,6 @@ Priority 優先度 - - Copy address - アドレスをコピーする - - - Copy label - ラベルをコピーする - - - Copy amount - 総額のコピー - - - Copy transaction ID - 取引 ID をコピー - - - Lock unspent - 未使用トランザクションをロックする - - - Unlock unspent - 未使用トランザクションをアンロックする - - - Copy quantity - 数量をコピーする - - - Copy fee - 手数料をコピーする - - - Copy after fee - 手数料差引後の値をコピーする - - - Copy bytes - バイト数をコピーする - - - Copy priority - 優先度をコピーする - - - Copy dust - ダストをコピーする - - - Copy change - 釣り銭をコピー - - - highest - 最高 - - - higher - 非常に高 - - - high - - - - medium-high - 中〜高 - - - medium - - - - low-medium - 低〜中 - - - low - - - - lower - 非常に低 - - - lowest - 最低 - - - (%1 locked) - (%1 がロック済み) - - - none - なし - - - This label turns red if the transaction size is greater than 1000 bytes. - トランザクションのサイズが1000バイトを超える場合にはこのラベルは赤色になります。 - - - This label turns red if the priority is smaller than "medium". - 優先度が「中」未満の場合、このラベルは赤色になります。 - - - This label turns red if any recipient receives an amount smaller than %1. - 受取人のうち誰かの受取額が %1 未満の場合にこのラベルは赤色になります。 - - - Can vary +/- %1 satoshi(s) per input. - ひとつの入力につき %1 satoshi 前後ずれることがあります。 - - - yes - はい - - - no - いいえ - - - This means a fee of at least %1 per kB is required. - これは少なくとも1kBあたり %1 の手数料が必要であることを意味します。 - - - Can vary +/- 1 byte per input. - ひとつの入力につき1バイト程度ずれることがあります。 - - - Transactions with higher priority are more likely to get included into a block. - より高い優先度を持つトランザクションの方がブロックに取り込まれやすくなります。 - - - (no label) - (ラベル無し) - - - change from %1 (%2) - %1 (%2) からのおつり - - - (change) - (おつり) - EditAddressDialog @@ -796,38 +486,6 @@ &Address アドレス帳 (&A) - - New receiving address - 新しい入金アドレス - - - New sending address - 新しい送信アドレス - - - Edit receiving address - 入金アドレスを編集 - - - Edit sending address - 送信アドレスを編集 - - - The entered address "%1" is already in the address book. - 入力されたアドレス "%1" は既にアドレス帳にあります。 - - - The entered address "%1" is not a valid Bitcoin address. - 入力されたアドレス "%1" は無効な Bitcoin アドレスです。 - - - Could not unlock wallet. - ウォレットをアンロックできませんでした。 - - - New key generation failed. - 新しいキーの生成に失敗しました。 - FreespaceChecker @@ -854,10 +512,6 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin のコア - version バージョン @@ -867,8 +521,8 @@ (%1ビット) - About Bitcoin Core - Bitcoinコアについて + About %1 + %1 について Command-line options @@ -907,8 +561,8 @@ 起動時にスプラッシュ画面を表示する (初期値: %u) - Reset all settings changes made over the GUI - GUI 経由で行われた設定の変更を全てリセット + Reset all settings changed in the GUI + GUI で行われた設定の変更を全てリセット @@ -918,16 +572,16 @@ ようこそ - Welcome to Bitcoin Core. - ようこそ! + Welcome to %1. + %1 へようこそ。 - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - これはプログラム最初の起動です。Bitcoin Coreがデータを保存する場所を選択して下さい。 + As this is the first time the program is launched, you can choose where %1 will store its data. + これはプログラム最初の起動です。%1 がデータを保存する場所を選択して下さい。 - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - Bitcoin Coreは、ビットコインのブロックチェーンのコピーを、ダウンロードして保存します。少なくとも%1ギガバイトのデータが、このディレクトリに保存されます。そしてそれは時間と共に増加します。またウォレットもこのディレクトリに保存されます。 + %1 will download and store a copy of the Bitcoin block chain. At least %2GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. + %1 は、ビットコインのブロックチェーンのコピーを、ダウンロードして保存します。少なくとも %2 ギガバイトのデータが、このディレクトリに保存されます。そしてそれは時間と共に増加します。またウォレットもこのディレクトリに保存されます。 Use the default data directory @@ -937,10 +591,6 @@ Use a custom data directory: 任意のデータ ディレクトリを使用: - - Bitcoin Core - Bitcoin のコア - Error: Specified data directory "%1" cannot be created. エラー: 指定のデータディレクトリ "%1" を作成できません。 @@ -976,10 +626,6 @@ Select payment request file 支払いリクエストファイルを選択してください - - Select payment request file to open - 開きたい支払いリクエストファイルを選択してください - OptionsDialog @@ -991,6 +637,14 @@ &Main メイン (&M) + + Automatically start %1 after logging in to the system. + システムにログインした際、自動的に %1 を起動する。 + + + &Start %1 on system login + システムにログインした時に %1 を起動 (&S) + Size of &database cache データベースキャッシュのサイズ (&D) @@ -1019,10 +673,6 @@ 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. ウィンドウを閉じる際にアプリケーションを終了するのではなく、最小化します。このオプションが有効化された場合、メニューから終了を選択した場合にのみアプリケーションは閉じられます。 - - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - ユーザ・インタフェイス言語はここで設定できます。この設定はBitcoin Coreの再起動後に有効となります。 - 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 |. トランザクションタブのコンテキストメニュー項目に表示する、サードパーティURL (例えばブロックエクスプローラ)。URL中の%sはトランザクションのハッシュ値に置き換えられます。垂直バー | で区切ることで、複数のURLを指定できます。 @@ -1047,14 +697,6 @@ &Network ネットワーク (&N) - - Automatically start Bitcoin Core after logging in to the system. - システムにログインした際、自動的にBitcoin Coreを起動する。 - - - &Start Bitcoin Core on system login - システムへログインした際にBitcoin Coreを起動する (&S) - (0 = auto, <0 = leave that many cores free) (0 = 自動、0以上 = 指定した数のコアをフリーにする) @@ -1139,6 +781,14 @@ &Window ウインドウ (&W) + + &Hide the icon from the system tray. + システムトレイのアイコンを隠す (&H) + + + Hide tray icon + トレイアイコンを隠す + Show only a tray icon after minimizing the window. ウインドウを最小化したあとトレイ アイコンだけを表示する。 @@ -1159,6 +809,10 @@ User Interface &language: ユーザインターフェースの言語 (&l) : + + The user interface language can be set here. This setting will take effect after restarting %1. + ここでユーザインターフェースの言語を設定できます。設定を反映するには %1 を再起動します。 + &Unit to show amounts in: 額を表示する単位 (&U) : @@ -1284,140 +938,49 @@ - PaymentServer + PeerTableModel - URI handling - URI の操作 + User Agent + ユーザエージェント - Invalid payment address %1 - 支払いのアドレス「%1」は無効です + Node/Service + ノード・サービス - Payment request rejected - 支払い要求は拒否されました + Ping Time + Ping時間 + + + QObject - Payment request network doesn't match client network. - 支払いリクエストのネットワークは現在のクライアントのネットワークに一致しません。 + Amount + 総額 - Payment request is not initialized. - 支払いリクエストは開始されていません。 + Enter a Bitcoin address (e.g. %1) + Bitcoinアドレスを入力してください (例 %1) - Requested payment amount of %1 is too small (considered dust). - 要求された支払額 %1 は少なすぎます (ダストとみなされてしまいます)。 + %1 d + %1日 - Payment request error - 支払いのリクエストのエラーです + %1 h + %1 h - Cannot start bitcoin: click-to-pay handler - Bitcoin を起動できません: click-to-pay handler + %1 m + %1 m - Payment request fetch URL is invalid: %1 - 支払い要求の取得先URLが無効です: %1 + %1 s + %1秒 - URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - URI を解析できません! これは無効な Bitcoin アドレスあるいや不正な形式の URI パラメーターによって引き起こされる場合があります。 - - - Payment request file handling - 支払いリクエストファイルを処理しています - - - Payment request file cannot be read! This can be caused by an invalid payment request file. - 支払いリクエストファイルを読み込めませんでした!無効な支払いリクエストファイルにより引き起こされた可能性があります。 - - - Payment request expired. - 支払いリクエストの期限が切れました。 - - - Unverified payment requests to custom payment scripts are unsupported. - カスタム支払いスクリプトに対する、検証されていない支払いリクエストはサポートされていません。 - - - Invalid payment request. - 無効な支払いリクエスト。 - - - Refund from %1 - %1 からの返金 - - - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - 支払リクエスト %1 は大きすぎます(%2バイトですが、%3バイトまでが許されています)。 - - - Error communicating with %1: %2 - %1: %2とコミュニケーション・エラーです - - - Payment request cannot be parsed! - 支払リクエストを読み込めませんでした! - - - Bad response from server %1 - サーバーの返事は無効 %1 - - - Payment acknowledged - 支払いは確認しました - - - Network request error - ネットワーク・リクエストのエラーです - - - - PeerTableModel - - User Agent - ユーザエージェント - - - Node/Service - ノード・サービス - - - Ping Time - Ping時間 - - - - QObject - - Amount - 総額 - - - Enter a Bitcoin address (e.g. %1) - Bitcoinアドレスを入力してください (例 %1) - - - %1 d - %1日 - - - %1 h - %1 h - - - %1 m - %1 m - - - %1 s - %1秒 - - - None - なし + None + なし N/A @@ -1428,25 +991,6 @@ %1ミリ秒 - - QRImageWidget - - &Save Image... - 画像を保存(&S) - - - &Copy Image - 画像をコピー(&C) - - - Save QR Code - QR コードの保存 - - - PNG Image (*.png) - PNG画像ファイル(*.png) - - RPCConsole @@ -1477,6 +1021,10 @@ Using BerkeleyDB version 使用中のBerkleyDBバージョン + + Datadir + データディレクトリ + Startup time 起動した日時 @@ -1513,10 +1061,6 @@ Memory usage メモリ使用量 - - Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. - 現在のデータディレクトリからBitcoin Coreのデバッグ用ログファイルを開きます。ログファイルが巨大な場合、数秒かかることがあります。 - Received 受取 @@ -1565,6 +1109,18 @@ User Agent ユーザエージェント + + Open the %1 debug log file from the current data directory. This can take a few seconds for large log files. + 現在のデータディレクトリから %1 のデバッグ用ログファイルを開きます。ログファイルが巨大な場合、数秒かかることがあります。 + + + Decrease font size + 文字サイズを縮小 + + + Increase font size + 文字サイズを拡大 + Services サービス @@ -1633,10 +1189,6 @@ Out: 出力: - - Build date - ビルドの日付 - Debug log file デバッグ用ログファイル @@ -1674,8 +1226,8 @@ ノードのbanを解除する (&U) - Welcome to the Bitcoin Core RPC console. - Bitcoin CoreのRPCコンソールへようこそ。 + Welcome to the %1 RPC console. + %1 のRPCコンソールへようこそ。 Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. @@ -1804,18 +1356,6 @@ Remove 削除 - - Copy label - ラベルをコピーする - - - Copy message - メッセージをコピーする - - - Copy amount - 総額のコピー - ReceiveRequestDialog @@ -1835,73 +1375,6 @@ &Save Image... 画像を保存(&S) - - Request payment to %1 - %1 への支払いリクエストを行う - - - Payment information - 支払い情報 - - - URI - URI - - - Address - アドレス - - - Amount - 総額 - - - Label - ラベル - - - Message - メッセージ - - - Resulting URI too long, try to reduce the text for label / message. - URI が長くなり過ぎます。ラベルやメッセージのテキストを短くしてください。 - - - Error encoding URI into QR Code. - QR コード用の URI エンコードでエラー。 - - - - RecentRequestsTableModel - - Date - 日付 - - - Label - ラベル - - - Message - メッセージ - - - Amount - 総額 - - - (no label) - (ラベル無し) - - - (no message) - (メッセージなし) - - - (no amount) - (金額なし) - SendCoinsDialog @@ -2021,14 +1494,6 @@ fast 高速 - - Send as zero-fee transaction if possible - 可能な場合には手数料ゼロのトランザクションとして送金する - - - (confirmation may take longer) - (検証に長い時間がかかる可能性があります) - Send to multiple recipients at once 一度に複数の人に送る @@ -2061,118 +1526,6 @@ S&end 送金 (&E) - - Confirm send coins - コインを送る確認 - - - %1 to %2 - %1 から %2 - - - Copy quantity - 数量をコピーする - - - Copy amount - 総額のコピー - - - Copy fee - 手数料をコピーする - - - Copy after fee - 手数料差引後の値をコピーする - - - Copy bytes - バイト数をコピーする - - - Copy priority - 優先度をコピーする - - - Copy change - 釣り銭をコピー - - - Total Amount %1 - 合計: %1 - - - or - または - - - The amount to pay must be larger than 0. - 支払額は0より大きくないといけません。 - - - The amount exceeds your balance. - 額が残高を超えています。 - - - The total exceeds your balance when the %1 transaction fee is included. - %1 の取引手数料を含めると額が残高を超えています。 - - - Transaction creation failed! - トラザクションの作成に失敗しました! - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - トランザクションは拒否されました。wallet.dat のコピーを使い、そしてコピーしたウォレットからコインを使用したことがマークされなかったときなど、ウォレットのいくつかのコインがすでに使用されている場合に、このエラーは起こるかもしれません。 - - - A fee higher than %1 is considered an absurdly high fee. - %1 よりも高い手数料の場合、手数料が高すぎると判断されます。 - - - Payment request expired. - 支払いリクエストの期限が切れました。 - - - Pay only the required fee of %1 - 要求手数料 %1 のみを支払う - - - Estimated to begin confirmation within %n block(s). - %n ブロック以内に検証が開始されると予想されます。 - - - The recipient address is not valid. Please recheck. - 受取アドレスが不正です。再チェックしてください。 - - - Duplicate address found: addresses should only be used once each. - 重複したアドレスが見つかりました: アドレスはそれぞれ一度のみ使用することができます。 - - - Warning: Invalid Bitcoin address - 警告:無効なBitcoinアドレスです - - - (no label) - (ラベル無し) - - - Warning: Unknown change address - 警告:未知のおつりアドレスです - - - Copy dust - ダストをコピーする - - - Are you sure you want to send? - 送ってよろしいですか? - - - added as transaction fee - 取引手数料として追加された - SendCoinsEntry @@ -2184,10 +1537,6 @@ Pay &To: 送り先(&T): - - Enter a label for this address to add it to your address book - アドレス帳に追加するには、このアドレスのラベルを入力します - &Label: ラベル(&L): @@ -2198,707 +1547,189 @@ This is a normal payment. - これは通常の支払です。 - - - The Bitcoin address to send the payment to - 支払の送金先Bitcoinアドレス - - - Alt+A - Alt+A - - - Paste address from clipboard - クリップボードからアドレスを貼付ける - - - Alt+P - Alt+P - - - Remove this entry - この項目を削除する - - - 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. - 送金する金額から手数料が差し引かれます。受取人は数量フィールドで指定した量よりも少ないビットコインを受け取ります。受取人が複数いる場合には、手数料は均等割されます。 - - - S&ubtract fee from amount - 送金額から手数料を差し引く (&U) - - - Message: - メッセージ: - - - This is an unauthenticated payment request. - これは未認証の支払いリクエストです。 - - - This is an authenticated payment request. - これは認証済みの支払いリクエストです。 - - - Enter a label for this address to add it to the list of used addresses - このアドレスに対するラベルを入力することで、使用済みアドレスの一覧に追加することができます - - - 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. - bitcoin: URIに添付されていたメッセージです。これは参照用としてトランザクションとともに保存されます。注意:このメッセージはBitcoinネットワークを通して送信されるわけではありません。 - - - Pay To: - 支払先: - - - Memo: - メモ: - - - - ShutdownWindow - - Bitcoin Core is shutting down... - Bitcoin Coreをシャットダウンしています。 - - - Do not shut down the computer until this window disappears. - このウィンドウが消えるまでコンピュータをシャットダウンしないで下さい。 - - - - SignVerifyMessageDialog - - Signatures - Sign / Verify a Message - 署名 - メッセージの署名/検証 - - - &Sign Message - メッセージの署名 (&S) - - - 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. - あなたの所有しているアドレスによりメッセージや合意書に署名をすることで、それらアドレスに対して送られたビットコインを受け取ることができることを証明できます。フィッシング攻撃により不正にあなたの識別情報を署名させられてしまうことを防ぐために、不明確なものやランダムなものに対して署名しないよう注意してください。合意することが可能な、よく詳細の記された文言にのみ署名するようにしてください。 - - - The Bitcoin address to sign the message with - メッセージを署名するBitcoinアドレス - - - Choose previously used address - 前に使用したアドレスを選ぶ - - - Alt+A - Alt+A - - - Paste address from clipboard - クリップボードからアドレスを貼付ける - - - Alt+P - Alt+P - - - Enter the message you want to sign here - ここにあなたが署名するメッセージを入力します - - - Signature - 署名 - - - Copy the current signature to the system clipboard - 現在の署名をシステムのクリップボードにコピーする - - - Sign the message to prove you own this Bitcoin address - この Bitcoin アドレスを所有していることを証明するためにメッセージに署名 - - - Sign &Message - メッセージの署名 (&M) - - - Reset all sign message fields - 入力項目の内容をすべて消去します - - - Clear &All - すべてクリア (&A) - - - &Verify Message - メッセージの検証 (&V) - - - 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! - 受取人のアドレスとメッセージ(改行やスペース、タブなども完全に一致するよう注意してください)および署名を以下に入力し、メッセージの署名を検証してください。中間者攻撃により騙されるのを防ぐため、署名対象のメッセージに書かれていること以上の意味を署名から読み取ろうとしないよう注意してください。これは署名作成者がこのアドレスで受け取ったことを証明するだけであり、トランザクションの送信権限を証明するものではないことに注意してください! - - - The Bitcoin address the message was signed with - メッセージの署名に使われたBitcoinアドレス - - - Verify the message to ensure it was signed with the specified Bitcoin address - 指定された Bitcoin アドレスで署名されたことを保証するメッセージを検証 - - - Verify &Message - メッセージの検証 (&M) - - - Reset all verify message fields - 入力項目の内容をすべて消去します - - - Click "Sign Message" to generate signature - 署名を作成するには"メッセージの署名"をクリック - - - The entered address is invalid. - 不正なアドレスが入力されました。 - - - Please check the address and try again. - アドレスを確かめてからもう一度試してください。 - - - The entered address does not refer to a key. - 入力されたアドレスに関連するキーがありません。 - - - Wallet unlock was cancelled. - ウォレットのアンロックはキャンセルされました。 - - - Private key for the entered address is not available. - 入力されたアドレスのプライベート キーが無効です。 - - - Message signing failed. - メッセージの署名に失敗しました。 - - - Message signed. - メッセージに署名しました。 - - - The signature could not be decoded. - 署名がデコードできません。 - - - Please check the signature and try again. - 署名を確認してからもう一度試してください。 - - - The signature did not match the message digest. - 署名はメッセージ ダイジェストと一致しませんでした。 - - - Message verification failed. - メッセージの検証に失敗しました。 - - - Message verified. - メッセージは検証されました。 - - - - SplashScreen - - Bitcoin Core - Bitcoin のコア - - - The Bitcoin Core developers - ビットコインコアの開発者 - - - [testnet] - [testnet] - - - - TrafficGraphWidget - - KB/s - KB/s - - - - TransactionDesc - - Open until %1 - ユニット %1 を開く - - - conflicted - 衝突 - - - %1/offline - %1/オフライン - - - %1/unconfirmed - %1/未検証 - - - %1 confirmations - %1 確認 - - - Status - ステータス - - - , broadcast through %n node(s) - %n ノードにブロードキャスト - - - Date - 日付 - - - Source - ソース - - - Generated - 生成された - - - From - 送信 - - - To - 受信 - - - own address - 自分のアドレス - - - watch-only - 監視限定 - - - label - ラベル - - - Credit - クレジット - - - matures in %n more block(s) - %n 以上のブロックが満期 - - - not accepted - 承認されなかった - - - Debit - 引き落とし額 - - - Total debit - 総出金額 - - - Total credit - 総入金額 - - - Transaction fee - 取引手数料 - - - Net amount - 正味金額 - - - Message - メッセージ - - - Comment - コメント - - - Transaction ID - 取引 ID - - - Merchant - 商人 - - - 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. - 生成されたコインは使う前に%1のブロックを完成させる必要があります。あなたが生成した時、このブロックはブロック チェーンに追加されるネットワークにブロードキャストされました。チェーンに追加されるのが失敗した場合、状態が"不承認"に変更されて使えなくなるでしょう。これは、別のノードがあなたの数秒前にブロックを生成する場合に時々起こるかもしれません。 - - - Debug information - デバッグ情報 - - - Transaction - 取引 - - - Inputs - 入力 - - - Amount - 総額 - - - true - 正しい - - - false - 正しくない - - - , has not been successfully broadcast yet - まだブロードキャストが成功していません - - - Open for %n more block(s) - %n 以上のブロックを開く - - - unknown - 未確認 - - - - TransactionDescDialog - - Transaction details - 取引の詳細 - - - This pane shows a detailed description of the transaction - ここでは取引の詳細を表示しています - - - - TransactionTableModel - - Date - 日付 - - - Type - タイプ - - - Immature (%1 confirmations, will be available after %2) - 未成熟(%1検証。%2検証完了後に使用可能となります) - - - Open for %n more block(s) - %n 以上のブロックを開く - - - Open until %1 - ユニット %1 を開く - - - Confirmed (%1 confirmations) - 検証されました (%1 検証済み) - - - This block was not received by any other nodes and will probably not be accepted! - このブロックは他のどのノードによっても受け取られないで、多分受け入れられないでしょう! - - - Generated but not accepted - 生成されましたが承認されませんでした - - - Offline - オフライン - - - Label - ラベル - - - Unconfirmed - 未検証 - - - Confirming (%1 of %2 recommended confirmations) - 検証中(%2の推奨検証数のうち、%1検証が完了) - - - Conflicted - 衝突 - - - Received with - 受け取り - - - Received from - 送り主 - - - Sent to - 送り先 - - - Payment to yourself - 自分自身への支払い - - - Mined - 発掘した - - - watch-only - 監視限定 - - - (n/a) - (n/a) - - - Transaction status. Hover over this field to show number of confirmations. - 取引の状況。このフィールドの上にカーソルを置くと検証の数を表示します。 - - - Date and time that the transaction was received. - 取引を受信した日時。 - - - Type of transaction. - 取引の種類。 - - - Whether or not a watch-only address is involved in this transaction. - 監視限定アドレスがこのトランザクションに含まれているかどうか - - - User-defined intent/purpose of the transaction. - ユーザ定義のトランザクションの意図や目的。 + これは通常の支払です。 - Amount removed from or added to balance. - 残高に追加または削除された総額。 + The Bitcoin address to send the payment to + 支払の送金先Bitcoinアドレス - - - TransactionView - All - すべて + Alt+A + Alt+A - Today - 今日 + Paste address from clipboard + クリップボードからアドレスを貼付ける - This week - 今週 + Alt+P + Alt+P - This month - 今月 + Remove this entry + この項目を削除する - Last month - 先月 + 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. + 送金する金額から手数料が差し引かれます。受取人は数量フィールドで指定した量よりも少ないビットコインを受け取ります。受取人が複数いる場合には、手数料は均等割されます。 - This year - 今年 + S&ubtract fee from amount + 送金額から手数料を差し引く (&U) - Range... - 期間... + Message: + メッセージ: - Received with - 送り主 + This is an unauthenticated payment request. + これは未認証の支払いリクエストです。 - Sent to - 送り先 + This is an authenticated payment request. + これは認証済みの支払いリクエストです。 - To yourself - 自分自身 + Enter a label for this address to add it to the list of used addresses + このアドレスに対するラベルを入力することで、使用済みアドレスの一覧に追加することができます - Mined - 発掘した + 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. + bitcoin: URIに添付されていたメッセージです。これは参照用としてトランザクションとともに保存されます。注意:このメッセージはBitcoinネットワークを通して送信されるわけではありません。 - Other - その他 + Pay To: + 支払先: - Enter address or label to search - 検索するアドレスまたはラベルを入力 + Memo: + メモ: + + + ShutdownWindow - Min amount - 最小の額 + %1 is shutting down... + %1 をシャットダウンしています... - Copy address - アドレスをコピーする + Do not shut down the computer until this window disappears. + このウィンドウが消えるまでコンピュータをシャットダウンしないで下さい。 + + + SignVerifyMessageDialog - Copy label - ラベルをコピーする + Signatures - Sign / Verify a Message + 署名 - メッセージの署名/検証 - Copy amount - 総額のコピー + &Sign Message + メッセージの署名 (&S) - Copy transaction ID - 取引 ID をコピー + 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. + あなたの所有しているアドレスによりメッセージや合意書に署名をすることで、それらアドレスに対して送られたビットコインを受け取ることができることを証明できます。フィッシング攻撃により不正にあなたの識別情報を署名させられてしまうことを防ぐために、不明確なものやランダムなものに対して署名しないよう注意してください。合意することが可能な、よく詳細の記された文言にのみ署名するようにしてください。 - Copy raw transaction - 生トランザクションをコピー + The Bitcoin address to sign the message with + メッセージを署名するBitcoinアドレス - Edit label - ラベルの編集 + Choose previously used address + 前に使用したアドレスを選ぶ - Show transaction details - 取引の詳細を表示 + Alt+A + Alt+A - Export Transaction History - トランザクション履歴をエクスポートする + Paste address from clipboard + クリップボードからアドレスを貼付ける - Watch-only - 監視限定 + Alt+P + Alt+P - Exporting Failed - エクスポートに失敗しました + Enter the message you want to sign here + ここにあなたが署名するメッセージを入力します - There was an error trying to save the transaction history to %1. - トランザクション履歴を %1 へ保存する際にエラーが発生しました。 + Signature + 署名 - Exporting Successful - エクスポートに成功しました + Copy the current signature to the system clipboard + 現在の署名をシステムのクリップボードにコピーする - The transaction history was successfully saved to %1. - トランザクション履歴は正常に%1に保存されました。 + Sign the message to prove you own this Bitcoin address + この Bitcoin アドレスを所有していることを証明するためにメッセージに署名 - Comma separated file (*.csv) - テキスト CSV (*.csv) + Sign &Message + メッセージの署名 (&M) - Confirmed - 検証済み + Reset all sign message fields + 入力項目の内容をすべて消去します - Date - 日付 + Clear &All + すべてクリア (&A) - Type - タイプ + &Verify Message + メッセージの検証 (&V) - Label - ラベル + 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! + 受取人のアドレスとメッセージ(改行やスペース、タブなども完全に一致するよう注意してください)および署名を以下に入力し、メッセージの署名を検証してください。中間者攻撃により騙されるのを防ぐため、署名対象のメッセージに書かれていること以上の意味を署名から読み取ろうとしないよう注意してください。これは署名作成者がこのアドレスで受け取ったことを証明するだけであり、トランザクションの送信権限を証明するものではないことに注意してください! - Address - Helbidea + The Bitcoin address the message was signed with + メッセージの署名に使われたBitcoinアドレス - ID - ID + Verify the message to ensure it was signed with the specified Bitcoin address + 指定された Bitcoin アドレスで署名されたことを保証するメッセージを検証 - Range: - 期間: + Verify &Message + メッセージの検証 (&M) - to - から + Reset all verify message fields + 入力項目の内容をすべて消去します - UnitDisplayStatusBarControl + SplashScreen - Unit to show amounts in. Click to select another unit. - 金額を表示する際の単位。クリックすることで他の単位を選択します。 + [testnet] + [testnet] - WalletFrame + TrafficGraphWidget - No wallet has been loaded. - ウォレットがロードされていません + KB/s + KB/s - WalletModel + TransactionDescDialog - Send Coins - コインを送る + This pane shows a detailed description of the transaction + ここでは取引の詳細を表示しています - WalletView - - &Export - エクスポート (&E) - - - Export the data in the current tab to a file - ファイルに現在のタブのデータをエクスポート - - - Backup Wallet - ウォレットのバックアップ - - - Wallet Data (*.dat) - ウォレット データ (*.dat) - - - Backup Failed - バックアップに失敗しました - - - There was an error trying to save the wallet data to %1. - ウォレットデータを%1へ保存する際にエラーが発生しました。 - - - The wallet data was successfully saved to %1. - ウォレット データは正常に%1に保存されました。 - + UnitDisplayStatusBarControl - Backup Successful - バックアップ成功 + Unit to show amounts in. Click to select another unit. + 金額を表示する際の単位。クリックすることで他の単位を選択します。 @@ -2927,14 +1758,6 @@ If <category> is not supplied or if <category> = 1, output all debugging information. <category> が与えられなかった場合や <category> = 1 の場合には、すべてのデバッグ情報が出力されます。 - - Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s) - ひとつのウォレットトランザクションで使用する合計手数料 (%s 単位) の最大値。低すぎる値を指定すると巨大なトランザクションの作成ができなくなります (規定値: %s) - - - Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. - あなたのPCの日付と時刻が正しいことを確認して下さい! もしあなたの時計が正しくなければBitcoin Coreが正確に動作しません。 - Prune configured below the minimum of %d MiB. Please use a higher number. 剪定が最小値の %d MiB以下に設定されています。もっと大きな値を使用してください。 @@ -2975,6 +1798,14 @@ Accept connections from outside (default: 1 if no -proxy or -connect) 外部からの接続を許可 (初期値: -proxy または -connect を使用していない場合は1) + + Bitcoin Core + Bitcoin のコア + + + The %s developers + %s の開発者 + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. -fallbackfee が高すぎます!これは手数料の推定機能が利用できない場合に支払うトランザクション手数料です。 @@ -2991,6 +1822,10 @@ Bind to given address and always listen on it. Use [host]:port notation for IPv6 指定のアドレスへバインドし、その上で常にリスンします。IPv6 は [ホスト名]:ポート番号 と表記します + + Cannot obtain a lock on data directory %s. %s is probably already running. + データ ディレクトリ %s のロックを取得することができません。おそらく %s は実行中です。 + Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup ウォレットの全トランザクションを削除し、これらを-rescanオプションを用いることで起動時にブロックチェインのデータのみからリカバリします。 @@ -2999,6 +1834,14 @@ Distributed under the MIT software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>. MITソフトウェアライセンスのもとで配布されています。付属のCOPYINGファイルまたは<http://www.opensource.org/licenses/mit-license.php>を参照してください。 + + Error loading %s: You can't enable HD on a already existing non-HD wallet + %s の読み込みエラー: 非HDウォレットが既に存在するため、HDウォレットを有効化できません + + + Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + %s の読み込みエラー! すべてのキーは正しく読み取れますが、取引データやアドレス帳のエントリが失われたか、正しくない可能性があります。 + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) ウォレットの取引を変更する際にコマンドを実行 (cmd の %s は TxID に置換される) @@ -3007,6 +1850,22 @@ Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) ホワイトリストのピアから受け取ったトランザクションに関しては、たとえローカルの中継ポリシーに違反しているとしても中継を行うようにする (デフォルト: %d) + + Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds) + 時間オフセット調整値のピア中央値に対する最大の許容値。ローカル時間の見込み値は、接続するピアにより前方ないし後方へ影響されます。(初期値: %u 秒) + + + Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s) + ひとつのウォレットトランザクションまたは生トランザクションで使用する合計手数料の最大値 (%s 単位)。低すぎる値を指定すると巨大なトランザクションの作成ができなくなります (規定値: %s) + + + Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly. + あなたのPCの日付と時刻が正しいことを確認して下さい! もしあなたの時計が正しくなければ %s が正確に動作しません。 + + + Please contribute if you find %s useful. Visit %s for further information about the software. + %s が有用だと感じられた方はぜひプロジェクトへの貢献をお願いします。ソフトウェアのより詳細な情報については %s をご覧ください。 + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) スクリプト検証スレッドを設定 (%uから%dの間, 0 = 自動, <0 = たくさんのコアを自由にしておく, 初期値: %d) @@ -3019,14 +1878,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications これはリリース前のテストビルドです - 各自の責任で利用すること - 採掘や商取引に使用しないでください - - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - このコンピュータの %s にバインドすることができません。おそらく Bitcoin Core は既に実行されています。 - - - Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. - サポートされていない引数 -whitelistalwaysrelay は無視されました。-whitelistrelay または -whitelistforcerelay を利用してください - Use UPnP to map the listening port (default: 1 when listening and no -proxy) リスン ポートの割当に UPnP を使用 (初期値: リスン中および-proxyが指定されていない場合は1) @@ -3043,22 +1894,22 @@ Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. 警告: ネットワークは完全に同意しないみたいです。マイナーは何かの問題を経験してるみたいなんです。 - - Warning: Unknown block versions being mined! It's possible unknown rules are in effect - 警告: 未知のバージョンのブロックが採掘されました。未知のルールが導入された可能性があります - Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. 警告: ピアーと完全に同意しないみたいです!アップグレードは必要かもしれません、それとも他のノードはアップグレードは必要かもしれません。 - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - 警告: wallet.dat が壊れたのでデータを復旧しました! オリジナルの wallet.dat は wallet.{timestamp}.bak として %s に保存されました; もしもあなたの残高や取引が正しくないならバックアップから復元してください。 - Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. 与えられたネットマスクやIPアドレスから接続を行う、ホワイトリストのピア。複数回指定できます。 + + You need to rebuild the database using -reindex-chainstate to change -txindex + -txindex を変更するには -reindex-chainstate を使用してデータベースを再構築する必要があります + + + %s corrupt, salvage failed + %s が壊れています。復旧にも失敗しました + -maxmempool must be at least %d MB -maxmempoolは最低でも %d MB必要です @@ -3071,10 +1922,22 @@ Append comment to the user agent string ユーザエージェント文字列にコメントを + + Attempt to recover private keys from a corrupt wallet on startup + 起動時に壊れたウォレットから秘密鍵を復旧することを試す + Block creation options: ブロック作成オプション: + + Cannot resolve -%s address: '%s' + -%s アドレス '%s' を解決できません + + + Change index out of range + おつりのインデックスが範囲外です + Connect only to the specified node(s) 指定したノードだけに接続 @@ -3083,6 +1946,10 @@ Connection options: 接続オプション: + + Copyright (C) %i-%i + Copyright (C) %i-%i + Corrupted block database detected 破損したブロック データベースが見つかりました @@ -3128,6 +1995,22 @@ Error initializing wallet database environment %s! ウォレットのデータベース環境 %s 初期化エラー! + + Error loading %s + %s 読み込みエラー + + + Error loading %s: Wallet corrupted + %s 読み込みエラー: ウォレットが壊れました + + + Error loading %s: Wallet requires newer version of %s + %s の読み込みに失敗しました: ウォレットの読み込みにはより新しいバージョンの %s が必要です + + + Error loading %s: You can't disable HD on a already existing HD wallet + %s の読み込みエラー: HDウォレットが既に存在するため、HDウォレットを無効化できません + Error loading block database ブロック データベースの読み込みエラー @@ -3152,10 +2035,18 @@ Incorrect or no genesis block found. Wrong datadir for network? 不正なブロックあるいは、生成されていないブロックが見つかりました。ネットワークの datadir が間違っていませんか? + + Initialization sanity check failed. %s is shutting down. + 初期化時の健全性チェックに失敗しました。%s を終了します。 + Invalid -onion address: '%s' 無効な -onion アドレス:'%s' + + Invalid amount for -%s=<amount>: '%s' + -%s=<数量> に対する不正な額: '%s' + Invalid amount for -fallbackfee=<amount>: '%s' 不正な額 -fallbackfee=<amount>: '%s' @@ -3164,6 +2055,10 @@ Keep the transaction memory pool below <n> megabytes (default: %u) トランザクションのメモリ・プールの総量を <n> メガバイト以下に維持する (初期値: %u) + + Loading banlist... + banリストを読み込んでいます... + Location of the auth cookie (default: data dir) 認証クッキーの場所 (デフォルト: ) @@ -3180,6 +2075,10 @@ Only connect to nodes in network <net> (ipv4, ipv6 or onion) <net> (ipv4, ipv6 または onion) ネットワーク内のノードだけに接続する + + Print this help message and exit + このヘルプメッセージを表示し終了する + Print version and exit バージョンを表示し終了 @@ -3192,6 +2091,14 @@ Prune mode is incompatible with -txindex. 剪定モードは-txindexと互換性がありません。 + + Rebuild chain state and block index from the blk*.dat files on disk + チェイン状態およびブロックインデックスをディスク上の blk*.dat ファイルから再構築する + + + Rebuild chain state from the currently indexed blocks + 既にインデックスされたブロックからチェイン状態を再構築する + Set database cache size in megabytes (%d to %d, default: %d) データベースのキャッシュサイズをメガバイトで設定 (%dから%d。初期値: %d) @@ -3204,6 +2111,14 @@ Specify wallet file (within data directory) ウォレットのファイルを指定 (データ・ディレクトリの中に) + + The source code is available from %s. + ソースコードは %s より入手可能です。 + + + Unable to bind to %s on this computer. %s is probably already running. + このコンピュータの %s にバインドすることができません。おそらく %s は既に実行されています。 + Unsupported argument -benchmark ignored, use -debug=bench. サポートされていない引数 -benchmark は無視されました。-debug=bench を使用してください。 @@ -3237,12 +2152,16 @@ 財布 %s はデータ・ディレクトリ%sの外にあります - Wallet options: - ウォレットオプション: + Wallet debugging/testing options: + ウォレットのデバッグ・テスト用オプション: + + + Wallet needed to be rewritten: restart %s to complete + ウォレットが書き直される必要がありました: 完了するために %s を再起動します - You need to rebuild the database using -reindex to change -txindex - -txindex を変更するには -reindex を使用してデータベースを再構築する必要があります + Wallet options: + ウォレットオプション: 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 @@ -3256,10 +2175,6 @@ Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces) 指定されたアドレスに対して JSON-RPC 接続をリッスンしするようバインドします。IPv6の場合には [host]:port 表記を使用してください。このオプションは複数回指定することが可能です (初期値: すべてのインターフェースに対してバインドする) - - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - データ ディレクトリ %s のロックを取得することができません。おそらく Bitcoin Core は実行中です。 - Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) umask 077 ではなく、システムのデフォルトパーミッションで新規ファイルを作成する (ウォレット機能が無効化されていた場合にのみ有効) @@ -3304,10 +2219,6 @@ Set maximum size of high-priority/low-fee transactions in bytes (default: %d) 最優先/最低手数料の最大サイズをバイトで指定 (初期値: %d) - - Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) - コイン生成が有効になっていた場合の利用スレッド数を設定する (-1 = すべてのコア, 初期値: %d) - The transaction amount is too small to send after the fee has been deducted 手数料差引後のトランザクションの金額が小さすぎるため、送金できません。 @@ -3316,6 +2227,10 @@ This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard. この製品はOpenSSLプロジェクトにより開発されたソフトウェアをOpenSSLツールキットとして利用しています <https://www.openssl.org/>。また、Eric Young氏により開発された暗号ソフトウェア、Thomas Bernard氏により書かれたUPnPソフトウェアを用いています。 + + Use hierarchical deterministic key generation (HD) after BIP32. Only has effect during wallet creation/first start + BIP32 に従った階層的決定性鍵生成方式 (HD) を利用します。ウォレットの生成時ないし最初に起動した時にのみ有効です。 + 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 ホワイトリストのピアはDoSによるアクセス禁止処理が無効化され、トランザクションは例えmempool内に既に存在していたとしても常にリレーされます。これは例えばゲートウェイに対して有用です @@ -3332,34 +2247,14 @@ Accept public REST requests (default: %u) 公開 REST リクエストを許可する (初期値: %u) - - Activating best chain... - 最優良のチェインを有効化しています... - - - Attempt to recover private keys from a corrupt wallet.dat on startup - 起動時に壊れた wallet.dat から秘密鍵を復旧することを試す - Automatically create Tor hidden service (default: %d) Tor秘匿サービスを自動的に作成する (初期値: %d) - - Cannot resolve -whitebind address: '%s' - -whitebind アドレス '%s' を解決できません - Connect through SOCKS5 proxy SOCKS5 プロキシ経由で接続する - - Copyright (C) 2009-%i The Bitcoin Core Developers - Copyright (C) 2009-%i Bitcoin Core 開発者 - - - Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - wallet.dat の読み込みに失敗しました: ウォレットの読み込みにはより新しいバージョンの Bitcoin Core が必要です - Error reading from database, shutting down. データベースの読み込みエラー。シャットダウンします。 @@ -3372,22 +2267,6 @@ Information 情報 - - Initialization sanity check failed. Bitcoin Core is shutting down. - 初期化時の健全性チェックに失敗しました。Bitcoin Coreを終了します。 - - - Invalid amount for -maxtxfee=<amount>: '%s' - -maxtxfee=<amount> に対する無効な数量です: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - 不正な額 -minrelaytxfee=<amount>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - 不正な額 -minrelaytxfee=<amount>: '%s' - Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) -paytxfee=<amount> に対する無効な数量です: '%s' (少なくとも %s でなければいけません) @@ -3412,14 +2291,6 @@ RPC server options: RPCサーバのオプション: - - Rebuild block chain index from current blk000??.dat files on startup - 起動時に現在の blk000??.dat ファイルからブロック チェーンのインデックスを再構築 - - - Receive and display P2P network alerts (default: %u) - P2Pネットワークのアラートの受け取りと表示を行う (デフォルト: %u) - Reducing -maxconnections from %d to %d, because of system limitations. システム上の制約から、-maxconnections を %d から %d に削減しました。 @@ -3492,10 +2363,6 @@ Username for JSON-RPC connections JSON-RPC 接続のユーザー名 - - Wallet needed to be rewritten: restart Bitcoin Core to complete - ウォレットが書き直される必要がありました: 完了するために Bitcoin Core を再起動します - Warning 警告 @@ -3516,10 +2383,6 @@ ZeroMQ notification options: ZeroMQ通知オプション: - - wallet.dat corrupt, salvage failed - wallet.dat が壊れ、復旧に失敗しました - Password for JSON-RPC connections JSON-RPC 接続のパスワード @@ -3528,10 +2391,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) 最良のブロックに変更する際にコマンドを実行 (cmd の %s はブロック ハッシュに置換される) - - This help message - このヘルプ メッセージ - Allow DNS lookups for -addnode, -seednode and -connect -addnode, -seednode と -connect で DNS ルックアップを許可する @@ -3540,10 +2399,6 @@ Loading addresses... アドレスを読み込んでいます... - - Error loading wallet.dat: Wallet corrupted - wallet.dat 読み込みエラー: ウォレットが壊れました - (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) (1 = トランザクションのメタデータ、例えばアカウントの所有者や支払リクエストの内容を保持する, 2 = トランザクションのメタデータを破棄する) @@ -3560,10 +2415,6 @@ Do not keep transactions in the mempool longer than <n> hours (default: %u) mempool内でトランザクションを <n> 時間以上保持しない (初期値: %u) - - Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. - wallet.dat の読み込みエラー! すべてのキーは正しく読み取れますが、取引データやアドレス帳のエントリが失われたか、正しくない可能性があります。 - Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) トランザクション作成の際、この値未満の手数料 (%s/kB単位) はゼロであるとみなす (デフォルト: %s) @@ -3600,6 +2451,10 @@ Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported. サポートされていない引数 -socks が見つかりました。SOCKSバージョンの設定はできないようになりました。SOCKS5プロキシのみがサポートされています。 + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + サポートされていない引数 -whitelistalwaysrelay は無視されました。-whitelistrelay または -whitelistforcerelay を利用してください + Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s) Tor 秘匿サービスを通し、別々の SOCKS5 プロキシを用いることでピアに到達する (初期値: %s) @@ -3609,20 +2464,20 @@ JSON-RPC接続時のユーザ名とハッシュ化されたパスワード。<userpw> フィールドのフォーマットは <USERNAME>:<SALT>$<HASH>。標準的な Python スクリプトが share/rpcuser 内に含まれています。このオプションは複数回指定できます。 - (default: %s) - (デフォルト: %s) + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + 警告: 未知のバージョンのブロックが採掘されました。未知のルールが導入された可能性があります - Always query for peer addresses via DNS lookup (default: %u) - DNS ルックアップを通してピアアドレスを常に問い合わせる (初期値: %u) + Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup. + 警告: ウォレットファイルが破損していましたのでデータを復旧しました!元の %s は %s として %s に保存されました; 残高やトランザクションが正しくない場合にはバックアップから復元してください。 - Error loading wallet.dat - wallet.dat 読み込みエラー + (default: %s) + (デフォルト: %s) - Generate coins (default: %u) - コインを生成 (初期値: %u) + Always query for peer addresses via DNS lookup (default: %u) + DNS ルックアップを通してピアアドレスを常に問い合わせる (初期値: %u) How many blocks to check at startup (default: %u, 0 = all) @@ -3708,18 +2563,6 @@ Unknown network specified in -onlynet: '%s' -onlynet で指定された '%s' は未知のネットワークです - - Cannot resolve -bind address: '%s' - -bind のアドレス '%s' を解決できません - - - Cannot resolve -externalip address: '%s' - -externalip のアドレス '%s' を解決できません - - - Invalid amount for -paytxfee=<amount>: '%s' - -paytxfee=<amount> の額 '%s' が無効です - Insufficient funds 残高不足 @@ -3730,7 +2573,7 @@ Add a node to connect to and attempt to keep the connection open - 接続するノードを追加し接続を持続するように試します + 接続するノードを追加し接続を保持します Loading wallet... diff --git a/src/qt/locale/bitcoin_ka.ts b/src/qt/locale/bitcoin_ka.ts index 1a072d1df116b..22e7651f6344d 100644 --- a/src/qt/locale/bitcoin_ka.ts +++ b/src/qt/locale/bitcoin_ka.ts @@ -21,10 +21,6 @@ C&lose &დახურვა - - &Copy Address - &მისამართის კოპირება - Delete the currently selected address from the list მონიშნული მისამართის წაშლა სიიდან @@ -41,69 +37,6 @@ &Delete &წაშლა - - Choose the address to send coins to - აირჩიეთ მონეტების გაგზავნის მისამართი - - - Choose the address to receive coins with - აირჩიეთ მონეტების მიღების მისამართი - - - C&hoose - &არჩევა - - - Sending addresses - გაგზავნის მისამართი - - - Receiving addresses - მიღების მისამართი - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - ეს არის თქვენი Bitcoin-მისამართები გადახდების შესასრულებლად. მონეტების გაგზავნამდე ყოველთვის შეამოწმეთ თანხა და მიმღების მისამართი. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - ეს არის თქვენი Bitcoin-მისამართები გადახდების მისაღებად. რეკომენდებულია ყოველი ტრანსაქციისათვის ახალი მიღების მისამართის გამოყენება. - - - Copy &Label - ნიშნუ&ლის კოპირება - - - &Edit - რ&ედაქტირება - - - Export Address List - მისამართების სიის ექსპორტი - - - Comma separated file (*.csv) - CSV-ფაილი (*.csv) - - - Exporting Failed - ექსპორტი ვერ განხორციელდა - - - - AddressTableModel - - Label - ნიშნული - - - Address - მისამართი - - - (no label) - (არ არის ნიშნული) - AskPassphraseDialog @@ -123,82 +56,6 @@ Repeat new passphrase გაიმეორეთ ახალი ფრაზა-პაროლი - - Encrypt wallet - საფულის დაშიფრვა - - - This operation needs your wallet passphrase to unlock the wallet. - ეს ოპერაცია მოითხოვს თქვენი საფულის ფრაზა-პაროლს საფულის განსაბლოკად. - - - Unlock wallet - საფულის განბლოკვა - - - This operation needs your wallet passphrase to decrypt the wallet. - ეს ოპერაცია მოითხოვს თქვენი საფულის ფრაზა-პაროლს საფულის გასაშიფრად. - - - Decrypt wallet - საფულის გაშიფრვა - - - Change passphrase - ფრაზა-პაროლის შეცვლა - - - Confirm wallet encryption - დაადასტურეთ საფულის დაშიფრვა - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - ყურადღება: საფულის დაშიფრვის შემდეგ თუ თქვენ დაკარგავთ ფრაზა-პაროლს, <b>ყველა ბიტქოინი დაგეკარგებათ</b>! - - - Are you sure you wish to encrypt your wallet? - დარწმუნებული ხართ, რომ გინდათ საფულის დაშიფრვა? - - - 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. - მნიშვნელოვანია: თქვენი საფულის ყველა ადრინდელი არქივი შეიცვლება ახლადგენერირებული დაშიფრული საფულის ფაილით. უსაფრთხოების მოსაზრებებით დაუშიფრავი საფულის ძველი არქივები ძალას დაკარგავს, როგორც კი დაიწყებთ ახალი, დაშიფრული საფულის გამოყენებას. - - - Warning: The Caps Lock key is on! - ყურადღება: ჩართულია Caps Lock რეჟიმი! - - - Wallet encrypted - საფულე დაშიფრულია - - - Wallet encryption failed - ვერ მოხერხდა საფულის დაშიფრვა - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - საფულის დაშიფრვა ვერ მოხერხდა სისტემაში შეცდომის გამო. თქვენი საფულე არ არის დაშფრული. - - - The supplied passphrases do not match. - ფრაზა-პაროლები არ ემთხვევა ერთმანეთს. - - - Wallet unlock failed - საფულის განბლოკვა ვერ მოხერხდა - - - The passphrase entered for the wallet decryption was incorrect. - საფულის განშიფრვის ფრაზა-პაროლი არაწორია - - - Wallet decryption failed - საფულის განშიფრვა ვერ მოხერხდა - - - Wallet passphrase was successfully changed. - საფულის ფრაზა-პაროლი შეცვლილია. - BanTableModel @@ -277,10 +134,6 @@ Open &URI... &URI-ის გახსნა... - - Importing blocks from disk... - ბლოკების იმპორტი დისკიდან... - Reindexing blocks on disk... დისკზე ბლოკების რეინდექსაცია... @@ -361,18 +214,10 @@ Tabs toolbar ბარათების პანელი - - Bitcoin Core - Bitcoin Core - Request payments (generates QR codes and bitcoin: URIs) გადახდის მოთხოვნა (შეიქმნება QR-კოდები და bitcoin: ბმულები) - - &About Bitcoin Core - Bitcoin Core-ს შეს&ახებ - Show the list of used sending addresses and labels გამოყენებული გაგზავნის მისამართებისა და ნიშნულების სიის ჩვენება @@ -389,10 +234,6 @@ &Command-line options საკომანდო სტრიქონის ოპ&ციები - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Bitcoin Core-ს დახმარების ჩვენება Bitcoin-ის საკომანდო სტრიქონის დასაშვები ოპციების სანახავად - No block source available... ბლოკების წყარო მიუწვდომელია... @@ -450,13 +291,6 @@ საფულე <b>დაშიფრულია</b> და ამჟამად <b>დაბლოკილია</b> - - ClientModel - - Network Alert - ქსელური განგაში - - CoinControlDialog @@ -519,130 +353,6 @@ Priority პრიორიტეტი - - Copy address - მისამართის კოპირება - - - Copy label - ნიშნულის კოპირება - - - Copy amount - თანხის კოპირება - - - Copy transaction ID - ტრანსაქციის ID-ს კოპირება - - - Lock unspent - დაუხარჯავის დაბლოკვა - - - Unlock unspent - დაუხარჯავის განბლოკვა - - - Copy quantity - რაოდენობის კოპირება - - - Copy fee - საკომისიოს კოპირება - - - Copy after fee - დამატებითი საკომისიოს კოპირება - - - Copy bytes - ბაიტების კოპირება - - - Copy priority - პრიორიტეტის კოპირება - - - Copy change - ხურდის კოპირება - - - highest - უმაღლესი - - - higher - უფრო მაღალი - - - high - მაღალი - - - medium-high - საშუალოზე მაღალი - - - medium - საშუალო - - - low-medium - საშუალოზე დაბალი - - - low - დაბალი - - - lower - უფრო დაბალი - - - lowest - უდაბლესი - - - (%1 locked) - (%1 დაბლოკილია) - - - none - ცარიელი - - - yes - კი - - - no - არა - - - This means a fee of at least %1 per kB is required. - ეს ნიშნავს, რომ კილობაიტზე საკომისიო იქნება მინიმუმ %1 - - - Can vary +/- 1 byte per input. - შეიძლება იყოს +/- 1 ბაიტი ყოველ შესავალზე. - - - Transactions with higher priority are more likely to get included into a block. - მეტი პრიორიტეტის ტრანსაქციებს მეტი შანსი აქვს მოხვდეს ბლოკში. - - - (no label) - (არ არის ნიშნული) - - - change from %1 (%2) - ხურდა %1-დან (%2) - - - (change) - (ხურდა) - EditAddressDialog @@ -666,38 +376,6 @@ &Address მის&ამართი - - New receiving address - ახალი მიღების მისამართი - - - New sending address - ახალი გაგზავნის მისამართი - - - Edit receiving address - მიღების მისამართის შეცვლა - - - Edit sending address - გაგზავნის მისამართის შეცვლა - - - The entered address "%1" is already in the address book. - მისამართი "%1" უკვე არის მისამართების წიგნში. - - - The entered address "%1" is not a valid Bitcoin address. - შეყვანილი მისამართი "%1" არ არის ვალიდური Bitcoin-მისამართი. - - - Could not unlock wallet. - საფულის განბლოკვა ვერ მოხერხდა. - - - New key generation failed. - ახალი გასაღების გენერირება ვერ მოხერხდა - FreespaceChecker @@ -724,18 +402,10 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin Core - version ვერსია - - About Bitcoin Core - Bitcoin Core-ს შესახებ - Command-line options კომანდების ზოლის ოპციები @@ -755,18 +425,6 @@ Welcome მოგესალმებით - - Welcome to Bitcoin Core. - მოგესალმებათ Bitcoin Core. - - - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - ეს პროგრამის პირველი გაშვებაა; შეგიძლიათ მიუთითოთ, სად შეინახოს მონაცემები Bitcoin Core-მ. - - - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - Bitcoin Core გადმოტვირთავს და შეინახავს Bitcoin-ის ბლოკთა ჯაჭვს. მითითებულ კატალოგში დაგროვდება სულ ცოტა %1 გბ მონაცემები, და მომავალში უფრო გაიზრდება. საფულეც ამავე კატალოგში შეინახება. - Use the default data directory ნაგულისხმევი კატალოგის გამოყენება @@ -775,10 +433,6 @@ Use a custom data directory: მითითებული კატალოგის გამოყენება: - - Bitcoin Core - Bitcoin Core - Error შეცდომა @@ -802,10 +456,6 @@ Select payment request file გადახდის მოთხოვნის ფაილის არჩევა - - Select payment request file to open - გადახდის მოთხოვნის ფაილის არჩევა გასახსნელად - OptionsDialog @@ -989,61 +639,6 @@ თქვენი სრული მიმდინარე ბალანსი - - PaymentServer - - URI handling - URI-ების დამუშავება - - - Invalid payment address %1 - გადახდის მისამართი არასწორია: %1 - - - Requested payment amount of %1 is too small (considered dust). - მოთხოვნილი გადახდის %1 მოცულობა ძალიან მცირეა (ითვლება "მტვრად") - - - Payment request error - გადახდის მოთხოვნის შეცდომა - - - Cannot start bitcoin: click-to-pay handler - ვერ გაიშვა bitcoin: click-to-pay - - - Payment request fetch URL is invalid: %1 - არასწორია გადახდის მოთხოვნის URL: %1 - - - Payment request file handling - გადახდის მოთხოვნის ფაილის დამუშავება - - - Unverified payment requests to custom payment scripts are unsupported. - არავერიფიცირებული გადახდის მოთხოვნები გადახდის სამომხმარებლო სკრიპტებისათვის არ არის მხარდაჭერილი. - - - Refund from %1 - დაბრუნება %1-საგან - - - Error communicating with %1: %2 - ვერ გამოდის კავშირზე %1: %2 - - - Bad response from server %1 - ცუდი პასუხი სერვერისაგან %1 - - - Payment acknowledged - გადახდა მიღებულია - - - Network request error - ქსელური მოთხოვნის შეცდომა - - PeerTableModel @@ -1066,25 +661,6 @@ მიუწვდ. - - QRImageWidget - - &Save Image... - გამო&სახულების შენახვა... - - - &Copy Image - გამოსახულების &კოპირება - - - Save QR Code - QR-კოდის შენახვა - - - PNG Image (*.png) - PNG სურათი (*.png) - - RPCConsole @@ -1167,10 +743,6 @@ Out: გამავალი: - - Build date - შექმნის დრო - Debug log file დახვეწის ლოგ-ფაილი @@ -1274,18 +846,6 @@ Remove წაშლა - - Copy label - ნიშნულის კოპირება - - - Copy message - მესიჯის კოპირება - - - Copy amount - თანხის კოპირება - ReceiveRequestDialog @@ -1305,111 +865,44 @@ &Save Image... გამო&სახულების შენახვა... + + + SendCoinsDialog - Request payment to %1 - %1-ის გადაზდის მოთხოვნა + Send Coins + მონეტების გაგზავნა - Payment information - ინფორმაცია გადახდის შესახებ + Coin Control Features + მონეტების კონტროლის პარამეტრები - URI - URI + Inputs... + ხარჯები... - Address - მისამართი + automatically selected + არჩეულია ავტომატურად - Amount - თანხა + Insufficient funds! + არ არის საკმარისი თანხა! - Label - ნიშნული + Quantity: + რაოდენობა: - Message - მესიჯი + Bytes: + ბაიტები: - Resulting URI too long, try to reduce the text for label / message. - URI ძალიან გრძელი გამოდის, შეამოკლეთ ნიშნულის/მესიჯის ტექსტი. + Amount: + თანხა: - Error encoding URI into QR Code. - შედომა URI-ის QR-კოდში გადაყვანისას. - - - - RecentRequestsTableModel - - Date - თარიღი - - - Label - ნიშნული - - - Message - მესიჯი - - - Amount - თანხა - - - (no label) - (არ არის ნიშნული) - - - (no message) - (მესიჯები არ არის) - - - (no amount) - (თანხა არ არის) - - - - SendCoinsDialog - - Send Coins - მონეტების გაგზავნა - - - Coin Control Features - მონეტების კონტროლის პარამეტრები - - - Inputs... - ხარჯები... - - - automatically selected - არჩეულია ავტომატურად - - - Insufficient funds! - არ არის საკმარისი თანხა! - - - Quantity: - რაოდენობა: - - - Bytes: - ბაიტები: - - - Amount: - თანხა: - - - Priority: - პრიორიტეტი: + Priority: + პრიორიტეტი: Fee: @@ -1463,86 +956,6 @@ S&end გაგ&ზავნა - - Confirm send coins - მონეტების გაგზავნის დადასტურება - - - %1 to %2 - %1-დან %2-ში - - - Copy quantity - რაოდენობის კოპირება - - - Copy amount - თანხის კოპირება - - - Copy fee - საკომისიოს კოპირება - - - Copy after fee - დამატებითი საკომისიოს კოპირება - - - Copy bytes - ბაიტების კოპირება - - - Copy priority - პრიორიტეტის კოპირება - - - Copy change - ხურდის კოპირება - - - or - ან - - - The amount to pay must be larger than 0. - გადახდის მოცულობა 0-ზე მეტი უნდა იყოს - - - The amount exceeds your balance. - თანხა აღემატება თქვენს ბალანსს - - - The total exceeds your balance when the %1 transaction fee is included. - საკომისიო %1-ის დამატების შემდეგ თანხა აჭარბებს თქვენს ბალანსს - - - Transaction creation failed! - შეცდომა ტრანსაქციის შექმნისას! - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - ტრანსაქცია უარყოფილია! შესაძლოა მონეტების ნაწილი თქვენი საფულიდან უკვე გამოყენებულია, რაც შეიძლება მოხდეს wallet.dat-ის ასლის გამოყენებისას, როცა მონეტები გაიგზავნა სხვა ასლიდან, აქ კი არ არის გაგზავნილად მონიშნული. - - - Warning: Invalid Bitcoin address - ყურადღება: არასწორია Bitcoin-მისამართი - - - (no label) - (არ არის ნიშნული) - - - Warning: Unknown change address - ყურადღება: უცნობია ხურდის მისამართი - - - Are you sure you want to send? - დარწმუნებული ხართ, რომ გინდათ გაგზავნა? - - - added as transaction fee - დამატებულია საკომისიო - SendCoinsEntry @@ -1554,10 +967,6 @@ Pay &To: ადრესა&ტი: - - Enter a label for this address to add it to your address book - შეიყვანეთ ამ მისამართის ნიშნული მისამართების წიგნში დასამატებლად - &Label: ნიშნუ&ლი: @@ -1609,10 +1018,6 @@ ShutdownWindow - - Bitcoin Core is shutting down... - Bitcoin Core იხურება... - Do not shut down the computer until this window disappears. არ გამორთოთ კომპიუტერი ამ ფანჯრის გაქრობამდე. @@ -1688,69 +1093,9 @@ Reset all verify message fields ვერიფიკაციის ყველა ველის წაშლა - - Click "Sign Message" to generate signature - ხელმოწერის გენერირებისათვის დააჭირეთ "მესიჯის ხელმოწერა"-ს - - - The entered address is invalid. - შეყვანილი მისამართი არასწორია. - - - Please check the address and try again. - შეამოწმეთ მისამართი და სცადეთ ხელახლა. - - - The entered address does not refer to a key. - შეყვანილი მისამართი არ არის კავშირში გასაღებთან. - - - Wallet unlock was cancelled. - საფულის განბლოკვა შეწყვეტილია. - - - Private key for the entered address is not available. - ამ მისამართისათვის პირადი გასაღები მიუწვდომელია. - - - Message signing failed. - ვერ მოხერხდა მესიჯის ხელმოწერა. - - - Message signed. - მესიჯი ხელმოწერილია. - - - The signature could not be decoded. - ხელმოწერის დეკოდირება ვერ ხერხდება. - - - Please check the signature and try again. - შეამოწმეთ ხელმოწერა და სცადეთ ხელახლა. - - - The signature did not match the message digest. - ხელმოწერა არ შეესაბამება მესიჯის დაიჯესტს. - - - Message verification failed. - მესიჯის ვერიფიკაცია ვერ მოხერხდა. - - - Message verified. - მესიჯი ვერიფიცირებულია. - SplashScreen - - Bitcoin Core - Bitcoin Core - - - The Bitcoin Core developers - Bitcoin Core-ს ავტორები - [testnet] [testnet] @@ -1763,426 +1108,16 @@ KB/s - - TransactionDesc - - Open until %1 - ღია იქნება სანამ %1 - - - conflicted - კონფლიქტშია - - - %1/offline - %1/გათიშულია - - - %1/unconfirmed - %1/დაუდასტურებელია - - - %1 confirmations - %1 დადასტურებულია - - - Status - სტატუსი - - - Date - თარიღი - - - Source - წყარო - - - Generated - გენერირებულია - - - From - გამგზავნი - - - To - მიმღები - - - own address - საკუთარი მისამართი - - - label - ნიშნული - - - Credit - კრედიტი - - - not accepted - უარყოფილია - - - Debit - დებიტი - - - Transaction fee - ტრანსაქციის საფასური - საკომისიო - - - Net amount - სუფთა თანხა - - - Message - მესიჯი - - - Comment - შენიშვნა - - - Transaction ID - ტრანსაქციის ID - - - Merchant - გამყიდველი - - - 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. - გენერირებული მონეტები გასაგზავნად მომწიფდება %1 ბლოკის შემდეგ. ეს ბლოკი გენერირების შემდეგ გავრცელებულ იქნა ქსელში ბლოკთა ჯაჭვზე დასამატებლად. თუ ის ვერ ჩაჯდა ჯაჭვში, მიეცემა სტატუსი "უარყოფილია" და ამ მონეტებს ვერ გამოიყენებთ. ასეთი რამ შეიძლება მოხდეს, თუ რომელიმე კვანძმა რამდენიმე წამით დაგასწროთ ბლოკის გენერირება. - - - Debug information - დახვეწის ინფორმაცია - - - Transaction - ტრანსაქცია - - - Inputs - ხარჯები - - - Amount - თანხა - - - true - ჭეშმარიტი - - - false - მცდარი - - - , has not been successfully broadcast yet - , დაგზავნა არ არის წარმატებით დასრულებული - - - unknown - უცნობია - - TransactionDescDialog - - Transaction details - ტრანსაქციის დეტალები - This pane shows a detailed description of the transaction ტრანსაქციის დაწვრილებითი აღწერილობა - - TransactionTableModel - - Date - თარიღი - - - Type - ტიპი - - - Immature (%1 confirmations, will be available after %2) - არ არის მომწიფებული (%1 დასტური, საჭიროა სულ %2) - - - Open until %1 - ღია იქნება სანამ %1 - - - Confirmed (%1 confirmations) - დადასტურებულია (%1დასტური) - - - This block was not received by any other nodes and will probably not be accepted! - ეს ბლოკი არ არის მიღებული არცერთი კვანძის მიერ და სავარაუდოდ უარყოფილია! - - - Generated but not accepted - გენერირებულია, მაგრამ უარყოფილია - - - Offline - ოფლაინშია - - - Label - ნიშნული - - - Unconfirmed - დაუდასტურებელია - - - Confirming (%1 of %2 recommended confirmations) - დადასტურებულია (%1, რეკომენდებულია %2) - - - Conflicted - კონფლიქტშია - - - Received with - შემოსულია - - - Received from - გამომგზავნი - - - Sent to - გაგზავნილია - - - Payment to yourself - გადახდილია საკუთარი თავისათვის - - - Mined - მოპოვებულია - - - (n/a) - (მიუწვდ.) - - - Transaction status. Hover over this field to show number of confirmations. - ტრანსაქციის სტატუსი. ველზე კურსორის შეყვანისას გამოჩნდება დასტურების რაოდენობა. - - - Date and time that the transaction was received. - ტრანსაქციის მიღების თარიღი და დრო. - - - Type of transaction. - ტრანსაქციის ტიპი. - - - Amount removed from or added to balance. - ბალანსიდან მოხსნილი ან დამატებული თანხა. - - - - TransactionView - - All - ყველა - - - Today - დღეს - - - This week - ამ კვირის - - - This month - ამ თვის - - - Last month - ბოლო თვის - - - This year - ამ წლის - - - Range... - შუალედი... - - - Received with - შემოსულია - - - Sent to - გაგზავნილია - - - To yourself - საკუთარი თავისათვის - - - Mined - მოპოვებულია - - - Other - სხვა - - - Enter address or label to search - შეიყვანეთ საძებნი მისამართი ან ნიშნული - - - Min amount - მინ. თანხა - - - Copy address - მისამართის კოპირება - - - Copy label - ნიშნულის კოპირება - - - Copy amount - თანხის კოპირება - - - Copy transaction ID - ტრანსაქციის ID-ს კოპირება - - - Edit label - ნიშნულის რედაქტირება - - - Show transaction details - ტრანსაქციის დეტალების ჩვენება - - - Export Transaction History - ტრანსაქციების ისტორიის ექსპორტი - - - Exporting Failed - ექსპორტი ვერ განხორციელდა - - - There was an error trying to save the transaction history to %1. - შეცდომა %1-ში ტრანსაქციების შენახვის მცდელობისას. - - - Exporting Successful - ეხპორტი განხორციელებულია - - - The transaction history was successfully saved to %1. - ტრანსაქციების ისტორია შენახულია %1-ში. - - - Comma separated file (*.csv) - CSV-ფაილი (*.csv) - - - Confirmed - დადასტურებულია - - - Date - თარიღი - - - Type - ტიპი - - - Label - ნიშნული - - - Address - მისამართი - - - ID - ID - - - Range: - შუალედი: - - - to - - - - UnitDisplayStatusBarControl - - WalletFrame - - No wallet has been loaded. - არ არის ჩატვირთული საფულე. - - - - WalletModel - - Send Coins - მონეტების გაგზავნა - - - - WalletView - - &Export - &ექსპორტი - - - Export the data in the current tab to a file - ამ ბარათიდან მონაცემების ექსპორტი ფაილში - - - Backup Wallet - საფულის არქივირება - - - Wallet Data (*.dat) - საფულის მონაცემები (*.dat) - - - Backup Failed - არქივირება ვერ მოხერხდა - - - There was an error trying to save the wallet data to %1. - შეცდომა %1-ში საფულის მონაცემების შენახვის მცდელობისას. - - - The wallet data was successfully saved to %1. - საფულის მონაცემები შენახულია %1-ში. - - - Backup Successful - არქივირება შესრულებულია - - bitcoin-core @@ -2213,6 +1148,10 @@ Accept connections from outside (default: 1 if no -proxy or -connect) გარედან შეერთებების დაშვება (ნაგულისხმევი: 1 თუ არ გამოიყენება -proxy ან -connect) + + Bitcoin Core + Bitcoin Core + Bind to given address and always listen on it. Use [host]:port notation for IPv6 მოცემულ მისამართზე მიჯაჭვა მუდმივად მასზე მიყურადებით. გამოიყენეთ [host]:port ფორმა IPv6-სათვის @@ -2233,10 +1172,6 @@ Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. ყურადღება: ჩვენ არ ვეთანხმებით ყველა პირს. შესაძლოა თქვენ ან სხვა კვანძებს განახლება გჭირდებათ. - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - ყურადღება: wallet.dat დაზიანებულია! ორიგინალური wallet.dat შენახულია როგორც wallet.{timestamp}.bak %s-ში; თუ შეამჩნიეთ უზუსტობა ნაშთში ან ტრანსაქციებში, აღადგინეთ არქივიდან. - <category> can be: <category> შეიძლება იყოს: @@ -2321,10 +1256,6 @@ Wallet options: სფულის ოპციები: - - You need to rebuild the database using -reindex to change -txindex - საჭიროა ბაზის ხელახალი აგება, გამოიყენეთ -reindex რათა შეცვალოთ -txindex - Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message) ბრძანების შესრულება შესაბამისი უწყების მიღებისას ან როცა შეინიშნება საგრძნობი გახლეჩა (cmd-ში %s შეიცვლება მესიჯით) @@ -2333,26 +1264,10 @@ Set maximum size of high-priority/low-fee transactions in bytes (default: %d) მაღალპრიორიტეტული/დაბალსაკომისიოიანი ტრანსაქციების მაქსიმალური ზომა ბაიტებში (ნაგულისხმევი: %d) - - Cannot resolve -whitebind address: '%s' - ვერ ხერხდება -whitebind მისამართის გარკვევა: '%s' - Information ინფორმაცია - - Invalid amount for -maxtxfee=<amount>: '%s' - დაუშვებელი მნიშვნელობა -pmaxtxfee<amount>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - დაუშვებელი მნიშვნელობა -minrelaytxfee=<amount>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - დაუშვებელი მნიშვნელობა -mintxfee=<amount>: '%s' - Send trace/debug info to console instead of debug.log file ტრასირების/დახვეწის ინფოს გაგზავნა კონსოლზე debug.log ფაილის ნაცვლად @@ -2389,10 +1304,6 @@ Zapping all transactions from wallet... ტრანსაქციების ჩახსნა საფულიდან... - - wallet.dat corrupt, salvage failed - wallet.dat დაზიანებულია, აღდგენა ვერ მოხერხდა - Password for JSON-RPC connections პაროლი JSON-RPC-შეერთებისათვის @@ -2401,10 +1312,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) კომანდის შესრულება უკეთესი ბლოკის გამოჩენისას (%s კომანდაში ჩანაცვლდება ბლოკის ჰეშით) - - This help message - ეს ტექსტი - Allow DNS lookups for -addnode, -seednode and -connect DNS-ძებნის დაშვება -addnode, -seednode და -connect-სათვის @@ -2413,14 +1320,6 @@ Loading addresses... მისამართების ჩატვირთვა... - - Error loading wallet.dat: Wallet corrupted - არ იტვირთება wallet.dat: საფულე დაზიანებულია - - - Error loading wallet.dat - არ იტვირთება wallet.dat - Invalid -proxy address: '%s' არასწორია მისამართი -proxy: '%s' @@ -2429,18 +1328,6 @@ Unknown network specified in -onlynet: '%s' -onlynet-ში მითითებულია უცნობი ქსელი: '%s' - - Cannot resolve -bind address: '%s' - ვერ ხერხდება -bind მისამართის გარკვევა: '%s' - - - Cannot resolve -externalip address: '%s' - ვერ ხერხდება -externalip მისამართის გარკვევა: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - დაუშვებელი მნიშვნელობა -paytxfee=<amount>: '%s' - Insufficient funds არ არის საკმარისი თანხა diff --git a/src/qt/locale/bitcoin_kk_KZ.ts b/src/qt/locale/bitcoin_kk_KZ.ts index cfa19d13f01e1..ff02521264f73 100644 --- a/src/qt/locale/bitcoin_kk_KZ.ts +++ b/src/qt/locale/bitcoin_kk_KZ.ts @@ -25,25 +25,6 @@ &Delete Жою - - Comma separated file (*.csv) - Үтірмен бөлінген текст (*.csv) - - - - AddressTableModel - - Label - таңба - - - Address - Адрес - - - (no label) - (таңбасыз) - AskPassphraseDialog @@ -59,31 +40,7 @@ Repeat new passphrase Жаңа құпия сөзді қайта енгізу - - Encrypt wallet - Әмиянді шифрлау - - - This operation needs your wallet passphrase to unlock the wallet. - Бұл операциясы бойынша сіздің әмиянізді қоршаудан шығару үшін әмиянның құпия сөзі керек - - - Unlock wallet - Әмиянізді қоршаудан шығару - - - This operation needs your wallet passphrase to decrypt the wallet. - Бұл операциясы бойынша сіздің әмиянізді шифрлап тастау үшін әмиянның құпия сөзі керек - - - Decrypt wallet - Әмиянізді шифрлап тастау - - - Change passphrase - Құпия сөзді өзгерту - - + BanTableModel @@ -174,9 +131,6 @@ Жаңартылған - - ClientModel - CoinControlDialog @@ -219,15 +173,7 @@ Priority Басымдық - - no - жоқ - - - (no label) - (таңбасыз) - - + EditAddressDialog @@ -238,7 +184,7 @@ &Address Адрес - + FreespaceChecker @@ -265,9 +211,6 @@ OverviewPage - - PaymentServer - PeerTableModel @@ -278,9 +221,6 @@ Саны - - QRImageWidget - RPCConsole @@ -297,37 +237,6 @@ ReceiveRequestDialog - - Address - Адрес - - - Amount - Саны - - - Label - таңба - - - - RecentRequestsTableModel - - Date - Күні - - - Label - таңба - - - Amount - Саны - - - (no label) - (таңбасыз) - SendCoinsDialog @@ -351,10 +260,6 @@ Dust: Шаң - - (no label) - (таңбасыз) - SendCoinsEntry @@ -375,70 +280,12 @@ TrafficGraphWidget - - TransactionDesc - - Date - Күні - - - Amount - Саны - - TransactionDescDialog - - TransactionTableModel - - Date - Күні - - - Label - таңба - - - - TransactionView - - Comma separated file (*.csv) - Үтірмен бөлінген файл (*.csv) - - - Confirmed - Растық - - - Date - Күні - - - Label - таңба - - - Address - Адрес - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - - WalletView - - &Export - Экспорт - - bitcoin-core diff --git a/src/qt/locale/bitcoin_ko_KR.ts b/src/qt/locale/bitcoin_ko_KR.ts index 34aeafcd5ca94..11e5d35af2465 100644 --- a/src/qt/locale/bitcoin_ko_KR.ts +++ b/src/qt/locale/bitcoin_ko_KR.ts @@ -25,10 +25,6 @@ C&lose 닫기(&L) - - &Copy Address - 주소 복사(&C) - Delete the currently selected address from the list 현재 목록에 선택한 주소 삭제 @@ -45,73 +41,6 @@ &Delete 삭제(&D) - - Choose the address to send coins to - 코인을 보내실 주소를 선택하세요 - - - Choose the address to receive coins with - 코인을 받으실 주소를 선택하세요 - - - C&hoose - 선택하기(&H) - - - Sending addresses - 타인 계좌 주소목록 - - - Receiving addresses - 내 계좌 주소목록 - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - 비트코인을 보내는 계좌 주소입니다. 코인을 보내기 전에 잔고와 받는 주소를 항상 확인하세요. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - 비트코인을 받을 수 있는 계좌 주소입니다. 매 거래마다 새로운 주소 사용을 권장합니다. - - - Copy &Label - 라벨 복사(&L) - - - &Edit - 편집(&E) - - - Export Address List - 주소 목록 내보내기 - - - Comma separated file (*.csv) - 쉼표로 구분된 파일(*.csv) - - - Exporting Failed - 내보내기 실패 - - - There was an error trying to save the address list to %1. Please try again. - %1으로 주소 목록을 저장하는 동안 오류가 발생했습니다. 다시 시도해주세요. - - - - AddressTableModel - - Label - 라벨 - - - Address - 주소 - - - (no label) - (라벨 없음) - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase 새로운 암호 재확인 - - Encrypt wallet - 지갑 암호화 - - - This operation needs your wallet passphrase to unlock the wallet. - 이 작업을 실행하려면 사용자 지갑의 암호가 필요합니다. - - - Unlock wallet - 지갑 잠금해제 - - - This operation needs your wallet passphrase to decrypt the wallet. - 이 작업은 지갑을 해독하기 위해 사용자 지갑의 암호가 필요합니다. - - - Decrypt wallet - 지갑 해독 - - - Change passphrase - 암호 변경 - - - Confirm wallet encryption - 지갑 암호화 승인 - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - 경고: 만약 암호화 된 지갑의 비밀번호를 잃어버릴 경우, <b>모든 비트코인들을 잃어버릴 수 있습니다</b>! - - - Are you sure you wish to encrypt your wallet? - 지갑 암호화를 허용하시겠습니까? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - 비트코인 코어는 암호화 과정을 마무리 하기 위해 종료됩니다. 당신의 지갑을 암호화하는 것이 여러분의 컴퓨터에 해를 끼치는 프로그램으로부터 여러분의 비트코인을 완전히 보호해주지는 못한다는 사실을 기억하십시오. - - - 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. - 중요: 본인 지갑파일에서 만든 예전 백업들은 새로 생성한 암호화 된 지갑 파일로 교체됩니다. 보안상 이유로 이전에 암호화 하지 않은 지갑 파일 백업은 사용할 수 없게 되니 빠른 시일 내로 새로 암호화 된 지갑을 사용하시기 바랍니다. - - - Warning: The Caps Lock key is on! - 경고: Caps Lock키가 켜져있습니다! - - - Wallet encrypted - 지갑 암호화 완료 - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - 지갑에 새로운 비밀문구를 입력하세요.<br/>비밀문구를 <b>열 개 이상의 무작위 글자</b> 혹은 <b>여덟개 이상의 단어로<b> 정하세요. - - - Enter the old passphrase and new passphrase to the wallet. - 지갑의 기존 암호와 새로운 암호를 입력해주세요. - - - Wallet encryption failed - 지갑 암호화 실패 - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - 지갑 암호화는 내부 오류로 인해 실패했습니다. 당신의 지갑은 암호화 되지 않았습니다. - - - The supplied passphrases do not match. - 지정한 암호가 일치하지 않습니다. - - - Wallet unlock failed - 지갑을 열지 못했습니다. - - - The passphrase entered for the wallet decryption was incorrect. - 지갑 해독을 위한 암호가 틀렸습니다. - - - Wallet decryption failed - 지갑 해독에 실패하였습니다. - - - Wallet passphrase was successfully changed. - 지갑 비밀번호가 성공적으로 변경되었습니다. - BanTableModel @@ -305,14 +146,6 @@ Open &URI... &URI 열기... - - Bitcoin Core client - 비트코인 코어 클라이언트 - - - Importing blocks from disk... - 디스크에서 블록 가져오는 중... - Reindexing blocks on disk... 디스크에서 블록 다시 색인중... @@ -357,10 +190,6 @@ &Receive 받기(&R) - - Show information about Bitcoin Core - 비트코인 코어에 관한 정보입니다. - &Show / Hide 보이기/숨기기(&S) @@ -397,22 +226,10 @@ Tabs toolbar 툴바 색인표 - - Bitcoin Core - 비트코인 코어 - Request payments (generates QR codes and bitcoin: URIs) 지불 요청하기 (QR코드와 비트코인이 생성됩니다: URIs) - - &About Bitcoin Core - 비트코인 코어 소개(&A) - - - Modify configuration options for Bitcoin Core - 비트코인 코어에 대한 설정을 수정합니다. - Show the list of used sending addresses and labels 한번 이상 사용된 보내는 주소와 주소 제목의 목록을 보여줍니다. @@ -429,10 +246,6 @@ &Command-line options 명령줄 옵션(&C) - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - 사용할 수 있는 비트코인 명령줄 옵션 목록을 가져오기 위해 Bitcoin-Qt 도움말 메시지를 표시합니다. - %n active connection(s) to Bitcoin network 비트코인 네트워크에 %n개의 연결이 활성화되어 있습니다. @@ -544,13 +357,6 @@ 지갑이 암호화 되었고 현재 잠겨져 있습니다 - - ClientModel - - Network Alert - 네트워크 경고 - - CoinControlDialog @@ -629,150 +435,6 @@ Priority 우선순위 - - Copy address - 주소 복사하기 - - - Copy label - 라벨 복사하기 - - - Copy amount - 거래액 복사 - - - Copy transaction ID - 거래 아이디 복사 - - - Lock unspent - 비트코인이 사용되지 않은 주소를 잠금 처리합니다. - - - Unlock unspent - 비트코인이 사용되지 않은 주소를 잠금 해제합니다. - - - Copy quantity - 수량 복사 - - - Copy fee - 수수료 복사 - - - Copy after fee - 수수료 이후 복사 - - - Copy bytes - bytes 복사 - - - Copy priority - 우선도 복사 - - - Copy dust - 더스트 복사 - - - Copy change - 잔돈 복사 - - - highest - 아주 높음 - - - higher - 보다 높음 - - - high - 높음 - - - medium-high - 약간 높음 - - - medium - 보통 - - - low-medium - 약간 낮음 - - - low - 낮음 - - - lower - 보다 낮음 - - - lowest - 아주 낮음 - - - (%1 locked) - (%1 잠금) - - - none - 없음 - - - This label turns red if the transaction size is greater than 1000 bytes. - 이 라벨은 1000바이트 이상의 거래가 이루어지면 붉게 변합니다. - - - This label turns red if the priority is smaller than "medium". - 이 라벨은 우선순위가 "보통" 이하인 경우 붉게 변합니다. - - - This label turns red if any recipient receives an amount smaller than %1. - 이 라벨은 수령인이 받은 액수가 잔고의 %1보다 작으면 붉게 변합니다. - - - Can vary +/- %1 satoshi(s) per input. - 입력마다 +/- %1 사토시가 변할 수 있습니다. - - - yes - - - - no - 아니요 - - - This means a fee of at least %1 per kB is required. - 이 뜻은 최소한 1kB 당 %1의 수수료가 필요하다는 의미입니다. - - - Can vary +/- 1 byte per input. - 입력마다 +/- 1 바이트가 변할 수 있습니다. - - - Transactions with higher priority are more likely to get included into a block. - 우선 순위가 높은 거래의 경우 블럭에 포함될 가능성이 더 많습니다. - - - (no label) - (라벨 없음) - - - change from %1 (%2) - ~로부터 변경 %1 (%2) - - - (change) - (잔돈) - EditAddressDialog @@ -796,38 +458,6 @@ &Address 주소(&A) - - New receiving address - 새로 받는 주소 - - - New sending address - 새로 보내는 주소 - - - Edit receiving address - 받는 주소 편집 - - - Edit sending address - 보내는 주소 편집 - - - The entered address "%1" is already in the address book. - 입력된 주소는"%1" 이미 주소록에 있습니다. - - - The entered address "%1" is not a valid Bitcoin address. - 입력한 "%1" 주소는 올바른 비트코인 주소가 아닙니다. - - - Could not unlock wallet. - 지갑을 열 수 없습니다. - - - New key generation failed. - 새로운 키 생성이 실패하였습니다. - FreespaceChecker @@ -854,10 +484,6 @@ HelpMessageDialog - - Bitcoin Core - 비트코인 코어 - version 버전 @@ -866,10 +492,6 @@ (%1-bit) (%1-비트) - - About Bitcoin Core - 비트코인 코어 소개 - Command-line options 명령줄 옵션 @@ -906,29 +528,13 @@ Show splash screen on startup (default: %u) 실행시 시작화면 보기 (기본값: %u) - - Reset all settings changes made over the GUI - GUI를 통해 수정된 모든 설정을 초기화 - - + Intro Welcome 환영합니다 - - Welcome to Bitcoin Core. - 비트코인 코어에 오신것을 환영합니다. - - - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - 프로그램이 처음으로 실행되고 있습니다. 비트코인 코어가 어디에 데이터를 저장할지 선택할 수 있습니다. - - - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - 비트코인 코어가 블럭체인의 복사본을 다운로드 저장합니다. 적어도 %1GB의 데이터가 이 폴더에 저장되며 시간이 경과할수록 점차 증가합니다. 그리고 지갑 또한 이 폴더에 저장됩니다. - Use the default data directory 기본 데이터 폴더를 사용하기 @@ -937,10 +543,6 @@ Use a custom data directory: 커스텀 데이터 폴더 사용: - - Bitcoin Core - 비트코인 코어 - Error: Specified data directory "%1" cannot be created. 오류: "%1" 지정한 데이터 디렉토리를 생성할 수 없습니다. @@ -976,10 +578,6 @@ Select payment request file 지불 요청 파일을 선택하세요 - - Select payment request file to open - 지불 요청 파일을 열기 위해서 선택하세요 - OptionsDialog @@ -1019,10 +617,6 @@ 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. 창을 닫으면 종료 대신 트레이로 보내기. 이 옵션을 활성화하면 메뉴에서 종료를 선택한 후에만 어플리케이션이 종료됩니다. - - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - 사용자 인터페이스 언어를 여기서 설정할 수 있습니다. 이 설정은 Bitcoin Core를 다시 시작할 때 적용됩니다. - 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 |. 서드-파티 URLs (예. 블록 탐색기)는 거래 탭의 컨텍스트 메뉴에 나타납니다. URL의 %s는 트랜잭션 해시값으로 대체됩니다. 여러 URLs는 수직 바 | 에서 나누어 집니다. @@ -1047,14 +641,6 @@ &Network 네트워크(&N) - - Automatically start Bitcoin Core after logging in to the system. - 시스템 로그인 후 자동으로 Bitcoin Core를 실행합니다. - - - &Start Bitcoin Core on system login - 시스템 로그인 후 Bitcoin Core 시작(&S) - (0 = auto, <0 = leave that many cores free) (0 = 자동, <0 = 지정된 코어 개수만큼 사용 안함) @@ -1284,182 +870,72 @@ - PaymentServer + PeerTableModel - URI handling - URI 조작중 + User Agent + 유저 에이전트 - Invalid payment address %1 - 잘못된 지불 주소입니다 %1 + Node/Service + 노드/서비스 - Payment request rejected - 지불 요청이 거부됨 + Ping Time + Ping 시간 + + + QObject - Payment request network doesn't match client network. - 지급 요청 네트워크가 클라이언트 네트워크와 일치되지 않습니다. + Amount + 거래액 - Payment request is not initialized. - 지불 요청이 초기화 되지 않았습니다. + Enter a Bitcoin address (e.g. %1) + 비트코인 주소를 입력하기 (예. %1) - Requested payment amount of %1 is too small (considered dust). - 요청한 금액 %1의 양이 너무 적습니다. (스팸성 거래로 간주) + %1 d + %1 일 - Payment request error - 지불 요청 오류 + %1 h + %1 시간 - Cannot start bitcoin: click-to-pay handler - 비트코인을 시작할 수 없습니다: 지급제어기를 클릭하시오 + %1 m + %1 분 - Payment request fetch URL is invalid: %1 - 대금 청구서의 URL이 올바르지 않습니다: %1 + %1 s + %1 초 - URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - URI의 파싱에 문제가 발생했습니다. 잘못된 비트코인 주소나 URI 파라미터 구성에 오류가 존재할 수 있습니다. + None + 없음 - Payment request file handling - 지불이 파일 처리를 요청합니다 + N/A + 없음 - Payment request file cannot be read! This can be caused by an invalid payment request file. - 지불 요청 파일을 읽을 수 없습니다. 이것은 잘못된 지불 요청 파일에 의해 발생하는 오류일 수 있습니다. + %1 ms + %1 ms + + + RPCConsole - Payment request expired. - 지불 요청이 만료됨. + Client name + 클라이언트 이름 - Unverified payment requests to custom payment scripts are unsupported. - 임의로 변경한 결제 스크립트 기반의 대금 청구서 양식은 검증되기 전까지는 지원되지 않습니다. + N/A + 없음 - Invalid payment request. - 잘못된 지불 요청. - - - Refund from %1 - %1 으로부터의 환불 - - - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - 지불 요청 %1은 너무 큽니다 (%2 바이트, %3 바이트까지 허용됩니다). - - - Error communicating with %1: %2 - %1과 소통하는데 오류: %2 - - - Payment request cannot be parsed! - 지불요청을 처리할 수 없습니다. - - - Bad response from server %1 - 서버로 부터 반응이 없습니다 %1 - - - Payment acknowledged - 지불이 승인됨 - - - Network request error - 네트워크 요청 오류 - - - - PeerTableModel - - User Agent - 유저 에이전트 - - - Node/Service - 노드/서비스 - - - Ping Time - Ping 시간 - - - - QObject - - Amount - 거래액 - - - Enter a Bitcoin address (e.g. %1) - 비트코인 주소를 입력하기 (예. %1) - - - %1 d - %1 일 - - - %1 h - %1 시간 - - - %1 m - %1 분 - - - %1 s - %1 초 - - - None - 없음 - - - N/A - 없음 - - - %1 ms - %1 ms - - - - QRImageWidget - - &Save Image... - 이미지 저장(&S)... - - - &Copy Image - 이미지 복사(&C) - - - Save QR Code - QR코드 저장 - - - PNG Image (*.png) - PNG 이미지 (*.png) - - - - RPCConsole - - Client name - 클라이언트 이름 - - - N/A - 없음 - - - Client version - 클라이언트 버전 + Client version + 클라이언트 버전 &Information @@ -1513,10 +989,6 @@ Memory usage 메모리 사용량 - - Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. - 현재의 데이터폴더에서 비트코인 디버그 파일을 엽니다. 용량이 큰 로그 파일은 몇 초가 걸릴 수 있습니다. - Received 받음 @@ -1633,10 +1105,6 @@ Out: Out: - - Build date - 빌드 날짜 - Debug log file 로그 파일 디버그 @@ -1673,10 +1141,6 @@ &Unban Node 노드 추방 취소(&U) - - Welcome to the Bitcoin Core RPC console. - 비트코인 RPC 콘솔에 오신걸 환영합니다 - Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. 기록을 찾아보려면 위 아래 화살표 키를, 화면을 지우려면 <b>Ctrl-L</b>키를 사용하십시오. @@ -1804,18 +1268,6 @@ Remove 삭제 - - Copy label - 라벨 복사하기 - - - Copy message - 메시지 복사 - - - Copy amount - 거래액 복사 - ReceiveRequestDialog @@ -1835,73 +1287,6 @@ &Save Image... 이미지 저장(&S)... - - Request payment to %1 - %1에 지불을 요청했습니다 - - - Payment information - 지불 정보 - - - URI - URI - - - Address - 주소 - - - Amount - 거래액 - - - Label - 라벨 - - - Message - 메시지 - - - Resulting URI too long, try to reduce the text for label / message. - URI 결과가 너무 길음, 라벨/메세지의 글을 줄이도록 하세요. - - - Error encoding URI into QR Code. - QR코드 인코딩 오류 - - - - RecentRequestsTableModel - - Date - 날짜 - - - Label - 라벨 - - - Message - 메시지 - - - Amount - 거래액 - - - (no label) - (라벨 없음) - - - (no message) - (메세지가 없습니다) - - - (no amount) - (거래액 없음) - SendCoinsDialog @@ -1970,935 +1355,289 @@ 선택 하기... - collapse fee-settings - 수수료 설정 접기 - - - per kilobyte - 킬로바이트 당 - - - If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte. - 사용자 정의 수수료가 1000사토시로 지정된 경우 트랜잭션의 크기가 250바이트 일 경우 1킬로바이트당 250사토시만 지불되지만 "최소 수수료"에선 1000사토시가 지불됩니다. 1킬로바이트가 넘는 트랜잭션인 경우 어떠한 경우에든 1킬로바이트 기준으로 지불됩니다. - - - Hide - 숨기기 - - - total at least - 최소 수수료 - - - Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process. - 블록의 용량보다 트랜잭션의 용량이 작은 경우에는 최소한의 수수료만으로도 충분합니다. 그러나 비트코인 네트워크의 처리량보다 더 많은 트랜잭션 요구는 영원히 검증이 안 될 수도 있습니다. - - - (read the tooltip) - (툴팁을 읽어보세요) - - - Recommended: - 권장: - - - Custom: - 사용자 정의: - - - (Smart fee not initialized yet. This usually takes a few blocks...) - (Smart fee가 아직 초기화되지 않았습니다. 블록 분석이 완료될 때 까지 기다려주십시오...) - - - Confirmation time: - 승인 시간: - - - normal - 일반 - - - fast - 빠름 - - - Send as zero-fee transaction if possible - 가능한 경우 수수료 없이 보내기 - - - (confirmation may take longer) - (거래 검증이 오래 걸릴 수 있습니다) - - - Send to multiple recipients at once - 다수의 수령인들에게 한번에 보내기 - - - Add &Recipient - 수령인 추가하기(&R) - - - Clear all fields of the form. - 양식의 모든 필드를 지웁니다 - - - Dust: - 더스트: - - - Clear &All - 모두 지우기(&A) - - - Balance: - 잔액: - - - Confirm the send action - 전송 기능 확인 - - - S&end - 보내기(&E) - - - Confirm send coins - 코인 전송을 확인 - - - %1 to %2 - %1을(를) %2(으)로 - - - Copy quantity - 수량 복사 - - - Copy amount - 거래액 복사 - - - Copy fee - 수수료 복사 - - - Copy after fee - 수수료 이후 복사 - - - Copy bytes - bytes 복사 - - - Copy priority - 우선도 복사 - - - Copy change - 잔돈 복사 - - - Total Amount %1 - 총 액수 %1 - - - or - 또는 - - - The amount to pay must be larger than 0. - 지불하는 금액은 0 보다 커야 합니다. - - - The amount exceeds your balance. - 잔고를 초과하였습니다. - - - The total exceeds your balance when the %1 transaction fee is included. - %1 의 거래수수료를 포함하면 잔고를 초과합니다. - - - Transaction creation failed! - 거래를 생성하는 것을 실패하였습니다 - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - 거래가 거부되었습니다. 몇몇 코인들이 지갑에서 이미 사용된 경우, 예를 들어 코인을 이미 사용한 wallet.dat를 복사해서 사용한 경우 지금 지갑에 기록이 안되있어 이런 일이 생길 수 있습니다. - - - A fee higher than %1 is considered an absurdly high fee. - %1 보다 높은 수수료는 너무 높은 수수료 입니다. - - - Payment request expired. - 지불 요청이 만료됨. - - - Pay only the required fee of %1 - 오직 %1 만의 수수료를 지불하기 - - - Estimated to begin confirmation within %n block(s). - %n 블록 안에 거래검증이 시작 될것으로 예상합니다. - - - The recipient address is not valid. Please recheck. - 수령인 주소가 정확하지 않습니다. 재확인 바랍니다 - - - Duplicate address found: addresses should only be used once each. - 두개 이상의 주소입니다: 한번에 하나의 주소에만 작업할 수 있습니다. - - - Warning: Invalid Bitcoin address - 경고: 잘못된 비트코인주소입니다 - - - (no label) - (라벨 없음) - - - Warning: Unknown change address - 경고: 알려지지 않은 주소변경입니다 - - - Copy dust - 더스트 복사 - - - Are you sure you want to send? - 정말로 보내시겠습니까? - - - added as transaction fee - 거래 수수료로 추가됨 - - - - SendCoinsEntry - - A&mount: - 금액(&M): - - - Pay &To: - 송금할 대상(&T) : - - - Enter a label for this address to add it to your address book - 주소록에 추가하려면 라벨을 입력하세요 - - - &Label: - 라벨(&L) - - - Choose previously used address - 이전에 사용한 주소를 선택하십시오 - - - This is a normal payment. - 이것은 정상적인 지불입니다. - - - The Bitcoin address to send the payment to - 이 비트코인 주소로 송금됩니다 - - - Alt+A - Alt+A - - - Paste address from clipboard - 클립보드로 부터 주소 붙여넣기 - - - Alt+P - Alt+P - - - Remove this entry - 항목을 지웁니다 - - - 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. - 수수료가 송금되는 금액에서 공제됩니다. 수령자는 금액 필드에서 입력한 금액보다 적은 금액을 전송받게 됩니다. 받는 사람이 여러 명인 경우 수수료는 균등하게 나누어집니다. - - - S&ubtract fee from amount - 송금액에서 수수료 공제(&U) - - - Message: - 메시지: - - - This is an unauthenticated payment request. - 인증 되지 않은 지급 요청입니다. - - - This is an authenticated payment request. - 인증 된 지급 요청 입니다. - - - Enter a label for this address to add it to the list of used addresses - 사용된 주소 목록에 새 주소를 추가하기 위해 라벨 이름을 입력해 주세요. - - - 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. - 비트코인에 첨부된 메시지: 참고용으로 거래와 함께 저장될 URI. 메모: 이 메시지는 비트코인 네트워크로 전송되지 않습니다. - - - Pay To: - 송금할 대상 : - - - Memo: - 메모: - - - - ShutdownWindow - - Bitcoin Core is shutting down... - Bitcoin Core이 종료 중입니다... - - - Do not shut down the computer until this window disappears. - 창이 사라지기 전까지 컴퓨터를 끄지마시오. - - - - SignVerifyMessageDialog - - Signatures - Sign / Verify a Message - 서명 - 싸인 / 메시지 확인 - - - &Sign Message - 메시지 서명(&S) - - - 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. - 여러분 자신을 증명하기 위해 주소를 첨가하고 서명할 수 있습니다. 피싱 공격으로 말미암아 여러분의 서명을 통해 속아 넘어가게 할 수 있으므로, 서명하지 않은 모든 모호한 요소를 주의하십시오. 조항들이 완전 무결한지 확인 후 동의하는 경우에만 서명하십시오. - - - The Bitcoin address to sign the message with - 메세지를 서명한 비트코인 주소 - - - Choose previously used address - 이전에 사용한 주소를 선택하십시오 - - - Alt+A - Alt+A - - - Paste address from clipboard - 클립보드로 부터 주소를 복사하기 - - - Alt+P - Alt+P - - - Enter the message you want to sign here - 여기에 서명하려는 메시지를 입력하십시오 - - - Signature - 서명 - - - Copy the current signature to the system clipboard - 현재 서명을 시스템 클립보드에 복사 - - - Sign the message to prove you own this Bitcoin address - 여러분의 비트코인 주소를 증명하려면 메시지 서명하십시오 - - - Sign &Message - 메시지에 서명(&M) - - - Reset all sign message fields - 메시지 필드의 모든 서명 재설정 - - - Clear &All - 모두 지우기(&A) - - - &Verify Message - 메시지 검증(&V) - - - 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! - 메시지를 검증하기 위해 아래 칸에 각각 지갑 주소와 메시지, 전자서명을 입력하세요. (메시지 원본의 띄어쓰기, 들여쓰기, 행 나눔 등이 정확하게 입력되어야 하므로 원본을 복사해서 입력하세요) 이 기능은 메시지 검증이 주 목적이며, 네트워크 침입자에 의해 변조되지 않도록 전자서명 해독에 불필요한 시간을 소모하지 마세요. - - - The Bitcoin address the message was signed with - 메세지의 서명에 사용된 비트코인 주소 - - - Verify the message to ensure it was signed with the specified Bitcoin address - 정확한 비트코인주소가 입력됬는지 메시지를 확인하시오 - - - Verify &Message - 메시지 검증(&M) - - - Reset all verify message fields - 모든 검증 메시지 필드 재설정 - - - Click "Sign Message" to generate signature - 서명을 만들려면 "메시지 서명"을 누르십시오 - - - The entered address is invalid. - 입력한 주소가 잘못되었습니다. - - - Please check the address and try again. - 주소를 확인하고 다시 시도하십시오. - - - The entered address does not refer to a key. - 입력한 주소는 키에서 참조하지 않습니다. - - - Wallet unlock was cancelled. - 지갑 잠금 해제를 취소했습니다. - - - Private key for the entered address is not available. - 입력한 주소에 대한 개인키가 없습니다. - - - Message signing failed. - 메시지 서명에 실패했습니다. - - - Message signed. - 메시지를 서명했습니다. - - - The signature could not be decoded. - 서명을 해독할 수 없습니다. - - - Please check the signature and try again. - 서명을 확인하고 다시 시도하십시오. - - - The signature did not match the message digest. - 메시지 다이제스트와 서명이 일치하지 않습니다. - - - Message verification failed. - 메시지 검증에 실패했습니다. - - - Message verified. - 메시지를 검증했습니다. - - - - SplashScreen - - Bitcoin Core - 비트코인 코어 - - - The Bitcoin Core developers - 비트코인코어 개발자들 - - - [testnet] - [테스트넷] - - - - TrafficGraphWidget - - KB/s - KB/s - - - - TransactionDesc - - Open until %1 - %1 까지 열림 - - - conflicted - 충돌 - - - %1/offline - %1/오프라인 - - - %1/unconfirmed - %1/미확인 - - - %1 confirmations - %1 확인됨 - - - Status - 상태 - - - , broadcast through %n node(s) - %n 노드를 거쳐 전파합니다. - - - Date - 날짜 - - - Source - 소스 - - - Generated - 생성하다 - - - From - 으로부터 - - - To - 에게 - - - own address - 자신의 주소 - - - watch-only - 모니터링 지갑 - - - label - 라벨 - - - Credit - 예금 - - - matures in %n more block(s) - %n개 블럭 후에 코인 숙성이 완료됩니다. - - - not accepted - 허용되지 않는다 - - - Debit - 차변 - - - Total debit - 총 출금액 - - - Total credit - 총 입금액 - - - Transaction fee - 송금 수수료 - - - Net amount - 총 거래액 - - - Message - 메시지 - - - Comment - 설명 - - - Transaction ID - 아이디 - - - Merchant - 상인 - - - 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. - 신규 채굴된 코인이 사용되기 위해서는 %1 개의 블럭이 경과되어야 합니다. 블럭을 생성할 때 블럭체인에 추가되도록 네트워크에 전파되는 과정을 거치는데, 블럭체인에 포함되지 못하고 실패한다면 해당 블럭의 상태는 '미승인'으로 표현되고 비트코인 또한 사용될 수 없습니다. 이 현상은 다른 노드가 비슷한 시간대에 동시에 블럭을 생성할 때 종종 발생할 수 있습니다. - - - Debug information - 디버깅 정보 - - - Transaction - 송금 - - - Inputs - 입력 - - - Amount - 거래액 - - - true - - - - false - 거짓 - - - , has not been successfully broadcast yet - . 아직 성공적으로 통보하지 않음 - - - Open for %n more block(s) - %n 개의 추가 블록을 읽습니다. - - - unknown - 알수없음 - - - - TransactionDescDialog - - Transaction details - 거래 세부 내역 - - - This pane shows a detailed description of the transaction - 이 창은 거래의 세부내역을 보여줍니다 - - - - TransactionTableModel - - Date - 날짜 + collapse fee-settings + 수수료 설정 접기 - Type - 종류 + per kilobyte + 킬로바이트 당 - Immature (%1 confirmations, will be available after %2) - 충분히 숙성되지 않은 상태 (%1 승인, %2 후에 사용 가능합니다) + If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte. + 사용자 정의 수수료가 1000사토시로 지정된 경우 트랜잭션의 크기가 250바이트 일 경우 1킬로바이트당 250사토시만 지불되지만 "최소 수수료"에선 1000사토시가 지불됩니다. 1킬로바이트가 넘는 트랜잭션인 경우 어떠한 경우에든 1킬로바이트 기준으로 지불됩니다. - - Open for %n more block(s) - %n 개의 추가 블록을 읽습니다. + + Hide + 숨기기 - Open until %1 - %1 까지 열림 + total at least + 최소 수수료 - Confirmed (%1 confirmations) - 확인됨 (%1 확인됨) + Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process. + 블록의 용량보다 트랜잭션의 용량이 작은 경우에는 최소한의 수수료만으로도 충분합니다. 그러나 비트코인 네트워크의 처리량보다 더 많은 트랜잭션 요구는 영원히 검증이 안 될 수도 있습니다. - This block was not received by any other nodes and will probably not be accepted! - 이 블럭은 다른 노드로부터 받지 않아 허용되지 않을 것임. + (read the tooltip) + (툴팁을 읽어보세요) - Generated but not accepted - 생성되었으나 거절됨 + Recommended: + 권장: - Offline - 오프라인 + Custom: + 사용자 정의: - Label - 라벨 + (Smart fee not initialized yet. This usually takes a few blocks...) + (Smart fee가 아직 초기화되지 않았습니다. 블록 분석이 완료될 때 까지 기다려주십시오...) - Unconfirmed - 미확인 + Confirmation time: + 승인 시간: - Confirming (%1 of %2 recommended confirmations) - 승인 중 (권장되는 승인 회수 %2 대비 현재 승인 수 %1) + normal + 일반 - Conflicted - 충돌 + fast + 빠름 - Received with - 보낸 주소 + Send to multiple recipients at once + 다수의 수령인들에게 한번에 보내기 - Received from - 보낸 주소 + Add &Recipient + 수령인 추가하기(&R) - Sent to - 받는 주소 + Clear all fields of the form. + 양식의 모든 필드를 지웁니다 - Payment to yourself - 자신에게 지불 + Dust: + 더스트: - Mined - 채굴 + Clear &All + 모두 지우기(&A) - watch-only - 모니터링 지갑 + Balance: + 잔액: - (n/a) - (없음) + Confirm the send action + 전송 기능 확인 - Transaction status. Hover over this field to show number of confirmations. - 거래상황. 마우스를 올리면 검증횟수가 표시됩니다. + S&end + 보내기(&E) + + + SendCoinsEntry - Date and time that the transaction was received. - 거래가 이루어진 날짜와 시각. + A&mount: + 금액(&M): - Type of transaction. - 거래의 종류. + Pay &To: + 송금할 대상(&T) : - Whether or not a watch-only address is involved in this transaction. - 이 트랜잭션에 모니터링 지갑를 포함할지의 여부입니다. + &Label: + 라벨(&L) - User-defined intent/purpose of the transaction. - 트랜잭션에 대한 사용자 정의 intent/purpose + Choose previously used address + 이전에 사용한 주소를 선택하십시오 - Amount removed from or added to balance. - 변경된 잔고. + This is a normal payment. + 이것은 정상적인 지불입니다. - - - TransactionView - All - 전체 + The Bitcoin address to send the payment to + 이 비트코인 주소로 송금됩니다 - Today - 오늘 + Alt+A + Alt+A - This week - 이번주 + Paste address from clipboard + 클립보드로 부터 주소 붙여넣기 - This month - 이번 달 + Alt+P + Alt+P - Last month - 지난 달 + Remove this entry + 항목을 지웁니다 - This year - 올 해 + 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. + 수수료가 송금되는 금액에서 공제됩니다. 수령자는 금액 필드에서 입력한 금액보다 적은 금액을 전송받게 됩니다. 받는 사람이 여러 명인 경우 수수료는 균등하게 나누어집니다. - Range... - 범위... + S&ubtract fee from amount + 송금액에서 수수료 공제(&U) - Received with - 보낸 주소 + Message: + 메시지: - Sent to - 받는 주소 + This is an unauthenticated payment request. + 인증 되지 않은 지급 요청입니다. - To yourself - 자기거래 + This is an authenticated payment request. + 인증 된 지급 요청 입니다. - Mined - 채굴 + Enter a label for this address to add it to the list of used addresses + 사용된 주소 목록에 새 주소를 추가하기 위해 라벨 이름을 입력해 주세요. - Other - 기타 + 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. + 비트코인에 첨부된 메시지: 참고용으로 거래와 함께 저장될 URI. 메모: 이 메시지는 비트코인 네트워크로 전송되지 않습니다. - Enter address or label to search - 검색하기 위한 주소 또는 표 입력 + Pay To: + 송금할 대상 : - Min amount - 최소 거래액 + Memo: + 메모: + + + ShutdownWindow - Copy address - 주소 복사하기 + Do not shut down the computer until this window disappears. + 창이 사라지기 전까지 컴퓨터를 끄지마시오. + + + SignVerifyMessageDialog - Copy label - 라벨 복사하기 + Signatures - Sign / Verify a Message + 서명 - 싸인 / 메시지 확인 - Copy amount - 거래액 복사 + &Sign Message + 메시지 서명(&S) - Copy transaction ID - 거래 아이디 복사 + 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. + 여러분 자신을 증명하기 위해 주소를 첨가하고 서명할 수 있습니다. 피싱 공격으로 말미암아 여러분의 서명을 통해 속아 넘어가게 할 수 있으므로, 서명하지 않은 모든 모호한 요소를 주의하십시오. 조항들이 완전 무결한지 확인 후 동의하는 경우에만 서명하십시오. - Copy raw transaction - 로우 트랜잭션 복사 + The Bitcoin address to sign the message with + 메세지를 서명한 비트코인 주소 - Edit label - 라벨 수정하기 + Choose previously used address + 이전에 사용한 주소를 선택하십시오 - Show transaction details - 거래 내역 확인 + Alt+A + Alt+A - Export Transaction History - 거래 기록 내보내기 + Paste address from clipboard + 클립보드로 부터 주소를 복사하기 - Watch-only - 모니터링 지갑 + Alt+P + Alt+P - Exporting Failed - 내보내기 실패 + Enter the message you want to sign here + 여기에 서명하려는 메시지를 입력하십시오 - There was an error trying to save the transaction history to %1. - %1으로 거래 기록을 저장하는데 오류가 있었습니다. + Signature + 서명 - Exporting Successful - 내보내기 성공 + Copy the current signature to the system clipboard + 현재 서명을 시스템 클립보드에 복사 - The transaction history was successfully saved to %1. - 거래 기록이 성공적으로 %1에 저장되었습니다. + Sign the message to prove you own this Bitcoin address + 여러분의 비트코인 주소를 증명하려면 메시지 서명하십시오 - Comma separated file (*.csv) - 각각의 파일에 쉼표하기(*.csv) + Sign &Message + 메시지에 서명(&M) - Confirmed - 확인됨 + Reset all sign message fields + 메시지 필드의 모든 서명 재설정 - Date - 날짜 + Clear &All + 모두 지우기(&A) - Type - 종류 + &Verify Message + 메시지 검증(&V) - Label - 라벨 + 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! + 메시지를 검증하기 위해 아래 칸에 각각 지갑 주소와 메시지, 전자서명을 입력하세요. (메시지 원본의 띄어쓰기, 들여쓰기, 행 나눔 등이 정확하게 입력되어야 하므로 원본을 복사해서 입력하세요) 이 기능은 메시지 검증이 주 목적이며, 네트워크 침입자에 의해 변조되지 않도록 전자서명 해독에 불필요한 시간을 소모하지 마세요. - Address - 주소 + The Bitcoin address the message was signed with + 메세지의 서명에 사용된 비트코인 주소 - ID - 아이디 + Verify the message to ensure it was signed with the specified Bitcoin address + 정확한 비트코인주소가 입력됬는지 메시지를 확인하시오 - Range: - 범위: + Verify &Message + 메시지 검증(&M) - to - 상대방 + Reset all verify message fields + 모든 검증 메시지 필드 재설정 - UnitDisplayStatusBarControl + SplashScreen - Unit to show amounts in. Click to select another unit. - 거래액을 표시하는 단위. 클릭해서 다른 단위를 선택할 수 있습니다. + [testnet] + [테스트넷] - WalletFrame + TrafficGraphWidget - No wallet has been loaded. - 지갑 불러오기가 안됩니다 + KB/s + KB/s - WalletModel + TransactionDescDialog - Send Coins - 코인들 보내기 + This pane shows a detailed description of the transaction + 이 창은 거래의 세부내역을 보여줍니다 - WalletView - - &Export - 내보내기(&E) - - - Export the data in the current tab to a file - 현재 탭에 있는 데이터를 파일로 내보내기 - - - Backup Wallet - 지갑 백업 - - - Wallet Data (*.dat) - 지갑 데이터(*.dat) - - - Backup Failed - 백업 실패 - - - There was an error trying to save the wallet data to %1. - 지갑 데이터를 %1 폴더에 저장하는 동안 오류가 발생했습니다. - - - The wallet data was successfully saved to %1. - 지갑 정보가 %1에 성공적으로 저장되었습니다 - + UnitDisplayStatusBarControl - Backup Successful - 백업 성공 + Unit to show amounts in. Click to select another unit. + 거래액을 표시하는 단위. 클릭해서 다른 단위를 선택할 수 있습니다. @@ -2927,14 +1666,6 @@ If <category> is not supplied or if <category> = 1, output all debugging information. <category>가 제공되지 않거나 <category> = 1 인 경우, 모든 디버깅 정보를 출력 - - Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s) - 하나의 지갑 트랜잭션에서의 총 수수료(%s)의 최대치; 너무 낮게 설정하면 큰 트랜잭션이 중지 됩니다 (기본값: %s) - - - Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. - 컴퓨터의 날짜와 시간이 올바른지 확인하십시오! 시간이 잘못되면 비트코인은 제대로 동작하지 않습니다. - Prune configured below the minimum of %d MiB. Please use a higher number. 블록 축소가 최소치의 %d MiB 밑으로 설정되어 있습니다. 더 높은 값을 사용해 보세요. @@ -2975,6 +1706,10 @@ Accept connections from outside (default: 1 if no -proxy or -connect) 외부 접속을 승인합니다 + + Bitcoin Core + 비트코인 코어 + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. -fallbackfee은 너무 높습니다! 이것은 수수료 예측을 이용할 수 없을 때 지불되는 트랜잭션 수수료입니다. @@ -3019,14 +1754,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications 이 빌드 버전은 정식 출시 전 테스트의 목적이며, 예기치 않은 위험과 오류가 발생할 수 있습니다. 채굴과 상점용 소프트웨어로 사용하는 것을 권하지 않습니다. - - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - 이 컴퓨터의 %s에 바인딩 할 수 없습니다. 아마도 비트코인이 실행중인 것 같습니다. - - - Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. - 지원하지 않는 인수 -whitelistalwaysrelay 는 무시됩니다, -whitelistrelay 나 -whitelistforcerelay 를 사용해 주세요. - Use UPnP to map the listening port (default: 1 when listening and no -proxy) 리슨(Listen) 포트를 할당하기 위해 UPnP 사용 (기본값: 열려있거나 -proxy 옵션을 사용하지 않을 시 1) @@ -3043,18 +1770,10 @@ Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. 경고 : 모든 네트워크가 동의해야 하나, 일부 채굴자들에게 문제가 있는 것으로 보입니다. - - Warning: Unknown block versions being mined! It's possible unknown rules are in effect - 경고: 알려지지 않은 버전의 블록이 채굴되었습니다. 알려지지 않은 규칙이 적용되었을 가능성이 있습니다. - Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. 경고: 현재 비트코인 버전이 다른 네트워크 참여자들과 동일하지 않는 것 같습니다. 당신 또는 다른 참여자들이 동일한 비트코인 버전으로 업그레이드 할 필요가 있습니다. - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - 경고 : wallet.dat가 손상되어 데이터가 복구되었습니다. 원래의 wallet.dat 파일은 %s 후에 wallet.{timestamp}.bak 이름으로 저장됩니다. 잔액과 거래 내역이 정확하지 않다면 백업 파일로 부터 복원해야 합니다. - Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. 설정된 넷마스크 혹은 IP 주소로 화이트리스트에 포함된 피어에 접속합니다. 이 설정은 복수로 지정 할 수 있습니다. @@ -3236,12 +1955,12 @@ 지갑 %s는 데이터 디렉토리 %s 밖에 위치합니다. - Wallet options: - 지갑 옵션: + Wallet debugging/testing options: + 지갑 디버깅/테스트 옵션: - You need to rebuild the database using -reindex to change -txindex - -txindex를 바꾸기 위해서는 -reindex를 사용해서 데이터베이스를 재구성해야 합니다. + Wallet options: + 지갑 옵션: 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 @@ -3255,10 +1974,6 @@ Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces) 선택된 주소로 고정하여 JSON-RPC 연결을 리슨(Listen)합니다. IPv6 프로토콜인 경우 [host]:port 방식의 명령어 표기법을 사용합니다. 이 옵션은 복수로 지정 할수 있습니다. (기본값: 모든 인터페이스에 고정) - - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - 데이터 디렉토리 %s에 락을 걸 수 없었습니다. 비트코인 코어가 이미 실행 중인 것으로 보입니다. - Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) umask 077 대신 시스템 기본 퍼미션으로 새 파일을 만듭니다 (지갑 기능이 비활성화 상태에서만 유효합니다) @@ -3303,10 +2018,6 @@ Set maximum size of high-priority/low-fee transactions in bytes (default: %d) 최대 크기를 최우선으로 설정 / 바이트당 최소 수수료로 거래(기본값: %d) - - Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) - 코인 생성에 대한 스레드 갯수 설정 (-1 = 모든 코어, 기본값: %d) - The transaction amount is too small to send after the fee has been deducted 거래액이 수수료를 지불하기엔 너무 작습니다 @@ -3331,34 +2042,14 @@ Accept public REST requests (default: %u) 공개 REST 요청을 허가 (기본값: %u) - - Activating best chain... - 최적 블록 체인을 활성화하는중... - - - Attempt to recover private keys from a corrupt wallet.dat on startup - 시작시 망가진 wallet.dat에서 개인키 복원을 시도 - Automatically create Tor hidden service (default: %d) Tor서비스를 자동적으로 생성 (기본값: %d) - - Cannot resolve -whitebind address: '%s' - -whitebind 주소를 확인할 수 없습니다: '%s' - Connect through SOCKS5 proxy SOCK5 프록시를 통해 연결 - - Copyright (C) 2009-%i The Bitcoin Core Developers - Copyright (C) 2009-%i The Bitcoin Core Developers - - - Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - wallet.dat 불러오기 오류: 최신 버전의 Bitcoin Core이 필요합니다. - Error reading from database, shutting down. 블록 데이터베이스를 불러오는데 오류가 발생하였습니다, 종료됩니다. @@ -3371,22 +2062,6 @@ Information 정보 - - Initialization sanity check failed. Bitcoin Core is shutting down. - 무결성 확인 초기화가 실패했습니다. Bitcoin Core가 종료됩니다. - - - Invalid amount for -maxtxfee=<amount>: '%s' - -maxtxfee=<amount>에 대한 양이 잘못되었습니다: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - 노드로 전달하기 위한 최저 거래 수수료가 부족합니다. - minrelaytxfee=<amount>: '%s' - - - - Invalid amount for -mintxfee=<amount>: '%s' - 최저 거래 수수료가 부족합니다. -mintxfee=<amount>: '%s' - Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) 유효하지 않은 금액 -paytxfee=<amount>: "%s" (최소 %s 이상이어야 됨) @@ -3411,14 +2086,6 @@ RPC server options: RPC 서버 설정 - - Rebuild block chain index from current blk000??.dat files on startup - 현재의 blk000??.dat 파일들로부터 블록체인 색인을 재구성합니다. - - - Receive and display P2P network alerts (default: %u) - P2P 네트워크 알림을 수신후 표시합니다 (기본값: %u) - Reducing -maxconnections from %d to %d, because of system limitations. 시스템 한계로 인하여 -maxconnections를 %d 에서 %d로 줄였습니다. @@ -3487,10 +2154,6 @@ Username for JSON-RPC connections JSON-RPC 연결에 사용할 사용자 이름 - - Wallet needed to be rewritten: restart Bitcoin Core to complete - 지갑을 새로 써야 합니다: 완료하기 위하여 Bitcoin Core을 다시 시작하십시오. - Warning 경고 @@ -3511,10 +2174,6 @@ ZeroMQ notification options: ZeroMQ 알림 옵션: - - wallet.dat corrupt, salvage failed - wallet.dat 파일이 손상되었고 복구가 실패하였습니다. - Password for JSON-RPC connections JSON-RPC 연결에 사용할 암호 @@ -3523,10 +2182,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) 최고의 블럭이 변하면 명령을 실행(cmd 에 있는 %s 는 블럭 해시에 의해 대체되어 짐) - - This help message - 도움말 메시지입니다 - Allow DNS lookups for -addnode, -seednode and -connect -addnode, -seednode, -connect 옵션에 대해 DNS 탐색 허용 @@ -3535,10 +2190,6 @@ Loading addresses... 주소를 불러오는 중... - - Error loading wallet.dat: Wallet corrupted - wallet.dat 불러오기 오류: 지갑 오류 - (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) (1 = 트랜잭션의 메타 데이터를 유지함 예. 계좌정보 와 지불 요구 정보, 2 = 트랜잭션 메타 데이터 파기) @@ -3555,10 +2206,6 @@ Do not keep transactions in the mempool longer than <n> hours (default: %u) 메모리 풀에 있는 트랜잭션 기록을 <n>시간 후 부터는 유지하지 않기 (기본값: %u) - - Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. - 경고 : wallet.dat 파일을 읽는 중 오류가 발생했습니다. 주소 키는 모두 정확하게 로딩되었으나 거래 데이터와 주소록 필드에서 누락이나 오류가 존재할 수 있습니다. - Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) 해당 금액(%s/kB) 보다 적은 수수료는 수수료 면제로 간주됩니다.(기본값: %s) @@ -3595,6 +2242,10 @@ Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported. 지원하지 않는 인수 -socks를 찾았습니다. 설정된 SOCKS의 버전은 더이상 사용할 수 없으며, SOCK5 프록시만을 지원합니다. + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + 지원하지 않는 인수 -whitelistalwaysrelay 는 무시됩니다, -whitelistrelay 나 -whitelistforcerelay 를 사용해 주세요. + Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s) Tor 서비스를 이용하여 피어에게 연결하기 위해 분리된 SOCKS5 프록시를 사용 (기본값: %s) @@ -3604,16 +2255,12 @@ JSON-RPC 연결시 사용자 이름과 해시화된 암호문. <userpw> 필드는 <USERNAME>:<SALT>$<HASH> 포멧으로 구성되어 있습니다. 전형적 파이썬 스크립트에선 share/rpcuser가 포함되어 있습니다. 이 옵션은 여러번 지정할 수 있습니다. - Always query for peer addresses via DNS lookup (default: %u) - DNS lookup을 통해 항상 피어주소에 대한 쿼리 보내기 (기본값: %u) - - - Error loading wallet.dat - wallet.dat 불러오기 오류 + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + 경고: 알려지지 않은 버전의 블록이 채굴되었습니다. 알려지지 않은 규칙이 적용되었을 가능성이 있습니다. - Generate coins (default: %u) - 코인 생성 (기본값: %u) + Always query for peer addresses via DNS lookup (default: %u) + DNS lookup을 통해 항상 피어주소에 대한 쿼리 보내기 (기본값: %u) How many blocks to check at startup (default: %u, 0 = all) @@ -3695,18 +2342,6 @@ Unknown network specified in -onlynet: '%s' -onlynet에 지정한 네트워크를 알 수 없습니다: '%s' - - Cannot resolve -bind address: '%s' - -bind 주소를 확인할 수 없습니다: '%s' - - - Cannot resolve -externalip address: '%s' - -externalip 주소를 확인할 수 없습니다: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - -paytxfee=<amount>에 대한 양이 잘못되었습니다: '%s' - Insufficient funds 자금 부족 diff --git a/src/qt/locale/bitcoin_ku_IQ.ts b/src/qt/locale/bitcoin_ku_IQ.ts new file mode 100644 index 0000000000000..da5e41a3583e9 --- /dev/null +++ b/src/qt/locale/bitcoin_ku_IQ.ts @@ -0,0 +1,272 @@ + + + AddressBookPage + + Create a new address + ناوونیشانێکی نوێ دروست بکە + + + &New + &نوێ + + + &Copy + &ڕوونووس + + + C&lose + C&داخستن + + + &Export + &هەناردن + + + &Delete + &سڕینەوە + + + + AskPassphraseDialog + + + BanTableModel + + + BitcoinGUI + + &Send + &ناردن + + + &File + &پەرگە + + + &Settings + &سازکارییەکان + + + &Help + &یارمەتی + + + Error + هەڵە + + + Warning + ئاگاداری + + + Information + زانیاری + + + + CoinControlDialog + + Amount: + کۆ: + + + Priority: + لەپێشی: + + + Fee: + تێچوون: + + + Amount + سەرجەم + + + Date + رێکەت + + + Priority + لەپێشی + + + + EditAddressDialog + + + FreespaceChecker + + name + ناو + + + + HelpMessageDialog + + version + وەشان + + + + Intro + + Welcome + بەخێربێن + + + Error + هەڵە + + + + OpenURIDialog + + + OptionsDialog + + Options + هەڵبژاردنەکان + + + + OverviewPage + + Total: + گشتی + + + + PeerTableModel + + + QObject + + Amount + سەرجەم + + + + RPCConsole + + &Information + &زانیاری + + + Name + ناو + + + Version + وەشان + + + &Open + &کردنەوە + + + &Clear + &پاککردنەوە + + + Totals + گشتییەکان + + + Yes + بەڵێ + + + No + نەخێر + + + + ReceiveCoinsDialog + + &Amount: + &سەرجەم: + + + &Message: + &پەیام: + + + Clear + پاککردنەوە + + + Show + پیشاندان + + + Remove + سڕینەوە + + + + ReceiveRequestDialog + + + SendCoinsDialog + + Amount: + کۆ: + + + Priority: + لەپێشی: + + + Fee: + تێچوون: + + + fast + خێرا + + + + SendCoinsEntry + + Message: + پەیام: + + + + ShutdownWindow + + + SignVerifyMessageDialog + + + SplashScreen + + + TrafficGraphWidget + + + TransactionDescDialog + + + UnitDisplayStatusBarControl + + + bitcoin-core + + Options: + هەڵبژاردنەکان: + + + Information + زانیاری + + + Warning + ئاگاداری + + + Error + هەڵە + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_ky.ts b/src/qt/locale/bitcoin_ky.ts index 51efd519c3821..14cb9c2020198 100644 --- a/src/qt/locale/bitcoin_ky.ts +++ b/src/qt/locale/bitcoin_ky.ts @@ -9,17 +9,6 @@ &Delete Ө&чүрүү - - - AddressTableModel - - Address - Дарек - - - (no label) - (аты жок) - AskPassphraseDialog @@ -70,23 +59,12 @@ Жаңыланган - - ClientModel - CoinControlDialog Date Дата - - none - жок - - - (no label) - (аты жок) - EditAddressDialog @@ -94,7 +72,7 @@ &Address &Дарек - + FreespaceChecker @@ -157,18 +135,12 @@ OverviewPage - - PaymentServer - PeerTableModel QObject - - QRImageWidget - RPCConsole @@ -209,29 +181,6 @@ ReceiveRequestDialog - - Address - Дарек - - - Message - Билдирүү - - - - RecentRequestsTableModel - - Date - Дата - - - Message - Билдирүү - - - (no label) - (аты жок) - SendCoinsDialog @@ -243,11 +192,7 @@ S&end &Жөнөтүү - - (no label) - (аты жок) - - + SendCoinsEntry @@ -279,54 +224,12 @@ TrafficGraphWidget - - TransactionDesc - - %1/offline - %1/тармакта эмес - - - Date - Дата - - - Message - Билдирүү - - TransactionDescDialog - - TransactionTableModel - - Date - Дата - - - - TransactionView - - Date - Дата - - - Address - Дарек - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - - WalletView - bitcoin-core diff --git a/src/qt/locale/bitcoin_la.ts b/src/qt/locale/bitcoin_la.ts index b11027d1ee275..ebaddba7e930e 100644 --- a/src/qt/locale/bitcoin_la.ts +++ b/src/qt/locale/bitcoin_la.ts @@ -9,10 +9,6 @@ Copy the currently selected address to the system clipboard Copia inscriptionem iam selectam in latibulum systematis - - &Copy Address - &Copia Inscriptionem - Delete the currently selected address from the list Dele active selectam inscriptionem ex enumeratione @@ -29,37 +25,6 @@ &Delete &Dele - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Hae sunt inscriptiones mittendi pensitationes. Semper inspice quantitatem et inscriptionem accipiendi antequam nummos mittis. - - - Copy &Label - Copia &Titulum - - - &Edit - &Muta - - - Comma separated file (*.csv) - Comma Separata Plica (*.csv) - - - - AddressTableModel - - Label - Titulus - - - Address - Inscriptio - - - (no label) - (nullus titulus) - AskPassphraseDialog @@ -79,82 +44,6 @@ Repeat new passphrase Itera novam tesseram - - Encrypt wallet - Cifra cassidile - - - This operation needs your wallet passphrase to unlock the wallet. - Huic operationi necesse est tessera cassidili tuo ut cassidile reseret. - - - Unlock wallet - Resera cassidile - - - This operation needs your wallet passphrase to decrypt the wallet. - Huic operationi necesse est tessera cassidili tuo ut cassidile decifret. - - - Decrypt wallet - Decifra cassidile - - - Change passphrase - Muta tesseram - - - Confirm wallet encryption - Confirma cifrationem cassidilis - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Monitio: Si cassidile tuum cifras et tesseram amittis, tu <b>AMITTES OMNES TUOS NUMMOS BITOS</b>! - - - Are you sure you wish to encrypt your wallet? - Certusne es te velle tuum cassidile cifrare? - - - 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. - GRAVE: Oportet ulla prioria conservata quae fecisti de plica tui cassidilis reponi a nove generata cifrata plica cassidilis. Propter securitatem, prioria conservata de plica non cifrata cassidilis inutilia fiet simul atque incipis uti novo cifrato cassidili. - - - Warning: The Caps Lock key is on! - Monitio: Litterae ut capitales seratae sunt! - - - Wallet encrypted - Cassidile cifratum - - - Wallet encryption failed - Cassidile cifrare abortum est - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Cassidile cifrare abortum est propter internum errorem. Tuum cassidile cifratum non est. - - - The supplied passphrases do not match. - Tesserae datae non eaedem sunt. - - - Wallet unlock failed - Cassidile reserare abortum est. - - - The passphrase entered for the wallet decryption was incorrect. - Tessera inserta pro cassidilis decifrando prava erat. - - - Wallet decryption failed - Cassidile decifrare abortum est. - - - Wallet passphrase was successfully changed. - Tessera cassidilis successa est in mutando. - BanTableModel @@ -217,10 +106,6 @@ &Change Passphrase... &Muta tesseram... - - Importing blocks from disk... - Importans frusta ab disco... - Reindexing blocks on disk... Recreans indicem frustorum in disco... @@ -301,10 +186,6 @@ Tabs toolbar Tabella instrumentorum "Tabs" - - Bitcoin Core - Bitcoin Nucleus - &Command-line options Optiones mandati initiantis @@ -362,13 +243,6 @@ Cassidile <b>cifratum</b> est et iam nunc <b>seratum</b> - - ClientModel - - Network Alert - Monitio Retis - - CoinControlDialog @@ -387,26 +261,6 @@ Confirmed Confirmatum - - Copy address - Copia inscriptionem - - - Copy label - Copia titulum - - - Copy amount - Copia quantitatem - - - Copy transaction ID - Copia transactionis ID - - - (no label) - (nullus titulus) - EditAddressDialog @@ -422,48 +276,12 @@ &Address &Inscriptio - - New receiving address - Nova inscriptio accipiendi - - - New sending address - Nova inscriptio mittendi - - - Edit receiving address - Muta inscriptionem accipiendi - - - Edit sending address - Muta inscriptionem mittendi - - - The entered address "%1" is already in the address book. - Inserta inscriptio "%1" iam in libro inscriptionum est. - - - The entered address "%1" is not a valid Bitcoin address. - Inscriptio inserta "%1" non valida inscriptio Bitcoin est. - - - Could not unlock wallet. - Non potuisse cassidile reserare - - - New key generation failed. - Generare novam clavem abortum est. - FreespaceChecker HelpMessageDialog - - Bitcoin Core - Bitcoin Nucleus - version versio @@ -483,10 +301,6 @@ Intro - - Bitcoin Core - Bitcoin Nucleus - Error Error @@ -613,17 +427,6 @@ Fossum pendendum quod nondum maturum est - - PaymentServer - - URI handling - Tractatio URI - - - Cannot start bitcoin: click-to-pay handler - Bitcoin incipere non potest: cliccare-ad-pensandum handler - - PeerTableModel @@ -638,13 +441,6 @@ N/A - - QRImageWidget - - Save QR Code - Salva codicem QR - - RPCConsole @@ -699,10 +495,6 @@ &Console &Terminale - - Build date - Dies aedificandi - Debug log file Debug catalogi plica @@ -734,68 +526,13 @@ &Message: Nuntius: - - Copy label - Copia titulum - - - Copy amount - Copia quantitatem - - + ReceiveRequestDialog Copy &Address &Copia Inscriptionem - - Address - Inscriptio - - - Amount - Quantitas - - - Label - Titulus - - - Message - Nuntius - - - Resulting URI too long, try to reduce the text for label / message. - Resultato URI nimis longo, conare minuere verba pro titulo / nuntio. - - - Error encoding URI into QR Code. - Error codificandi URI in codicem QR. - - - - RecentRequestsTableModel - - Date - Dies - - - Label - Titulus - - - Message - Nuntius - - - Amount - Quantitas - - - (no label) - (nullus titulus) - SendCoinsDialog @@ -839,31 +576,7 @@ S&end &Mitte - - Confirm send coins - Confirma mittendum nummorum - - - Copy amount - Copia quantitatem - - - The amount to pay must be larger than 0. - Oportet quantitatem ad pensandum maiorem quam 0 esse. - - - The amount exceeds your balance. - Quantitas est ultra quod habes. - - - The total exceeds your balance when the %1 transaction fee is included. - Quantitas est ultra quod habes cum merces transactionis %1 includitur. - - - (no label) - (nullus titulus) - - + SendCoinsEntry @@ -874,10 +587,6 @@ Pay &To: Pensa &Ad: - - Enter a label for this address to add it to your address book - Insero titulum huic inscriptioni ut eam in tuum librum inscriptionum addas. - &Label: &Titulus: @@ -972,65 +681,9 @@ Reset all verify message fields Reconstitue omnes campos verificandi nuntii - - Click "Sign Message" to generate signature - Clicca "Signa Nuntium" ut signatio generetur - - - The entered address is invalid. - Inscriptio inserta non valida est. - - - Please check the address and try again. - Sodes inscriptionem proba et rursus conare. - - - The entered address does not refer to a key. - Inserta inscriptio clavem non refert. - - - Wallet unlock was cancelled. - Cassidilis reserare cancellatum est. - - - Private key for the entered address is not available. - Clavis privata absens est pro inserta inscriptione. - - - Message signing failed. - Nuntium signare abortum est. - - - Message signed. - Nuntius signatus. - - - The signature could not be decoded. - Signatio decodificari non potuit. - - - Please check the signature and try again. - Sodes signationem proba et rursus conare. - - - The signature did not match the message digest. - Signatio non convenit digesto nuntii - - - Message verification failed. - Nuntium verificare abortum est. - - - Message verified. - Nuntius verificatus. - SplashScreen - - Bitcoin Core - Bitcoin Nucleus - [testnet] [testnet] @@ -1039,362 +692,16 @@ TrafficGraphWidget - - TransactionDesc - - Open until %1 - Apertum donec %1 - - - %1/offline - %1/non conecto - - - %1/unconfirmed - %1/non confirmata - - - %1 confirmations - %1 confirmationes - - - Status - Status - - - Date - Dies - - - Source - Fons - - - Generated - Generatum - - - From - Ab - - - To - Ad - - - own address - inscriptio propria - - - label - titulus - - - Credit - Creditum - - - not accepted - non acceptum - - - Debit - Debitum - - - Transaction fee - Transactionis merces - - - Net amount - Cuncta quantitas - - - Message - Nuntius - - - Comment - Annotatio - - - Transaction ID - ID transactionis - - - Debug information - Informatio de debug - - - Transaction - Transactio - - - Inputs - Lectenda - - - Amount - Quantitas - - - true - verum - - - false - falsum - - - , has not been successfully broadcast yet - , nondum prospere disseminatum est - - - unknown - ignotum - - TransactionDescDialog - - Transaction details - Particularia transactionis - This pane shows a detailed description of the transaction Haec tabula monstrat descriptionem verbosam transactionis - - TransactionTableModel - - Date - Dies - - - Type - Typus - - - Open until %1 - Apertum donec %1 - - - Confirmed (%1 confirmations) - Confirmatum (%1 confirmationes) - - - This block was not received by any other nodes and will probably not be accepted! - Hoc frustum non acceptum est ab ulla alia nodis et probabiliter non acceptum erit! - - - Generated but not accepted - Generatum sed non acceptum - - - Label - Titulus - - - Received with - Acceptum cum - - - Received from - Acceptum ab - - - Sent to - Missum ad - - - Payment to yourself - Pensitatio ad te ipsum - - - Mined - Fossa - - - (n/a) - (n/a) - - - Transaction status. Hover over this field to show number of confirmations. - Status transactionis. Supervola cum mure ut monstretur numerus confirmationum. - - - Date and time that the transaction was received. - Dies et tempus quando transactio accepta est. - - - Type of transaction. - Typus transactionis. - - - Amount removed from or added to balance. - Quantitas remota ex pendendo aut addita ei. - - - - TransactionView - - All - Omne - - - Today - Hodie - - - This week - Hac hebdomade - - - This month - Hoc mense - - - Last month - Postremo mense - - - This year - Hoc anno - - - Range... - Intervallum... - - - Received with - Acceptum cum - - - Sent to - Missum ad - - - To yourself - Ad te ipsum - - - Mined - Fossa - - - Other - Alia - - - Enter address or label to search - Insere inscriptionem vel titulum ut quaeras - - - Min amount - Quantitas minima - - - Copy address - Copia inscriptionem - - - Copy label - Copia titulum - - - Copy amount - Copia quantitatem - - - Copy transaction ID - Copia transactionis ID - - - Edit label - Muta titulum - - - Show transaction details - Monstra particularia transactionis - - - Comma separated file (*.csv) - Comma Separata Plica (*.csv) - - - Confirmed - Confirmatum - - - Date - Dies - - - Type - Typus - - - Label - Titulus - - - Address - Inscriptio - - - ID - ID - - - Range: - Intervallum: - - - to - ad - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - Send Coins - Mitte Nummos - - - - WalletView - - &Export - &Exporta - - - Export the data in the current tab to a file - Exporta data in hac tabella in plicam - - - Backup Wallet - Conserva cassidile - - - Wallet Data (*.dat) - Data cassidilis (*.dat) - - - Backup Failed - Conservare abortum est. - - - Backup Successful - Successum in conservando - - bitcoin-core @@ -1425,6 +732,10 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Accipe conexiones externas (praedefinitum: 1 nisi -proxy neque -connect) + + Bitcoin Core + Bitcoin Nucleus + Bind to given address and always listen on it. Use [host]:port notation for IPv6 Conglutina ad inscriptionem datam et semper in eam ausculta. Utere [moderatrum]:porta notationem pro IPv6 @@ -1437,10 +748,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Hoc est prae-dimittum experimentala aedes - utere eo periculo tuo proprio - nolite utere fodendo vel applicationibus mercatoriis - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Monitio: wallet.data corrupta, data salvata! Originalis wallet.dat salvata ut wallet.{timestamp}.bak in %s; si pendendum tuum vel transactiones pravae sunt, oportet ab conservato restituere. - Block creation options: Optiones creandi frustorum: @@ -1493,26 +800,10 @@ Verifying wallet... Verificante cassidilem... - - Cannot resolve -whitebind address: '%s' - Non posse resolvere -whitebind inscriptionem: '%s' - Information Informatio - - Invalid amount for -maxtxfee=<amount>: '%s' - Quantitas non valida pro -maxtxfee=<amount>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Quantitas non valida pro -minrelaytxfee=<amount>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - Quantitas non valida pro -mintxfee=<amount>: '%s' - Send trace/debug info to console instead of debug.log file Mitte informationem vestigii/debug ad terminale potius quam plicam debug.log @@ -1545,10 +836,6 @@ Warning Monitio - - wallet.dat corrupt, salvage failed - wallet.dat corrupta, salvare abortum est - Password for JSON-RPC connections Tessera pro conexionibus JSON-RPC @@ -1557,10 +844,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) Pelle mandatum quando optissimum frustum mutat (%s in mandato substituitur ab hash frusti) - - This help message - Hic nuntius auxilii - Allow DNS lookups for -addnode, -seednode and -connect Permitte quaerenda DNS pro -addnode, -seednode, et -connect @@ -1569,14 +852,6 @@ Loading addresses... Legens inscriptiones... - - Error loading wallet.dat: Wallet corrupted - Error legendi wallet.dat: Cassidile corruptum - - - Error loading wallet.dat - Error legendi wallet.dat - Invalid -proxy address: '%s' Inscriptio -proxy non valida: '%s' @@ -1585,18 +860,6 @@ Unknown network specified in -onlynet: '%s' Ignotum rete specificatum in -onlynet: '%s' - - Cannot resolve -bind address: '%s' - Non posse resolvere -bind inscriptonem: '%s' - - - Cannot resolve -externalip address: '%s' - Non posse resolvere -externalip inscriptionem: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - Quantitas non valida pro -paytxfee=<quantitas>: '%s' - Insufficient funds Inopia nummorum diff --git a/src/qt/locale/bitcoin_lt.ts b/src/qt/locale/bitcoin_lt.ts index 873a6939b7a5c..9e98baa77af73 100644 --- a/src/qt/locale/bitcoin_lt.ts +++ b/src/qt/locale/bitcoin_lt.ts @@ -25,10 +25,6 @@ C&lose &Užverti - - &Copy Address - &Kopijuoti adresą - Delete the currently selected address from the list Ištrinti pasirinktą adresą iš sąrašo @@ -45,73 +41,6 @@ &Delete &Trinti - - Choose the address to send coins to - Pasirinkite adresą kuriam siūsite monetas - - - Choose the address to receive coins with - Pasirinkite adresą su kuriuo gauti monetas - - - C&hoose - P&asirinkti - - - Sending addresses - Siunčiami adresai - - - Receiving addresses - Gaunami adresai - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Tai yra jūsų Bitcoin adresai mokėjimų siuntimui. Visada patikrinkite siunčiamą sumą ir gavėjo adresą prieš siųsdami monetas. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Tai yra jūsų Bitcoin adresai mokėjimų gavimui. Rekomenduojame naudoti naujus gavimo adresus kiekvienai tranzakcijai. - - - Copy &Label - Kopijuoti ž&ymę - - - &Edit - &Keisti - - - Export Address List - Eksportuoti adresų sąrašą - - - Comma separated file (*.csv) - Kableliais atskirtų duomenų failas (*.csv) - - - Exporting Failed - Eksportavimas nepavyko - - - There was an error trying to save the address list to %1. Please try again. - Bandant išsaugoti adresų sąrašą - įvyko klaida keliant į %1. Prašome bandyti dar kartą. - - - - AddressTableModel - - Label - Žymė - - - Address - Adresas - - - (no label) - (nėra žymės) - AskPassphraseDialog @@ -131,78 +60,6 @@ Repeat new passphrase Pakartokite naują slaptafrazę - - Encrypt wallet - Užšifruoti piniginę - - - This operation needs your wallet passphrase to unlock the wallet. - Ši operacija reikalauja jūsų piniginės slaptafrazės jai atrakinti. - - - Unlock wallet - Atrakinti piniginę - - - This operation needs your wallet passphrase to decrypt the wallet. - Ši operacija reikalauja jūsų piniginės slaptafrazės jai iššifruoti. - - - Decrypt wallet - Iššifruoti piniginę - - - Change passphrase - Pakeisti slaptafrazę - - - Confirm wallet encryption - Patvirtinkite piniginės užšifravimą - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Dėmesio: jei užšifruosite savo piniginę ir pamesite slaptafrazę, jūs<b>PRARASITE VISUS SAVO BITCOINUS</b>! - - - Are you sure you wish to encrypt your wallet? - Ar tikrai norite šifruoti savo piniginę? - - - Warning: The Caps Lock key is on! - Įspėjimas: įjungtas Caps Lock klavišas! - - - Wallet encrypted - Piniginė užšifruota - - - Wallet encryption failed - Nepavyko užšifruoti piniginę - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Dėl vidinės klaidos nepavyko užšifruoti piniginę.Piniginė neužšifruota. - - - The supplied passphrases do not match. - Įvestos slaptafrazės nesutampa. - - - Wallet unlock failed - Nepavyko atrakinti piniginę - - - The passphrase entered for the wallet decryption was incorrect. - Neteisingai įvestas slaptažodis piniginės iššifravimui. - - - Wallet decryption failed - Nepavyko iššifruoti piniginės - - - Wallet passphrase was successfully changed. - Piniginės slaptažodis sėkmingai pakeistas. - BanTableModel @@ -249,6 +106,10 @@ Quit application Išjungti programą + + &About %1 + &Apie %1 + About &Qt Apie &Qt @@ -285,14 +146,6 @@ Open &URI... Atidaryti &URI... - - Bitcoin Core client - Bitcoin Core klientas - - - Importing blocks from disk... - Blokai importuojami iš disko... - Reindexing blocks on disk... Blokai iš naujo indeksuojami... @@ -337,10 +190,6 @@ &Receive &Gauti - - Show information about Bitcoin Core - Rodyti informaciją apie Bitcoin Core - &Show / Hide &Rodyti / Slėpti @@ -369,14 +218,6 @@ Tabs toolbar Kortelių įrankinė - - Bitcoin Core - Bitcoin branduolys - - - &About Bitcoin Core - &Apie Bitcoin Core - &Command-line options Komandinės eilutės parametrai @@ -418,13 +259,6 @@ Piniginė <b>užšifruota</b> ir šiuo metu <b>užrakinta</b> - - ClientModel - - Network Alert - Tinklo įspėjimas - - CoinControlDialog @@ -491,94 +325,6 @@ Priority Pirmumas - - Copy address - Kopijuoti adresą - - - Copy label - Kopijuoti žymę - - - Copy amount - Kopijuoti sumą - - - Copy quantity - Kopijuoti kiekį - - - Copy fee - Kopijuoti mokestį - - - Copy after fee - Kopijuoti po mokesčio - - - Copy bytes - Kopijuoti baitus - - - Copy priority - Kopijuoti pirmumą - - - highest - auksčiausias - - - higher - aukštesnis - - - high - aukštas - - - medium-high - vidutiniškai aukštas - - - medium - vidutiniškai - - - low-medium - žemai-vidutiniškas - - - low - žemas - - - lower - žemesnis - - - lowest - žemiausias - - - none - niekas - - - yes - taip - - - no - ne - - - (no label) - (nėra žymės) - - - (change) - (Graža) - EditAddressDialog @@ -594,38 +340,6 @@ &Address &Adresas - - New receiving address - Naujas gavimo adresas - - - New sending address - Naujas siuntimo adresas - - - Edit receiving address - Keisti gavimo adresą - - - Edit sending address - Keisti siuntimo adresą - - - The entered address "%1" is already in the address book. - Įvestas adresas „%1“ jau yra adresų knygelėje. - - - The entered address "%1" is not a valid Bitcoin address. - Įvestas adresas „%1“ nėra galiojantis Bitcoin adresas. - - - Could not unlock wallet. - Nepavyko atrakinti piniginės. - - - New key generation failed. - Naujo rakto generavimas nepavyko. - FreespaceChecker @@ -636,18 +350,10 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin branduolys - version versija - - About Bitcoin Core - Apie Bitcoin Core - Command-line options Komandinės eilutės parametrai @@ -667,14 +373,6 @@ Welcome Sveiki - - Welcome to Bitcoin Core. - Sveiki atvykę į Bitcoin Core. - - - Bitcoin Core - Bitcoin branduolys - Error Klaida @@ -841,29 +539,6 @@ Jūsų balansas - - PaymentServer - - URI handling - URI apdorojimas - - - Invalid payment address %1 - Neteisingas mokėjimo adresas %1 - - - Payment request rejected - Mokėjimo siuntimas atmestas - - - Payment request expired. - Mokėjimo siuntimas pasibaigė - - - Network request error - Tinklo užklausos klaida - - PeerTableModel @@ -886,21 +561,6 @@ nėra - - QRImageWidget - - &Copy Image - Kopijuoti nuotrauką - - - Save QR Code - Įrašyti QR kodą - - - PNG Image (*.png) - PNG paveikslėlis (*.png) - - RPCConsole @@ -979,10 +639,6 @@ Totals Viso: - - Build date - Kompiliavimo data - Debug log file Derinimo žurnalo failas @@ -1038,15 +694,7 @@ Clear Išvalyti - - Copy label - Kopijuoti žymę - - - Copy amount - Kopijuoti sumą - - + ReceiveRequestDialog @@ -1057,53 +705,6 @@ Copy &Address &Kopijuoti adresą - - Payment information - Mokėjimo informacija - - - Address - Adresas - - - Amount - Suma - - - Label - Žymė - - - Message - Žinutė - - - Error encoding URI into QR Code. - Klaida, koduojant URI į QR kodą. - - - - RecentRequestsTableModel - - Date - Data - - - Label - Žymė - - - Message - Žinutė - - - Amount - Suma - - - (no label) - (nėra žymės) - SendCoinsDialog @@ -1171,55 +772,7 @@ S&end &Siųsti - - Confirm send coins - Patvirtinti monetų siuntimą - - - Copy quantity - Kopijuoti kiekį - - - Copy amount - Kopijuoti sumą - - - Copy fee - Kopijuoti mokestį - - - Copy after fee - Kopijuoti po mokesčio - - - Copy bytes - Kopijuoti baitus - - - Copy priority - Kopijuoti pirmumą - - - The amount to pay must be larger than 0. - Apmokėjimo suma turi būti didesnė nei 0. - - - The amount exceeds your balance. - Suma viršija jūsų balansą. - - - The total exceeds your balance when the %1 transaction fee is included. - Jei pridedame sandorio mokestį %1 bendra suma viršija jūsų balansą. - - - Payment request expired. - Mokėjimo siuntimas pasibaigė - - - (no label) - (nėra žymės) - - + SendCoinsEntry @@ -1230,10 +783,6 @@ Pay &To: Mokėti &gavėjui: - - Enter a label for this address to add it to your address book - Įveskite žymę šiam adresui kad galėtumėte įtraukti ją į adresų knygelę - &Label: Ž&ymė: @@ -1308,57 +857,9 @@ Verify &Message &Patikrinti žinutę - - Click "Sign Message" to generate signature - Spragtelėkite "Registruotis žinutę" tam, kad gauti parašą - - - The entered address is invalid. - Įvestas adresas negalioja. - - - Please check the address and try again. - Prašom patikrinti adresą ir bandyti iš naujo. - - - Wallet unlock was cancelled. - Piniginės atrakinimas atšauktas. - - - Message signing failed. - Žinutės pasirašymas nepavyko. - - - Message signed. - Žinutė pasirašyta. - - - The signature could not be decoded. - Nepavyko iškoduoti parašo. - - - Please check the signature and try again. - Prašom patikrinti parašą ir bandyti iš naujo. - - - The signature did not match the message digest. - Parašas neatitinka žinutės. - - - Message verification failed. - Žinutės tikrinimas nepavyko. - - - Message verified. - Žinutė patikrinta. - - + SplashScreen - - Bitcoin Core - Bitcoin branduolys - [testnet] [testavimotinklas] @@ -1371,358 +872,16 @@ KB/s - - TransactionDesc - - Open until %1 - Atidaryta iki %1 - - - %1/offline - %1/neprisijungęs - - - %1/unconfirmed - %1/nepatvirtintas - - - %1 confirmations - %1 patvirtinimų - - - Status - Būsena - - - Date - Data - - - Source - Šaltinis - - - Generated - Sugeneruotas - - - From - Nuo - - - To - Kam - - - own address - savo adresas - - - label - žymė - - - Credit - Kreditas - - - not accepted - nepriimta - - - Debit - Debitas - - - Transaction fee - Sandorio mokestis - - - Net amount - Neto suma - - - Message - Žinutė - - - Comment - Komentaras - - - Transaction ID - Sandorio ID - - - Debug information - Derinimo informacija - - - Transaction - Sandoris - - - Amount - Suma - - - true - tiesa - - - false - netiesa - - - , has not been successfully broadcast yet - , transliavimas dar nebuvo sėkmingas - - - unknown - nežinomas - - TransactionDescDialog - - Transaction details - Sandorio detelės - This pane shows a detailed description of the transaction Šis langas sandorio detalų aprašymą - - TransactionTableModel - - Date - Data - - - Type - Tipas - - - Open until %1 - Atidaryta iki %1 - - - Confirmed (%1 confirmations) - Patvirtinta (%1 patvirtinimai) - - - This block was not received by any other nodes and will probably not be accepted! - Šis blokas negautas nė vienu iš mazgų ir matomai nepriimtas - - - Generated but not accepted - Išgauta bet nepriimta - - - Label - Žymė - - - Received with - Gauta su - - - Received from - Gauta iš - - - Sent to - Išsiųsta - - - Payment to yourself - Mokėjimas sau - - - Mined - Išgauta - - - (n/a) - nepasiekiama - - - Transaction status. Hover over this field to show number of confirmations. - Sandorio būklė. Užvedus pelės žymeklį ant šios srities matysite patvirtinimų skaičių. - - - Date and time that the transaction was received. - Sandorio gavimo data ir laikas - - - Type of transaction. - Sandorio tipas. - - - Amount removed from or added to balance. - Suma pridėta ar išskaičiuota iš balanso - - - - TransactionView - - All - Visi - - - Today - Šiandien - - - This week - Šią savaitę - - - This month - Šį mėnesį - - - Last month - Paskutinį mėnesį - - - This year - Šiais metais - - - Range... - Intervalas... - - - Received with - Gauta su - - - Sent to - Išsiųsta - - - To yourself - Skirta sau - - - Mined - Išgauta - - - Other - Kita - - - Enter address or label to search - Įveskite adresą ar žymę į paiešką - - - Min amount - Minimali suma - - - Copy address - Kopijuoti adresą - - - Copy label - Kopijuoti žymę - - - Copy amount - Kopijuoti sumą - - - Edit label - Taisyti žymę - - - Show transaction details - Rodyti sandėrio detales - - - Exporting Failed - Eksportavimas nepavyko - - - Comma separated file (*.csv) - Kableliais atskirtų duomenų failas (*.csv) - - - Confirmed - Patvirtintas - - - Date - Data - - - Type - Tipas - - - Label - Žymė - - - Address - Adresas - - - ID - ID - - - Range: - Grupė: - - - to - skirta - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - Send Coins - Siųsti monetas - - - - WalletView - - &Export - &Eksportuoti - - - Export the data in the current tab to a file - Eksportuoti informaciją iš dabartinės lentelės į failą - - - Backup Wallet - Backup piniginę - - - Wallet Data (*.dat) - Piniginės duomenys (*.dat) - - - Backup Failed - Nepavyko padaryti atsarginės kopijos - - - Backup Successful - Atsarginė kopija sėkmingai padaryta - - bitcoin-core @@ -1745,6 +904,10 @@ Run in the background as a daemon and accept commands Dirbti fone kaip šešėlyje ir priimti komandas + + Bitcoin Core + Bitcoin branduolys + Connect only to the specified node(s) Prisijungti tik prie nurodyto mazgo @@ -1765,18 +928,6 @@ Information Informacija - - Invalid amount for -maxtxfee=<amount>: '%s' - Neteisinga suma -maxtxfee=<amount>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Neteisinga suma -minrelaytxfee=<amount>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - Neteisinga suma -mintxfee=<amount>: '%s' - Send trace/debug info to console instead of debug.log file Siųsti atsekimo/derinimo info į konsolę vietoj debug.log failo @@ -1793,10 +944,6 @@ Password for JSON-RPC connections Slaptažodis JSON-RPC sujungimams - - This help message - Pagelbos žinutė - Allow DNS lookups for -addnode, -seednode and -connect Leisti DNS paiešką sujungimui ir mazgo pridėjimui @@ -1805,22 +952,10 @@ Loading addresses... Užkraunami adresai... - - Error loading wallet.dat: Wallet corrupted - wallet.dat pakrovimo klaida, wallet.dat sugadintas - - - Error loading wallet.dat - wallet.dat pakrovimo klaida - Invalid -proxy address: '%s' Neteisingas proxy adresas: '%s' - - Invalid amount for -paytxfee=<amount>: '%s' - Neteisinga suma -paytxfee=<amount>: '%s' - Insufficient funds Nepakanka lėšų diff --git a/src/qt/locale/bitcoin_lv_LV.ts b/src/qt/locale/bitcoin_lv_LV.ts index 5a59184b0cef8..bac58756952ab 100644 --- a/src/qt/locale/bitcoin_lv_LV.ts +++ b/src/qt/locale/bitcoin_lv_LV.ts @@ -21,10 +21,6 @@ C&lose &Aizvērt - - &Copy Address - &Kopēt adresi - Delete the currently selected address from the list Izdzēst iezīmētās adreses no saraksta @@ -41,73 +37,6 @@ &Delete &Dzēst - - Choose the address to send coins to - Izvēlies adresi uz kuru sūtīt bitcoins - - - Choose the address to receive coins with - Izvēlies adresi ar kuru saņemt bitcoins - - - C&hoose - &Izvēlēties - - - Sending addresses - Sūtīšanas adreses - - - Receiving addresses - Saņemšanas adreses - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Šīs ir jūsu Bitcoin adreses maksājumu sūtīšanai. Vienmēr pārbaudiet summu un saņēmēja adresi pirms monētu sūtīšanas. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Šīs ir jūsu Bitcoin adreses maksājumu saņemšanai. Ir ieteicams katram darījumam izmantot jaunu saņemšanas adresi. - - - Copy &Label - Kopēt &Nosaukumu - - - &Edit - &Rediģēt - - - Export Address List - Eksportēt Adrešu Sarakstu - - - Comma separated file (*.csv) - Fails ar komatu kā atdalītāju (*.csv) - - - Exporting Failed - Eksportēšana Neizdevās - - - There was an error trying to save the address list to %1. Please try again. - Radās kļūda, saglabājot adrešu sarakstu %1. Lūdzu, mēģiniet vēlreiz! - - - - AddressTableModel - - Label - Nosaukums - - - Address - Adrese - - - (no label) - (bez nosaukuma) - AskPassphraseDialog @@ -127,90 +56,6 @@ Repeat new passphrase Jaunā parole vēlreiz - - Encrypt wallet - Šifrēt maciņu - - - This operation needs your wallet passphrase to unlock the wallet. - Lai veikto šo darbību, maciņš jāatslēdz ar paroli. - - - Unlock wallet - Atslēgt maciņu - - - This operation needs your wallet passphrase to decrypt the wallet. - Šai darbībai maciņš jāatšifrē ar maciņa paroli. - - - Decrypt wallet - Atšifrēt maciņu - - - Change passphrase - Mainīt paroli - - - Confirm wallet encryption - Apstiprināt maciņa šifrēšanu - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Brīdinājums: Ja tu nošifrē savu maciņu un pazaudē paroli, tu <b>PAZAUDĒSI VISAS SAVAS BITCOINS</b>! - - - Are you sure you wish to encrypt your wallet? - Vai tu tiešām vēlies šifrēt savu maciņu? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Bitcoin Core tiks aizvērts, lai pabeigtu šifrēšansa procesu. Atcerieties, ka jūsu maka šifrēšana nevar pilnībā pasargāt jūsu monētas no to nozagašanas, inficējot datoru ar ļaunprātīgām programmām. - - - 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. - SVARĪGI: Iepriekšējie maka faila dublējumi ir jāaizvieto ar jauno, šifrēto maka failu. Drošības apsvērumu dēļ iepriekšējie nešifrētā maka dublējumi vairs nebūs derīgi, tiklīdz sāksiet izmantot jauno, šifrēto maku. - - - Warning: The Caps Lock key is on! - Brīdinājums: Caps Lock ir ieslēgts! - - - Wallet encrypted - Maciņš nošifrēts - - - Enter the old passphrase and new passphrase to the wallet. - Ievadiet veco un jauno maka paroli. - - - Wallet encryption failed - Maciņa šifrēšana neizdevās - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Maciņa šifrēšana neizdevās programmas kļūdas dēļ. Jūsu maciņš netika šifrēts. - - - The supplied passphrases do not match. - Ievadītās paroles nav vienādas. - - - Wallet unlock failed - Maciņu atšifrēt neizdevās - - - The passphrase entered for the wallet decryption was incorrect. - Maciņa atšifrēšanai ievadītā parole nav pareiza. - - - Wallet decryption failed - Maciņu neizdevās atšifrēt - - - Wallet passphrase was successfully changed. - Maciņa parole tika veiksmīgi nomainīta. - BanTableModel @@ -289,14 +134,6 @@ Open &URI... Atvērt &URI... - - Bitcoin Core client - Bitcoin Core klients - - - Importing blocks from disk... - Importē blokus no diska... - Reindexing blocks on disk... Bloku reindeksēšana no diska... @@ -341,10 +178,6 @@ &Receive &Saņemt - - Show information about Bitcoin Core - Parādīt informāciju par Bitcoin Core - &Show / Hide &Rādīt / Paslēpt @@ -381,18 +214,10 @@ Tabs toolbar Ciļņu rīkjosla - - Bitcoin Core - Bitcoin Core - Request payments (generates QR codes and bitcoin: URIs) Pieprasīt maksājumus (izveido QR kodu un bitcoin: URIs) - - &About Bitcoin Core - Par &Bitcoin Core - Open a bitcoin: URI or payment request Atvērt bitcoin URI vai maksājuma pieprasījumu @@ -454,13 +279,6 @@ Maciņš ir <b>šifrēts</b> un pašlaik <b>slēgts</b> - - ClientModel - - Network Alert - Tīkla brīdinājums - - CoinControlDialog @@ -523,118 +341,6 @@ Priority Prioritāte - - Copy address - Kopēt adresi - - - Copy label - Kopēt nosaukumu - - - Copy amount - Kopēt daudzumu - - - Copy transaction ID - Kopēt transakcijas ID - - - Lock unspent - Aizslēgt neiztērēto - - - Unlock unspent - Atslēgt neiztērēto - - - Copy quantity - Kopēt daudzumu - - - Copy fee - Kopēt maksu - - - Copy after fee - Kopēt pēc maksas - - - Copy bytes - Kopēt baitus - - - Copy priority - Kopēt prioritāti - - - Copy change - Kopēt atlikumu - - - highest - augstākais - - - higher - augstāks - - - high - augsts - - - medium-high - vidēji-augsts - - - medium - vidējs - - - low-medium - zemi-vidējs - - - low - zems - - - lower - zemāks - - - lowest - zemākais - - - (%1 locked) - (%1 aizslēgts) - - - none - neviena - - - yes - - - - no - - - - (no label) - (bez nosaukuma) - - - change from %1 (%2) - atlikums no %1 (%2) - - - (change) - (atlikums) - EditAddressDialog @@ -650,38 +356,6 @@ &Address &Adrese - - New receiving address - Jauna saņemšanas adrese - - - New sending address - Jauna nosūtīšanas adrese - - - Edit receiving address - Mainīt saņemšanas adresi - - - Edit sending address - Mainīt nosūtīšanas adresi - - - The entered address "%1" is already in the address book. - Nupat ierakstītā adrese "%1" jau atrodas adrešu grāmatā. - - - The entered address "%1" is not a valid Bitcoin address. - Ierakstītā adrese "%1" nav derīga Bitcoin adrese. - - - Could not unlock wallet. - Nav iespējams atslēgt maciņu. - - - New key generation failed. - Neizdevās ģenerēt jaunu atslēgu. - FreespaceChecker @@ -704,10 +378,6 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin Core - version versija @@ -716,10 +386,6 @@ (%1-bit) (%1-biti) - - About Bitcoin Core - Par Bitcoin Core - Command-line options Komandrindas iespējas @@ -739,10 +405,6 @@ Welcome Sveiciens - - Welcome to Bitcoin Core. - Sveicināts Bitcoin Core - Use the default data directory Izmantot noklusēto datu mapi @@ -751,10 +413,6 @@ Use a custom data directory: Izmantot pielāgotu datu mapi: - - Bitcoin Core - Bitcoin Core - Error Kļūda @@ -778,10 +436,6 @@ Select payment request file Izvēlies maksājuma pieprasījuma datni - - Select payment request file to open - Izvēlies maksājuma pieprasījuma datni lai atvēru - OptionsDialog @@ -973,45 +627,6 @@ Jūsu kopējā tekošā bilance - - PaymentServer - - URI handling - URI apstrāde - - - Invalid payment address %1 - Nederīga maksājuma adrese %1 - - - Payment request rejected - Maksājuma pieprasījums noraidīts - - - Payment request network doesn't match client network. - Maksājuma pieprasījuma tīkls neatbilst klienta tīklam. - - - Payment request error - Maksājumu pieprasījuma kļūda - - - Cannot start bitcoin: click-to-pay handler - Nevar palaist Bitcoin: nospied-lai-maksātu apstrādātāju - - - Refund from %1 - Atmaksa no %1 - - - Payment acknowledged - Maksājums atzīts - - - Network request error - Tīkla pieprasījuma kļūda - - PeerTableModel @@ -1034,25 +649,6 @@ N/A - - QRImageWidget - - &Save Image... - &Saglabāt Attēlu... - - - &Copy Image - &Kopēt Attēlu - - - Save QR Code - Saglabāt QR kodu - - - PNG Image (*.png) - PNG Attēls (*.png) - - RPCConsole @@ -1135,10 +731,6 @@ Out: Iz.: - - Build date - Kompilācijas datums - Debug log file Atkļūdošanas žurnāla datne @@ -1222,18 +814,6 @@ Remove Noņemt - - Copy label - Kopēt nosaukumu - - - Copy message - Kopēt ziņojumu - - - Copy amount - Kopēt daudzumu - ReceiveRequestDialog @@ -1253,123 +833,56 @@ &Save Image... &Saglabāt Attēlu... + + + SendCoinsDialog - Request payment to %1 - Pieprasīt maksājumu uz %1 + Send Coins + Sūtīt Bitkoinus - Payment information - Maksājuma informācija + Coin Control Features + Bitcoin Kontroles Funkcijas - URI - URI + Inputs... + Ieejas... - Address - Adrese + automatically selected + automātiski atlasīts - Amount - Daudzums + Insufficient funds! + Nepietiekami līdzekļi! - Label - Nosaukums + Quantity: + Daudzums: - Message - Ziņojums + Bytes: + Baiti: - Resulting URI too long, try to reduce the text for label / message. - Rezultāta URI pārāk garš, mēģiniet saīsināt nosaukumu vai ziņojumu. + Amount: + Daudzums: - Error encoding URI into QR Code. - Kļūda kodējot URI QR kodā. + Priority: + Prioritāte: - - - RecentRequestsTableModel - Date - Datums + Fee: + Maksa: - Label - Nosaukums + After Fee: + Pēc Maksas: - Message - Ziņojums - - - Amount - Daudzums - - - (no label) - (bez nosaukuma) - - - (no message) - (nav ziņojuma) - - - (no amount) - (nav summas) - - - - SendCoinsDialog - - Send Coins - Sūtīt Bitkoinus - - - Coin Control Features - Bitcoin Kontroles Funkcijas - - - Inputs... - Ieejas... - - - automatically selected - automātiski atlasīts - - - Insufficient funds! - Nepietiekami līdzekļi! - - - Quantity: - Daudzums: - - - Bytes: - Baiti: - - - Amount: - Daudzums: - - - Priority: - Prioritāte: - - - Fee: - Maksa: - - - After Fee: - Pēc Maksas: - - - Change: - Atlikums: + Change: + Atlikums: Custom change address @@ -1407,78 +920,6 @@ S&end &Sūtīt - - Confirm send coins - Apstiprināt bitkoinu sūtīšanu - - - %1 to %2 - %1 līdz %2 - - - Copy quantity - Kopēt daudzumu - - - Copy amount - Kopēt daudzumu - - - Copy fee - Kopēt maksu - - - Copy after fee - Kopēt pēc maksas - - - Copy bytes - Kopēt baitus - - - Copy priority - Kopēt prioritāti - - - Copy change - Kopēt atlikumu - - - or - vai - - - The amount to pay must be larger than 0. - Nosūtāmajai summai jābūt lielākai par 0. - - - The amount exceeds your balance. - Daudzums pārsniedz pieejamo. - - - The total exceeds your balance when the %1 transaction fee is included. - Kopsumma pārsniedz pieejamo, ja pieskaitīta %1 transakcijas maksa. - - - Transaction creation failed! - Transakcijas izveidošana neizdevās! - - - Warning: Invalid Bitcoin address - Brīdinājums: Nederīga Bitcoin adrese - - - (no label) - (bez nosaukuma) - - - Warning: Unknown change address - Brīdinājums: Nezināma atlikuma adrese - - - added as transaction fee - pievienots kā transakcijas maksa - SendCoinsEntry @@ -1490,10 +931,6 @@ Pay &To: &Saņēmējs: - - Enter a label for this address to add it to your address book - Lai pievienotu adresi adrešu grāmatai, tai jādod nosaukums - &Label: &Nosaukums: @@ -1537,10 +974,6 @@ ShutdownWindow - - Bitcoin Core is shutting down... - Bitcoin Core tiek izslēgta... - Do not shut down the computer until this window disappears. Neizslēdziet datoru kamēr šis logs nepazūd. @@ -1612,69 +1045,9 @@ Reset all verify message fields Atiestatīt visus laukus - - Click "Sign Message" to generate signature - Nospied "Parakstīt Ziņojumu" lai ģenerētu parakstu - - - The entered address is invalid. - Ievadītā adrese ir nederīga. - - - Please check the address and try again. - Lūdzu pārbaudi adresi un mēģini vēlreiz. - - - The entered address does not refer to a key. - Ievadītā adrese neattiecas uz atslēgu. - - - Wallet unlock was cancelled. - Maciņa atslēgšana tika atcelta. - - - Private key for the entered address is not available. - Privātā atslēga priekš ievadītās adreses nav pieejama. - - - Message signing failed. - Neizdevās parakstīt ziņojumu. - - - Message signed. - Ziņojums parakstīts. - - - The signature could not be decoded. - Paraksts nevarēja tikt dekodēts. - - - Please check the signature and try again. - Lūdzu pārbaudi parakstu un mēģini vēlreiz. - - - The signature did not match the message digest. - Paraksts neatbilda ziņojuma apkopojumam. - - - Message verification failed. - Ziņojumu neizdevās pārbaudīt. - - - Message verified. - Ziņojums pārbaudīts. - SplashScreen - - Bitcoin Core - Bitcoin Core - - - The Bitcoin Core developers - Bitcoin Core izstrādātāji - [testnet] [testnets] @@ -1687,410 +1060,16 @@ KB/s - - TransactionDesc - - Open until %1 - Atvērts līdz %1 - - - conflicted - pretrunā - - - %1/offline - %1/bezsaistē - - - %1/unconfirmed - %1/neapstiprinātas - - - %1 confirmations - %1 apstiprinājumu - - - Status - Status - - - Date - Datums - - - Source - Avots - - - Generated - Ģenerēts - - - From - No - - - To - Uz - - - own address - paša adrese - - - label - etiķete - - - Credit - Kredīts - - - not accepted - nav pieņemts - - - Debit - Debets - - - Transaction fee - Transakcijas maksa - - - Net amount - Neto summa - - - Message - Ziņojums - - - Comment - Komentārs - - - Transaction ID - Transakcijas ID - - - Merchant - Tirgotājs - - - Debug information - Atkļūdošanas informācija - - - Transaction - Transakcija - - - Inputs - Ieejas - - - Amount - Daudzums - - - true - patiess - - - false - nepatiess - - - , has not been successfully broadcast yet - , vēl nav veiksmīgi izziņots - - - unknown - nav zināms - - TransactionDescDialog - - Transaction details - Transakcijas detaļas - This pane shows a detailed description of the transaction Šis panelis parāda transakcijas detaļas - - TransactionTableModel - - Date - Datums - - - Type - Tips - - - Open until %1 - Atvērts līdz %1 - - - Confirmed (%1 confirmations) - Apstiprināts (%1 apstiprinājumu) - - - This block was not received by any other nodes and will probably not be accepted! - Neviens cits mezgls šo bloku nav saņēmis un droši vien netiks akceptēts! - - - Generated but not accepted - Ģenerēts, taču nav akceptēts - - - Offline - Bezsaitē - - - Label - Nosaukums - - - Unconfirmed - Neapstiprināts - - - Conflicted - Pretrunā - - - Received with - Saņemts ar - - - Received from - Saņemts no - - - Sent to - Nosūtīts - - - Payment to yourself - Maksājums sev - - - Mined - Atrasts - - - (n/a) - (nav pieejams) - - - Transaction status. Hover over this field to show number of confirmations. - Transakcijas statuss. Turiet peli virs šī lauka, lai redzētu apstiprinājumu skaitu. - - - Date and time that the transaction was received. - Transakcijas saņemšanas datums un laiks. - - - Type of transaction. - Transakcijas tips. - - - Amount removed from or added to balance. - Bilancei pievienotais vai atņemtais daudzums. - - - - TransactionView - - All - Visi - - - Today - Šodien - - - This week - Šonedēļ - - - This month - Šomēnes - - - Last month - Pēdējais mēnesis - - - This year - Šogad - - - Range... - Diapazons... - - - Received with - Saņemts ar - - - Sent to - Nosūtīts - - - To yourself - Sev - - - Mined - Atrasts - - - Other - Cits - - - Enter address or label to search - Ierakstiet meklējamo nosaukumu vai adresi - - - Min amount - Minimālais daudzums - - - Copy address - Kopēt adresi - - - Copy label - Kopēt nosaukumu - - - Copy amount - Kopēt daudzumu - - - Copy transaction ID - Kopēt transakcijas ID - - - Edit label - Mainīt nosaukumu - - - Show transaction details - Rādīt transakcijas detaļas - - - Export Transaction History - Eksportēt Transakciju Vēsturi - - - Exporting Failed - Eksportēšana Neizdevās - - - Exporting Successful - Eksportēšana Veiksmīga - - - The transaction history was successfully saved to %1. - Transakciju vēsture tika veiksmīgi saglabāta uz %1. - - - Comma separated file (*.csv) - Fails ar komatu kā atdalītāju (*.csv) - - - Confirmed - Apstiprināts - - - Date - Datums - - - Type - Tips - - - Label - Nosaukums - - - Address - Adrese - - - ID - ID - - - Range: - Diapazons: - - - to - uz - - UnitDisplayStatusBarControl - - WalletFrame - - No wallet has been loaded. - Neviens maciņš nav ielādēts. - - - - WalletModel - - Send Coins - Sūtīt Bitkoinus - - - - WalletView - - &Export - &Eksportēt - - - Export the data in the current tab to a file - Datus no tekošā ieliktņa eksportēt uz failu - - - Backup Wallet - Izveidot maciņa rezerves kopiju - - - Wallet Data (*.dat) - Maciņa dati (*.dat) - - - Backup Failed - Rezerves kopēšana neizdevās - - - There was an error trying to save the wallet data to %1. - Notikusi kļūme mēģinot saglabāt maciņa datus uz %1. - - - The wallet data was successfully saved to %1. - Maciņa dati tika veiksmīgi saglabāti uz %1. - - - Backup Successful - Dublēšana Veiksmīga - - bitcoin-core @@ -2117,6 +1096,10 @@ Run in the background as a daemon and accept commands Darbināt fonā kā servisu un pieņemt komandas + + Bitcoin Core + Bitcoin Core + <category> can be: <category> var būt: @@ -2161,26 +1144,10 @@ Wallet options: Maciņa iespējas: - - Cannot resolve -whitebind address: '%s' - Nevar atrisināt -whitebind adresi: '%s' - Information Informācija - - Invalid amount for -maxtxfee=<amount>: '%s' - Nederīgs daudzums priekš -maxtxfee=<amount>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Nederīgs daudzums priekš -minrelaytxfee=<amount>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - Nederīgs daudzums priekš -mintxfee=<amount>: '%s' - RPC server options: RPC servera iestatījumi: @@ -2213,10 +1180,6 @@ Warning Brīdinājums - - wallet.dat corrupt, salvage failed - wallet.dat ir bojāts, glābšana neizdevās - Password for JSON-RPC connections JSON-RPC savienojumu parole @@ -2225,10 +1188,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) Izpildīt komandu, kad labāk atbilstošais bloks izmainās (%s cmd aizvieto ar bloka hešu) - - This help message - Šis palīdzības paziņojums - Allow DNS lookups for -addnode, -seednode and -connect Atļaut DNS uzmeklēšanu priekš -addnode, -seednode un -connect @@ -2237,14 +1196,6 @@ Loading addresses... Ielādē adreses... - - Error loading wallet.dat: Wallet corrupted - Nevar ielādēt wallet.dat: maciņš bojāts - - - Error loading wallet.dat - Kļūda ielādējot wallet.dat - Invalid -proxy address: '%s' Nederīga -proxy adrese: '%s' @@ -2253,18 +1204,6 @@ Unknown network specified in -onlynet: '%s' -onlynet komandā norādīts nepazīstams tīkls: '%s' - - Cannot resolve -bind address: '%s' - Nevar uzmeklēt -bind adresi: '%s' - - - Cannot resolve -externalip address: '%s' - Nevar atrisināt -externalip adresi: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - Nederīgs daudzums priekš -paytxfree=<amount>: '%s' - Insufficient funds Nepietiek bitkoinu diff --git a/src/qt/locale/bitcoin_mk_MK.ts b/src/qt/locale/bitcoin_mk_MK.ts index b7797063b2856..b696111a5379a 100644 --- a/src/qt/locale/bitcoin_mk_MK.ts +++ b/src/qt/locale/bitcoin_mk_MK.ts @@ -25,10 +25,6 @@ C&lose З&атвори - - &Copy Address - &Копирај Адреса - Delete the currently selected address from the list Избриши ја избраната адреса од листата @@ -45,57 +41,6 @@ &Delete &Избриши - - Choose the address to send coins to - Изберете адресата за да пратите биткоини - - - Choose the address to receive coins with - Изберете адресата за да примите биткоини - - - C&hoose - И&збери - - - Sending addresses - Адреси за праќање - - - Receiving addresses - Адреси за примање - - - Copy &Label - Копирај &Етикета - - - &Edit - &Уреди - - - Export Address List - Експортирај Листа со Адреси - - - Exporting Failed - Експортирањето не Успеа - - - - AddressTableModel - - Label - Етикета - - - Address - Адреса - - - (no label) - (без етикета) - AskPassphraseDialog @@ -111,70 +56,6 @@ Repeat new passphrase Повторете ја новата тајна фраза - - Encrypt wallet - Криптирање на паричник - - - Unlock wallet - Отклучи паричник - - - Decrypt wallet - Декриптирање на паричник - - - Change passphrase - Измени тајна фраза - - - Confirm wallet encryption - Потврдете го криптирањето на паричникот - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Предупредување: Ако го шифрирате вашиот паричник и ја изгубите вашата тајна фраза, ќе <b>ГИ ИЗГУБИТЕ СИТЕ ВАШИ БИТКОИНИ</b>! - - - Are you sure you wish to encrypt your wallet? - Дали сте сигурни дека сакате да криптирате вашиот паричник? - - - Warning: The Caps Lock key is on! - Предупредување: Caps Lock копчето е активно! - - - Wallet encrypted - Паричникот е криптиран - - - Wallet encryption failed - Криптирањето на паричникот е неуспешно - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Криптирањето на паричникот не успеа поради интерна грешка. Вашиот паричник не е криптиран. - - - The supplied passphrases do not match. - Приложените тајни фрази не се поклопуваат - - - Wallet unlock failed - Отклучувањето на паричникот е неуспешно - - - The passphrase entered for the wallet decryption was incorrect. - Тајната фраза која што ја внесовте за декриптирање на паричникот е неточна. - - - Wallet decryption failed - Декриптирањето на паричникот е неуспешно - - - Wallet passphrase was successfully changed. - Тајната фраза е успешно променета. - BanTableModel @@ -249,14 +130,6 @@ Open &URI... Отвори &URI... - - Bitcoin Core client - Биткоин Core софтверот - - - Importing blocks from disk... - Внесување на блокови од дискот... - Reindexing blocks on disk... Повторно индексирање на блокови од дискот... @@ -285,10 +158,6 @@ &Receive &Прими - - Show information about Bitcoin Core - Прикажи информации за Биткоин Core - &Show / Hide &Прикажи / Сокриј @@ -305,14 +174,6 @@ &Help &Помош - - Bitcoin Core - Биткоин Core - - - &About Bitcoin Core - &За Биткоин Core - Processed %n block(s) of transaction history. Обработен %n блок од историјата на трансакции.Обработени %n блокови од историјата на трансакции. @@ -384,9 +245,6 @@ - - ClientModel - CoinControlDialog @@ -429,126 +287,6 @@ Priority Приоритет - - Copy address - Копирај адреса - - - Copy label - Копирај етикета - - - Copy amount - Копирај сума - - - Lock unspent - Заклучи непотрошени - - - Unlock unspent - Отклучи непотрошени - - - Copy quantity - Копирај количина - - - Copy fee - Копирај провизија - - - Copy after fee - Копирај после провизија - - - Copy bytes - Копирај бајти - - - Copy priority - Копирај приоритет - - - Copy dust - Копирај прашина - - - Copy change - Копирај кусур - - - highest - највисок - - - higher - повисок - - - high - висок - - - medium-high - средно-висок - - - medium - среден - - - low-medium - ниско-среден - - - low - низок - - - lower - понизок - - - lowest - најнизок - - - none - нема - - - This label turns red if the transaction size is greater than 1000 bytes. - Оваа етикета станува црвена ако големината на трансакцијата е поголема од 1000 бајти. - - - This label turns red if the priority is smaller than "medium". - Оваа етикета станува црвена ако приоритетот е помал од "среден". - - - This label turns red if any recipient receives an amount smaller than %1. - Оваа етикета станува црвена ако примачот прими сума помала од %1. - - - yes - да - - - no - не - - - Transactions with higher priority are more likely to get included into a block. - Трансакциите со повисок приоритет имаат поголеми шанси да бидат вклучени во блок. - - - (no label) - (без етикета) - - - (change) - (кусур) - EditAddressDialog @@ -564,7 +302,7 @@ &Address &Адреса - + FreespaceChecker @@ -574,10 +312,6 @@ HelpMessageDialog - - Bitcoin Core - Биткоин Core - version верзија @@ -586,17 +320,9 @@ (%1-bit) (%1-бит) - - About Bitcoin Core - За Биткоин Core - Intro - - Bitcoin Core - Биткоин Core - Error Грешка @@ -655,9 +381,6 @@ Вкупно: - - PaymentServer - PeerTableModel @@ -688,21 +411,6 @@ %1 мс - - QRImageWidget - - &Save Image... - &Сними Слика... - - - Save QR Code - Сними QR Код - - - PNG Image (*.png) - PNG Слика (*.png) - - RPCConsole @@ -768,19 +476,7 @@ Show Прикажи - - Copy label - Копирај етикета - - - Copy message - Копирај порака - - - Copy amount - Копирај сума - - + ReceiveRequestDialog @@ -799,50 +495,7 @@ &Save Image... &Сними Слика... - - URI - URI - - - Address - Адреса - - - Amount - Сума - - - Label - Етикета - - - Message - Порака - - - - RecentRequestsTableModel - - Date - Дата - - - Label - Етикета - - - Message - Порака - - - Amount - Сума - - - (no label) - (без етикета) - - + SendCoinsDialog @@ -873,42 +526,6 @@ Dust: Прашина: - - Copy quantity - Копирај количина - - - Copy amount - Копирај сума - - - Copy fee - Копирај провизија - - - Copy after fee - Копирај после провизија - - - Copy bytes - Копирај бајти - - - Copy priority - Копирај приоритет - - - Copy change - Копирај кусур - - - (no label) - (без етикета) - - - Copy dust - Копирај прашина - SendCoinsEntry @@ -933,100 +550,26 @@ SplashScreen - - Bitcoin Core - Биткоин Core - TrafficGraphWidget - - TransactionDesc - - Date - Дата - - - Message - Порака - - - Amount - Сума - - TransactionDescDialog - - TransactionTableModel - - Date - Дата - - - Label - Етикета - - - - TransactionView - - Copy address - Копирај Адреса - - - Copy label - Копирај етикета - - - Copy amount - Копирај сума - - - Exporting Failed - Експортирањето не Успеа - - - Date - Дата - - - Label - Етикета - - - Address - Адреса - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - - WalletView - - &Export - &Експорт - - - Export the data in the current tab to a file - Експортирај ги податоците од активното јазиче во датотека - - bitcoin-core Options: Опции: + + Bitcoin Core + Биткоин Core + Warning Предупредување diff --git a/src/qt/locale/bitcoin_mn.ts b/src/qt/locale/bitcoin_mn.ts index b790010066c29..e38320ac5d271 100644 --- a/src/qt/locale/bitcoin_mn.ts +++ b/src/qt/locale/bitcoin_mn.ts @@ -21,10 +21,6 @@ C&lose &Хаах - - &Copy Address - Хаягийг &Хуулбарлах - Delete the currently selected address from the list Одоо сонгогдсон байгаа хаягуудыг жагсаалтаас устгах @@ -41,65 +37,6 @@ &Delete &Устгах - - Choose the address to send coins to - Зооснуудыг илгээх хаягийг сонгоно уу - - - Choose the address to receive coins with - Зооснуудыг хүлээн авах хаягийг сонгоно уу - - - C&hoose - С&онго - - - Sending addresses - Илгээх хаягууд - - - Receiving addresses - Хүлээн авах хаяг - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Эдгээр Биткойн хаягууд нь илгээх хаягууд. Хүлээн авах хаяг болон тоо хэмжээг илгээхээсээ өмнө сайн нягталж үзэж байна уу - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Эдгээр Биткойн хаягууд нь хүлээн авах хаягууд. Гүйлгээ болгонд шинээр хаяг үүсгэхийг бид санал болгож байна. - - - Copy &Label - &Шошгыг хуулбарлах - - - &Edit - &Ѳѳрчлѳх - - - Export Address List - Экспорт хийх хаягуудын жагсаалт - - - Comma separated file (*.csv) - Таслалаар тусгаарлагдсан хүснэгтэн файл (.csv) - - - - AddressTableModel - - Label - Шошго - - - Address - Хаяг - - - (no label) - (шошгогүй) - AskPassphraseDialog @@ -115,66 +52,6 @@ Repeat new passphrase Шинэ нууц үгийг давтана уу - - Encrypt wallet - Түрүйвчийг цоожлох - - - This operation needs your wallet passphrase to unlock the wallet. - Энэ үйлдэлийг гүйцэтгэхийн тулд та нууц үгээрээ түрүйвчийн цоожийг тайлах хэрэгтэй - - - Unlock wallet - Түрүйвчийн цоожийг тайлах - - - This operation needs your wallet passphrase to decrypt the wallet. - Энэ үйлдэлийг гүйцэтгэхийн тулд та эхлээд түрүйвчийн нууц үгийг оруулж цоожийг тайлах шаардлагтай. - - - Decrypt wallet - Түрүйвчийн цоожийг устгах - - - Change passphrase - Нууц үгийг солих - - - Confirm wallet encryption - Түрүйвчийн цоожийг баталгаажуулах - - - Wallet encrypted - Түрүйвч цоожлогдлоо - - - Wallet encryption failed - Түрүйвчийн цоожлол амжилттай болсонгүй - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Түрүйвчийн цоожлол дотоод алдаанаас үүдэн амжилттай болсонгүй. Түрүйвч цоожлогдоогүй байна. - - - The supplied passphrases do not match. - Таны оруулсан нууц үг таарсангүй - - - Wallet unlock failed - Түрүйвчийн цоож тайлагдсангүй - - - The passphrase entered for the wallet decryption was incorrect. - Таны оруулсан түрүйвчийн цоожийг тайлах нууц үг буруу байна - - - Wallet decryption failed - Түрүйвчийн цоож амжилттай устгагдсангүй - - - Wallet passphrase was successfully changed. - Түрүйвчийн нууц үг амжилттай ѳѳр - BanTableModel @@ -298,9 +175,6 @@ Түрүйвч <b>цоожтой</b> ба одоогоор цоож <b>хаалттай</b> байна - - ClientModel - CoinControlDialog @@ -323,31 +197,7 @@ Confirmed Баталгаажлаа - - Copy address - Хаягийг санах - - - Copy label - Шошгыг санах - - - Copy amount - Хэмжээг санах - - - Copy change - Ѳѳрчлѳлтийг санах - - - (no label) - (шошгогүй) - - - (change) - (ѳѳрчлѳх) - - + EditAddressDialog @@ -362,34 +212,6 @@ &Address &Хаяг - - New receiving address - Шинэ хүлээн авах хаяг - - - New sending address - Шинэ явуулах хаяг - - - Edit receiving address - Хүлээн авах хаягийг ѳѳрчлѳх - - - Edit sending address - Явуулах хаягийг ѳѳрчлѳх - - - The entered address "%1" is already in the address book. - Таны оруулсан хаяг "%1" нь хаягийн бүртгэлд ѳмнѳ нь орсон байна - - - Could not unlock wallet. - Түрүйвчийн цоожийг тайлж чадсангүй - - - New key generation failed. - Шинэ түлхүүр амжилттай гарсангүй - FreespaceChecker @@ -453,9 +275,6 @@ Хэрэглэж болох хэмжээ: - - PaymentServer - PeerTableModel @@ -470,13 +289,6 @@ Алга Байна - - QRImageWidget - - PNG Image (*.png) - PNG форматын зураг (*.png) - - RPCConsole @@ -562,18 +374,6 @@ Remove Устгах - - Copy label - Шошгыг санах - - - Copy message - Зурвасыг санах - - - Copy amount - Хэмжээг санах - ReceiveRequestDialog @@ -581,49 +381,6 @@ Copy &Address Хаягийг &Хуулбарлах - - Address - Хаяг - - - Amount - Хэмжээ - - - Label - Шошго - - - Message - Зурвас - - - - RecentRequestsTableModel - - Date - Огноо - - - Label - Шошго - - - Message - Зурвас - - - Amount - Хэмжээ - - - (no label) - (шошгогүй) - - - (no message) - (зурвас алга) - SendCoinsDialog @@ -671,43 +428,7 @@ S&end Яв&уул - - Confirm send coins - Зоос явуулахыг баталгаажуулна уу - - - Copy amount - Хэмжээг санах - - - Copy change - Ѳѳрчлѳлтийг санах - - - or - эсвэл - - - The amount to pay must be larger than 0. - Тѳлѳх хэмжээ 0.-оос их байх ёстой - - - The amount exceeds your balance. - Энэ хэмжээ таны балансаас хэтэрсэн байна. - - - The total exceeds your balance when the %1 transaction fee is included. - Гүйлгээний тѳлбѳр %1-ийг тооцхоор нийт дүн нь таны балансаас хэтрээд байна. - - - Warning: Invalid Bitcoin address - Анхаар:Буруу Биткойны хаяг байна - - - (no label) - (шошгогүй) - - + SendCoinsEntry @@ -718,10 +439,6 @@ Pay &To: Тѳлѳх &хаяг: - - Enter a label for this address to add it to your address book - Энэ хаягийг ѳѳрийн бүртгэлдээ авахын тулд шошго оруул - &Label: &Шошго: @@ -749,10 +466,6 @@ ShutdownWindow - - Bitcoin Core is shutting down... - Биткойны цѳм хаагдаж байна... - Do not shut down the computer until this window disappears. Энэ цонхыг хаагдтал компьютерээ бүү унтраагаарай @@ -783,278 +496,16 @@ TrafficGraphWidget - - TransactionDesc - - Open until %1 - %1 хүртэл нээлттэй - - - conflicted - зѳрчилдлѳѳ - - - %1/unconfirmed - %1/баталгаажаагүй - - - %1 confirmations - %1 баталгаажилтууд - - - Date - Огноо - - - Message - Зурвас - - - Transaction ID - Тодорхойлолт - - - Amount - Хэмжээ - - - , has not been successfully broadcast yet - , хараахан амжилттай цацагдаагүй байна - - - unknown - үл мэдэгдэх - - TransactionDescDialog - - Transaction details - Гүйлгээний мэдээллэл - This pane shows a detailed description of the transaction Гүйлгээний дэлгэрэнгүйг энэ бичил цонх харуулж байна - - TransactionTableModel - - Date - Огноо - - - Type - Тѳрѳл - - - Open until %1 - %1 хүртэл нээлттэй - - - Confirmed (%1 confirmations) - Баталгаажлаа (%1 баталгаажилт) - - - This block was not received by any other nodes and will probably not be accepted! - Энэ блокийг аль ч нод хүлээн авсангүй ба ер нь зѳвшѳѳрѳгдѳхгүй байж мэднэ! - - - Generated but not accepted - Үүсгэгдсэн гэхдээ хүлээн авагдаагүй - - - Label - Шошго - - - Unconfirmed - Баталгаажаагүй - - - Conflicted - Зѳрчилдлѳѳ - - - Received with - Хүлээн авсан хаяг - - - Received from - Хүлээн авагдсан хаяг - - - Sent to - Явуулсан хаяг - - - Payment to yourself - Ѳѳрлүүгээ хийсэн тѳлбѳр - - - Mined - Олборлогдсон - - - (n/a) - (алга байна) - - - Transaction status. Hover over this field to show number of confirmations. - Гүйлгээний байдал. Энд хулганыг авчирч баталгаажуулалтын тоог харна уу. - - - Date and time that the transaction was received. - Гүйлгээг хүлээн авсан огноо ба цаг. - - - Type of transaction. - Гүйлгээний тѳрѳл - - - Amount removed from or added to balance. - Балансаас авагдсан болон нэмэгдсэн хэмжээ. - - - - TransactionView - - All - Бүгд - - - Today - Ѳнѳѳдѳр - - - This week - Энэ долоо хоног - - - This month - Энэ сар - - - Last month - Ѳнгѳрсѳн сар - - - This year - Энэ жил - - - Received with - Хүлээн авсан хаяг - - - Sent to - Явуулсан хаяг - - - To yourself - Ѳѳрлүүгээ - - - Mined - Олборлогдсон - - - Other - Бусад - - - Enter address or label to search - Хайлт хийхийн тулд хаяг эсвэл шошгыг оруул - - - Min amount - Хамгийн бага хэмжээ - - - Copy address - Хаягийг санах - - - Copy label - Шошгыг санах - - - Copy amount - Хэмжээг санах - - - Edit label - Шошгыг ѳѳрчлѳх - - - Show transaction details - Гүйлгээний дэлгэрэнгүйг харуул - - - The transaction history was successfully saved to %1. - Гүйлгээнүй түүхийг %1-д амжилттай хадгаллаа. - - - Comma separated file (*.csv) - Таслалаар тусгаарлагдсан хүснэгтэн файл (.csv) - - - Confirmed - Баталгаажлаа - - - Date - Огноо - - - Type - Тѳрѳл - - - Label - Шошго - - - Address - Хаяг - - - ID - Тодорхойлолт - - - to - -рүү/руу - - UnitDisplayStatusBarControl - - WalletFrame - - No wallet has been loaded. - Ямар ч түрүйвч ачааллагдсангүй. - - - - WalletModel - - Send Coins - Зоос явуулах - - - - WalletView - - &Export - &Экспортдлох - - - Export the data in the current tab to a file - Сонгогдсон таб дээрхи дата-г экспортлох - - bitcoin-core @@ -1073,14 +524,6 @@ Loading addresses... Хаягуудыг ачааллаж байна... - - Error loading wallet.dat: Wallet corrupted - wallet.dat-ыг ачааллахад алдаа гарлаа: Түрүйвч эвдэрсэн байна - - - Error loading wallet.dat - wallet.dat-ыг ачааллахад алдаа гарлаа - Invalid -proxy address: '%s' Эдгээр прокси хаягнууд буруу байна: '%s' diff --git a/src/qt/locale/bitcoin_ms_MY.ts b/src/qt/locale/bitcoin_ms_MY.ts index df98dd839646c..de4c32c2df868 100644 --- a/src/qt/locale/bitcoin_ms_MY.ts +++ b/src/qt/locale/bitcoin_ms_MY.ts @@ -17,10 +17,6 @@ &Copy &Salin - - &Copy Address - &Salin Alamat - &Export &Eksport @@ -29,30 +25,7 @@ &Delete &Padam - - Choose the address to send coins to - Pilih alamat untuk menghantar syiling - - - Choose the address to receive coins with - Pilih alamat untuk menerima syiling - - - C&hoose - &Pilih - - - Comma separated file (*.csv) - Fail yang dipisahkan dengan koma - - - - AddressTableModel - - Address - Alamat - - + AskPassphraseDialog @@ -66,9 +39,6 @@ Pilihan - - ClientModel - CoinControlDialog @@ -82,7 +52,7 @@ &Address Alamat - + FreespaceChecker @@ -101,18 +71,12 @@ OverviewPage - - PaymentServer - PeerTableModel QObject - - QRImageWidget - RPCConsole @@ -125,13 +89,6 @@ Copy &Address &Salin Alamat - - Address - Alamat - - - - RecentRequestsTableModel SendCoinsDialog @@ -155,42 +112,12 @@ TrafficGraphWidget - - TransactionDesc - TransactionDescDialog - - TransactionTableModel - - - TransactionView - - Comma separated file (*.csv) - Fail yang dipisahkan dengan koma - - - Address - Alamat - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - - WalletView - - &Export - &Eksport - - bitcoin-core diff --git a/src/qt/locale/bitcoin_nb.ts b/src/qt/locale/bitcoin_nb.ts index 94e02f8900ed1..b5ffdb2e10253 100644 --- a/src/qt/locale/bitcoin_nb.ts +++ b/src/qt/locale/bitcoin_nb.ts @@ -25,10 +25,6 @@ C&lose &Lukk - - &Copy Address - &Kopier Adresse - Delete the currently selected address from the list Slett den valgte adressen fra listen. @@ -45,73 +41,6 @@ &Delete &Slett - - Choose the address to send coins to - Velg adressen å sende mynter til - - - Choose the address to receive coins with - Velg adressen til å motta mynter med - - - C&hoose - &Velg - - - Sending addresses - Utsendingsadresser - - - Receiving addresses - Mottaksadresser - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Dette er dine Bitcoin-adresser for å sende betalinger. Alltid sjekk beløp og mottakeradresse før sending av mynter. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Dette er dine Bitcoin-adresser for å sende betalinger. Det er anbefalt å bruk en ny mottaksadresse for hver transaksjon. - - - Copy &Label - Kopier &Merkelapp - - - &Edit - &Rediger - - - Export Address List - Ekporter Adresseliste - - - Comma separated file (*.csv) - Kommaseparert fil (*.csv) - - - Exporting Failed - Eksportering feilet - - - There was an error trying to save the address list to %1. Please try again. - Det oppstod en feil under lagring av adresselisten til %1. Vennligst prøv på nytt. - - - - AddressTableModel - - Label - Merkelapp - - - Address - Adresse - - - (no label) - (ingen merkelapp) - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase Gjenta ny adgangsfrase - - Encrypt wallet - Krypter lommebok - - - This operation needs your wallet passphrase to unlock the wallet. - Denne operasjonen krever adgangsfrasen til lommeboken for å låse den opp. - - - Unlock wallet - Lås opp lommebok - - - This operation needs your wallet passphrase to decrypt the wallet. - Denne operasjonen krever adgangsfrasen til lommeboken for å dekryptere den. - - - Decrypt wallet - Dekrypter lommebok - - - Change passphrase - Endre adgangsfrase - - - Confirm wallet encryption - Bekreft kryptering av lommebok - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Advarsel: Hvis du krypterer lommeboken og mister adgangsfrasen, så vil du <b>MISTE ALLE DINE BITCOINS</b>! - - - Are you sure you wish to encrypt your wallet? - Er du sikker på at du vil kryptere lommeboken? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Bitcoin Core vil nå avslutte for å fullføre krypteringsprosessen. Husk at kryptering av lommeboken ikke kan beskytte fullstendig mot tyveri av dine bitcoins hvis datamaskinen din er infisert av skadevare. - - - 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. - VIKTIG: Tidligere sikkerhetskopier av din lommebokfil bør erstattes med den nylig genererte og krypterte filen, da de blir ugyldiggjort av sikkerhetshensyn så snart du begynner å bruke den nye krypterte lommeboken. - - - Warning: The Caps Lock key is on! - Advarsel: Caps Lock er på! - - - Wallet encrypted - Lommebok kryptert - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Oppgi adgangsfrasen til lommeboken.<br/>Vennligst bruk en adgangsfrase med <b>ti eller flere tilfeldige tegn</b>, eller <b>åtte eller flere ord</b>. - - - Enter the old passphrase and new passphrase to the wallet. - Oppgi gammel og ny adgangsfrase til lommeboken. - - - Wallet encryption failed - Kryptering av lommebok feilet - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Kryptering av lommebok feilet på grunn av en intern feil. Din lommebok ble ikke kryptert. - - - The supplied passphrases do not match. - De angitte adgangsfrasene er ulike. - - - Wallet unlock failed - Opplåsing av lommebok feilet - - - The passphrase entered for the wallet decryption was incorrect. - Adgangsfrasen angitt for dekryptering av lommeboken var feil. - - - Wallet decryption failed - Dekryptering av lommebok feilet - - - Wallet passphrase was successfully changed. - Adgangsfrase for lommebok endret. - BanTableModel @@ -269,6 +110,10 @@ Quit application Avslutt applikasjonen + + &About %1 + &Om %1 + About &Qt Om &Qt @@ -305,14 +150,6 @@ Open &URI... Åpne &URI... - - Bitcoin Core client - Bitcoin Core-klient - - - Importing blocks from disk... - Importere blokker... - Reindexing blocks on disk... Reindekserer blokker på harddisk... @@ -357,10 +194,6 @@ &Receive &Motta - - Show information about Bitcoin Core - Vis informasjon om Bitcoin Core - &Show / Hide &Vis / Skjul @@ -397,22 +230,10 @@ Tabs toolbar Verktøylinje for faner - - Bitcoin Core - Bitcoin Core - Request payments (generates QR codes and bitcoin: URIs) Forespør betalinger (genererer QR-koder og bitcoin: URIer) - - &About Bitcoin Core - &Om Bitcoin Core - - - Modify configuration options for Bitcoin Core - Endre konfigurasjonsvalg for Bitcoin Core - Show the list of used sending addresses and labels Vis listen av brukte utsendingsadresser og merkelapper @@ -429,10 +250,6 @@ &Command-line options &Kommandolinjevalg - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Vis Bitcoin Core hjelpemeldingen for å få en liste med mulige kommandolinjevalg - %n active connection(s) to Bitcoin network %n aktiv forbindelse til Bitcoin-nettverket%n aktive forbindelser til Bitcoin-nettverket @@ -544,13 +361,6 @@ Lommeboken er <b>kryptert</b> og for tiden <b>låst</b> - - ClientModel - - Network Alert - Nettverksvarsel - - CoinControlDialog @@ -629,150 +439,6 @@ Priority Prioritet - - Copy address - Kopier adresse - - - Copy label - Kopier merkelapp - - - Copy amount - Kopier beløp - - - Copy transaction ID - Kopier transaksjons-ID - - - Lock unspent - Lås ubrukte - - - Unlock unspent - Lås opp ubrukte - - - Copy quantity - Kopier mengde - - - Copy fee - Kopier gebyr - - - Copy after fee - Kopier totalt - - - Copy bytes - Kopier bytes - - - Copy priority - Kopier prioritet - - - Copy dust - Kopier støv - - - Copy change - Kopier veksel - - - highest - høyest - - - higher - høyere - - - high - høy - - - medium-high - medium-høy - - - medium - medium - - - low-medium - lav-medium - - - low - lav - - - lower - lavere - - - lowest - lavest - - - (%1 locked) - (%1 låst) - - - none - ingen - - - This label turns red if the transaction size is greater than 1000 bytes. - Denne teksten blir rød hvis transaksjonsstørrelsen er større enn 1000 bytes. - - - This label turns red if the priority is smaller than "medium". - Denne teksten blir rød hvis prioriteten er lavere enn "medium". - - - This label turns red if any recipient receives an amount smaller than %1. - Denne teksten blir rød dersom en mottaker mottar et beløp mindre enn %1. - - - Can vary +/- %1 satoshi(s) per input. - Kan variere +/- %1 satoshi(er) per input. - - - yes - ja - - - no - nei - - - This means a fee of at least %1 per kB is required. - Dette betyr at et gebyr på minst %1 per KB er påkrevd. - - - Can vary +/- 1 byte per input. - Kan variere +/- 1 byte per input. - - - Transactions with higher priority are more likely to get included into a block. - Transaksjoner med høyere prioritet har mer sannsynlighet for å bli inkludert i en blokk. - - - (no label) - (ingen merkelapp) - - - change from %1 (%2) - veksel fra %1 (%2) - - - (change) - (veksel) - EditAddressDialog @@ -796,38 +462,6 @@ &Address &Adresse - - New receiving address - Ny mottaksadresse - - - New sending address - Ny utsendingsadresse - - - Edit receiving address - Rediger mottaksadresse - - - Edit sending address - Rediger utsendingsadresse - - - The entered address "%1" is already in the address book. - Den oppgitte adressen "%1" er allerede i adresseboken. - - - The entered address "%1" is not a valid Bitcoin address. - Den angitte adressed "%1" er ikke en gyldig Bitcoin-adresse. - - - Could not unlock wallet. - Kunne ikke låse opp lommeboken. - - - New key generation failed. - Generering av ny nøkkel feilet. - FreespaceChecker @@ -854,10 +488,6 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin Core - version versjon @@ -866,10 +496,6 @@ (%1-bit) (%1-bit) - - About Bitcoin Core - Om Bitcoin Core - Command-line options Kommandolinjevalg @@ -906,29 +532,13 @@ Show splash screen on startup (default: %u) Vis velkomstbilde ved oppstart (default: %u) - - Reset all settings changes made over the GUI - Nullstill alle oppsettendringer gjort via det grafiske grensesnittet - - + Intro Welcome Velkommen - - Welcome to Bitcoin Core. - Velkommen til Bitcoin Core. - - - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - Siden dette er første gang programmet starter, kan du nå velge hvor Bitcoin Core skal lagre sine data. - - - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - Bitcoin Core vil laste ned og lagre en kopi av Bitcoin sin blokkjede. Minst %1GB av data vil bli lagret i denne mappen, og det vil vokse over tid. Lommeboken vil også bli lagret i denne mappen. - Use the default data directory Bruk standard datamappe @@ -937,10 +547,6 @@ Use a custom data directory: Bruk en egendefinert datamappe: - - Bitcoin Core - Bitcoin Core - Error: Specified data directory "%1" cannot be created. Feil: Den oppgitte datamappen "%1" kan ikke opprettes. @@ -976,10 +582,6 @@ Select payment request file Velg fil for betalingsetterspørring - - Select payment request file to open - Velg fil for betalingsetterspørring å åpne - OptionsDialog @@ -1019,10 +621,6 @@ 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. Minimer i stedet for å avslutte applikasjonen når vinduet lukkes. Når dette er valgt, vil applikasjonen avsluttes kun etter at Avslutte er valgt i menyen. - - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - Språk for brukergrensesnittet kan velges her. Denne innstillingen trer i kraft etter omstart av Bitcoin Core. - 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 |. Tredjepart URLer (f. eks. en blokkutforsker) som dukker opp i transaksjonsfanen som kontekst meny elementer. %s i URLen er erstattet med transaksjonen sin hash. Flere URLer er separert av en vertikal linje |. @@ -1047,14 +645,6 @@ &Network &Nettverk - - Automatically start Bitcoin Core after logging in to the system. - Start Bitcoin Core automatisk ved oppstart av datamaskinen. - - - &Start Bitcoin Core on system login - &Start Bitcoin Core ved oppstart av datamaskinen - (0 = auto, <0 = leave that many cores free) (0 = automatisk, <0 = la så mange kjerner være ledig) @@ -1284,182 +874,72 @@ - PaymentServer + PeerTableModel - URI handling - URI-håndtering + User Agent + Brukeragent - Invalid payment address %1 - Ugyldig betalingsadresse %1 + Node/Service + Node/Tjeneste - Payment request rejected - Betalingsetterspørring avvist + Ping Time + Ping-tid + + + QObject - Payment request network doesn't match client network. - Nettverk for betalingsetterspørring er ikke i overensstemmelse med klientnettverket. + Amount + Beløp - Payment request is not initialized. - Betalingsetterspørringen er ikke initialisert. + Enter a Bitcoin address (e.g. %1) + Oppgi en Bitcoin-adresse (f.eks. %1) - Requested payment amount of %1 is too small (considered dust). - Forespurt betalingsmengde på %1 er for liten (betraktet som støv). + %1 d + %1 d - Payment request error - Betalingsetterspørringsfeil + %1 h + %1 t - Cannot start bitcoin: click-to-pay handler - Kan ikke starte Bitcoin: klikk-og-betal håndterer + %1 m + %1 m - Payment request fetch URL is invalid: %1 - Hentelenke for betalingsetterspørring er ugyldig: %1 + %1 s + %1 s - URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - URI kan ikke fortolkes! Dette kan være forårsaket av en ugyldig Bitcoin-adresse eller feilformede URI-parametre. + None + Ingen - Payment request file handling - Filhåndtering for betalingsetterspørring + N/A + - - Payment request file cannot be read! This can be caused by an invalid payment request file. - Betalingsetterspørringsfil kan ikke leses! Dette kan være forårsaket av en ugyldig betalingsetterspørringsfil. + %1 ms + %1 ms + + + RPCConsole - Payment request expired. - Betalingsetterspørringen har utløpt. + Client name + Klientnavn - Unverified payment requests to custom payment scripts are unsupported. - Uverifiserte betalingsforespørsler til egentilpassede betalingscript er ikke støttet. + N/A + - - Invalid payment request. - Ugyldig betalingsetterspørring. - - - Refund from %1 - Refundering fra %1 - - - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - Betalingsforespørsel %1 er for stor (%2 bytes, tillatt %3 bytes). - - - Error communicating with %1: %2 - Feil i kommunikasjonen med %1: %2 - - - Payment request cannot be parsed! - Betaingsetterspørrelse kan ikke fortolkes! - - - Bad response from server %1 - Dårlig svar fra server %1 - - - Payment acknowledged - Betaling erkjent - - - Network request error - Nettverksforespørsel feil - - - - PeerTableModel - - User Agent - Brukeragent - - - Node/Service - Node/Tjeneste - - - Ping Time - Ping-tid - - - - QObject - - Amount - Beløp - - - Enter a Bitcoin address (e.g. %1) - Oppgi en Bitcoin-adresse (f.eks. %1) - - - %1 d - %1 d - - - %1 h - %1 t - - - %1 m - %1 m - - - %1 s - %1 s - - - None - Ingen - - - N/A - - - - - %1 ms - %1 ms - - - - QRImageWidget - - &Save Image... - &Lagre Bilde... - - - &Copy Image - &Kopier Bilde - - - Save QR Code - Lagre QR-kode - - - PNG Image (*.png) - PNG-bilde (*.png) - - - - RPCConsole - - Client name - Klientnavn - - - N/A - - - - - Client version - Klientversjon + Client version + Klientversjon &Information @@ -1513,10 +993,6 @@ Memory usage Minnebruk - - Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. - Åpne Bitcoin Core sin loggfil for feilsøk fra gjeldende datamappe. Dette kan ta noen sekunder for store loggfiler. - Received Mottatt @@ -1633,10 +1109,6 @@ Out: Ut: - - Build date - Byggedato - Debug log file Loggfil for feilsøk @@ -1673,10 +1145,6 @@ &Unban Node Fjern &Utestengning av Node - - Welcome to the Bitcoin Core RPC console. - Velkommen til Bitcoin Core sin RPC-konsoll. - Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. Bruk opp og ned pil for å navigere historikken, og <b>Ctrl-L</b> for å tømme skjermen. @@ -1804,18 +1272,6 @@ Remove Fjern - - Copy label - Kopier merkelapp - - - Copy message - Kopier melding - - - Copy amount - Kopier beløp - ReceiveRequestDialog @@ -1835,73 +1291,6 @@ &Save Image... &Lagre Bilde... - - Request payment to %1 - Etterspør betaling til %1 - - - Payment information - Betalingsinformasjon - - - URI - URI - - - Address - Adresse - - - Amount - Beløp - - - Label - Merkelapp - - - Message - Melding - - - Resulting URI too long, try to reduce the text for label / message. - Resultat URI for lang, prøv å redusere teksten for merkelapp / melding. - - - Error encoding URI into QR Code. - Feil ved koding av URI til QR-kode. - - - - RecentRequestsTableModel - - Date - Dato - - - Label - Merkelapp - - - Message - Melding - - - Amount - Beløp - - - (no label) - (ingen merkelapp) - - - (no message) - (ingen melding) - - - (no amount) - (intet beløp) - SendCoinsDialog @@ -1954,951 +1343,305 @@ Veksel: - If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address. - Hvis dette er aktivert, men adressen for veksel er tom eller ugyldig, vil veksel bli sendt til en nylig generert adresse. - - - Custom change address - Egendefinert adresse for veksel - - - Transaction Fee: - Transaksjonsgebyr: - - - Choose... - Velg... - - - collapse fee-settings - Legg ned gebyrinnstillinger - - - per kilobyte - per kilobyte - - - If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte. - Hvis den egendefinerte avgiften er satt til 1000 satoshis og transaksjonen bare er 250 bytes, da vil "per kilobyte" bare betale 250 satoshis i gebyr, mens "minstebeløp" betaler 1000 satoshis. For transaksjoner større enn en kilobyte vil begge betale for antall kilobyte. - - - Hide - Skjul - - - total at least - minstebeløp - - - Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process. - Betaling av bare minimumsavgiften går helt fint så lenge det er mindre transaksjonsvolum enn plass i blokkene. Men vær klar over at dette kan ende opp i en transaksjon som aldri blir bekreftet når det er mer etterspørsel etter Bitcoin-transaksjoner enn nettverket kan behandle. - - - (read the tooltip) - (les verktøytipset) - - - Recommended: - Anbefalt: - - - Custom: - Egendefinert: - - - (Smart fee not initialized yet. This usually takes a few blocks...) - (Smartgebyr ikke innført ennå. Dette tar vanligvis noen blokker...) - - - Confirmation time: - Bekreftelsestid: - - - normal - normal - - - fast - rask - - - Send as zero-fee transaction if possible - Send uten transaksjonsgebyr hvis mulig - - - (confirmation may take longer) - (bekreftelse kan ta lengre tid) - - - Send to multiple recipients at once - Send til flere enn en mottaker - - - Add &Recipient - Legg til &Mottaker - - - Clear all fields of the form. - Fjern alle felter fra skjemaet. - - - Dust: - Støv: - - - Clear &All - Fjern &Alt - - - Balance: - Saldo: - - - Confirm the send action - Bekreft sending - - - S&end - S&end - - - Confirm send coins - Bekreft sending av bitcoins - - - %1 to %2 - %1 til %2 - - - Copy quantity - Kopier mengde - - - Copy amount - Kopier beløp - - - Copy fee - Kopier gebyr - - - Copy after fee - Kopier fra gebyr - - - Copy bytes - Kopier bytes - - - Copy priority - Kopier prioritet - - - Copy change - Kopier veksel - - - Total Amount %1 - Totalt Beløp %1 - - - or - eller - - - The amount to pay must be larger than 0. - Beløpet som skal betales må være over 0. - - - The amount exceeds your balance. - Beløpet overstiger saldo. - - - The total exceeds your balance when the %1 transaction fee is included. - Totalbeløpet overstiger saldo etter at %1 transaksjonsgebyr er lagt til. - - - Transaction creation failed! - Opprettelse av transaksjon feilet! - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - Transaksjonen ble avvist! Dette kan skje hvis noen av myntene i lommeboken allerede er brukt, som hvis du kopierte wallet.dat og mynter ble brukt i kopien uten å bli markert som brukt her. - - - A fee higher than %1 is considered an absurdly high fee. - Et gebyr høyere enn %1 er ansett som et absurd høyt gebyr. - - - Payment request expired. - Betalingsetterspørringen har utløpt. - - - Pay only the required fee of %1 - Betal kun påkrevd gebyr på %1 - - - Estimated to begin confirmation within %n block(s). - Anslått til å begynne bekreftelse innen %n blokk.Anslått til å begynne bekreftelse innen %n blokker. - - - The recipient address is not valid. Please recheck. - Mottakeradressen er ikke gyldig. Vennligst kontroller på nytt. - - - Duplicate address found: addresses should only be used once each. - Gjenbruk av adresse funnet: adresser skal bare brukes en gang hver. - - - Warning: Invalid Bitcoin address - Advarsel: Ugyldig Bitcoin-adresse - - - (no label) - (ingen merkelapp) - - - Warning: Unknown change address - Advarsel: Ukjent adresse for veksel - - - Copy dust - Kopier støv - - - Are you sure you want to send? - Er du sikker på at du vil sende? - - - added as transaction fee - lagt til som transaksjonsgebyr - - - - SendCoinsEntry - - A&mount: - &Beløp: - - - Pay &To: - Betal &Til: - - - Enter a label for this address to add it to your address book - Skriv inn en merkelapp for denne adressen for å legge den til i din adressebok - - - &Label: - &Merkelapp: - - - Choose previously used address - Velg tidligere brukt adresse - - - This is a normal payment. - Dette er en normal betaling. - - - The Bitcoin address to send the payment to - Bitcoin-adressen betalingen skal sendes til - - - Alt+A - Alt+A - - - Paste address from clipboard - Lim inn adresse fra utklippstavlen - - - Alt+P - Alt+P - - - Remove this entry - Fjern denne oppføringen - - - 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. - Gebyret vil bli trukket fra beløpet som blir sendt. Mottakeren vil motta mindre bitcoins enn det du skriver inn i beløpsfeltet. Hvis det er valgt flere mottakere, deles gebyret likt. - - - S&ubtract fee from amount - T&rekk fra gebyr fra beløp - - - Message: - Melding: - - - This is an unauthenticated payment request. - Dette er en uautorisert betalingsetterspørring. - - - This is an authenticated payment request. - Dette er en autorisert betalingsetterspørring. - - - Enter a label for this address to add it to the list of used addresses - Skriv inn en merkelapp for denne adressen for å legge den til listen av brukte adresser - - - 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. - En melding som var tilknyttet bitcoinen: URI vil bli lagret med transaksjonen for din oversikt. Denne meldingen vil ikke bli sendt over Bitcoin-nettverket. - - - Pay To: - Betal Til: - - - Memo: - Memo: - - - - ShutdownWindow - - Bitcoin Core is shutting down... - Bitcoin Core lukker... - - - Do not shut down the computer until this window disappears. - Slå ikke av datamaskinen før dette vinduet forsvinner. - - - - SignVerifyMessageDialog - - Signatures - Sign / Verify a Message - Signaturer - Signer / Verifiser en Melding - - - &Sign Message - &Signer Melding - - - 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. - Du kan signere meldinger/avtaler med adresser for å bevise at du kan motta bitcoins sendt til dem. Vær forsiktig med å signere noe vagt eller tilfeldig, siden phishing-angrep kan prøve å lure deg til å signere din identitet over til dem. Bare signer fullt detaljerte utsagn som du er enig i. - - - The Bitcoin address to sign the message with - Bitcoin-adressen meldingen skal signeres med - - - Choose previously used address - Velg tidligere brukt adresse - - - Alt+A - Alt+A - - - Paste address from clipboard - Lim inn adresse fra utklippstavlen - - - Alt+P - Alt+P - - - Enter the message you want to sign here - Skriv inn meldingen du vil signere her - - - Signature - Signatur - - - Copy the current signature to the system clipboard - Kopier valgt signatur til utklippstavle - - - Sign the message to prove you own this Bitcoin address - Signer meldingen for å bevise at du eier denne Bitcoin-adressen - - - Sign &Message - Signer &Melding - - - Reset all sign message fields - Tilbakestill alle felter for meldingssignering - - - Clear &All - Fjern &Alt - - - &Verify Message - &Verifiser Melding - - - 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! - Skriv inn mottakerens adresse, melding (forsikre deg om at du kopier linjeskift, mellomrom, faner osv. nøyaktig) og underskrift nedenfor for å bekrefte meldingen. Vær forsiktig så du ikke leser mer ut av signaturen enn hva som er i den signerte meldingen i seg selv, for å unngå å bli lurt av et man-in-the-middle-angrep. Merk at dette bare beviser at den som signerer kan motta med adressen, dette beviser ikke hvem som har sendt transaksjoner! - - - The Bitcoin address the message was signed with - Bitcoin-adressen meldingen ble signert med - - - Verify the message to ensure it was signed with the specified Bitcoin address - Verifiser meldingen for å være sikker på at den ble signert av den angitte Bitcoin-adressen - - - Verify &Message - Verifiser &Melding - - - Reset all verify message fields - Tilbakestill alle felter for meldingsverifikasjon - - - Click "Sign Message" to generate signature - Klikk "Signer Melding" for å generere signatur - - - The entered address is invalid. - Angitt adresse er ugyldig. - - - Please check the address and try again. - Vennligst sjekk adressen og prøv igjen. - - - The entered address does not refer to a key. - Angitt adresse refererer ikke til en nøkkel. - - - Wallet unlock was cancelled. - Opplåsing av lommebok ble avbrutt. - - - Private key for the entered address is not available. - Privat nøkkel for den angitte adressen er ikke tilgjengelig. - - - Message signing failed. - Signering av melding feilet. - - - Message signed. - Melding signert. - - - The signature could not be decoded. - Signaturen kunne ikke dekodes. - - - Please check the signature and try again. - Vennligst sjekk signaturen og prøv igjen. - - - The signature did not match the message digest. - Signaturen passer ikke til meldingen. - - - Message verification failed. - Verifikasjon av melding feilet. - - - Message verified. - Melding verifisert. - - - - SplashScreen - - Bitcoin Core - Bitcoin Core - - - The Bitcoin Core developers - Bitcoin Core utviklerne - - - [testnet] - [testnett] - - - - TrafficGraphWidget - - KB/s - KB/s - - - - TransactionDesc - - Open until %1 - Åpen til %1 - - - conflicted - konflikt - - - %1/offline - %1/frakoblet - - - %1/unconfirmed - %1/ubekreftet - - - %1 confirmations - %1 bekreftelser - - - Status - Status - - - , broadcast through %n node(s) - , kringkast gjennom %n node, kringkast gjennom %n noder - - - Date - Dato - - - Source - Kilde - - - Generated - Generert - - - From - Fra - - - To - Til - - - own address - egen adresse - - - watch-only - kun observerbar - - - label - merkelapp - - - Credit - Kredit - - - matures in %n more block(s) - blir moden om %n blokkblir moden om %n blokker - - - not accepted - ikke akseptert - - - Debit - Debet - - - Total debit - Total debet - - - Total credit - Total kredit - - - Transaction fee - Transaksjonsgebyr - - - Net amount - Nettobeløp - - - Message - Melding - - - Comment - Kommentar - - - Transaction ID - Transaksjons-ID - - - Merchant - Forhandler - - - 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. - Genererte bitcoins må modnes %1 blokker før de kan brukes. Da du genererte denne blokken ble den kringkastet på nettverket for å bli lagt til i kjeden av blokker. Hvis den ikke kommer med i kjeden vil den endre seg til "ikke akseptert" og pengene vil ikke kunne brukes. Dette vil noen ganger skje hvis en annen node genererer en blokk noen sekunder i tid fra din egen. - - - Debug information - Informasjon for feilsøk - - - Transaction - Transaksjon - - - Inputs - Inndata - - - Amount - Beløp - - - true - sann - - - false - usann + If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address. + Hvis dette er aktivert, men adressen for veksel er tom eller ugyldig, vil veksel bli sendt til en nylig generert adresse. - , has not been successfully broadcast yet - , har ikke blitt kringkastet med hell enda - - - Open for %n more block(s) - Åpen for %n blokk tilÅpen for %n blokker til + Custom change address + Egendefinert adresse for veksel - unknown - ukjent + Transaction Fee: + Transaksjonsgebyr: - - - TransactionDescDialog - Transaction details - Transaksjonsdetaljer + Choose... + Velg... - This pane shows a detailed description of the transaction - Her vises en detaljert beskrivelse av transaksjonen + collapse fee-settings + Legg ned gebyrinnstillinger - - - TransactionTableModel - Date - Dato + per kilobyte + per kilobyte - Type - Type + If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte. + Hvis den egendefinerte avgiften er satt til 1000 satoshis og transaksjonen bare er 250 bytes, da vil "per kilobyte" bare betale 250 satoshis i gebyr, mens "minstebeløp" betaler 1000 satoshis. For transaksjoner større enn en kilobyte vil begge betale for antall kilobyte. - Immature (%1 confirmations, will be available after %2) - Umoden (%1 bekreftelser, vil være tilgjengelig etter %2) - - - Open for %n more block(s) - Åpen for %n blokk tilÅpen for %n blokker til + Hide + Skjul - Open until %1 - Åpen til %1 + total at least + minstebeløp - Confirmed (%1 confirmations) - Bekreftet (%1 bekreftelser) + Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process. + Betaling av bare minimumsavgiften går helt fint så lenge det er mindre transaksjonsvolum enn plass i blokkene. Men vær klar over at dette kan ende opp i en transaksjon som aldri blir bekreftet når det er mer etterspørsel etter Bitcoin-transaksjoner enn nettverket kan behandle. - This block was not received by any other nodes and will probably not be accepted! - Denne blokken har ikke blitt mottatt av noen andre noder og vil sannsynligvis ikke bli akseptert! + (read the tooltip) + (les verktøytipset) - Generated but not accepted - Generert men ikke akseptert + Recommended: + Anbefalt: - Offline - Frakoblet + Custom: + Egendefinert: - Label - Merkelapp + (Smart fee not initialized yet. This usually takes a few blocks...) + (Smartgebyr ikke innført ennå. Dette tar vanligvis noen blokker...) - Unconfirmed - Ubekreftet + Confirmation time: + Bekreftelsestid: - Confirming (%1 of %2 recommended confirmations) - Bekrefter (%1 av %2 anbefalte bekreftelser) + normal + normal - Conflicted - Konflikt + fast + rask - Received with - Mottatt med + Send to multiple recipients at once + Send til flere enn en mottaker - Received from - Mottatt fra + Add &Recipient + Legg til &Mottaker - Sent to - Sendt til + Clear all fields of the form. + Fjern alle felter fra skjemaet. - Payment to yourself - Betaling til deg selv + Dust: + Støv: - Mined - Utvunnet + Clear &All + Fjern &Alt - watch-only - kun observerbar + Balance: + Saldo: - (n/a) - - + Confirm the send action + Bekreft sending - Transaction status. Hover over this field to show number of confirmations. - Transaksjonsstatus. Hold muspekeren over dette feltet for å se antall bekreftelser. + S&end + S&end + + + SendCoinsEntry - Date and time that the transaction was received. - Dato og tid for da transaksjonen ble mottat. + A&mount: + &Beløp: - Type of transaction. - Type transaksjon. + Pay &To: + Betal &Til: - Whether or not a watch-only address is involved in this transaction. - Hvorvidt en kun observerbar adresse er involvert i denne transaksjonen. + &Label: + &Merkelapp: - User-defined intent/purpose of the transaction. - Brukerdefinert intensjon/hensikt med transaksjonen. + Choose previously used address + Velg tidligere brukt adresse - Amount removed from or added to balance. - Beløp fjernet eller lagt til saldo. + This is a normal payment. + Dette er en normal betaling. - - - TransactionView - All - Alle + The Bitcoin address to send the payment to + Bitcoin-adressen betalingen skal sendes til - Today - I dag + Alt+A + Alt+A - This week - Denne uken + Paste address from clipboard + Lim inn adresse fra utklippstavlen - This month - Denne måneden + Alt+P + Alt+P - Last month - Forrige måned + Remove this entry + Fjern denne oppføringen - This year - Dette året + 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. + Gebyret vil bli trukket fra beløpet som blir sendt. Mottakeren vil motta mindre bitcoins enn det du skriver inn i beløpsfeltet. Hvis det er valgt flere mottakere, deles gebyret likt. - Range... - Intervall... + S&ubtract fee from amount + T&rekk fra gebyr fra beløp - Received with - Mottatt med + Message: + Melding: - Sent to - Sendt til + This is an unauthenticated payment request. + Dette er en uautorisert betalingsetterspørring. - To yourself - Til deg selv + This is an authenticated payment request. + Dette er en autorisert betalingsetterspørring. - Mined - Utvunnet + Enter a label for this address to add it to the list of used addresses + Skriv inn en merkelapp for denne adressen for å legge den til listen av brukte adresser - Other - Andre + 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. + En melding som var tilknyttet bitcoinen: URI vil bli lagret med transaksjonen for din oversikt. Denne meldingen vil ikke bli sendt over Bitcoin-nettverket. - Enter address or label to search - Skriv inn adresse eller merkelapp for søk + Pay To: + Betal Til: - Min amount - Minimumsbeløp + Memo: + Memo: + + + ShutdownWindow - Copy address - Kopier adresse + Do not shut down the computer until this window disappears. + Slå ikke av datamaskinen før dette vinduet forsvinner. + + + SignVerifyMessageDialog - Copy label - Kopier merkelapp + Signatures - Sign / Verify a Message + Signaturer - Signer / Verifiser en Melding - Copy amount - Kopier beløp + &Sign Message + &Signer Melding - Copy transaction ID - Kopier transaksjons-ID + 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. + Du kan signere meldinger/avtaler med adresser for å bevise at du kan motta bitcoins sendt til dem. Vær forsiktig med å signere noe vagt eller tilfeldig, siden phishing-angrep kan prøve å lure deg til å signere din identitet over til dem. Bare signer fullt detaljerte utsagn som du er enig i. - Copy raw transaction - Kopier råtransaksjon + The Bitcoin address to sign the message with + Bitcoin-adressen meldingen skal signeres med - Edit label - Rediger merkelapp + Choose previously used address + Velg tidligere brukt adresse - Show transaction details - Vis transaksjonsdetaljer + Alt+A + Alt+A - Export Transaction History - Eksporter Transaksjonshistorikk + Paste address from clipboard + Lim inn adresse fra utklippstavlen - Watch-only - Kun observer + Alt+P + Alt+P - Exporting Failed - Ekport Feilet + Enter the message you want to sign here + Skriv inn meldingen du vil signere her - There was an error trying to save the transaction history to %1. - En feil oppstod ved lagring av transaksjonshistorikken til %1. + Signature + Signatur - Exporting Successful - Ekport Fullført + Copy the current signature to the system clipboard + Kopier valgt signatur til utklippstavle - The transaction history was successfully saved to %1. - Transaksjonshistorikken ble lagret til %1. + Sign the message to prove you own this Bitcoin address + Signer meldingen for å bevise at du eier denne Bitcoin-adressen - Comma separated file (*.csv) - Kommaseparert fil (*.csv) + Sign &Message + Signer &Melding - Confirmed - Bekreftet + Reset all sign message fields + Tilbakestill alle felter for meldingssignering - Date - Dato + Clear &All + Fjern &Alt - Type - Type + &Verify Message + &Verifiser Melding - Label - Merkelapp + 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! + Skriv inn mottakerens adresse, melding (forsikre deg om at du kopier linjeskift, mellomrom, faner osv. nøyaktig) og underskrift nedenfor for å bekrefte meldingen. Vær forsiktig så du ikke leser mer ut av signaturen enn hva som er i den signerte meldingen i seg selv, for å unngå å bli lurt av et man-in-the-middle-angrep. Merk at dette bare beviser at den som signerer kan motta med adressen, dette beviser ikke hvem som har sendt transaksjoner! - Address - Adresse + The Bitcoin address the message was signed with + Bitcoin-adressen meldingen ble signert med - ID - ID + Verify the message to ensure it was signed with the specified Bitcoin address + Verifiser meldingen for å være sikker på at den ble signert av den angitte Bitcoin-adressen - Range: - Intervall: + Verify &Message + Verifiser &Melding - to - til + Reset all verify message fields + Tilbakestill alle felter for meldingsverifikasjon - UnitDisplayStatusBarControl + SplashScreen - Unit to show amounts in. Click to select another unit. - Enhet å vise beløper i. Klikk for å velge en annen enhet. + [testnet] + [testnett] - WalletFrame + TrafficGraphWidget - No wallet has been loaded. - Ingen lommebok har blitt lastet. + KB/s + KB/s - WalletModel + TransactionDescDialog - Send Coins - Send Bitcoins + This pane shows a detailed description of the transaction + Her vises en detaljert beskrivelse av transaksjonen - WalletView - - &Export - &Eksporter - - - Export the data in the current tab to a file - Eksporter data fra nåværende fane til fil - - - Backup Wallet - Sikkerhetskopier Lommebok - - - Wallet Data (*.dat) - Lommebokdata (*.dat) - - - Backup Failed - Sikkerhetskopiering Feilet - - - There was an error trying to save the wallet data to %1. - En feil oppstod ved lagring av lommebok til %1. - - - The wallet data was successfully saved to %1. - Lommeboken ble lagret til %1. - + UnitDisplayStatusBarControl - Backup Successful - Sikkerhetskopiering Fullført + Unit to show amounts in. Click to select another unit. + Enhet å vise beløper i. Klikk for å velge en annen enhet. @@ -2927,14 +1670,6 @@ If <category> is not supplied or if <category> = 1, output all debugging information. Hvis <category> ikke er oppgitt eller hvis <category> = 1, ta ut all informasjon for feilsøking. - - Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s) - Maksimalt samlede gebyrer (i %s) til å bruke i en enkelt lommeboktransaksjon; settes dette for lavt kan store transaksjoner kanskje avbrytes (standardverdi: %s) - - - Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. - Vennligst undersøk at din datamaskin har riktig dato og klokkeslett! Hvis klokken er stilt feil vil ikke Bitcoin Core fungere riktig. - Prune configured below the minimum of %d MiB. Please use a higher number. Beskjæringsmodus er konfigurert under minimum på %d MiB. Vennligst bruk et høyere nummer. @@ -2975,6 +1710,10 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Ta imot tilkoblinger fra utsiden (standardverdi: 1 hvis uten -proxy eller -connect) + + Bitcoin Core + Bitcoin Core + Bind to given address and always listen on it. Use [host]:port notation for IPv6 Bind til angitt adresse. Bruk [vertsmaskin]:port notasjon for IPv6 @@ -3003,10 +1742,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Dette er en forhåndssluppet testversjon - bruk på egen risiko - ikke for bruk til blokkutvinning eller bedriftsapplikasjoner - - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - Ute av stand til å binde til %s på denne datamaskinen. Bitcoin Core kjører sannsynligvis allerede. - Use UPnP to map the listening port (default: 1 when listening and no -proxy) Bruk UPnP for lytteport (standardverdi: 1 ved lytting og uten -proxy) @@ -3027,10 +1762,6 @@ Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Advarsel: Vi ser ikke ut til å være enige med våre noder! Du må oppgradere, eller andre noder må oppgradere. - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Advarsel: wallet.dat korrupt, data reddet! Original wallet.dat lagret som wallet.{timestamp}.bak i %s; hvis din saldo eller dine transaksjoner ikke er korrekte bør du gjenopprette fra en backup. - Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. Hvitelist noder som kobler til fra den oppgitte nettmasken eller IP-adressen. Kan oppgis flere ganger. @@ -3191,10 +1922,6 @@ Wallet options: Valg for lommebok: - - You need to rebuild the database using -reindex to change -txindex - Du må gjenoppbygge databasen med å bruke -reindex for å endre -txindex - 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 Tillat JSON-RPC-tilkoblinger fra angitt kilde. Gyldig for <ip> er en enkelt IP (f. eks. 1.2.3.4), et nettverk/nettmaske (f. eks. 1.2.3.4/255.255.255.0) eller et nettverk/CIDR (f. eks. 1.2.3.4/24). Dette alternativet kan angis flere ganger @@ -3207,10 +1934,6 @@ Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces) Bind til gitt adresse for å lytte for JSON-RPC-tilkoblinger. Bruk [host]:port notasjon for IPv6. Dette alternativet kan angis flere ganger (standardverdi: bind til alle grensesnitt) - - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - Ute av stand til å låse datamappen %s. Bitcoin Core kjører sannsynligvis allerede. - Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) Opprett nye filer med standardtillatelser i systemet, i stedet for umask 077 (kun virksom med lommebokfunksjonalitet slått av) @@ -3255,10 +1978,6 @@ Set maximum size of high-priority/low-fee transactions in bytes (default: %d) Sett maksimum størrelse for transaksjoner med høy prioritet / lavt gebyr, i bytes (standardverdi: %d) - - Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) - Angi antall tråder for mynt generering hvis aktivert (-1 = alle kjerner, standardverdi: %d) - The transaction amount is too small to send after the fee has been deducted Transaksjonsbeløpet er for lite til å sendes etter at gebyret er fratrukket @@ -3283,34 +2002,14 @@ Accept public REST requests (default: %u) Godta offentlige REST forespørsler (standardverdi: %u) - - Activating best chain... - Aktiverer beste kjede... - - - Attempt to recover private keys from a corrupt wallet.dat on startup - Forsøk å berge private nøkler fra en korrupt wallet.dat ved oppstart - Automatically create Tor hidden service (default: %d) Automatisk opprette Tor skjult tjeneste (standardverdi: %d) - - Cannot resolve -whitebind address: '%s' - Kan ikke løse -whitebind-adresse: '%s' - Connect through SOCKS5 proxy Koble til via SOCKS5-proxy - - Copyright (C) 2009-%i The Bitcoin Core Developers - Copyright (C) 2009-%i utviklerne av Bitcoin Core - - - Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - Feil ved lasting av wallet.dat: Lommeboken krever en nyere versjon av Bitcoin Core - Error reading from database, shutting down. Feil ved lesing fra database, stenger ned. @@ -3323,22 +2022,6 @@ Information Informasjon - - Initialization sanity check failed. Bitcoin Core is shutting down. - Sunnhetssjekk ved oppstart feilet. Bitcoin Core stenges ned. - - - Invalid amount for -maxtxfee=<amount>: '%s' - Ugyldig beløp for -maxtxfee=<amount>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Ugyldig mengde for -minrelaytxfee=<beløp>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - Ugyldig mengde for -mintxfee=<beløp>: '%s' - Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) Ugyldig beløp for -paytxfee=<amount>: '%s' (må være minst %s) @@ -3363,14 +2046,6 @@ RPC server options: Innstillinger for RPC-server: - - Rebuild block chain index from current blk000??.dat files on startup - Gjenopprett blokkjedeindeks fra gjeldende blk000??.dat filer ved oppstart - - - Receive and display P2P network alerts (default: %u) - Motta og vis P2P nettverksvarsler (standardvalg: %u) - Reducing -maxconnections from %d to %d, because of system limitations. Reduserer -maxconnections fra %d til %d, pga. systembegrensninger. @@ -3443,10 +2118,6 @@ Username for JSON-RPC connections Brukernavn for JSON-RPC forbindelser - - Wallet needed to be rewritten: restart Bitcoin Core to complete - Lommeboken måtte skrives på nytt: start Bitcoin Core på nytt for å fullføre - Warning Advarsel @@ -3463,10 +2134,6 @@ ZeroMQ notification options: Valg for ZeroMQ-meldinger: - - wallet.dat corrupt, salvage failed - wallet.dat korrupt, bergning feilet - Password for JSON-RPC connections Passord for JSON-RPC forbindelser @@ -3475,10 +2142,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) Utfør kommando når beste blokk endrer seg (%s i kommandoen erstattes med blokkens hash) - - This help message - Denne hjelpemeldingen - Allow DNS lookups for -addnode, -seednode and -connect Tillat oppslag i DNS for -addnode, -seednode og -connect @@ -3487,10 +2150,6 @@ Loading addresses... Laster adresser... - - Error loading wallet.dat: Wallet corrupted - Feil ved lasting av wallet.dat: Lommeboken er skadet - (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) (1 = behold metadata for transaksjon som f. eks. kontoeier og informasjon om betalingsanmodning, 2 = dropp metadata for transaksjon) @@ -3507,10 +2166,6 @@ Do not keep transactions in the mempool longer than <n> hours (default: %u) Ikke hold transaksjoner i minnet lenger enn <n> timer (standard: %u) - - Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. - Feil ved lesing av wallet.dat! Alle nøkler lest riktig, men transaksjonsdataene eller oppføringer i adresseboken mangler kanskje eller er feil. - Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) Gebyrer (i %s/Kb) mindre enn dette anses som null gebyr for laging av transaksjoner (standardverdi: %s) @@ -3563,14 +2218,6 @@ Always query for peer addresses via DNS lookup (default: %u) Alltid søk etter nodeadresser via DNS-oppslag (standardverdi: %u) - - Error loading wallet.dat - Feil ved lasting av wallet.dat - - - Generate coins (default: %u) - Generer mynter (standardverdi: %u) - How many blocks to check at startup (default: %u, 0 = all) Hvor mange blokker skal sjekkes ved oppstart (standardverdi: %u, 0 = alle) @@ -3655,18 +2302,6 @@ Unknown network specified in -onlynet: '%s' Ukjent nettverk angitt i -onlynet '%s' - - Cannot resolve -bind address: '%s' - Kunne ikke slå opp -bind adresse: '%s' - - - Cannot resolve -externalip address: '%s' - Kunne ikke slå opp -externalip adresse: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - Ugyldig beløp for -paytxfee=<beløp>: '%s' - Insufficient funds Utilstrekkelige midler diff --git a/src/qt/locale/bitcoin_nl.ts b/src/qt/locale/bitcoin_nl.ts index fe29959abf5ba..3009c154e334e 100644 --- a/src/qt/locale/bitcoin_nl.ts +++ b/src/qt/locale/bitcoin_nl.ts @@ -25,10 +25,6 @@ C&lose S&luiten - - &Copy Address - &Kopiëer Adres - Delete the currently selected address from the list Verwijder het geselecteerde adres van de lijst @@ -45,73 +41,6 @@ &Delete &Verwijder - - Choose the address to send coins to - Kies het adres om munten naar te versturen - - - Choose the address to receive coins with - Kies het adres om munten op te ontvangen - - - C&hoose - K&iezen - - - Sending addresses - Verstuuradressen - - - Receiving addresses - Ontvang adressen - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Dit zijn uw Bitcoinadressen om betalingen mee te doen. Controleer altijd het bedrag en het ontvang adres voordat u uw bitcoins verstuurt. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Dit zijn uw Bitcoinadressen waarmee u kunt betalen. We raden u aan om een nieuw ontvangstadres voor elke transactie te gebruiken. - - - Copy &Label - Kopiëer &Label - - - &Edit - &Bewerk - - - Export Address List - Exporteer adreslijst - - - Comma separated file (*.csv) - Kommagescheiden bestand (*.csv) - - - Exporting Failed - Export Mislukt - - - There was an error trying to save the address list to %1. Please try again. - Een fout is opgetreden tijdens het opslaan van deze adreslijst naar %1. Probeer het nogmaals. - - - - AddressTableModel - - Label - Label - - - Address - Adres - - - (no label) - (geen label) - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase Herhaal nieuw wachtwoord - - Encrypt wallet - Versleutel portemonnee - - - This operation needs your wallet passphrase to unlock the wallet. - Deze operatie vereist uw portemonneewachtwoord om de portemonnee te openen. - - - Unlock wallet - Open portemonnee - - - This operation needs your wallet passphrase to decrypt the wallet. - Deze operatie vereist uw portemonneewachtwoord om de portemonnee te ontsleutelen - - - Decrypt wallet - Ontsleutel portemonnee - - - Change passphrase - Wijzig wachtwoord - - - Confirm wallet encryption - Bevestig versleuteling van uw portemonnee - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Waarschuwing: Als u uw portemonnee versleutelt en uw wachtwoord vergeet, zult u <b>AL UW BITCOINS VERLIEZEN</b>! - - - Are you sure you wish to encrypt your wallet? - Weet u zeker dat u uw portemonnee wilt versleutelen? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Bitcoin Core zal nu afsluiten om het versleutelingsproces te voltooien. Hou er rekening mee dat versleuteling van uw portemonnee u niet volledig beschermt tegen diefstal van jouw bitcoins door malware op je computer. - - - 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. - BELANGRIJK: Elke eerder gemaakte backup van uw portemonneebestand dient u te vervangen door het nieuw gegenereerde, versleutelde portemonneebestand. Om veiligheidsredenen zullen eerdere backups van het niet-versleutelde portemonneebestand onbruikbaar worden zodra u uw nieuwe, versleutelde, portemonnee begint te gebruiken. - - - Warning: The Caps Lock key is on! - Waarschuwing: De Caps Locktoets staat aan! - - - Wallet encrypted - Portemonnee versleuteld - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Voer een nieuw wachtwoord in voor uw portemonnee.<br/>Gebruik een wachtwoord van <b>tien of meer willekeurige karakters</b>, of <b>acht of meer woorden</b>. - - - Enter the old passphrase and new passphrase to the wallet. - Voer het oude en nieuwe wachtwoord in voor uw portemonnee. - - - Wallet encryption failed - Portemonneeversleuteling mislukt - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Portemonneeversleuteling mislukt door een interne fout. Uw portemonnee is niet versleuteld. - - - The supplied passphrases do not match. - De opgegeven wachtwoorden komen niet overeen - - - Wallet unlock failed - Portemonnee openen mislukt - - - The passphrase entered for the wallet decryption was incorrect. - Het opgegeven wachtwoord voor de portemonnee-ontsleuteling is niet correct. - - - Wallet decryption failed - Portemonnee-ontsleuteling mislukt - - - Wallet passphrase was successfully changed. - Portemonneewachtwoord is met succes gewijzigd. - BanTableModel @@ -269,6 +110,14 @@ Quit application Programma afsluiten + + &About %1 + &Over %1 + + + Show information about %1 + Toon informatie over %1 + About &Qt Over &Qt @@ -281,6 +130,10 @@ &Options... &Opties... + + Modify configuration options for %1 + Wijzig configuratieopties voor %1 + &Encrypt Wallet... &Versleutel Portemonnee... @@ -305,14 +158,6 @@ Open &URI... Open &URI... - - Bitcoin Core client - Bitcoin Coreapplicatie - - - Importing blocks from disk... - Blokken aan het importeren vanaf harde schijf... - Reindexing blocks on disk... Bezig met herindexeren van blokken op harde schijf... @@ -357,10 +202,6 @@ &Receive &Ontvangen - - Show information about Bitcoin Core - Toon informatie over Bitcoin Core - &Show / Hide &Toon / Verberg @@ -397,22 +238,10 @@ Tabs toolbar Tab-werkbalk - - Bitcoin Core - Bitcoin Core - Request payments (generates QR codes and bitcoin: URIs) Vraag betaling aan (genereert QR-codes en bitcoin: URI's) - - &About Bitcoin Core - &Over Bitcoin Core - - - Modify configuration options for Bitcoin Core - Wijzig configuratieopties voor Bitcoin Core - Show the list of used sending addresses and labels Toon de lijst met gebruikte verstuuradressen en -labels @@ -427,16 +256,20 @@ &Command-line options - &Opdrachytregelopties - - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Toon het Bitcoin Core hulpbericht om een lijst te krijgen met mogelijke Bitcoinopdrachtregelopties + &Opdrachtregelopties %n active connection(s) to Bitcoin network %n actieve verbinding met Bitcoinnetwerk%n actieve verbindingen met Bitcoinnetwerk + + Indexing blocks on disk... + Bezig met indexeren van blokken op harde schijf... + + + Processing blocks on disk... + Bezig met verwerken van blokken op harde schijf... + No block source available... Geen bron voor blokken beschikbaar... @@ -493,6 +326,14 @@ Up to date Bijgewerkt + + Show the %1 help message to get a list with possible Bitcoin command-line options + Toon het %1 hulpbericht om een lijst te krijgen met mogelijke Bitcoin commandoregelopties + + + %1 client + %1 client + Catching up... Aan het bijwerken... @@ -544,13 +385,6 @@ Portemonnee is <b>versleuteld</b> en momenteel <b>gesloten</b> - - ClientModel - - Network Alert - Netwerkwaarschuwing - - CoinControlDialog @@ -629,150 +463,6 @@ Priority Prioriteit - - Copy address - Kopieer adres - - - Copy label - Kopieer label - - - Copy amount - Kopieer bedrag - - - Copy transaction ID - Kopieer transactie-ID - - - Lock unspent - Blokeer ongebruikte - - - Unlock unspent - Deblokkeer ongebruikte - - - Copy quantity - Kopieer aantal - - - Copy fee - Kopieerkosten - - - Copy after fee - Kopieernaheffing - - - Copy bytes - Kopieer bytes - - - Copy priority - Kopieer prioriteit - - - Copy dust - Kopieër stof - - - Copy change - Kopieer wisselgeld - - - highest - hoogste - - - higher - hoger - - - high - hoog - - - medium-high - gemiddeld hoog - - - medium - gemiddeld - - - low-medium - laag gemiddeld - - - low - laag - - - lower - lager - - - lowest - laagste - - - (%1 locked) - (%1 geblokeerd) - - - none - geen - - - This label turns red if the transaction size is greater than 1000 bytes. - Dit label wordt rood als de transactie groter is dan 1000 bytes. - - - This label turns red if the priority is smaller than "medium". - Dit label wordt rood als de prioriteit lager is dan "gemiddeld". - - - This label turns red if any recipient receives an amount smaller than %1. - Dit label wordt rood wanneer een ontvanger minder dan %1 krijgt. - - - Can vary +/- %1 satoshi(s) per input. - Kan per input +/- %1 satoshi(s) variëren. - - - yes - ja - - - no - nee - - - This means a fee of at least %1 per kB is required. - Dit betekent dat kosten van minimaal %1 per kB aan verbonden zijn. - - - Can vary +/- 1 byte per input. - Kan +/- 1 byte per invoer variëren. - - - Transactions with higher priority are more likely to get included into a block. - Transacties met een hogere prioriteit zullen eerder in een blok gezet worden. - - - (no label) - (geen label) - - - change from %1 (%2) - wijzig van %1 (%2) - - - (change) - (wijzig) - EditAddressDialog @@ -796,38 +486,6 @@ &Address &Adres - - New receiving address - Nieuw ontvangstadres - - - New sending address - Nieuw adres om naar te versturen - - - Edit receiving address - Bewerk ontvangstadres - - - Edit sending address - Bewerk adres om naar te versturen - - - The entered address "%1" is already in the address book. - Het opgegeven adres "%1" bestaat al in uw adresboek. - - - The entered address "%1" is not a valid Bitcoin address. - Het opgegeven adres "%1" is een ongeldig Bitcoinadres - - - Could not unlock wallet. - Kon de portemonnee niet openen. - - - New key generation failed. - Genereren nieuwe sleutel mislukt. - FreespaceChecker @@ -854,10 +512,6 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin Core - version versie @@ -867,8 +521,8 @@ (%1-bit) - About Bitcoin Core - Over Bitcoin Core + About %1 + Over %1 Command-line options @@ -907,8 +561,8 @@ Toon opstartscherm bij opstarten (standaard: %u) - Reset all settings changes made over the GUI - Reset alle wijzigingen aan instellingen gedaan met de GUI + Reset all settings changed in the GUI + Reset alle wijzigingen aan instellingen gedaan in de GUI @@ -918,16 +572,16 @@ Welkom - Welcome to Bitcoin Core. - Welkom bij Bitcoin Core + Welcome to %1. + Welkom bij %1. - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - Omdat dit de eerste keer is dat het programma gestart is, kunt u nu kiezen waar Bitcoin Core de data moet opslaan. + As this is the first time the program is launched, you can choose where %1 will store its data. + Omdat dit de eerste keer is dat het programma gestart is, kunt u nu kiezen waar %1 de data moet opslaan. - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - Bitcoin Core zal een kopie van de Bitcoinblokketen downloaden en opslaan. Tenminste %1 GB aan data wordt opgeslagen in deze map en het zal groeien in de tijd. De portemonnee wordt ook in deze map opgeslagen. + %1 will download and store a copy of the Bitcoin block chain. At least %2GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. + %1 zal een kopie van de Bitcoin blokketen downloaden en opslaan. Tenminste %2 GB aan data wordt opgeslagen in deze map en het zal groeien in de tijd. De portemonnee wordt ook in deze map opgeslagen. Use the default data directory @@ -937,10 +591,6 @@ Use a custom data directory: Gebruik een persoonlijke gegevensmap: - - Bitcoin Core - Bitcoin Core - Error: Specified data directory "%1" cannot be created. Fout: De gespecificeerde directory "%1" kan niet worden gecreëerd. @@ -976,10 +626,6 @@ Select payment request file Selecteer betalingsverzoek bestand - - Select payment request file to open - Selecteer betalingsverzoek bestand om te openen - OptionsDialog @@ -991,6 +637,14 @@ &Main &Algemeen + + Automatically start %1 after logging in to the system. + Start %1 automatisch na inloggen in het systeem. + + + &Start %1 on system login + &Start %1 bij het inloggen op het systeem + Size of &database cache Grootte van de &databasecache @@ -1019,10 +673,6 @@ 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. Minimaliseren in plaats van de applicatie af te sluiten wanneer het venster is afgesloten. Als deze optie is ingeschakeld, zal de toepassing pas worden afgesloten na het selecteren van Exit in het menu. - - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - Stel hier de taal van de applicatie in. Deze instelling zal van kracht worden na het herstarten van de applicatie. - 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 |. URL's van derden (bijvoorbeeld block explorer) die in de transacties tab verschijnen als contextmenuelementen. %s in de URL is vervangen door transactiehash. Verscheidene URL's zijn gescheiden door een verticale streep |. @@ -1047,14 +697,6 @@ &Network &Netwerk - - Automatically start Bitcoin Core after logging in to the system. - Bitcoin Core automatisch starten bij inloggen. - - - &Start Bitcoin Core on system login - &Start Bitcoin Core tijdens login. - (0 = auto, <0 = leave that many cores free) (0 = auto, <0 = laat dit aantal kernen vrij) @@ -1139,6 +781,14 @@ &Window &Scherm + + &Hide the icon from the system tray. + &Verberg het icoon van de systeembalk. + + + Hide tray icon + Verberg systeembalk icoon + Show only a tray icon after minimizing the window. Laat alleen een systeemvakicoon zien wanneer het venster geminimaliseerd is @@ -1159,6 +809,10 @@ User Interface &language: Taal &Gebruikersinterface: + + The user interface language can be set here. This setting will take effect after restarting %1. + De taal van de gebruikersinterface kan hier ingesteld worden. Deze instelling zal pas van kracht worden nadat %1 herstart wordt. + &Unit to show amounts in: &Eenheid om bedrag in te tonen: @@ -1284,169 +938,59 @@ - PaymentServer + PeerTableModel - URI handling - URI-behandeling + User Agent + User Agent - Invalid payment address %1 - Ongeldig betalingsadres %1 + Node/Service + Node/Dienst - Payment request rejected - Betalingsverzoek geweigerd + Ping Time + Ping tijd + + + QObject - Payment request network doesn't match client network. - Betalingsaanvraagnetwerk komt niet overeen met klantennetwerk. + Amount + Bedrag - Payment request is not initialized. - Betalingsaanvraag is niet geïnitialiseerd. + Enter a Bitcoin address (e.g. %1) + Voer een Bitcoinadres in (bijv. %1) - Requested payment amount of %1 is too small (considered dust). - Het gevraagde betalingsbedrag van %1 is te weinig (beschouwd als stof). + %1 d + %1 d - Payment request error - Fout bij betalingsverzoek + %1 h + %1 uur - Cannot start bitcoin: click-to-pay handler - Kan bitcoin niet starten: click-to-pay handler + %1 m + %1 m - Payment request fetch URL is invalid: %1 - URL om betalingsverzoek te verkrijgen is ongeldig: %1 + %1 s + %1 s - URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - URI kan niet verwerkt worden! Dit kan het gevolg zijn van een ongeldig Bitcoinadres of misvormde URI-parameters. + None + Geen - Payment request file handling - Betalingsverzoek bestandsafhandeling - - - Payment request file cannot be read! This can be caused by an invalid payment request file. - Betalingsverzoekbestand kan niet gelezen of verwerkt worden! Dit kan veroorzaakt worden door een ongeldig betalingsverzoek-bestand. - - - Payment request expired. - Betalingsverzoek verlopen. - - - Unverified payment requests to custom payment scripts are unsupported. - Niet-geverifieerde betalingsverzoeken naar aangepaste betaling scripts worden niet ondersteund. - - - Invalid payment request. - Ongeldig betalingsverzoek. - - - Refund from %1 - Restitutie van %1 - - - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - Betalingsverzoek %1 is te groot (%2 bytes, toegestaan ​​%3 bytes). - - - Error communicating with %1: %2 - Fout bij communiceren met %1: %2 - - - Payment request cannot be parsed! - Betalingsverzoek kan niet juist worden ontleed of verwerkt! - - - Bad response from server %1 - Ongeldige respons van server %1 - - - Payment acknowledged - Betaling bevestigd - - - Network request error - Netwerkfout bij verzoek - - - - PeerTableModel - - User Agent - User Agent - - - Node/Service - Node/Dienst - - - Ping Time - Ping tijd - - - - QObject - - Amount - Bedrag - - - Enter a Bitcoin address (e.g. %1) - Voer een Bitcoinadres in (bijv. %1) - - - %1 d - %1 d - - - %1 h - %1 uur - - - %1 m - %1 m - - - %1 s - %1 s - - - None - Geen - - - N/A - N.v.t. + N/A + N.v.t. %1 ms %1 ms - - QRImageWidget - - &Save Image... - &Afbeelding opslaan... - - - &Copy Image - &Afbeelding kopiëren - - - Save QR Code - Sla QR-code op - - - PNG Image (*.png) - PNG afbeelding (*.png) - - RPCConsole @@ -1477,6 +1021,10 @@ Using BerkeleyDB version Gebruikt BerkeleyDB versie + + Datadir + Data map + Startup time Opstarttijd @@ -1513,10 +1061,6 @@ Memory usage Geheugengebruik - - Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. - Open het Bitcoin Core debuglogbestand van de huidige gegevensmap. Dit kan enkele seconden duren voor grote logbestanden. - Received Ontvangen @@ -1565,6 +1109,18 @@ User Agent User Agent + + Open the %1 debug log file from the current data directory. This can take a few seconds for large log files. + Open het %1 debug-logbestand van de huidige datamap. Dit kan een aantal seconden duren voor grote logbestanden. + + + Decrease font size + Verklein lettergrootte + + + Increase font size + Vergroot lettergrootte + Services Diensten @@ -1627,16 +1183,12 @@ In: - In; + In: Out: Uit: - - Build date - Bouwdatum - Debug log file Debuglogbestand @@ -1674,8 +1226,8 @@ &Maak Ban Ongedaan voor Node - Welcome to the Bitcoin Core RPC console. - Welkom op de Bitcoin Core RPC console. + Welcome to the %1 RPC console. + Welkom bij de %1 RPC-console. Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. @@ -1804,18 +1356,6 @@ Remove Verwijder - - Copy label - Kopieer label - - - Copy message - Kopieer bericht - - - Copy amount - Kopieer bedrag - ReceiveRequestDialog @@ -1835,73 +1375,6 @@ &Save Image... &Sla afbeelding op... - - Request payment to %1 - Betalingsverzoek tot %1 - - - Payment information - Betalingsinformatie - - - URI - URI - - - Address - Adres - - - Amount - Bedrag - - - Label - Label - - - Message - Bericht - - - Resulting URI too long, try to reduce the text for label / message. - Resulterende URI te lang, probeer de tekst korter te maken voor het label/bericht. - - - Error encoding URI into QR Code. - Fout tijdens encoderen URI in QR-code - - - - RecentRequestsTableModel - - Date - Datum - - - Label - Label - - - Message - Bericht - - - Amount - Bedrag - - - (no label) - (geen label) - - - (no message) - (geen bericht) - - - (no amount) - (geen bedrag) - SendCoinsDialog @@ -2021,14 +1494,6 @@ fast snel - - Send as zero-fee transaction if possible - Indien mogelijk, verstuur zonder transactiekosten - - - (confirmation may take longer) - (bevestiging kan langer duren) - Send to multiple recipients at once Verstuur in een keer aan verschillende ontvangers @@ -2055,850 +1520,216 @@ Confirm the send action - Bevestig de verstuuractie - - - S&end - V&erstuur - - - Confirm send coins - Bevestig versturen munten - - - %1 to %2 - %1 tot %2 - - - Copy quantity - Kopieer aantal - - - Copy amount - Kopieer bedrag - - - Copy fee - Kopieerkosten - - - Copy after fee - Kopieernaheffing - - - Copy bytes - Kopieer bytes - - - Copy priority - Kopieer prioriteit - - - Copy change - Kopieer wijziging - - - Total Amount %1 - Totaalbedrag %1 - - - or - of - - - The amount to pay must be larger than 0. - Het ingevoerde bedrag moet groter zijn dan 0. - - - The amount exceeds your balance. - Bedrag is hoger dan uw huidige saldo - - - The total exceeds your balance when the %1 transaction fee is included. - Totaal overschrijdt uw huidige saldo wanneer de %1 transactiekosten worden meegerekend - - - Transaction creation failed! - Transactie creatie niet gelukt! - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - De transactie was afgewezen. Dit kan gebeuren als u eerder uitgegeven munten opnieuw wilt versturen, zoals wanneer u een kopie van uw wallet.dat heeft gebruikt en in de kopie deze munten zijn gemarkeerd als uitgegeven, maar in de huidige nog niet. - - - A fee higher than %1 is considered an absurdly high fee. - Transactiekosten van meer dan %1 wordt beschouwd als een absurd hoge transactiekosten. - - - Payment request expired. - Betalingsverzoek verlopen. - - - Pay only the required fee of %1 - Betaal alleen de verplichte transactiekosten van %1 - - - Estimated to begin confirmation within %n block(s). - Schatting is dat bevestiging begint over %n blok.Schatting is dat bevestiging begint over %n blokken. - - - The recipient address is not valid. Please recheck. - Het adres van de ontvanger is niet geldig. Gelieve opnieuw te controleren.. - - - Duplicate address found: addresses should only be used once each. - Dubbel adres gevonden: adressen mogen maar één keer worden gebruikt worden. - - - Warning: Invalid Bitcoin address - Waarschuwing: Ongeldig Bitcoinadres - - - (no label) - (geen label) - - - Warning: Unknown change address - Waarschuwing: Onbekend wisselgeldadres - - - Copy dust - Kopieër stof - - - Are you sure you want to send? - Weet u zeker dat u wilt versturen? - - - added as transaction fee - toegevoegd als transactiekosten - - - - SendCoinsEntry - - A&mount: - B&edrag: - - - Pay &To: - Betaal &Aan: - - - Enter a label for this address to add it to your address book - Vul een label in voor dit adres om het toe te voegen aan uw adresboek - - - &Label: - &Label: - - - Choose previously used address - Kies een eerder gebruikt adres - - - This is a normal payment. - Dit is een normale betaling. - - - The Bitcoin address to send the payment to - Het Bitcoinadres om betaling aan te versturen - - - Alt+A - Alt+A - - - Paste address from clipboard - Plak adres vanuit klembord - - - Alt+P - Alt+P - - - Remove this entry - Verwijder deze toevoeging - - - 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. - De transactiekosten zal worden afgetrokken van het bedrag dat verstuurd wordt. De ontvangers zullen minder bitcoins ontvangen dan ingevoerd is in het hoeveelheidsveld. Als er meerdere ontvangers geselecteerd zijn, dan worden de transactiekosten gelijk verdeeld. - - - S&ubtract fee from amount - Trek de transactiekosten a&f van het bedrag. - - - Message: - Bericht: - - - This is an unauthenticated payment request. - Dit is een niet-geverifieerd betalingsverzoek. - - - This is an authenticated payment request. - Dit is een geverifieerd betalingsverzoek. - - - Enter a label for this address to add it to the list of used addresses - Vul een label voor dit adres in om het aan de lijst met gebruikte adressen toe te voegen - - - 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. - Een bericht dat werd toegevoegd aan de bitcoin: URI welke wordt opgeslagen met de transactie ter referentie. Opmerking: Dit bericht zal niet worden verzonden over het Bitcoinnetwerk. - - - Pay To: - Betaal Aan: - - - Memo: - Memo: - - - - ShutdownWindow - - Bitcoin Core is shutting down... - Bitcoin Core is aan het afsluiten... - - - Do not shut down the computer until this window disappears. - Sluit de computer niet af totdat dit venster verdwenen is. - - - - SignVerifyMessageDialog - - Signatures - Sign / Verify a Message - Handtekeningen – Onderteken een bericht / Verifiëer een handtekening - - - &Sign Message - &Onderteken Bericht - - - 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. - U kunt berichten/overeenkomsten ondertekenen met uw adres om te bewijzen dat u Bitcoins kunt versturen. Wees voorzichtig met het ondertekenen van iets vaags of willekeurigs, omdat phishingaanvallen u kunnen proberen te misleiden tot het ondertekenen van overeenkomsten om uw identiteit aan hen toe te vertrouwen. Onderteken alleen volledig gedetailleerde verklaringen voordat u akkoord gaat. - - - The Bitcoin address to sign the message with - Het Bitcoinadres om bericht mee te ondertekenen - - - Choose previously used address - Kies een eerder gebruikt adres - - - Alt+A - Alt+A - - - Paste address from clipboard - Plak adres vanuit klembord - - - Alt+P - Alt+P - - - Enter the message you want to sign here - Typ hier het bericht dat u wilt ondertekenen - - - Signature - Handtekening - - - Copy the current signature to the system clipboard - Kopieer de huidige handtekening naar het systeemklembord - - - Sign the message to prove you own this Bitcoin address - Onderteken een bericht om te bewijzen dat u een bepaald Bitcoinadres bezit - - - Sign &Message - Onderteken &Bericht - - - Reset all sign message fields - Verwijder alles in de invulvelden - - - Clear &All - Verwijder &Alles - - - &Verify Message - &Verifiëer Bericht - - - 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! - Voer het adres van de ontvanger in, bericht (zorg ervoor dat de regeleinden, spaties, tabs etc. precies kloppen) en onderteken onderaan om het bericht te verifiëren. Wees voorzicht om niet meer in de ondertekening te lezen dan in het getekende bericht zelf, om te voorkomen dat je wordt aangevallen met een man-in-the-middle attack. Houd er mee rekening dat dit alleen de ondertekende partij bewijst met het ontvangen adres, er kan niet bewezen worden dat er een transactie heeft plaatsgevonden! - - - The Bitcoin address the message was signed with - Het Bitcoinadres waarmee het bericht ondertekend is - - - Verify the message to ensure it was signed with the specified Bitcoin address - Controleer een bericht om te verifiëren dat het gespecificeerde Bitcoinadres het bericht heeft ondertekend. - - - Verify &Message - Verifiëer &Bericht - - - Reset all verify message fields - Verwijder alles in de invulvelden - - - Click "Sign Message" to generate signature - Klik "Onderteken Bericht" om de handtekening te genereren - - - The entered address is invalid. - Het opgegeven adres is ongeldig. - - - Please check the address and try again. - Controleer s.v.p. het adres en probeer het opnieuw. - - - The entered address does not refer to a key. - Het opgegeven adres verwijst niet naar een sleutel. - - - Wallet unlock was cancelled. - Portemonnee-ontsleuteling is geannuleerd - - - Private key for the entered address is not available. - Geheime sleutel voor het ingevoerde adres is niet beschikbaar. - - - Message signing failed. - Ondertekenen van het bericht is mislukt. - - - Message signed. - Bericht ondertekend. - - - The signature could not be decoded. - De handtekening kon niet worden gedecodeerd. - - - Please check the signature and try again. - Controleer s.v.p. de handtekening en probeer het opnieuw. - - - The signature did not match the message digest. - De handtekening hoort niet bij het bericht. - - - Message verification failed. - Berichtverificatie mislukt. - - - Message verified. - Bericht correct geverifiëerd. - - - - SplashScreen - - Bitcoin Core - Bitcoin Core - - - The Bitcoin Core developers - De Bitcoin Core-ontwikkelaars - - - [testnet] - [testnetwerk] - - - - TrafficGraphWidget - - KB/s - KB/s - - - - TransactionDesc - - Open until %1 - Openen totdat %1 - - - conflicted - conflicterend - - - %1/offline - %1/offline - - - %1/unconfirmed - %1/onbevestigd - - - %1 confirmations - %1 bevestigingen - - - Status - Status - - - , broadcast through %n node(s) - , uitgezonden naar %n node, uitgezonden naar %n nodes - - - Date - Datum - - - Source - Bron - - - Generated - Gegenereerd - - - From - Van - - - To - Aan - - - own address - eigen adres - - - watch-only - alleen-bekijkbaar - - - label - label - - - Credit - Credit - - - matures in %n more block(s) - komt tot wasdom na %n nieuw blokkomt tot wasdom na %n nieuwe blokken - - - not accepted - niet geaccepteerd - - - Debit - Debet - - - Total debit - Totaal debit - - - Total credit - Totaal credit - - - Transaction fee - Transactiekosten - - - Net amount - Netto bedrag - - - Message - Bericht - - - Comment - Opmerking - - - Transaction ID - Transactie-ID: - - - Merchant - Handelaar - - - 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. - Gegenereerde munten moeten %1 blokken rijpen voordat ze kunnen worden besteed. Toen dit blok gegenereerd werd, werd het uitgezonden naar het netwerk om aan de blokketen toegevoegd te worden. Als het niet lukt om in de keten toegevoegd te worden, zal de status te veranderen naar "niet geaccepteerd" en het zal deze niet besteedbaar zijn. Dit kan soms gebeuren als een ander knooppunt een blok genereert binnen een paar seconden na die van u. - - - Debug information - Debuginformatie - - - Transaction - Transactie - - - Inputs - Inputs - - - Amount - Bedrag - - - true - waar - - - false - onwaar - - - , has not been successfully broadcast yet - , is nog niet met succes uitgezonden - - - Open for %n more block(s) - Open voor nog %n blokOpen voor nog %n blokken - - - unknown - onbekend - - - - TransactionDescDialog - - Transaction details - Transactiedetails - - - This pane shows a detailed description of the transaction - Dit venster laat een uitgebreide beschrijving van de transactie zien - - - - TransactionTableModel - - Date - Datum - - - Type - Type - - - Immature (%1 confirmations, will be available after %2) - Premature (%1 bevestigingen, zal beschikbaar zijn na %2) - - - Open for %n more block(s) - Open voor nog %n blokOpen voor nog %n blokken - - - Open until %1 - Open tot %1 - - - Confirmed (%1 confirmations) - Bevestigd (%1 bevestigingen) - - - This block was not received by any other nodes and will probably not be accepted! - Dit blok is niet ontvangen bij andere nodes en zal waarschijnlijk niet worden geaccepteerd! - - - Generated but not accepted - Gegenereerd maar niet geaccepteerd - - - Offline - Niet verbonden - - - Label - Label - - - Unconfirmed - Onbevestigd - - - Confirming (%1 of %2 recommended confirmations) - Bevestigen (%1 van %2 aanbevolen bevestigingen) - - - Conflicted - Conflicterend - - - Received with - Ontvangen met - - - Received from - Ontvangen van - - - Sent to - Verstuurd aan - - - Payment to yourself - Betaling aan uzelf - - - Mined - Gedolven - - - watch-only - alleen-bekijkbaar + Bevestig de verstuuractie - (n/a) - (nvt) + S&end + V&erstuur + + + SendCoinsEntry - Transaction status. Hover over this field to show number of confirmations. - Transactiestatus. Houd de muiscursor boven dit veld om het aantal bevestigingen te laten zien. + A&mount: + B&edrag: - Date and time that the transaction was received. - Datum en tijd waarop deze transactie is ontvangen. + Pay &To: + Betaal &Aan: - Type of transaction. - Type transactie. + &Label: + &Label: - Whether or not a watch-only address is involved in this transaction. - Of er een alleen-bekijken adres is betrokken bij deze transactie. + Choose previously used address + Kies een eerder gebruikt adres - User-defined intent/purpose of the transaction. - Door gebruiker gedefinieerde intentie/doel van de transactie + This is a normal payment. + Dit is een normale betaling. - Amount removed from or added to balance. - Bedrag verwijderd van of toegevoegd aan saldo + The Bitcoin address to send the payment to + Het Bitcoinadres om betaling aan te versturen - - - TransactionView - All - Alles + Alt+A + Alt+A - Today - Vandaag + Paste address from clipboard + Plak adres vanuit klembord - This week - Deze week + Alt+P + Alt+P - This month - Deze maand + Remove this entry + Verwijder deze toevoeging - Last month - Vorige maand + 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. + De transactiekosten zal worden afgetrokken van het bedrag dat verstuurd wordt. De ontvangers zullen minder bitcoins ontvangen dan ingevoerd is in het hoeveelheidsveld. Als er meerdere ontvangers geselecteerd zijn, dan worden de transactiekosten gelijk verdeeld. - This year - Dit jaar + S&ubtract fee from amount + Trek de transactiekosten a&f van het bedrag. - Range... - Bereik... + Message: + Bericht: - Received with - Ontvangen met + This is an unauthenticated payment request. + Dit is een niet-geverifieerd betalingsverzoek. - Sent to - Verstuurd aan + This is an authenticated payment request. + Dit is een geverifieerd betalingsverzoek. - To yourself - Aan uzelf + Enter a label for this address to add it to the list of used addresses + Vul een label voor dit adres in om het aan de lijst met gebruikte adressen toe te voegen - Mined - Gedolven + 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. + Een bericht dat werd toegevoegd aan de bitcoin: URI welke wordt opgeslagen met de transactie ter referentie. Opmerking: Dit bericht zal niet worden verzonden over het Bitcoinnetwerk. - Other - Anders + Pay To: + Betaal Aan: - Enter address or label to search - Vul adres of label in om te zoeken + Memo: + Memo: + + + ShutdownWindow - Min amount - Min. bedrag + %1 is shutting down... + %1 is aan het afsluiten... - Copy address - Kopieer adres + Do not shut down the computer until this window disappears. + Sluit de computer niet af totdat dit venster verdwenen is. + + + SignVerifyMessageDialog - Copy label - Kopieer label + Signatures - Sign / Verify a Message + Handtekeningen – Onderteken een bericht / Verifiëer een handtekening - Copy amount - Kopieer bedrag + &Sign Message + &Onderteken Bericht - Copy transaction ID - Kopieer transactie-ID + 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. + U kunt berichten/overeenkomsten ondertekenen met uw adres om te bewijzen dat u Bitcoins kunt versturen. Wees voorzichtig met het ondertekenen van iets vaags of willekeurigs, omdat phishingaanvallen u kunnen proberen te misleiden tot het ondertekenen van overeenkomsten om uw identiteit aan hen toe te vertrouwen. Onderteken alleen volledig gedetailleerde verklaringen voordat u akkoord gaat. - Copy raw transaction - Kopieer ruwe transactie + The Bitcoin address to sign the message with + Het Bitcoinadres om bericht mee te ondertekenen - Edit label - Bewerk label + Choose previously used address + Kies een eerder gebruikt adres - Show transaction details - Toon transactiedetails + Alt+A + Alt+A - Export Transaction History - Exporteer Transactiegeschiedenis + Paste address from clipboard + Plak adres vanuit klembord - Watch-only - Alleen-bekijkbaar + Alt+P + Alt+P - Exporting Failed - Export Mislukt + Enter the message you want to sign here + Typ hier het bericht dat u wilt ondertekenen - There was an error trying to save the transaction history to %1. - Er is een fout opgetreden bij het opslaan van het transactiegeschiedenis naar %1. + Signature + Handtekening - Exporting Successful - Export Succesvol + Copy the current signature to the system clipboard + Kopieer de huidige handtekening naar het systeemklembord - The transaction history was successfully saved to %1. - Het transactiegeschiedenis was succesvol bewaard in %1. + Sign the message to prove you own this Bitcoin address + Onderteken een bericht om te bewijzen dat u een bepaald Bitcoinadres bezit - Comma separated file (*.csv) - Kommagescheiden bestand (*.csv) + Sign &Message + Onderteken &Bericht - Confirmed - Bevestigd + Reset all sign message fields + Verwijder alles in de invulvelden - Date - Datum + Clear &All + Verwijder &Alles - Type - Type + &Verify Message + &Verifiëer Bericht - Label - Label + 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! + Voer het adres van de ontvanger in, bericht (zorg ervoor dat de regeleinden, spaties, tabs etc. precies kloppen) en onderteken onderaan om het bericht te verifiëren. Wees voorzicht om niet meer in de ondertekening te lezen dan in het getekende bericht zelf, om te voorkomen dat je wordt aangevallen met een man-in-the-middle attack. Houd er mee rekening dat dit alleen de ondertekende partij bewijst met het ontvangen adres, er kan niet bewezen worden dat er een transactie heeft plaatsgevonden! - Address - Adres + The Bitcoin address the message was signed with + Het Bitcoinadres waarmee het bericht ondertekend is - ID - ID + Verify the message to ensure it was signed with the specified Bitcoin address + Controleer een bericht om te verifiëren dat het gespecificeerde Bitcoinadres het bericht heeft ondertekend. - Range: - Bereik: + Verify &Message + Verifiëer &Bericht - to - naar + Reset all verify message fields + Verwijder alles in de invulvelden - UnitDisplayStatusBarControl + SplashScreen - Unit to show amounts in. Click to select another unit. - Eenheid om bedragen uit te drukken. Klik om een andere eenheid te selecteren. + [testnet] + [testnetwerk] - WalletFrame + TrafficGraphWidget - No wallet has been loaded. - Portemonnee werd niet geladen. + KB/s + KB/s - WalletModel + TransactionDescDialog - Send Coins - Verstuur Munten + This pane shows a detailed description of the transaction + Dit venster laat een uitgebreide beschrijving van de transactie zien - WalletView - - &Export - &Exporteer - - - Export the data in the current tab to a file - Exporteer de data in de huidige tab naar een bestand - - - Backup Wallet - Portemonnee backuppen - - - Wallet Data (*.dat) - Portemonneedata (*.dat) - - - Backup Failed - Backup Mislukt - - - There was an error trying to save the wallet data to %1. - Er is een fout opgetreden bij het wegschrijven van de portemonneedata naar %1. - - - The wallet data was successfully saved to %1. - De portemonneedata is succesvol opgeslagen in %1. - + UnitDisplayStatusBarControl - Backup Successful - Backup Succesvol + Unit to show amounts in. Click to select another unit. + Eenheid om bedragen uit te drukken. Klik om een andere eenheid te selecteren. @@ -2927,14 +1758,6 @@ If <category> is not supplied or if <category> = 1, output all debugging information. Als er geen <categorie> is opgegeven of als de <categorie> 1 is, laat dan alle debugginginformatie zien. - - Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s) - Maximum totale transactiekosten (in %s) om te gebruiken voor een enkele portemonneetransactie; als dit te laag is ingesteld kan het grote transacties verhinderen (default: %s) - - - Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. - Check a.u.b. of de datum en tijd van uw computer correct zijn! Als uw klok verkeerd staat zal Bitcoin Core niet correct werken. - Prune configured below the minimum of %d MiB. Please use a higher number. Snoeien is geconfigureerd on het minimum van %d MiB. Gebruik a.u.b. een hoger aantal. @@ -2975,6 +1798,10 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Accepteer verbindingen van buitenaf (standaard: 1 als geen -proxy of -connect is opgegeven) + + Bitcoin Core + Bitcoin Core + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. -fallbackfee is zeer hoog ingesteld! Dit zijn de transactie kosten die u mogelijk betaald wanneer de schattingen niet beschikbaar zijn. @@ -2991,6 +1818,10 @@ Bind to given address and always listen on it. Use [host]:port notation for IPv6 Bind aan opgegeven adres en luister er altijd op. Gebruik [host]:port notatie voor IPv6 + + Cannot obtain a lock on data directory %s. %s is probably already running. + Kan geen lock verkrijgen op gegevensmap %s. %s draait waarschijnlijk al. + Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup Verwijder alle transacties van de portemonnee en herstel alleen de delen van de blokketen door -rescan tijdens het opstarten @@ -2999,6 +1830,10 @@ Distributed under the MIT software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>. Uitgegeven onder de MIT-softwarelicentie, zie het bijgevoegde bestand COPYING of <http://www.opensource.org/licenses/mit-license.php>. + + Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Waarschuwing: Fout bij het lezen van %s! Alle sleutels zijn in goede orde uitgelezen, maar transactiedata of adresboeklemma's zouden kunnen ontbreken of fouten bevatten. + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) Voer opdracht uit zodra een portemonneetransactie verandert (%s in cmd wordt vervangen door TxID) @@ -3007,6 +1842,18 @@ Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) Forceer het doorsturen van transacties van goedgekeurde peers, zelfs wanneer deze niet voldoen aan de lokale doorstuur regels (standaard: %d) + + Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds) + Maximum toegestane peer tijd compensatie. Lokaal perspectief van tijd mag worden beinvloed door peers die met deze hoeveelheid voor of achter lopen. (standaard: %u seconden) + + + Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s) + Maximum totale transactiekosten (in %s) om te gebruiken in een enkele portemoneetransactie; als dit te laag is ingesteld kunnen grote transacties worden verhinderd (standaard: %s) + + + Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly. + Waarschuwing: Controleer dat de datum en tijd van uw computer correct zijn ingesteld! Bij een onjuist ingestelde klok zal %s niet goed werken. + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) Kies het aantal scriptverificatie processen (%u tot %d, 0 = auto, <0 = laat dit aantal kernen vrij, standaard: %d) @@ -3019,14 +1866,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Dit is een prerelease testversie – gebruik op eigen risico! Gebruik deze niet voor het delven van munten of handelsdoeleinden - - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - Niet in staat om %s te verbinden op deze computer. Bitcoin Core draait waarschijnlijk al. - - - Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. - Niet ondersteund argument -whitelistalwaysrelay genegeerd, gebruik -whitelistrelay en/of -whitelistforcerelay. - Use UPnP to map the listening port (default: 1 when listening and no -proxy) Gebruik UPnP om de luisterende poort te mappen (standaard: 1 als er geluisterd worden en geen -proxy is meegegeven) @@ -3043,22 +1882,18 @@ Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Waarschuwing: Het lijkt erop dat het netwerk geen consensus kan vinden! Sommige delvers lijken problemen te ondervinden. - - Warning: Unknown block versions being mined! It's possible unknown rules are in effect - Waarschuwing: Onbekende blok versies worden gemined! Er zijn mogelijk onbekende regels in werking getreden - Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Waarschuwing: Het lijkt erop dat we geen consensus kunnen vinden met onze peers! Mogelijk dient u te upgraden, of andere nodes moeten wellicht upgraden. - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Waarschuwing: wallet.dat is corrupt, data is veiliggesteld! Originele wallet.dat is opgeslagen als wallet.{tijdstip}.bak in %s; als uw balans of transacties incorrect zijn dient u een backup terug te zetten. - Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. Goedgekeurde peers die verbinden van het ingegeven netmask of IP adres. Kan meerdere keren gespecificeerd worden. + + You need to rebuild the database using -reindex-chainstate to change -txindex + Om -txindex te kunnen veranderen dient u de database opnieuw te bouwen met gebruik van -reindex-chainstate. + -maxmempool must be at least %d MB -maxmempool moet tenminste %d MB zijn @@ -3071,10 +1906,22 @@ Append comment to the user agent string Voeg commentaar toe aan de user agent string + + Attempt to recover private keys from a corrupt wallet on startup + Probeer privésleutels te herstellen van een corrupte wallet bij opstarten + Block creation options: Blokcreatie-opties: + + Cannot resolve -%s address: '%s' + Kan -%s adres niet herleiden: '%s' + + + Change index out of range + Wijzigingsindex buiten bereik + Connect only to the specified node(s) Verbind alleen naar de gespecificeerde node(s) @@ -3083,6 +1930,10 @@ Connection options: Verbindingsopties: + + Copyright (C) %i-%i + Auteursrecht (C) %i-%i + Corrupted block database detected Corrupte blokkendatabase gedetecteerd @@ -3127,6 +1978,18 @@ Error initializing wallet database environment %s! Probleem met initializeren van de database-omgeving %s! + + Error loading %s + Fout bij het laden van %s + + + Error loading %s: Wallet corrupted + Fout bij het laden van %s: Portomonnee corrupt + + + Error loading %s: Wallet requires newer version of %s + Fout bij laden %s: Portemonnee vereist een nieuwere versie van %s + Error loading block database Fout bij het laden van blokkendatabase @@ -3151,10 +2014,18 @@ Incorrect or no genesis block found. Wrong datadir for network? Incorrect of geen genesisblok gevonden. Verkeerde datamap voor het netwerk? + + Initialization sanity check failed. %s is shutting down. + Initialisatie sanity check mislukt. %s is aan het afsluiten. + Invalid -onion address: '%s' Ongeldig -onion adres '%s' + + Invalid amount for -%s=<amount>: '%s' + Ongeldig bedrag voor -%s=<bedrag>: '%s' + Invalid amount for -fallbackfee=<amount>: '%s' Ongeldig bedrag voor -fallbackfee=<bedrag>: '%s' @@ -3163,6 +2034,10 @@ Keep the transaction memory pool below <n> megabytes (default: %u) De transactiegeheugenpool moet onder de <n> megabytes blijven (standaard: %u) + + Loading banlist... + Verbanningslijst aan het laden... + Location of the auth cookie (default: data dir) Locatie van de auth cookie (standaard: data dir) @@ -3179,6 +2054,10 @@ Only connect to nodes in network <net> (ipv4, ipv6 or onion) Verbind alleen met nodes in netwerk <net> (ipv4, ipv6 of onion) + + Print this help message and exit + Print dit helpbericht en sluit af + Print version and exit Laat versie zien en sluit af @@ -3191,6 +2070,14 @@ Prune mode is incompatible with -txindex. Snoeimodus is niet-compatibel met -txindex + + Rebuild chain state and block index from the blk*.dat files on disk + Herbouw ketenstaat en block index met behulp van de blk*.dat bestanden op de hardeschijf + + + Rebuild chain state from the currently indexed blocks + Herbouw ketenstaat vanuit de huidige geindexeerde blokken + Set database cache size in megabytes (%d to %d, default: %d) Zet database cache grootte in megabytes (%d tot %d, standaard: %d) @@ -3203,6 +2090,10 @@ Specify wallet file (within data directory) Specificeer het portemonnee bestand (vanuit de gegevensmap) + + Unable to bind to %s on this computer. %s is probably already running. + Niet in staat om %s te verbinden op deze computer. %s draait waarschijnlijk al. + Unsupported argument -benchmark ignored, use -debug=bench. Niet-ondersteund argument -benchmark genegeerd, gebruik -debug=bench. @@ -3236,12 +2127,16 @@ Portemonnee %s bevindt zich buiten de gegevensmap %s - Wallet options: - Portemonnee instellingen: + Wallet debugging/testing options: + Portomonee debugging/testing opties: - You need to rebuild the database using -reindex to change -txindex - Om -txindex te kunnen veranderen dient u de database herbouwen met gebruik van -reindex. + Wallet needed to be rewritten: restart %s to complete + Portemonnee moest herschreven worden: Herstart %s om te voltooien + + + Wallet options: + Portemonnee instellingen: 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 @@ -3255,10 +2150,6 @@ Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces) Bind aan gegeven adres om te luisteren voor JSON-RPC verbindingen. Gebruik [host]:poort notatie voor IPv6. Deze optie kan meerdere keren gespecificeerd worden (standaard: bind aan alle interfaces. - - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - Kan geen lock verkrijgen op gegevensmap %s. Bitcoin Core draait waarschijnlijk al. - Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) Creër nieuwe bestanden met standaard systeem bestandsrechten in plaats van umask 077 (alleen effectief met uitgeschakelde portemonnee functionaliteit) @@ -3303,10 +2194,6 @@ Set maximum size of high-priority/low-fee transactions in bytes (default: %d) Stel maximumgrootte in bytes in voor hoge-prioriteits-/lage-transactiekosten-transacties (standaard: %d) - - Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) - Stel het aantal threads in voor het genereren van coins indien ingesteld (-1 = alle kernen, standaard: %d) - The transaction amount is too small to send after the fee has been deducted Het transactiebedrag is te klein om te versturen nadat de transactiekosten in mindering zijn gebracht @@ -3331,34 +2218,14 @@ Accept public REST requests (default: %u) Accepteer publieke REST-verzoeken (standaard: %u) - - Activating best chain... - Beste reeks activeren... - - - Attempt to recover private keys from a corrupt wallet.dat on startup - Probeer privésleutels te herstellen van een corrupte wallet.dat bij opstarten - Automatically create Tor hidden service (default: %d) Creëer automatisch verborgen dienst van Tor (standaard:%d) - - Cannot resolve -whitebind address: '%s' - Kan -whitebind adres niet herleiden: '%s' - Connect through SOCKS5 proxy Verbind door SOCKS5 proxy - - Copyright (C) 2009-%i The Bitcoin Core Developers - Auteursrecht (C) 2009-%i De Bitcoin Core Ontwikkelaars - - - Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - Fout bij laden wallet.dat: Portemonnee vereist een nieuwere versie van Bitcoin Core - Error reading from database, shutting down. Fout bij het lezen van de database, afsluiten. @@ -3371,22 +2238,6 @@ Information Informatie - - Initialization sanity check failed. Bitcoin Core is shutting down. - Initialisatie sanity check mislukt. Bitcoin Core is aan het afsluiten. - - - Invalid amount for -maxtxfee=<amount>: '%s' - Ongeldig bedrag voor -maxtxfee=<bedrag>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Ongeldig bedrag voor -minrelaytxfee=<bedrag>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - Ongeldig bedrag voor -mintxfee=<bedrag>: '%s' - Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) Ongeldig bedrag voor -paytxfee=<bedrag>: '%s' (Minimum %s) @@ -3411,14 +2262,6 @@ RPC server options: RPC server opties: - - Rebuild block chain index from current blk000??.dat files on startup - Herbouwen blokketenindex vanuit huidige blk000??.dat-bestanden bij opstarten? - - - Receive and display P2P network alerts (default: %u) - Ontvang en toon P2P-netwerkwaarschuwingen (standaard: %u) - Reducing -maxconnections from %d to %d, because of system limitations. Verminder -maxconnections van %d naar %d, vanwege systeembeperkingen. @@ -3491,10 +2334,6 @@ Username for JSON-RPC connections Gebruikersnaam voor JSON-RPC-verbindingen - - Wallet needed to be rewritten: restart Bitcoin Core to complete - Portemonnee moest herschreven worden: Herstart Bitcoin Core om te voltooien - Warning Waarschuwing @@ -3515,10 +2354,6 @@ ZeroMQ notification options: ZeroMQ notificatieopties: - - wallet.dat corrupt, salvage failed - wallet.dat corrupt, veiligstellen mislukt - Password for JSON-RPC connections Wachtwoord voor JSON-RPC-verbindingen @@ -3527,10 +2362,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) Voer opdracht uit zodra het beste blok verandert (%s in cmd wordt vervangen door blokhash) - - This help message - Dit helpbericht - Allow DNS lookups for -addnode, -seednode and -connect Sta DNS-naslag toe voor -addnode, -seednode en -connect @@ -3539,10 +2370,6 @@ Loading addresses... Adressen aan het laden... - - Error loading wallet.dat: Wallet corrupted - Fout bij laden wallet.dat: Portemonnee corrupt - (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) (1 = behoudt tx meta data bijv. account eigenaar en betalingsverzoek informatie, 2. sla tx meta data niet op) @@ -3559,10 +2386,6 @@ Do not keep transactions in the mempool longer than <n> hours (default: %u) Bewaar transactie niet langer dan <n> uren in de geheugenpool (standaard: %u) - - Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. - Fout tijdens lezen van wallet.dat! Alle sleutels zijn correct te lezen, maar de transactiondatabase of adresboekingangen zijn mogelijk verdwenen of incorrect. - Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) Transactiekosten (in %s/kB) kleiner dan dit worden beschouwd dat geen transactiekosten in rekening worden gebracht voor transactiecreatie (standaard: %s) @@ -3599,6 +2422,10 @@ Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported. Niet-ondersteund argument -socks gevonden. Instellen van SOCKS-versie is niet meer mogelijk, alleen SOCKS5-proxies worden ondersteund. + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + Niet ondersteund argument -whitelistalwaysrelay genegeerd, gebruik -whitelistrelay en/of -whitelistforcerelay. + Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s) Gebruik een aparte SOCKS5 proxy om verborgen diensten van Tor te bereiken (standaard: %s) @@ -3608,20 +2435,20 @@ Gebruikersnaam en gehasht wachtwoord voor JSON-RPC-verbindingen. De velden <userpw> is in het formaat: <GEBRUIKERSNAAM>:<SALT>$<HASH>. Een kanoniek Pythonscript is inbegrepen in de share/rpcuser. Deze optie kan meerdere keren worden meegegeven - (default: %s) - (standaard: %s) + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + Waarschuwing: Onbekende blok versies worden gemined! Er zijn mogelijk onbekende regels in werking getreden - Always query for peer addresses via DNS lookup (default: %u) - Vind anderen door middel van een DNS-naslag (standaard: %u) + Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup. + Waarschuwing: portomonee bestand is corrupt, data is veiliggesteld! Originele %s is opgeslagen als %s in %s; als uw balans of transacties incorrect zijn dient u een backup terug te zetten. - Error loading wallet.dat - Fout bij laden wallet.dat + (default: %s) + (standaard: %s) - Generate coins (default: %u) - Genereer munten (standaard: %u) + Always query for peer addresses via DNS lookup (default: %u) + Vind anderen door middel van een DNS-naslag (standaard: %u) How many blocks to check at startup (default: %u, 0 = all) @@ -3707,18 +2534,6 @@ Unknown network specified in -onlynet: '%s' Onbekend netwerk gespecificeerd in -onlynet: '%s' - - Cannot resolve -bind address: '%s' - Kan -bind adres niet herleiden: '%s' - - - Cannot resolve -externalip address: '%s' - Kan -externlip adres niet herleiden: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - Ongeldig bedrag voor -paytxfee=<bedrag>: '%s' - Insufficient funds Ontoereikend saldo diff --git a/src/qt/locale/bitcoin_pam.ts b/src/qt/locale/bitcoin_pam.ts index c5a0b17e801fe..12151a576c984 100644 --- a/src/qt/locale/bitcoin_pam.ts +++ b/src/qt/locale/bitcoin_pam.ts @@ -25,10 +25,6 @@ C&lose I&sara - - &Copy Address - &Kopyan ing address - Delete the currently selected address from the list Ilako ya ing kasalungsungan makapiling address keng listahan @@ -37,61 +33,6 @@ &Delete &Ilako - - Choose the address to send coins to - Pilinan ing address a magpadalang coins kang - - - Choose the address to receive coins with - Pilinan ing address a tumanggap coins a atin - - - C&hoose - P&ilinan - - - Sending addresses - Address king pamag-Send - - - Receiving addresses - Address king pamag-Tanggap - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Reni reng kekang Bitcoin address king pamagpadalang kabayaran. Lawan mulang masalese reng alaga ampo ing address na ning tumanggap bayu ka magpadalang barya. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Reni reng kekang Bitcoin addresses keng pamananggap bayad. Rerekomenda mi na gumamit kang bayung address keng balang transaksiyon. - - - Copy &Label - Kopyan ing &Label - - - &Edit - &Alilan - - - Comma separated file (*.csv) - Comma separated file (*.csv) - - - - AddressTableModel - - Label - Label - - - Address - Address - - - (no label) - (alang label) - AskPassphraseDialog @@ -111,82 +52,6 @@ Repeat new passphrase Pasibayuan ya ing bayung passphrase - - Encrypt wallet - I-encrypt ye ing wallet - - - This operation needs your wallet passphrase to unlock the wallet. - Ing operasyun a ini kailangan ne ing kekayung wallet passphrase, ban a-unlock ya ing wallet - - - Unlock wallet - Unlock ya ing wallet - - - This operation needs your wallet passphrase to decrypt the wallet. - Ing operasyun a ini kailangan ne ing kekang wallet passphrase ban a-decrypt ne ing wallet. - - - Decrypt wallet - I-decrypt ya ing wallet - - - Change passphrase - Alilan ya ing passphrase - - - Confirm wallet encryption - Kumpirman ya ing wallet encryption - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Kapabaluan: Istung in-encrypt me ing kekang wallet at meala ya ing passphrase na, ma-<b>ALA NO NGAN RING KEKANG BITCOINS</b> - - - Are you sure you wish to encrypt your wallet? - Siguradu na kang buri meng i-encrypt ing kekang wallet? - - - 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. - Mayalaga: Reng milabas a backups a gewa mu gamit ing wallet file mu dapat lamung mialilan bayung gawang encrypted wallet file. Para keng seguridad , reng milabas a backups dareng ali maka encrypt a wallet file ma-ala nala istung inumpisan mu nalang gamitan reng bayu, at me encrypt a wallet. - - - Warning: The Caps Lock key is on! - Kapabaluan: Makabuklat ya ing Caps Lock key! - - - Wallet encrypted - Me-encrypt ne ing wallet - - - Wallet encryption failed - Memali ya ing pamag-encrypt king wallet - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Memali ya ing encryption uli na ning ausan dang internal error. E ya me-encrypt ing wallet yu. - - - The supplied passphrases do not match. - E la mitutugma ring mibieng passphrase - - - Wallet unlock failed - Memali ya ing pamag-unlock king wallet - - - The passphrase entered for the wallet decryption was incorrect. - E ya istu ing passphrase a pepalub da para king wallet decryption - - - Wallet decryption failed - Me-mali ya ing pamag-decrypt king wallet - - - Wallet passphrase was successfully changed. - Mi-alilan ne ing passphrase na ning wallet. - BanTableModel @@ -309,10 +174,6 @@ Tabs toolbar Gamit para king Tabs - - Bitcoin Core - Kapilubluban ning Bitcoin - &Command-line options Pipamilian command-line @@ -362,13 +223,6 @@ Maka-<b>encrypt</b> ya ing wallet at kasalukuyan yang maka-<b>locked</b> - - ClientModel - - Network Alert - Alertu ning Network - - CoinControlDialog @@ -387,22 +241,6 @@ Confirmed Me-kumpirma - - Copy address - Kopyan ing address - - - Copy label - Kopyan ing label - - - Copy amount - Kopyan ing alaga - - - (no label) - (alang label) - EditAddressDialog @@ -418,48 +256,12 @@ &Address &Address - - New receiving address - Bayung address king pamagtanggap - - - New sending address - Bayung address king pamagpadala - - - Edit receiving address - Alilan ya ing address king pamagpadala - - - Edit sending address - Alilan ya ing address king pamagpadala - - - The entered address "%1" is already in the address book. - Ing pepalub yung address "%1" ati na yu king aklat dareng address - - - The entered address "%1" is not a valid Bitcoin address. - Ing pepalub yung address "%1" ali ya katanggap-tanggap a Bitcoin address. - - - Could not unlock wallet. - Ali ya bisang mag-unlock ing wallet - - - New key generation failed. - Memali ya ing pamangaua king key - FreespaceChecker HelpMessageDialog - - Bitcoin Core - Kapilubluban ning Bitcoin - version bersion @@ -483,10 +285,6 @@ Welcome Malaus ka - - Bitcoin Core - Kapilubluban ning Bitcoin - Error Mali @@ -613,9 +411,6 @@ Ing kekang kasalungsungan kabuuang balanse - - PaymentServer - PeerTableModel @@ -630,9 +425,6 @@ N/A - - QRImageWidget - RPCConsole @@ -691,10 +483,6 @@ Totals Kabuuan: - - Build date - Kaaldauan ning pamaglalang - Debug log file Debug log file @@ -718,60 +506,13 @@ &Label: &Label: - - Copy label - Kopyan ing label - - - Copy amount - Kopyan ing alaga - - + ReceiveRequestDialog Copy &Address &Kopyan ing address - - Address - Address - - - Amount - Alaga - - - Label - Label - - - Message - Mensayi - - - - RecentRequestsTableModel - - Date - Kaaldauan - - - Label - Label - - - Message - Mensayi - - - Amount - Alaga - - - (no label) - (alang label) - SendCoinsDialog @@ -815,31 +556,7 @@ S&end Ipadala - - Confirm send coins - Kumpirman ing pamagpadalang barya - - - Copy amount - Kopyan ing alaga - - - The amount to pay must be larger than 0. - Ing alaga na ning bayaran dapat mung mas matas ya king 0. - - - The amount exceeds your balance. - Ing alaga mipasobra ya king kekang balanse. - - - The total exceeds your balance when the %1 transaction fee is included. - Ing kabuuan mipasobra ya king kekang balanse istung inabe ya ing %1 a bayad king transaksion - - - (no label) - (alang label) - - + SendCoinsEntry @@ -850,10 +567,6 @@ Pay &To: Ibayad &kang: - - Enter a label for this address to add it to your address book - Magpalub kang label para king address a ini ban a-iabe me king aklat dareng address - &Label: &Label: @@ -948,65 +661,9 @@ Reset all verify message fields Ibalik king dati reng ngan fields na ning pamag beripikang mensayi - - Click "Sign Message" to generate signature - I-click ing "Pirman ing Mensayi" ban agawa ya ing metung a pirma - - - The entered address is invalid. - Ing milub a address e ya katanggap-tanggap. - - - Please check the address and try again. - Maliaring pakilawe pasibayu ing address at pasibayuan ya iti. - - - The entered address does not refer to a key. - Ing milub a address ali ya mag-refer king metung a key. - - - Wallet unlock was cancelled. - Me-kansela ya ing pamag-unlock king wallet. - - - Private key for the entered address is not available. - Ing private key para king milub a address, ala ya. - - - Message signing failed. - Me-mali ya ing pamag-pirma king mensayi . - - - Message signed. - Me-pirman ne ing mensayi. - - - The signature could not be decoded. - Ing pirma ali ya bisang ma-decode. - - - Please check the signature and try again. - Maliaring pakilawe pasibayu ing pirma kaibat pasibayuan ya iti. - - - The signature did not match the message digest. - Ing pirma ali ya makatugma king message digest. - - - Message verification failed. - Me-mali ya ing pamag-beripika king mensayi. - - - Message verified. - Me-beripika ne ing mensayi. - SplashScreen - - Bitcoin Core - Kapilubluban ning Bitcoin - [testnet] [testnet] @@ -1015,330 +672,16 @@ TrafficGraphWidget - - TransactionDesc - - Open until %1 - Makabuklat anggang %1 - - - %1/offline - %1/offline - - - %1/unconfirmed - %1/ali me-kumpirma - - - %1 confirmations - %1 kumpirmasion - - - Status - Kabilian - - - Date - Kaaldauan - - - Source - Pikuanan - - - Generated - Megawa - - - From - Menibat - - - To - Para kang - - - own address - sariling address - - - label - label - - - Credit - Credit - - - not accepted - ali metanggap - - - Debit - Debit - - - Transaction fee - Bayad king Transaksion - - - Net amount - Alaga dareng eganagana - - - Message - Mensayi - - - Comment - Komentu - - - Transaction ID - ID - - - Debug information - Impormasion ning Debug - - - Transaction - Transaksion - - - Amount - Alaga - - - true - tutu - - - false - e tutu - - - , has not been successfully broadcast yet - , eya matagumpeng mibalita - - - unknown - e miya balu - - TransactionDescDialog - - Transaction details - Detalye ning Transaksion - This pane shows a detailed description of the transaction Ining pane a ini magpakit yang detalyadung description ning transaksion - - TransactionTableModel - - Date - Kaaldauan - - - Type - Klase - - - Open until %1 - Makabuklat anggang %1 - - - Confirmed (%1 confirmations) - Me-kumpirma(%1 kumpirmasion) - - - This block was not received by any other nodes and will probably not be accepted! - Ing block a ini ali de atanggap deng aliwa pang nodes ania ali ya magsilbing tanggapan - - - Generated but not accepted - Me-generate ya oneng ali ya metanggap - - - Label - Label - - - Received with - Atanggap kayabe ning - - - Received from - Atanggap menibat kang - - - Sent to - Mipadala kang - - - Payment to yourself - Kabayaran keka - - - Mined - Me-mina - - - (n/a) - (n/a) - - - Transaction status. Hover over this field to show number of confirmations. - Status ning Transaksion: Itapat me babo na ning field a ini ban ipakit dala reng bilang dareng me-kumpirma na - - - Date and time that the transaction was received. - Aldo at oras nung kapilan me tanggap ya ing transaksion - - - Type of transaction. - Klase ning transaksion - - - Amount removed from or added to balance. - Alagang milako o miragdag king balanse. - - - - TransactionView - - All - Eganagana - - - Today - Aldo iti - - - This week - Paruminggung iti - - - This month - Bulan a iti - - - Last month - Milabas a bulan - - - This year - Banuang iti - - - Range... - Angganan... - - - Received with - Atanggap kayabe ning - - - Sent to - Mipadala kang - - - To yourself - Keng sarili mu - - - Mined - Me-mina - - - Other - Aliwa - - - Enter address or label to search - Magpalub kang address o label para pantunan - - - Min amount - Pekaditak a alaga - - - Copy address - Kopyan ing address - - - Copy label - Kopyan ing label - - - Copy amount - Kopyan ing alaga - - - Edit label - Alilan ing label - - - Show transaction details - Ipakit ing detalye ning transaksion - - - Comma separated file (*.csv) - Comma separated file (*.csv) - - - Confirmed - Me-kumpirma - - - Date - Kaaldauan - - - Type - Klase - - - Label - Label - - - Address - Address - - - ID - ID - - - Range: - Angga: - - - to - para kang - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - Send Coins - Magpadalang Barya - - - - WalletView - bitcoin-core @@ -1369,6 +712,10 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Tumanggap koneksion menibat king kilwal (default: 1 if no -proxy or -connect) + + Bitcoin Core + Kapilubluban ning Bitcoin + Block creation options: Pipamilian king pamag-gawang block: @@ -1401,26 +748,10 @@ Failed to listen on any port. Use -listen=0 if you want this. Memali ya ing pamakiramdam kareng gang nanung port. Gamita me ini -listen=0 nung buri me ini. - - Cannot resolve -whitebind address: '%s' - Eya me-resolve ing -whitebind address: '%s' - Information &Impormasion - - Invalid amount for -maxtxfee=<amount>: '%s' - Eya maliari ing alaga keng -maxtxfee=<amount>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Eya maliari ing alaga keng -minrelaytxfee=<amount>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - Eya maliari ing alaga keng -mintxfee=<amount>: '%s' - Send trace/debug info to console instead of debug.log file Magpadalang trace/debug info okeng console kesa keng debug.log file @@ -1445,10 +776,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) I-execute ing command istung mialilan ya ing best block (%s in cmd is replaced by block hash) - - This help message - Ining saup a mensayi - Allow DNS lookups for -addnode, -seednode and -connect Payagan ing pamaglawe DNS para king -addnode, -seednode and -connect @@ -1457,14 +784,6 @@ Loading addresses... Lo-load da ne ing address... - - Error loading wallet.dat: Wallet corrupted - Me-mali ya ing pamag-load king wallet.dat: Me-corrupt ya ing wallet - - - Error loading wallet.dat - Me-mali ya ing pamag-load king wallet.dat - Invalid -proxy address: '%s' Ali katanggap-tanggap a -proxy addresss: '%s' @@ -1473,18 +792,6 @@ Unknown network specified in -onlynet: '%s' E kilalang network ing mepili king -onlynet: '%s' - - Cannot resolve -bind address: '%s' - Eya me-resolve ing -bind address: '%s' - - - Cannot resolve -externalip address: '%s' - Eya me-resolve ing -externalip address: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - Eya maliari ing alaga keng -paytxfee=<amount>: '%s' - Insufficient funds Kulang a pondo diff --git a/src/qt/locale/bitcoin_pl.ts b/src/qt/locale/bitcoin_pl.ts index ffbacfd4929f4..6d41cbeef227e 100644 --- a/src/qt/locale/bitcoin_pl.ts +++ b/src/qt/locale/bitcoin_pl.ts @@ -3,7 +3,7 @@ AddressBookPage Right-click to edit address or label - Kliknij prawy przycisk aby edytować adres lub etykietę + Kliknij prawy przycisk myszy, aby edytować adres lub etykietę Create a new address @@ -25,10 +25,6 @@ C&lose Z&amknij - - &Copy Address - &Kopiuj adres - Delete the currently selected address from the list Usuń zaznaczony adres z listy @@ -45,73 +41,6 @@ &Delete &Usuń - - Choose the address to send coins to - Wybierz adres, na który chcesz wysłać monety - - - Choose the address to receive coins with - Wybierz adres, na który chcesz otrzymać monety - - - C&hoose - W&ybierz - - - Sending addresses - Adres wysyłania - - - Receiving addresses - Adres odbiorczy - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Tutaj znajdują się adresy Bitcoin na które wysyłasz płatności. Zawsze sprawdzaj ilość i adres odbiorcy przed wysyłką monet. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - To twoje adresy Bitcoin, na które otrzymujesz płatności. Zaleca się używanie nowych adresów odbiorczych dla każdej transakcji. - - - Copy &Label - Kopiuj &Etykietę - - - &Edit - &Modyfikuj - - - Export Address List - Eksportuj listę adresową - - - Comma separated file (*.csv) - Pliki (*.csv) rozdzielone przecinkami - - - Exporting Failed - Błąd przy próbie eksportowania - - - There was an error trying to save the address list to %1. Please try again. - Wystąpił błąd podczas próby zapisu listy adresów %1. Proszę spróbować ponownie. - - - - AddressTableModel - - Label - Etykieta - - - Address - Adres - - - (no label) - (brak etykiety) - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase Powtórz nowe hasło - - Encrypt wallet - Zaszyfruj portfel - - - This operation needs your wallet passphrase to unlock the wallet. - Operacja wymaga hasła portfela, aby go odblokować. - - - Unlock wallet - Odblokuj portfel - - - This operation needs your wallet passphrase to decrypt the wallet. - Operacja wymaga hasła portfela, aby go odszyfrować. - - - Decrypt wallet - Odszyfruj portfel - - - Change passphrase - Zmień hasło - - - Confirm wallet encryption - Potwierdź szyfrowanie portfela - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Uwaga: jeśli zaszyfrujesz swój portfel i zgubisz hasło <b>STRACISZ WSZYSTKIE SWOJE BITCOINY</b>! - - - Are you sure you wish to encrypt your wallet? - Jesteś pewien, że chcesz zaszyfrować swój portfel? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Program Bitcoin Core zamknie się, aby dokończyć proces szyfrowania. Pamiętaj, że szyfrowanie portfela nie zabezpiecza w pełni twoich bitcoinów przed kradzieżą przez złośliwe oprogramowanie mogące zainfekować twój komputer. - - - 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. - WAŻNE: Wszystkie wcześniejsze kopie pliku portfela powinny być zamienione na nowe, szyfrowane pliki. Z powodów bezpieczeństwa, poprzednie kopie nieszyfrowanych plików portfela staną się bezużyteczne jak tylko zaczniesz korzystać z nowego, szyfrowanego portfela. - - - Warning: The Caps Lock key is on! - Uwaga: klawisz Caps Lock jest włączony! - - - Wallet encrypted - Portfel zaszyfrowany - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Wprowadź nowe hasło do portfela.<br/>Proszę używać hasła złożonego z <b>10 lub więcej losowych znaków</b> albo <b>8 lub więcej słów.</b> - - - Enter the old passphrase and new passphrase to the wallet. - Podaj stare i nowe hasło do portfela. - - - Wallet encryption failed - Szyfrowanie portfela nie powiodło się - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Szyfrowanie portfela nie powiodło się z powodu wewnętrznego błędu. Twój portfel nie został zaszyfrowany. - - - The supplied passphrases do not match. - Podane hasła nie są takie same. - - - Wallet unlock failed - Odblokowanie portfela nie powiodło się - - - The passphrase entered for the wallet decryption was incorrect. - Wprowadzone hasło do odszyfrowania portfela jest niepoprawne. - - - Wallet decryption failed - Odszyfrowanie portfela nie powiodło się - - - Wallet passphrase was successfully changed. - Hasło portfela zostało pomyślnie zmienione. - BanTableModel @@ -269,6 +110,14 @@ Quit application Zamknij program + + &About %1 + &O %1 + + + Show information about %1 + Pokaż informacje o %1 + About &Qt O &Qt @@ -281,6 +130,10 @@ &Options... &Opcje... + + Modify configuration options for %1 + Zmień opcje konfiguracji dla %1 + &Encrypt Wallet... Zaszyfruj Portf&el @@ -305,14 +158,6 @@ Open &URI... Otwórz URI... - - Bitcoin Core client - Klient Rdzenia Bitcoina - - - Importing blocks from disk... - Importowanie bloków z dysku... - Reindexing blocks on disk... Ponowne indeksowanie bloków na dysku... @@ -357,10 +202,6 @@ &Receive Odbie&rz - - Show information about Bitcoin Core - Pokaż informacje o Rdzeniu Bitcoina - &Show / Hide &Pokaż / Ukryj @@ -397,22 +238,10 @@ Tabs toolbar Pasek zakładek - - Bitcoin Core - Rdzeń Bitcoina - Request payments (generates QR codes and bitcoin: URIs) Żądaj płatności (generuje kod QR oraz bitcoinowe URI) - - &About Bitcoin Core - &O Bitcoin Core - - - Modify configuration options for Bitcoin Core - Zmień opcje konfiguracji dla Bitcoin Core - Show the list of used sending addresses and labels Pokaż listę adresów i etykiet użytych do wysyłania @@ -429,14 +258,18 @@ &Command-line options &Opcje linii komend - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Pokaż pomoc Rdzenia Bitcoin, aby zobaczyć listę wszystkich opcji linii poleceń - %n active connection(s) to Bitcoin network %n aktywnych połączeń do sieci Bitcoin%n aktywnych połączeń do sieci Bitcoin%n aktywnych połączeń do sieci Bitcoin + + Indexing blocks on disk... + Indeksowanie bloków na dysku... + + + Processing blocks on disk... + Przetwarzanie blocks on disk... + No block source available... Brak dostępnych źródeł bloków... @@ -493,6 +326,14 @@ Up to date Aktualny + + Show the %1 help message to get a list with possible Bitcoin command-line options + Pokaż pomoc %1 aby zobaczyć listę wszystkich opcji lnii poleceń. + + + %1 client + %1 klient + Catching up... Trwa synchronizacja… @@ -544,13 +385,6 @@ Portfel jest <b>zaszyfrowany</b> i obecnie <b>zablokowany</b> - - ClientModel - - Network Alert - Komunikat Sieci - - CoinControlDialog @@ -629,150 +463,6 @@ Priority Priorytet - - Copy address - Kopiuj adres - - - Copy label - Kopiuj etykietę - - - Copy amount - Kopiuj kwotę - - - Copy transaction ID - Skopiuj ID transakcji - - - Lock unspent - Zablokuj niewydane - - - Unlock unspent - Odblokuj niewydane - - - Copy quantity - Skopiuj ilość - - - Copy fee - Skopiuj opłatę - - - Copy after fee - Skopiuj ilość po opłacie - - - Copy bytes - Skopiuj ilość bajtów - - - Copy priority - Skopiuj priorytet - - - Copy dust - Kopiuj kurz - - - Copy change - Skopiuj resztę - - - highest - najwyższa - - - higher - wyższa - - - high - wysoka - - - medium-high - średnio wysoki - - - medium - średnia - - - low-medium - średnio niski - - - low - niski - - - lower - niższy - - - lowest - najniższy - - - (%1 locked) - (%1 zablokowane) - - - none - żaden - - - This label turns red if the transaction size is greater than 1000 bytes. - Ta etykieta staje się czerwona, kiedy transakcja jest większa niż 1000 bajtów. - - - This label turns red if the priority is smaller than "medium". - Ta etykieta jest czerwona, jeżeli priorytet jest mniejszy niż "średni" - - - This label turns red if any recipient receives an amount smaller than %1. - Etykieta staje się czerwona kiedy którykolwiek odbiorca otrzymuje kwotę mniejszą niż %1. - - - Can vary +/- %1 satoshi(s) per input. - Waha się +/- %1 satoshi na wejście. - - - yes - tak - - - no - nie - - - This means a fee of at least %1 per kB is required. - Oznacza to wymaganą opłatę minimum %1 na kB. - - - Can vary +/- 1 byte per input. - Waha się +/- 1 bajt na wejście. - - - Transactions with higher priority are more likely to get included into a block. - Transakcje o wyższym priorytecie zwykle szybciej zostają dołączone do bloku. - - - (no label) - (brak etykiety) - - - change from %1 (%2) - reszta z %1 (%2) - - - (change) - (reszta) - EditAddressDialog @@ -796,38 +486,6 @@ &Address &Adres - - New receiving address - Nowy adres otrzymywania - - - New sending address - Nowy adres wysyłania - - - Edit receiving address - Zmień adres odbioru - - - Edit sending address - Zmień adres wysyłania - - - The entered address "%1" is already in the address book. - Wprowadzony adres «%1» już istnieje w książce adresowej. - - - The entered address "%1" is not a valid Bitcoin address. - Wprowadzony adres «%1"» nie jest poprawnym adresem bitcoinowym. - - - Could not unlock wallet. - Nie można było odblokować portfela. - - - New key generation failed. - Tworzenie nowego klucza nie powiodło się. - FreespaceChecker @@ -854,10 +512,6 @@ HelpMessageDialog - - Bitcoin Core - Rdzeń Bitcoina - version wersja @@ -867,8 +521,8 @@ (%1-bit) - About Bitcoin Core - O Bitcoin Core + About %1 + Informacje o %1 Command-line options @@ -907,8 +561,8 @@ Wyświetl okno powitalne podczas uruchamiania (domyślnie: %u) - Reset all settings changes made over the GUI - Ustaw jako domyślne wszystkie ustawienia interfejsu + Reset all settings changed in the GUI + Zresetuj wszystkie ustawienia zmienione w GUI @@ -918,16 +572,16 @@ Witaj - Welcome to Bitcoin Core. - Witaj w Bitcoin Core + Welcome to %1. + Witaj w %1. - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - Ponieważ jest to pierwsze uruchomienie programu, możesz wybrać gdzie Bitcoin Core będzie przechowywał swoje dane. + As this is the first time the program is launched, you can choose where %1 will store its data. + Ponieważ jest to pierwsze uruchomienie programu, możesz wybrać gdzie %1 będzie przechowywał swoje dane. - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - Program pobierze i będzie przechowywał kopię łańcucha bloków bitcoinowych. W wybranym katalogu musi być przynajmniej %1 GB miejsca, a z czasem ilość danych będzie rosła. Portfel będzie przechowywany w tym samym katalogu. + %1 will download and store a copy of the Bitcoin block chain. At least %2GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. + %1 pobierze i będzie przechowywał kopię łańcucha bloków Bitcoin. W wybranym katalogu zostanie zapisanych %2GB danych, a z czasem ta ilość będzie rosła. Portfel będzie przechowywany w tym samym katalogu. Use the default data directory @@ -937,10 +591,6 @@ Use a custom data directory: Użyj wybranego folderu dla danych - - Bitcoin Core - Rdzeń Bitcoina - Error: Specified data directory "%1" cannot be created. Błąd: podany folder danych «%1» nie mógł zostać utworzony. @@ -976,10 +626,6 @@ Select payment request file Otwórz żądanie zapłaty z pliku - - Select payment request file to open - Wybierz plik żądania zapłaty do otwarcia - OptionsDialog @@ -991,6 +637,14 @@ &Main Główne + + Automatically start %1 after logging in to the system. + Automatycznie uruchom %1 po zalogowaniu do systemu. + + + &Start %1 on system login + Uruchamiaj %1 wraz z zalogowaniem do &systemu + Size of &database cache Wielkość bufora bazy &danych @@ -1019,10 +673,6 @@ 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. Minimalizuje zamiast zakończyć działanie programu przy zamykaniu okna. Kiedy ta opcja jest włączona, program zakończy działanie po wybieraniu Zamknij w menu. - - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - Można tu ustawić język interfejsu uzytkownika. Żeby ustawienie przyniosło skutek trzeba uruchomić ponownie Bitcoin. - 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 |. Zewnętrzne URL podglądu transakcji (np. eksplorator bloków), które będą wyświetlały się w menu kontekstowym, w zakładce transakcji. %s będzie zamieniany w adresie na hash transakcji. Oddziel wiele adresów pionową kreską |. @@ -1047,14 +697,6 @@ &Network &Sieć - - Automatically start Bitcoin Core after logging in to the system. - Automatycznie uruchamia Bitcoin po zalogowaniu do systemu. - - - &Start Bitcoin Core on system login - Uruchamiaj Bitcoin Core wraz z zalogowaniem do &systemu - (0 = auto, <0 = leave that many cores free) (0 = automatycznie, <0 = zostaw tyle wolnych rdzeni) @@ -1139,6 +781,14 @@ &Window &Okno + + &Hide the icon from the system tray. + Ukryj ikonę z zasobnika systemowego. + + + Hide tray icon + Ukryj ikonę zasobnika + Show only a tray icon after minimizing the window. Pokazuj tylko ikonę przy zegarku po zminimalizowaniu okna. @@ -1159,6 +809,10 @@ User Interface &language: Język &użytkownika: + + The user interface language can be set here. This setting will take effect after restarting %1. + Można tu ustawić język interfejsu uzytkownika. Ustawienie przyniesie skutek po ponownym uruchomieniu %1. + &Unit to show amounts in: &Jednostka pokazywana przy kwocie: @@ -1284,169 +938,59 @@ - PaymentServer + PeerTableModel - URI handling - Obsługa URI + User Agent + Aplikacja kliencka - Invalid payment address %1 - błędny adres płatności %1 + Node/Service + Węzeł/Usługi - Payment request rejected - Żądanie płatności odrzucone + Ping Time + Czas odpowiedzi + + + QObject - Payment request network doesn't match client network. - Sieć żądania płatności nie odpowiada sieci klienta. + Amount + Kwota - Payment request is not initialized. - Żądanie płatności nie jest zainicjowane. + Enter a Bitcoin address (e.g. %1) + Wprowadź adres bitcoinowy (np. %1) - Requested payment amount of %1 is too small (considered dust). - Żądana kwota %1 jest za niska (uznano za kurz). + %1 d + %1 d - Payment request error - Błąd żądania płatności + %1 h + %1 h - Cannot start bitcoin: click-to-pay handler - Nie można uruchomić protokołu bitcoin: kliknij-by-zapłacić + %1 m + %1 m - Payment request fetch URL is invalid: %1 - URL pobrania żądania zapłaty jest nieprawidłowe: %1 + %1 s + %1 s - URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - URI nie może zostać przetworzony! Może to być spowodowane nieprawidłowym adresem Bitcoin lub uszkodzonymi parametrami URI. + None + Żaden - Payment request file handling - Przechwytywanie plików żądania płatności - - - Payment request file cannot be read! This can be caused by an invalid payment request file. - Plików żądania płatności nie może zostać odczytany. Mogło to być spowodowane nieprawidłowym plikiem żądania płatności. - - - Payment request expired. - Żądanie płatności upłynęło. - - - Unverified payment requests to custom payment scripts are unsupported. - Niezweryfikowane żądania płatności do własnych skryptów płatności są niewspierane. - - - Invalid payment request. - Nieprawidłowe żądanie płatności - - - Refund from %1 - Zwrot z %1 - - - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - Żądanie płatności %1 jest zbyt duże (%2 bajtów, dozwolone %3 bajtów). - - - Error communicating with %1: %2 - Błąd komunikacji z %1 : %2 - - - Payment request cannot be parsed! - Żądanie płatności nie może zostać przetworzone. - - - Bad response from server %1 - Błędna odpowiedź z serwera %1 - - - Payment acknowledged - Płatność potwierdzona - - - Network request error - Błąd żądania sieci - - - - PeerTableModel - - User Agent - Aplikacja kliencka - - - Node/Service - Węzeł/Usługi - - - Ping Time - Czas odpowiedzi - - - - QObject - - Amount - Kwota - - - Enter a Bitcoin address (e.g. %1) - Wprowadź adres bitcoinowy (np. %1) - - - %1 d - %1 d - - - %1 h - %1 h - - - %1 m - %1 m - - - %1 s - %1 s - - - None - Żaden - - - N/A - NIEDOSTĘPNE + N/A + NIEDOSTĘPNE %1 ms %1 ms - - QRImageWidget - - &Save Image... - &Zapisz obraz... - - - &Copy Image - &Kopiuj obraz - - - Save QR Code - Zapisz kod QR - - - PNG Image (*.png) - Obraz PNG (*.png) - - RPCConsole @@ -1477,6 +1021,10 @@ Using BerkeleyDB version Używana wersja BerkeleyDB + + Datadir + Katalog danych + Startup time Czas uruchomienia @@ -1513,10 +1061,6 @@ Memory usage Zużycie pamięci - - Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. - Otwórz plik logowania debugowania Bitcoin Core z obecnego katalogu z danymi. Może to potrwać kilka sekund przy większych plikach. - Received Otrzymane @@ -1565,6 +1109,18 @@ User Agent Aplikacja kliencka + + Open the %1 debug log file from the current data directory. This can take a few seconds for large log files. + Otwórz plik dziennika debugowania %1 z obecnego katalogu z danymi. Może to potrwać kilka sekund przy większych plikach. + + + Decrease font size + Zmniejsz rozmiar czcionki + + + Increase font size + Zwiększ rozmiar czcionki + Services Usługi @@ -1629,10 +1185,6 @@ Out: Wyjście: - - Build date - Data kompilacji - Debug log file Plik logowania debugowania @@ -1670,8 +1222,8 @@ Odblokuj węzeł - Welcome to the Bitcoin Core RPC console. - Witaj w konsoli Bitcoin Core RPC. + Welcome to the %1 RPC console. + Witaj w konsoli %1 RPC. Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. @@ -1800,18 +1352,6 @@ Remove Usuń - - Copy label - Kopiuj etykietę - - - Copy message - Kopiuj wiadomość - - - Copy amount - Kopiuj kwotę - ReceiveRequestDialog @@ -1831,73 +1371,6 @@ &Save Image... &Zapisz obraz... - - Request payment to %1 - Zażądaj płatności do %1 - - - Payment information - Informacje o płatności - - - URI - URI - - - Address - Adres - - - Amount - Kwota - - - Label - Etykieta - - - Message - Wiadomość - - - Resulting URI too long, try to reduce the text for label / message. - Wynikowy URI jest zbyt długi, spróbuj zmniejszyć tekst etykiety / wiadomości - - - Error encoding URI into QR Code. - Błąd kodowania URI w Kodzie QR. - - - - RecentRequestsTableModel - - Date - Data - - - Label - Etykieta - - - Message - Wiadomość - - - Amount - Kwota - - - (no label) - (brak etykiety) - - - (no message) - (brak wiadomości) - - - (no amount) - (brak kwoty) - SendCoinsDialog @@ -2015,887 +1488,245 @@ fast - szybko - - - Send as zero-fee transaction if possible - Wyślij bez opłaty jeżeli to możliwe - - - (confirmation may take longer) - (potwierdzenie może potrwać dłużej) - - - Send to multiple recipients at once - Wyślij do wielu odbiorców na raz - - - Add &Recipient - Dodaj Odbio&rcę - - - Clear all fields of the form. - Wyczyść wszystkie pola formularza. - - - Dust: - Pył: - - - Clear &All - Wyczyść &wszystko - - - Balance: - Saldo: - - - Confirm the send action - Potwierdź akcję wysyłania - - - S&end - Wy&syłka - - - Confirm send coins - Potwierdź wysyłanie monet - - - %1 to %2 - %1 do %2 - - - Copy quantity - Skopiuj ilość - - - Copy amount - Kopiuj kwotę - - - Copy fee - Skopiuj opłatę - - - Copy after fee - Skopiuj ilość po opłacie - - - Copy bytes - Skopiuj ilość bajtów - - - Copy priority - Skopiuj priorytet - - - Copy change - Skopiuj resztę - - - Total Amount %1 - Łączna kwota %1 - - - or - lub - - - The amount to pay must be larger than 0. - Kwota do zapłacenia musi być większa od 0. - - - The amount exceeds your balance. - Kwota przekracza twoje saldo. - - - The total exceeds your balance when the %1 transaction fee is included. - Suma przekracza twoje saldo, gdy doliczymy %1 prowizji transakcyjnej. - - - Transaction creation failed! - Utworzenie transakcji nie powiodło się! - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - Transakcja została odrzucona! Może się to zdarzyć jeśli część monet z portfela została już wydana używając kopii pliku wallet.dat i nie zostało to tutaj uwzględnione. - - - A fee higher than %1 is considered an absurdly high fee. - Opłata wyższa niż %1 jest uważana za szalenie wysoką. - - - Payment request expired. - Żądanie płatności upłynęło. - - - Pay only the required fee of %1 - Zapłać tylko wymaganą opłatę %1 - - - Estimated to begin confirmation within %n block(s). - Przybliżony czas zatwierdzenia: %n bloków.Przybliżony czas zatwierdzenia: %n bloków.Przybliżony czas zatwierdzenia: %n bloków. - - - The recipient address is not valid. Please recheck. - Adres odbiorcy jest nieprawidłowy, proszę sprawić ponownie. - - - Duplicate address found: addresses should only be used once each. - Znaleziono powtórzony adres, można wysłać tylko raz na każdy adres podczas jednej operacji wysyłania. - - - Warning: Invalid Bitcoin address - Ostrzeżenie: nieprawidłowy adres Bitcoin - - - (no label) - (brak etykiety) - - - Warning: Unknown change address - Ostrzeżenie: Nieznany adres reszty - - - Copy dust - Kopiuj kurz - - - Are you sure you want to send? - Czy na pewno chcesz wysłać? - - - added as transaction fee - dodano jako opłata transakcyjna - - - - SendCoinsEntry - - A&mount: - Su&ma: - - - Pay &To: - Zapłać &dla: - - - Enter a label for this address to add it to your address book - Wprowadź etykietę dla tego adresu by dodać go do książki adresowej - - - &Label: - &Etykieta: - - - Choose previously used address - Wybierz wcześniej użyty adres - - - This is a normal payment. - To jest standardowa płatność - - - The Bitcoin address to send the payment to - Adres Bitcoin gdzie wysłać płatność - - - Alt+A - Alt+A - - - Paste address from clipboard - Wklej adres ze schowka - - - Alt+P - Alt+P - - - Remove this entry - Usuń ten wpis - - - 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. - Opłata zostanie odjęta od kwoty wysyłane.Odbiorca otrzyma mniej niż bitcoins wpisz w polu kwoty. Jeśli wybrano kilku odbiorców, opłata jest podzielona równo. - - - S&ubtract fee from amount - Odejmij od wysokości opłaty - - - Message: - Wiadomość: - - - This is an unauthenticated payment request. - To żądanie zapłaty nie zostało zweryfikowane. - - - This is an authenticated payment request. - To żądanie zapłaty jest zweryfikowane. - - - Enter a label for this address to add it to the list of used addresses - Wprowadź etykietę dla tego adresu by dodać go do listy użytych adresów - - - 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. - Wiadomość, która została dołączona do URI bitcoin:, która będzie przechowywana wraz z transakcją w celach informacyjnych. Uwaga: Ta wiadomość nie będzie rozsyłana w sieci Bitcoin. - - - Pay To: - Wpłać do: - - - Memo: - Notatka: - - - - ShutdownWindow - - Bitcoin Core is shutting down... - Bitcoin Core się zamyka... - - - Do not shut down the computer until this window disappears. - Nie wyłączaj komputera dopóki to okno nie zniknie. - - - - SignVerifyMessageDialog - - Signatures - Sign / Verify a Message - Podpisy - Podpisz / zweryfikuj wiadomość - - - &Sign Message - Podpi&sz Wiadomość - - - 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. - Możesz podpisywać wiadomości swoimi adresami aby udowodnić, że jesteś ich właścicielem. Uważaj, aby nie podpisywać niczego co wzbudza Twoje podejrzenia, ponieważ ktoś może stosować phishing próbując nakłonić Cię do ich podpisania. Akceptuj i podpisuj tylko w pełni zrozumiałe komunikaty i wiadomości. - - - The Bitcoin address to sign the message with - Adres Bitcoin, za pomocą którego podpisać wiadomość - - - Choose previously used address - Wybierz wcześniej użyty adres - - - Alt+A - Alt+A - - - Paste address from clipboard - Wklej adres ze schowka - - - Alt+P - Alt+P - - - Enter the message you want to sign here - Tutaj wprowadź wiadomość, którą chcesz podpisać - - - Signature - Podpis - - - Copy the current signature to the system clipboard - Kopiuje aktualny podpis do schowka systemowego - - - Sign the message to prove you own this Bitcoin address - Podpisz wiadomość aby dowieść, że ten adres jest twój - - - Sign &Message - Podpisz Wiado&mość - - - Reset all sign message fields - Zresetuj wszystkie pola podpisanej wiadomości - - - Clear &All - Wyczyść &wszystko - - - &Verify Message - &Zweryfikuj wiadomość - - - 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! - Wpisz adres, wiadomość oraz sygnaturę (podpis) odbiorcy (upewnij się, że dokładnie skopiujesz wszystkie zakończenia linii, spacje, tabulacje itp.). Uważaj by nie dodać więcej do podpisu niż do samej podpisywanej wiadomości by uniknąć ataku man-in-the-middle. -Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadawca posiada klucz do adresu, natomiast nie potwierdza to, że poprawne wysłanie jakiejkolwiek transakcji! - - - The Bitcoin address the message was signed with - Adres Bitcoin, którym została podpisana wiadomość - - - Verify the message to ensure it was signed with the specified Bitcoin address - Zweryfikuj wiadomość, aby upewnić się, że została podpisana odpowiednim adresem Bitcoin. - - - Verify &Message - Zweryfikuj Wiado&mość - - - Reset all verify message fields - Resetuje wszystkie pola weryfikacji wiadomości - - - Click "Sign Message" to generate signature - Kliknij "Podpisz Wiadomość" żeby uzyskać podpis - - - The entered address is invalid. - Podany adres jest nieprawidłowy. - - - Please check the address and try again. - Proszę sprawdzić adres i spróbować ponownie. - - - The entered address does not refer to a key. - Wprowadzony adres nie odnosi się do klucza. - - - Wallet unlock was cancelled. - Odblokowanie portfela zostało anulowane. - - - Private key for the entered address is not available. - Klucz prywatny dla podanego adresu nie jest dostępny. - - - Message signing failed. - Podpisanie wiadomości nie powiodło się. - - - Message signed. - Wiadomość podpisana. - - - The signature could not be decoded. - Podpis nie może zostać zdekodowany. - - - Please check the signature and try again. - Sprawdź podpis i spróbuj ponownie. - - - The signature did not match the message digest. - Podpis nie odpowiada skrótowi wiadomości. - - - Message verification failed. - Weryfikacja wiadomości nie powiodła się. - - - Message verified. - Wiadomość zweryfikowana. - - - - SplashScreen - - Bitcoin Core - Rdzeń Bitcoina - - - The Bitcoin Core developers - Deweloperzy Bitcoin Core - - - [testnet] - [testnet] - - - - TrafficGraphWidget - - KB/s - KB/s - - - - TransactionDesc - - Open until %1 - Otwórz do %1 - - - conflicted - konflikt - - - %1/offline - %1/offline - - - %1/unconfirmed - %1/niezatwierdzone - - - %1 confirmations - %1 potwierdzeń - - - Status - Status - - - , broadcast through %n node(s) - , przekazywany przez %n węzłów, przekazywany przez %n węzłów, przekazywany przez %n węzłów - - - Date - Data - - - Source - Źródło - - - Generated - Wygenerowano - - - From - Od - - - To - Do - - - own address - własny adres - - - watch-only - tylko-obserwowany - - - label - etykieta - - - Credit - Przypisy - - - matures in %n more block(s) - potwierdzona przy %n blokach więcejpotwierdzona przy %n blokach więcejpotwierdzona przy %n blokach więcej - - - not accepted - niezaakceptowane - - - Debit - Debet - - - Total debit - Razem wychodzących - - - Total credit - Razem przychodzących - - - Transaction fee - Opłata transakcyjna - - - Net amount - Kwota netto - - - Message - Wiadomość - - - Comment - Komentarz - - - Transaction ID - ID transakcji - - - Merchant - Kupiec - - - 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. - Wygenerowane monety muszą dojrzeć przez %1 bloków zanim będzie można je wydać. Gdy wygenerowałeś ten blok został on ogłoszony w sieci i dodany do łańcucha bloków. Jeżeli nie uda mu się wejść do łańcucha jego status zostanie zmieniony na "nie zaakceptowano" i nie będzie można go wydać. To czasem zdarza się gdy inny węzeł wygeneruje blok w kilka sekund od twojego. - - - Debug information - Informacje debugowania - - - Transaction - Transakcja - - - Inputs - Wejścia - - - Amount - Kwota - - - true - prawda - - - false - fałsz - - - , has not been successfully broadcast yet - , nie został jeszcze pomyślnie rozesłany - - - Open for %n more block(s) - Otwórz dla %n następnych blokówOtwórz dla %n następnych blokówOtwórz dla %n następnych bloków - - - unknown - nieznany - - - - TransactionDescDialog - - Transaction details - Szczegóły transakcji - - - This pane shows a detailed description of the transaction - Ten panel pokazuje szczegółowy opis transakcji - - - - TransactionTableModel - - Date - Data - - - Type - Typ - - - Immature (%1 confirmations, will be available after %2) - Niedojrzała (%1 potwierdzeń, będzie dostępna po %2) - - - Open for %n more block(s) - Otwórz dla %n następnych blokówOtwórz dla %n następnych blokówOtwórz dla %n następnych bloków - - - Open until %1 - Otwórz do %1 - - - Confirmed (%1 confirmations) - Zatwierdzony (%1 potwierdzeń) - - - This block was not received by any other nodes and will probably not be accepted! - Ten blok nie został odebrany przez jakikolwiek inny węzeł i prawdopodobnie nie zostanie zaakceptowany! - - - Generated but not accepted - Wygenerowano ale nie zaakceptowano - - - Offline - Offline - - - Label - Etykieta - - - Unconfirmed - Niepotwierdzone: - - - Confirming (%1 of %2 recommended confirmations) - Potwierdzanie (%1 z %2 rekomendowanych potwierdzeń) + szybko - Conflicted - Konflikt + Send to multiple recipients at once + Wyślij do wielu odbiorców na raz - Received with - Otrzymane przez + Add &Recipient + Dodaj Odbio&rcę - Received from - Odebrano od + Clear all fields of the form. + Wyczyść wszystkie pola formularza. - Sent to - Wysłano do + Dust: + Pył: - Payment to yourself - Płatność do siebie + Clear &All + Wyczyść &wszystko - Mined - Wydobyto + Balance: + Saldo: - watch-only - tylko-obserwowany + Confirm the send action + Potwierdź akcję wysyłania - (n/a) - (brak) + S&end + Wy&syłka + + + SendCoinsEntry - Transaction status. Hover over this field to show number of confirmations. - Status transakcji. Najedź na pole, aby zobaczyć liczbę potwierdzeń. + A&mount: + Su&ma: - Date and time that the transaction was received. - Data i czas odebrania transakcji. + Pay &To: + Zapłać &dla: - Type of transaction. - Rodzaj transakcji. + &Label: + &Etykieta: - Whether or not a watch-only address is involved in this transaction. - Czy adres tylko-obserwowany jest lub nie użyty w tej transakcji. + Choose previously used address + Wybierz wcześniej użyty adres - User-defined intent/purpose of the transaction. - Zdefiniowana przez użytkownika intencja/cel transakcji. + This is a normal payment. + To jest standardowa płatność - Amount removed from or added to balance. - Kwota usunięta z lub dodana do konta. + The Bitcoin address to send the payment to + Adres Bitcoin gdzie wysłać płatność - - - TransactionView - All - Wszystko + Alt+A + Alt+A - Today - Dzisiaj + Paste address from clipboard + Wklej adres ze schowka - This week - W tym tygodniu + Alt+P + Alt+P - This month - W tym miesiącu + Remove this entry + Usuń ten wpis - Last month - W zeszłym miesiącu + 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. + Opłata zostanie odjęta od kwoty wysyłane.Odbiorca otrzyma mniej niż bitcoins wpisz w polu kwoty. Jeśli wybrano kilku odbiorców, opłata jest podzielona równo. - This year - W tym roku + S&ubtract fee from amount + Odejmij od wysokości opłaty - Range... - Zakres... + Message: + Wiadomość: - Received with - Otrzymane przez + This is an unauthenticated payment request. + To żądanie zapłaty nie zostało zweryfikowane. - Sent to - Wysłano do + This is an authenticated payment request. + To żądanie zapłaty jest zweryfikowane. - To yourself - Do siebie + Enter a label for this address to add it to the list of used addresses + Wprowadź etykietę dla tego adresu by dodać go do listy użytych adresów - Mined - Wydobyto + 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. + Wiadomość, która została dołączona do URI bitcoin:, która będzie przechowywana wraz z transakcją w celach informacyjnych. Uwaga: Ta wiadomość nie będzie rozsyłana w sieci Bitcoin. - Other - Inne + Pay To: + Wpłać do: - Enter address or label to search - Wprowadź adres albo etykietę żeby wyszukać + Memo: + Notatka: + + + ShutdownWindow - Min amount - Min suma + %1 is shutting down... + %1 się zamyka... - Copy address - Kopiuj adres + Do not shut down the computer until this window disappears. + Nie wyłączaj komputera dopóki to okno nie zniknie. + + + SignVerifyMessageDialog - Copy label - Kopiuj etykietę + Signatures - Sign / Verify a Message + Podpisy - Podpisz / zweryfikuj wiadomość - Copy amount - Kopiuj kwotę + &Sign Message + Podpi&sz Wiadomość - Copy transaction ID - Skopiuj ID transakcji + 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. + Możesz podpisywać wiadomości swoimi adresami aby udowodnić, że jesteś ich właścicielem. Uważaj, aby nie podpisywać niczego co wzbudza Twoje podejrzenia, ponieważ ktoś może stosować phishing próbując nakłonić Cię do ich podpisania. Akceptuj i podpisuj tylko w pełni zrozumiałe komunikaty i wiadomości. - Copy raw transaction - Skopiuj surowe dane transakcji + The Bitcoin address to sign the message with + Adres Bitcoin, za pomocą którego podpisać wiadomość - Edit label - Zmień etykietę + Choose previously used address + Wybierz wcześniej użyty adres - Show transaction details - Pokaż szczegóły transakcji + Alt+A + Alt+A - Export Transaction History - Eksport historii transakcji + Paste address from clipboard + Wklej adres ze schowka - Watch-only - Tylko obserwowany + Alt+P + Alt+P - Exporting Failed - Błąd przy próbie eksportu + Enter the message you want to sign here + Tutaj wprowadź wiadomość, którą chcesz podpisać - There was an error trying to save the transaction history to %1. - Wystąpił błąd przy próbie zapisu historii transakcji do %1. + Signature + Podpis - Exporting Successful - Eksport powiódł się + Copy the current signature to the system clipboard + Kopiuje aktualny podpis do schowka systemowego - The transaction history was successfully saved to %1. - Historia transakcji została zapisana do %1. + Sign the message to prove you own this Bitcoin address + Podpisz wiadomość aby dowieść, że ten adres jest twój - Comma separated file (*.csv) - CSV (rozdzielany przecinkami) + Sign &Message + Podpisz Wiado&mość - Confirmed - Potwierdzony + Reset all sign message fields + Zresetuj wszystkie pola podpisanej wiadomości - Date - Data + Clear &All + Wyczyść &wszystko - Type - Typ + &Verify Message + &Zweryfikuj wiadomość - Label - Etykieta + 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! + Wpisz adres, wiadomość oraz sygnaturę (podpis) odbiorcy (upewnij się, że dokładnie skopiujesz wszystkie zakończenia linii, spacje, tabulacje itp.). Uważaj by nie dodać więcej do podpisu niż do samej podpisywanej wiadomości by uniknąć ataku man-in-the-middle. +Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadawca posiada klucz do adresu, natomiast nie potwierdza to, że poprawne wysłanie jakiejkolwiek transakcji! - Address - Adres + The Bitcoin address the message was signed with + Adres Bitcoin, którym została podpisana wiadomość - ID - ID + Verify the message to ensure it was signed with the specified Bitcoin address + Zweryfikuj wiadomość, aby upewnić się, że została podpisana odpowiednim adresem Bitcoin. - Range: - Zakres: + Verify &Message + Zweryfikuj Wiado&mość - to - do + Reset all verify message fields + Resetuje wszystkie pola weryfikacji wiadomości - UnitDisplayStatusBarControl + SplashScreen - Unit to show amounts in. Click to select another unit. - Jednostka w jakiej pokazywane są kwoty. Kliknij aby wybrać inną. + [testnet] + [testnet] - WalletFrame + TrafficGraphWidget - No wallet has been loaded. - Nie załadowano żadnego portfela. + KB/s + KB/s - WalletModel + TransactionDescDialog - Send Coins - Wyślij monety + This pane shows a detailed description of the transaction + Ten panel pokazuje szczegółowy opis transakcji - WalletView - - &Export - &Eksportuj - - - Export the data in the current tab to a file - Eksportuj dane z aktywnej karty do pliku - - - Backup Wallet - Kopia zapasowa portfela - - - Wallet Data (*.dat) - Dane portfela (*.dat) - - - Backup Failed - Nie udało się wykonać kopii zapasowej - - - There was an error trying to save the wallet data to %1. - Wystąpił błąd przy próbie zapisu pliku portfela do %1. - - - The wallet data was successfully saved to %1. - Plik portfela został zapisany do %1. - + UnitDisplayStatusBarControl - Backup Successful - Wykonano kopię zapasową + Unit to show amounts in. Click to select another unit. + Jednostka w jakiej pokazywane są kwoty. Kliknij aby wybrać inną. @@ -2924,10 +1755,6 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw If <category> is not supplied or if <category> = 1, output all debugging information. Jeżeli <category> nie zostanie określona lub <category> = 1, wyświetl wszystkie informacje debugowania. - - Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. - Proszę sprawdzić czy data i czas na Twoim komputerze są poprawne! Jeżeli ustawienia zegara będą złe, Bitcoin Core nie będzie działał prawidłowo. - Prune configured below the minimum of %d MiB. Please use a higher number. Przycinanie skonfigurowano poniżej minimalnych %d MiB. Proszę użyć wyższej liczby. @@ -2956,6 +1783,14 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw Accept connections from outside (default: 1 if no -proxy or -connect) Akceptuj połączenia z zewnątrz (domyślnie: 1 jeśli nie ustawiono -proxy lub -connect) + + Bitcoin Core + Rdzeń Bitcoina + + + The %s developers + Deweloperzy %s + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. -fallbackfee ma ustawioną bardzo dużą wartość! Jest to prowizja za transakcje, którą możesz zapłacić gdy oszacowanie opłaty jest niemożliwe. @@ -2964,6 +1799,10 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw Bind to given address and always listen on it. Use [host]:port notation for IPv6 Skojarz z podanym adresem i nasłuchuj na nim. Użyj formatu [host]:port dla IPv6 + + Cannot obtain a lock on data directory %s. %s is probably already running. + Nie można uzyskać blokady na katalogu z danymi %s. %s najprawdopodobniej jest już uruchomiony. + Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup Usuwa wszystkie transakcje w portfelu i tylko odtwarza te części z łańcucha bloków poprzez -rescan przy starcie @@ -2972,6 +1811,10 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw Distributed under the MIT software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>. Rozprowadzane na licencji MIT, zobacz dołączony plik COPYING lub <http://www.opensource.org/licenses/mit-license.php>. + + Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Błąd odczytu %s! Wszystkie klucze zostały odczytane poprawnie, ale może brakować danych transakcji lub wpisów w książce adresowej, lub mogą one być nieprawidłowe. + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) Wykonaj polecenie, kiedy transakcja portfela ulegnie zmianie (%s w poleceniu zostanie zastąpione przez TxID) @@ -2980,6 +1823,10 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) Wymuś przekazywanie transakcji od osób z białej listy, nawet jeśli narusza to lokalną politykę przekazywania (default: %d) + + Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly. + Proszę sprawdzić czy data i czas na Twoim komputerze są poprawne! Jeżeli ustawienia zegara będą złe, %s nie będzie działał prawidłowo. + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) Ustaw liczbę wątków skryptu weryfikacyjnego (%u do %d, 0 = auto, <0 = zostaw tyle rdzeni wolnych, domyślnie: %d) @@ -2988,17 +1835,9 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw This is a pre-release test build - use at your own risk - do not use for mining or merchant applications To jest testowa wersja - używaj na własne ryzyko - nie używaj do wykopywania oraz przy aplikacjach kupieckich - - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - Nie można przywiązać z portem %s na tym komputerze. Bitcoin Core prawdopodobnie już działa. - - - Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. - Niewspierany argument -whitelistalwaysrelay zignorowany, użyj -whitelistrelay i/lub -whitelistforcerelay. - Use UPnP to map the listening port (default: 1 when listening and no -proxy) - Używaj UPnP do mapowania portu nasłuchu (domyślnie: 1 gdy nasłuchuje i brak -proxy) + Użyj UPnP do mapowania portu nasłuchu (domyślnie: 1 gdy nasłuchuje i brak -proxy) WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) @@ -3016,14 +1855,18 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Uwaga: Wygląda na to, że nie ma pełnej zgodności z naszymi peerami! Możliwe, że potrzebujesz aktualizacji bądź inne węzły jej potrzebują - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Ostrzeżenie: Odtworzono dane z uszkodzonego pliku wallet.dat! Oryginalny wallet.dat został zapisany jako wallet.{timestamp}.bak w %s; jeśli twoje saldo lub transakcje są niepoprawne powinieneś odtworzyć kopię zapasową. - Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. Dodawaj do białej listy węzły łączące się z podanej maski sieciowej lub adresu IP. Może być określona kilka razy. + + You need to rebuild the database using -reindex-chainstate to change -txindex + Musisz przebudować bazę używając -reindex-chainstate aby zmienić -txindex + + + %s corrupt, salvage failed + %s uszkodzony, odtworzenie się nie powiodło + -maxmempool must be at least %d MB -maxmempool musi być przynajmniej %d MB @@ -3032,6 +1875,10 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw <category> can be: <category> mogą być: + + Attempt to recover private keys from a corrupt wallet on startup + Próbuj odzyskać klucze prywatne z uszkodzonego portfela podczas uruchamiania. + Block creation options: Opcje tworzenia bloku: @@ -3044,6 +1891,10 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw Connection options: Opcje połączenia: + + Copyright (C) %i-%i + Prawa autorskie (C) %i-%i + Corrupted block database detected Wykryto uszkodzoną bazę bloków @@ -3072,6 +1923,18 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw Error initializing wallet database environment %s! Błąd inicjowania środowiska bazy portfela %s! + + Error loading %s + Błąd ładowania %s + + + Error loading %s: Wallet corrupted + Błąd ładowania %s: Uszkodzony portfel + + + Error loading %s: Wallet requires newer version of %s + Błąd ładowania %s: Portfel wymaga nowszej wersji %s + Error loading block database Błąd ładowania bazy bloków @@ -3096,10 +1959,18 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw Incorrect or no genesis block found. Wrong datadir for network? Nieprawidłowy lub brak bloku genezy. Błędny folder_danych dla sieci? + + Initialization sanity check failed. %s is shutting down. + Wstępna kontrola poprawności nie powiodła się. %s wyłącza się. + Invalid -onion address: '%s' Nieprawidłowy adres -onion: '%s' + + Invalid amount for -%s=<amount>: '%s' + Nieprawidłowa kwota dla -%s=<amount>: '%s' + Invalid amount for -fallbackfee=<amount>: '%s' Nieprawidłowa kwota dla -fallbackfee=<amount>: '%s' @@ -3116,6 +1987,10 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw Only connect to nodes in network <net> (ipv4, ipv6 or onion) Łącz z węzłami tylko w sieci <net> (ipv4, piv6 lub onion) + + Print this help message and exit + Wyświetl ten tekst pomocy i wyjdź + Print version and exit Wyświetl wersję i wyjdź @@ -3128,6 +2003,14 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw Prune mode is incompatible with -txindex. Tryb ograniczony jest niekompatybilny z -txindex. + + Rebuild chain state and block index from the blk*.dat files on disk + Odbuduj stan lańcucha i indeks bloków z obecnych na dysku plików blk*.dat + + + Rebuild chain state from the currently indexed blocks + Odbuduj stan łańcucha z aktualnie zindeksowanych bloków + Set database cache size in megabytes (%d to %d, default: %d) Ustaw wielkość pamięci podręcznej w megabajtach (%d do %d, domyślnie: %d) @@ -3140,6 +2023,10 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw Specify wallet file (within data directory) Określ plik portfela (w obrębie folderu danych) + + Unable to bind to %s on this computer. %s is probably already running. + Nie można przywiązać do %s na tym komputerze. %s prawdopodobnie jest już uruchomiony. + Unsupported argument -benchmark ignored, use -debug=bench. Niewspierany argument -benchmark zignorowany, użyj -debug=bench. @@ -3173,12 +2060,16 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw Portfel %s znajduje się poza folderem danych %s - Wallet options: - Opcje portfela: + Wallet debugging/testing options: + Opcje debugowania/testowania portfela: - You need to rebuild the database using -reindex to change -txindex - Musisz przebudować bazę używając parametru -reindex aby zmienić -txindex + Wallet needed to be rewritten: restart %s to complete + Portfel wymaga przepisania: zrestartuj %s aby ukończyć + + + Wallet options: + Opcje portfela: 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 @@ -3192,10 +2083,6 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces) Powiąż się z podanym adresem, aby nasłuchiwać połączenia JSON-RPC. Użyj notacji [host]:port dla IPv6. Ta opcja może być określona kilka razy (domyślnie: powiąż ze wszystkimi interfejsami) - - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - Nie można uzyskać blokady na katalogu z danymi %s. Rdzeń Bitcoin najprawdopodobniej jest już uruchomiony. - Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) Twórz nowe pliki z domyślnymi dla systemu uprawnieniami, zamiast umask 077 (skuteczne tylko przy wyłączonej funkcjonalności portfela) @@ -3232,10 +2119,6 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw Set maximum size of high-priority/low-fee transactions in bytes (default: %d) Ustaw maksymalny rozmiar transakcji o wysokim priorytecie/niskiej prowizji w bajtach (domyślnie: %d) - - Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) - Ustaw liczbę wątków dla generowania monet (-1 = wszystkie rdzenie, domyślnie: %d) - The transaction amount is too small to send after the fee has been deducted Zbyt niska kwota transakcji do wysłania po odjęciu opłaty @@ -3256,34 +2139,14 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw Accept public REST requests (default: %u) Akceptuj publiczne żądania REST (domyślnie: %u) - - Activating best chain... - Aktywuje najlepszy łańcuch - - - Attempt to recover private keys from a corrupt wallet.dat on startup - Próbuj podczas uruchamiania programu odzyskać klucze prywatne z uszkodzonego pliku wallet.dat - Automatically create Tor hidden service (default: %d) Stwórz automatycznie ukrytą usługę Tora (domyślnie: %d) - - Cannot resolve -whitebind address: '%s' - Nie można rozwiązać adresu -whitebind: '%s' - Connect through SOCKS5 proxy Połącz przez SOCKS5 proxy - - Copyright (C) 2009-%i The Bitcoin Core Developers - Copyright (C) 2009-%i The Bitcoin Core Developers - - - Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - Błąd ładowania wallet.dat: Portfel wymaga nowszej wersji Bitcoin Core - Error reading from database, shutting down. Błąd odczytu z bazy danych, wyłączam się. @@ -3296,22 +2159,6 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw Information Informacja - - Initialization sanity check failed. Bitcoin Core is shutting down. - Wstępna kontrola poprawności nie powiodła się. Bitcoin Core wyłącza się. - - - Invalid amount for -maxtxfee=<amount>: '%s' - Nieprawidłowa kwota dla -maxtxfee=<amount>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Nieprawidłowa kwota dla -minrelaytxfee=<amount>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - Nieprawidłowa kwota dla -mintxfee=<amount>: '%s' - Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) Nieprawidłowa kwota dla -paytxfee=<amount>: '%s' (musi być co najmniej %s) @@ -3336,14 +2183,6 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw RPC server options: Opcje serwera RPC: - - Rebuild block chain index from current blk000??.dat files on startup - Odbuduj indeks łańcucha bloków z obecnych plików blk000??.dat podczas ponownego uruchomienia - - - Receive and display P2P network alerts (default: %u) - Odbieranie i wyświetlanie alertów sieci P2P (domyślnie: %u) - Reducing -maxconnections from %d to %d, because of system limitations. Zmniejszanie -maxconnections z %d do %d z powodu ograniczeń systemu. @@ -3412,10 +2251,6 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw Username for JSON-RPC connections Nazwa użytkownika dla połączeń JSON-RPC - - Wallet needed to be rewritten: restart Bitcoin Core to complete - Portfel wymaga przepisania: zrestartuj Bitcoina aby ukończyć - Warning Ostrzeżenie @@ -3428,10 +2263,6 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw ZeroMQ notification options: Opcje powiadomień ZeroMQ: - - wallet.dat corrupt, salvage failed - wallet.dat uszkodzony, odtworzenie się nie powiodło - Password for JSON-RPC connections Hasło do połączeń JSON-RPC @@ -3440,10 +2271,6 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw Execute command when the best block changes (%s in cmd is replaced by block hash) Wykonaj polecenie kiedy najlepszy blok ulegnie zmianie (%s w komendzie zastanie zastąpione przez hash bloku) - - This help message - Ta wiadomość pomocy - Allow DNS lookups for -addnode, -seednode and -connect Zezwól -addnode, -seednode i -connect na łączenie się z serwerem DNS @@ -3452,17 +2279,13 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw Loading addresses... Wczytywanie adresów... - - Error loading wallet.dat: Wallet corrupted - Błąd ładowania wallet.dat: Uszkodzony portfel - (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) (1 = zachowaj wysłane metadane np. właściciel konta i informacje o żądaniach płatności, 2 = porzuć wysłane metadane) -maxtxfee is set very high! Fees this large could be paid on a single transaction. - -matxfee jest ustawione bardzo wysokie! Tak wysokie opłaty mogą być zapłacone w jednej transakcji. + -maxtxfee ma ustawioną badzo dużą wartość! Tak wysokie opłaty mogą być zapłacone w jednej transakcji. -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. @@ -3472,10 +2295,6 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw Do not keep transactions in the mempool longer than <n> hours (default: %u) Nie trzymaj w pamięci transakcji starszych niż <n> godz. (domyślnie: %u) - - Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. - Ostrzeżenie: błąd odczytu wallet.dat! Wszystkie klucze zostały odczytane, ale może brakować pewnych danych transakcji lub wpisów w książce adresowej lub mogą one być nieprawidłowe. - Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) Opłaty (w %s/Kb) mniejsze niż ta będą traktowane jako bez opłaty przy tworzeniu transakcji (domyślnie: %s) @@ -3506,16 +2325,24 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d) - Próbuje utrzymać ruch wychodzący poniżej zadanego (w MiB na dobę), 0 = bez limitu (domyślnie: %d) + Próbuje utrzymać ruch wychodzący poniżej zadanego (w MiB na 24h), 0 = bez limitu (domyślnie: %d) Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported. Znaleziono niewspierany argument -socks. Wybieranie wersji SOCKS nie jest już możliwe, wsparcie programu obejmuje tylko proxy SOCKS5 + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + Niewspierany argument -whitelistalwaysrelay zignorowany, użyj -whitelistrelay i/lub -whitelistforcerelay. + Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s) Użyj oddzielnego prozy SOCKS5 aby osiągnąć węzły w ukrytych usługach Tor (domyślnie: %s) + + Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup. + Ostrzeżenie: Odtworzono dane z uszkodzonego pliku portfela! Oryginalny %s został zapisany jako %s w %s; jeśli twoje saldo lub transakcje są niepoprawne powinieneś odtworzyć kopię zapasową. + (default: %s) (domyślnie: %s) @@ -3524,14 +2351,6 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw Always query for peer addresses via DNS lookup (default: %u) Zawsze wypytuj o adresy węzłów poprzez podejrzenie DNS (domyślnie: %u) - - Error loading wallet.dat - Błąd ładowania wallet.dat - - - Generate coins (default: %u) - Generuj monety (domyślnie: %u) - How many blocks to check at startup (default: %u, 0 = all) Ile bloków sprawdzić przy starcie (domyślnie: %u, 0 = wszystkie) @@ -3616,18 +2435,6 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw Unknown network specified in -onlynet: '%s' Nieznana sieć w -onlynet: '%s' - - Cannot resolve -bind address: '%s' - Nie można uzyskać adresu -bind: '%s' - - - Cannot resolve -externalip address: '%s' - Nie można uzyskać adresu -externalip: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - Nieprawidłowa kwota dla -paytxfee=<amount>: '%s' - Insufficient funds Niewystarczające środki diff --git a/src/qt/locale/bitcoin_pt_BR.ts b/src/qt/locale/bitcoin_pt_BR.ts index 1b92395c79809..fe9dd66269ff5 100644 --- a/src/qt/locale/bitcoin_pt_BR.ts +++ b/src/qt/locale/bitcoin_pt_BR.ts @@ -3,7 +3,7 @@ AddressBookPage Right-click to edit address or label - Clique com o botão direito para editar o endereço ou rótulo + Clique com o botão direito para editar o endereço ou rótulo Create a new address @@ -25,10 +25,6 @@ C&lose &Fechar - - &Copy Address - &Copiar Endereço - Delete the currently selected address from the list Excluir os endereços selecionados da lista @@ -45,73 +41,6 @@ &Delete &Excluir - - Choose the address to send coins to - Escolha o endereço para enviar moedas - - - Choose the address to receive coins with - Escolha o endereço para receber moedas - - - C&hoose - Escol&ha - - - Sending addresses - Endereços para envios - - - Receiving addresses - Endereços de recebimento - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Esses são seus endereços Bitcoin para enviar pagamentos. Confira sempre a quantia e o destinatário antes de enviar moedas. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Estes são os seus endereços Bitcoin para receber pagamentos. Recomenda-se a utilização de um novo endereço de recebimento para cada transação. - - - Copy &Label - Copiar &Rótulo - - - &Edit - &Editar - - - Export Address List - Exportar lista de endereços - - - Comma separated file (*.csv) - Arquivo separado por vírgulas (*. csv) - - - Exporting Failed - Exportação Falhou - - - There was an error trying to save the address list to %1. Please try again. - Ocorreu um erro ao tentar salvar a lista de endereço em %1.. Por favor tente novamente. - - - - AddressTableModel - - Label - Rótulo - - - Address - Endereço - - - (no label) - (Sem rótulo) - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase Repita a nova frase de segurança - - Encrypt wallet - Criptografar carteira - - - This operation needs your wallet passphrase to unlock the wallet. - Esta operação precisa de sua frase de segurança para desbloquear a carteira. - - - Unlock wallet - Desbloquear carteira - - - This operation needs your wallet passphrase to decrypt the wallet. - Esta operação precisa de sua frase de segurança para descriptografar a carteira. - - - Decrypt wallet - Descriptografar carteira - - - Change passphrase - Alterar frase de segurança - - - Confirm wallet encryption - Confirmar criptografia da carteira - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Atenção: Se você criptografar sua carteira e perder sua frase, você vai <b>perder todos os seus BITCOINS!</b> - - - Are you sure you wish to encrypt your wallet? - Tem certeza de que deseja criptografar sua carteira? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - O Bitcoin irá fechar agora para terminar o processo de criptografia. Lembre-se que criptografando sua carteira não te protege totalmente de ter seus bitcoins roubados por um malware que infectar seu computador. - - - 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. - IMPORTANTE: Qualquer backup prévio que você tenha feito do seu arquivo wallet deve ser substituído pelo novo e encriptado arquivo wallet gerado. Por razões de segurança, qualquer backup do arquivo wallet não criptografado se tornará inútil assim que você começar a usar uma nova carteira criptografada. - - - Warning: The Caps Lock key is on! - Atenção: A tecla Caps Lock está ligada! - - - Wallet encrypted - Carteira criptografada - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Digite a nova frase da carteira. <br/>Por favor utilize uma senha com <b>dez ou mais caracteres aleartórios</b>, ou <b>oito ou mais palavras</b>. - - - Enter the old passphrase and new passphrase to the wallet. - Insira a frase antiga e a nova da carteira. - - - Wallet encryption failed - A criptografia da carteira falhou - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - A criptografia da carteira falhou devido a um erro interno. Sua carteira não estava criptografada. - - - The supplied passphrases do not match. - A frase de segurança fornecida não confere. - - - Wallet unlock failed - O desbloqueio da carteira falhou - - - The passphrase entered for the wallet decryption was incorrect. - A frase de segurança digitada para a descriptografia da carteira estava incorreta. - - - Wallet decryption failed - A descriptografia da carteira falhou - - - Wallet passphrase was successfully changed. - A frase de segurança da carteira foi alterada com êxito. - BanTableModel @@ -269,6 +110,10 @@ Quit application Sair da aplicação + + &About %1 + &About %1 + About &Qt Sobre &Qt @@ -281,6 +126,10 @@ &Options... &Opções... + + Modify configuration options for %1 + Modificar opções de configuração para o %1 + &Encrypt Wallet... &Criptografar Carteira... @@ -305,14 +154,6 @@ Open &URI... Abrir &URI... - - Bitcoin Core client - Cliente Bitcoin - - - Importing blocks from disk... - Importando blocos do disco... - Reindexing blocks on disk... Reindexando blocos no disco... @@ -357,10 +198,6 @@ &Receive &Receber - - Show information about Bitcoin Core - Mostrar informações sobre Bitcoin - &Show / Hide &Exibir/Ocultar @@ -397,22 +234,10 @@ Tabs toolbar Barra de ferramentas - - Bitcoin Core - Bitcoin - Request payments (generates QR codes and bitcoin: URIs) Solicitações de pagamentos (gera códigos QR e bitcoin: URIs) - - &About Bitcoin Core - &Sobre Bitcoin - - - Modify configuration options for Bitcoin Core - Modificar opções de configuração do Bitcoin - Show the list of used sending addresses and labels Mostrar a lista de endereços de envio e rótulos usados @@ -429,14 +254,18 @@ &Command-line options Opções de linha de &comando - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Mostra a mensagem de ajuda do Bitcoin para pegar a lista com os comandos possíveis - %n active connection(s) to Bitcoin network %n conexão ativa na rede Bitcoin%n conexões ativas na rede Bitcoin + + Indexing blocks on disk... + Indexando blocos no disco... + + + Processing blocks on disk... + Processando blocos no disco... + No block source available... Nenhum servidor disponível... @@ -493,6 +322,14 @@ Up to date Atualizado + + Show the %1 help message to get a list with possible Bitcoin command-line options + Mostrar a mensagem de ajuda do %1 para obter uma lista com possíveis opções de linha de comando Bitcoin + + + %1 client + cliente %1 + Catching up... Recuperando o atraso ... @@ -544,13 +381,6 @@ Carteira está <b>criptografada</b> e atualmente <b>bloqueada</b> - - ClientModel - - Network Alert - Alerta da Rede - - CoinControlDialog @@ -629,150 +459,6 @@ Priority Prioridade - - Copy address - Copiar endereço - - - Copy label - Copiar rótulo - - - Copy amount - Copiar quantia - - - Copy transaction ID - Copiar ID da transação - - - Lock unspent - Travar não gasto - - - Unlock unspent - Destravar não gasto - - - Copy quantity - Copiar quantidade - - - Copy fee - Copiar taxa - - - Copy after fee - Copia pós-taxa - - - Copy bytes - Copiar bytes - - - Copy priority - Copia prioridade - - - Copy dust - Copiar poeira - - - Copy change - Copia alteração - - - highest - mais alta possível - - - higher - muito alta - - - high - alta - - - medium-high - média-alta - - - medium - média - - - low-medium - média-baixa - - - low - baixa - - - lower - muito baixa - - - lowest - a mais baixa possível - - - (%1 locked) - (%1 travado) - - - none - Nenhum - - - This label turns red if the transaction size is greater than 1000 bytes. - Este texto fica vermelho se o tamanho da transação for maior que 1000 bytes. - - - This label turns red if the priority is smaller than "medium". - Este texto fica vermelho se a prioridade é menor que "medio". - - - This label turns red if any recipient receives an amount smaller than %1. - Este texto fica vermelho se qualquer destinatário receber uma quantidade menor que %1. - - - Can vary +/- %1 satoshi(s) per input. - Pode variar +/- %1 satoshi(s) por entrada. - - - yes - sim - - - no - não - - - This means a fee of at least %1 per kB is required. - Isso significa que uma taxa de pelo menos %1 por kB é necessária. - - - Can vary +/- 1 byte per input. - Pode variar +/- 1 byte por entrada. - - - Transactions with higher priority are more likely to get included into a block. - Transações de alta prioridade são mais propensas a serem incluídas em um bloco. - - - (no label) - (Sem rótulo) - - - change from %1 (%2) - troco de %1 (%2) - - - (change) - (troco) - EditAddressDialog @@ -796,38 +482,6 @@ &Address &Endereço - - New receiving address - Novo endereço de recebimento - - - New sending address - Novo endereço de envio - - - Edit receiving address - Editar endereço de recebimento - - - Edit sending address - Editar endereço de envio - - - The entered address "%1" is already in the address book. - O endereço digitado "%1" já se encontra no catálogo de endereços. - - - The entered address "%1" is not a valid Bitcoin address. - O endereço digitado "%1" não é um endereço Bitcoin válido. - - - Could not unlock wallet. - Não foi possível desbloquear a carteira. - - - New key generation failed. - A geração de nova chave falhou. - FreespaceChecker @@ -854,10 +508,6 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin - version versão @@ -867,8 +517,8 @@ (%1-bit) - About Bitcoin Core - Sobre o Bitcoin + About %1 + Sobre %1 Command-line options @@ -907,8 +557,8 @@ Exibir tela de abertura na inicialização (padrão: %u) - Reset all settings changes made over the GUI - Desfazer todas as mudanças de configuração feitas na interface + Reset all settings changed in the GUI + Resetar todas as configuraçãoes do GUI @@ -918,16 +568,8 @@ Bem-vindo - Welcome to Bitcoin Core. - Bem vindo ao Bitcoin. - - - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - A primeira vez que o programa é aberto você pode escolher onde o Bitcoin vai guardar os dados. - - - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - O Bitcoin vai fazer download e salvar uma cópia da cadeia de blocos do Bitcoin: Blockchain. Pelo menos %1 GB de dados serão armazenados nesse diretório e isso aumentará ao longo do tempo. Sua carteira também será armazenada nesse diretório. + Welcome to %1. + Bem vindo ao %1 Use the default data directory @@ -937,10 +579,6 @@ Use a custom data directory: Use um diretório de dados personalizado: - - Bitcoin Core - Bitcoin - Error: Specified data directory "%1" cannot be created. Erro: Diretório de dados "%1" não pode ser criado. @@ -976,10 +614,6 @@ Select payment request file Selecione o arquivo de cobrança - - Select payment request file to open - Selecione o arquivo de cobrança para ser aberto - OptionsDialog @@ -991,6 +625,14 @@ &Main Principal + + Automatically start %1 after logging in to the system. + Executar o %1 automaticamente ao iniciar o sistema. + + + &Start %1 on system login + $Iniciar %1 ao fazer login no sistema + Size of &database cache Tamanho do banco de &dados do cache @@ -1019,10 +661,6 @@ 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. Minimizar em vez de fechar o programa quando a janela for fechada. Quando essa opção estiver ativa, o programa só será fechado somente pela opção Sair no menu Arquivo. - - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - A linguagem da interface do usuário pode ser alterada aqui. A mudança ocorrerá após o reinício do Bitcoin Core. - 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 |. URLs de terceiros (exemplo: explorador de blocos) que aparecem na aba de transações como itens do menu de contexto. %s na URL é substituido pela hash da transação. Múltiplas URLs são separadas pela barra vertical |. @@ -1047,14 +685,6 @@ &Network Rede - - Automatically start Bitcoin Core after logging in to the system. - Inicar automaticamente o Bitcoin ao logar no sistema. - - - &Start Bitcoin Core on system login - &Iniciar Bitcoin no login do sistema - (0 = auto, <0 = leave that many cores free) (0 = automático, <0 = número de cores deixados livres) @@ -1139,6 +769,14 @@ &Window &Janela + + &Hide the icon from the system tray. + &Ocultar o ícone da bandeja do sistema. + + + Hide tray icon + Ocultar ícone de bandeja + Show only a tray icon after minimizing the window. Mostrar apenas um ícone na bandeja ao minimizar a janela. @@ -1159,6 +797,10 @@ User Interface &language: &Linguagem da interface: + + The user interface language can be set here. This setting will take effect after restarting %1. + O idioma de interface do usuário pode ser definido aqui. Essa configuração terá efeito após reiniciar o %1 + &Unit to show amounts in: &Unidade usada para mostrar quantidades: @@ -1284,136 +926,45 @@ - PaymentServer + PeerTableModel - URI handling - Manipulação de URI + User Agent + User Agent - Invalid payment address %1 - Endereço de pagamento inválido %1 + Node/Service + Nó/Serviço - Payment request rejected - Solicitação de pagamento rejeitada + Ping Time + Ping + + + QObject - Payment request network doesn't match client network. - Rede de pedido de pagamento não corresponde rede do cliente. + Amount + Quantidade - Payment request is not initialized. - Pedido de pagamento não é inicializado. + Enter a Bitcoin address (e.g. %1) + Informe um endereço Bitcoin (ex: %1) - Requested payment amount of %1 is too small (considered dust). - Valor do pagamento solicitado de %1 é muito pequeno (Considerado poeira). + %1 d + %1 d - Payment request error - Erro no pedido de pagamento + %1 h + %1 h - Cannot start bitcoin: click-to-pay handler - Não foi possível iniciar bitcoin: manipulador clique-para-pagar + %1 m + %1 m - Payment request fetch URL is invalid: %1 - URL de cobrança é inválida: %1 - - - URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - URI não pode ser analisado ! Isto pode ser causado por um endereço Bitcoin inválido ou parâmetros URI informados incorretamente. - - - Payment request file handling - Manipulação de arquivo de cobrança - - - Payment request file cannot be read! This can be caused by an invalid payment request file. - Arquivo de pedido de pagamento não pode ser lido ! Isto pode ser causado por uma requisição de pagamento inválida. - - - Payment request expired. - Pedido de pagamento expirado. - - - Unverified payment requests to custom payment scripts are unsupported. - Cobrança não verificada para scripts de pagamento personalizados não é suportado. - - - Invalid payment request. - Pedido de pagamento inválido. - - - Refund from %1 - Reembolso de %1 - - - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - Pedido de pagamento %1 é muito grande (%2 bytes, permitido %3 bytes). - - - Error communicating with %1: %2 - Erro na comunicação com %1: %2 - - - Payment request cannot be parsed! - Requisição de pagamento não pode ser analisado! - - - Bad response from server %1 - Resposta incorreta do servidor %1 - - - Payment acknowledged - Pagamento reconhecido - - - Network request error - Erro de solicitação de rede - - - - PeerTableModel - - User Agent - User Agent - - - Node/Service - Nó/Serviço - - - Ping Time - Ping - - - - QObject - - Amount - Quantidade - - - Enter a Bitcoin address (e.g. %1) - Informe um endereço Bitcoin (ex: %1) - - - %1 d - %1 d - - - %1 h - %1 h - - - %1 m - %1 m - - - %1 s - %1 s + %1 s + %1 s None @@ -1428,25 +979,6 @@ %1 ms - - QRImageWidget - - &Save Image... - &Salvar imagem - - - &Copy Image - &Copiar Imagem - - - Save QR Code - Salvar código QR - - - PNG Image (*.png) - PNG Imagem (*.png) - - RPCConsole @@ -1513,10 +1045,6 @@ Memory usage Uso de memória - - Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. - Abrir o arquivo de log de depuração do Bitcoin na pasta de dados atual. Isso pode demorar para arquivos grandes. - Received Recebido @@ -1565,6 +1093,14 @@ User Agent User Agent + + Decrease font size + Diminuir o tamanho da fonte + + + Increase font size + Aumentar o tamanho da fonte + Services Serviços @@ -1633,10 +1169,6 @@ Out: Saída: - - Build date - Data do 'build' - Debug log file Arquivo de log de Depuração @@ -1674,8 +1206,8 @@ &Desbanir nó - Welcome to the Bitcoin Core RPC console. - Bem vindo ao console de RPC do Bitcoin. + Welcome to the %1 RPC console. + Bem-vindo ao console RPC do %1 Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. @@ -1804,18 +1336,6 @@ Remove Remover - - Copy label - Copiar rótulo - - - Copy message - Copiar mensagem - - - Copy amount - Copiar quantia - ReceiveRequestDialog @@ -1835,73 +1355,6 @@ &Save Image... &Salvar Imagem... - - Request payment to %1 - Requisitar pagamento para %1 - - - Payment information - Informação de pagamento - - - URI - URI - - - Address - Endereço - - - Amount - Quantidade - - - Label - Rótulo - - - Message - Mensagem - - - Resulting URI too long, try to reduce the text for label / message. - URI resultante muito longa. Tente reduzir o texto do rótulo ou da mensagem. - - - Error encoding URI into QR Code. - Erro ao codigicar o URI em código QR - - - - RecentRequestsTableModel - - Date - Data - - - Label - Rótulo - - - Message - Mensagem - - - Amount - Quantidade - - - (no label) - (Sem rótulo) - - - (no message) - (sem mensagem) - - - (no amount) - (sem quantia especificada) - SendCoinsDialog @@ -1970,935 +1423,289 @@ Escolher - collapse fee-settings - Ocultar painel - - - per kilobyte - por kilobyte - - - If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte. - Se a taxa personalizada for definida em 1000 satoshis e a transação tiver somente 250 bytes, então "por kilobyte" somente paga 250 satoshis de taxa, enquanto "pelo menos" paga 1000 satoshis. Se a transação for maior que 1 kilobyte, ambos pagam por kilobyte. - - - Hide - Ocultar - - - total at least - pelo menos - - - Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process. - Pagando apenas a taxa mínima é bom, desde que haja pouco volume de transações. Mas esteja ciente de que isso pode acabar em uma transação nunca confirmanda uma vez que há mais demanda por transações do que a rede pode processar. - - - (read the tooltip) - (Leia o popup) - - - Recommended: - Recomendado: - - - Custom: - Personalizado: - - - (Smart fee not initialized yet. This usually takes a few blocks...) - (Smart fee não iniciado. Isso requer alguns blocos...) - - - Confirmation time: - Tempo de confirmação: - - - normal - normal - - - fast - rápido - - - Send as zero-fee transaction if possible - Enviar sem taxa de transação se possível - - - (confirmation may take longer) - (confirmação pode demorar) - - - Send to multiple recipients at once - Enviar para vários destinatários de uma só vez - - - Add &Recipient - Adicionar destinatário - - - Clear all fields of the form. - Limpar todos os campos do formulário. - - - Dust: - Poeira: - - - Clear &All - Limpar Tudo - - - Balance: - Saldo: - - - Confirm the send action - Confirmar o envio - - - S&end - Enviar - - - Confirm send coins - Confirmar envio de moedas - - - %1 to %2 - %1 para %2 - - - Copy quantity - Copiar quantidade - - - Copy amount - Copiar quantia - - - Copy fee - Copiar taxa - - - Copy after fee - Copia pós-taxa - - - Copy bytes - Copiar bytes - - - Copy priority - Copia prioridade - - - Copy change - Copia alteração - - - Total Amount %1 - Quantia Total %1 - - - or - ou - - - The amount to pay must be larger than 0. - A quantidade a ser paga precisa ser maior que 0. - - - The amount exceeds your balance. - A quantidade excede seu saldo. - - - The total exceeds your balance when the %1 transaction fee is included. - O total excede seu saldo quando uma taxa de transação de %1 é incluída. - - - Transaction creation failed! - A criação de transação falhou! - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - A transação foi rejeitada! Isso pode acontecer se alguns bitcoins na sua carteira já foram gastos em outro local, por exemplo se você tiver uma cópia do wallet.dat e os bitcoins tiverem sido gastos na cópia mas não marcados como gastos aqui ainda. - - - A fee higher than %1 is considered an absurdly high fee. - Uma taxa maior que %1 é considerada uma taxa absurdamente alto. - - - Payment request expired. - Pedido de pagamento expirado. - - - Pay only the required fee of %1 - Pagar somente a taxa requerida de %1 - - - Estimated to begin confirmation within %n block(s). - Confirmação estimada em %n bloco.Confirmação estimada em %n blocos. - - - The recipient address is not valid. Please recheck. - O endereço do destinatário é inválido. Favor confirmar. - - - Duplicate address found: addresses should only be used once each. - Endereço duplicado encontrado: Endereços devem ser usados somente uma vez cada. - - - Warning: Invalid Bitcoin address - Atenção: endereço de Bitcoin inválido - - - (no label) - (Sem rótulo) - - - Warning: Unknown change address - Atenção: endereço de troco desconhecido - - - Copy dust - Copiar poeira - - - Are you sure you want to send? - Tem certeza que quer enviar? - - - added as transaction fee - Adicionado como taxa de transação - - - - SendCoinsEntry - - A&mount: - Q&uantidade: - - - Pay &To: - Pagar &Para: - - - Enter a label for this address to add it to your address book - Digite um rótulo para este endereço para adicioná-lo ao catálogo de endereços - - - &Label: - &Rótulo: - - - Choose previously used address - Escolher endereço usado anteriormente - - - This is a normal payment. - Este é um pagamento normal. - - - The Bitcoin address to send the payment to - Endereço que enviará o pagamento - - - Alt+A - Alt+A - - - Paste address from clipboard - Colar o endereço da área de transferência - - - Alt+P - Alt+P - - - Remove this entry - Remover esta entrada - - - 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. - A taxa será deduzida da quantia sendo enviada. O destinatário receberá menos bitcoins do que você colocou no campo de quantidade. Se varios destinatários estão selecionados, a taxa é dividida igualmente. - - - S&ubtract fee from amount - &Retirar taxa da quantia - - - Message: - Mensagem: - - - This is an unauthenticated payment request. - Esta é uma cobrança não autenticada. - - - This is an authenticated payment request. - Esta é uma cobrança autenticada. - - - Enter a label for this address to add it to the list of used addresses - Digite um rótulo para este endereço para adicioná-lo no catálogo - - - 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. - A mensagem que foi anexada ao bitcoin: URI na qual será gravada na transação para sua referência. Nota: Essa mensagem não será gravada publicamente na rede Bitcoin. - - - Pay To: - Pague Para: - - - Memo: - Memorizar: - - - - ShutdownWindow - - Bitcoin Core is shutting down... - Bitcoin está sendo encerrado... - - - Do not shut down the computer until this window disappears. - Não desligue o computador até que esta janela desapareça. - - - - SignVerifyMessageDialog - - Signatures - Sign / Verify a Message - Assinaturas - Assinar / Verificar uma mensagem - - - &Sign Message - &Assinar mensagem - - - 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. - Você pode assinar mensagens com seus endereços para provar que você pode receber bitcoins enviados por alguém. Cuidado para não assinar nada vago ou aleatório, pois ataques phishing podem tentar te enganar para assinar coisas para eles como se fosse você. Somente assine termos bem detalhados que você concorde. - - - The Bitcoin address to sign the message with - O enderesso Bitcoin que assinará a mensagem - - - Choose previously used address - Escolha um endereço usado anteriormente - - - Alt+A - Alt+A - - - Paste address from clipboard - Colar o endereço da área de transferência - - - Alt+P - Alt+P - - - Enter the message you want to sign here - Entre a mensagem que você quer assinar aqui - - - Signature - Assinatura - - - Copy the current signature to the system clipboard - Copiar a assinatura para a área de transferência do sistema - - - Sign the message to prove you own this Bitcoin address - Assinar mensagem para provar que você é dono deste endereço Bitcoin - - - Sign &Message - Assinar &mensagem - - - Reset all sign message fields - Limpar todos os campos de assinatura da mensagem - - - Clear &All - Limpar Tudo - - - &Verify Message - &Verificar mensagem - - - 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! - Coloque o endereço do autor, a mensagem (certifique-se de copiar toda a mensagem, incluindo quebras de linha, espaços, tabulações, etc.) e a assinatura embaixo para verificar a mensagem. Cuidado para não ler mais da assinatura do que está assinado na mensagem, para evitar ser enganado pelo ataque man-in-the-middle. Note que isso somente prova a propriedade de um endereço, e não o remetende de qualquer transação. - - - The Bitcoin address the message was signed with - O enderesso Bitcoin que assionou a mesnagem - - - Verify the message to ensure it was signed with the specified Bitcoin address - Verificar mensagem para se assegurar que ela foi assinada pelo dono de um endereço Bitcoin específico. - - - Verify &Message - Verificar &mensagem - - - Reset all verify message fields - Limpar todos os campos de assinatura da mensagem - - - Click "Sign Message" to generate signature - Clique em "Assinar mensagem" para gerar a assinatura - - - The entered address is invalid. - O endereço fornecido é inválido. - - - Please check the address and try again. - Por favor, verifique o endereço e tente novamente. - - - The entered address does not refer to a key. - O endereço fornecido não se refere a uma chave. - - - Wallet unlock was cancelled. - Desbloqueamento da Carteira foi cancelado. - - - Private key for the entered address is not available. - A chave privada para o endereço fornecido não está disponível. - - - Message signing failed. - Assinatura da mensagem falhou. - - - Message signed. - Mensagem assinada. - - - The signature could not be decoded. - A assinatura não pode ser decodificada. - - - Please check the signature and try again. - Por favor, verifique a assinatura e tente novamente. - - - The signature did not match the message digest. - A assinatura não corresponde ao "resumo da mensagem". - - - Message verification failed. - Verificação da mensagem falhou. - - - Message verified. - Mensagem verificada. - - - - SplashScreen - - Bitcoin Core - Bitcoin - - - The Bitcoin Core developers - Programadores do Bitcoin - - - [testnet] - [testnet] - - - - TrafficGraphWidget - - KB/s - KB/s - - - - TransactionDesc - - Open until %1 - Aberto até %1 - - - conflicted - em conflito - - - %1/offline - %1/offline - - - %1/unconfirmed - %1/não confirmadas - - - %1 confirmations - %1 confirmações - - - Status - Status - - - , broadcast through %n node(s) - , difundir atráves de %n nó, difundir atráves de %n nós - - - Date - Data - - - Source - Fonte - - - Generated - Gerados - - - From - De - - - To - Para - - - own address - seu próprio endereço - - - watch-only - monitorado - - - label - rótulo - - - Credit - Crédito - - - matures in %n more block(s) - matura em mais %n blocomatura em mais %n blocos - - - not accepted - não aceito - - - Debit - Débito - - - Total debit - Débito total - - - Total credit - Credito total - - - Transaction fee - Taxa de transação - - - Net amount - Valor líquido - - - Message - Mensagem - - - Comment - Comentário - - - Transaction ID - ID da transação - - - Merchant - Mercador - - - 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. - Bitcoins recém minerados precisam aguardar %1 blocos antes de serem gastos. Quando o bloco foi gerado, ele foi disseminado pela rede para ser adicionado à blockchain. Se ele falhar em ser inserido na cadeia, seu estado será modificado para "não aceito" e ele não poderá ser gasto. Isso pode acontecer eventualmente quando blocos são gerados quase que simultaneamente. - - - Debug information - Informação de depuração - - - Transaction - Transação - - - Inputs - Entradas - - - Amount - Quantidade - - - true - verdadeiro - - - false - falso - - - , has not been successfully broadcast yet - , ainda não foi propagada na rede com sucesso. - - - Open for %n more block(s) - Abrir para mais %n blocoAbrir para mais %n blocos - - - unknown - desconhecido - - - - TransactionDescDialog - - Transaction details - Detalhes da transação - - - This pane shows a detailed description of the transaction - Este painel mostra uma descrição detalhada da transação - - - - TransactionTableModel - - Date - Data + collapse fee-settings + Ocultar painel - Type - Tipo + per kilobyte + por kilobyte - Immature (%1 confirmations, will be available after %2) - Recém-criado (%1 confirmações, disponível somente após %2) + If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte. + Se a taxa personalizada for definida em 1000 satoshis e a transação tiver somente 250 bytes, então "por kilobyte" somente paga 250 satoshis de taxa, enquanto "pelo menos" paga 1000 satoshis. Se a transação for maior que 1 kilobyte, ambos pagam por kilobyte. - - Open for %n more block(s) - Abrir para mais %n blocoAbrir para mais %n blocos + + Hide + Ocultar - Open until %1 - Aberto até %1 + total at least + pelo menos - Confirmed (%1 confirmations) - Confirmado (%1 confirmações) + Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process. + Pagando apenas a taxa mínima é bom, desde que haja pouco volume de transações. Mas esteja ciente de que isso pode acabar em uma transação nunca confirmanda uma vez que há mais demanda por transações do que a rede pode processar. - This block was not received by any other nodes and will probably not be accepted! - Este bloco não foi recebido por nenhum outro participante da rede e provavelmente não será aceito! + (read the tooltip) + (Leia o popup) - Generated but not accepted - Gerado mas não aceito + Recommended: + Recomendado: - Offline - Offline + Custom: + Personalizado: - Label - Rótulo + (Smart fee not initialized yet. This usually takes a few blocks...) + (Smart fee não iniciado. Isso requer alguns blocos...) - Unconfirmed - Não confirmado + Confirmation time: + Tempo de confirmação: - Confirming (%1 of %2 recommended confirmations) - Confirmando (%1 de %2 confirmações recomendadas) + normal + normal - Conflicted - Conflitou + fast + rápido - Received with - Recebido + Send to multiple recipients at once + Enviar para vários destinatários de uma só vez - Received from - Recebido + Add &Recipient + Adicionar destinatário - Sent to - Enviado + Clear all fields of the form. + Limpar todos os campos do formulário. - Payment to yourself - Pagamento para você mesmo + Dust: + Poeira: - Mined - Minerado + Clear &All + Limpar Tudo - watch-only - monitorado + Balance: + Saldo: - (n/a) - (n/a) + Confirm the send action + Confirmar o envio - Transaction status. Hover over this field to show number of confirmations. - Status da transação. Passe o mouse sobre este campo para mostrar o número de confirmações. + S&end + Enviar + + + SendCoinsEntry - Date and time that the transaction was received. - Data e hora em que a transação foi recebida. + A&mount: + Q&uantidade: - Type of transaction. - Tipo de transação. + Pay &To: + Pagar &Para: - Whether or not a watch-only address is involved in this transaction. - Mostrar ou não endereços Bitcoin na lista de transações. + &Label: + &Rótulo: - User-defined intent/purpose of the transaction. - Intenção/Propósito definido pelo usuário para a transação + Choose previously used address + Escolher endereço usado anteriormente - Amount removed from or added to balance. - Quantidade debitada ou creditada ao saldo. + This is a normal payment. + Este é um pagamento normal. - - - TransactionView - All - Todos + The Bitcoin address to send the payment to + Endereço que enviará o pagamento - Today - Hoje + Alt+A + Alt+A - This week - Esta semana + Paste address from clipboard + Colar o endereço da área de transferência - This month - Este mês + Alt+P + Alt+P - Last month - Mês passado + Remove this entry + Remover esta entrada - This year - Este ano + 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. + A taxa será deduzida da quantia sendo enviada. O destinatário receberá menos bitcoins do que você colocou no campo de quantidade. Se varios destinatários estão selecionados, a taxa é dividida igualmente. - Range... - Intervalo... + S&ubtract fee from amount + &Retirar taxa da quantia - Received with - Recebido + Message: + Mensagem: - Sent to - Enviado + This is an unauthenticated payment request. + Esta é uma cobrança não autenticada. - To yourself - Para você mesmo + This is an authenticated payment request. + Esta é uma cobrança autenticada. - Mined - Minerado + Enter a label for this address to add it to the list of used addresses + Digite um rótulo para este endereço para adicioná-lo no catálogo - Other - Outro + 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. + A mensagem que foi anexada ao bitcoin: URI na qual será gravada na transação para sua referência. Nota: Essa mensagem não será gravada publicamente na rede Bitcoin. - Enter address or label to search - Procure um endereço ou rótulo + Pay To: + Pague Para: - Min amount - Quantidade mínima + Memo: + Memorizar: + + + ShutdownWindow - Copy address - Copiar endereço + Do not shut down the computer until this window disappears. + Não desligue o computador até que esta janela desapareça. + + + SignVerifyMessageDialog - Copy label - Copiar rótulo + Signatures - Sign / Verify a Message + Assinaturas - Assinar / Verificar uma mensagem - Copy amount - Copiar quantia + &Sign Message + &Assinar mensagem - Copy transaction ID - Copiar ID da transação + 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. + Você pode assinar mensagens com seus endereços para provar que você pode receber bitcoins enviados por alguém. Cuidado para não assinar nada vago ou aleatório, pois ataques phishing podem tentar te enganar para assinar coisas para eles como se fosse você. Somente assine termos bem detalhados que você concorde. - Copy raw transaction - Copia os dados brutos da transação + The Bitcoin address to sign the message with + O enderesso Bitcoin que assinará a mensagem - Edit label - Editar rótulo + Choose previously used address + Escolha um endereço usado anteriormente - Show transaction details - Mostrar detalhes da transação + Alt+A + Alt+A - Export Transaction History - Exportar Histórico de Transação + Paste address from clipboard + Colar o endereço da área de transferência - Watch-only - Monitorado + Alt+P + Alt+P - Exporting Failed - Exportação Falhou + Enter the message you want to sign here + Entre a mensagem que você quer assinar aqui - There was an error trying to save the transaction history to %1. - Ocorreu um erro ao tentar salvar o histórico de transação em %1. + Signature + Assinatura - Exporting Successful - Exportação feita com sucesso + Copy the current signature to the system clipboard + Copiar a assinatura para a área de transferência do sistema - The transaction history was successfully saved to %1. - O histórico de transação foi gravado com sucesso em %1. + Sign the message to prove you own this Bitcoin address + Assinar mensagem para provar que você é dono deste endereço Bitcoin - Comma separated file (*.csv) - Arquivo separado por vírgulas (*. csv) + Sign &Message + Assinar &mensagem - Confirmed - Confirmado + Reset all sign message fields + Limpar todos os campos de assinatura da mensagem - Date - Data + Clear &All + Limpar Tudo - Type - Tipo + &Verify Message + &Verificar mensagem - Label - Rótulo + 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! + Coloque o endereço do autor, a mensagem (certifique-se de copiar toda a mensagem, incluindo quebras de linha, espaços, tabulações, etc.) e a assinatura embaixo para verificar a mensagem. Cuidado para não ler mais da assinatura do que está assinado na mensagem, para evitar ser enganado pelo ataque man-in-the-middle. Note que isso somente prova a propriedade de um endereço, e não o remetende de qualquer transação. - Address - Endereço + The Bitcoin address the message was signed with + O enderesso Bitcoin que assionou a mesnagem - ID - ID + Verify the message to ensure it was signed with the specified Bitcoin address + Verificar mensagem para se assegurar que ela foi assinada pelo dono de um endereço Bitcoin específico. - Range: - Intervalo: + Verify &Message + Verificar &mensagem - to - para + Reset all verify message fields + Limpar todos os campos de assinatura da mensagem - UnitDisplayStatusBarControl + SplashScreen - Unit to show amounts in. Click to select another unit. - Unidade para mostrar. Clique para selecionar outra unidade. + [testnet] + [testnet] - WalletFrame + TrafficGraphWidget - No wallet has been loaded. - Nenhuma carteira foi carregada. + KB/s + KB/s - WalletModel + TransactionDescDialog - Send Coins - Send Coins + This pane shows a detailed description of the transaction + Este painel mostra uma descrição detalhada da transação - WalletView - - &Export - &Exportar - - - Export the data in the current tab to a file - Exportar os dados na aba atual para um arquivo - - - Backup Wallet - Fazer cópia de segurança da Carteira - - - Wallet Data (*.dat) - Dados da Carteira (*.dat) - - - Backup Failed - Cópia de segurança Falhou - - - There was an error trying to save the wallet data to %1. - Ocorreu um erro ao tentar salvar os dados da carteira em %1. - - - The wallet data was successfully saved to %1. - Os dados da carteira foram salvos com sucesso em %1. - + UnitDisplayStatusBarControl - Backup Successful - Backup feito com sucesso + Unit to show amounts in. Click to select another unit. + Unidade para mostrar. Clique para selecionar outra unidade. @@ -2927,14 +1734,6 @@ If <category> is not supplied or if <category> = 1, output all debugging information. Se <category> não for suprida ou se <category> = 1, mostrar toda informação de depuração. - - Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s) - Total máximo de comissão (em %s) que será usado em uma única transação; um valor muito baixo pode cancelar uma transação grande (padrão: %s) - - - Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. - Por favor verifique se a data e horário estão corretos no seu computador! Se o seu relógio estiver incorreto, a Carteira Bitcoin não irá funcionar corretamente. - Prune configured below the minimum of %d MiB. Please use a higher number. Corte configurado abaixo do nível mínimo de %d de MiB. Por favor use um número mais alto. @@ -2975,6 +1774,10 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Aceitar conexões externas (padrão: 1 se opções -proxy ou -connect não estiverem presentes) + + Bitcoin Core + Bitcoin + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. -fallbackfee está muito alta! Essa é a taxa de transação que você vai pagar quando a taxa estimada não estiver disponível. @@ -3019,14 +1822,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Este pode ser um build de teste pré-lançamento - use por sua conta e risco - não use para mineração ou aplicações de comércio. - - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - Impossível ouvir em %s neste computador. Provavelmente o Bitcoin já está sendo executado. - - - Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. - Argumento não suportado -whitelistalwaysrelay foi ignorado, utilize -whitelistrelay e/ou -whitelistforcerelay. - Use UPnP to map the listening port (default: 1 when listening and no -proxy) Use UPnP para mapear a porta escutada (padrão: 1 quando escutando e sem -proxy) @@ -3043,18 +1838,10 @@ Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Atenção: A rede não parecem concordar plenamente! Alguns mineiros parecem estar enfrentando problemas. - - Warning: Unknown block versions being mined! It's possible unknown rules are in effect - Aviso: Versões de bloco desconhecidas sendo mineradas! É possível que regras estranhas estejam ativas - Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Atenção: Nós não parecemos concordar plenamente com nossos colegas! Você pode precisar atualizar ou outros nós podem precisar atualizar. - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Atenção: wallet.dat corrompido, dados recuperados! Arquivo wallet.dat original salvo como wallet.{timestamp}.bak em %s; se seu saldo ou transações estiverem incorretos, você deve restaurar o backup. - Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. Lista Branca pares de ligação da máscara de rede dado ou o endereço IP . Pode ser especificado várias vezes. @@ -3239,10 +2026,6 @@ Wallet options: Opções da carteira: - - You need to rebuild the database using -reindex to change -txindex - Você precisa reconstruir o banco de dados utilizando -reindex - 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 Permitir conexões JSON-RPC de uma fonte específica. Válido para um único ip (ex. 1.2.3.4), até uma rede/máscara (ex. 1.2.3.4/255.255.255.0) ou uma rede/CIDR (ex. 1.2.3.4/24). Esta opção pode ser usada múltiplas vezes @@ -3255,10 +2038,6 @@ Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces) Conecte ao endereço dado para receber conecções JSON-RPC. Use a notação [destino]:porta para IPv6. Essa opção pode ser especificada várias vezes (padrão: conecte a todas as interfaces) - - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - Não foi possível obter acesso exclusivo ao diretório de dados %s. Provavelmente Bitcoin já está sendo executado. - Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) Criar novos arquivos com permissões padrão do sistema, em vez de umask 077 (apenas efetivo com funcionalidade de carteira desabilitada) @@ -3303,10 +2082,6 @@ Set maximum size of high-priority/low-fee transactions in bytes (default: %d) Define o tamanho máximo de alta-prioridade por taxa baixa nas transações em bytes (padrão: %d) - - Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) - Determina o número de núcleos para a geração de moedas se ativado (-1 = todos os núcleos, padrão: %d) - The transaction amount is too small to send after the fee has been deducted A quantia da transação é muito pequena para mandar @@ -3331,34 +2106,14 @@ Accept public REST requests (default: %u) Aceitar pedidos restantes públicas (padrão: %u) - - Activating best chain... - Ativando a melhor sequência... - - - Attempt to recover private keys from a corrupt wallet.dat on startup - Tentar recuperar na inicialização chaves privadas de um arquivo wallet.dat corrompido - Automatically create Tor hidden service (default: %d) Criar automaticamente serviços ocultos do Tor (padrão: %d) - - Cannot resolve -whitebind address: '%s' - Impossível resolver endereço -whitebind: '%s' - Connect through SOCKS5 proxy Connecte-se através de um proxy SOCKS5 - - Copyright (C) 2009-%i The Bitcoin Core Developers - Copyright (C) 2009-%i Desenvolvedores Bitcoin Core - - - Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - Erro ao carregar wallet.dat: A carteira requer a nova versão do Bitcoin - Error reading from database, shutting down. Erro ao ler o banco de dados. Finalizando. @@ -3371,22 +2126,6 @@ Information Informação - - Initialization sanity check failed. Bitcoin Core is shutting down. - O teste de integridade da inicialização falhou. O Core do Bitcoin está sendo desligado. - - - Invalid amount for -maxtxfee=<amount>: '%s' - Quantidade inválida para -maxtxfee=<quantidade>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Quantidade inválida para -minrelaytxfee=<amount>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - Valor inválido para -mintxfee=<amount>: '%s' - Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) Valor inválido para -paytxfee=<amount>: '%s' (precisa ser no mínimo %s) @@ -3411,14 +2150,6 @@ RPC server options: Opções do servidor RPC: - - Rebuild block chain index from current blk000??.dat files on startup - Reconstruir índice de cadeia de bloco a partir dos arquivos blk000??.dat atuais durante a inicialização - - - Receive and display P2P network alerts (default: %u) - Receba e mostre P2P alerta de rede (padrão: %u) - Reducing -maxconnections from %d to %d, because of system limitations. Reduzindo -maxconnections de %d para %d, devido a limitações do sistema @@ -3491,10 +2222,6 @@ Username for JSON-RPC connections Nome de usuário para conexões JSON-RPC - - Wallet needed to be rewritten: restart Bitcoin Core to complete - Sua carteira precisou ser reescrita: favor reiniciar o Bitcoin para completar - Warning Atenção @@ -3515,10 +2242,6 @@ ZeroMQ notification options: Opções de notificação ZeroMQ: - - wallet.dat corrupt, salvage failed - wallet.dat corrompido, recuperação falhou - Password for JSON-RPC connections Senha para conexões JSON-RPC @@ -3527,10 +2250,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) Executa um comando quando o melhor bloco mudar (%s no comando será substituído pelo hash do bloco) - - This help message - Exibe esta mensagem de ajuda - Allow DNS lookups for -addnode, -seednode and -connect Permitir consultas DNS para -addnode, -seednode e -connect @@ -3539,10 +2258,6 @@ Loading addresses... Carregando endereços... - - Error loading wallet.dat: Wallet corrupted - Erro ao carregar wallet.dat: Carteira corrompida - (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) (1 = manter metadados tx e.g. informação do dono da conta e requisição de pagamente, 2 = descartar metadados tx) @@ -3559,10 +2274,6 @@ Do not keep transactions in the mempool longer than <n> hours (default: %u) Não manter transações na mempool por mais que <n> horas (padrão: %u) - - Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. - Erro ao ler o arquivo wallet.dat! Todas as chaves foram lidas corretamente, mas os dados de transações ou o livro de endereços podem estar faltando ou ser incorretos. - Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) Comissões (em %s/kB) menores serão consideradas como zero para criação de transação (padrão %s) @@ -3599,6 +2310,10 @@ Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported. Argumento inválido -socks encontrado. Definir a versão do SOCKS não é mais possível, somente proxys SOCK5 são suportados. + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + Argumento não suportado -whitelistalwaysrelay foi ignorado, utilize -whitelistrelay e/ou -whitelistforcerelay. + Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s) Use um proxy SOCKS5 separado para alcançar participantes da rede via serviços ocultos Tor (padrão: %s) @@ -3607,6 +2322,10 @@ Username and hashed password for JSON-RPC connections. The field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A canonical python script is included in share/rpcuser. This option can be specified multiple times Nome de usuário e senha hash para conexões JSON-RPC. O campo <userpw> vem com o formato: <USERNAME>:<SALT>$<HASH>. Um script python canônico é incluído em share/rpcuser. Essa opção pode ser especificada múltiplas vezes. + + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + Aviso: Versões de bloco desconhecidas sendo mineradas! É possível que regras estranhas estejam ativas + (default: %s) (padrão: %s) @@ -3615,14 +2334,6 @@ Always query for peer addresses via DNS lookup (default: %u) Sempre pergunte pelo endereço de peer via pesquisa DNS (padrão: %u) - - Error loading wallet.dat - Erro ao carregar wallet.dat - - - Generate coins (default: %u) - Gerar moedas (padrão: %u) - How many blocks to check at startup (default: %u, 0 = all) Quantos blocos devem ser checados ao iniciar (padrão: %u, 0 = todos) @@ -3707,18 +2418,6 @@ Unknown network specified in -onlynet: '%s' Rede desconhecida especificada em -onlynet: '%s' - - Cannot resolve -bind address: '%s' - Impossível encontrar o endereço -bind: '%s' - - - Cannot resolve -externalip address: '%s' - Impossível encontrar endereço -externalip: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - Quantidade inválida para -paytxfee=<quantidade>: '%s' - Insufficient funds Saldo insuficiente diff --git a/src/qt/locale/bitcoin_pt_PT.ts b/src/qt/locale/bitcoin_pt_PT.ts index 362769138a842..16b912dfdc57b 100644 --- a/src/qt/locale/bitcoin_pt_PT.ts +++ b/src/qt/locale/bitcoin_pt_PT.ts @@ -25,10 +25,6 @@ C&lose F&echar - - &Copy Address - &Copiar Endereço - Delete the currently selected address from the list Eliminar o endereço selecionado da lista @@ -45,73 +41,6 @@ &Delete &Eliminar - - Choose the address to send coins to - Escolha o endereço para enviar as moedas - - - Choose the address to receive coins with - Escolha o endereço para receber as moedas com - - - C&hoose - Escol&her - - - Sending addresses - Endereços de envio - - - Receiving addresses - Endereços de a receber - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Estes são os seus endereços Bitcoin para enviar pagamentos. Verifique sempre o valor e o endereço de envio antes de enviar moedas. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Estes são os seus endereços do Bitcoin para receber pagamentos. É recomendado que utilize um novo endereço para cada transação. - - - Copy &Label - Copiar &Rótulo - - - &Edit - &Editar - - - Export Address List - Exportar Lista de Endereços - - - Comma separated file (*.csv) - Ficheiro separado por vírgulas (*.csv) - - - Exporting Failed - Exportação Falhou - - - There was an error trying to save the address list to %1. Please try again. - Houve um erro ao tentar a guardar a lista de endereços em %1. Por favor tente novamente. - - - - AddressTableModel - - Label - Etiqueta - - - Address - Endereço - - - (no label) - (sem etiqueta) - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase Repita a nova frase de palavra-passe - - Encrypt wallet - Encriptar carteira - - - This operation needs your wallet passphrase to unlock the wallet. - Esta operação precisa da sua frase de palavra-passe da carteira para desbloquear a mesma. - - - Unlock wallet - Desbloquear carteira - - - This operation needs your wallet passphrase to decrypt the wallet. - Esta operação precisa da sua frase de palavra-passe da carteira para desencriptar a mesma. - - - Decrypt wallet - Desencriptar carteira - - - Change passphrase - Alterar frase de palavra-passe - - - Confirm wallet encryption - Confirmar encriptação da carteira - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Aviso: se encriptar a sua carteira e perder a sua frase de de palavra-passe, irá <b>PERDER TODOS OS SEUS BITCOINS</b>! - - - Are you sure you wish to encrypt your wallet? - Tem a certeza que deseja encriptar a carteira? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - O cliente Bitcoin Core irá agora ser fechado para terminar o processo de encriptação. Recorde que a encriptação da sua carteira não protegerá totalmente os seus bitcoins de serem roubados por programas maliciosos que infectem o seu computador. - - - 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. - IMPORTANTE: Qualquer cópia de segurança da carteira anterior deverá ser substituída com o novo ficheiro de carteira, agora encriptado. Por razões de segurança, cópias de segurança não encriptadas tornar-se-ão inúteis assim que começar a usar a nova carteira encriptada. - - - Warning: The Caps Lock key is on! - Atenção: a tecla Caps Lock está ativada! - - - Wallet encrypted - Carteira encriptada - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Insira a nova frase de palavra-passe da sua carteira. <br/> Por favor, utilize uma frase de palavra-passe com <b>mais de 10 ou mais carateres aleatórios,</b> ou <b>oito ou mais palavras</b>. - - - Enter the old passphrase and new passphrase to the wallet. - Insira a frase de palavra-passe antiga e a nova frase de palavra-passe para carteira. - - - Wallet encryption failed - A encriptação da carteira falhou - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - A encriptação da carteira falhou devido a um erro interno. A carteira não foi encriptada. - - - The supplied passphrases do not match. - As frases de palavra-passe inseridas não coincidem. - - - Wallet unlock failed - O desbloqueio da carteira falhou - - - The passphrase entered for the wallet decryption was incorrect. - A frase de palavra-passe inserida para a desencriptação da carteira estava incorreta. - - - Wallet decryption failed - A desencriptação da carteira falhou - - - Wallet passphrase was successfully changed. - A frase de palavra-passe da carteira foi alterada com sucesso. - BanTableModel @@ -269,6 +110,14 @@ Quit application Sair da aplicação + + &About %1 + &Acerca de %1 + + + Show information about %1 + Mostrar informação sobre %1 + About &Qt Sobre &Qt @@ -281,6 +130,10 @@ &Options... &Opções... + + Modify configuration options for %1 + Modificar opções de configuração para %1 + &Encrypt Wallet... E&ncriptar Carteira... @@ -305,14 +158,6 @@ Open &URI... Abrir &URI... - - Bitcoin Core client - Cliente do Bitcoin Core - - - Importing blocks from disk... - A importar os blocos do disco... - Reindexing blocks on disk... A reindexar os blocos no disco... @@ -357,10 +202,6 @@ &Receive &Receber - - Show information about Bitcoin Core - Mostrar informação sobre o Bitcoin Core - &Show / Hide Mo&strar / Ocultar @@ -397,22 +238,10 @@ Tabs toolbar Barra de ferramentas dos separadores - - Bitcoin Core - Bitcoin Core - Request payments (generates QR codes and bitcoin: URIs) Solicitar pagamentos (gera códigos QR e bitcoin: URIs) - - &About Bitcoin Core - &Sobre o Bitcoin Core - - - Modify configuration options for Bitcoin Core - Modificar as opções de configuração do Bitcoin Core - Show the list of used sending addresses and labels Mostrar a lista de rótulos e endereços de envio usados @@ -429,14 +258,18 @@ &Command-line options &Opções da linha de &comando - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Mostrar a mensagem de ajuda do Bitcoin Core para obter uma lista com possíveis opções de linha de comando do Bitcoin - %n active connection(s) to Bitcoin network %n ligação ativa à rede Bitcoin%n ligações ativas à rede Bitcoin + + Indexing blocks on disk... + A indexar blocos no disco... + + + Processing blocks on disk... + A processar blocos no disco... + No block source available... Nenhuma fonte de blocos disponível... @@ -544,13 +377,6 @@ A carteira está <b>encriptada</b> e atualmente <b>bloqueada</b> - - ClientModel - - Network Alert - Alerta da Rede - - CoinControlDialog @@ -629,150 +455,6 @@ Priority Prioridade - - Copy address - Copiar endereço - - - Copy label - Copiar etiqueta - - - Copy amount - Copiar valor - - - Copy transaction ID - Copiar id. da transação - - - Lock unspent - Bloquear não gastas - - - Unlock unspent - Desbloquear não gastas - - - Copy quantity - Copiar quantidade - - - Copy fee - Copiar taxa - - - Copy after fee - Copiar depois da taxa - - - Copy bytes - Copiar bytes - - - Copy priority - Copiar prioridade - - - Copy dust - Copiar lixo - - - Copy change - Copiar alteração - - - highest - muito alta - - - higher - mais alta - - - high - alta - - - medium-high - média alta - - - medium - média - - - low-medium - média baixa - - - low - baixa - - - lower - mais baixa - - - lowest - muito baixa - - - (%1 locked) - (%1 bloqueados) - - - none - nenhum - - - This label turns red if the transaction size is greater than 1000 bytes. - Esta etiqueta fica vermelha se o tamanho da transação exceder os 1000 bytes. - - - This label turns red if the priority is smaller than "medium". - Esta etiqueta fica vermelha se a prioridade for menor que "média". - - - This label turns red if any recipient receives an amount smaller than %1. - Esta etiqueta fica vermelha se qualquer recipiente receber uma quantia menor que %1. - - - Can vary +/- %1 satoshi(s) per input. - Pode variar +/- %1 satoshi(s) por entrada - - - yes - sim - - - no - não - - - This means a fee of at least %1 per kB is required. - Isto significa que uma taxa de pelo menos %1 por kB é necessária. - - - Can vary +/- 1 byte per input. - Pode variar +/- 1 byte por input. - - - Transactions with higher priority are more likely to get included into a block. - Transacções com uma prioridade mais alta têm uma maior probabilidade de serem incluídas num bloco. - - - (no label) - (sem etiqueta) - - - change from %1 (%2) - troco de %1 (%2) - - - (change) - (troco) - EditAddressDialog @@ -796,38 +478,6 @@ &Address E&ndereço - - New receiving address - Novo endereço de entrada - - - New sending address - Novo endereço de saída - - - Edit receiving address - Editar endereço de entrada - - - Edit sending address - Editar endereço de saída - - - The entered address "%1" is already in the address book. - O endereço introduzido "%1" já se encontra no livro de endereços. - - - The entered address "%1" is not a valid Bitcoin address. - O endereço introduzido "%1" não é um endereço bitcoin válido. - - - Could not unlock wallet. - Impossível desbloquear carteira. - - - New key generation failed. - Falha ao gerar nova chave. - FreespaceChecker @@ -854,10 +504,6 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin Core - version versão @@ -867,8 +513,8 @@ (%1-bit) - About Bitcoin Core - Sobre o Bitcoin Core + About %1 + Sobre %1 Command-line options @@ -906,11 +552,7 @@ Show splash screen on startup (default: %u) Mostrar o ecrã de abertura no arranque (predefinição: %u) - - Reset all settings changes made over the GUI - Reiniciar as alterações das configurações efetuadas na GUI - - + Intro @@ -918,16 +560,8 @@ Bem-vindo - Welcome to Bitcoin Core. - Bem-vindo ao Bitcoin Core. - - - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - Como esta é a primeira vez que o programa é iniciado, pode escolher onde guardar os seus dados do Bitcoin Core. - - - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - O Bitcoin Core irá transferir e guardar uma cópia da cadeia de bloco do Bitcoin. Pelo menos %1GB de dados serão guardados nesta diretoria, e estes irão crescer ao longo do tempo. A sua carteira também será guardada nesta diretoria. + Welcome to %1. + Bem-vindo a %1. Use the default data directory @@ -937,10 +571,6 @@ Use a custom data directory: Utilizar uma diretoria de dados personalizada: - - Bitcoin Core - Bitcoin Core - Error: Specified data directory "%1" cannot be created. Erro: não pode ser criada a diretoria de dados especificada como "%1. @@ -976,10 +606,6 @@ Select payment request file Seleccione o ficheiro de pedido de pagamento - - Select payment request file to open - Seleccione o ficheiro de pedido de pagamento a abrir - OptionsDialog @@ -991,6 +617,10 @@ &Main &Principal + + &Start %1 on system login + &Iniciar o %1 no início de sessão do sistema + Size of &database cache Tamanho da cache da base de &dados @@ -1019,10 +649,6 @@ 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. Minimize ao invés de sair da aplicação quando a janela é fechada. Com esta opção selecionada, a aplicação apenas será encerrada quando escolher Sair da aplicação no menú. - - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - O idioma da da interface do utilizador pode ser definida aqui. Esta definição será aplicada depois de reiniciar o Bitcoin Core. - 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 |. URLs de outrem (ex. um explorador de blocos) que aparece no separador de transações como itens do menu de contexto. @@ -1048,14 +674,6 @@ &Network &Rede - - Automatically start Bitcoin Core after logging in to the system. - Iniciar automaticamente o Bitcoin Core depois de iniciar a sessão no sistema. - - - &Start Bitcoin Core on system login - &Iniciar o Bitcoin Core ao iniciar a sessão no sistema - (0 = auto, <0 = leave that many cores free) (0 = automático, <0 = deixar essa quantidade de núcleos livre) @@ -1140,6 +758,10 @@ &Window &Janela + + Hide tray icon + Ocultar ícone da bandeja + Show only a tray icon after minimizing the window. Apenas mostrar o ícone da bandeja de sistema após minimizar a janela. @@ -1285,167 +907,57 @@ - PaymentServer + PeerTableModel - URI handling - Manuseamento de URI + User Agent + Agente Usuário - Invalid payment address %1 - Endereço de pagamento inválido %1 + Node/Service + Nó/Serviço - Payment request rejected - Pedido de pagamento rejeitado + Ping Time + Tempo de Latência + + + QObject - Payment request network doesn't match client network. - Rede de requisição de pagamento não corresponde com a rede do cliente. + Amount + Quantia - Payment request is not initialized. - Requisição de pagamento não iniciou. + Enter a Bitcoin address (e.g. %1) + Entre um endereço Bitcoin (ex. %1) - Requested payment amount of %1 is too small (considered dust). - Quantia solicitada para pagamento de %1 é muito pequena (considerada "pó"). + %1 d + %1 d - Payment request error - Erro de pedido de pagamento + %1 h + %1 h - Cannot start bitcoin: click-to-pay handler - Não é possível iniciar o Bitcoin: utilizador clique-para-pagar + %1 m + %1 m - Payment request fetch URL is invalid: %1 - O URL de pedido de pagamento é inválido: %1 + %1 s + %1 s - URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - URI não foi lido correctamente! Isto pode ser causado por um endereço Bitcoin inválido ou por parâmetros URI malformados. + None + Nenhum - Payment request file handling - Controlo de pedidos de pagamento. + N/A + N/D - Payment request file cannot be read! This can be caused by an invalid payment request file. - O ficheiro de pedido de pagamento não pôde ser lido! Isto pode ter sido causado por um ficheiro de pedido de pagamento inválido. - - - Payment request expired. - Pedido de pagamento expirou. - - - Unverified payment requests to custom payment scripts are unsupported. - Pedidos de pagamento não-verificados para scripts de pagamento personalizados não são suportados. - - - Invalid payment request. - Pedido de pagamento inválido. - - - Refund from %1 - Reembolsar de %1 - - - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - Pedido de pagamento %1 excede o tamanho (%2 bytes, permitido %3 bytes). - - - Error communicating with %1: %2 - Erro ao comunicar com %1: %2 - - - Payment request cannot be parsed! - O pedido de pagamento não pode ser lido ou processado! - - - Bad response from server %1 - Má resposta do servidor %1 - - - Payment acknowledged - Pagamento confirmado - - - Network request error - Erro de pedido de rede - - - - PeerTableModel - - User Agent - Agente Usuário - - - Node/Service - Nó/Serviço - - - Ping Time - Tempo de Latência - - - - QObject - - Amount - Quantia - - - Enter a Bitcoin address (e.g. %1) - Entre um endereço Bitcoin (ex. %1) - - - %1 d - %1 d - - - %1 h - %1 h - - - %1 m - %1 m - - - %1 s - %1 s - - - None - Nenhum - - - N/A - N/D - - - %1 ms - %1 ms - - - - QRImageWidget - - &Save Image... - &Salvar Imagem... - - - &Copy Image - &Copiar Imagem - - - Save QR Code - Guardar Código QR - - - PNG Image (*.png) - Imagem PNG (*.png) + %1 ms + %1 ms @@ -1514,10 +1026,6 @@ Memory usage Utilização de memória - - Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. - Abrir o ficheiro de registo de depuração da pasta de dados actual. Isto pode demorar alguns segundos para ficheiros de registo grandes. - Received Recebido @@ -1566,6 +1074,14 @@ User Agent Agente Usuário + + Decrease font size + Diminuir tamanho da letra + + + Increase font size + Aumentar tamanho da letra + Services Serviços @@ -1634,10 +1150,6 @@ Out: Saída: - - Build date - Data de compilação - Debug log file Ficheiro de registo de depuração @@ -1675,8 +1187,8 @@ &Desbloquear Nó - Welcome to the Bitcoin Core RPC console. - Bem-vindo à consola RPC do Bitcoin Core. + Welcome to the %1 RPC console. + Bem-vindo à consola RPC da %1. Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. @@ -1805,18 +1317,6 @@ Remove Remover - - Copy label - Copiar rótulo - - - Copy message - Copiar mensagem - - - Copy amount - Copiar quantia - ReceiveRequestDialog @@ -1836,73 +1336,6 @@ &Save Image... &Salvar Imagem... - - Request payment to %1 - Requisitar Pagamento para %1 - - - Payment information - Informação de Pagamento - - - URI - URI - - - Address - Endereço - - - Amount - Quantia - - - Label - Rótulo - - - Message - Mensagem - - - Resulting URI too long, try to reduce the text for label / message. - URI resultante muito longo. Tente reduzir o texto do rótulo / mensagem. - - - Error encoding URI into QR Code. - Erro ao codificar URI em Código QR. - - - - RecentRequestsTableModel - - Date - Data - - - Label - Rótulo - - - Message - Mensagem - - - Amount - Quantia - - - (no label) - (sem rótulo) - - - (no message) - (sem mensagem) - - - (no amount) - (sem quantia) - SendCoinsDialog @@ -1980,922 +1413,284 @@ If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte. - Se a taxa fixa for 1000 satoshis e a transação for somente 250 bytes, pagará somente 250 satoshis "por kilobyte" em custos se trasacionar "pelo menos" 1000 satoshis. Transações superiores a um kilobyte são cobradas por kilobyte. - - - Hide - Esconder - - - total at least - total minimo - - - Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process. - Pode pagar somente a taxa minima desde que haja um volume de transações inferior ao espaço nos blocos. No entanto tenha em atenção que esta opção poderá acabar em uma transação nunca confirmada assim que os pedidos de transações excedam a capacidade de processamento da rede. - - - (read the tooltip) - (leia a dica) - - - Recommended: - Recomendado: - - - Custom: - Uso: - - - (Smart fee not initialized yet. This usually takes a few blocks...) - (Taxa inteligente ainda não foi acionada. Normalmente demora alguns blocos...) - - - Confirmation time: - Tempo de confirmação: - - - normal - normal - - - fast - rapido - - - Send as zero-fee transaction if possible - Enviar como uma transação a custo zero se possivél - - - (confirmation may take longer) - (confirmação poderá demorar mais) - - - Send to multiple recipients at once - Enviar para múltiplos destinatários de uma vez - - - Add &Recipient - Adicionar &Destinatário - - - Clear all fields of the form. - Limpar todos os campos do formulário. - - - Dust: - Lixo: - - - Clear &All - Limpar &Tudo - - - Balance: - Saldo: - - - Confirm the send action - Confirme ação de envio - - - S&end - E&nviar - - - Confirm send coins - Confirme envio de moedas - - - %1 to %2 - %1 para %2 - - - Copy quantity - Copiar quantidade - - - Copy amount - Copiar quantia - - - Copy fee - Copiar taxa - - - Copy after fee - Copiar valor após taxa - - - Copy bytes - Copiar bytes - - - Copy priority - Copiar prioridade - - - Copy change - Copiar alteração - - - Total Amount %1 - Quantia Total %1 - - - or - ou - - - The amount to pay must be larger than 0. - A quantia a pagar deverá ser maior que 0. - - - The amount exceeds your balance. - A quantia excede o seu saldo. - - - The total exceeds your balance when the %1 transaction fee is included. - O total excede o seu saldo quando a taxa de transação de %1 for incluída. - - - Transaction creation failed! - Erro: A criação da transação falhou! - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - A transação foi rejeitada! Isto poderá acontecer se algumas das moedas na sua carteira já tiverem sido gastas, se por exemplo tiver usado uma cópia do ficheiro wallet.dat e as moedas tiverem sido gastas na cópia mas não tiverem sido marcadas como gastas aqui. - - - A fee higher than %1 is considered an absurdly high fee. - Uma taxa superior a %1 é considerada muito alta. - - - Payment request expired. - Pedido de pagamento expirou. - - - Pay only the required fee of %1 - Pagar somente a taxa mínima de %1 - - - The recipient address is not valid. Please recheck. - O endereço de destino não é válido. Por favor, verifique novamente. - - - Duplicate address found: addresses should only be used once each. - Endereço duplicado encontrado: cada endereço só poderá ser usado uma vez. - - - Warning: Invalid Bitcoin address - Aviso: Endereço Bitcoin inválido - - - (no label) - (sem rótulo) - - - Warning: Unknown change address - Aviso: Endereço de troco desconhecido - - - Copy dust - Copiar lixo - - - Are you sure you want to send? - Tem a certeza que deseja enviar? - - - added as transaction fee - adicionados como taxa de transação - - - - SendCoinsEntry - - A&mount: - Qu&antia: - - - Pay &To: - &Pagar A: - - - Enter a label for this address to add it to your address book - Escreva um rótulo para este endereço para o adicionar ao seu livro de endereços - - - &Label: - Rótu&lo: - - - Choose previously used address - Escolha o endereço utilizado anteriormente - - - This is a normal payment. - Este é um pagamento normal. - - - The Bitcoin address to send the payment to - O endereço Bitcoin para enviar o pagamento - - - Alt+A - Alt+A - - - Paste address from clipboard - Cole endereço da área de transferência - - - Alt+P - Alt+P - - - Remove this entry - Remover esta entrada - - - 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. - A taxa será deduzida ao montante enviado. O destinatário irá receber menos bitcoins do que as que introduziu no campo montante. Caso sejam seleccionados múltiplos destinatários, a taxa será repartida equitativamente. - - - S&ubtract fee from amount - S&ubtrair taxa ao montante - - - Message: - Mensagem: - - - This is an unauthenticated payment request. - Pedido de pagamento não autenticado. - - - This is an authenticated payment request. - Pedido de pagamento autenticado. - - - Enter a label for this address to add it to the list of used addresses - Introduza um rótulo para este endereço para o adicionar à sua lista de endereços usados - - - 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. - Uma mensagem que estava anexada ao URI bitcoin: que será armazenada com a transação para sua referência. Nota: Esta mensagem não será enviada através da rede Bitcoin. - - - Pay To: - Pagar a: - - - Memo: - Memorando: - - - - ShutdownWindow - - Bitcoin Core is shutting down... - O Bitcoin Core está a encerrar... - - - Do not shut down the computer until this window disappears. - Não desligue o computador enquanto esta janela não desaparecer. - - - - SignVerifyMessageDialog - - Signatures - Sign / Verify a Message - Assinaturas - Assinar / Verificar uma Mensagem - - - &Sign Message - &Assinar Mensagem - - - 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. - Pode assinar mensagens com os seus endereços para provar que são seus. Tenha atenção ao assinar mensagens ambíguas, pois ataques de phishing podem tentar enganá-lo de modo a assinar a sua identidade para os atacantes. Apenas assine declarações detalhadas com as quais concorde. - - - The Bitcoin address to sign the message with - O endereço Bitcoin para designar a mensagem - - - Choose previously used address - Escolha o endereço utilizado anteriormente - - - Alt+A - Alt+A - - - Paste address from clipboard - Colar endereço da área de transferência - - - Alt+P - Alt+P - - - Enter the message you want to sign here - Escreva aqui a mensagem que deseja assinar - - - Signature - Assinatura - - - Copy the current signature to the system clipboard - Copiar a assinatura actual para a área de transferência - - - Sign the message to prove you own this Bitcoin address - Assine uma mensagem para provar que é dono deste endereço Bitcoin - - - Sign &Message - Assinar &Mensagem - - - Reset all sign message fields - Repor todos os campos de assinatura de mensagem - - - Clear &All - Limpar &Tudo - - - &Verify Message - &Verificar Mensagem - - - 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! - Introduza o endereço de assinatura, mensagem (assegure-se que copia quebras de linha, espaços, tabulações, etc. exactamente) e assinatura abaixo para verificar a mensagem. Tenha atenção para não ler mais na assinatura do que o que estiver na mensagem assinada, para evitar ser enganado por um atacante que se encontre entre si e quem assinou a mensagem. - - - The Bitcoin address the message was signed with - O endereço Bitcoin com que a mensagem foi designada - - - Verify the message to ensure it was signed with the specified Bitcoin address - Verifique a mensagem para assegurar que foi assinada com o endereço Bitcoin especificado - - - Verify &Message - Verificar &Mensagem - - - Reset all verify message fields - Repor todos os campos de verificação de mensagem - - - Click "Sign Message" to generate signature - Clique "Assinar mensagem" para gerar a assinatura - - - The entered address is invalid. - O endereço introduzido é inválido. - - - Please check the address and try again. - Por favor verifique o endereço e tente de novo. - - - The entered address does not refer to a key. - O endereço introduzido não refere a nenhuma chave. - - - Wallet unlock was cancelled. - O desbloqueio da carteira foi cancelado. - - - Private key for the entered address is not available. - A chave privada para o endereço introduzido não está disponível. - - - Message signing failed. - Assinatura de mensagem falhou. - - - Message signed. - Mensagem assinada. - - - The signature could not be decoded. - A assinatura não pôde ser descodificada. - - - Please check the signature and try again. - Por favor verifique a assinatura e tente de novo. - - - The signature did not match the message digest. - A assinatura não condiz com o conteúdo da mensagem. - - - Message verification failed. - Verificação da mensagem falhou. - - - Message verified. - Mensagem verificada. - - - - SplashScreen - - Bitcoin Core - Bitcoin Core - - - The Bitcoin Core developers - Os programadores do Bitcoin Core - - - [testnet] - [rede de testes] - - - - TrafficGraphWidget - - KB/s - KB/s - - - - TransactionDesc - - Open until %1 - Aberto até %1 - - - conflicted - em conflito: - - - %1/offline - %1/desligado - - - %1/unconfirmed - %1/não confirmada - - - %1 confirmations - %1 confirmações - - - Status - Estado - - - , broadcast through %n node(s) - , transmitida através de %n nó, transmitida através de %n nós - - - Date - Data - - - Source - Origem - - - Generated - Gerado - - - From - De - - - To - Para - - - own address - endereço próprio - - - watch-only - modo-verificação - - - label - rótulo - - - Credit - Crédito - - - matures in %n more block(s) - matura em %n blocomatura em %n blocos - - - not accepted - não aceite - - - Debit - Débito - - - Total debit - Total a debitar - - - Total credit - Total a creditar - - - Transaction fee - Taxa de transação - - - Net amount - Valor líquido - - - Message - Mensagem - - - Comment - Comentário - - - Transaction ID - ID da Transação - - - Merchant - Comerciante - - - 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. - Moedas geradas deverão maturar por %1 blocos antes de poderem ser gastas. Quando gerou este bloco, ele foi transmitido para a rede para ser incluído na cadeia de blocos. Se a inclusão na cadeia de blocos falhar, o seu estado irá ser alterado para "não aceite" e as moedas não poderão ser gastas. Isto poderá acontecer ocasionalmente se outro nó da rede gerar um bloco a poucos segundos de diferença do seu. - - - Debug information - Informação de depuração - - - Transaction - Transação - - - Inputs - Entradas - - - Amount - Quantia - - - true - verdadeiro - - - false - falso - - - , has not been successfully broadcast yet - , ainda não foi transmitida com sucesso - - - Open for %n more block(s) - Aberta por mais %n blocoAberta por mais %n blocos - - - unknown - desconhecido - - - - TransactionDescDialog - - Transaction details - Detalhes da transação - - - This pane shows a detailed description of the transaction - Esta janela mostra uma descrição detalhada da transação - - - - TransactionTableModel - - Date - Data + Se a taxa fixa for 1000 satoshis e a transação for somente 250 bytes, pagará somente 250 satoshis "por kilobyte" em custos se trasacionar "pelo menos" 1000 satoshis. Transações superiores a um kilobyte são cobradas por kilobyte. - Type - Tipo + Hide + Esconder - Immature (%1 confirmations, will be available after %2) - Imaturo (%1 confirmações, estará disponível após %2) - - - Open for %n more block(s) - Aberta por mais %n blocoAberta por mais %n blocos + total at least + total minimo - Open until %1 - Aberto até %1 + Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process. + Pode pagar somente a taxa minima desde que haja um volume de transações inferior ao espaço nos blocos. No entanto tenha em atenção que esta opção poderá acabar em uma transação nunca confirmada assim que os pedidos de transações excedam a capacidade de processamento da rede. - Confirmed (%1 confirmations) - Confirmada (%1 confirmações) + (read the tooltip) + (leia a dica) - This block was not received by any other nodes and will probably not be accepted! - Este bloco não foi recebido por outros nós e provavelmente não será aceite pela rede! + Recommended: + Recomendado: - Generated but not accepted - Gerado mas não aceite + Custom: + Uso: - Offline - Offline + (Smart fee not initialized yet. This usually takes a few blocks...) + (Taxa inteligente ainda não foi acionada. Normalmente demora alguns blocos...) - Label - Rótulo + Confirmation time: + Tempo de confirmação: - Unconfirmed - Não confirmado: + normal + normal - Confirming (%1 of %2 recommended confirmations) - A confirmar (%1 de %2 confirmações recomendadas) + fast + rapido - Conflicted - Em Conflito: + Send to multiple recipients at once + Enviar para múltiplos destinatários de uma vez - Received with - Recebido com + Add &Recipient + Adicionar &Destinatário - Received from - Recebido de + Clear all fields of the form. + Limpar todos os campos do formulário. - Sent to - Enviado para + Dust: + Lixo: - Payment to yourself - Pagamento a si mesmo + Clear &All + Limpar &Tudo - Mined - Minadas + Balance: + Saldo: - watch-only - modo-verificação + Confirm the send action + Confirme ação de envio - (n/a) - (n/d) + S&end + E&nviar + + + SendCoinsEntry - Transaction status. Hover over this field to show number of confirmations. - Estado da transação. Passar o cursor por cima deste campo para mostrar o número de confirmações. + A&mount: + Qu&antia: - Date and time that the transaction was received. - Data e hora em que a transação foi recebida. + Pay &To: + &Pagar A: - Type of transaction. - Tipo de transação. + &Label: + Rótu&lo: - Whether or not a watch-only address is involved in this transaction. - Desde que um endereço de modo-verificação faça parte ou não desta transação + Choose previously used address + Escolha o endereço utilizado anteriormente - User-defined intent/purpose of the transaction. - Motivo da transacção definido pelo utilizador. + This is a normal payment. + Este é um pagamento normal. - Amount removed from or added to balance. - Quantia retirada ou adicionada ao saldo. + The Bitcoin address to send the payment to + O endereço Bitcoin para enviar o pagamento - - - TransactionView - All - Todas + Alt+A + Alt+A - Today - Hoje + Paste address from clipboard + Cole endereço da área de transferência - This week - Esta semana + Alt+P + Alt+P - This month - Este mês + Remove this entry + Remover esta entrada - Last month - Mês passado + 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. + A taxa será deduzida ao montante enviado. O destinatário irá receber menos bitcoins do que as que introduziu no campo montante. Caso sejam seleccionados múltiplos destinatários, a taxa será repartida equitativamente. - This year - Este ano + S&ubtract fee from amount + S&ubtrair taxa ao montante - Range... - Período... + Message: + Mensagem: - Received with - Recebida com + This is an unauthenticated payment request. + Pedido de pagamento não autenticado. - Sent to - Enviada para + This is an authenticated payment request. + Pedido de pagamento autenticado. - To yourself - Para si mesmo + Enter a label for this address to add it to the list of used addresses + Introduza um rótulo para este endereço para o adicionar à sua lista de endereços usados - Mined - Minadas + 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. + Uma mensagem que estava anexada ao URI bitcoin: que será armazenada com a transação para sua referência. Nota: Esta mensagem não será enviada através da rede Bitcoin. - Other - Outras + Pay To: + Pagar a: - Enter address or label to search - Escreva endereço ou rótulo a procurar + Memo: + Memorando: + + + ShutdownWindow - Min amount - Quantia mínima + %1 is shutting down... + %1 está a encerrar... - Copy address - Copiar endereço + Do not shut down the computer until this window disappears. + Não desligue o computador enquanto esta janela não desaparecer. + + + SignVerifyMessageDialog - Copy label - Copiar rótulo + Signatures - Sign / Verify a Message + Assinaturas - Assinar / Verificar uma Mensagem - Copy amount - Copiar quantia + &Sign Message + &Assinar Mensagem - Copy transaction ID - Copiar ID da Transação + 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. + Pode assinar mensagens com os seus endereços para provar que são seus. Tenha atenção ao assinar mensagens ambíguas, pois ataques de phishing podem tentar enganá-lo de modo a assinar a sua identidade para os atacantes. Apenas assine declarações detalhadas com as quais concorde. - Copy raw transaction - Copiar dados brutos da transacção + The Bitcoin address to sign the message with + O endereço Bitcoin para designar a mensagem - Edit label - Editar rótulo + Choose previously used address + Escolha o endereço utilizado anteriormente - Show transaction details - Mostrar detalhes da transação + Alt+A + Alt+A - Export Transaction History - Exportar Histórico de Transacções + Paste address from clipboard + Colar endereço da área de transferência - Watch-only - Modo-verificação + Alt+P + Alt+P - Exporting Failed - A Exportação Falhou + Enter the message you want to sign here + Escreva aqui a mensagem que deseja assinar - There was an error trying to save the transaction history to %1. - Ocorreu um erro ao tentar guardar o histórico de transações em %1. + Signature + Assinatura - Exporting Successful - Exportação Bem Sucedida + Copy the current signature to the system clipboard + Copiar a assinatura actual para a área de transferência - The transaction history was successfully saved to %1. - O histórico de transacções foi com guardado com sucesso em %1. + Sign the message to prove you own this Bitcoin address + Assine uma mensagem para provar que é dono deste endereço Bitcoin - Comma separated file (*.csv) - Ficheiro separado por vírgulas (*.csv) + Sign &Message + Assinar &Mensagem - Confirmed - Confirmada + Reset all sign message fields + Repor todos os campos de assinatura de mensagem - Date - Data + Clear &All + Limpar &Tudo - Type - Tipo + &Verify Message + &Verificar Mensagem - Label - Rótulo + 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! + Introduza o endereço de assinatura, mensagem (assegure-se que copia quebras de linha, espaços, tabulações, etc. exactamente) e assinatura abaixo para verificar a mensagem. Tenha atenção para não ler mais na assinatura do que o que estiver na mensagem assinada, para evitar ser enganado por um atacante que se encontre entre si e quem assinou a mensagem. - Address - Endereço + The Bitcoin address the message was signed with + O endereço Bitcoin com que a mensagem foi designada - ID - ID + Verify the message to ensure it was signed with the specified Bitcoin address + Verifique a mensagem para assegurar que foi assinada com o endereço Bitcoin especificado - Range: - Período: + Verify &Message + Verificar &Mensagem - to - até + Reset all verify message fields + Repor todos os campos de verificação de mensagem - UnitDisplayStatusBarControl + SplashScreen - Unit to show amounts in. Click to select another unit. - Unidade de valores recebidos. Clique para selecionar outra unidade. + [testnet] + [rede de testes] - WalletFrame + TrafficGraphWidget - No wallet has been loaded. - Não foi carregada nenhuma carteira. + KB/s + KB/s - WalletModel + TransactionDescDialog - Send Coins - Enviar Moedas + This pane shows a detailed description of the transaction + Esta janela mostra uma descrição detalhada da transação - WalletView - - &Export - &Exportar - - - Export the data in the current tab to a file - Exportar os dados no separador actual para um ficheiro - - - Backup Wallet - Cópia de Segurança da Carteira - - - Wallet Data (*.dat) - Dados da Carteira (*.dat) - - - Backup Failed - Cópia de Segurança Falhou - - - There was an error trying to save the wallet data to %1. - Ocorreu um erro ao tentar guardar os dados da carteira em %1. - - - The wallet data was successfully saved to %1. - Os dados da carteira foram guardados com sucesso em %1. - + UnitDisplayStatusBarControl - Backup Successful - Cópia de Segurança Bem Sucedida + Unit to show amounts in. Click to select another unit. + Unidade de valores recebidos. Clique para selecionar outra unidade. @@ -2924,14 +1719,6 @@ If <category> is not supplied or if <category> = 1, output all debugging information. Se <category> não é fornecida ou <category> = 1, imprimir toda a informação de depuração. - - Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s) - Total máximo de taxas (em %s) a utilizar numa única transacção; definir este valor demasiado baixo pode abortar transacções grandes (padrão: %s) - - - Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. - Por favor verifique que a data e hora do seu computador estão correctas! Se o seu relógio não estiver certo o Bitcoin Core não irá funcionar correctamente. - Prune configured below the minimum of %d MiB. Please use a higher number. Poda configurada abaixo do mínimo de %d MiB. Por favor, utilize um valor mais elevado. @@ -2972,6 +1759,10 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Aceitar ligações externas (padrão: 1 sem -proxy ou -connect) + + Bitcoin Core + Bitcoin Core + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. -fallbackfee está definida muito elevada! Esta é a taxa de transação pode poderá pagar quando as estimativas de taxas não estão disponíveis. @@ -3016,14 +1807,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Esta é uma versão de testes pré-lançamento - use à sua responsabilidade - não usar para minar ou aplicações comerciais - - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - Incapaz de vincular à porta %s neste computador. O Bitcoin Core provavelmente já está a correr. - - - Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. - Argumento não suportado -whitelistalwaysrelay ignorado, utilize -whitelistrelay e/ou -whitelistforcerelay. - Use UPnP to map the listening port (default: 1 when listening and no -proxy) Utilizar UPnP para mapear a porta de escuta (predefinição: 1 quando escutar e sem -proxy) @@ -3040,18 +1823,10 @@ Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Aviso: A rede não parece estar completamente de acordo! Parece que alguns mineiros estão com dificuldades técnicas. - - Warning: Unknown block versions being mined! It's possible unknown rules are in effect - Atenção: Versões desconhecidas de blocos estão a ser mineradas! É possível que regras desconhecias estão a ser efetuadas - Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Atenção: Parecemos não estar de acordo com os nossos pares! Poderá ter que atualizar o seu cliente, ou outros nós poderão ter que atualizar os seus clientes. - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Atenção: wallet.dat corrompido, dados recuperados! wallet.dat original salvo como wallet.{timestamp}.bak em %s; se o seu saldo ou transações estiverem incorrectos deverá recuperar uma cópia de segurança. - Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. Ligações na lista branca conectam desde a seguinte netmask ou endereço IP. Posse ser especificado varias vezes. @@ -3124,6 +1899,18 @@ Error initializing wallet database environment %s! Erro ao inicializar o ambiente %s da base de dados da carteira + + Error loading %s + Erro ao carregar %s + + + Error loading %s: Wallet corrupted + Erro ao carregar %s: carteira corrompida + + + Error loading %s: Wallet requires newer version of %s + Erro ao carregar %s: a carteira requer a nova versão de %s + Error loading block database Erro ao carregar base de dados de blocos @@ -3152,6 +1939,10 @@ Invalid -onion address: '%s' Endereço -onion inválido: '%s' + + Invalid amount for -%s=<amount>: '%s' + Valor inválido para -%s=<amount>: '%s' + Invalid amount for -fallbackfee=<amount>: '%s' Valor inválido para -fallbackfee=<amount>: '%s' @@ -3176,6 +1967,10 @@ Only connect to nodes in network <net> (ipv4, ipv6 or onion) Somente conectar aos nodes na rede <net> (ipv4, ipv6 ou onion) + + Print this help message and exit + Imprimir esta mensagem de ajuda e sair + Print version and exit Imprimir versão e sair @@ -3236,10 +2031,6 @@ Wallet options: Opções da carteira: - - You need to rebuild the database using -reindex to change -txindex - É necessário reconstruir as bases de dados usando -reindex para mudar o -txindex - 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 Permitir conexções JSON-RPC de fontes especificas. Valido para <ip> um unico IP (ex. 1.2.3.4), uma rede/netmask (ex. 1.2.3.4/255.255.255.0) ou uma rede/CIDR (ex. 1.2.3.4/24). Esta opção pode ser especificada varias vezes @@ -3252,10 +2043,6 @@ Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces) Vinculado para dar o endereço para atender as ligações JSON-RPC. Use [host]: Notação de porta para IPv6. Esta opção pode ser especificada várias vezes (padrão: ligam-se a todas as interfaces) - - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - Impossível trancar a pasta de dados %s. Provavelmente o Bitcoin Core já está a ser executado. - Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) Crie ficheiros novos com as permisões predefinidas do sistema, em vez de umask 077 (apenas eficaz caso a funcionalidade carteira esteja desactivada) @@ -3300,10 +2087,6 @@ Set maximum size of high-priority/low-fee transactions in bytes (default: %d) Definir tamanho máximo de transações com alta-prioridade/baixa-taxa em bytes (por defeito: %d) - - Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) - Definir o número threads para a geração de moedas, caso activo (-1 = todos os cores, padrão: %d) - The transaction amount is too small to send after the fee has been deducted O montante da transacção é demasiado baixo após a dedução da taxa @@ -3328,34 +2111,14 @@ Accept public REST requests (default: %u) Aceitar pedidos REST públicos (predefinição: %u) - - Activating best chain... - A activar a melhor cadeia... - - - Attempt to recover private keys from a corrupt wallet.dat on startup - Tentar recuperar chaves privadas de um wallet.dat corrompido ao iniciar - Automatically create Tor hidden service (default: %d) Criar automaticamente o serviço Tor oculto (predefinição: %d) - - Cannot resolve -whitebind address: '%s' - Não foi possível resolver o endereço -whitebind: '%s' - Connect through SOCKS5 proxy Ligar através de um proxy SOCKS5 - - Copyright (C) 2009-%i The Bitcoin Core Developers - Copyright (C) 2009-%i Os Programadores do Bitcoin Core - - - Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - Erro ao carregar wallet.dat: A carteira requer uma versão mais recente do Bitcoin Core - Error reading from database, shutting down. Erro ao ler da base de dados, encerrando. @@ -3368,22 +2131,6 @@ Information Informação - - Initialization sanity check failed. Bitcoin Core is shutting down. - Falha na prova real inicial. Bitcoin Core está a desligar. - - - Invalid amount for -maxtxfee=<amount>: '%s' - Quantia inválida para -maxtxfee=<quantidade>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Quantia inválida para -minrelaytxfee=<quantidade>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - Quantia inválida para -mintxfee=<quantidade>: '%s' - Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) Montante inválido para -paytxfee=<amount>: '%s' (deverá ser no mínimo %s) @@ -3408,14 +2155,6 @@ RPC server options: Opções do servidor RPC: - - Rebuild block chain index from current blk000??.dat files on startup - Reconstruir a cadeia de blocos a partir dos ficheiros blk000??.dat actuais ao iniciar - - - Receive and display P2P network alerts (default: %u) - Receber e mostrar alertas da rede P2P (padrão: %u) - Reducing -maxconnections from %d to %d, because of system limitations. Reduzindo -maxconnections de %d para %d, devido a limitações no sistema. @@ -3488,10 +2227,6 @@ Username for JSON-RPC connections Nome de utilizador para ligações JSON-RPC - - Wallet needed to be rewritten: restart Bitcoin Core to complete - A Carteira precisou de ser reescrita: reinicie o Bitcoin Core para completar o processo - Warning Aviso @@ -3512,10 +2247,6 @@ ZeroMQ notification options: Opções de notificação ZeroMQ: - - wallet.dat corrupt, salvage failed - wallet.dat corrompido, recuperação falhou - Password for JSON-RPC connections Palavra-passe para ligações JSON-RPC @@ -3524,10 +2255,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) Executar comando quando o melhor bloco mudar (no comando, %s é substituído pela hash do bloco) - - This help message - Esta mensagem de ajuda - Allow DNS lookups for -addnode, -seednode and -connect Permitir procuras DNS para -addnode, -seednode e -connect @@ -3536,10 +2263,6 @@ Loading addresses... A carregar os endereços... - - Error loading wallet.dat: Wallet corrupted - Erro ao carregar wallet.dat: Carteira danificada - (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) (1 = guardar metadados da transacção ex: proprietário da conta e informação do pedido de pagamento, 2 = descartar metadados da transacção) @@ -3556,10 +2279,6 @@ Do not keep transactions in the mempool longer than <n> hours (default: %u) Não guardar transações no banco de memória por mais de <n> horas (predefinição: %u) - - Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. - Erro ao ler wallet.dat! Todas as chaves foram lidas correctamente, mas os dados das transacções ou do livro de endereços podem estar em falta ou incorrectos. - Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) Taxas (em %s/kB) abaixo deste valor são consideradas nulas para a criação de transacções (padrão: %s) @@ -3596,6 +2315,10 @@ Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported. Encontrado um argumento não suportado -socks. Definir a versão do SOCKS já não é possível, apenas proxies SOCKS5 são suportados. + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + Argumento não suportado -whitelistalwaysrelay ignorado, utilize -whitelistrelay e/ou -whitelistforcerelay. + Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s) Use um proxy SOCKS5 separado para alcançar pares via serviços ocultos do Tor (padrão: %s) @@ -3604,6 +2327,10 @@ Username and hashed password for JSON-RPC connections. The field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A canonical python script is included in share/rpcuser. This option can be specified multiple times Username e hash da password para ligações JSON-RPC. O campo <userpw> está no formato: <USERNAME>:<SALT>$<HASH>. Um script python está incluido em share/rpcuser. Esta opção pode ser especificada múltiplas vezes. + + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + Atenção: Versões desconhecidas de blocos estão a ser mineradas! É possível que regras desconhecias estão a ser efetuadas + (default: %s) (predefinição: %s) @@ -3612,14 +2339,6 @@ Always query for peer addresses via DNS lookup (default: %u) Utilizar sempre a consulta de DNS para endereços de pares (predefinição: %u) - - Error loading wallet.dat - Erro ao carregar wallet.dat - - - Generate coins (default: %u) - Gerar moedas (predefinição: %u) - How many blocks to check at startup (default: %u, 0 = all) Quantos blocos para verificar no arranque (predefinição: %u, 0 = todos) @@ -3704,18 +2423,6 @@ Unknown network specified in -onlynet: '%s' Rede desconhecida especificada em -onlynet: '%s' - - Cannot resolve -bind address: '%s' - Não foi possível resolver o endereço -bind: '%s' - - - Cannot resolve -externalip address: '%s' - Não foi possível resolver o endereço -externalip: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - Quantia inválida para -paytxfee=<amount>: '%s' - Insufficient funds Fundos insuficientes diff --git a/src/qt/locale/bitcoin_ro.ts b/src/qt/locale/bitcoin_ro.ts index 11ac69f0f2dd1..270a4ba062994 100644 --- a/src/qt/locale/bitcoin_ro.ts +++ b/src/qt/locale/bitcoin_ro.ts @@ -11,7 +11,7 @@ &New - &Nou + Nou Copy the currently selected address to the system clipboard @@ -19,15 +19,11 @@ &Copy - &Copiază + Copiază C&lose - Î&nchide - - - &Copy Address - &Copiază Adresa + Închide Delete the currently selected address from the list @@ -39,32 +35,38 @@ &Export - &Exportă - - - Choose the address to send coins to - Indică adresa de expediere a monedelor + Exportă - Choose the address to receive coins with - Indică adresa de a primi monedele + &Delete + Șterge - - - AddressTableModel - + AskPassphraseDialog - + + Passphrase Dialog + Secventa de cuvinte a parolei + + + Enter passphrase + Introduceti parola + + + New passphrase + Noua parolă + + + Repeat new passphrase + Repetati noua parolă + + BanTableModel BitcoinGUI - - ClientModel - CoinControlDialog @@ -89,18 +91,12 @@ OverviewPage - - PaymentServer - PeerTableModel QObject - - QRImageWidget - RPCConsole @@ -110,9 +106,6 @@ ReceiveRequestDialog - - RecentRequestsTableModel - SendCoinsDialog @@ -131,38 +124,12 @@ TrafficGraphWidget - - TransactionDesc - TransactionDescDialog - - TransactionTableModel - - - TransactionView - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - - WalletView - - &Export - &Exportă - - - Export the data in the current tab to a file - Exportă datele din tabul curent in fisier - - bitcoin-core diff --git a/src/qt/locale/bitcoin_ro_RO.ts b/src/qt/locale/bitcoin_ro_RO.ts index 502052dffb296..e6f591aa9e67c 100644 --- a/src/qt/locale/bitcoin_ro_RO.ts +++ b/src/qt/locale/bitcoin_ro_RO.ts @@ -25,10 +25,6 @@ C&lose Închide - - &Copy Address - &Copiază Adresa - Delete the currently selected address from the list Şterge adresele curent selectate din listă @@ -45,73 +41,6 @@ &Delete &Şterge - - Choose the address to send coins to - Alegeţi adresa unde vreţi să trimiteţi monedele - - - Choose the address to receive coins with - Alegeţi adresa unde vreţi să primiţi monedele - - - C&hoose - &Alegeţi - - - Sending addresses - Adresa destinatarului - - - Receiving addresses - Adresa de primire - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Acestea sînt adresele dumneavoastră Bitcoin pentru efectuarea plăţilor. Verificaţi întotdeauna cantitatea şi adresa de primire înainte de a trimite monede. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Acestea sînt adresele dumneavoastră Bitcoin folosite pentru a primi plati. Este recomandat să folosiţi o adresă nouă de primire pentru fiecare tranzacţie în parte. - - - Copy &Label - Copiază &eticheta - - - &Edit - &Editare - - - Export Address List - Exportă listă de adrese - - - Comma separated file (*.csv) - Fişier text cu valori separate prin virgulă (*.csv) - - - Exporting Failed - Export nereuşit - - - There was an error trying to save the address list to %1. Please try again. - A apărut o eroare la salvarea listei de adrese la %1. Vă rugăm să încercaţi din nou. - - - - AddressTableModel - - Label - Etichetă - - - Address - Adresă - - - (no label) - (fără etichetă) - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase Repetaţi noua frază de acces - - Encrypt wallet - Criptare portofel - - - This operation needs your wallet passphrase to unlock the wallet. - Această acţiune necesită fraza dvs. de acces pentru deblocarea portofelului. - - - Unlock wallet - Deblocare portofel - - - This operation needs your wallet passphrase to decrypt the wallet. - Această acţiune necesită fraza dvs. de acces pentru decriptarea portofelului. - - - Decrypt wallet - Decriptare portofel - - - Change passphrase - Schimbare frază de acces - - - Confirm wallet encryption - Confirmaţi criptarea portofelului - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Atenţie: Dacă pierdeţi parola portofelului electronic după criptare, <b>VEŢI PIERDE ÎNTREAGA SUMĂ DE BITCOIN ACUMULATĂ</b>! - - - Are you sure you wish to encrypt your wallet? - Sigur doriţi să criptaţi portofelul dvs.? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Bitcoin se va închide acum pentru a termina procesul de criptare. Ţineţi minte că criptarea portofelului nu vă poate proteja în totalitate de furtul monedelor de către programe dăunătoare care vă infectează calculatorul. - - - 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. - IMPORTANT: Orice copie de siguranţă făcută anterior portofelului dumneavoastră ar trebui înlocuită cu cea generată cel mai recent, fişier criptat al portofelului. Pentru siguranţă, copiile de siguranţă vechi ale portofelului ne-criptat vor deveni inutile imediat ce veţi începe folosirea noului fişier criptat al portofelului. - - - Warning: The Caps Lock key is on! - Atenţie! Caps Lock este pornit! - - - Wallet encrypted - Portofel criptat - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Introduceţi noua parolă a portofelului electronic.<br/>Vă rugăm să folosiţi o parolă de<b>minimum 10 caractere aleatoare</b>, sau <b>minimum 8 cuvinte</b>. - - - Enter the old passphrase and new passphrase to the wallet. - Introduceţi vechea şi noua parolă pentru portofel. - - - Wallet encryption failed - Criptarea portofelului nu a reuşit - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Criptarea portofelului nu a reuşit din cauza unei erori interne. Portofelul dvs. nu a fost criptat. - - - The supplied passphrases do not match. - Frazele de acces introduse nu se potrivesc. - - - Wallet unlock failed - Deblocarea portofelului nu a reuşit - - - The passphrase entered for the wallet decryption was incorrect. - Fraza de acces introdusă pentru decriptarea portofelului a fost incorectă. - - - Wallet decryption failed - Decriptarea portofelului nu a reuşit - - - Wallet passphrase was successfully changed. - Parola portofelului electronic a fost schimbată. - BanTableModel @@ -305,14 +146,6 @@ Open &URI... Deschide &URI... - - Bitcoin Core client - Clientul Bitcoin Core - - - Importing blocks from disk... - Import blocuri de pe disk... - Reindexing blocks on disk... Se reindexează blocurile pe disc... @@ -357,10 +190,6 @@ &Receive P&rimeşte - - Show information about Bitcoin Core - Arată informaţii despre Bitcoin Core - &Show / Hide Arată/Ascunde @@ -397,22 +226,10 @@ Tabs toolbar Bara de unelte - - Bitcoin Core - Nucleul Bitcoin - Request payments (generates QR codes and bitcoin: URIs) Cereţi plăţi (generează coduri QR şi bitcoin-uri: URls) - - &About Bitcoin Core - &Despre Nucleul Bitcoin - - - Modify configuration options for Bitcoin Core - Modifică opţiunile de configurare pentru Bitcoin - Show the list of used sending addresses and labels Arată lista de adrese trimise şi etichetele folosite. @@ -429,10 +246,6 @@ &Command-line options Opţiuni linie de &comandă - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Arată mesajul de ajutor Bitcoin Core pentru a obţine o listă cu opţiunile posibile de linii de comandă Bitcoin - %n active connection(s) to Bitcoin network %n conexiune activă către reţeaua Bitcoin%n conexiuni active către reţeaua Bitcoin%n de conexiuni active către reţeaua Bitcoin @@ -544,13 +357,6 @@ Portofelul este <b>criptat</b> iar în momentul de faţă este <b>blocat</b> - - ClientModel - - Network Alert - Alertă reţea - - CoinControlDialog @@ -629,150 +435,6 @@ Priority Prioritate - - Copy address - Copiază adresa - - - Copy label - Copiază eticheta - - - Copy amount - Copiază suma - - - Copy transaction ID - Copiază ID tranzacţie - - - Lock unspent - Blocare necheltuiţi - - - Unlock unspent - Deblocare necheltuiţi - - - Copy quantity - Copiază cantitea - - - Copy fee - Copiază taxa - - - Copy after fee - Copiază după taxă - - - Copy bytes - Copiază octeţi - - - Copy priority - Copiază prioritatea - - - Copy dust - Copiază praf - - - Copy change - Copiază rest - - - highest - cea mai mare - - - higher - mai mare - - - high - mare - - - medium-high - medie-mare - - - medium - medie - - - low-medium - medie-scăzută - - - low - scazută - - - lower - mai scăzută - - - lowest - cea mai scăzută - - - (%1 locked) - (%1 blocat) - - - none - nimic - - - This label turns red if the transaction size is greater than 1000 bytes. - Această etichetă devine roşie în cazul în care dimensiunea tranzacţiei este mai mare de 1000 de octeţi. - - - This label turns red if the priority is smaller than "medium". - Această etichetă devine roşie dacă prioritatea e mai mică decît "medie". - - - This label turns red if any recipient receives an amount smaller than %1. - Această etichetă devine roşie, dacă orice beneficiar primeşte o sumă mai mică decât %1. - - - Can vary +/- %1 satoshi(s) per input. - Poate varia +/- %1 satoshi pentru fiecare intrare. - - - yes - da - - - no - nu - - - This means a fee of at least %1 per kB is required. - Aceasta înseamnă o taxă de cel puţin %1 pe kB necesar. - - - Can vary +/- 1 byte per input. - Poate varia +/- 1 octet pentru fiecare intrare. - - - Transactions with higher priority are more likely to get included into a block. - Tranzacţiile cu prioritate mai mare sînt mai susceptibile de fi incluse într-un bloc. - - - (no label) - (fără etichetă) - - - change from %1 (%2) - restul de la %1 (%2) - - - (change) - (rest) - EditAddressDialog @@ -796,38 +458,6 @@ &Address &Adresă - - New receiving address - Noua adresă de primire - - - New sending address - Noua adresă de trimitere - - - Edit receiving address - Editează adresa de primire - - - Edit sending address - Editează adresa de trimitere - - - The entered address "%1" is already in the address book. - Adresa introdusă "%1" se află deja în lista de adrese. - - - The entered address "%1" is not a valid Bitcoin address. - Adresa introdusă "%1" nu este o adresă bitcoin validă. - - - Could not unlock wallet. - Portofelul nu a putut fi deblocat. - - - New key generation failed. - Generarea noii chei nu a reuşit. - FreespaceChecker @@ -854,10 +484,6 @@ HelpMessageDialog - - Bitcoin Core - Nucleul Bitcoin - version versiunea @@ -867,8 +493,8 @@ (%1-bit) - About Bitcoin Core - Despre Nucleul Bitcoin + About %1 + Despre %1 Command-line options @@ -906,29 +532,13 @@ Show splash screen on startup (default: %u) Afişează ecran splash la pornire (implicit: %u) - - Reset all settings changes made over the GUI - Resetează toate schimbările făcute în GUI - - + Intro Welcome Bun venit - - Welcome to Bitcoin Core. - Bine aţi venit la Nucleul Bitcoin. - - - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - Dacă aceasta este prima dată cînd programul este lansat, puteţi alege unde Nucleul Bitcoin va stoca datele. - - - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - Nucleul Bitcoin se va descărca şi va stoca o copie a lanţului blocului Bitcoin. Cel puţin %1GB de date vor fi stocate în acest dosar şi se va mări în timp. Portofelul va fi, de asemenea, stocat în acest dosar. - Use the default data directory Foloseşte dosarul de date implicit @@ -937,10 +547,6 @@ Use a custom data directory: Foloseşte un dosar de date personalizat: - - Bitcoin Core - Nucleul Bitcoin - Error: Specified data directory "%1" cannot be created. Eroare: Directorul datelor specificate "%1" nu poate fi creat. @@ -976,10 +582,6 @@ Select payment request file Selectaţi fişierul cerere de plată - - Select payment request file to open - Selectaţi fişierul cerere de plată pentru deschidere - OptionsDialog @@ -1019,10 +621,6 @@ 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. Minimizează fereastra în locul părăsirii programului în momentul închiderii ferestrei. Cînd acestă opţiune e activă, aplicaţia se va opri doar în momentul selectării comenzii 'Închide aplicaţia' din menu. - - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - Limba interfeţei utilizatorului poate fi setată aici. Această setare va avea efect după repornirea Nucleului Bitcoin. - 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 |. URL-uri terţe părţi (de exemplu, un explorator de bloc), care apar în tab-ul tranzacţiilor ca elemente de meniu contextual. %s în URL este înlocuit cu hash de tranzacţie. URL-urile multiple sînt separate prin bară verticală |. @@ -1047,14 +645,6 @@ &Network Reţea - - Automatically start Bitcoin Core after logging in to the system. - Porneşte automat Bitcoin Core după logarea în sistem. - - - &Start Bitcoin Core on system login - Porneşte Nucleul Bitcoin la pornirea sistemului - (0 = auto, <0 = leave that many cores free) (0 = automat, <0 = lasă atîtea nuclee libere) @@ -1268,190 +858,80 @@ - PaymentServer + PeerTableModel - URI handling - Gestionare URI + User Agent + Agent utilizator - Invalid payment address %1 - Adresă pentru plată nevalidă %1 + Node/Service + Nod/Serviciu - Payment request rejected - Cerere de plată refuzată + Ping Time + Timp ping + + + QObject - Payment request network doesn't match client network. - Cererea de plată din reţea nu se potriveşte cu clientul din reţea + Amount + Cantitate - Payment request is not initialized. - Cererea de plată nu este iniţializată. + Enter a Bitcoin address (e.g. %1) + Introduceţi o adresă Bitcoin (de exemplu %1) - Requested payment amount of %1 is too small (considered dust). - Suma cerută de plată de %1 este prea mică (considerată praf). + %1 d + %1 z - Payment request error - Eroare la cererea de plată + %1 h + %1 h - Cannot start bitcoin: click-to-pay handler - Nu poate porni bitcoin: manipulator clic-pentru-plată + %1 m + %1 m - Payment request fetch URL is invalid: %1 - URL-ul cererii de plată preluat nu este valid: %1 + %1 s + %1 s - URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - URI nu poate fi analizat! Acest lucru poate fi cauzat de o adresă Bitcoin nevalidă sau parametri URI deformaţi. + None + Niciuna - Payment request file handling - Manipulare fişier cerere de plată + N/A + N/A - Payment request file cannot be read! This can be caused by an invalid payment request file. - Fişierul cerere de plată nu poate fi citit! Cauza poate fi un fişier cerere de plată nevalid. + %1 ms + %1 ms + + + RPCConsole - Payment request expired. - Cererea de plată a expirat. + Client name + Nume client - Unverified payment requests to custom payment scripts are unsupported. - Cererile de plată neverificate prin script-uri personalizate de plată nu sînt suportate. + N/A + indisponibil - Invalid payment request. - Cerere de plată nevalidă. + Client version + Versiune client - Refund from %1 - Rambursare de la %1 + &Information + &Informaţii - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - Cererea de plată %1 este prea mare (%2 octeţi, permis %3 octeţi). - - - Error communicating with %1: %2 - Eroare la comunicarea cu %1: %2 - - - Payment request cannot be parsed! - Cererea de plată nu poate fi analizată! - - - Bad response from server %1 - Răspuns greşit de la server %1 - - - Payment acknowledged - Plată acceptată - - - Network request error - Eroare în cererea de reţea - - - - PeerTableModel - - User Agent - Agent utilizator - - - Node/Service - Nod/Serviciu - - - Ping Time - Timp ping - - - - QObject - - Amount - Cantitate - - - Enter a Bitcoin address (e.g. %1) - Introduceţi o adresă Bitcoin (de exemplu %1) - - - %1 d - %1 z - - - %1 h - %1 h - - - %1 m - %1 m - - - %1 s - %1 s - - - None - Niciuna - - - N/A - N/A - - - %1 ms - %1 ms - - - - QRImageWidget - - &Save Image... - &Salvează imagine... - - - &Copy Image - &Copiază imaginea - - - Save QR Code - Salvează codul QR - - - PNG Image (*.png) - Imagine de tip PNG (*.png) - - - - RPCConsole - - Client name - Nume client - - - N/A - indisponibil - - - Client version - Versiune client - - - &Information - &Informaţii - - - Debug window - Fereastra de depanare + Debug window + Fereastra de depanare General @@ -1589,10 +1069,6 @@ Out: Ieşire: - - Build date - Construit la data - Debug log file Fişier jurnal depanare @@ -1621,10 +1097,6 @@ 1 &year 1 &an - - Welcome to the Bitcoin Core RPC console. - Bun venit la consola Nucleului Bitcoin RPC. - Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. Folosiţi săgetile sus şi jos pentru a naviga în istoric şi <b>Ctrl-L</b> pentru a curăţa. @@ -1748,18 +1220,6 @@ Remove Înlătură - - Copy label - Copiază eticheta - - - Copy message - Copiază mesajul - - - Copy amount - Copiază suma - ReceiveRequestDialog @@ -1779,73 +1239,6 @@ &Save Image... &Salvează imaginea... - - Request payment to %1 - Cere plata pentru %1 - - - Payment information - Informaţiile plăţii - - - URI - URI - - - Address - Adresă - - - Amount - Sumă - - - Label - Etichetă - - - Message - Mesaj - - - Resulting URI too long, try to reduce the text for label / message. - URI rezultat este prea lung, încearcaţi să reduceţi textul pentru etichetă / mesaj. - - - Error encoding URI into QR Code. - Eroare la codarea URl-ului în cod QR. - - - - RecentRequestsTableModel - - Date - Data - - - Label - Etichetă - - - Message - Mesaj - - - Amount - Sumă - - - (no label) - (fără etichetă) - - - (no message) - (nici un mesaj) - - - (no amount) - (sumă nulă) - SendCoinsDialog @@ -1945,14 +1338,6 @@ fast rapid - - Send as zero-fee transaction if possible - Trimite ca taxă zero dacă este posibil - - - (confirmation may take longer) - (confirmarea poate dura mai mult) - Send to multiple recipients at once Trimite simultan către mai mulţi destinatari @@ -1985,106 +1370,6 @@ S&end Trimit&e - - Confirm send coins - Confirmă trimiterea de monede - - - %1 to %2 - %1 la %2 - - - Copy quantity - Copiază cantitea - - - Copy amount - Copiază suma - - - Copy fee - Copiază taxa - - - Copy after fee - Copiază după taxă - - - Copy bytes - Copiază octeţi - - - Copy priority - Copiază prioritatea - - - Copy change - Copiază rest - - - Total Amount %1 - Suma totală %1 - - - or - sau - - - The amount to pay must be larger than 0. - Suma de plată trebuie să fie mai mare decît 0. - - - The amount exceeds your balance. - Suma depăşeşte soldul contului. - - - The total exceeds your balance when the %1 transaction fee is included. - Totalul depăşeşte soldul contului dacă se include şi plata taxei de %1. - - - Transaction creation failed! - Creare tranzacţie nereuşită! - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - Tranzacţia a fost respinsă! Acest lucru se poate întîmpla dacă o parte din monedele tale din portofel au fost deja cheltuite, la fel ca şi cum aţi fi folosit o copie a wallet.dat şi monedele au fost cheltuite în copie, dar nu au fost marcate ca şi cheltuite şi aici. - - - Payment request expired. - Cererea de plată a expirat. - - - The recipient address is not valid. Please recheck. - Adresa destinatarului nu este validă, vă rugăm să o verificaţi. - - - Duplicate address found: addresses should only be used once each. - Adresă duplicat găsită: fiecare adresă ar trebui folosită o singură dată. - - - Warning: Invalid Bitcoin address - Atenţie: Adresa bitcoin nevalidă! - - - (no label) - (fără etichetă) - - - Warning: Unknown change address - Atenţie: Adresă de rest necunoscută - - - Copy dust - Copiază praf - - - Are you sure you want to send? - Sigur doriţi să trimiteţi? - - - added as transaction fee - adăugat ca taxă de tranzacţie - SendCoinsEntry @@ -2096,10 +1381,6 @@ Pay &To: Plăteşte că&tre: - - Enter a label for this address to add it to your address book - Introduceţi o etichetă pentru această adresă pentru a fi adăugată în lista dvs. de adrese - &Label: &Etichetă: @@ -2156,8 +1437,8 @@ ShutdownWindow - Bitcoin Core is shutting down... - Nucleul Bitcoin se închide... + %1 is shutting down... + %1 se închide Do not shut down the computer until this window disappears. @@ -2242,586 +1523,80 @@ Reset all verify message fields Resetează toate cîmpurile mesajelor semnate + + + SplashScreen - Click "Sign Message" to generate signature - Faceţi clic pe "Semneaza msaj" pentru a genera semnătura + [testnet] + [testnet] + + + TrafficGraphWidget - The entered address is invalid. - Adresa introdusă nu este validă + KB/s + KB/s + + + TransactionDescDialog - Please check the address and try again. - Vă rugăm verificaţi adresa şi încercaţi din nou. + This pane shows a detailed description of the transaction + Acest panou arată o descriere detaliată a tranzacţiei + + + UnitDisplayStatusBarControl - The entered address does not refer to a key. - Adresa introdusă nu se referă la o cheie. + Unit to show amounts in. Click to select another unit. + Unitatea în care sînt arătate sumele. Faceţi clic pentru a selecta o altă unitate. + + + bitcoin-core - Wallet unlock was cancelled. - Blocarea portofelului a fost întreruptă. + Options: + Opţiuni: - Private key for the entered address is not available. - Cheia privată pentru adresa introdusă nu este validă. + Specify data directory + Specificaţi dosarul de date - Message signing failed. - Semnarea mesajului nu a reuşit. + Connect to a node to retrieve peer addresses, and disconnect + Se conectează la un nod pentru a obţine adresele partenerilor, şi apoi se deconectează - Message signed. - Mesaj semnat. + Specify your own public address + Specificaţi adresa dvs. publică - The signature could not be decoded. - Această semnatură nu a putut fi decodată. + Accept command line and JSON-RPC commands + Acceptă comenzi din linia de comandă şi comenzi JSON-RPC - Please check the signature and try again. - Vă rugăm verificaţi semnătura şi încercaţi din nou. + Run in the background as a daemon and accept commands + Rulează în fundal ca un demon şi acceptă comenzi - The signature did not match the message digest. - Semnatura nu se potriveşte cu mesajul. + Accept connections from outside (default: 1 if no -proxy or -connect) + Acceptă conexiuni din afară (implicit: 1 dacă nu se foloseşte -proxy sau -connect) - Message verification failed. - Verificarea mesajului nu a reuşit. + Bitcoin Core + Nucleul Bitcoin - Message verified. - Mesaj verificat. + Bind to given address and always listen on it. Use [host]:port notation for IPv6 + Ataşaţi adresei date şi ascultaţi totdeauna pe ea. Folosiţi notaţia [host]:port pentru IPv6 - - - SplashScreen - Bitcoin Core - Nucleul Bitcoin + Distributed under the MIT software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>. + Distribuit sub licenţa de programe MIT/X11, vezi fişierul însoţitor COPYING sau <http://www.opensource.org/licenses/mit-license.php>. - The Bitcoin Core developers - Dezvoltatorii Nucleului Bitcoin - - - [testnet] - [testnet] - - - - TrafficGraphWidget - - KB/s - KB/s - - - - TransactionDesc - - Open until %1 - Deschis pînă la %1 - - - conflicted - în conflict - - - %1/offline - %1/deconectat - - - %1/unconfirmed - %1/neconfirmat - - - %1 confirmations - %1 confirmări - - - Status - Stare - - - , broadcast through %n node(s) - , distribuit prin %n nod, distribuit prin %n noduri, distribuit prin %n de noduri - - - Date - Data - - - Source - Sursa - - - Generated - Generat - - - From - De la - - - To - Către - - - own address - adresa proprie - - - watch-only - doar-supraveghere - - - label - etichetă - - - Credit - Credit - - - matures in %n more block(s) - se maturizează în încă %n blocse maturizează în încă %n blocurise maturizează în încă %n de blocuri - - - not accepted - neacceptat - - - Debit - Debit - - - Total debit - Total debit - - - Total credit - Total credit - - - Transaction fee - Taxă tranzacţie - - - Net amount - Suma netă - - - Message - Mesaj - - - Comment - Comentariu - - - Transaction ID - ID-ul tranzacţie - - - Merchant - Comerciant - - - 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. - Monedele generate trebuie să crească %1 blocuri înainte să poată fi cheltuite. Cînd aţi generat acest bloc, a fost transmis reţelei pentru a fi adaugat la lanţul de blocuri. Aceasta se poate întîmpla ocazional dacă alt nod generează un bloc la numai cîteva secunde de al dvs. - - - Debug information - Informaţii pentru depanare - - - Transaction - Tranzacţie - - - Inputs - Intrări - - - Amount - Sumă - - - true - adevărat - - - false - fals - - - , has not been successfully broadcast yet - , nu s-a propagat încă - - - Open for %n more block(s) - Deschis pentru încă %n blocDeschis pentru încă %n blocuriDeschis pentru încă %n de blocuri - - - unknown - necunoscut - - - - TransactionDescDialog - - Transaction details - Detaliile tranzacţiei - - - This pane shows a detailed description of the transaction - Acest panou arată o descriere detaliată a tranzacţiei - - - - TransactionTableModel - - Date - Data - - - Type - Tip - - - Immature (%1 confirmations, will be available after %2) - Imatur (%1 confirmări, va fi disponibil după %2) - - - Open for %n more block(s) - Deschis pentru încă %n blocDeschis pentru încă %n blocuriDeschis pentru încă %n de blocuri - - - Open until %1 - Deschis până la %1 - - - Confirmed (%1 confirmations) - Confirmat (%1 confirmări) - - - This block was not received by any other nodes and will probably not be accepted! - Acest bloc nu a fost recepţionat de nici un alt nod şi probabil nu va fi acceptat! - - - Generated but not accepted - Generat dar neacceptat - - - Offline - Deconectat - - - Label - Etichetă - - - Unconfirmed - Neconfirmat - - - Confirming (%1 of %2 recommended confirmations) - Confirmare (%1 din %2 confirmări recomandate) - - - Conflicted - În conflict - - - Received with - Recepţionat cu - - - Received from - Primit de la - - - Sent to - Trimis către - - - Payment to yourself - Plată către dvs. - - - Mined - Minerit - - - watch-only - doar-supraveghere - - - (n/a) - indisponibil - - - Transaction status. Hover over this field to show number of confirmations. - Starea tranzacţiei. Treceţi cu mouse-ul peste acest cîmp pentru afişarea numărului de confirmări. - - - Date and time that the transaction was received. - Data şi ora la care a fost recepţionată tranzacţia. - - - Type of transaction. - Tipul tranzacţiei. - - - Whether or not a watch-only address is involved in this transaction. - Indiferent dacă sau nu o adresă doar-suăpraveghere este implicată în această tranzacţie. - - - Amount removed from or added to balance. - Suma extrasă sau adăugată la sold. - - - - TransactionView - - All - Toate - - - Today - Astăzi - - - This week - Săptămîna aceasta - - - This month - Luna aceasta - - - Last month - Luna trecută - - - This year - Anul acesta - - - Range... - Interval... - - - Received with - Recepţionat cu - - - Sent to - Trimis către - - - To yourself - Către dvs. - - - Mined - Minerit - - - Other - Altele - - - Enter address or label to search - Introduceţi adresa sau eticheta pentru căutare - - - Min amount - Suma minimă - - - Copy address - Copiază adresa - - - Copy label - Copiază eticheta - - - Copy amount - Copiază suma - - - Copy transaction ID - Copiază ID tranzacţie - - - Edit label - Editează eticheta - - - Show transaction details - Arată detaliile tranzacţiei - - - Export Transaction History - Export istoric tranzacţii - - - Watch-only - Doar-supraveghere - - - Exporting Failed - Export nereuşit - - - There was an error trying to save the transaction history to %1. - S-a produs o eroare la salvarea istoricului tranzacţiilor la %1. - - - Exporting Successful - Export reuşit - - - The transaction history was successfully saved to %1. - Istoricul tranzacţiilor a fost salvat cu succes la %1. - - - Comma separated file (*.csv) - Fişier text cu valori separate prin virgulă (*.csv) - - - Confirmed - Confirmat - - - Date - Data - - - Type - Tip - - - Label - Etichetă - - - Address - Adresă - - - ID - ID - - - Range: - Interval: - - - to - către - - - - UnitDisplayStatusBarControl - - Unit to show amounts in. Click to select another unit. - Unitatea în care sînt arătate sumele. Faceţi clic pentru a selecta o altă unitate. - - - - WalletFrame - - No wallet has been loaded. - Nu a fost încărcat nici un portofel. - - - - WalletModel - - Send Coins - Trimitere bitcoin - - - - WalletView - - &Export - &Export - - - Export the data in the current tab to a file - Exportă datele din tab-ul curent într-un fişier - - - Backup Wallet - Copie de siguranţă portofel - - - Wallet Data (*.dat) - Date portofel (*.dat) - - - Backup Failed - Copierea de siguranţă nu a reuşit - - - There was an error trying to save the wallet data to %1. - S-a produs o eroare la salvarea datelor portofelului la %1. - - - The wallet data was successfully saved to %1. - Datele portofelului s-au salvat cu succes la %1. - - - Backup Successful - Copie de siguranţă efectuată cu succes - - - - bitcoin-core - - Options: - Opţiuni: - - - Specify data directory - Specificaţi dosarul de date - - - Connect to a node to retrieve peer addresses, and disconnect - Se conectează la un nod pentru a obţine adresele partenerilor, şi apoi se deconectează - - - Specify your own public address - Specificaţi adresa dvs. publică - - - Accept command line and JSON-RPC commands - Acceptă comenzi din linia de comandă şi comenzi JSON-RPC - - - Run in the background as a daemon and accept commands - Rulează în fundal ca un demon şi acceptă comenzi - - - Accept connections from outside (default: 1 if no -proxy or -connect) - Acceptă conexiuni din afară (implicit: 1 dacă nu se foloseşte -proxy sau -connect) - - - Bind to given address and always listen on it. Use [host]:port notation for IPv6 - Ataşaţi adresei date şi ascultaţi totdeauna pe ea. Folosiţi notaţia [host]:port pentru IPv6 - - - Distributed under the MIT software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>. - Distribuit sub licenţa de programe MIT/X11, vezi fişierul însoţitor COPYING sau <http://www.opensource.org/licenses/mit-license.php>. - - - Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) - Execută comanda cînd o tranzacţie a portofelului se schimbă (%s în cmd este înlocuit de TxID) + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + Execută comanda cînd o tranzacţie a portofelului se schimbă (%s în cmd este înlocuit de TxID) Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) @@ -2831,10 +1606,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Aceasta este o versiune de test preliminară - vă asumaţi riscul folosind-o - nu folosiţi pentru minerit sau aplicaţiile comercianţilor - - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - Nu se poate lega la %s pe acest calculator. Nucleul Bitcoin probabil deja rulează. - Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Atenţie: Reţeaua nu pare să fie de acord în totalitate! Aparent nişte mineri au probleme. @@ -2843,10 +1614,6 @@ Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Atenţie: Aparent, nu sîntem de acord cu toţi partenerii noştri! Va trebui să faceţi o actualizare, sau alte noduri necesită actualizare. - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Atenţie: fişierul wallet.dat este corupt, date salvate! Fişierul original wallet.dat a fost salvat ca wallet.{timestamp}.bak in %s; dacă balansul sau tranzactiile sînt incorecte ar trebui să restauraţi dintr-o copie de siguranţă. - <category> can be: <category> poate fi: @@ -2955,18 +1722,10 @@ Wallet options: Opţiuni portofel: - - You need to rebuild the database using -reindex to change -txindex - Trebuie să reconstruiţi baza de date folosind -reindex pentru a schimba -txindex - 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 Permite conexiunile JSON-RPC din sursa specificată. Valid pentru <ip> sînt IP singulare (ex. 1.2.3.4), o reţea/mască-reţea (ex. 1.2.3.4/255.255.255.0) sau o reţea/CIDR (ex. 1.2.3.4/24). Această opţiune poate fi specificată de mai multe ori - - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - Nu se poate obţine blocarea folderului cu date %s. Nucleul Bitcoin probabil deja rulează. - Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message) Execută comanda cînd o alertă relevantă este primită sau vedem o bifurcaţie foarte lungă (%s în cmd este înlocuit de mesaj) @@ -2988,17 +1747,13 @@ Acceptă cererile publice REST (implicit: %u) - Cannot resolve -whitebind address: '%s' - Nu se poate rezolva adresa -whitebind: '%s' + Automatically create Tor hidden service (default: %d) + Crează automat un serviciu Tor ascuns (implicit: %d) Connect through SOCKS5 proxy Conectare prin proxy SOCKS5 - - Copyright (C) 2009-%i The Bitcoin Core Developers - Copyright (C) 2009-%i Dezvoltatorii Bitcoin - Error reading from database, shutting down. Eroare la citirea bazei de date. Oprire. @@ -3007,22 +1762,6 @@ Information Informaţie - - Initialization sanity check failed. Bitcoin Core is shutting down. - Nu s-a reuşit iniţierea verificării sănătăţii. Nucleul Bitcoin se opreşte. - - - Invalid amount for -maxtxfee=<amount>: '%s' - Sumă nevalidă pentru -maxtxfee=<suma>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Sumă nevalidă pentru -minrelaytxfee=<suma>:'%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - Sumă nevalidă pentru -mintxfee=<suma>: '%s' - Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) Sumă nevalidă pentru -paytxfee=<suma>: '%s' (trebuie să fie cel puţin %s) @@ -3087,10 +1826,6 @@ Username for JSON-RPC connections Utilizator pentru conexiunile JSON-RPC - - Wallet needed to be rewritten: restart Bitcoin Core to complete - Portofelul necesită rescrierea: reporniţi Nucleul Bitcoin pentru completare - Warning Avertisment @@ -3099,10 +1834,6 @@ Zapping all transactions from wallet... Şterge toate tranzacţiile din portofel... - - wallet.dat corrupt, salvage failed - wallet.dat corupt, salvare nereuşită - Password for JSON-RPC connections Parola pentru conexiunile JSON-RPC @@ -3111,10 +1842,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) Execută comanda cînd cel mai bun bloc se modifică (%s în cmd este înlocuit cu hash-ul blocului) - - This help message - Acest mesaj de ajutor - Allow DNS lookups for -addnode, -seednode and -connect Permite căutări DNS pentru -addnode, -seednode şi -connect @@ -3123,10 +1850,6 @@ Loading addresses... Încărcare adrese... - - Error loading wallet.dat: Wallet corrupted - Eroare la încărcarea wallet.dat: Portofel corupt - Output debugging information (default: %u, supplying <category> is optional) Produce toate informaţiile de depanare (implicit: %u <category> furnizată este opţională) @@ -3135,14 +1858,6 @@ (default: %s) (implicit: %s) - - Error loading wallet.dat - Eroare la încărcarea wallet.dat - - - Generate coins (default: %u) - Generează monede (implicit: %u) - How many blocks to check at startup (default: %u, 0 = all) Cîte blocuri verifică la pornire (implicit: %u, 0 = toate) @@ -3167,18 +1882,6 @@ Unknown network specified in -onlynet: '%s' Reţeaua specificată în -onlynet este necunoscută: '%s' - - Cannot resolve -bind address: '%s' - Nu se poate rezolva adresa -bind: '%s' - - - Cannot resolve -externalip address: '%s' - Nu se poate rezolva adresa -externalip: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - Suma nevalidă pentru -paytxfee=<amount>: '%s' - Insufficient funds Fonduri insuficiente diff --git a/src/qt/locale/bitcoin_ru.ts b/src/qt/locale/bitcoin_ru.ts index b4546a21578f4..e2949a9482539 100644 --- a/src/qt/locale/bitcoin_ru.ts +++ b/src/qt/locale/bitcoin_ru.ts @@ -25,10 +25,6 @@ C&lose &Закрыть - - &Copy Address - &Копировать адрес - Delete the currently selected address from the list Удалить выбранный адрес из списка @@ -45,73 +41,6 @@ &Delete &Удалить - - Choose the address to send coins to - Выберите адрес для отправки на него монет - - - Choose the address to receive coins with - Выберите адрес для получения монет - - - C&hoose - &Выбрать - - - Sending addresses - Адреса отправки - - - Receiving addresses - Адреса получения - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Это ваши адреса Bitcoin для отправки платежей. Всегда проверяйте количество и адрес получателя перед отправкой перевода. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Это ваши адреса Bitcoin для приёма платежей. Рекомендуется использовать новый адрес получения для каждой транзакции. - - - Copy &Label - Копировать &метку - - - &Edit - &Правка - - - Export Address List - Экспортировать список адресов - - - Comma separated file (*.csv) - Текст, разделённый запятыми (*.csv) - - - Exporting Failed - Экспорт не удался - - - There was an error trying to save the address list to %1. Please try again. - Произошла ошибка при попытке сохранить список адресов, %1. Пожалуйста, попробуйте еще раз. - - - - AddressTableModel - - Label - Метка - - - Address - Адрес - - - (no label) - [нет метки] - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase Повторите новый пароль - - Encrypt wallet - Зашифровать бумажник - - - This operation needs your wallet passphrase to unlock the wallet. - Для выполнения операции требуется пароль вашего бумажника. - - - Unlock wallet - Разблокировать бумажник - - - This operation needs your wallet passphrase to decrypt the wallet. - Для выполнения операции требуется пароль вашего бумажника. - - - Decrypt wallet - Расшифровать бумажник - - - Change passphrase - Сменить пароль - - - Confirm wallet encryption - Подтвердите шифрование бумажника - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Внимание: если вы зашифруете бумажник и потеряете пароль, вы <b>ПОТЕРЯЕТЕ ВСЕ ВАШИ БИТКОЙНЫ</b>! - - - Are you sure you wish to encrypt your wallet? - Вы уверены, что хотите зашифровать ваш бумажник? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Сейчас программа закроется для завершения процесса шифрования. Помните, что шифрование вашего бумажника не может полностью защитить ваши биткоины от кражи с помощью инфицирования вашего компьютера вредоносным ПО. - - - 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. - ВАЖНО: все предыдущие резервные копии вашего бумажника должны быть заменены новым зашифрованным файлом. В целях безопасности предыдущие резервные копии незашифрованного бумажника станут бесполезны, как только вы начнёте использовать новый зашифрованный бумажник. - - - Warning: The Caps Lock key is on! - Внимание: Caps Lock включен! - - - Wallet encrypted - Бумажник зашифрован - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Введите новый пароль бумажника.<br/>Используйте пароль, состоящий из <b>десяти или более случайных символов</b>, или <b>восьми или более слов</b>. - - - Enter the old passphrase and new passphrase to the wallet. - Введите старый и новый пароль для кошелька. - - - Wallet encryption failed - Не удалось зашифровать бумажник - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Шифрование бумажника не удалось из-за внутренней ошибки. Ваш бумажник не был зашифрован. - - - The supplied passphrases do not match. - Введённые пароли не совпадают. - - - Wallet unlock failed - Разблокировка бумажника не удалась - - - The passphrase entered for the wallet decryption was incorrect. - Указанный пароль не подходит. - - - Wallet decryption failed - Расшифрование бумажника не удалось - - - Wallet passphrase was successfully changed. - Пароль бумажника успешно изменён. - BanTableModel @@ -269,6 +110,14 @@ Quit application Закрыть приложение + + &About %1 + &О %1 + + + Show information about %1 + Показать информацию о %1 + About &Qt О &Qt @@ -305,14 +154,6 @@ Open &URI... Открыть &URI... - - Bitcoin Core client - Bitcoin Core клиент - - - Importing blocks from disk... - Импортируются блоки с диска... - Reindexing blocks on disk... Идёт переиндексация блоков на диске... @@ -357,10 +198,6 @@ &Receive &Получить - - Show information about Bitcoin Core - Показать информацию о Bitcoin Core - &Show / Hide &Показать / Скрыть @@ -397,22 +234,10 @@ Tabs toolbar Панель вкладок - - Bitcoin Core - Bitcoin Core - Request payments (generates QR codes and bitcoin: URIs) Запросить платежи (создаёт QR-коды и bitcoin: ссылки) - - &About Bitcoin Core - &О Bitcoin Core - - - Modify configuration options for Bitcoin Core - Изменить опции конфигурации Bitcoin Core - Show the list of used sending addresses and labels Показать список использованных адресов и меток отправки @@ -429,14 +254,18 @@ &Command-line options &Параметры командной строки - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Показать помощь по Bitcoin Core и получить список доступных параметров командной строки. - %n active connection(s) to Bitcoin network %n активных соединений с сетью Bitcoin%n активных соединений с сетью Bitcoin%n активных соединений с сетью Bitcoin%n активных соединений с сетью Bitcoin + + Indexing blocks on disk... + Индексация блоков на диске... + + + Processing blocks on disk... + Обработка блоков на диске... + No block source available... Источник блоков недоступен... @@ -493,6 +322,10 @@ Up to date Синхронизировано + + %1 client + %1 клиент + Catching up... Синхронизируется... @@ -544,13 +377,6 @@ Бумажник <b>зашифрован</b> и в настоящее время <b>заблокирован</b> - - ClientModel - - Network Alert - Сетевая Тревога - - CoinControlDialog @@ -629,150 +455,6 @@ Priority Приоритет - - Copy address - Копировать адрес - - - Copy label - Копировать метку - - - Copy amount - Скопировать сумму - - - Copy transaction ID - Скопировать ID транзакции - - - Lock unspent - Заблокировать непотраченное - - - Unlock unspent - Разблокировать непотраченное - - - Copy quantity - Копировать количество - - - Copy fee - Копировать комиссию - - - Copy after fee - Копировать после комиссии - - - Copy bytes - Копировать байты - - - Copy priority - Копировать приоритет - - - Copy dust - Копировать пыль - - - Copy change - Копировать сдачу - - - highest - самый высокий - - - higher - выше - - - high - высокий - - - medium-high - выше среднего - - - medium - средний - - - low-medium - ниже среднего - - - low - низкий - - - lower - ниже - - - lowest - самый низкий - - - (%1 locked) - (%1 заблокировано) - - - none - ничего - - - This label turns red if the transaction size is greater than 1000 bytes. - Эта метка становится красной, если размер транзакции будет больше, чем 1000 байт. - - - This label turns red if the priority is smaller than "medium". - Эта метка становится красной, если приоритет меньше, чем "среднее". - - - This label turns red if any recipient receives an amount smaller than %1. - Эта метка становится красной, если любой из получателей принимает количество меньше, чем %1. - - - Can vary +/- %1 satoshi(s) per input. - Может отличаться на +/- %1 сатоши на вход. - - - yes - да - - - no - нет - - - This means a fee of at least %1 per kB is required. - Это значит, что требуется комиссия как минимум %1 на КБ. - - - Can vary +/- 1 byte per input. - Может отличаться на +/- 1 байт на вход. - - - Transactions with higher priority are more likely to get included into a block. - Транзакции с более высоким приоритетом будут вероятнее других включены в блок. - - - (no label) - [нет метки] - - - change from %1 (%2) - сдача с %1 (%2) - - - (change) - (размен) - EditAddressDialog @@ -796,38 +478,6 @@ &Address &Адрес - - New receiving address - Новый адрес для получения - - - New sending address - Новый адрес для отправки - - - Edit receiving address - Изменение адреса для получения - - - Edit sending address - Изменение адреса для отправки - - - The entered address "%1" is already in the address book. - Введённый адрес «%1» уже находится в адресной книге. - - - The entered address "%1" is not a valid Bitcoin address. - Введённый адрес "%1" не является правильным Bitcoin-адресом. - - - Could not unlock wallet. - Не удается разблокировать бумажник. - - - New key generation failed. - Генерация нового ключа не удалась. - FreespaceChecker @@ -854,10 +504,6 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin Core - version версия @@ -867,8 +513,8 @@ (%1-бит) - About Bitcoin Core - О Bitcoin Core + About %1 + О %1 Command-line options @@ -906,11 +552,7 @@ Show splash screen on startup (default: %u) Показывать экран-заставку при запуске (по умолчанию: %u) - - Reset all settings changes made over the GUI - Сбросить все настройки сделанные через графический интерфейс - - + Intro @@ -918,16 +560,8 @@ Добро пожаловать - Welcome to Bitcoin Core. - Добро пожаловать в Bitcoin Core. - - - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - Так как вы впервые запустили программу, вы можете выбрать, где Bitcoin Core будет хранить данные. - - - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - Bitcoin Core скачает и сохранит копию цепи блоков. Как минимум, %1ГБ данных будет храниться в этом каталоге, и со временем он будет расти. Бумажник будет также сохранён в этом каталоге. + Welcome to %1. + Добро пожаловать в %1 Use the default data directory @@ -937,10 +571,6 @@ Use a custom data directory: Использовать другой каталог данных: - - Bitcoin Core - Bitcoin Core - Error: Specified data directory "%1" cannot be created. Ошибка: не удалось создать указанный каталог данных "%1". @@ -976,10 +606,6 @@ Select payment request file Выбрать файл запроса платежа - - Select payment request file to open - Выберите файл запроса платежа - OptionsDialog @@ -1019,10 +645,6 @@ 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. Сворачивать вместо закрытия. Если данная опция будет выбрана — приложение закроется только после выбора соответствующего пункта в меню. - - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - Здесь можно выбрать язык интерфейса. Настройки вступят в силу после перезапуска Bitcoin Core. - 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 |. Сторонние URL (например, block explorer), которые отображаются на вкладке транзакций как пункты контекстного меню. %s в URL заменяется хэшем транзакции. URL отделяются друг от друга вертикальной чертой |. @@ -1047,14 +669,6 @@ &Network &Сеть - - Automatically start Bitcoin Core after logging in to the system. - Автоматически запускать Bitcoin Core после входа в систему - - - &Start Bitcoin Core on system login - &Запускать Bitcoin Core при входе в систему - (0 = auto, <0 = leave that many cores free) (0 = автоматически, <0 = оставить столько незагруженных ядер) @@ -1139,6 +753,10 @@ &Window &Окно + + Hide tray icon + Скрыть иконку в трее + Show only a tray icon after minimizing the window. Показывать только иконку в системном лотке после сворачивания окна. @@ -1284,171 +902,61 @@ - PaymentServer + PeerTableModel - URI handling - Обработка URI + User Agent + Юзер-агент - Invalid payment address %1 - Неверный адрес платежа %1 + Node/Service + Узел/сервис - Payment request rejected - Запрос платежа отклонён + Ping Time + Время задержки + + + QObject - Payment request network doesn't match client network. - Сеть запроса платежа не совпадает с сетью клиента. + Amount + Сумма - Payment request is not initialized. - Запрос платежа не инициализирован. + Enter a Bitcoin address (e.g. %1) + Введите адрес Bitcoin (например, %1) - Requested payment amount of %1 is too small (considered dust). - Запрошенная сумма платежа %1 слишком мала (считается пылью). + %1 d + %1 д - Payment request error - Ошибка запроса платежа + %1 h + %1 ч - Cannot start bitcoin: click-to-pay handler - Не удаётся запустить bitcoin: обработчик click-to-pay + %1 m + %1 мин - Payment request fetch URL is invalid: %1 - Неверный URL запроса платежа: %1 + %1 s + %1 с - URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - Не удалось обработать URI! Это может быть связано с неверным адресом Bitcoin или неправильными параметрами URI. + None + Ничего - Payment request file handling - Обработка файла запроса платежа + N/A + Н/Д - Payment request file cannot be read! This can be caused by an invalid payment request file. - Файл запроса платежа не может быть прочитан! Обычно это происходит из-за неверного файла запроса платежа. + %1 ms + %1 мс - - Payment request expired. - Запрос платежа просрочен. - - - Unverified payment requests to custom payment scripts are unsupported. - Непроверенные запросы платежей с нестандартными платёжными сценариями не поддерживаются. - - - Invalid payment request. - Неверный запрос платежа. - - - Refund from %1 - Возврат от %1 - - - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - Запрос платежа %1 слишком большой (%2 байтов, разрешено %3 байтов). - - - Error communicating with %1: %2 - Ошибка связи с %1: %2 - - - Payment request cannot be parsed! - Запрос платежа не может быть разобран! - - - Bad response from server %1 - Плохой ответ от сервера %1 - - - Payment acknowledged - Платёж принят - - - Network request error - Ошибка сетевого запроса - - - - PeerTableModel - - User Agent - Юзер-агент - - - Node/Service - Узел/сервис - - - Ping Time - Время задержки - - - - QObject - - Amount - Сумма - - - Enter a Bitcoin address (e.g. %1) - Введите адрес Bitcoin (например, %1) - - - %1 d - %1 д - - - %1 h - %1 ч - - - %1 m - %1 мин - - - %1 s - %1 с - - - None - Ничего - - - N/A - Н/Д - - - %1 ms - %1 мс - - - - QRImageWidget - - &Save Image... - &Сохранить изображение... - - - &Copy Image - &Копировать изображение - - - Save QR Code - Сохранить QR-код - - - PNG Image (*.png) - Изображение PNG (*.png) - - - - RPCConsole + + + RPCConsole Client name Имя клиента @@ -1513,10 +1021,6 @@ Memory usage Использование памяти - - Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. - Открыть отладочный лог-файл Bitcoin Core из текущего каталога данных. Это может занять несколько секунд для больших лог-файлов. - Received Получено @@ -1633,10 +1137,6 @@ Out: Выход: - - Build date - Дата сборки - Debug log file Отладочный лог-файл @@ -1673,10 +1173,6 @@ &Unban Node &Разблокировать узел - - Welcome to the Bitcoin Core RPC console. - Добро пожаловать в RPC-консоль Bitcoin Core. - Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. Используйте стрелки вверх и вниз для просмотра истории и <b>Ctrl-L</b> для очистки экрана. @@ -1804,18 +1300,6 @@ Remove Удалить - - Copy label - Копировать метку - - - Copy message - Копировать сообщение - - - Copy amount - Скопировать сумму - ReceiveRequestDialog @@ -1835,73 +1319,6 @@ &Save Image... &Сохранить изображение... - - Request payment to %1 - Запросить платёж на %1 - - - Payment information - Информация платежа - - - URI - URI - - - Address - Адрес - - - Amount - Сумма - - - Label - Метка - - - Message - Сообщение - - - Resulting URI too long, try to reduce the text for label / message. - Получившийся URI слишком длинный, попробуйте сократить текст метки / сообщения. - - - Error encoding URI into QR Code. - Ошибка кодирования URI в QR-код - - - - RecentRequestsTableModel - - Date - Дата - - - Label - Метка - - - Message - Сообщение - - - Amount - Сумма - - - (no label) - [нет метки] - - - (no message) - (нет сообщения) - - - (no amount) - (нет суммы) - SendCoinsDialog @@ -1966,939 +1383,293 @@ Комиссия - Choose... - Выберите... - - - collapse fee-settings - Свернуть настройки комиссии - - - per kilobyte - за килобайт - - - If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte. - Если комиссия установлена в 1000 сатоши, а транзакция составляет лишь 250 байт, тогда комиссия "на килобайт" составит 250 сатоши, а "всего как минимум" — 1000 сатоши. Для транзакций крупнее килобайта в обоих случаях будет использоваться платёж "на килобайт". - - - Hide - Скрыть - - - total at least - Итого как минимум - - - Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process. - Уплата минимальной комиссии — не проблема, пока объём транзакций меньше, чем свободное место в блоках. Учтите, однако, что такая транзакция может никогда не подтвердиться, если спрос на транзакции превышает возможности сети по их обработке. - - - (read the tooltip) - (прочтите подсказку) - - - Recommended: - Рекомендовано: - - - Custom: - Выборочно: - - - (Smart fee not initialized yet. This usually takes a few blocks...) - (Умная комиссия пока не инициализирована. Обычно для этого требуется несколько блоков...) - - - Confirmation time: - Время подтверждения: - - - normal - обычный - - - fast - ускоренный - - - Send as zero-fee transaction if possible - Осуществить транзакцию бесплатно, если возможно - - - (confirmation may take longer) - (подтверждение может занять больше времени) - - - Send to multiple recipients at once - Отправить нескольким получателям одновременно - - - Add &Recipient - &Добавить получателя - - - Clear all fields of the form. - Очистить все поля формы - - - Dust: - Пыль: - - - Clear &All - Очистить &всё - - - Balance: - Баланс: - - - Confirm the send action - Подтвердить отправку - - - S&end - &Отправить - - - Confirm send coins - Подтвердите отправку монет - - - %1 to %2 - С %1 на %2 - - - Copy quantity - Копировать количество - - - Copy amount - Скопировать сумму - - - Copy fee - Копировать комиссию - - - Copy after fee - Копировать после комиссии - - - Copy bytes - Копировать байты - - - Copy priority - Копировать приоритет - - - Copy change - Копировать размен - - - Total Amount %1 - Общая сумма %1 - - - or - или - - - The amount to pay must be larger than 0. - Сумма для отправки должно быть больше 0. - - - The amount exceeds your balance. - Сумма превышает Ваш баланс - - - The total exceeds your balance when the %1 transaction fee is included. - Сумма превысит Ваш баланс, если комиссия в размере %1 будет добавлена к транзакции - - - Transaction creation failed! - Не удалось создать транзакцию! - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - Транзакция была отклонена! Такое может произойти, если некоторые монеты уже были потрачены, например, если Вы используете одну копию бумажника (wallet.dat), а монеты были потрачены из другой копии, но не были отмечены как потраченные в этой. - - - A fee higher than %1 is considered an absurdly high fee. - Комиссия больше, чем %1, считается невероятно большой. - - - Payment request expired. - Запрос платежа просрочен. - - - Pay only the required fee of %1 - Заплатить только обязательную комиссию %1 - - - Estimated to begin confirmation within %n block(s). - Подтверждение ожидается через %n блок.Подтверждение ожидается через %n блока.Подтверждение ожидается через %n блоков.Подтверждение ожидается через %n блоков. - - - The recipient address is not valid. Please recheck. - Адрес получателя неверный. Пожалуйста, перепроверьте. - - - Duplicate address found: addresses should only be used once each. - Обнаружен дублирующийся адрес: используйте каждый адрес только один раз. - - - Warning: Invalid Bitcoin address - Внимание: неверный адрес Bitcoin - - - (no label) - [нет метки] - - - Warning: Unknown change address - Внимание: неизвестный адрес для сдачи - - - Copy dust - Копировать пыль - - - Are you sure you want to send? - Вы уверены, что хотите отправить? - - - added as transaction fee - добавлено как комиссия - - - - SendCoinsEntry - - A&mount: - Ко&личество: - - - Pay &To: - Полу&чатель: - - - Enter a label for this address to add it to your address book - Введите метку для данного адреса (для добавления в адресную книгу) - - - &Label: - &Метка: - - - Choose previously used address - Выберите ранее использованный адрес - - - This is a normal payment. - Это нормальный платёж. - - - The Bitcoin address to send the payment to - Адрес Bitcoin, на который отправить платёж - - - Alt+A - Alt+A - - - Paste address from clipboard - Вставить адрес из буфера обмена - - - Alt+P - Alt+P - - - Remove this entry - Удалить эту запись - - - 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. - С отправляемой суммы будет удержана комиссия. Получателю придёт меньше биткоинов, чем вы вводите в поле количества. Если выбрано несколько получателей, комиссия распределяется поровну. - - - S&ubtract fee from amount - Вычесть комиссию из суммы - - - Message: - Сообщение: - - - This is an unauthenticated payment request. - Это неавторизованный запрос платежа. - - - This is an authenticated payment request. - Это авторизованный запрос платежа. - - - Enter a label for this address to add it to the list of used addresses - Введите метку для этого адреса, чтобы добавить его в список использованных - - - 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. - К bitcoin: URI было прикреплено сообщение, которое будет сохранено вместе с транзакцией для вашего сведения. Заметьте: сообщение не будет отправлено через сеть Bitcoin. - - - Pay To: - Получатель: - - - Memo: - Примечание: - - - - ShutdownWindow - - Bitcoin Core is shutting down... - Bitcoin Core выключается... - - - Do not shut down the computer until this window disappears. - Не выключайте компьютер, пока это окно не исчезнет. - - - - SignVerifyMessageDialog - - Signatures - Sign / Verify a Message - Подписи - подписать/проверить сообщение - - - &Sign Message - &Подписать сообщение - - - 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. - Вы можете подписывать сообщения/соглашения своими адресами, чтобы доказать свою возможность получать биткоины на них. Будьте осторожны, не подписывайте что-то неопределённое или случайное, так как фишинговые атаки могут обманным путём заставить вас подписать нежелательные сообщения. Подписывайте только те сообщения, с которыми вы согласны вплоть до мелочей. - - - The Bitcoin address to sign the message with - Адрес Bitcoin, которым подписать сообщение - - - Choose previously used address - Выберите ранее использованный адрес - - - Alt+A - Alt+A - - - Paste address from clipboard - Вставить адрес из буфера обмена - - - Alt+P - Alt+P - - - Enter the message you want to sign here - Введите сообщение для подписи - - - Signature - Подпись - - - Copy the current signature to the system clipboard - Скопировать текущую подпись в системный буфер обмена - - - Sign the message to prove you own this Bitcoin address - Подписать сообщение, чтобы доказать владение адресом Bitcoin - - - Sign &Message - Подписать &Сообщение - - - Reset all sign message fields - Сбросить значения всех полей подписывания сообщений - - - Clear &All - Очистить &всё - - - &Verify Message - &Проверить сообщение - - - 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! - Введите ниже адрес получателя, сообщение (убедитесь, что переводы строк, пробелы, табы и т.п. в точности скопированы) и подпись, чтобы проверить сообщение. Убедитесь, что не скопировали лишнего в подпись, по сравнению с самим подписываемым сообщением, чтобы не стать жертвой атаки "man-in-the-middle". Заметьте, что эта операция удостоверяет лишь авторство подписавшего, но не может удостоверить отправителя транзакции. - - - The Bitcoin address the message was signed with - Адрес Bitcoin, которым было подписано сообщение - - - Verify the message to ensure it was signed with the specified Bitcoin address - Проверить сообщение, чтобы убедиться, что оно было подписано указанным адресом Bitcoin - - - Verify &Message - Проверить &Сообщение - - - Reset all verify message fields - Сбросить все поля проверки сообщения - - - Click "Sign Message" to generate signature - Нажмите "Подписать сообщение" для создания подписи - - - The entered address is invalid. - Введённый адрес неверен - - - Please check the address and try again. - Пожалуйста, проверьте адрес и попробуйте ещё раз. - - - The entered address does not refer to a key. - Введённый адрес не связан с ключом - - - Wallet unlock was cancelled. - Разблокировка бумажника была отменена. - - - Private key for the entered address is not available. - Для введённого адреса недоступен закрытый ключ - - - Message signing failed. - Не удалось подписать сообщение - - - Message signed. - Сообщение подписано - - - The signature could not be decoded. - Подпись не может быть раскодирована. - - - Please check the signature and try again. - Пожалуйста, проверьте подпись и попробуйте ещё раз. - - - The signature did not match the message digest. - Подпись не соответствует отпечатку сообщения. - - - Message verification failed. - Проверка сообщения не удалась. - - - Message verified. - Сообщение проверено. - - - - SplashScreen - - Bitcoin Core - Bitcoin Core - - - The Bitcoin Core developers - Разработчики Bitcoin Core - - - [testnet] - [тестовая сеть] - - - - TrafficGraphWidget - - KB/s - КБ/сек - - - - TransactionDesc - - Open until %1 - Открыто до %1 - - - conflicted - в противоречии - - - %1/offline - %1/отключен - - - %1/unconfirmed - %1/не подтверждено - - - %1 confirmations - %1 подтверждений - - - Status - Статус - - - , broadcast through %n node(s) - , разослано через %n узел, разослано через %n узла, разослано через %n узлов, разослано через %n узлов - - - Date - Дата - - - Source - Источник - - - Generated - Сгенерированно - - - From - От - - - To - Для - - - own address - свой адрес - - - watch-only - только наблюдение - - - label - метка - - - Credit - Кредит - - - matures in %n more block(s) - будет доступно через %n блокбудет доступно через %n блокабудет доступно через %n блоковбудет доступно через %n блоков - - - not accepted - не принято - - - Debit - Дебет - - - Total debit - Всего дебет - - - Total credit - Всего кредит - - - Transaction fee - Комиссия - - - Net amount - Чистая сумма - - - Message - Сообщение - - - Comment - Комментарий: - - - Transaction ID - ID транзакции - - - Merchant - Продавец - - - 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. - Сгенерированные монеты должны подождать %1 блоков, прежде чем они могут быть потрачены. Когда Вы сгенерировали этот блок, он был отправлен в сеть для добавления в цепочку блоков. Если он не попадёт в цепь, его статус изменится на "не принят", и монеты будут недействительны. Это иногда происходит в случае, если другой узел сгенерирует блок на несколько секунд раньше вас. - - - Debug information - Отладочная информация - - - Transaction - Транзакция - - - Inputs - Входы - - - Amount - Сумма - - - true - истина - - - false - ложь - - - , has not been successfully broadcast yet - , ещё не было успешно разослано - - - Open for %n more block(s) - Открыто для ещё %n блокаОткрыто для ещё %n блоковОткрыто для ещё %n блоковОткрыто для ещё %n блоков - - - unknown - неизвестно - - - - TransactionDescDialog - - Transaction details - Детали транзакции - - - This pane shows a detailed description of the transaction - Эта панель отображает детальное описание транзакции. + Choose... + Выберите... - - - TransactionTableModel - Date - Дата + collapse fee-settings + Свернуть настройки комиссии - Type - Тип + per kilobyte + за килобайт - Immature (%1 confirmations, will be available after %2) - Незрелый (%1 подтверждений, будет доступен после %2) + If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte. + Если комиссия установлена в 1000 сатоши, а транзакция составляет лишь 250 байт, тогда комиссия "на килобайт" составит 250 сатоши, а "всего как минимум" — 1000 сатоши. Для транзакций крупнее килобайта в обоих случаях будет использоваться платёж "на килобайт". - - Open for %n more block(s) - Открыто для ещё %n блокаОткрыто для ещё %n блоковОткрыто для ещё %n блоковОткрыто для ещё %n блоков + + Hide + Скрыть - Open until %1 - Открыто до %1 + total at least + Итого как минимум - Confirmed (%1 confirmations) - Подтверждено (%1 подтверждений) + Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process. + Уплата минимальной комиссии — не проблема, пока объём транзакций меньше, чем свободное место в блоках. Учтите, однако, что такая транзакция может никогда не подтвердиться, если спрос на транзакции превышает возможности сети по их обработке. - This block was not received by any other nodes and will probably not be accepted! - Этот блок не был получен другими узлами и, возможно, не будет принят! + (read the tooltip) + (прочтите подсказку) - Generated but not accepted - Сгенерированно, но не подтверждено + Recommended: + Рекомендовано: - Offline - Нет активных соединений с сетью + Custom: + Выборочно: - Label - Метка + (Smart fee not initialized yet. This usually takes a few blocks...) + (Умная комиссия пока не инициализирована. Обычно для этого требуется несколько блоков...) - Unconfirmed - Неподтверждено + Confirmation time: + Время подтверждения: - Confirming (%1 of %2 recommended confirmations) - Подтверждено(%1 подтверждений, рекомендуется %2 подтверждений) + normal + обычный - Conflicted - В противоречии + fast + ускоренный - Received with - Получено + Send to multiple recipients at once + Отправить нескольким получателям одновременно - Received from - Получено от + Add &Recipient + &Добавить получателя - Sent to - Отправлено + Clear all fields of the form. + Очистить все поля формы - Payment to yourself - Отправлено себе + Dust: + Пыль: - Mined - Добыто + Clear &All + Очистить &всё - watch-only - только наблюдение + Balance: + Баланс: - (n/a) - [не доступно] + Confirm the send action + Подтвердить отправку - Transaction status. Hover over this field to show number of confirmations. - Статус транзакции. Подведите курсор к нужному полю для того, чтобы увидеть количество подтверждений. + S&end + &Отправить + + + SendCoinsEntry - Date and time that the transaction was received. - Дата и время, когда транзакция была получена. + A&mount: + Ко&личество: - Type of transaction. - Тип транзакции. + Pay &To: + Полу&чатель: - Whether or not a watch-only address is involved in this transaction. - Использовался ли в транзакции адрес для наблюдения. + &Label: + &Метка: - User-defined intent/purpose of the transaction. - Определяемое пользователем намерение/цель транзакции. + Choose previously used address + Выберите ранее использованный адрес - Amount removed from or added to balance. - Сумма, добавленная, или снятая с баланса. + This is a normal payment. + Это нормальный платёж. - - - TransactionView - All - Все + The Bitcoin address to send the payment to + Адрес Bitcoin, на который отправить платёж - Today - Сегодня + Alt+A + Alt+A - This week - На этой неделе + Paste address from clipboard + Вставить адрес из буфера обмена - This month - В этом месяце + Alt+P + Alt+P - Last month - В прошлом месяце + Remove this entry + Удалить эту запись - This year - В этом году + 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. + С отправляемой суммы будет удержана комиссия. Получателю придёт меньше биткоинов, чем вы вводите в поле количества. Если выбрано несколько получателей, комиссия распределяется поровну. - Range... - Промежуток... + S&ubtract fee from amount + Вычесть комиссию из суммы - Received with - Получено на + Message: + Сообщение: - Sent to - Отправлено на + This is an unauthenticated payment request. + Это неавторизованный запрос платежа. - To yourself - Отправленные себе + This is an authenticated payment request. + Это авторизованный запрос платежа. - Mined - Добытые + Enter a label for this address to add it to the list of used addresses + Введите метку для этого адреса, чтобы добавить его в список использованных - Other - Другое + 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. + К bitcoin: URI было прикреплено сообщение, которое будет сохранено вместе с транзакцией для вашего сведения. Заметьте: сообщение не будет отправлено через сеть Bitcoin. - Enter address or label to search - Введите адрес или метку для поиска + Pay To: + Получатель: - Min amount - Мин. сумма + Memo: + Примечание: + + + ShutdownWindow - Copy address - Копировать адрес + Do not shut down the computer until this window disappears. + Не выключайте компьютер, пока это окно не исчезнет. + + + SignVerifyMessageDialog - Copy label - Копировать метку + Signatures - Sign / Verify a Message + Подписи - подписать/проверить сообщение - Copy amount - Скопировать сумму + &Sign Message + &Подписать сообщение - Copy transaction ID - Скопировать ID транзакции + 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. + Вы можете подписывать сообщения/соглашения своими адресами, чтобы доказать свою возможность получать биткоины на них. Будьте осторожны, не подписывайте что-то неопределённое или случайное, так как фишинговые атаки могут обманным путём заставить вас подписать нежелательные сообщения. Подписывайте только те сообщения, с которыми вы согласны вплоть до мелочей. - Copy raw transaction - Скопировать исходную транзакции + The Bitcoin address to sign the message with + Адрес Bitcoin, которым подписать сообщение - Edit label - Изменить метку + Choose previously used address + Выберите ранее использованный адрес - Show transaction details - Показать подробности транзакции + Alt+A + Alt+A - Export Transaction History - Экспортировать историю транзакций + Paste address from clipboard + Вставить адрес из буфера обмена - Watch-only - Для наблюдения + Alt+P + Alt+P - Exporting Failed - Экспорт не удался + Enter the message you want to sign here + Введите сообщение для подписи - There was an error trying to save the transaction history to %1. - Произошла ошибка при сохранении истории транзакций в %1. + Signature + Подпись - Exporting Successful - Экспорт успешно завершён + Copy the current signature to the system clipboard + Скопировать текущую подпись в системный буфер обмена - The transaction history was successfully saved to %1. - История транзакций была успешно сохранена в %1. + Sign the message to prove you own this Bitcoin address + Подписать сообщение, чтобы доказать владение адресом Bitcoin - Comma separated file (*.csv) - Текст, разделённый запятыми (*.csv) + Sign &Message + Подписать &Сообщение - Confirmed - Подтверждено + Reset all sign message fields + Сбросить значения всех полей подписывания сообщений - Date - Дата + Clear &All + Очистить &всё - Type - Тип + &Verify Message + &Проверить сообщение - Label - Метка + 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! + Введите ниже адрес получателя, сообщение (убедитесь, что переводы строк, пробелы, табы и т.п. в точности скопированы) и подпись, чтобы проверить сообщение. Убедитесь, что не скопировали лишнего в подпись, по сравнению с самим подписываемым сообщением, чтобы не стать жертвой атаки "man-in-the-middle". Заметьте, что эта операция удостоверяет лишь авторство подписавшего, но не может удостоверить отправителя транзакции. - Address - Адрес + The Bitcoin address the message was signed with + Адрес Bitcoin, которым было подписано сообщение - ID - ID + Verify the message to ensure it was signed with the specified Bitcoin address + Проверить сообщение, чтобы убедиться, что оно было подписано указанным адресом Bitcoin - Range: - Промежуток от: + Verify &Message + Проверить &Сообщение - to - до + Reset all verify message fields + Сбросить все поля проверки сообщения - UnitDisplayStatusBarControl + SplashScreen - Unit to show amounts in. Click to select another unit. - Единица измерения количества монет. Щёлкните для выбора другой единицы. + [testnet] + [тестовая сеть] - WalletFrame + TrafficGraphWidget - No wallet has been loaded. - Не был загружен ни один бумажник. + KB/s + КБ/сек - WalletModel + TransactionDescDialog - Send Coins - Отправка + This pane shows a detailed description of the transaction + Эта панель отображает детальное описание транзакции. - WalletView - - &Export - &Экспорт - - - Export the data in the current tab to a file - Экспортировать данные из вкладки в файл - - - Backup Wallet - Сделать резервную копию бумажника - - - Wallet Data (*.dat) - Данные бумажника (*.dat) - - - Backup Failed - Резервное копирование не удалось - - - There was an error trying to save the wallet data to %1. - Произошла ошибка при сохранении данных бумажника в %1. - - - The wallet data was successfully saved to %1. - Данные бумажника были успешно сохранены в %1. - + UnitDisplayStatusBarControl - Backup Successful - Резервное копирование успешно завершено + Unit to show amounts in. Click to select another unit. + Единица измерения количества монет. Щёлкните для выбора другой единицы. @@ -2927,14 +1698,6 @@ If <category> is not supplied or if <category> = 1, output all debugging information. Если <category> не предоставлена или равна 1, выводить всю отладочную информацию. - - Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s) - Максимальная сумма комиссий (%s) для одной транзакции в бумажнике; слишком низкое значение может вызвать прерывание больших транзакций (по умолчанию: %s) - - - Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. - Внимание: убедитесь, что дата и время на Вашем компьютере выставлены верно! Если Ваши часы идут неправильно, Bitcoin Core будет работать некорректно. - Prune configured below the minimum of %d MiB. Please use a higher number. Удаление блоков выставлено ниже, чем минимум в %d Мб. Пожалуйста, используйте большее значение. @@ -2975,6 +1738,10 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Принимать подключения извне (по умолчанию: 1, если не используется -proxy или -connect) + + Bitcoin Core + Bitcoin Core + Bind to given address and always listen on it. Use [host]:port notation for IPv6 Привязаться к указанному адресу и всегда прослушивать только его. Используйте [хост]:порт для IPv6 @@ -3007,10 +1774,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Это пре-релизная тестовая сборка - используйте на свой страх и риск - не используйте для добычи или торговых приложений - - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - Не удалось забиндиться на %s на этом компьютере. Возможно, Bitcoin Core уже запущен. - Use UPnP to map the listening port (default: 1 when listening and no -proxy) Использовать UPnP для проброса порта (по умолчанию: 1, если используется прослушивание и нет -proxy) @@ -3027,18 +1790,10 @@ Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Внимание: похоже, в сети нет полного согласия! Некоторый майнеры, возможно, испытывают проблемы. - - Warning: Unknown block versions being mined! It's possible unknown rules are in effect - Внимание: Получена неизвестная версия блока! Возможно неизвестные правила вступили в силу. - Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Внимание: мы не полностью согласны с подключенными участниками! Вам или другим участникам, возможно, следует обновиться. - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Внимание: wallet.dat повреждён, данные спасены! Оригинальный wallet.dat сохранён как wallet.{timestamp}.bak в %s; если ваш баланс или транзакции некорректны, вы должны восстановить файл из резервной копии. - Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. Вносить в белый список участников, подключающихся с указанной маски сети или IP. Можно использовать многократно. @@ -3107,6 +1862,10 @@ Error initializing wallet database environment %s! Ошибка инициализации окружения БД бумажника %s! + + Error loading %s + Ошибка загрузки %s + Error loading block database Ошибка чтения базы данных блоков @@ -3211,10 +1970,6 @@ Wallet options: Настройки бумажника: - - You need to rebuild the database using -reindex to change -txindex - Вам необходимо пересобрать базы данных с помощью -reindex, чтобы изменить -txindex - 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 Разрешить подключения JSON-RPC с указанного источника. Разрешённые значения для <ip> — отдельный IP (например, 1.2.3.4), сеть/маска сети (например, 1.2.3.4/255.255.255.0) или сеть/CIDR (например, 1.2.3.4/24). Эту опцию можно использовать многократно @@ -3227,10 +1982,6 @@ Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces) Привязаться к указанному адресу для прослушивания JSON-RPC подключений. Используйте запись [хост]:порт для IPv6. Эту опцию можно использовать многократно (по умолчанию: привязываться ко всем интерфейсам) - - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - Не удалось установить блокировку на каталог данных %s. Возможно, Bitcoin Core уже запущен. - Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) Создавать новые файлы с системными правами по умолчанию вместо umask 077 (эффективно только при отключенном бумажнике) @@ -3275,10 +2026,6 @@ Set maximum size of high-priority/low-fee transactions in bytes (default: %d) Задать максимальный размер высокоприоритетных/низкокомиссионных транзакций в байтах (по умолчанию: %d) - - Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) - Задать число потоков генерации монет, если она включена (-1 = все ядра процессора, по умолчанию: %d) - The transaction amount is too small to send after the fee has been deducted Сумма транзакции за вычетом комиссии слишком мала @@ -3303,34 +2050,14 @@ Accept public REST requests (default: %u) Принимать публичные REST-запросы (по умолчанию: %u) - - Activating best chain... - Активируется лучшая цепь... - - - Attempt to recover private keys from a corrupt wallet.dat on startup - Попытаться восстановить приватные ключи из повреждённого wallet.dat при запуске - Automatically create Tor hidden service (default: %d) Автоматически создавать скрытый Tor сервис (по умолчанию: %d) - - Cannot resolve -whitebind address: '%s' - Не удаётся разрешить адрес в параметре -whitebind: '%s' - Connect through SOCKS5 proxy Подключаться через SOCKS5 прокси - - Copyright (C) 2009-%i The Bitcoin Core Developers - Все права защищены © 2009-%i Разработчики Bitcoin Core - - - Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - Ошибка загрузки wallet.dat: бумажник требует более новую версию Bitcoin Core - Error reading from database, shutting down. Ошибка чтения базы данных, работа завершается. @@ -3343,22 +2070,6 @@ Information Информация - - Initialization sanity check failed. Bitcoin Core is shutting down. - Не удалось проверить чистоту. Bitcoin Core выключается. - - - Invalid amount for -maxtxfee=<amount>: '%s' - Неверное значение -maxtxfee=<amount>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Неверная сумма в параметре -minrelaytxfee=<кол-во>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - Неверная сумма в параметре -mintxfee=<кол-во>: '%s' - Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) Неверное количество в параметре -paytxfee=<кол-во>: '%s' (должно быть как минимум %s) @@ -3383,14 +2094,6 @@ RPC server options: Параметры сервера RPC: - - Rebuild block chain index from current blk000??.dat files on startup - Перестроить при запуске индекс цепи блоков из текущих файлов blk000??.dat - - - Receive and display P2P network alerts (default: %u) - Получать и отображать P2P сетевые тревоги (по умолчанию: %u) - Reducing -maxconnections from %d to %d, because of system limitations. Уменьшите -maxconnections с %d до %d, из-за ограничений системы. @@ -3463,10 +2166,6 @@ Username for JSON-RPC connections Имя для подключений JSON-RPC - - Wallet needed to be rewritten: restart Bitcoin Core to complete - Необходимо перезаписать бумажник, перезапустите Bitcoin Core для завершения операции. - Warning Внимание @@ -3487,10 +2186,6 @@ ZeroMQ notification options: ZeroMQ параметры оповещения: - - wallet.dat corrupt, salvage failed - wallet.dat повреждён, спасение данных не удалось - Password for JSON-RPC connections Пароль для подключений JSON-RPC @@ -3499,10 +2194,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) Выполнить команду, когда появляется новый блок (%s в команде заменяется на хэш блока) - - This help message - Эта справка - Allow DNS lookups for -addnode, -seednode and -connect Разрешить поиск в DNS для -addnode, -seednode и -connect @@ -3511,10 +2202,6 @@ Loading addresses... Загрузка адресов... - - Error loading wallet.dat: Wallet corrupted - Ошибка загрузки wallet.dat: Бумажник поврежден - (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) (1 = сохранять метаданные транзакции: например, владельца аккаунта и информацию запроса платежа; 2 = отбросить метаданные) @@ -3531,10 +2218,6 @@ Do not keep transactions in the mempool longer than <n> hours (default: %u) Не хранить транзакции в памяти дольше, чем <n> часов (по умолчанию %u) - - Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. - Ошибка чтения wallet.dat! Все ключи прочитаны верно, но данные транзакций или записи адресной книги могут отсутствовать или быть неправильными. - Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) Комиссии (в %s/Кб) меньшие этого значения считаются нулевыми при создании транзакций (по умолчанию: %s) @@ -3579,6 +2262,10 @@ Username and hashed password for JSON-RPC connections. The field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A canonical python script is included in share/rpcuser. This option can be specified multiple times Имя пользователя и хэш пароля для JSON-RPC соединений. Поле <userpw> использует формат: <USERNAME>:<SALT>$<HASH>. Каноничный пример скрипта на питоне включен в "share/rpcuser". Эта опция может быть указана несколько раз + + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + Внимание: Получена неизвестная версия блока! Возможно неизвестные правила вступили в силу. + (default: %s) (по умолчанию: %s) @@ -3587,14 +2274,6 @@ Always query for peer addresses via DNS lookup (default: %u) Всегда запрашивать адреса участников с помощью DNS (по умолчанию: %u) - - Error loading wallet.dat - Ошибка при загрузке wallet.dat - - - Generate coins (default: %u) - Включить добычу монет (по умолчанию: %u) - How many blocks to check at startup (default: %u, 0 = all) Сколько блоков проверять при запуске (по умолчанию: %u, 0 = все) @@ -3679,18 +2358,6 @@ Unknown network specified in -onlynet: '%s' В параметре -onlynet указана неизвестная сеть: '%s' - - Cannot resolve -bind address: '%s' - Не удаётся разрешить адрес в параметре -bind: '%s' - - - Cannot resolve -externalip address: '%s' - Не удаётся разрешить адрес в параметре -externalip: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - Неверная сумма в параметре -paytxfee=<кол-во>: '%s' - Insufficient funds Недостаточно монет diff --git a/src/qt/locale/bitcoin_ru_RU.ts b/src/qt/locale/bitcoin_ru_RU.ts index 41e467e496e82..a6f9ffccbd776 100644 --- a/src/qt/locale/bitcoin_ru_RU.ts +++ b/src/qt/locale/bitcoin_ru_RU.ts @@ -21,10 +21,6 @@ C&lose Закрыть - - &Copy Address - Копировать адрес - Delete the currently selected address from the list Удалить выбранный адрес из списка @@ -41,14 +37,7 @@ &Delete Удалить - - C&hoose - Выбрать - - - - AddressTableModel - + AskPassphraseDialog @@ -57,14 +46,6 @@ BitcoinGUI - - Bitcoin Core - Bitcoin Core - - - &About Bitcoin Core - О Bitcoin Core - &Command-line options Опции командной строки @@ -82,9 +63,6 @@ Информация - - ClientModel - CoinControlDialog @@ -99,18 +77,6 @@ Confirmed Подтвержденные - - Copy address - Копировать адрес - - - yes - Да - - - no - Нет - EditAddressDialog @@ -124,18 +90,10 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin Core - version версия - - About Bitcoin Core - О Bitcoin Core - Command-line options Опции командной строки @@ -147,10 +105,6 @@ Intro - - Bitcoin Core - Bitcoin Core - Error Ошибка @@ -173,18 +127,12 @@ OverviewPage - - PaymentServer - PeerTableModel QObject - - QRImageWidget - RPCConsole @@ -198,13 +146,6 @@ ReceiveRequestDialog - - RecentRequestsTableModel - - Date - Дата - - SendCoinsDialog @@ -219,68 +160,22 @@ SplashScreen - - Bitcoin Core - Bitcoin Core - TrafficGraphWidget - - TransactionDesc - - Date - Дата - - TransactionDescDialog - - TransactionTableModel - - Date - Дата - - - - TransactionView - - Copy address - Копировать адрес - - - Confirmed - Подтвержденные - - - Date - Дата - - UnitDisplayStatusBarControl - WalletFrame - - - WalletModel - - - WalletView - - &Export - Экспорт - + bitcoin-core - Export the data in the current tab to a file - Экспортировать данные текущей вкладки в файл + Bitcoin Core + Bitcoin Core - - - bitcoin-core Information Информация diff --git a/src/qt/locale/bitcoin_sk.ts b/src/qt/locale/bitcoin_sk.ts index 9addbdaa8a10e..e2b8a0201599b 100644 --- a/src/qt/locale/bitcoin_sk.ts +++ b/src/qt/locale/bitcoin_sk.ts @@ -25,10 +25,6 @@ C&lose Zatvoriť - - &Copy Address - &Kopírovať adresu - Delete the currently selected address from the list Vymaž vybranú adresu zo zoznamu @@ -45,73 +41,6 @@ &Delete &Zmazať - - Choose the address to send coins to - Zvoľte adresu kam poslať coins - - - Choose the address to receive coins with - Zvoľte adresu na ktorú prijať coins - - - C&hoose - Vybrať - - - Sending addresses - Adresa odoslania - - - Receiving addresses - Prijímacia adresa - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Toto sú Vaše Bitcoin adresy pre posielanie platieb. Vždy skontrolujte množstvo a prijímaciu adresu pred poslaním coins. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Toto sú vaše Bitcoin adresy pre prijímanie platieb. Odporúča sa použiť novú prijímaciu adresu pre každú transakciu. - - - Copy &Label - Kopírovať &popis - - - &Edit - &Upraviť - - - Export Address List - Exportovať zoznam adries - - - Comma separated file (*.csv) - Čiarkou oddelovaný súbor (*.csv) - - - Exporting Failed - Export zlyhal - - - There was an error trying to save the address list to %1. Please try again. - Nastala chyba pri pokuse uložiť zoznam adries do %1. Skúste znovu. - - - - AddressTableModel - - Label - Popis - - - Address - Adresa - - - (no label) - (bez popisu) - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase Zopakujte nové heslo - - Encrypt wallet - Zašifrovať peňaženku - - - This operation needs your wallet passphrase to unlock the wallet. - Táto operácia potrebuje heslo k vašej peňaženke aby ju mohla dešifrovať. - - - Unlock wallet - Odomknúť peňaženku - - - This operation needs your wallet passphrase to decrypt the wallet. - Táto operácia potrebuje heslo k vašej peňaženke na dešifrovanie peňaženky. - - - Decrypt wallet - Dešifrovať peňaženku - - - Change passphrase - Zmena hesla - - - Confirm wallet encryption - Potvrďte šifrovanie peňaženky - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Varovanie: Ak zašifrujete peňaženku a stratíte heslo, <b>STRATÍTE VŠETKY VAŠE BITCOINY</b>!⏎ - - - Are you sure you wish to encrypt your wallet? - Ste si istí, že si želáte zašifrovať peňaženku? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Jadro Bitcoin sa teraz ukončí pre dokončenie procesu šifrovania. Pamätaj, že šifrovanie peňaženky Ťa nemôže úplne ochrániť pred krádežou bitcoinov pomocou škodlivého software. - - - 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. - DÔLEŽITÉ: Všetky doterajšie záložné kópie peňaženky ktoré ste zhotovili by mali byť nahradené novým zašifrovaným súborom s peňaženkou. Z bezpečnostných dôvodov sa predchádzajúce kópie nezašifrovanej peňaženky stanú neužitočné keď začnete používať novú zašifrovanú peňaženku. - - - Warning: The Caps Lock key is on! - Varovanie: Caps Lock je zapnutý - - - Wallet encrypted - Peňaženka zašifrovaná - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Zadajte nové heslo k peňaženke.<br/>Prosím použite heslo s dĺžkou aspoň <b>10 alebo viac náhodných znakov</b>, alebo <b>8 alebo viac slov</b>. - - - Enter the old passphrase and new passphrase to the wallet. - Zadajte staré a nové heslo k peňaženke. - - - Wallet encryption failed - Šifrovanie peňaženky zlyhalo - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Šifrovanie peňaženky zlyhalo kôli internej chybe. Vaša peňaženka nebola zašifrovaná. - - - The supplied passphrases do not match. - Zadané heslá nesúhlasia. - - - Wallet unlock failed - Odomykanie peňaženky zlyhalo - - - The passphrase entered for the wallet decryption was incorrect. - Zadané heslo pre dešifrovanie peňaženky bolo nesprávne. - - - Wallet decryption failed - Zlyhalo šifrovanie peňaženky. - - - Wallet passphrase was successfully changed. - Heslo k peňaženke bolo úspešne zmenené. - BanTableModel @@ -269,6 +110,10 @@ Quit application Ukončiť program + + &About %1 + &O %1 + About &Qt O &Qt @@ -305,14 +150,6 @@ Open &URI... Otvoriť &URI... - - Bitcoin Core client - Bitcoin Core klient - - - Importing blocks from disk... - Importujem bloky z disku... - Reindexing blocks on disk... Preindexúvam bloky na disku... @@ -357,10 +194,6 @@ &Receive &Prijať - - Show information about Bitcoin Core - Zobraziť informácie o Bitcoin Core - &Show / Hide Zobraziť / skryť @@ -397,22 +230,10 @@ Tabs toolbar Lišta záložiek - - Bitcoin Core - Jadro Bitcoin - Request payments (generates QR codes and bitcoin: URIs) Vyžiadať platby (vygeneruje QR kódy a bitcoin: URI) - - &About Bitcoin Core - O jadre Bitcoin - - - Modify configuration options for Bitcoin Core - Upraviť možnosti nastavenia pre Jadro Bitcoin - Show the list of used sending addresses and labels Zobraziť zoznam použitých adries odosielateľa a ich popisy @@ -429,10 +250,6 @@ &Command-line options Možnosti príkazového riadku - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Zobraziť pomocnú správu od Bitcoin Jadra pre získanie zoznamu dostupných možností príkazového riadku - %n active connection(s) to Bitcoin network %n aktívne pripojenie do siete Bitcoin%n aktívne pripojenia do siete Bitcoin%n aktívnych pripojení do siete Bitcoin @@ -544,13 +361,6 @@ Peňaženka je <b>zašifrovaná</b> a momentálne <b>zamknutá</b> - - ClientModel - - Network Alert - Výstraha siete - - CoinControlDialog @@ -629,150 +439,6 @@ Priority Priorita - - Copy address - Kopírovať adresu - - - Copy label - Kopírovať popis - - - Copy amount - Kopírovať sumu - - - Copy transaction ID - Kopírovať ID transakcie - - - Lock unspent - Uzamknúť neminuté - - - Unlock unspent - Odomknúť neminuté - - - Copy quantity - Kopírovať množstvo - - - Copy fee - Kopírovať poplatok - - - Copy after fee - Kopírovať za poplatok - - - Copy bytes - Kopírovať bajty - - - Copy priority - Kopírovať prioritu - - - Copy dust - Kopírovať prach - - - Copy change - Kopírovať zmenu - - - highest - najvyššie - - - higher - vyššie - - - high - vysoké - - - medium-high - stredne vysoké - - - medium - stredné - - - low-medium - stredne nízke - - - low - nízke - - - lower - nižšie - - - lowest - najnižšie - - - (%1 locked) - (%1 zamknutých) - - - none - žiadne - - - This label turns red if the transaction size is greater than 1000 bytes. - Tento popis sčervenie ak veľkosť transakcie presiahne 1000 bajtov. - - - This label turns red if the priority is smaller than "medium". - Tento popis sčervenie ak je priorita nižšia ako "stredná". - - - This label turns red if any recipient receives an amount smaller than %1. - Tento popis sčervenie ak ktorýkoľvek príjemca dostane sumu menšiu ako %1. - - - Can vary +/- %1 satoshi(s) per input. - Môže sa líšiť o +/- %1 satoshi pre každý vstup - - - yes - áno - - - no - nie - - - This means a fee of at least %1 per kB is required. - To znamená že požadovaný poplatok je aspoň %1 za kB. - - - Can vary +/- 1 byte per input. - Môže sa pohybovať +/- 1 bajt pre vstup. - - - Transactions with higher priority are more likely to get included into a block. - Transakcie s vysokou prioritou sa pravdepodobnejsie dostanú do bloku. - - - (no label) - (bez popisu) - - - change from %1 (%2) - zmena od %1 (%2) - - - (change) - (zmena) - EditAddressDialog @@ -796,38 +462,6 @@ &Address &Adresa - - New receiving address - Nová adresa pre prijímanie - - - New sending address - Nová adresa pre odoslanie - - - Edit receiving address - Upraviť prijímacie adresy - - - Edit sending address - Upraviť odosielaciu adresu - - - The entered address "%1" is already in the address book. - Vložená adresa "%1" sa už nachádza v adresári. - - - The entered address "%1" is not a valid Bitcoin address. - Vložená adresa "%1" nieje platnou adresou bitcoin. - - - Could not unlock wallet. - Nepodarilo sa odomknúť peňaženku. - - - New key generation failed. - Generovanie nového kľúča zlyhalo. - FreespaceChecker @@ -854,10 +488,6 @@ HelpMessageDialog - - Bitcoin Core - Jadro Bitcoin - version verzia @@ -866,10 +496,6 @@ (%1-bit) (%1-bit) - - About Bitcoin Core - O jadre Bitcoin - Command-line options Voľby príkazového riadku @@ -906,29 +532,13 @@ Show splash screen on startup (default: %u) Zobraziť uvítaciu obrazovku pri štarte (predvolené: %u) - - Reset all settings changes made over the GUI - Reštartovať všetky nastavenia urobené v používateľskom rozhraní. - - + Intro Welcome Vitajte - - Welcome to Bitcoin Core. - Vitajte v jadre Bitcoin. - - - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - Keďže spúštate program prvý krát, môžte si vybrať kde bude Bitcoin Jadro ukladať svoje dáta. - - - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - Jadro Bitcoin stiahne zo siete a uloží kópiu Bitcoin blockchain. Aspoň %1GB dát bude uložených v tomto priečinku a časom porastie. Peňaženka bude tiež uložená v tomto priečinku. - Use the default data directory Použiť predvolený dátový adresár @@ -937,10 +547,6 @@ Use a custom data directory: Použiť vlastný dátový adresár: - - Bitcoin Core - Jadro Bitcoin - Error: Specified data directory "%1" cannot be created. Chyba: Zadaný priečinok pre dáta "%1" nemôže byť vytvorený. @@ -976,10 +582,6 @@ Select payment request file Vyberte súbor s výzvou k platbe - - Select payment request file to open - Vyberte ktorý súbor s výzvou k platbe otvoriť - OptionsDialog @@ -1019,10 +621,6 @@ 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. Minimalizovať namiesto ukončenia aplikácie keď sa okno zavrie. Keď je zvolená táto možnosť, aplikácia sa zavrie len po zvolení Ukončiť v menu. - - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - Tu sa dá nastaviť jazyk užívateľského rozhrania. Toto nastavenie bude účinné po reštartovaní Jadra Bitcoin. - 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 |. URL tretích strán (napr. prehliadač blockchain) ktoré sa zobrazujú v záložke transakcií ako položky kontextového menu. %s v URL je nahradené hash-om transakcie. Viaceré URL sú oddelené zvislou čiarou |. @@ -1047,14 +645,6 @@ &Network &Sieť - - Automatically start Bitcoin Core after logging in to the system. - Automaticky spustiť Jadro Bitcoin po prihlásení do systému - - - &Start Bitcoin Core on system login - &Spustiť Bitcoin pri spustení systému správy okien - (0 = auto, <0 = leave that many cores free) (0 = auto, <0 = nechať toľko jadier voľných) @@ -1284,178 +874,68 @@ - PaymentServer + PeerTableModel - URI handling - Spracovanie URI + User Agent + Aplikácia - Invalid payment address %1 - Neplatná adresa platby %1 + Node/Service + Uzol/Služba - Payment request rejected - Požiadavka na platbu zamietnutá + Ping Time + Čas odozvy + + + QObject - Payment request network doesn't match client network. - Sieť požiadavky na platbu nie je zhodná so sieťou klienta. + Amount + Suma - Payment request is not initialized. - Požiadavka na platbu nie je inicializovaná + Enter a Bitcoin address (e.g. %1) + Zadajte bitcoin adresu (napr. %1) - Requested payment amount of %1 is too small (considered dust). - Požadovaná platba sumy %1 je príliš malá (považovaná za prach). + %1 d + %1 d - Payment request error - Chyba pri vyžiadaní platby + %1 h + %1 h - Cannot start bitcoin: click-to-pay handler - Nedá sa spustiť obslužný program bitcoin: click-to-pay zaplatiť kliknutím + %1 m + %1 m - Payment request fetch URL is invalid: %1 - URL pre stiahnutie výzvy na zaplatenie je neplatné: %1 + %1 s + %1 s - URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - URI sa nedá analyzovať! To môže byť spôsobené neplatnou Bitcoin adresou alebo zle upravenými vlastnosťami URI. + None + Žiadne - Payment request file handling - Obsluha súboru s požiadavkou na platbu + N/A + nie je k dispozícii - Payment request file cannot be read! This can be caused by an invalid payment request file. - Súbor s výzvou na zaplatenie sa nedá čítať alebo spracovať! To môže byť spôsobené aj neplatným súborom s výzvou. + %1 ms + %1 ms + + + RPCConsole - Payment request expired. - Vypršala platnosť požiadavky na platbu. + Client name + Meno klienta - Unverified payment requests to custom payment scripts are unsupported. - Program nepodporuje neoverené platobné výzvy na vlastná skripty. - - - Invalid payment request. - Chybná požiadavka na platbu. - - - Refund from %1 - Vrátenie z %1 - - - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - Požiadavka na platbu %1 je príliš veľká (%2 bajtov, povolené je %3 bajtov). - - - Error communicating with %1: %2 - Chyba komunikácie s %1: %2 - - - Payment request cannot be parsed! - Požiadavka na platbu nemôže byť analyzovaná! - - - Bad response from server %1 - Zlá odpoveď zo servera %1 - - - Payment acknowledged - Platba potvrdená - - - Network request error - Chyba požiadavky siete - - - - PeerTableModel - - User Agent - Aplikácia - - - Node/Service - Uzol/Služba - - - Ping Time - Čas odozvy - - - - QObject - - Amount - Suma - - - Enter a Bitcoin address (e.g. %1) - Zadajte bitcoin adresu (napr. %1) - - - %1 d - %1 d - - - %1 h - %1 h - - - %1 m - %1 m - - - %1 s - %1 s - - - None - Žiadne - - - N/A - nie je k dispozícii - - - %1 ms - %1 ms - - - - QRImageWidget - - &Save Image... - Uložiť obrázok... - - - &Copy Image - Kopírovať obrázok - - - Save QR Code - Ukladanie QR kódu - - - PNG Image (*.png) - PNG obrázok (*.png) - - - - RPCConsole - - Client name - Meno klienta - - - N/A - nie je k dispozícii + N/A + nie je k dispozícii Client version @@ -1513,10 +993,6 @@ Memory usage Využitie pamäte - - Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. - Otvoriť Bitcoin log súbor pre ladenie z aktuálneho dátového adresára. Toto môže trvať niekoľko sekúnd pre veľké súbory. - Received Prijaté @@ -1630,10 +1106,6 @@ Out: Von: - - Build date - Dátum zostavenia - Debug log file Súbor záznamu ladenia @@ -1670,10 +1142,6 @@ &Unban Node &odblokovať uzol - - Welcome to the Bitcoin Core RPC console. - Vitajte v RPC konzole pre Jadro Bitcoin. - Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. Použi šípky hore a dolu pre navigáciu históriou a <b>Ctrl-L</b> pre vyčistenie obrazovky. @@ -1801,18 +1269,6 @@ Remove Odstrániť - - Copy label - Kopírovať popis - - - Copy message - Kopírovať správu - - - Copy amount - Kopírovať sumu - ReceiveRequestDialog @@ -1832,73 +1288,6 @@ &Save Image... Uložiť obrázok... - - Request payment to %1 - Vyžiadať platbu pre %1 - - - Payment information - Informácia o platbe - - - URI - URI - - - Address - Adresa - - - Amount - Suma - - - Label - Popis - - - Message - Správa - - - Resulting URI too long, try to reduce the text for label / message. - Výsledné URI príliš dlhé, skráť text pre názov / správu. - - - Error encoding URI into QR Code. - Chyba v zakódovaní URI do QR kódu - - - - RecentRequestsTableModel - - Date - Dátum - - - Label - Popis - - - Message - Správa - - - Amount - Suma - - - (no label) - (bez popisu) - - - (no message) - (žiadna správa) - - - (no amount) - (žiadna suma) - SendCoinsDialog @@ -2018,14 +1407,6 @@ fast rýchle - - Send as zero-fee transaction if possible - Poslať ako transakciu bez poplatku, ak je to možné - - - (confirmation may take longer) - (potvrdenie môže trvať dlhšie) - Send to multiple recipients at once Poslať viacerým príjemcom naraz @@ -2058,114 +1439,6 @@ S&end &Odoslať - - Confirm send coins - Potvrdiť odoslanie bitcoins - - - %1 to %2 - %1 do %2 - - - Copy quantity - Kopírovať množstvo - - - Copy amount - Kopírovať sumu - - - Copy fee - Kopírovať poplatok - - - Copy after fee - Kopírovať za poplatok - - - Copy bytes - Kopírovať bajty - - - Copy priority - Kopírovať prioritu - - - Copy change - Kopírovať zmenu - - - Total Amount %1 - Celkové množstvo %1 - - - or - alebo - - - The amount to pay must be larger than 0. - Suma na úhradu musí byť väčšia ako 0. - - - The amount exceeds your balance. - Suma je vyššia ako Váš zostatok. - - - The total exceeds your balance when the %1 transaction fee is included. - Suma celkom prevyšuje Váš zostatok ak sú započítané %1 transakčné poplatky. - - - Transaction creation failed! - Vytvorenie transakcie zlyhalo! - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - Transakcia bola zamietnutá! Toto sa môže stať ak niektoré coins vo vašej peňaženke už boli minuté, ako keď použijete kópiu wallet.dat a coins boli minuté z kópie ale neoznačené ako minuté tu. - - - A fee higher than %1 is considered an absurdly high fee. - Poplatok vyšší ako %1 je považovaný za šialene vysoký. - - - Payment request expired. - Vypršala platnosť požiadavky na platbu. - - - Pay only the required fee of %1 - Zaplatiť len vyžadovaný poplatok z %1 - - - The recipient address is not valid. Please recheck. - Adresa príjemcu je neplatná. Prosím, overte ju. - - - Duplicate address found: addresses should only be used once each. - Našla sa duplicitná adresa: každú adresu je možné použiť len raz. - - - Warning: Invalid Bitcoin address - Varovanie: Nesprávna Bitcoin adresa - - - (no label) - (bez popisu) - - - Warning: Unknown change address - Varovanie: Neznáma adresa pre výdavok - - - Copy dust - Kopírovať prach - - - Are you sure you want to send? - Určite to chcete odoslať? - - - added as transaction fee - pridané ako transakčný poplatok - SendCoinsEntry @@ -2177,10 +1450,6 @@ Pay &To: Zapla&tiť: - - Enter a label for this address to add it to your address book - Vložte popis pre túto adresu aby sa pridala do adresára - &Label: &Popis: @@ -2252,10 +1521,6 @@ ShutdownWindow - - Bitcoin Core is shutting down... - Jadro Bitcoin sa ukončuje... - Do not shut down the computer until this window disappears. Nevypínajte počítač kým toto okno nezmizne. @@ -2339,594 +1604,84 @@ Reset all verify message fields Obnoviť všetky polia v overiť správu + + + SplashScreen - Click "Sign Message" to generate signature - Kliknite "Podpísať Správu" na získanie podpisu + [testnet] + [testovacia sieť] + + + TrafficGraphWidget - The entered address is invalid. - Zadaná adresa je neplatná. + KB/s + KB/s + + + TransactionDescDialog - Please check the address and try again. - Prosím skontrolujte adresu a skúste znova. + This pane shows a detailed description of the transaction + Táto časť obrazovky zobrazuje detailný popis transakcie + + + UnitDisplayStatusBarControl - The entered address does not refer to a key. - Vložená adresa nezodpovedá žiadnemu kľúcu. + Unit to show amounts in. Click to select another unit. + Jednotka pre zobrazovanie súm. Kliknite pre zvolenie inej jednotky. + + + bitcoin-core - Wallet unlock was cancelled. - Odomknutie peňaženky bolo zrušené. + Options: + Možnosti: - Private key for the entered address is not available. - Súkromný kľúč pre vložená adresu nieje k dispozícii. + Specify data directory + Určiť priečinok s dátami - Message signing failed. - Podpísanie správy zlyhalo. + Connect to a node to retrieve peer addresses, and disconnect + Pripojiť sa k uzlu, získať adresy ďalších počítačov v sieti a odpojiť sa - Message signed. - Správa podpísaná. + Specify your own public address + Určite vašu vlastnú verejnú adresu - The signature could not be decoded. - Podpis nie je možné dekódovať. + Accept command line and JSON-RPC commands + Prijímať príkazy z príkazového riadku a JSON-RPC - Please check the signature and try again. - Prosím skontrolujte podpis a skúste znova. + Error: A fatal internal error occurred, see debug.log for details + Chyba: Vyskytla sa interná chyba, pre viac informácií zobrazte debug.log - The signature did not match the message digest. - Podpis sa nezhoduje so zhrnutím správy + Fee (in %s/kB) to add to transactions you send (default: %s) + Poplatok (za %s/kB) pridaný do tranzakcie, ktorú posielate (predvolené: %s) - Message verification failed. - Overenie správy zlyhalo. + Pruning blockstore... + Redukovanie blockstore... - Message verified. - Správa overená. + Run in the background as a daemon and accept commands + Bežať na pozadí ako démon a prijímať príkazy - - - SplashScreen - Bitcoin Core - Jadro Bitcoin + Unable to start HTTP server. See debug log for details. + Nepodarilo sa spustiť HTTP server. Pre viac detailov zobrazte debug log. - The Bitcoin Core developers - Vývojári jadra Bitcoin + Accept connections from outside (default: 1 if no -proxy or -connect) + Prijať spojenia zvonku (predvolené: 1 ak žiadne -proxy alebo -connect) - [testnet] - [testovacia sieť] - - - - TrafficGraphWidget - - KB/s - KB/s - - - - TransactionDesc - - Open until %1 - Otvorené do %1 - - - conflicted - sporné - - - %1/offline - %1/offline - - - %1/unconfirmed - %1/nepotvrdené - - - %1 confirmations - %1 potvrdení - - - Status - Stav - - - , broadcast through %n node(s) - , vysielať cez %n uzol, vysielať cez %n uzle, vysielať cez %n uzolov - - - Date - Dátum - - - Source - Zdroj - - - Generated - Vygenerované - - - From - od - - - To - Pre - - - own address - vlastná adresa - - - watch-only - Iba sledovanie - - - label - popis - - - Credit - Kredit - - - not accepted - neprijaté - - - Debit - Debet - - - Total debit - Debit spolu - - - Total credit - Kredit spolu - - - Transaction fee - Transakčný poplatok - - - Net amount - Suma netto - - - Message - Správa - - - Comment - Komentár - - - Transaction ID - ID transakcie - - - Merchant - Kupec - - - 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. - Vygenerované mince musia dospieť %1 blokov kým môžu byť minuté. Keď vytvoríte tento blok, bude rozoslaný do siete aby bol akceptovaný do reťaze blokov. Ak sa nedostane do reťazca, jeho stav sa zmení na "zamietnutý" a nebude sa dať minúť. Toto sa môže občas stať ak iný uzol vytvorí blok približne v rovnakom čase. - - - Debug information - Ladiace informácie - - - Transaction - Transakcie - - - Inputs - Vstupy - - - Amount - Suma - - - true - pravda - - - false - nepravda - - - , has not been successfully broadcast yet - , ešte nebola úspešne odoslaná - - - Open for %n more block(s) - Otvorené pre %n ďalší blokOtvorené pre %n ďalšie blokyOtvorené pre %n ďalších blokov - - - unknown - neznámy - - - - TransactionDescDialog - - Transaction details - Detaily transakcie - - - This pane shows a detailed description of the transaction - Táto časť obrazovky zobrazuje detailný popis transakcie - - - - TransactionTableModel - - Date - Dátum - - - Type - Typ - - - Immature (%1 confirmations, will be available after %2) - Nezrelé (%1 potvrdení, bude k dispozícii po %2) - - - Open for %n more block(s) - Otvorené pre %n ďalší blokOtvorené pre %n ďalšie blokyOtvorené pre %n ďalších blokov - - - Open until %1 - Otvorené do %1 - - - Confirmed (%1 confirmations) - Potvrdené (%1 potvrdení) - - - This block was not received by any other nodes and will probably not be accepted! - Ten blok nebol prijatý žiadnou inou nódou a pravdepodobne nebude akceptovaný! - - - Generated but not accepted - Vygenerované ale neakceptované - - - Offline - Offline - - - Label - Popis - - - Unconfirmed - Nepotvrdené - - - Confirming (%1 of %2 recommended confirmations) - Potvrdzuje sa ( %1 z %2 odporúčaných potvrdení) - - - Conflicted - V rozpore - - - Received with - Prijaté s - - - Received from - Prijaté od: - - - Sent to - Odoslané na - - - Payment to yourself - Platba sebe samému - - - Mined - Vyťažené - - - watch-only - Iba sledovanie - - - (n/a) - (n/a) - - - Transaction status. Hover over this field to show number of confirmations. - Status transakcie. Pohybujte myšou nad týmto poľom a zjaví sa počet potvrdení. - - - Date and time that the transaction was received. - Dátum a čas prijatia transakcie. - - - Type of transaction. - Typ transakcie. - - - Whether or not a watch-only address is involved in this transaction. - Či sú ale nie sú, adresy iba na sledovanie zahrnuté v tejto transakcii. - - - Amount removed from or added to balance. - Suma pridaná alebo odobraná k zostatku. - - - - TransactionView - - All - Všetko - - - Today - Dnes - - - This week - Tento týždeň - - - This month - Tento mesiac - - - Last month - Minulý mesiac - - - This year - Tento rok - - - Range... - Rozsah... - - - Received with - Prijaté s - - - Sent to - Odoslané na - - - To yourself - Samému sebe - - - Mined - Vyťažené - - - Other - Iné - - - Enter address or label to search - Vložte adresu alebo popis pre vyhľadávanie - - - Min amount - Min množstvo - - - Copy address - Kopírovať adresu - - - Copy label - Kopírovať popis - - - Copy amount - Kopírovať sumu - - - Copy transaction ID - Kopírovať ID transakcie - - - Copy raw transaction - Kopírovať celú tranzakciu - - - Edit label - Editovať popis - - - Show transaction details - Zobraziť podrobnosti transakcie - - - Export Transaction History - Exportovať históriu transakcií - - - Watch-only - Iba sledovanie - - - Exporting Failed - Export zlyhal - - - There was an error trying to save the transaction history to %1. - Vyskytla sa chyba pri pokuse o uloženie histórie transakcií do %1. - - - Exporting Successful - Export úspešný - - - The transaction history was successfully saved to %1. - História transakciá bola úspešne uložená do %1. - - - Comma separated file (*.csv) - Čiarkou oddelovaný súbor (*.csv) - - - Confirmed - Potvrdené - - - Date - Dátum - - - Type - Typ - - - Label - Popis - - - Address - Adresa - - - ID - ID - - - Range: - Rozsah: - - - to - do - - - - UnitDisplayStatusBarControl - - Unit to show amounts in. Click to select another unit. - Jednotka pre zobrazovanie súm. Kliknite pre zvolenie inej jednotky. - - - - WalletFrame - - No wallet has been loaded. - Nie je načítaná peňaženka. - - - - WalletModel - - Send Coins - Poslať Bitcoins - - - - WalletView - - &Export - &Exportovať... - - - Export the data in the current tab to a file - Exportovať tento náhľad do súboru - - - Backup Wallet - Zálohovať peňaženku - - - Wallet Data (*.dat) - Údaje peňaženky (*.dat) - - - Backup Failed - Záloha zlyhala - - - There was an error trying to save the wallet data to %1. - Vyskytla sa chyba pri pokuse o uloženie dát peňaženky do %1. - - - The wallet data was successfully saved to %1. - Dáta peňaženky boli úspešne uložené do %1. - - - Backup Successful - Záloha úspešná - - - - bitcoin-core - - Options: - Možnosti: - - - Specify data directory - Určiť priečinok s dátami - - - Connect to a node to retrieve peer addresses, and disconnect - Pripojiť sa k uzlu, získať adresy ďalších počítačov v sieti a odpojiť sa - - - Specify your own public address - Určite vašu vlastnú verejnú adresu - - - Accept command line and JSON-RPC commands - Prijímať príkazy z príkazového riadku a JSON-RPC - - - Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. - Skontrolujte správnosť nastavenia dátumu a času na vašom počítači! Ak je čas nesprávny Jadro Bitcoin nebude správne fungovať. - - - Error: A fatal internal error occurred, see debug.log for details - Chyba: Vyskytla sa interná chyba, pre viac informácií zobrazte debug.log - - - Fee (in %s/kB) to add to transactions you send (default: %s) - Poplatok (za %s/kB) pridaný do tranzakcie, ktorú posielate (predvolené: %s) - - - Pruning blockstore... - Redukovanie blockstore... - - - Run in the background as a daemon and accept commands - Bežať na pozadí ako démon a prijímať príkazy - - - Unable to start HTTP server. See debug log for details. - Nepodarilo sa spustiť HTTP server. Pre viac detailov zobrazte debug log. - - - Accept connections from outside (default: 1 if no -proxy or -connect) - Prijať spojenia zvonku (predvolené: 1 ak žiadne -proxy alebo -connect) + Bitcoin Core + Jadro Bitcoin Bind to given address and always listen on it. Use [host]:port notation for IPv6 @@ -2952,10 +1707,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Toto je pred-testovacia verzia - použitie je na vlastné riziko - nepoužívajte na tvorbu bitcoin ani obchodovanie. - - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - Nepodarilo sa pripojiť na %s na tomto počítači. Bitcoin Jadro je už pravdepodobne spustené. - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) VAROVANIE: príliš veľa vygenerovaných blokov; %d prijatých blokov v posledných %d hodinách (očakávaných %d) @@ -2974,10 +1725,6 @@ The network does not appear to fully agree! Some miners appear to be experiencin Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Varovanie: Zjavne sa úplne nezhodujeme s našimi peer-mi! Možno potrebujete prejsť na novšiu verziu alebo ostatné uzly potrebujú vyššiu verziu. - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Varovanie: wallet.dat je poškodený, údaje úspešne získané! Pôvodný wallet.dat uložený ako wallet.{timestamp}.bak v %s; ak váš zostatok alebo transakcie niesu správne, mali by ste súbor obnoviť zo zálohy. - Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. Uzle na zoznam povolených, ktoré sa pripájajú z danej netmask alebo IP adresy. Môže byť zadané viac krát. @@ -3038,6 +1785,18 @@ The network does not appear to fully agree! Some miners appear to be experiencin Error initializing wallet database environment %s! Chyba spustenia databázového prostredia peňaženky %s! + + Error loading %s + Chyba načítania %s + + + Error loading %s: Wallet corrupted + Chyba načítania %s: Peňaženka je poškodená + + + Error loading %s: Wallet requires newer version of %s + Chyba načítania %s: Peňaženka vyžaduje novšiu verziu %s + Error loading block database Chyba načítania databázy blokov @@ -3066,10 +1825,18 @@ The network does not appear to fully agree! Some miners appear to be experiencin Invalid -onion address: '%s' Neplatná -onion adresa: '%s' + + Invalid amount for -%s=<amount>: '%s' + Neplatná suma pre -%s=<amount>: '%s' + Invalid amount for -fallbackfee=<amount>: '%s' Neplatná suma pre -fallbackfee=<amount>: '%s' + + Loading banlist... + Načítavam banlist... + Not enough file descriptors available. Nedostatok kľúčových slov súboru. @@ -3130,10 +1897,6 @@ The network does not appear to fully agree! Some miners appear to be experiencin Wallet options: Voľby peňaženky: - - You need to rebuild the database using -reindex to change -txindex - Potrebujete prebudovať databázu použitím -reindex zmeniť -txindex - 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 Povoliť JSON-RPC pripojenia zo zadaného zdroja. Pre <ip> sú platné jednoduché IP (napr. 1.2.3.4), sieť/netmask (napr. 1.2.3.4/255.255.255.0) alebo sieť/CIDR (napr. 1.2.3.4/24). Táto možnosť môže byť zadaná niekoľko krát @@ -3146,10 +1909,6 @@ The network does not appear to fully agree! Some miners appear to be experiencin Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces) Spojiť s danou adresou pre počúvanie JSON-RPC spojení. Použite zápis [host]:port pre IPv6. Táto možnosť môže byt zadaná niekoľko krát (predvolené: spojiť so všetkými rozhraniami) - - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - Neviem uzamknúť data adresár %s. Jadro Bitcoin je pravdepodobne už spustené. - Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) Vytvoriť nové súbory z predvolenými systémovými právami, namiesto umask 077 (funguje iba z vypnutou funkcionalitou peňaženky) @@ -3186,10 +1945,6 @@ The network does not appear to fully agree! Some miners appear to be experiencin Set maximum size of high-priority/low-fee transactions in bytes (default: %d) Nastaviť najväčšiu veľkosť vysoká-dôležitosť/nízke-poplatky transakcií v bajtoch (prednastavené: %d) - - Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) - Nastaviť počet vlákien pre generáciu mincí (-1 = všetky jadrá, predvolené: %d) - The transaction amount is too small to send after the fee has been deducted Suma je príliš malá pre odoslanie tranzakcie @@ -3210,34 +1965,14 @@ The network does not appear to fully agree! Some miners appear to be experiencin Accept public REST requests (default: %u) Akceptovať verejné REST žiadosti (predvolené: %u) - - Activating best chain... - Aktivácia najlepšej reťaze... - - - Attempt to recover private keys from a corrupt wallet.dat on startup - Pokus o obnovenie privátnych kľúčov z poškodenej wallet.dat pri spustení - Automatically create Tor hidden service (default: %d) Automaticky vytvoriť skrytú službu Tor (predvolené: %d) - - Cannot resolve -whitebind address: '%s' - Nedá sa vyriešiť -whitebind adresa: '%s' - Connect through SOCKS5 proxy Pripojiť cez proxy server SOCKS5 - - Copyright (C) 2009-%i The Bitcoin Core Developers - Autorské práva (C) 2009-%i Vývojári jadra Bitcoin - - - Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - Chyba pri čítaní wallet.dat: Peňaženka vyžaduje vyššiu verziu Jadra Bitcoin - Error reading from database, shutting down. Chyba pri načítaní z databázy, ukončuje sa. @@ -3250,22 +1985,6 @@ The network does not appear to fully agree! Some miners appear to be experiencin Information Informácia - - Initialization sanity check failed. Bitcoin Core is shutting down. - Inicializačná kontrola zlyhala. Jadro Bitcoin sa ukončuje. - - - Invalid amount for -maxtxfee=<amount>: '%s' - Neplatná suma pre -maxtxfee=<amount>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Neplatná suma pre -minrelaytxfee=<amount>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - Neplatná suma pre -mintxfee=<amount>: '%s' - Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) Neplatná suma pre -paytxfee=<amount>: '%s' (musí byť aspoň %s) @@ -3290,10 +2009,6 @@ The network does not appear to fully agree! Some miners appear to be experiencin RPC server options: Možnosti servra RPC: - - Receive and display P2P network alerts (default: %u) - Obdržať a zobraziť sieťové P2P varovania (predvolené: %u) - Send trace/debug info to console instead of debug.log file Odoslať trace/debug informácie na konzolu namiesto debug.info žurnálu @@ -3354,10 +2069,6 @@ The network does not appear to fully agree! Some miners appear to be experiencin Username for JSON-RPC connections Užívateľské meno pre JSON-RPC spojenia - - Wallet needed to be rewritten: restart Bitcoin Core to complete - Peňaženka musí byť prepísaná: pre dokončenie reštartujte Jadro Bitcoin - Warning Upozornenie @@ -3366,10 +2077,6 @@ The network does not appear to fully agree! Some miners appear to be experiencin Zapping all transactions from wallet... Zmazať všetky transakcie z peňaženky... - - wallet.dat corrupt, salvage failed - wallet.dat je poškodený, záchrana zlyhala - Password for JSON-RPC connections Heslo pre JSON-rPC spojenia @@ -3378,10 +2085,6 @@ The network does not appear to fully agree! Some miners appear to be experiencin Execute command when the best block changes (%s in cmd is replaced by block hash) Vykonaj príkaz, ak zmeny v najlepšom bloku (%s v príkaze nahradí blok hash) - - This help message - Táto pomocná správa - Allow DNS lookups for -addnode, -seednode and -connect Povoliť vyhľadávanie DNS pre pridanie nódy a spojenie @@ -3390,10 +2093,6 @@ The network does not appear to fully agree! Some miners appear to be experiencin Loading addresses... Načítavanie adries... - - Error loading wallet.dat: Wallet corrupted - Chyba načítania wallet.dat: Peňaženka je poškodená - (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) (1 = zachovať metaúdaje tx napr. vlastníka účtu a informácie o platobných príkazoch, 2 = zahodiť metaúdaje tx) @@ -3426,14 +2125,6 @@ The network does not appear to fully agree! Some miners appear to be experiencin Always query for peer addresses via DNS lookup (default: %u) Vždy sa dotazovať adresy partnerských uzlov cez vyhľadávanie DNS (predvolené: %u) - - Error loading wallet.dat - Chyba načítania wallet.dat - - - Generate coins (default: %u) - Generovať mince (predvolené: %u) - How many blocks to check at startup (default: %u, 0 = all) Koľko blokov overiť pri spustení (predvolené: %u, 0 = všetky) @@ -3514,18 +2205,6 @@ The network does not appear to fully agree! Some miners appear to be experiencin Unknown network specified in -onlynet: '%s' Neznáma sieť upresnená v -onlynet: '%s' - - Cannot resolve -bind address: '%s' - Nemožno rozriešiť -bind adress: '%s' - - - Cannot resolve -externalip address: '%s' - Nemožno rozriešiť -externalip address: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - Neplatná suma pre -paytxfee=<amount>: '%s' - Insufficient funds Nedostatok prostriedkov diff --git a/src/qt/locale/bitcoin_sl_SI.ts b/src/qt/locale/bitcoin_sl_SI.ts index 1b540a7310f08..155be7bb27144 100644 --- a/src/qt/locale/bitcoin_sl_SI.ts +++ b/src/qt/locale/bitcoin_sl_SI.ts @@ -25,10 +25,6 @@ C&lose &Zapri - - &Copy Address - &Kopiraj naslov - Delete the currently selected address from the list Izbriši trenutno označeni naslov iz seznama @@ -45,73 +41,6 @@ &Delete I&zbriši - - Choose the address to send coins to - Izbira naslova, na katerega pošiljate plačilo - - - Choose the address to receive coins with - Izbira naslova za prejem plačila - - - C&hoose - &Izberi - - - Sending addresses - Imenik naslovov za pošiljanje - - - Receiving addresses - Imenik naslovov za prejemanje - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - To je vaš imenik shranjenih naslovov Bitcoin, na katere lahko pošiljate plačila. Pred vsakim odlivom vedno preverite, če sta znesek in prejemnikov naslov pravilna. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - To je imenik vaših ustvarjenih naslovov Bitcoin, na katere lahko prejemate plačila. Priporočljivo je, da za vsak nov priliv ustvarite nov prejemni naslov. - - - Copy &Label - Kopiraj &oznako - - - &Edit - &Uredi - - - Export Address List - Izvozi seznam naslovov - - - Comma separated file (*.csv) - Datoteka s podatki, ločenimi z vejico (*.csv) - - - Exporting Failed - Seznama naslovov ni bilo mogoče izvoziti. - - - There was an error trying to save the address list to %1. Please try again. - Napaka pri shranjevanju seznama naslovov v datoteko %1. Prosimo, poskusite znova. - - - - AddressTableModel - - Label - Oznaka - - - Address - Naslov - - - (no label) - (brez oznake) - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase Ponovite novo geslo - - Encrypt wallet - Šifriraj denarnico - - - This operation needs your wallet passphrase to unlock the wallet. - To dejanje zahteva geslo za odklepanje vaše denarnice. - - - Unlock wallet - Odkleni denarnico - - - This operation needs your wallet passphrase to decrypt the wallet. - To dejanje zahteva geslo za dešifriranje vaše denarnice. - - - Decrypt wallet - Dešifriraj denarnico - - - Change passphrase - Zamenjaj geslo - - - Confirm wallet encryption - Potrditev šifriranja denarnice - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Opozorilo: V primeru izgube gesla šifrirane denarnice, boste <b>IZGUBILI VSE BITCOINE V DENARNICI</b>! - - - Are you sure you wish to encrypt your wallet? - Ali ste prepričani, da želite šifrirati vašo denarnico? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Program se bo zaprl, da dokonča proces šifriranja. Zapomnite si, da šifriranje ne more popolnoma zaščititi vaše denarnice pred krajami in zlonamernimi programi, ki bi lahko bili nameščeni na vašem računalniku. - - - 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. - POMEMBNO: Vse starejše obstoječe varnostne kopije denarnice je potrebno zamenjati s to novo, šifrirano varnostno kopijo. Iz varnostnih razlogov bodo stare varnostne kopije postale neuporabne takoj, ko začnete uporabljati novo, šifrirano denarnico. - - - Warning: The Caps Lock key is on! - Opozorilo: imate vklopljene velike črke (Caps Lock) - - - Wallet encrypted - Denarnica je šifrirana - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Vnesite novo geslo. Prosimo, da uporabite geslo sestavljeno iz <b>deset ali več</b> naključnih znakov, ali <b>osem ali več</b> besed. - - - Enter the old passphrase and new passphrase to the wallet. - Vnesite staro in novo geslo denarnice. - - - Wallet encryption failed - Denarnice ni bilo mogoče šifrirati. - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Prišlo je do napake. Denarnice ni bilo mogoče šifrirati. - - - The supplied passphrases do not match. - Vnešeni gesli se ne ujemata - - - Wallet unlock failed - Denarnice ni bilo mogoče odkleniti. - - - The passphrase entered for the wallet decryption was incorrect. - Vnesli ste napačno geslo za dešifriranje denarnice. - - - Wallet decryption failed - Denarnice ni bilo mogoče dešifrirati. - - - Wallet passphrase was successfully changed. - Geslo za dostop do denarnice je bilo uspešno zamenjano. - BanTableModel @@ -297,14 +138,6 @@ Open &URI... Odpri &URI ... - - Bitcoin Core client - Odjemalec Bitcoin Core - - - Importing blocks from disk... - Uvažam bloke z diska ... - Reindexing blocks on disk... Poustvarjam kazalo blokov na disku ... @@ -349,10 +182,6 @@ &Receive P&rejmi - - Show information about Bitcoin Core - Oglejte si informacije o programu - &Show / Hide &Prikaži / Skrij @@ -389,22 +218,10 @@ Tabs toolbar Orodna vrstica zavihkov - - Bitcoin Core - Bitcoin Core - Request payments (generates QR codes and bitcoin: URIs) Zahtevajte plačilo (ustvarite zahtevek s kodo QR in URI tipa bitcoin:) - - &About Bitcoin Core - &O programu - - - Modify configuration options for Bitcoin Core - Spremenite programske nastavitve - Show the list of used sending addresses and labels Preglejte in uredite seznam naslovov, na katere ste kdaj poslali plačila @@ -421,10 +238,6 @@ &Command-line options Opcije &ukazne vrstice - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Oglejte si seznam in kratek opis vseh opcij pri zagonu programa iz ukazne vrstice - %n active connection(s) to Bitcoin network %n aktivna povezava v omrežje Bitcoin%n aktivni povezavi v omrežje Bitcoin%n aktivne povezave v omrežje Bitcoin%n aktivnih povezav v omrežje Bitcoin @@ -439,7 +252,7 @@ %n hour(s) - %n ura%n uri%n ure%n ur + %n uro%n uri%n ure%n ur %n day(s) @@ -536,13 +349,6 @@ Denarnica je <b>šifrirana</b> in trenutno <b>zaklenjena</b> - - ClientModel - - Network Alert - Omrežno opozorilo - - CoinControlDialog @@ -621,150 +427,6 @@ Priority Prioriteta - - Copy address - Kopiraj naslov - - - Copy label - Kopiraj oznako - - - Copy amount - Kopiraj znesek - - - Copy transaction ID - Kopiraj ID transakcije - - - Lock unspent - Zakleni neporabljeno - - - Unlock unspent - Odkleni neporabljeno - - - Copy quantity - Kopiraj število vhodov - - - Copy fee - Kopiraj znesek provizije - - - Copy after fee - Kopiraj končni znesek - - - Copy bytes - Kopiraj število bajtov - - - Copy priority - Kopiraj prioriteto - - - Copy dust - Kopiraj prah - - - Copy change - Kopiraj znesek vračila - - - highest - najvišja - - - higher - višja - - - high - visoka - - - medium-high - srednje visoka - - - medium - srednja - - - low-medium - srednje nizka - - - low - nizka - - - lower - nižja - - - lowest - najnižja - - - (%1 locked) - (%1 zaklenjeno) - - - none - nič - - - This label turns red if the transaction size is greater than 1000 bytes. - Oznaka postane rdeča, če je transakcije večja od 1000 bajtov. - - - This label turns red if the priority is smaller than "medium". - Oznaka postane rdeča, če je prioriteta transakcije manjša kot "srednja". - - - This label turns red if any recipient receives an amount smaller than %1. - Oznaka postane rdeča, če je znesek manjši od %1. - - - Can vary +/- %1 satoshi(s) per input. - Lahko variira +/- %1 satoshijev na vhod. - - - yes - da - - - no - ne - - - This means a fee of at least %1 per kB is required. - To pomeni, da je zahtevana provizija v višini vsaj %1 na KiB. - - - Can vary +/- 1 byte per input. - Lahko variira +/-1 bajt na vhod. - - - Transactions with higher priority are more likely to get included into a block. - Transakcije z višjo prioriteto imajo boljše možnosti za vključitev v blok. - - - (no label) - (brez oznake) - - - change from %1 (%2) - vračilo od %1 (%2) - - - (change) - (vračilo) - EditAddressDialog @@ -788,38 +450,6 @@ &Address &Naslov - - New receiving address - Nov naslov za prilive - - - New sending address - Nov naslov za odlive - - - Edit receiving address - Uredi naslov za prilive - - - Edit sending address - Uredi naslov za odlive - - - The entered address "%1" is already in the address book. - Vnešeni naslov %1 je že v imeniku. - - - The entered address "%1" is not a valid Bitcoin address. - Vnešeni naslov %1 ni veljaven naslov Bitcoin. - - - Could not unlock wallet. - Denarnice ni bilo mogoče odkleniti. - - - New key generation failed. - Novega ključa ni bilo mogoče ustvariti. - FreespaceChecker @@ -846,10 +476,6 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin Core - version različica @@ -858,10 +484,6 @@ (%1-bit) (%1-bit) - - About Bitcoin Core - O programu Bitcoin Core - Command-line options Možnosti ukazne vrstice @@ -881,18 +503,6 @@ Welcome Dobrodošli - - Welcome to Bitcoin Core. - Dobrodošli v programu Bitcoin Core. - - - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - To je prvi zagon programa, zato lahko izberete mapo, v katero bo program shranjeval podatke. - - - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - Program bo prenesel in shranil kopijo verige blokov. V izbrani podatkovni mapi bo shranjenih vsaj %1 GiB podatkov, ta količina pa bo sčasoma še naraščala. V tej mapi bo shranjena tudi denarnica. - Use the default data directory Uporabi privzeto podatkovno mapo @@ -901,10 +511,6 @@ Use a custom data directory: Uporabi to podatkovno mapo: - - Bitcoin Core - Bitcoin Core - Error: Specified data directory "%1" cannot be created. Napaka: Ni mogoče ustvariti mape "%1". @@ -940,10 +546,6 @@ Select payment request file Izbiranje datoteke z zahtevkom za plačilo - - Select payment request file to open - Izberite datoteko, ki vsebuje zahtevek za plačilo - OptionsDialog @@ -983,10 +585,6 @@ 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. Ko zaprete glavno okno programa, bo program tekel še naprej, okno pa bo zgolj minimirano. Program v tem primeru ustavite tako, da v meniju izberete ukaz Izhod. - - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - Nastavitev jezika uporabniškega vmesnika programa. Nova nastavitev jezika bo uporabljena šele, ko boste znova zagnali program. - 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 |. Naslovi URL tretjih oseb (npr. raziskovalec blokov), ki bodo navedeni v kontekstnem meniju seznama transakcij. Niz %s iz naslova URL je nadomeščen s hash vrednostjo transakcije. Več zaporednih naslovov URL je med seboj ločenih z znakom |. @@ -1011,14 +609,6 @@ &Network &Omrežje - - Automatically start Bitcoin Core after logging in to the system. - Ob uporabnikovi prijavi v sistem se bo program samodejno zagnal - - - &Start Bitcoin Core on system login - &Zaženi program ob prijavi v sistem - (0 = auto, <0 = leave that many cores free) (0 = samodejno, <0 = toliko procesorskih jeder naj ostane prostih) @@ -1224,190 +814,80 @@ - PaymentServer + PeerTableModel - URI handling - Rokovanje z URI + User Agent + Ime agenta - Invalid payment address %1 - Neveljaven naslov plačila %1 + Node/Service + Naslov - Payment request rejected - Zahtevek za plačilo je bil zavrnjen. + Ping Time + Odzivni čas + + + QObject - Payment request network doesn't match client network. - Zahtevek za plačilo in vaš odjemalec se nahajata na dveh različnih omrežjih. + Amount + Znesek - Payment request is not initialized. - Zahtevek za plačilo ni inicializiran. + Enter a Bitcoin address (e.g. %1) + Vnesite naslov Bitcoin (npr. %1): - Requested payment amount of %1 is too small (considered dust). - Znesek %1 v zahtevku za plačilo je prenizek (smatran za prah.) + %1 d + %1 d - Payment request error - Napaka pri zahtevku za plačilo + %1 h + %1 h - Cannot start bitcoin: click-to-pay handler - Ni mogoče zagnati rokovalca plačilnih povezav tipa bitcoin:. + %1 m + %1 m - Payment request fetch URL is invalid: %1 - Naslov URL za pridobitev zahtevka za plačilo ni veljaven: %1 + %1 s + %1 s - URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - URI je neprepoznaven! Možno je, da je naslov Bitcoin neveljaven, ali da so parametri v URI napačno oblikovani. + None + Nič - Payment request file handling - Rokovanje z datoteko z zahtevkom za plačilo + N/A + Neznano - Payment request file cannot be read! This can be caused by an invalid payment request file. - Datoteke z zahtevkom za plačilo ni mogoče prebrati! Možno je, da datoteka ni veljavna. + %1 ms + %1 ms + + + RPCConsole - Payment request expired. - Zahtevek za plačilo je potekel. + Client name + Ime odjemalca - Unverified payment requests to custom payment scripts are unsupported. - Nepreverjeni zahtevki za plačilo, namenjeni plačilni skripti po meri, niso podprti. + N/A + Neznano - Invalid payment request. - Neveljaven zahtevek za plačilo. + Client version + Različica odjemalca - Refund from %1 - Povračilo od %1 + &Information + &Informacije - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - Zahtevek za plačilo %1 je prevelik (%2 bajtov, dovoljenih je %3 bajtov.) - - - Error communicating with %1: %2 - Napaka pri povezavi z %1: %2 - - - Payment request cannot be parsed! - Zahtevek za plačilo je neprepoznaven! - - - Bad response from server %1 - Napačen odziv strežnika %1 - - - Payment acknowledged - Plačilo priznano - - - Network request error - Napaka omrežne zahteve - - - - PeerTableModel - - User Agent - Ime agenta - - - Node/Service - Naslov - - - Ping Time - Odzivni čas - - - - QObject - - Amount - Znesek - - - Enter a Bitcoin address (e.g. %1) - Vnesite naslov Bitcoin (npr. %1): - - - %1 d - %1 d - - - %1 h - %1 h - - - %1 m - %1 m - - - %1 s - %1 s - - - None - Nič - - - N/A - Neznano - - - %1 ms - %1 ms - - - - QRImageWidget - - &Save Image... - &Shrani sliko ... - - - &Copy Image - &Kopiraj sliko - - - Save QR Code - Shrani kodo QR - - - PNG Image (*.png) - PNG slika (*.png) - - - - RPCConsole - - Client name - Ime odjemalca - - - N/A - Neznano - - - Client version - Različica odjemalca - - - &Information - &Informacije - - - Debug window - Razhroščevalno okno + Debug window + Razhroščevalno okno General @@ -1441,10 +921,6 @@ Current number of blocks Trenutno število blokov - - Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. - Odpre razhroščevalni dnevnik debug.log, ki se nahaja v trenutni podatkovni mapi. Če je datoteka velika, lahko postopek traja nekaj sekund. - Received Prejeto @@ -1533,10 +1009,6 @@ Out: Odhodnih: - - Build date - Datum izgradnje - Debug log file Razhroščevalni dnevnik @@ -1545,10 +1017,6 @@ Clear console Počisti konzolo - - Welcome to the Bitcoin Core RPC console. - Dobrodošli v konzoli RPC programa Bitcoin Core. - Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. Uporabite tipki gor in dol za navigacijo po zgodovini ukazov. Uporabite <b>Ctrl-L</b> za izbris zaslona in zgodovine ukazov. @@ -1672,18 +1140,6 @@ Remove Odstrani - - Copy label - Kopiraj oznako - - - Copy message - Kopiraj sporočilo - - - Copy amount - Kopiraj znesek - ReceiveRequestDialog @@ -1703,73 +1159,6 @@ &Save Image... &Shrani sliko ... - - Request payment to %1 - Zahtevek za plačilo z oznako: %1 - - - Payment information - Informacije o plačilu - - - URI - URI - - - Address - Naslov - - - Amount - Znesek - - - Label - Oznaka - - - Message - Sporočilo - - - Resulting URI too long, try to reduce the text for label / message. - Nastali URI je predolg. Skušajte skrajšati besedilo v oznaki/sporočilu. - - - Error encoding URI into QR Code. - Napaka pri pretvorbi URI v kodo QR. - - - - RecentRequestsTableModel - - Date - Datum - - - Label - Oznaka - - - Message - Sporočilo - - - Amount - Znesek - - - (no label) - (brez oznake) - - - (no message) - (brez sporočila) - - - (no amount) - (brez zneska) - SendCoinsDialog @@ -1889,14 +1278,6 @@ fast hitro - - Send as zero-fee transaction if possible - Pošlji brez provizije, če je mogoče - - - (confirmation may take longer) - (čas do potrditve je lahko daljši) - Send to multiple recipients at once Pošlji več prejemnikom hkrati @@ -1929,110 +1310,6 @@ S&end &Pošlji - - Confirm send coins - Potrdi pošiljanje - - - %1 to %2 - %1 na %2 - - - Copy quantity - Kopiraj število vhodov - - - Copy amount - Kopiraj znesek - - - Copy fee - Kopiraj provizijo - - - Copy after fee - Kopiraj Po proviziji - - - Copy bytes - Kopiraj bajte - - - Copy priority - Kopiraj prioriteto - - - Copy change - Kopiraj vračilo - - - or - ali - - - The amount to pay must be larger than 0. - Znesek za plačilo mora biti večji od 0. - - - The amount exceeds your balance. - Znesek je večji od stanja sredstev, s katerimi razpolagate. - - - The total exceeds your balance when the %1 transaction fee is included. - Celotni znesek z vključeno provizijo %1 je večji od stanja sredstev, s katerimi razpolagate. - - - Transaction creation failed! - Transakcije ni bilo mogoče ustvariti! - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - Transakcija je bila zavrnjena! To se lahko zgodi, če so bili kateri od kovancev iz denarnice že porabljeni, kot v primeru, da ste kje uporabili kopijo datoteke wallet.dat in kovance tam že porabili, lokalno pa ti še niso bili označeni kot porabljeni. - - - A fee higher than %1 is considered an absurdly high fee. - Provizija, višja od %1, velja za nesmiselno visoko. - - - Payment request expired. - Zahtevek za plačilo je potekel. - - - Estimated to begin confirmation within %n block(s). - Predviden začetek potrditev po %n najdenem bloku.Predviden začetek potrditev po %n najdenih blokih.Predviden začetek potrditev po %n najdenih blokih.Predviden začetek potrditev po %n najdenih blokih. - - - The recipient address is not valid. Please recheck. - Naslov prejemnika je neveljaven. Prosimo, preverite. - - - Duplicate address found: addresses should only be used once each. - Naslov je že bil uporabljen. Vsak naslov naj bi se uporabil samo enkrat. - - - Warning: Invalid Bitcoin address - Opozorilo: Neveljaven bitcoin naslov - - - (no label) - (brez oznake) - - - Warning: Unknown change address - Opozorilo: Neznan naslov za vračilo drobiža - - - Copy dust - Kopiraj prah - - - Are you sure you want to send? - Ali ste prepričani, da želite izvesti plačilo? - - - added as transaction fee - dodano kot provizija transakcije - SendCoinsEntry @@ -2044,10 +1321,6 @@ Pay &To: Prejemnik &plačila: - - Enter a label for this address to add it to your address book - Vnesite oznako, pod katero bo zgornji naslov shranjen v imenik - &Label: &Oznaka: @@ -2119,10 +1392,6 @@ ShutdownWindow - - Bitcoin Core is shutting down... - Program se ustavlja ... - Do not shut down the computer until this window disappears. Dokler to okno ne izgine, ne zaustavljajte računalnika. @@ -2214,582 +1483,72 @@ Reset all verify message fields Počisti vsa polja za vnos v oknu za preverjanje + + + SplashScreen - Click "Sign Message" to generate signature - Kliknite "Podpiši sporočilo" da ustvarite podpis + [testnet] + [testnet] + + + TrafficGraphWidget - The entered address is invalid. - Vnešeni naslov ni veljaven. + KB/s + KiB/s + + + TransactionDescDialog - Please check the address and try again. - Prosimo preverite naslov in poskusite znova. + This pane shows a detailed description of the transaction + V tem podoknu so prikazane podrobnosti o transakciji + + + UnitDisplayStatusBarControl - The entered address does not refer to a key. - Vnešeni naslov se ne nanaša na noben ključ. + Unit to show amounts in. Click to select another unit. + Merska enota za prikaz zneskov. Kliknite za izbiro druge enote. + + + bitcoin-core - Wallet unlock was cancelled. - Odklepanje denarnice je bilo preklicano. + Options: + Možnosti: - Private key for the entered address is not available. - Zasebni ključ vnešenega naslova ni na voljo. + Specify data directory + Izberite podatkovno mapo - Message signing failed. - Podpisa ni bilo mogoče ustvariti. + Connect to a node to retrieve peer addresses, and disconnect + Povežite se z vozliščem za pridobitev naslovov soležnikov in nato prekinite povezavo. - Message signed. - Podpis je bil ustvarjen. + Specify your own public address + Določite vaš lasten javni naslov - The signature could not be decoded. - Podpisa ni bilo mogoče razbrati. + Accept command line and JSON-RPC commands + Sprejemaj ukaze iz ukazne vrstice in preko JSON-RPC - Please check the signature and try again. - Prosimo preverite podpis in poskusite znova. + Run in the background as a daemon and accept commands + Teci v ozadju in sprejemaj ukaze - The signature did not match the message digest. - Podpis se ne ujema z rezultatom funkcije preverjanja. + Accept connections from outside (default: 1 if no -proxy or -connect) + Sprejemaj zunanje povezave (privzeto: 1, razen če ste vklopili opciji -proxy ali -connect) - Message verification failed. - Podpis ni veljaven za to sporočilo. + Bitcoin Core + Bitcoin Core - Message verified. - Podpis sporočila je veljaven. - - - - SplashScreen - - Bitcoin Core - Bitcoin Core - - - The Bitcoin Core developers - Bitcoin Core razvijalci - - - [testnet] - [testnet] - - - - TrafficGraphWidget - - KB/s - KiB/s - - - - TransactionDesc - - Open until %1 - Odprto do %1 - - - conflicted - v konfliktu - - - %1/offline - %1/brez povezave - - - %1/unconfirmed - %1/nepotrjeno - - - %1 confirmations - %1 potrdil - - - Status - Status - - - , broadcast through %n node(s) - , posredovano %n vozlišču, posredovano %n vozliščema, posredovano %n vozliščem, posredovano %n vozliščem - - - Date - Datum - - - Source - Izvor - - - Generated - Generirano - - - From - Pošiljatelj - - - To - Prejemnik - - - own address - lasten naslov - - - watch-only - opazovano - - - label - oznaka - - - Credit - V dobro - - - matures in %n more block(s) - dozori po %n najdenem blokudozori po %n najdenih blokihdozori po %n najdenih blokihdozori po %n najdenih blokih - - - not accepted - ni bilo sprejeto - - - Debit - Debit - - - Total debit - Skupaj v breme - - - Total credit - Skupaj v dobro - - - Transaction fee - Provizija transakcije - - - Net amount - Neto znesek - - - Message - Sporočilo - - - Comment - Opomba - - - Transaction ID - ID transakcije - - - Merchant - Trgovec - - - 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. - Ustvarjeni kovanci morajo zoreti %1 blokov, preden jih lahko porabite. Ko ste ta blok zgenerirali, je bil posredovan v omrežje, da bo dodan v verigo. Če se bloku ni uspelo uvrstiti v verigo, se bo njegovo stanje spremenilo v "ni bilo sprejeto" in kovancev ne bo mogoče porabiti. To se včasih zgodi, če kak drug rudar v roku nekaj sekund hkrati z vami odkrije drug blok. - - - Debug information - Razhroščevalne informacije - - - Transaction - Transakcija - - - Inputs - Vhodi - - - Amount - Znesek - - - true - pravilno - - - false - nepravilno - - - , has not been successfully broadcast yet - , še ni bila uspešno raznešena - - - Open for %n more block(s) - Še %n blok do potrditveŠe %n bloka do potrditveŠe %n bloki do potrditveŠe %n blokov do potrditve - - - unknown - neznano - - - - TransactionDescDialog - - Transaction details - Podrobnosti transakcije - - - This pane shows a detailed description of the transaction - V tem podoknu so prikazane podrobnosti o transakciji - - - - TransactionTableModel - - Date - Datum - - - Type - Vrsta - - - Immature (%1 confirmations, will be available after %2) - Nedozorelo (št. potrditev: %1, na voljo šele po: %2) - - - Open for %n more block(s) - Še %n blok do potrditveŠe %n bloka do potrditveŠe %n bloki do potrditveŠe %n blokov do potrditve - - - Open until %1 - Odprto do %1 - - - Confirmed (%1 confirmations) - Potrjeno (%1 potrdil) - - - This block was not received by any other nodes and will probably not be accepted! - Ta blok ni prejelo še nobeno vozlišče. Najverjetneje ne bo sprejet! - - - Generated but not accepted - Generirano, toda ne sprejeto - - - Offline - Brez povezave - - - Label - Oznaka - - - Unconfirmed - Nepotrjeno - - - Confirming (%1 of %2 recommended confirmations) - V potrjevanju (št. potrditev: %1 od priporočenih %2) - - - Conflicted - V konfliktu - - - Received with - Prejemek - - - Received from - Prejemek - - - Sent to - Izdatek - - - Payment to yourself - Nakazilo sebi - - - Mined - Narudarjeno - - - watch-only - opazovano - - - (n/a) - (ni na voljo) - - - Transaction status. Hover over this field to show number of confirmations. - Stanje transakcije. Zapeljite z miško čez to polje za prikaz števila potrdil. - - - Date and time that the transaction was received. - Datum in čas, ko je transakcija bila prejeta. - - - Type of transaction. - Vrsta transakcije. - - - Whether or not a watch-only address is involved in this transaction. - Ali je v transakciji udeležen kateri od opazovanih naslovov. - - - User-defined intent/purpose of the transaction. - Uporabniško določen namen transakcije. - - - Amount removed from or added to balance. - Znesek spremembe stanja sredstev. - - - - TransactionView - - All - Vse - - - Today - Danes - - - This week - Ta teden - - - This month - Ta mesec - - - Last month - Prejšnji mesec - - - This year - To leto - - - Range... - Območje ... - - - Received with - Prejemek - - - Sent to - Izdatek - - - To yourself - Nakazilo sebi - - - Mined - Narudarjeno - - - Other - Drugo - - - Enter address or label to search - Iščite po naslovu ali oznaki - - - Min amount - Minimalni znesek - - - Copy address - Kopiraj naslov - - - Copy label - Kopiraj oznako - - - Copy amount - Kopiraj znesek - - - Copy transaction ID - Kopiraj ID transakcije - - - Edit label - Uredi oznako - - - Show transaction details - Prikaži podrobnosti transakcije - - - Export Transaction History - Izvoz zgodovine transakcij - - - Watch-only - Opazovano - - - Exporting Failed - Seznama transakcij ni bilo mogoče izvoziti. - - - There was an error trying to save the transaction history to %1. - Prišlo je do napake med shranjevanjem zgodovine transakcij v datoteko %1. - - - Exporting Successful - Uspešen izvoz - - - The transaction history was successfully saved to %1. - Zgodovina poteklih transakcij je bila uspešno shranjena v datoteko %1. - - - Comma separated file (*.csv) - Datoteka s podatki, ločenimi z vejico (*.csv) - - - Confirmed - Potrjeno - - - Date - Datum - - - Type - Vrsta - - - Label - Oznaka - - - Address - Naslov - - - ID - ID - - - Range: - Območje: - - - to - za - - - - UnitDisplayStatusBarControl - - Unit to show amounts in. Click to select another unit. - Merska enota za prikaz zneskov. Kliknite za izbiro druge enote. - - - - WalletFrame - - No wallet has been loaded. - Denarnica ni bila naložena. - - - - WalletModel - - Send Coins - Pošlji - - - - WalletView - - &Export - &Izvozi - - - Export the data in the current tab to a file - Izvozi podatke iz trenutnega zavihka v datoteko - - - Backup Wallet - Izdelava varnostne kopije denarnice - - - Wallet Data (*.dat) - Podatki denarnice (*.dat) - - - Backup Failed - Varnostne kopije ni bilo mogoče izdelati. - - - There was an error trying to save the wallet data to %1. - Prišlo je do napake pri shranjevanju podatkov denarnice v datoteko %1. - - - The wallet data was successfully saved to %1. - Podatki iz denarnice so bili uspešno shranjeni v datoteko %1. - - - Backup Successful - Varnostna kopija je bila uspešno izdelana - - - - bitcoin-core - - Options: - Možnosti: - - - Specify data directory - Izberite podatkovno mapo - - - Connect to a node to retrieve peer addresses, and disconnect - Povežite se z vozliščem za pridobitev naslovov soležnikov in nato prekinite povezavo. - - - Specify your own public address - Določite vaš lasten javni naslov - - - Accept command line and JSON-RPC commands - Sprejemaj ukaze iz ukazne vrstice in preko JSON-RPC - - - Run in the background as a daemon and accept commands - Teci v ozadju in sprejemaj ukaze - - - Accept connections from outside (default: 1 if no -proxy or -connect) - Sprejemaj zunanje povezave (privzeto: 1, razen če ste vklopili opciji -proxy ali -connect) - - - Bind to given address and always listen on it. Use [host]:port notation for IPv6 - Veži dani naslov in tam vedno poslušaj. Za naslove protokola IPv6 uporabite zapis [gostitelj]:vrata. + Bind to given address and always listen on it. Use [host]:port notation for IPv6 + Veži dani naslov in tam vedno poslušaj. Za naslove protokola IPv6 uporabite zapis [gostitelj]:vrata. Distributed under the MIT software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>. @@ -2807,10 +1566,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications To je preizkusna različica še neizdanega programa. Uporabljate jo na lastno odgovornost. Programa ne uporabljajte je za rudarjenje ali trgovske aplikacije. - - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - Na tem računalniku ni bilo mogoče vezati naslova %s. Odjemalec Bitcoin Core je verjetno že zagnan. - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) OPOZORILO: Generirano je bilo nenavadno veliko število blokov. Št. prejetih blokov: %d v št. ur: %d (pričakovanih je %d blokov) @@ -2827,10 +1582,6 @@ Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Opozorilo: Trenutno se s soležniki ne strinjam v popolnosti! Mogoče bi morali vi ali drugi udeleženci posodobiti odjemalce. - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Opozorilo: Datoteka wallet.dat je bila okvarjena, podatki pa so bili kljub temu rešeni! Originalna datoteka je bila shranjena kot wallet.{čas.oznaka}.bak v mapo %s. Če sta skupno stanje ali seznam transakcij napačna, morate datoteko restavrirati iz varnostne kopije. - Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. Sprejemaj povezave samo od soležnikov, ki so na naslovih, ki ustrezajo navedeni omrežni maski ali naslovu. Opcijo lahko navedete večkrat. @@ -2951,10 +1702,6 @@ Wallet options: Izbire denarnice: - - You need to rebuild the database using -reindex to change -txindex - Ob spremembi vrednosti opcije -txindex boste morali obnoviti bazo podatkov z uporabo opcije -reindex - 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 Iz navedenega vira dovoli povezave na JSON-RPC. Veljavne oblike vrednosti parametra <ip> so: edinstven naslov IP (npr.: 1.2.3.4), kombinacija omrežje/netmask (npr.: 1.2.3.4/255.255.255.0), ali pa kombinacija omrežje/CIDR (1.2.3.4/24). To opcijo lahko navedete večkrat. @@ -2967,10 +1714,6 @@ Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces) Veži dani naslov in sprejemaj povezave na JSON-RPC. Za naslove protokola IPv6 uporabite zapis [gostitelj]:vrata. To opcijo lahko navedete večkrat. (privzeto: veži vse omrežne vmesnike) - - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - Ne morem zakleniti podatkovne mape %s. Bitcoin Core je verjetno že zagnan. - Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) Ustvarjaj nove datoteke s privzetimi sistemskimi dovoljenji, namesto z umask 077. (To pride v poštev samo, kadar imate izklopljeno funkcijo denarnice.) @@ -2999,38 +1742,14 @@ (default: %u) (privzeto: %u) - - Activating best chain... - Prehajam na najboljšo verigo ... - - - Cannot resolve -whitebind address: '%s' - Naslova %s, podanega pri opciji -whitebind ni mogoče razrešiti. - Connect through SOCKS5 proxy Poveži se preko posredniškega strežnika SOCKS5 - - Copyright (C) 2009-%i The Bitcoin Core Developers - Copyright (C) 2009-%i The Bitcoin Core Developers - Information Informacije - - Invalid amount for -maxtxfee=<amount>: '%s' - Neveljavna količina za -maxtxfee=<amount>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Neveljavna količina za -minrelaytxfee=<amount>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - Neveljavna količina za -mintxfee=<amount>: '%s' - Need to specify a port with -whitebind: '%s' Pri opciji -whitebind morate navesti vrata: %s @@ -3079,10 +1798,6 @@ Zapping all transactions from wallet... Brišem vse transakcije iz denarnice ... - - wallet.dat corrupt, salvage failed - Datoteka wallet.dat je poškodovana in je ni bilo mogoče obnoviti. - Password for JSON-RPC connections Geslo za povezave na JSON-RPC @@ -3091,10 +1806,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) Izvedi ukaz, ko je najden najboljši blok (niz %s v ukazu bo zamenjan s hash vrednostjo bloka) - - This help message - To sporočilo pomoči - Allow DNS lookups for -addnode, -seednode and -connect Omogoči poizvedbe DNS za opcije -addnode, -seednode in -connect. @@ -3103,10 +1814,6 @@ Loading addresses... Nalagam naslove ... - - Error loading wallet.dat: Wallet corrupted - Napaka pri nalaganju wallet.dat: denarnica pokvarjena - Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s) Za dostop do soležnikov preko skritih storitev Tor uporabi drug posredniški strežnik SOCKS5 (privzeto: %s) @@ -3115,10 +1822,6 @@ (default: %s) (privzeto: %s) - - Error loading wallet.dat - Napaka pri nalaganju wallet.dat - Invalid -proxy address: '%s' Neveljaven naslov -proxy: '%s' @@ -3151,18 +1854,6 @@ Unknown network specified in -onlynet: '%s' Neznano omrežje določeno v -onlynet: '%s'. - - Cannot resolve -bind address: '%s' - Naslova %s, podanega pri opciji -bind ni mogoče razrešiti. - - - Cannot resolve -externalip address: '%s' - Naslova "%s", podanega pri opciji -externalip ni mogoče razrešiti. - - - Invalid amount for -paytxfee=<amount>: '%s' - Neveljavna količina za -paytxfee=<amount>: '%s' - Insufficient funds Premalo sredstev diff --git a/src/qt/locale/bitcoin_sq.ts b/src/qt/locale/bitcoin_sq.ts index d87bd9db5811a..6c86b7d9fcd87 100644 --- a/src/qt/locale/bitcoin_sq.ts +++ b/src/qt/locale/bitcoin_sq.ts @@ -21,10 +21,6 @@ &Copy &Kopjo - - &Copy Address - &Kopjo adresen - Delete the currently selected address from the list Fshi adresen e selektuar nga lista @@ -37,65 +33,6 @@ &Delete &Fshi - - Choose the address to send coins to - Zgjidh adresen ku do te dergoni monedhat - - - Sending addresses - Duke derguar adresen - - - Receiving addresses - Duke marr adresen - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Këto janë Bitcoin adresat e juaja për të dërguar pagesa. Gjithmon kontrolloni shumën dhe adresën pranuese para se të dërgoni monedha. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Këto janë Bitcoin adresat e juaja për të pranuar pagesa. Rekomandohet që gjithmon të përdorni një adresë të re për çdo transaksion. - - - Copy &Label - Kopjo &Etiketë - - - &Edit - &Ndrysho - - - Export Address List - Eksporto listën e adresave - - - Comma separated file (*.csv) - Skedar i ndarë me pikëpresje(*.csv) - - - Exporting Failed - Eksportimi dështoj - - - There was an error trying to save the address list to %1. Please try again. - Gabim gjatë ruajtjes së listës së adresave në %1. Ju lutem provoni prapë. - - - - AddressTableModel - - Label - Etiketë - - - Address - Adresë - - - (no label) - (pa etiketë) - AskPassphraseDialog @@ -111,67 +48,7 @@ Repeat new passphrase Përsërisni frazkalimin e ri - - Encrypt wallet - Kripto portofolin - - - This operation needs your wallet passphrase to unlock the wallet. - Ky veprim ka nevojë per frazkalimin e portofolit tuaj që të ç'kyç portofolin. - - - Unlock wallet - ç'kyç portofolin. - - - This operation needs your wallet passphrase to decrypt the wallet. - Ky veprim kërkon frazkalimin e portofolit tuaj që të dekriptoj portofolin. - - - Decrypt wallet - Dekripto portofolin - - - Change passphrase - Ndrysho frazkalimin - - - Confirm wallet encryption - Konfirmoni enkriptimin e portofolit - - - Are you sure you wish to encrypt your wallet? - Jeni te sigurt te enkriptoni portofolin tuaj? - - - Wallet encrypted - Portofoli u enkriptua - - - Wallet encryption failed - Enkriptimi i portofolit dështoi - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Enkriptimi i portofolit dështoi për shkak të një gabimi të brëndshëm. portofoli juaj nuk u enkriptua. - - - The supplied passphrases do not match. - Frazkalimet e plotësuara nuk përputhen. - - - Wallet unlock failed - ç'kyçja e portofolit dështoi - - - The passphrase entered for the wallet decryption was incorrect. - Frazkalimi i futur për dekriptimin e portofolit nuk ishte i saktë. - - - Wallet decryption failed - Dekriptimi i portofolit dështoi - - + BanTableModel @@ -249,14 +126,6 @@ Tabs toolbar Shiriti i mjeteve - - Bitcoin Core - Berthama Bitcoin - - - &About Bitcoin Core - Rreth Berthames Bitkoin - %1 and %2 %1 dhe %2 @@ -298,9 +167,6 @@ Portofoli po <b> enkriptohet</b> dhe është <b> i kyçur</b> - - ClientModel - CoinControlDialog @@ -319,22 +185,6 @@ Date Data - - Copy address - Kopjo adresën - - - yes - po - - - no - jo - - - (no label) - (pa etiketë) - EditAddressDialog @@ -350,34 +200,6 @@ &Address &Adresa - - New receiving address - Adresë e re pritëse - - - New sending address - Adresë e re dërgimi - - - Edit receiving address - Ndrysho adresën pritëse - - - Edit sending address - ndrysho adresën dërguese - - - The entered address "%1" is already in the address book. - Adresa e dhënë "%1" është e zënë në librin e adresave. - - - Could not unlock wallet. - Nuk mund të ç'kyçet portofoli. - - - New key generation failed. - Krijimi i çelësit të ri dështoi. - FreespaceChecker @@ -388,18 +210,10 @@ HelpMessageDialog - - Bitcoin Core - Berthama Bitcoin - version versioni - - About Bitcoin Core - Rreth Berthames Bitkoin - Intro @@ -407,14 +221,6 @@ Welcome Miresevini - - Welcome to Bitcoin Core. - Miresevini ne Berthamen Bitcoin - - - Bitcoin Core - Berthama Bitcoin - Error Problem @@ -441,9 +247,6 @@ Formilarë - - PaymentServer - PeerTableModel @@ -454,9 +257,6 @@ Sasia - - QRImageWidget - RPCConsole @@ -501,37 +301,6 @@ Copy &Address &Kopjo adresen - - Address - Adresë - - - Amount - Sasia - - - Label - Etiketë - - - - RecentRequestsTableModel - - Date - Data - - - Label - Etiketë - - - Amount - Sasia - - - (no label) - (pa etiketë) - SendCoinsDialog @@ -559,18 +328,6 @@ Confirm the send action Konfirmo veprimin e dërgimit - - Confirm send coins - konfirmo dërgimin e monedhave - - - The amount to pay must be larger than 0. - Shuma e paguar duhet të jetë më e madhe se 0. - - - (no label) - (pa etiketë) - SendCoinsEntry @@ -582,10 +339,6 @@ Pay &To: Paguaj &drejt: - - Enter a label for this address to add it to your address book - Krijoni një etiketë për këtë adresë që t'ja shtoni librit të adresave - &Label: &Etiketë: @@ -627,10 +380,6 @@ SplashScreen - - Bitcoin Core - Berthama Bitcoin - [testnet] [testo rrjetin] @@ -639,172 +388,26 @@ TrafficGraphWidget - - TransactionDesc - - Open until %1 - Hapur deri më %1 - - - %1/unconfirmed - %1/I pakonfirmuar - - - %1 confirmations - %1 konfirmimet - - - Date - Data - - - Transaction - transaksionit - - - Amount - Sasia - - - , has not been successfully broadcast yet - , nuk është transmetuar me sukses deri tani - - - unknown - i/e panjohur - - TransactionDescDialog - - Transaction details - Detajet e transaksionit - This pane shows a detailed description of the transaction Ky panel tregon një përshkrim të detajuar të transaksionit - - TransactionTableModel - - Date - Data - - - Type - Lloji - - - Open until %1 - Hapur deri më %1 - - - Confirmed (%1 confirmations) - I/E konfirmuar(%1 konfirmime) - - - This block was not received by any other nodes and will probably not be accepted! - Ky bllok është marrë nga ndonjë nyje dhe ka shumë mundësi të mos pranohet! - - - Generated but not accepted - I krijuar por i papranuar - - - Label - Etiketë - - - Received with - Marrë me - - - Sent to - Dërguar drejt - - - Payment to yourself - Pagesë ndaj vetvetes - - - Mined - Minuar - - - (n/a) - (p/a) - - - - TransactionView - - Received with - Marrë me - - - Sent to - Dërguar drejt - - - Mined - Minuar - - - Copy address - Kopjo adresën - - - Exporting Failed - Eksportimi dështoj - - - Comma separated file (*.csv) - Skedar i ndarë me pikëpresje(*.csv) - - - Date - Data - - - Type - Lloji - - - Label - Etiketë - - - Address - Adresë - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - Send Coins - Dërgo Monedha - - - - WalletView - - Export the data in the current tab to a file - Eksporto të dhënat e skedës korrente në një skedar - - bitcoin-core Options: Opsionet: + + Bitcoin Core + Berthama Bitcoin + Information Informacion diff --git a/src/qt/locale/bitcoin_sr.ts b/src/qt/locale/bitcoin_sr.ts index b6ba896b38f54..6b6f1af6f6453 100644 --- a/src/qt/locale/bitcoin_sr.ts +++ b/src/qt/locale/bitcoin_sr.ts @@ -17,10 +17,6 @@ &Copy Kopirajte - - &Copy Address - Kopirajte adresu - Delete the currently selected address from the list Izbrisite trenutno izabranu adresu sa liste @@ -29,25 +25,6 @@ &Delete &Избриши - - Comma separated file (*.csv) - Зарезом одвојене вредности (*.csv) - - - - AddressTableModel - - Label - Етикета - - - Address - Адреса - - - (no label) - (без етикете) - AskPassphraseDialog @@ -63,74 +40,6 @@ Repeat new passphrase Поновите нову лозинку - - Encrypt wallet - Шифровање новчаника - - - This operation needs your wallet passphrase to unlock the wallet. - Ова акција захтева лозинку Вашег новчаника да би га откључала. - - - Unlock wallet - Откључавање новчаника - - - This operation needs your wallet passphrase to decrypt the wallet. - Ова акција захтева да унесете лозинку да би дешифловала новчаник. - - - Decrypt wallet - Дешифровање новчаника - - - Change passphrase - Промена лозинке - - - Confirm wallet encryption - Одобрите шифровање новчаника - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Упозорење: Ако се ваш новчаник шифрује а потом изгубите лозинкзу, ви ћете <b>ИЗГУБИТИ СВЕ BITCOIN-Е</b>! - - - Are you sure you wish to encrypt your wallet? - Да ли сте сигурни да желите да се новчаник шифује? - - - Wallet encrypted - Новчаник је шифрован - - - Wallet encryption failed - Неуспело шифровање новчаника - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Настала је унутрашња грешка током шифровања новчаника. Ваш новчаник није шифрован. - - - The supplied passphrases do not match. - Лозинке које сте унели се не подударају. - - - Wallet unlock failed - Неуспело откључавање новчаника - - - The passphrase entered for the wallet decryption was incorrect. - Лозинка коју сте унели за откључавање новчаника је нетачна. - - - Wallet decryption failed - Неуспело дешифровање новчаника - - - Wallet passphrase was successfully changed. - Лозинка за приступ новчанику је успешно промењена. - BanTableModel @@ -221,10 +130,6 @@ Tabs toolbar Трака са картицама - - &About Bitcoin Core - O Bitcoin Coru - Up to date Ажурно @@ -250,9 +155,6 @@ Новчаник јс <b>шифрован</b> и тренутно <b>закључан</b> - - ClientModel - CoinControlDialog @@ -271,22 +173,6 @@ Confirmed Potvrdjen - - Copy address - kopiraj adresu - - - Copy label - kopiraj naziv - - - Copy amount - kopiraj iznos - - - (no label) - (без етикете) - EditAddressDialog @@ -302,15 +188,7 @@ &Address &Адреса - - The entered address "%1" is already in the address book. - Унешена адреса "%1" се већ налази у адресару. - - - Could not unlock wallet. - Немогуће откључати новчаник. - - + FreespaceChecker @@ -320,10 +198,6 @@ version верзија - - About Bitcoin Core - O Bitcoin Coru - Usage: Korišćenje: @@ -361,9 +235,6 @@ Форма - - PaymentServer - PeerTableModel @@ -374,9 +245,6 @@ iznos - - QRImageWidget - RPCConsole @@ -394,60 +262,13 @@ &Message: Poruka: - - Copy label - kopiraj naziv - - - Copy amount - kopiraj iznos - - + ReceiveRequestDialog Copy &Address Kopirajte adresu - - Address - Адреса - - - Amount - iznos - - - Label - Етикета - - - Message - Poruka - - - - RecentRequestsTableModel - - Date - datum - - - Label - Етикета - - - Message - Poruka - - - Amount - iznos - - - (no label) - (без етикете) - SendCoinsDialog @@ -467,15 +288,7 @@ S&end &Пошаљи - - Copy amount - kopiraj iznos - - - (no label) - (без етикете) - - + SendCoinsEntry @@ -523,258 +336,16 @@ TrafficGraphWidget - - TransactionDesc - - Open until %1 - Otvoreno do %1 - - - %1/unconfirmed - %1/nepotvrdjeno - - - %1 confirmations - %1 potvrde - - - Date - datum - - - label - етикета - - - Message - Poruka - - - Transaction - transakcije - - - Amount - iznos - - - , has not been successfully broadcast yet - , nije još uvek uspešno emitovan - - - unknown - nepoznato - - TransactionDescDialog - - Transaction details - detalji transakcije - This pane shows a detailed description of the transaction Ovaj odeljak pokazuje detaljan opis transakcije - - TransactionTableModel - - Date - datum - - - Type - tip - - - Open until %1 - Otvoreno do %1 - - - Confirmed (%1 confirmations) - Potvrdjena (%1 potvrdjenih) - - - This block was not received by any other nodes and will probably not be accepted! - Ovaj blok nije primljen od ostalih čvorova (nodova) i verovatno neće biti prihvaćen! - - - Generated but not accepted - Generisan ali nije prihvaćen - - - Label - Етикета - - - Received with - Primljen sa - - - Received from - Primljeno od - - - Sent to - Poslat ka - - - Payment to yourself - Isplata samom sebi - - - Mined - Minirano - - - (n/a) - (n/a) - - - Transaction status. Hover over this field to show number of confirmations. - Status vaše transakcije. Predjite mišem preko ovog polja da bi ste videli broj konfirmacija - - - Date and time that the transaction was received. - Datum i vreme primljene transakcije. - - - Type of transaction. - Tip transakcije - - - Amount removed from or added to balance. - Iznos odbijen ili dodat balansu. - - - - TransactionView - - All - Sve - - - Today - Danas - - - This week - ove nedelje - - - This month - Ovog meseca - - - Last month - Prošlog meseca - - - This year - Ove godine - - - Range... - Opseg... - - - Received with - Primljen sa - - - Sent to - Poslat ka - - - To yourself - Vama - samom sebi - - - Mined - Minirano - - - Other - Drugi - - - Enter address or label to search - Navedite adresu ili naziv koji bi ste potražili - - - Min amount - Min iznos - - - Copy address - kopiraj adresu - - - Copy label - kopiraj naziv - - - Copy amount - kopiraj iznos - - - Edit label - promeni naziv - - - Comma separated file (*.csv) - Зарезом одвојене вредности (*.csv) - - - Confirmed - Potvrdjen - - - Date - datum - - - Type - tip - - - Label - Етикета - - - Address - Адреса - - - Range: - Opseg: - - - to - do - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - Send Coins - Слање новца - - - - WalletView - - Backup Wallet - Backup новчаника - - bitcoin-core @@ -801,22 +372,10 @@ Password for JSON-RPC connections Lozinka za JSON-RPC konekcije - - This help message - Ova poruka Pomoći - Loading addresses... učitavam adrese.... - - Error loading wallet.dat: Wallet corrupted - Грешка током учитавања wallet.dat: Новчаник је покварен - - - Error loading wallet.dat - Грешка током учитавања wallet.dat - Loading block index... Učitavam blok indeksa... diff --git a/src/qt/locale/bitcoin_sr@latin.ts b/src/qt/locale/bitcoin_sr@latin.ts index c836c8ddbaedb..86243bc14c1ef 100644 --- a/src/qt/locale/bitcoin_sr@latin.ts +++ b/src/qt/locale/bitcoin_sr@latin.ts @@ -25,10 +25,6 @@ C&lose Zatvori - - &Copy Address - Kopiraj adresu - Delete the currently selected address from the list Briše trenutno izabranu adresu sa liste @@ -45,69 +41,6 @@ &Delete &Izbrisati - - Choose the address to send coins to - Izaberi adresu za slanje bitkoina - - - Choose the address to receive coins with - Izaberi adresu za primanje bitkoina - - - C&hoose - I&zaberi - - - Sending addresses - Adrese za slanje - - - Receiving addresses - Adrese za primanje - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Ovo su vase Bitkoin adrese za slanje bitkoina. Uvek proverite unetu kolicinu bitkoina i adresu za slanje bitkoin pre slanja. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Ovo su vase Bitkoin adrese za primanje bitkoina. Preporuceno je da koristite drugaciju adresu za primanje kod svake transakcije. - - - &Edit - &Izmeni - - - Export Address List - Izvezi listu adresa - - - Comma separated file (*.csv) - Zapetom odvojene ('.csv) datoteke - - - Exporting Failed - Izvoz nije uspeo - - - There was an error trying to save the address list to %1. Please try again. - Dogodila se greska prilikom cuvanja adrese u %1. Molimo pokusajte ponovo. - - - - AddressTableModel - - Label - Etiketa - - - Address - Adresa - - - (no label) - (bez etikete) - AskPassphraseDialog @@ -127,94 +60,6 @@ Repeat new passphrase Ponovo unesite pristupnu frazu - - Encrypt wallet - Enkriptuj/Sifruj novcanik - - - This operation needs your wallet passphrase to unlock the wallet. - Da bi ste otkljucali novcanik potrebno je da unesete pristupnu frazu - - - Unlock wallet - Otkljucaj novcanik - - - This operation needs your wallet passphrase to decrypt the wallet. - Da bi ste dekriptovali/desifrovali novcanik potrebno je da unesete pristupnu frazu - - - Decrypt wallet - Dekriptuj/Desifruj novcanik - - - Change passphrase - Izmeni pristupnu frazu - - - Confirm wallet encryption - Potvrdite enkripciju/sifrovanje novcanika - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Upozorenje: Ako ekriptujete/sifrujete novcanik, a izgubite pristupnu frazu <b>IZGUBICETE SVE VASE BITKOINE</b>! - - - Are you sure you wish to encrypt your wallet? - Da li ste sigurni da zelite da enkriptujete/sifrujete novcanik? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Bitcoin Core ce se sada zatvoriti radi zavrsavanje procesa enkripcije/sifrovanja novcanika. Zapamtite da enkriptovanje/sifrovanje novcanika ne moze u potpunosti da zastiti vase bitkoine od kradje od strane virusa koji su zarazili vas racunar. - - - 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. - VAZNO : Bilo koja prethodne rezervne kopije koje ste nacinili od svoje datoteke novcanika treba da se zamene sa novogenerisanom, sifrovanom datotekom novcanika. Iz bezbednosnih razloga, prethodne rezervne kopije su nezasifrovanih datoteka novcanika ce postati beskorisne cim pocnete da koristite novi, sifrovani novčanik. - - - Warning: The Caps Lock key is on! - Upozorenje: Dugme Caps Lock je upaljeno - - - Wallet encrypted - Novcanik je enkriptovan/sifrovan - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Unesite novu pristupnu frazu u novcanik.<br/>Molimo koristite pristupnu frazu od <br/>deset ili vise nasumicnih karaktera <br/>, ili <b>osm ili vise reci </b>. - - - Enter the old passphrase and new passphrase to the wallet. - Unesite staru pristupnu frazu i novu pristupnu frazu u novcanik. - - - Wallet encryption failed - Ekripcija/Sifrovanje novcanika nije uspelo - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Enkriptovanje/Sifrovanje novcanika nije uspelo zbog greske. Vas novcanik nije enkriptovan/sifrovan. - - - The supplied passphrases do not match. - Uneta pristupne fraze se ne podudaraju - - - Wallet unlock failed - Otkljucavanje novcanika nije uspelo - - - The passphrase entered for the wallet decryption was incorrect. - Pristupna fraza za dekriptovanje/desifrovanje novcanika nije tacna. - - - Wallet decryption failed - Dekriptovanje/desifrovanje novcanika nije uspelo - - - Wallet passphrase was successfully changed. - Pristupna fraza novcanika je uspesno promenjena. - BanTableModel @@ -229,18 +74,11 @@ BitcoinGUI - - Bitcoin Core - Bitcoin Core - Error Greska - - ClientModel - CoinControlDialog @@ -251,10 +89,6 @@ Date Datum - - (no label) - (bez etikete) - EditAddressDialog @@ -264,17 +98,9 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin Core - Intro - - Bitcoin Core - Bitcoin Core - Error Greska @@ -289,9 +115,6 @@ OverviewPage - - PaymentServer - PeerTableModel @@ -302,9 +125,6 @@ Kolicina - - QRImageWidget - RPCConsole @@ -313,52 +133,9 @@ ReceiveRequestDialog - - Address - Adresa - - - Amount - Kolicina - - - Label - Etiketa - - - Message - Poruka - - - - RecentRequestsTableModel - - Date - Datum - - - Label - Etiketa - - - Message - Poruka - - - Amount - Kolicina - - - (no label) - (bez etikete) - SendCoinsDialog - - (no label) - (bez etikete) - SendCoinsEntry @@ -371,252 +148,22 @@ SplashScreen - - Bitcoin Core - Bitcoin Core - - - The Bitcoin Core developers - Razvojni tim Bitcoin Core - TrafficGraphWidget - - TransactionDesc - - %1/offline - %1/van mreze - - - %1/unconfirmed - %1/nepotvrdjeno - - - %1 confirmations - %1 potvrdjeno/ih - - - Status - Stanje/Status - - - Date - Datum - - - Source - Izvor - - - Generated - Generisano - - - From - Od - - - To - Kome - - - own address - sopstvena adresa - - - watch-only - samo za gledanje - - - label - etiketa - - - Credit - Kredit - - - not accepted - nije prihvaceno - - - Debit - Zaduzenje - - - Total debit - Ukupno zaduzenje - - - Total credit - Totalni kredit - - - Transaction fee - Taksa transakcije - - - Net amount - Neto iznos - - - Message - Poruka - - - Comment - Komentar - - - Transaction ID - ID Transakcije - - - Merchant - Trgovac - - - Debug information - Informacije debugovanja - - - Transaction - Transakcije - - - Inputs - Unosi - - - Amount - Kolicina - - - true - tacno - - - false - netacno - - - , has not been successfully broadcast yet - , nisu uspesno jos emitovano - - - unknown - nepoznato - - TransactionDescDialog - - Transaction details - Detalji transakcije - - - - TransactionTableModel - - Date - Datum - - - Type - Tip - - - Label - Etiketa - - - Received with - Primljeno uz - - - Received from - Primljeno od - - - Sent to - Poslat - - - Payment to yourself - Placanje samom sebi - - - Mined - Iskopano - - - watch-only - samo za gledanje - - - - TransactionView - - Received with - Primljeno uz - - - Sent to - Poslat - - - Mined - Iskopano - - - Exporting Failed - Izvoz nije uspeo - - - Comma separated file (*.csv) - Zarezom odvojene ('.csv) datoteke - - - Date - Datum - - - Type - Tip - - - Label - Etiketa - - - Address - Adresa - UnitDisplayStatusBarControl - WalletFrame - - - WalletModel - - - WalletView - - &Export - &Izvoz - + bitcoin-core - Export the data in the current tab to a file - Izvoz podataka iz trenutne kartice u datoteku + Bitcoin Core + Bitcoin Core - - - bitcoin-core Insufficient funds Nedovoljno sredstava diff --git a/src/qt/locale/bitcoin_sv.ts b/src/qt/locale/bitcoin_sv.ts index acf37bd1d4eee..a637cebe2cd53 100644 --- a/src/qt/locale/bitcoin_sv.ts +++ b/src/qt/locale/bitcoin_sv.ts @@ -25,10 +25,6 @@ C&lose S&täng - - &Copy Address - &Kopiera adress - Delete the currently selected address from the list Ta bort den valda adressen från listan @@ -45,74 +41,6 @@ &Delete &Radera - - Choose the address to send coins to - Välj en adress att sända betalning till - - - Choose the address to receive coins with - Välj en adress att ta emot betalning till - - - C&hoose - V&älj - - - Sending addresses - Avsändaradresser - - - Receiving addresses - Mottagaradresser - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Detta är dina Bitcoin-adresser för att skicka betalningar. Kolla alltid summan och den mottagande adressen innan du skickar Bitcoins. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Detta är dina Bitcoin-adresser för att ta emot betalningar. Det rekommenderas att använda en ny mottagningsadress för varje transaktion. - - - Copy &Label - Kopiera &etikett - - - &Edit - &Ändra - - - Export Address List - Exportera adresslistan - - - Comma separated file (*.csv) - Kommaseparerad fil (*.csv) - - - Exporting Failed - Exporteringen misslyckades - - - There was an error trying to save the address list to %1. Please try again. - Det inträffade ett fel när adresslistan skulle sparas till %1. -Var vänlig och försök igen. - - - - AddressTableModel - - Label - Etikett - - - Address - Adress - - - (no label) - (ingen etikett) - AskPassphraseDialog @@ -132,94 +60,6 @@ Var vänlig och försök igen. Repeat new passphrase Upprepa nytt lösenord - - Encrypt wallet - Kryptera plånbok - - - This operation needs your wallet passphrase to unlock the wallet. - Denna operation behöver din plånboks lösenord för att låsa upp plånboken. - - - Unlock wallet - Lås upp plånbok - - - This operation needs your wallet passphrase to decrypt the wallet. - Denna operation behöver din plånboks lösenord för att dekryptera plånboken. - - - Decrypt wallet - Dekryptera plånbok - - - Change passphrase - Ändra lösenord - - - Confirm wallet encryption - Bekräfta kryptering av plånbok - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - VARNING: Om du krypterar din plånbok och glömmer ditt lösenord, kommer du att <b>FÖRLORA ALLA DINA TILLGÅNGAR</b>! - - - Are you sure you wish to encrypt your wallet? - Är du säker på att du vill kryptera din plånbok? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Bitcoin Core kommer att stängas för att slutföra krypteringsprocessen. Kom ihåg att plånbokskryptering inte garanterar fullt skydd mot skadlig kod på din dator. - - - 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. - VIKTIGT: Alla tidigare säkerhetskopior du har gjort av plånbokens fil ska ersättas med den nya genererade, krypterade plånboks filen. Av säkerhetsskäl kommer tidigare säkerhetskopior av den okrypterade plånboks filen blir oanvändbara när du börjar använda en ny, krypterad plånbok. - - - Warning: The Caps Lock key is on! - Varning: Caps Lock är påslaget! - - - Wallet encrypted - Plånboken är krypterad - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Ange plånbokens nya lösenord. <br/> Använd ett lösenord på <b>tio eller fler slumpmässiga tecken,</b> eller <b>åtta eller fler ord.</b>. - - - Enter the old passphrase and new passphrase to the wallet. - Ge det gamla lösenordet och det nya lösenordet för plånboken. - - - Wallet encryption failed - Kryptering av plånbok misslyckades - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Kryptering av plånbok misslyckades på grund av ett internt fel. Din plånbok blev inte krypterad. - - - The supplied passphrases do not match. - De angivna lösenorden överensstämmer inte. - - - Wallet unlock failed - Upplåsning av plånbok misslyckades - - - The passphrase entered for the wallet decryption was incorrect. - Lösenordet för dekryptering av plånbok var felaktig. - - - Wallet decryption failed - Dekryptering av plånbok misslyckades - - - Wallet passphrase was successfully changed. - Plånbokens lösenord har ändrats. - BanTableModel @@ -270,6 +110,14 @@ Var vänlig och försök igen. Quit application Avsluta programmet + + &About %1 + &Om %1 + + + Show information about %1 + Visa information om %1 + About &Qt Om &Qt @@ -282,6 +130,10 @@ Var vänlig och försök igen. &Options... &Alternativ... + + Modify configuration options for %1 + Ändra konfigurationsalternativ för %1 + &Encrypt Wallet... &Kryptera plånbok... @@ -306,14 +158,6 @@ Var vänlig och försök igen. Open &URI... Öppna &URI... - - Bitcoin Core client - Bitcoin Core-klient - - - Importing blocks from disk... - Importerar block från disk... - Reindexing blocks on disk... Återindexerar block på disken... @@ -358,10 +202,6 @@ Var vänlig och försök igen. &Receive &Ta emot - - Show information about Bitcoin Core - Visa information om Bitcoin Core - &Show / Hide &Visa / Göm @@ -398,22 +238,10 @@ Var vänlig och försök igen. Tabs toolbar Verktygsfält för tabbar - - Bitcoin Core - Bitcoin Core - Request payments (generates QR codes and bitcoin: URIs) Begär betalning (genererar QR-koder och bitcoin-URI) - - &About Bitcoin Core - &Om Bitcoin Core - - - Modify configuration options for Bitcoin Core - Ändra konfigurationsalternativ för Bitcoin Core - Show the list of used sending addresses and labels Visa listan av använda avsändaradresser och etiketter @@ -430,14 +258,18 @@ Var vänlig och försök igen. &Command-line options &Kommandoradsalternativ - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Visa Bitcoin Cores hjälpmeddelande för att få en lista med möjliga Bitcoin-kommandoradsalternativ. - %n active connection(s) to Bitcoin network %n aktiva anslutningar till Bitcoin-nätverket.%n aktiva anslutningar till Bitcoin-nätverket. + + Indexing blocks on disk... + Indexerar block på disken... + + + Processing blocks on disk... + Bearbetar block på disken... + No block source available... Ingen block-källa tillgänglig... @@ -494,6 +326,14 @@ Var vänlig och försök igen. Up to date Uppdaterad + + Show the %1 help message to get a list with possible Bitcoin command-line options + Visa %1 hjälpmeddelande för att få en lista med möjliga Bitcoin kommandoradsalternativ. + + + %1 client + %1-klient + Catching up... Hämtar senaste... @@ -545,13 +385,6 @@ Var vänlig och försök igen. Denna plånbok är <b>krypterad</b> och för närvarande <b>låst</b> - - ClientModel - - Network Alert - Nätverkslarm - - CoinControlDialog @@ -630,150 +463,6 @@ Var vänlig och försök igen. Priority Prioritet - - Copy address - Kopiera adress - - - Copy label - Kopiera etikett - - - Copy amount - Kopiera belopp - - - Copy transaction ID - Kopiera transaktions ID - - - Lock unspent - Lås ospenderat - - - Unlock unspent - Lås upp ospenderat - - - Copy quantity - Kopiera kvantitet - - - Copy fee - Kopiera avgift - - - Copy after fee - Kopiera efter avgift - - - Copy bytes - Kopiera byte - - - Copy priority - Kopiera prioritet - - - Copy dust - Kopiera damm - - - Copy change - Kopiera växel - - - highest - högst - - - higher - högre - - - high - hög - - - medium-high - medelhög - - - medium - medel - - - low-medium - lågmedel - - - low - låg - - - lower - lägre - - - lowest - lägst - - - (%1 locked) - (%1 låst) - - - none - ingen - - - This label turns red if the transaction size is greater than 1000 bytes. - Denna etikett blir röd om transaktionens storlek är större än 1000 bytes. - - - This label turns red if the priority is smaller than "medium". - Denna etikett blir röd om prioriteten är lägre än "medium". - - - This label turns red if any recipient receives an amount smaller than %1. - Denna etikett blir röd om någon mottagare får ett belopp mindre än %1. - - - Can vary +/- %1 satoshi(s) per input. - Kan variera +/- %1 satoshi per inmatning. - - - yes - ja - - - no - nej - - - This means a fee of at least %1 per kB is required. - Detta betyder att en avgift på minst %1 per kB behövs. - - - Can vary +/- 1 byte per input. - Kan variera +/- 1 byte per inmatning. - - - Transactions with higher priority are more likely to get included into a block. - Transaktioner med högre prioritet har större sannolikhet att inkluderas i ett block. - - - (no label) - (Ingen etikett) - - - change from %1 (%2) - växel från %1 (%2) - - - (change) - (växel) - EditAddressDialog @@ -797,38 +486,6 @@ Var vänlig och försök igen. &Address &Adress - - New receiving address - Ny mottagaradress - - - New sending address - Ny avsändaradress - - - Edit receiving address - Redigera mottagaradress - - - Edit sending address - Redigera avsändaradress - - - The entered address "%1" is already in the address book. - Den angivna adressen "%1" finns redan i adressboken. - - - The entered address "%1" is not a valid Bitcoin address. - Den angivna adressen "%1" är inte en giltig Bitcoin-adress. - - - Could not unlock wallet. - Plånboken kunde inte låsas upp. - - - New key generation failed. - Misslyckades med generering av ny nyckel. - FreespaceChecker @@ -855,10 +512,6 @@ Var vänlig och försök igen. HelpMessageDialog - - Bitcoin Core - Bitcoin Core - version version @@ -868,8 +521,8 @@ Var vänlig och försök igen. (%1-bit) - About Bitcoin Core - Om Bitcoin Core + About %1 + Om %1 Command-line options @@ -908,8 +561,8 @@ Var vänlig och försök igen. Visa startbild vid uppstart (standard: %u) - Reset all settings changes made over the GUI - Återställ alla inställningar som gjorts över GUI + Reset all settings changed in the GUI + Återställ alla inställningar som gjorts i GUI @@ -919,16 +572,16 @@ Var vänlig och försök igen. Välkommen - Welcome to Bitcoin Core. - Välkommen till Bitcoin Core. + Welcome to %1. + Välkommen till %1. - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - Eftersom detta är första gången programmet startas får du välja var Bitcoin Core skall lagra sina data. + As this is the first time the program is launched, you can choose where %1 will store its data. + Eftersom detta är första gången programmet startas får du välja var %1 skall lagra sitt data. - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - Bitcoin Core kommer att ladda ner och spara en kopia av Bitcoin-blockkedjan. Åtminstone %1GB av data kommer att sparas i denna katalog, och den kommer att växa över tiden. Plånboken kommer också att sparas i denna katalog. + %1 will download and store a copy of the Bitcoin block chain. At least %2GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. + %1 kommer att ladda ner och spara en kopia av Bitcoin blockkedjan. Åtminstone %2GB av data kommer att sparas i denna katalog, och den kommer att växa över tiden. Plånboken kommer också att sparas i denna katalog. Use the default data directory @@ -938,10 +591,6 @@ Var vänlig och försök igen. Use a custom data directory: Använd en anpassad datakatalog: - - Bitcoin Core - Bitcoin Core - Error: Specified data directory "%1" cannot be created. Fel: Den angivna datakatalogen "%1" kan inte skapas. @@ -977,10 +626,6 @@ Var vänlig och försök igen. Select payment request file Välj betalningsbegäransfil - - Select payment request file to open - Välj betalningsbegäransfil att öppna - OptionsDialog @@ -992,6 +637,14 @@ Var vänlig och försök igen. &Main &Allmänt + + Automatically start %1 after logging in to the system. + Starta %1 automatiskt efter inloggningen. + + + &Start %1 on system login + &Starta %1 vid systemlogin + Size of &database cache Storleken på &databascache @@ -1020,10 +673,6 @@ Var vänlig och försök igen. 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. Minimera istället för att stänga programmet när fönstret stängs. När detta alternativ är aktiverat stängs programmet endast genom att välja Stäng i menyn. - - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - Gränssnittets språk kan väljas här. Denna inställning träder i kraft efter omstart av Bitcoin Core. - 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 |. Tredjeparts URL:er (t.ex. en blockutforskare) som finns i transaktionstabben som ett menyval i sammanhanget. %s i URL:en ersätts med tansaktionshashen. Flera URL:er är separerade med vertikala streck |. @@ -1048,14 +697,6 @@ Var vänlig och försök igen. &Network &Nätverk - - Automatically start Bitcoin Core after logging in to the system. - Kör Bitcoin Core automatiskt vid systeminloggning. - - - &Start Bitcoin Core on system login - &Kör Bitcoin Core vid systeminloggning - (0 = auto, <0 = leave that many cores free) (0 = auto, <0 = lämna så många kärnor lediga) @@ -1140,6 +781,14 @@ Var vänlig och försök igen. &Window &Fönster + + &Hide the icon from the system tray. + &Göm ikonen från systemfältet. + + + Hide tray icon + Göm systemfältsikonen + Show only a tray icon after minimizing the window. Visa endast en systemfältsikon vid minimering. @@ -1160,6 +809,10 @@ Var vänlig och försök igen. User Interface &language: Användargränssnittets &språk: + + The user interface language can be set here. This setting will take effect after restarting %1. + Användargränssnittets språk kan ställas in här. Denna inställning träder i kraft efter en omstart av %1. + &Unit to show amounts in: &Måttenhet att visa belopp i: @@ -1285,169 +938,59 @@ Var vänlig och försök igen. - PaymentServer + PeerTableModel - URI handling - URI hantering + User Agent + Användaragent - Invalid payment address %1 - Felaktig betalningsadress %1 + Node/Service + Nod/Tjänst - Payment request rejected - Betalningsbegäran avslogs + Ping Time + Pingtid + + + QObject - Payment request network doesn't match client network. - Betalningsbegärans nätverk matchar inte klientens nätverk. + Amount + Mängd - Payment request is not initialized. - Betalningsbegäran är inte initierad. + Enter a Bitcoin address (e.g. %1) + Ange en Bitcoin-adress (t.ex. %1) - Requested payment amount of %1 is too small (considered dust). - Begärd betalning av %1 är för liten (betraktas som damm). + %1 d + %1 d - Payment request error - Fel vid betalningsbegäran + %1 h + %1 h - Cannot start bitcoin: click-to-pay handler - Kan inte starta bitcoin: klicka-och-betala handhavare + %1 m + %1 m - Payment request fetch URL is invalid: %1 - Betalningsbegärans hämta URL är felaktig: %1 + %1 s + %1 s - URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - URI går inte att tolkas! Detta kan orsakas av en ogiltig Bitcoin-adress eller felaktiga URI parametrar. + None + Ingen - Payment request file handling - Hantering av betalningsbegäransfil - - - Payment request file cannot be read! This can be caused by an invalid payment request file. - Betalningsbegäransfilen kan inte läsas! Detta kan orsakas av en felaktig betalningsbegäransfil. - - - Payment request expired. - Betalningsbegäran löpte ut. - - - Unverified payment requests to custom payment scripts are unsupported. - Overifierade betalningsbegärningar till specialbetalningsskript stöds inte. - - - Invalid payment request. - Ogiltig betalningsbegäran. - - - Refund from %1 - Återbetalning från %1 - - - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - Betalningsbegäran %1 är för stor (%2 bytes, tillåten %3 bytes) - - - Error communicating with %1: %2 - Kommunikationsfel med %1: %2 - - - Payment request cannot be parsed! - Betalningsbegäran kan inte behandlas! - - - Bad response from server %1 - Dåligt svar från server %1 - - - Payment acknowledged - Betalningen bekräftad - - - Network request error - Fel vid närverksbegäran - - - - PeerTableModel - - User Agent - Användaragent - - - Node/Service - Nod/Tjänst - - - Ping Time - Pingtid - - - - QObject - - Amount - Mängd - - - Enter a Bitcoin address (e.g. %1) - Ange en Bitcoin-adress (t.ex. %1) - - - %1 d - %1 d - - - %1 h - %1 h - - - %1 m - %1 m - - - %1 s - %1 s - - - None - Ingen - - - N/A - ej tillgänglig + N/A + ej tillgänglig %1 ms %1 ms - - QRImageWidget - - &Save Image... - &Spara Bild... - - - &Copy Image - &Kopiera Bild - - - Save QR Code - Spara QR-kod - - - PNG Image (*.png) - PNG-bild (*.png) - - RPCConsole @@ -1478,6 +1021,10 @@ Var vänlig och försök igen. Using BerkeleyDB version Använder BerkeleyDB versionen + + Datadir + Datakatalog + Startup time Uppstartstid @@ -1514,10 +1061,6 @@ Var vänlig och försök igen. Memory usage Minnesåtgång - - Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. - Öppna felsökningsloggfilen för Bitcoin Core från den nuvarande datakatalogen. Detta kan ta några sekunder om loggfilen är stor. - Received Mottagen @@ -1566,6 +1109,18 @@ Var vänlig och försök igen. User Agent Användaragent + + Open the %1 debug log file from the current data directory. This can take a few seconds for large log files. + Öppna %1 debug-loggfilen från aktuell datakatalog. Detta kan ta några sekunder för stora loggfiler. + + + Decrease font size + Minska fontstorleken + + + Increase font size + Öka fontstorleken + Services Tjänster @@ -1634,10 +1189,6 @@ Var vänlig och försök igen. Out: Ut: - - Build date - Kompileringsdatum - Debug log file Debugloggfil @@ -1675,8 +1226,8 @@ Var vänlig och försök igen. &Ta bort ban från nod - Welcome to the Bitcoin Core RPC console. - Välkommen till RPC-konsolen för Bitcoin Core. + Welcome to the %1 RPC console. + Välkommen till %1 RPC-konsolen. Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. @@ -1805,18 +1356,6 @@ Var vänlig och försök igen. Remove Ta bort - - Copy label - Kopiera etikett - - - Copy message - Kopiera meddelande - - - Copy amount - Kopiera belopp - ReceiveRequestDialog @@ -1836,73 +1375,6 @@ Var vänlig och försök igen. &Save Image... &Spara Bild... - - Request payment to %1 - Begär betalning till %1 - - - Payment information - Betalningsinformation - - - URI - URI - - - Address - Adress - - - Amount - Mängd - - - Label - Etikett - - - Message - Meddelande - - - Resulting URI too long, try to reduce the text for label / message. - URI:n är för lång, försöka minska texten för etikett / meddelande. - - - Error encoding URI into QR Code. - Fel vid skapande av QR-kod från URI. - - - - RecentRequestsTableModel - - Date - Datum - - - Label - Etikett - - - Message - Meddelande - - - Amount - Mängd - - - (no label) - (Ingen etikett) - - - (no message) - (inget meddelande) - - - (no amount) - (ingen summa) - SendCoinsDialog @@ -2022,14 +1494,6 @@ Var vänlig och försök igen. fast snabb - - Send as zero-fee transaction if possible - Sänd som nollavgiftstransaktion om möjligt - - - (confirmation may take longer) - (bekräftelse kan ta längre tid) - Send to multiple recipients at once Skicka till flera mottagare samtidigt @@ -2062,118 +1526,6 @@ Var vänlig och försök igen. S&end &Skicka - - Confirm send coins - Bekräfta skickade mynt - - - %1 to %2 - %1 till %2 - - - Copy quantity - Kopiera kvantitet - - - Copy amount - Kopiera belopp - - - Copy fee - Kopiera avgift - - - Copy after fee - Kopiera efter avgift - - - Copy bytes - Kopiera byte - - - Copy priority - Kopiera prioritet - - - Copy change - Kopiera växel - - - Total Amount %1 - Total summa %1 - - - or - eller - - - The amount to pay must be larger than 0. - Det betalade beloppet måste vara större än 0. - - - The amount exceeds your balance. - Värdet överstiger ditt saldo. - - - The total exceeds your balance when the %1 transaction fee is included. - Totalvärdet överstiger ditt saldo när transaktionsavgiften %1 är pålagd. - - - Transaction creation failed! - Transaktionen gick inte att skapa! - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - Transaktionen avslogs! Detta kan hända om några av mynten i plånboken redan spenderats, t.ex om du använt en kopia av wallet.dat och mynt spenderades i kopian men inte markerats som spenderade här. - - - A fee higher than %1 is considered an absurdly high fee. - En avgift som är högre än %1 anses vara en orimligt hög avgift. - - - Payment request expired. - Betalningsbegäran löpte ut. - - - Pay only the required fee of %1 - Betala endast den nödvändiga avgiften på %1 - - - Estimated to begin confirmation within %n block(s). - Uppskattas till att påbörja bekräftelse inom %n block.Uppskattas till att påbörja bekräftelse inom %n block. - - - The recipient address is not valid. Please recheck. - Mottagarens adress är ogiltig. Kontrollera igen. - - - Duplicate address found: addresses should only be used once each. - Duplicerad adress upptäckt: adresser skall endast användas en gång var. - - - Warning: Invalid Bitcoin address - Varning: Felaktig Bitcoinadress - - - (no label) - (Ingen etikett) - - - Warning: Unknown change address - Varning: Okänd växeladress - - - Copy dust - Kopiera damm - - - Are you sure you want to send? - Är du säker på att du vill skicka? - - - added as transaction fee - adderad som transaktionsavgift - SendCoinsEntry @@ -2185,721 +1537,199 @@ Var vänlig och försök igen. Pay &To: Betala &Till: - - Enter a label for this address to add it to your address book - Ange ett namn för den här adressen och lägg till den i din adressbok - &Label: &Etikett: Choose previously used address - Välj tidigare använda adresser - - - This is a normal payment. - Detta är en normal betalning. - - - The Bitcoin address to send the payment to - Bitcoinadress att sända betalning till - - - Alt+A - Alt+A - - - Paste address from clipboard - Klistra in adress från Urklipp - - - Alt+P - Alt+P - - - Remove this entry - Radera denna post - - - 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. - Avgiften dras från beloppet som skickas. Mottagaren kommer att få mindre bitcoins än du angivit i belopp-fältet. Om flera mottagare valts kommer avgiften delas jämt. - - - S&ubtract fee from amount - S&ubtrahera avgiften från beloppet - - - Message: - Meddelande: - - - This is an unauthenticated payment request. - Detta är en oautentiserad betalningsbegäran. - - - This is an authenticated payment request. - Detta är en autentiserad betalningsbegäran. - - - Enter a label for this address to add it to the list of used addresses - Ange en etikett för denna adress att adderas till listan över använda adresser - - - 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. - Ett meddelande som bifogades bitcoin-URI, vilket lagras med transaktionen som referens. NB: Meddelandet kommer inte att sändas över Bitcoinnätverket. - - - Pay To: - Betala Till: - - - Memo: - PM: - - - - ShutdownWindow - - Bitcoin Core is shutting down... - Bitcoin Core stängs av... - - - Do not shut down the computer until this window disappears. - Stäng inte av datorn förrän denna ruta försvinner. - - - - SignVerifyMessageDialog - - Signatures - Sign / Verify a Message - Signaturer - Signera / Verifiera ett Meddelande - - - &Sign Message - &Signera Meddelande - - - 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. - Du kan underteckna meddelanden/avtal med dina adresser för att bevisa att du kan ta emot bitcoins som skickats till dem. Var försiktig så du inte undertecknar något oklart eller konstigt, eftersom phishing-angrepp kan försöka få dig att underteckna din identitet till dem. Underteckna endast väldetaljerade meddelanden som du godkänner. - - - The Bitcoin address to sign the message with - Bitcoinadress att signera meddelandet med - - - Choose previously used address - Välj tidigare använda adresser - - - Alt+A - Alt+A - - - Paste address from clipboard - Klistra in adress från Urklipp - - - Alt+P - Alt+P - - - Enter the message you want to sign here - Skriv in meddelandet du vill signera här - - - Signature - Signatur - - - Copy the current signature to the system clipboard - Kopiera signaturen till systemets Urklipp - - - Sign the message to prove you own this Bitcoin address - Signera meddelandet för att bevisa att du äger denna adress - - - Sign &Message - Signera &Meddelande - - - Reset all sign message fields - Rensa alla fält - - - Clear &All - Rensa &alla - - - &Verify Message - &Verifiera Meddelande - - - 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! - Ange mottagarens adress, meddelande (kopiera radbrytningar, mellanrum, flikar, etc. exakt) och signatur nedan för att verifiera meddelandet. Undvik att läsa in mera information i signaturen än vad som stod i själva undertecknade meddelandet, för att undvika ett man-in-the-middle-angrepp. Notera att detta endast bevisar att undertecknad tar emot med adressen, det bevisar inte vem som skickat transaktionen! - - - The Bitcoin address the message was signed with - Bitcoinadressen som meddelandet signerades med - - - Verify the message to ensure it was signed with the specified Bitcoin address - Verifiera meddelandet för att vara säker på att den var signerad med den angivna Bitcoin-adressen - - - Verify &Message - Verifiera &Meddelande - - - Reset all verify message fields - Rensa alla fält - - - Click "Sign Message" to generate signature - Klicka "Signera Meddelande" för att få en signatur - - - The entered address is invalid. - Den angivna adressen är ogiltig. - - - Please check the address and try again. - Vad god kontrollera adressen och försök igen. - - - The entered address does not refer to a key. - Den angivna adressen refererar inte till en nyckel. - - - Wallet unlock was cancelled. - Upplåsningen av plånboken avbröts. - - - Private key for the entered address is not available. - Privata nyckel för den angivna adressen är inte tillgänglig. - - - Message signing failed. - Signeringen av meddelandet misslyckades. - - - Message signed. - Meddelandet är signerat. - - - The signature could not be decoded. - Signaturen kunde inte avkodas. - - - Please check the signature and try again. - Kontrollera signaturen och försök igen. - - - The signature did not match the message digest. - Signaturen matchade inte meddelandesammanfattningen. - - - Message verification failed. - Meddelandet verifikation misslyckades. - - - Message verified. - Meddelandet är verifierad. - - - - SplashScreen - - Bitcoin Core - Bitcoin Kärna - - - The Bitcoin Core developers - Bitcoin Core-utvecklarna - - - [testnet] - [testnet] - - - - TrafficGraphWidget - - KB/s - KB/s - - - - TransactionDesc - - Open until %1 - Öppet till %1 - - - conflicted - konflikterade - - - %1/offline - %1/nerkopplad - - - %1/unconfirmed - %1/obekräftade - - - %1 confirmations - %1 bekräftelser - - - Status - Status - - - , broadcast through %n node(s) - , sänd genom %n nod, sänd genom %n noder - - - Date - Datum - - - Source - Källa - - - Generated - Genererad - - - From - Från - - - To - Till - - - own address - egen adress - - - watch-only - granska-bara - - - label - etikett - - - Credit - Kredit - - - matures in %n more block(s) - mognar om %n fler blockmognar om %n fler block - - - not accepted - inte accepterad - - - Debit - Belasta - - - Total debit - Total skuld - - - Total credit - Total kredit - - - Transaction fee - Transaktionsavgift - - - Net amount - Nettobelopp - - - Message - Meddelande - - - Comment - Kommentar - - - Transaction ID - Transaktions-ID - - - Merchant - Handlare - - - 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. - Genererade mynt måste vänta %1 block innan de kan användas. När du skapade detta block sändes det till nätverket för att läggas till i blockkedjan. Om blocket inte kommer in i kedjan kommer dess status att ändras till "accepteras inte" och kommer ej att gå att spendera. Detta kan ibland hända om en annan nod genererar ett block nästan samtidigt som dig. - - - Debug information - Debug information - - - Transaction - Transaktion - - - Inputs - Inputs - - - Amount - Mängd - - - true - sant - - - false - falsk - - - , has not been successfully broadcast yet - , har inte lyckats skickas ännu - - - Open for %n more block(s) - Öppet för %n mer blockÖppet för %n mer block - - - unknown - okänd - - - - TransactionDescDialog - - Transaction details - Transaktionsdetaljer - - - This pane shows a detailed description of the transaction - Den här panelen visar en detaljerad beskrivning av transaktionen - - - - TransactionTableModel - - Date - Datum - - - Type - Typ - - - Immature (%1 confirmations, will be available after %2) - Omogen (%1 konfirmeringar, blir tillgänglig efter %2) - - - Open for %n more block(s) - Öppet för %n mer blockÖppet för %n mer block - - - Open until %1 - Öppet till %1 - - - Confirmed (%1 confirmations) - Bekräftad (%1 bekräftelser) - - - This block was not received by any other nodes and will probably not be accepted! - Det här blocket togs inte emot av några andra noder och kommer antagligen inte att bli godkänt. - - - Generated but not accepted - Genererad men inte accepterad - - - Offline - Nerkopplad - - - Label - Etikett - - - Unconfirmed - Okonfirmerade - - - Confirming (%1 of %2 recommended confirmations) - Konfirmerar (%1 of %2 konfirmeringar) - - - Conflicted - Konflikterade - - - Received with - Mottagen med - - - Received from - Mottaget från - - - Sent to - Skickad till - - - Payment to yourself - Betalning till dig själv - - - Mined - Genererade - - - watch-only - granska-bara - - - (n/a) - (n/a) - - - Transaction status. Hover over this field to show number of confirmations. - Transaktionsstatus. Håll muspekaren över för att se antal bekräftelser. - - - Date and time that the transaction was received. - Tidpunkt då transaktionen mottogs. - - - Type of transaction. - Transaktionstyp. - - - Whether or not a watch-only address is involved in this transaction. - Anger om granska-bara--adresser är involverade i denna transaktion. + Välj tidigare använda adresser - User-defined intent/purpose of the transaction. - Användardefinierat syfte/ändamål för transaktionen. + This is a normal payment. + Detta är en normal betalning. - Amount removed from or added to balance. - Belopp draget eller tillagt till balans. + The Bitcoin address to send the payment to + Bitcoinadress att sända betalning till - - - TransactionView - All - Alla + Alt+A + Alt+A - Today - Idag + Paste address from clipboard + Klistra in adress från Urklipp - This week - Denna vecka + Alt+P + Alt+P - This month - Denna månad + Remove this entry + Radera denna post - Last month - Föregående månad + 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. + Avgiften dras från beloppet som skickas. Mottagaren kommer att få mindre bitcoins än du angivit i belopp-fältet. Om flera mottagare valts kommer avgiften delas jämt. - This year - Det här året + S&ubtract fee from amount + S&ubtrahera avgiften från beloppet - Range... - Period... + Message: + Meddelande: - Received with - Mottagen med + This is an unauthenticated payment request. + Detta är en oautentiserad betalningsbegäran. - Sent to - Skickad till + This is an authenticated payment request. + Detta är en autentiserad betalningsbegäran. - To yourself - Till dig själv + Enter a label for this address to add it to the list of used addresses + Ange en etikett för denna adress att adderas till listan över använda adresser - Mined - Genererade + 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. + Ett meddelande som bifogades bitcoin-URI, vilket lagras med transaktionen som referens. NB: Meddelandet kommer inte att sändas över Bitcoinnätverket. - Other - Övriga + Pay To: + Betala Till: - Enter address or label to search - Sök efter adress eller etikett + Memo: + PM: + + + ShutdownWindow - Min amount - Minsta mängd + %1 is shutting down... + %1 stängs av... - Copy address - Kopiera adress + Do not shut down the computer until this window disappears. + Stäng inte av datorn förrän denna ruta försvinner. + + + SignVerifyMessageDialog - Copy label - Kopiera etikett + Signatures - Sign / Verify a Message + Signaturer - Signera / Verifiera ett Meddelande - Copy amount - Kopiera belopp + &Sign Message + &Signera Meddelande - Copy transaction ID - Kopiera transaktions ID + 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. + Du kan underteckna meddelanden/avtal med dina adresser för att bevisa att du kan ta emot bitcoins som skickats till dem. Var försiktig så du inte undertecknar något oklart eller konstigt, eftersom phishing-angrepp kan försöka få dig att underteckna din identitet till dem. Underteckna endast väldetaljerade meddelanden som du godkänner. - Copy raw transaction - Kopiera rå transaktion + The Bitcoin address to sign the message with + Bitcoinadress att signera meddelandet med - Edit label - Ändra etikett + Choose previously used address + Välj tidigare använda adresser - Show transaction details - Visa transaktionsdetaljer + Alt+A + Alt+A - Export Transaction History - Exportera Transaktionshistoriken + Paste address from clipboard + Klistra in adress från Urklipp - Watch-only - Granska-bara + Alt+P + Alt+P - Exporting Failed - Exporteringen misslyckades + Enter the message you want to sign here + Skriv in meddelandet du vill signera här - There was an error trying to save the transaction history to %1. - Det inträffade ett fel när transaktionshistoriken skulle sparas till %1. + Signature + Signatur - Exporting Successful - Exporteringen lyckades + Copy the current signature to the system clipboard + Kopiera signaturen till systemets Urklipp - The transaction history was successfully saved to %1. - Transaktionshistoriken sparades utan problem till %1. + Sign the message to prove you own this Bitcoin address + Signera meddelandet för att bevisa att du äger denna adress - Comma separated file (*.csv) - Kommaseparerad fil (*.csv) + Sign &Message + Signera &Meddelande - Confirmed - Bekräftad + Reset all sign message fields + Rensa alla fält - Date - Datum + Clear &All + Rensa &alla - Type - Typ + &Verify Message + &Verifiera Meddelande - Label - Etikett + 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! + Ange mottagarens adress, meddelande (kopiera radbrytningar, mellanrum, flikar, etc. exakt) och signatur nedan för att verifiera meddelandet. Undvik att läsa in mera information i signaturen än vad som stod i själva undertecknade meddelandet, för att undvika ett man-in-the-middle-angrepp. Notera att detta endast bevisar att undertecknad tar emot med adressen, det bevisar inte vem som skickat transaktionen! - Address - Adress + The Bitcoin address the message was signed with + Bitcoinadressen som meddelandet signerades med - ID - ID + Verify the message to ensure it was signed with the specified Bitcoin address + Verifiera meddelandet för att vara säker på att den var signerad med den angivna Bitcoin-adressen - Range: - Intervall: + Verify &Message + Verifiera &Meddelande - to - till + Reset all verify message fields + Rensa alla fält - UnitDisplayStatusBarControl + SplashScreen - Unit to show amounts in. Click to select another unit. - &Enhet att visa belopp i. Klicka för att välja annan enhet. + [testnet] + [testnet] - WalletFrame + TrafficGraphWidget - No wallet has been loaded. - Ingen plånbok har laddats in. + KB/s + KB/s - WalletModel + TransactionDescDialog - Send Coins - Skicka pengar + This pane shows a detailed description of the transaction + Den här panelen visar en detaljerad beskrivning av transaktionen - WalletView - - &Export - &Exportera - - - Export the data in the current tab to a file - Exportera informationen i den nuvarande fliken till en fil - - - Backup Wallet - Säkerhetskopiera Plånbok - - - Wallet Data (*.dat) - Plånboks-data (*.dat) - - - Backup Failed - Säkerhetskopiering misslyckades - - - There was an error trying to save the wallet data to %1. - Det inträffade ett fel när plånbokens data skulle sparas till %1. - - - The wallet data was successfully saved to %1. - Plånbokens data sparades utan problem till %1. - + UnitDisplayStatusBarControl - Backup Successful - Säkerhetskopiering lyckades + Unit to show amounts in. Click to select another unit. + &Enhet att visa belopp i. Klicka för att välja annan enhet. @@ -2928,14 +1758,6 @@ Var vänlig och försök igen. If <category> is not supplied or if <category> = 1, output all debugging information. Om <kategori> inte anges eller om <category> = 1, visa all avlusningsinformation. - - Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s) - Maximal total avgift (i %s) att använda i en plånbokstransaktion. Sätts denna för lågtkan stora transaktioner komma att avbrytas (förvalt: %s) - - - Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. - Vänligen kontrollera att din dators datum och tid är korrekt! Om din klocka går fel kommer Bitcoin Core inte att fungera ordentligt. - Prune configured below the minimum of %d MiB. Please use a higher number. Beskärning konfigurerad under miniminivån %d MiB. Vänligen använd ett högre värde. @@ -2976,6 +1798,10 @@ Var vänlig och försök igen. Accept connections from outside (default: 1 if no -proxy or -connect) Acceptera anslutningar utifrån (förvalt: 1 om ingen -proxy eller -connect) + + Bitcoin Core + Bitcoin Core + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. -fallbackfee är satt väldigt högt! Detta är avgiften du kan komma att betala om uppskattad avgift inte finns tillgänglig. @@ -2992,6 +1818,10 @@ Var vänlig och försök igen. Bind to given address and always listen on it. Use [host]:port notation for IPv6 Bind till given adress och lyssna alltid på den. Använd [värd]:port notation för IPv6 + + Cannot obtain a lock on data directory %s. %s is probably already running. + Kan inte låsa data-mappen %s. %s körs förmodligen redan. + Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup Ta bort alla plånbokstransaktioner och återskapa bara dom som är en del av blockkedjan genom att ange -rescan vid uppstart @@ -3000,6 +1830,14 @@ Var vänlig och försök igen. Distributed under the MIT software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>. Distribuerad under MIT mjukvarulicens, se den bifogade filen COPYING eller <http://www.opensource.org/licenses/mit-license.php>. + + Error loading %s: You can't enable HD on a already existing non-HD wallet + Fel vid laddning av %s: Du kan inte aktivera HD på en existerande icke-HD plånbok + + + Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Fel vid läsning av %s! Alla nycklar lästes korrekt, men transaktionsdatat eller adressbokens poster kanske saknas eller är felaktiga. + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) Exekvera kommando när en plånbokstransaktion ändras (%s i cmd är ersatt av TxID) @@ -3008,6 +1846,22 @@ Var vänlig och försök igen. Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) Vidarebefodra alltid transaktioner från vitlistade noder även om de bryter mot lokala reläpolicyn (förvalt: %d) + + Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds) + Maximalt tillåten median-peer tidsoffset justering. Lokalt perspektiv av tiden kan bli påverkad av partners, framåt eller bakåt denna tidsrymd. (förvalt: %u sekunder) + + + Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s) + Maximal total avgift (i %s) att använda i en plånbokstransaktion eller råa transaktioner. Sätts denna för lågt kan stora transaktioner avbrytas (förvalt: %s) + + + Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly. + Vänligen kolla så att din dators datum och tid är korrekt! Om din klocka går fel kommer %s inte att fungera korrekt. + + + Please contribute if you find %s useful. Visit %s for further information about the software. + Var snäll och bidra om du finner %s användbar. Besök %s för mer information om mjukvaran. + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) Ange antalet skriptkontrolltrådar (%u till %d, 0 = auto, <0 = lämna så många kärnor lediga, förval: %d) @@ -3020,14 +1874,6 @@ Var vänlig och försök igen. This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Detta är ett förhands testbygge - använd på egen risk - använd inte för mining eller handels applikationer - - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - Det går inte att binda till %s på den här datorn. Bitcoin Core är förmodligen redan igång. - - - Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. - Argumentet -whitelistalwaysrelay stöds inte utan ignoreras, använd -whitelistrelay och/eller -whitelistforcerelay. - Use UPnP to map the listening port (default: 1 when listening and no -proxy) Använd UPnP för att mappa den lyssnande porten (förvalt: 1 när lyssning aktiverat och utan -proxy) @@ -3044,22 +1890,22 @@ Var vänlig och försök igen. Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Varning: Nätverket verkar inte vara helt överens! Några miners verkar ha problem. - - Warning: Unknown block versions being mined! It's possible unknown rules are in effect - Varning: Okända blockversioner bryts! Det är möjligt att okända regler används - Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Varning: Vi verkar inte helt överens med våra peers! Du kan behöva uppgradera, eller andra noder kan behöva uppgradera. - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Varning: wallet.dat korrupt, datan har räddats! Den ursprungliga wallet.dat har sparas som wallet.{timestamp}.bak i %s; om ditt saldo eller transaktioner är felaktiga ska du återställa från en säkerhetskopia. - Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. Vitlista klienter som ansluter från angivna nätmasker eller IP-adresser. Kan specificeras flera gånger. + + You need to rebuild the database using -reindex-chainstate to change -txindex + Du måste återskapa databasen med -reindex-chainstate för att ändra -txindex + + + %s corrupt, salvage failed + %s är korrupt, räddning misslyckades + -maxmempool must be at least %d MB -maxmempool måste vara minst %d MB @@ -3072,10 +1918,22 @@ Var vänlig och försök igen. Append comment to the user agent string Lägg till kommentar till user-agent-strängen + + Attempt to recover private keys from a corrupt wallet on startup + Försök att rädda privata nycklar från en korrupt plånbok vid uppstart + Block creation options: Block skapande inställningar: + + Cannot resolve -%s address: '%s' + Kan inte matcha -%s adress: '%s' + + + Change index out of range + Förändringsindexet utom räckhåll + Connect only to the specified node(s) Koppla enbart upp till den/de specificerade noden/noder @@ -3084,6 +1942,10 @@ Var vänlig och försök igen. Connection options: Anslutningsalternativ: + + Copyright (C) %i-%i + Copyright (C) %i-%i + Corrupted block database detected Korrupt blockdatabas har upptäckts @@ -3128,6 +1990,22 @@ Var vänlig och försök igen. Error initializing wallet database environment %s! Fel vid initiering av plånbokens databasmiljö %s! + + Error loading %s + Fel vid inläsning av %s + + + Error loading %s: Wallet corrupted + Fel vid inläsningen av %s: Plånboken är koruppt + + + Error loading %s: Wallet requires newer version of %s + Fel vid inläsningen av %s: Plånboken kräver en senare version av %s + + + Error loading %s: You can't disable HD on a already existing HD wallet + Fel vid laddning av %s: Du kan inte avaktivera HD på en redan existerande HD plånbok + Error loading block database Fel vid inläsning av blockdatabasen @@ -3152,10 +2030,18 @@ Var vänlig och försök igen. Incorrect or no genesis block found. Wrong datadir for network? Felaktig eller inget genesisblock hittades. Fel datadir för nätverket? + + Initialization sanity check failed. %s is shutting down. + Initieringschecken fallerade. %s stängs av. + Invalid -onion address: '%s' Ogiltig -onion adress:'%s' + + Invalid amount for -%s=<amount>: '%s' + Ogiltigt belopp för -%s=<belopp>:'%s' + Invalid amount for -fallbackfee=<amount>: '%s' Ogiltigt belopp för -fallbackfee=<belopp>: '%s' @@ -3164,6 +2050,10 @@ Var vänlig och försök igen. Keep the transaction memory pool below <n> megabytes (default: %u) Håll minnespoolen över transaktioner under <n> megabyte (förvalt: %u) + + Loading banlist... + Laddar svarta listan... + Location of the auth cookie (default: data dir) Plats för authcookie (förvalt: datamapp) @@ -3180,6 +2070,10 @@ Var vänlig och försök igen. Only connect to nodes in network <net> (ipv4, ipv6 or onion) Anslut enbart till noder i nätverket <net> (IPv4, IPv6 eller onion) + + Print this help message and exit + Visa denna hjälptext och avsluta + Print version and exit Visa version och avsluta @@ -3192,6 +2086,14 @@ Var vänlig och försök igen. Prune mode is incompatible with -txindex. Beskärningsläge är inkompatibel med -txindex. + + Rebuild chain state and block index from the blk*.dat files on disk + Återskapa blockkedjans status och index från blk*.dat filer på disken + + + Rebuild chain state from the currently indexed blocks + Återskapa blockkedjans status från aktuella indexerade block + Set database cache size in megabytes (%d to %d, default: %d) Sätt databasens cachestorlek i megabyte (%d till %d, förvalt: %d) @@ -3204,6 +2106,14 @@ Var vänlig och försök igen. Specify wallet file (within data directory) Ange plånboksfil (inom datakatalogen) + + The source code is available from %s. + Källkoden är tillgänglig från %s. + + + Unable to bind to %s on this computer. %s is probably already running. + Det går inte att binda till %s på den här datorn. %s är förmodligen redan igång. + Unsupported argument -benchmark ignored, use -debug=bench. Argumentet -benchmark stöds inte och ignoreras, använd -debug=bench. @@ -3237,12 +2147,16 @@ Var vänlig och försök igen. Plånbok %s ligger utanför datakatalogen %s - Wallet options: - Plånboksinställningar: + Wallet debugging/testing options: + Plånbokens Avlusnings/Testnings optioner: + + + Wallet needed to be rewritten: restart %s to complete + Plånboken behöver sparas om: Starta om %s för att fullfölja - You need to rebuild the database using -reindex to change -txindex - Du måste återskapa databasen med -reindex för att ändra -txindex + Wallet options: + Plånboksinställningar: 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 @@ -3256,10 +2170,6 @@ Var vänlig och försök igen. Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces) Bind till angiven adress för att lyssna på JSON-RPC-anslutningar. Använd [värd]:port-format for IPv6. Detta alternativ kan anges flera gånger (förvalt: bind till alla gränssnitt) - - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - Kan inte låsa data-mappen %s. Bitcoin Core körs förmodligen redan. - Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) Skapa nya filer med systemets förvalda rättigheter, istället för umask 077 (bara effektivt med avaktiverad plånboks funktionalitet) @@ -3304,10 +2214,6 @@ Var vänlig och försök igen. Set maximum size of high-priority/low-fee transactions in bytes (default: %d) Sätt den maximala storleken av hög-prioriterade/låg-avgifts transaktioner i byte (förvalt: %d) - - Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) - Ange antalet trådar för myntgenerering om påslagen (-1= alla kärnor, förval: %d) - The transaction amount is too small to send after the fee has been deducted Transaktionen är för liten att skicka efter det att avgiften har dragits @@ -3316,6 +2222,10 @@ Var vänlig och försök igen. This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard. Denna produkten innehåller mjukvara utvecklad av OpenSSL Project för användning i OpenSSL Toolkit <https://www.openssl.org/> och kryptografisk mjukvara utvecklad av Eric Young samt UPnP-mjukvara skriven av Thomas Bernard. + + Use hierarchical deterministic key generation (HD) after BIP32. Only has effect during wallet creation/first start + Använd hierarkisk deterministisk nyckel generering (HD) efter BIP32. Har bara effekt under plånbokens skapande/första användning. + 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 Vitlistade klienter kan inte bli DoS-bannade och deras transaktioner reläas alltid, även om dom redan är i mempoolen, användbart för t.ex en gateway @@ -3332,34 +2242,14 @@ Var vänlig och försök igen. Accept public REST requests (default: %u) Acceptera publika REST förfrågningar (förvalt: %u) - - Activating best chain... - Aktiverar bästa kedjan... - - - Attempt to recover private keys from a corrupt wallet.dat on startup - Försök att rädda privata nycklar från en korrupt wallet.dat vid uppstart - Automatically create Tor hidden service (default: %d) Skapa automatiskt dold tjänst i Tor (förval: %d) - - Cannot resolve -whitebind address: '%s' - Kan inte matcha -whitebind adress: '%s' - Connect through SOCKS5 proxy Anslut genom SOCKS5 proxy - - Copyright (C) 2009-%i The Bitcoin Core Developers - Copyright (C) 2009-%i Bitcoin Core Utvecklarna - - - Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - Fel vid inläsningen av wallet.dat: Kontofilen kräver en senare version av Bitcoin Core - Error reading from database, shutting down. Fel vid läsning från databas, avslutar. @@ -3372,22 +2262,6 @@ Var vänlig och försök igen. Information Information - - Initialization sanity check failed. Bitcoin Core is shutting down. - Initieringschecken fallerade. Bitcoin Core stängs av... - - - Invalid amount for -maxtxfee=<amount>: '%s' - Otillåtet belopp för -maxtxfee=<belopp>: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Ogiltigt belopp för -minrelaytxfee=<belopp>: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - Ogiltigt belopp för -mintxfee=<belopp>: '%s' - Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) Ogiltigt belopp för -paytxfee=<belopp>:'%s' (måste vara minst %s) @@ -3412,14 +2286,6 @@ Var vänlig och försök igen. RPC server options: RPC-serveralternativ: - - Rebuild block chain index from current blk000??.dat files on startup - Återskapa blockkedjans index från nuvarande blk000??.dat filer under uppstarten - - - Receive and display P2P network alerts (default: %u) - Mottag och visa P2P nätverksvarningar (förvalt: %u) - Reducing -maxconnections from %d to %d, because of system limitations. Minskar -maxconnections från %d till %d, på grund av systembegränsningar. @@ -3492,10 +2358,6 @@ Var vänlig och försök igen. Username for JSON-RPC connections Användarnamn för JSON-RPC-anslutningar - - Wallet needed to be rewritten: restart Bitcoin Core to complete - Kontot behöver sparas om: Starta om Bitcoin Core för att fullfölja - Warning Varning @@ -3516,10 +2378,6 @@ Var vänlig och försök igen. ZeroMQ notification options: ZeroMQ-alternativ för notiser: - - wallet.dat corrupt, salvage failed - wallet.dat korrupt, räddning misslyckades - Password for JSON-RPC connections Lösenord för JSON-RPC-anslutningar @@ -3528,10 +2386,6 @@ Var vänlig och försök igen. Execute command when the best block changes (%s in cmd is replaced by block hash) Exekvera kommando när det bästa blocket ändras (%s i cmd är utbytt av blockhash) - - This help message - Det här hjälp medelandet - Allow DNS lookups for -addnode, -seednode and -connect Tillåt DNS-sökningar för -addnode, -seednode och -connect @@ -3540,10 +2394,6 @@ Var vänlig och försök igen. Loading addresses... Laddar adresser... - - Error loading wallet.dat: Wallet corrupted - Fel vid inläsningen av wallet.dat: Plånboken är skadad - (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) (1 = spara tx metadata t.ex. kontoägare och betalningsbegäransinformation, 2 = släng tx metadata) @@ -3560,10 +2410,6 @@ Var vänlig och försök igen. Do not keep transactions in the mempool longer than <n> hours (default: %u) Håll inte transaktioner i minnespoolen längre än <n> timmar (förvalt: %u) - - Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. - Fel vid läsning av wallet.dat! Alla nycklar lästes korrekt, men transaktionsdata eller adressbokens poster kanske saknas eller är felaktiga. - Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) Avgifter (i %s/kB) mindre än detta anses vara nollavgifter vid skapande av transaktion (standard: %s) @@ -3600,6 +2446,10 @@ Var vänlig och försök igen. Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported. Argumentet -socks hittades och stöds inte. Det är inte längre möjligt att sätta SOCKS-version längre, bara SOCKS5-proxy stöds. + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + Argumentet -whitelistalwaysrelay stöds inte utan ignoreras, använd -whitelistrelay och/eller -whitelistforcerelay. + Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s) Använd separat SOCKS5 proxy för att nå kollegor via dolda tjänster i Tor (förvalt: -%s) @@ -3609,20 +2459,20 @@ Var vänlig och försök igen. Användarnamn och hashat lösenord för JSON-RPC-anslutningar. Fältet <userpw> kommer i formatet: <USERNAME>:<SALT>$<HASH>. Ett kanoniskt pythonskript finns inkluderat i share/rpcuser. Detta alternativ kan anges flera gånger - (default: %s) - (förvalt: %s) + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + Varning: Okända blockversioner bryts! Det är möjligt att okända regler används - Always query for peer addresses via DNS lookup (default: %u) - Sök alltid efter klientadresser med DNS sökningen (förvalt: %u) + Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup. + Varning: Plånboksfilen var korrupt, datat har räddats! Den ursprungliga %s har sparas som %s i %s. Om ditt saldo eller transaktioner är felaktiga bör du återställa från en säkerhetskopia. - Error loading wallet.dat - Fel vid inläsning av plånboksfilen wallet.dat + (default: %s) + (förvalt: %s) - Generate coins (default: %u) - Generera mynt (förvalt: %u) + Always query for peer addresses via DNS lookup (default: %u) + Sök alltid efter klientadresser med DNS sökningen (förvalt: %u) How many blocks to check at startup (default: %u, 0 = all) @@ -3708,18 +2558,6 @@ Var vänlig och försök igen. Unknown network specified in -onlynet: '%s' Okänt nätverk som anges i -onlynet: '%s' - - Cannot resolve -bind address: '%s' - Kan inte matcha -bind adress: '%s' - - - Cannot resolve -externalip address: '%s' - Kan inte matcha -externalip adress: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - Ogiltigt belopp för -paytxfee=<belopp>:'%s' - Insufficient funds Otillräckligt med bitcoins diff --git a/src/qt/locale/bitcoin_ta.ts b/src/qt/locale/bitcoin_ta.ts index c93524cdacc2f..6878d23fe22ea 100644 --- a/src/qt/locale/bitcoin_ta.ts +++ b/src/qt/locale/bitcoin_ta.ts @@ -17,10 +17,6 @@ C&lose &மூடு - - &Copy Address - &முகவரியை நகலெடு - &Export &ஏற்றுமதி @@ -29,44 +25,9 @@ &Delete &அழி - - C&hoose - &தேர்ந்தெடு - - - Sending addresses - அனுப்பும் முகவரிகள் - - - Receiving addresses - பெறும் முகவரிகள் - - - &Edit - &தொகு - - - - AddressTableModel - - Label - லேபிள் - - - Address - விலாசம் - - + AskPassphraseDialog - - Encrypt wallet - என்க்ரிப்ட் பணப்பை - - - Decrypt wallet - டிக்ரிப்ட் பணப்பை - BanTableModel @@ -145,10 +106,6 @@ &Help &உதவி - - Bitcoin Core - Bitcoin மையம் - %n hour(s) %n மணி%n மணி @@ -202,13 +159,6 @@ அனுப்பிய பரிவர்த்தனை - - ClientModel - - Network Alert - பிணைய எச்சரிக்கை - - CoinControlDialog @@ -255,27 +205,7 @@ Priority முன்னுரிமை - - Copy address - பிரதியை முகவரியை - - - Copy amount - நகலை தொகை - - - none - none - - - yes - ஆம் - - - no - இல்லை - - + EditAddressDialog @@ -288,14 +218,6 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin மையம் - - - About Bitcoin Core - Bitcoin மையம் பற்றி - Intro @@ -303,10 +225,6 @@ Welcome நல்வரவு - - Bitcoin Core - Bitcoin மையம் - Error தவறு @@ -413,9 +331,6 @@ மொத்தம்: - - PaymentServer - PeerTableModel @@ -454,25 +369,6 @@ %1 ms - - QRImageWidget - - &Save Image... - &படத்தை சேமி... - - - &Copy Image - &படத்தை - - - Save QR Code - QR குறியீடு காப்பாற்ற - - - PNG Image (*.png) - PNG படத்தை (*.png) - - RPCConsole @@ -638,14 +534,6 @@ Remove நீக்கு - - Copy message - நகலை செய்தி - - - Copy amount - நகலை தொகை - ReceiveRequestDialog @@ -665,46 +553,7 @@ &Save Image... &படத்தை சேமி... - - URI - URI - - - Address - விலாசம் - - - Amount - விலை - - - Label - லேபிள் - - - Message - செய்தி - - - - RecentRequestsTableModel - - Date - தேதி - - - Label - லேபிள் - - - Message - செய்தி - - - Amount - விலை - - + SendCoinsDialog @@ -755,19 +604,7 @@ S&end &அனுப்பு - - %1 to %2 - %1 to %2 - - - Copy amount - நகலை தொகை - - - or - அல்லது - - + SendCoinsEntry @@ -811,10 +648,6 @@ SplashScreen - - Bitcoin Core - Bitcoin மையம் - TrafficGraphWidget @@ -823,188 +656,18 @@ KB/s - - TransactionDesc - - Status - நிலை - - - Date - தேதி - - - Source - மூலம் - - - Credit - கடன் - - - Debit - பற்று - - - Total debit - மொத்த பற்று - - - Total credit - மொத்த கடன் - - - Net amount - நிகர தொகை - - - Message - செய்தி - - - Comment - கருத்து - - - Transaction ID - பரிவர்த்தனை ID - - - Merchant - வணிகர் - - - Debug information - சரிசெய்வதற்கான தகவல் - - - Transaction - பரிவர்த்தனை - - - Inputs - உள்ளீடுகள் - - - Amount - விலை - - - true - உண்மை - - - false - தவறான - - TransactionDescDialog - - TransactionTableModel - - Date - தேதி - - - Offline - ஆஃப்லைன் - - - Label - லேபிள் - - - (n/a) - (n/a) - - - - TransactionView - - All - முழுவதும் - - - Today - இன்று - - - This week - இந்த வாரம் - - - This month - இந்த மாதம் - - - Last month - கடந்த மாதம் - - - This year - இந்த வருடம் - - - Range... - எல்லை... - - - Other - வேறு - - - Copy address - பிரதியை முகவரியை - - - Copy amount - நகலை தொகை - - - Confirmed - உறுதியாக - - - Date - தேதி - - - Label - லேபிள் - - - Address - விலாசம் - - - ID - ID - - - Range: - எல்லை: - - UnitDisplayStatusBarControl - WalletFrame - - - WalletModel - - - WalletView + bitcoin-core - &Export - &ஏற்றுமதி + Bitcoin Core + Bitcoin மையம் - - - bitcoin-core (default: %u) (default: %u) diff --git a/src/qt/locale/bitcoin_th_TH.ts b/src/qt/locale/bitcoin_th_TH.ts index ba3b1e8741baa..2630939146563 100644 --- a/src/qt/locale/bitcoin_th_TH.ts +++ b/src/qt/locale/bitcoin_th_TH.ts @@ -25,10 +25,6 @@ C&lose &ปิด - - &Copy Address - &คัดลอกที่อยู่ - Delete the currently selected address from the list ลบที่อยู่ที่เลือกไว้ในขณะนี้จากรายการ @@ -45,72 +41,13 @@ &Delete &ลบ - - Choose the address to send coins to - เลือกที่อยู่เพื่อส่งเหรียญไปไว้ - - - Choose the address to receive coins with - เลือกที่อยู่เพื่อรับเหรียญไว้ - - - C&hoose - &เลือก - - - Sending addresses - ส่งที่อยู่ - - - Receiving addresses - กำลังรับที่อยู่ - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - ที่อยู่เหล่านี้เป็นที่อยู่ Bitcoin ของคุณ สำหรับใช้เพื่อส่งเงิน กรุณาตรวจสอบจำนวนเงินและที่อยู่สำหรับรับเงินก่อนส่งเหรียญไป - - - Copy &Label - คัดลอก &ป้ายชื่อ - - - &Edit - &แก้ไข - - - Export Address List - ส่งออกรายการที่อยู่ - - - Comma separated file (*.csv) - คั่นไฟล์ด้วยเครื่องหมายจุลภาค (*.csv) - - - Exporting Failed - ส่งออกข้อมูลล้มเหลว - - - There was an error trying to save the address list to %1. Please try again. - พบข้อผิดพลาดบางกระการในการพยายามบันทึกรายชื่อที่อยู่ไปยัง %1. กรุณาลองใหม่อีกครั้ง - - AddressTableModel - - Label - ชื่อ - + AskPassphraseDialog - Address - ที่อยู่ + Passphrase Dialog + ช่องสำหรับ รหัสผ่าน - - (no label) - (ไม่มีชื่อ) - - - - AskPassphraseDialog Enter passphrase ใส่รหัสผ่าน @@ -123,107 +60,115 @@ Repeat new passphrase กรุณากรอกรหัสผ่านใหม่อีกครั้งหนึ่ง + + + BanTableModel - Encrypt wallet - กระเป๋าสตางค์ที่เข้ารหัส + IP/Netmask + IP/Netmask (ตัวกรอง IP) - This operation needs your wallet passphrase to unlock the wallet. - การดำเนินการนี้ต้องมีรหัสผ่านกระเป๋าเงินของคุณเพื่อปลดล็อคกระเป๋าเงิน + Banned Until + ห้าม จนถึง + + + + BitcoinGUI + + Sign &message... + เซ็นต์ชื่อด้วย &ข้อความ... + + + Synchronizing with network... + กำลังทำข้อมูลให้ตรงกันกับเครือข่าย ... - Unlock wallet - เปิดกระเป๋าสตางค์ + &Overview + &ภาพรวม - This operation needs your wallet passphrase to decrypt the wallet. - การดำเนินการนี้ต้องมีรหัสผ่านกระเป๋าเงินของคุณในการถอดรหัสกระเป๋าเงิน + Node + Node/โหนด - Decrypt wallet - ถอดรหัสกระเป๋าสตางค์ + Show general overview of wallet + แสดงภาพรวมทั่วไปของกระเป๋าเงิน - Change passphrase - เปลี่ยนรหัสผ่าน + &Transactions + &การทำรายการ - Confirm wallet encryption - ยืนยันการเข้ารหัสกระเป๋าสตางค์ + Browse transaction history + เรียกดูประวัติการทำธุรกรรม - Are you sure you wish to encrypt your wallet? - คุณแน่ใจแล้วหรือว่าต้องการเข้ารหัสกระเป๋าสตางค์ของคุณ? + E&xit + &ออก - Wallet encrypted - กระเป๋าสตางค์ถูกเข้ารหัสเรียบร้อยแล้ว + Quit application + ออกจากโปรแกรม - Wallet encryption failed - การเข้ารหัสกระเป๋าสตางค์ผิดพลาด + &About %1 + &เกี่ยวกับ %1 - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - กระเป๋าเงินเข้ารหัสล้มเหลวเนื่องจากข้อผิดพลาดภายใน กระเป๋าเงินของคุณไม่ได้เข้ารหัส + Show information about %1 + แสดงข้อมูล เกี่ยวกับ %1 - The supplied passphrases do not match. - รหัสผ่านที่คุณกรอกไม่ตรงกัน + About &Qt + เกี่ยวกับ &Qt - Wallet unlock failed - ปลดล็อคกระเป๋าเงินล้มเหลว + Show information about Qt + แสดงข้อมูล เกี่ยวกับ Qt - The passphrase entered for the wallet decryption was incorrect. - ป้อนรหัสผ่านสำหรับการถอดรหัสกระเป๋าเงินไม่ถูกต้อง + &Options... + &ตัวเลือก... - Wallet decryption failed - ถอดรหัสกระเป๋าเงินล้มเหลว + Modify configuration options for %1 + ปรับปรุง ข้อมูลการตั้งค่าตัวเลือก สำหรับ %1 - - - BanTableModel - - - BitcoinGUI - Synchronizing with network... - กำลังทำข้อมูลให้ตรงกันกับเครือข่าย ... + &Encrypt Wallet... + &กระเป๋าเงินเข้ารหัส - &Overview - &ภาพรวม + &Backup Wallet... + &สำรองกระเป๋าเงิน... - Show general overview of wallet - แสดงภาพรวมทั่วไปของกระเป๋าเงิน + &Change Passphrase... + &เปลี่ยนรหัสผ่าน... - &Transactions - &การทำรายการ + &Sending addresses... + &ที่เก็บเงิน ที่จะส่ง bitcoin - Browse transaction history - เรียกดูประวัติการทำธุรกรรม + &Receiving addresses... + &ที่เก็บเงิน ที่จะรับ bitcoin - E&xit - E&ออก + Open &URI... + เปิด &URI - Quit application - ออกจากโปรแกรม + Reindexing blocks on disk... + กำลังทำดัชนี ที่เก็บบล็อก ใหม่ ในดิสก์... - About &Qt - เกี่ยวกับ &Qt + Send coins to a Bitcoin address + ส่ง coins ไปยัง ที่เก็บ Bitcoin - &Options... - &ตัวเลือก... + Backup wallet to another location + สำรอง กระเป๋าเงินไปยัง ที่เก็บอื่น Change the passphrase used for wallet encryption @@ -231,7 +176,11 @@ &Debug window - &หน้าต่างตรวจสอบข้อผิดพลาด + &หน้าต่าง Debug + + + Open debugging and diagnostic console + เปิด แผลงควบคุม debugging และ diagnostic &Verify message... @@ -243,7 +192,7 @@ Wallet - กระเป๋าสตางค์ + กระเป๋าเงิน &Send @@ -253,6 +202,26 @@ &Receive &รับ + + &Show / Hide + &แสดง / ซ่อน + + + Show or hide the main Window + แสดง หรือ ซ่อน หน้าหลัก + + + Encrypt the private keys that belong to your wallet + เข้ารหัส private keys/ รหัสส่วนตัว สำหรับกระเป๋าเงินของท่าน + + + Sign messages with your Bitcoin addresses to prove you own them + เซ็นชื่อด้วยข้อความ ที่เก็บ Bitcoin เพื่อแสดงว่าท่านเป็นเจ้าของ bitcoin นี้จริง + + + Verify messages to ensure they were signed with specified Bitcoin addresses + ตรวจสอบ ข้อความ เพื่อให้แน่ใจว่า การเซ็นต์ชื่อ ด้วยที่เก็บ Bitcoin แล้ว + &File &ไฟล์ @@ -269,17 +238,135 @@ Tabs toolbar แถบเครื่องมือ + + Request payments (generates QR codes and bitcoin: URIs) + เรียกเก็บ การชำระเงิน (สร้าง QR codes และ bitcoin: URIs) + + + Show the list of used sending addresses and labels + แสดงรายการ ที่เก็บเงินที่จะส่ง bitcoin ออก และป้ายชื่อ ที่ใช้ไปแล้ว + + + Show the list of used receiving addresses and labels + แสดงรายการ ที่เก็บเงินที่จะรับ bitcoin เข้า และป้ายชื่อ ที่ใช้ไปแล้ว + + + Open a bitcoin: URI or payment request + เปิด bitcoin: URI หรือ การเรียกเก็บเงิน (การเรียกให้ชำระเงิน) + + + &Command-line options + &ตัวเลือก Command-line + %n active connection(s) to Bitcoin network - %n ที่ใช้งานการเชื่อมต่อกับเครือข่าย Bitcoin + %n ช่องการเชื่อมต่อที่ใช้งานได้ เพื่อเชื่อมกับเครือข่าย Bitcoin + + + Indexing blocks on disk... + การกำลังสร้างดัชนีของบล็อก ในดิสก์... + + + Processing blocks on disk... + กำลังดำเนินการกับบล็อกในดิสก์... + + + No block source available... + ไม่มีบล็อกเริ่มต้น ให้ใช้ได้... + + + Processed %n block(s) of transaction history. + %n บล็อกในประวัติรายการ ได้รับการดำเนินการเรียบร้อยแล้ว + + + %n hour(s) + %n ชั่วโมง + + + %n day(s) + %n วัน + + + %n week(s) + %n สัปดาห์ + + + %1 and %2 + %1 และ %2 + + + %n year(s) + %n ปี + + + %1 behind + %1 ตามหลัง + + + Last received block was generated %1 ago. + บล็อกสุดท้ายที่ได้รับ สร้างขึ้นเมื่อ %1 มาแล้ว + + + Transactions after this will not yet be visible. + รายการหลังจากนี้ จะไม่แสดงให้เห็น + + + Error + ข้อผิดพลาด + + + Warning + คำเตือน + + + Information + ข้อมูล Up to date ทันสมัย + + Show the %1 help message to get a list with possible Bitcoin command-line options + แสดง %1 ข้อความช่วยเหลือ เพื่อแสดงรายการ ตัวเลือกที่เป็นไปได้สำหรับ Bitcoin command-line + + + %1 client + %1 ลูกค้า + Catching up... - จับได้... + กำลังตามให้ทัน... + + + Date: %1 + + วันที่: %1 + + + + Amount: %1 + + จำนวน: %1 + + + + Type: %1 + + ชนิด: %1 + + + + Label: %1 + + ป้ายชื่อ: %1 + + + + Address: %1 + + ที่อยู่: %1 + Sent transaction @@ -298,15 +385,68 @@ กระเป๋าเงินถูก <b>เข้ารหัส</b> และในปัจจุบัน <b>ล็อค </b> - - ClientModel - CoinControlDialog + + Coin Selection + การเลือก Coin + + + Quantity: + จำนวน: + + + Bytes: + ไบต์: + + + Amount: + จำนวน: + + + Priority: + ความเร่งด่วน: + + + Fee: + ค่าธรรมเนียม: + + + Dust: + เศษ: + + + After Fee: + ส่วนที่เหลือจากค่าธรรมเนียม: + + + Change: + เงินทอน: + + + (un)select all + (ไม่)เลือกทั้งหมด + + + Tree mode + โหมดแบบต้นไม้ + + + List mode + โหมดแบบรายการ + Amount จำนวน + + Received with label + รับโดยป้ายชื่อ (label) + + + Received with address + รับโดยที่เก็บ + Date วันที่ @@ -323,11 +463,7 @@ Priority ระดับความสำคัญ - - (no label) - (ไม่มีชื่อ) - - + EditAddressDialog @@ -336,59 +472,299 @@ &Label - &ชื่อ + &ป้ายชื่อ + + + The label associated with this address list entry + รายการแสดง ป้ายชื่อที่เกี่ยวข้องกับที่เก็บนี้ + + + The address associated with this address list entry. This can only be modified for sending addresses. + ที่เก็บที่เกี่ยวข้องกับ ที่เก็บที่แสดงรายการนี้ การปรับปรุงนี้ทำได้สำหรับ ที่เก็บเงินที่จะใช่ส่งเงิน เท่านั้น &Address - &ที่อยู่ + &ที่เก็บ + + + + FreespaceChecker + + A new data directory will be created. + ไดเร็กทอรี่ใหม่ที่ใช้เก็บข้อมูลจะถูกสร้างขึ้นมา + + + name + ชื่อ + + + Path already exists, and is not a directory. + พาธ มีอยู่แล้ว พาธนี่ไม่ใช่ไดเร็กทอรี่ + + + Cannot create data directory here. + ไม่สามารถสร้างไดเร็กทอรี่ข้อมูลที่นี่ + + + + HelpMessageDialog + + version + เวอร์ชั่น + + + (%1-bit) + (%1-บิท) + + + About %1 + เกี่ยวกับ %1 + + + Command-line options + ตัวเลือก Command-line + + + Usage: + วิธีใช้งาน: + + + command-line options + ตัวเลือก command-line - New receiving address - ที่อยู่ผู้รับใหม่ + UI Options: + ตัวเลือก UI: - New sending address - ที่อยู่ผู้ส่งใหม่ + Choose data directory on startup (default: %u) + เลือกไดเร็กทอรี่ข้อมูลตั้งแต่เริ่มต้นสตาร์ทอัพ (ค่าเริ่มต้น: %u) - Edit receiving address - แก้ไขที่อยู่ผู้รับ + Set language, for example "de_DE" (default: system locale) + ตั้งค่าภาษา ยกตัวอย่าง "de_DE" (ค่าเริ่มต้น: ภาษาท้องถิ่นของระบบ) - Edit sending address - แก้ไขที่อยู่ผู้ส่ง + Start minimized + เริ่มต้นมินิไมซ์ - The entered address "%1" is already in the address book. - ป้อนที่อยู่ "%1" ที่มีอยู่แล้วในสมุดที่อยู่ + Set SSL root certificates for payment request (default: -system-) + ตั้งค่า SSL root certificates สำหรับเรียกการชำระเงิน (ค่าเริ่มต้น: -system-) - Could not unlock wallet. - ไม่สามารถปลดล็อคกระเป๋าเงิน + Show splash screen on startup (default: %u) + แสดง splash screen ตอนเริ่มต้น (ค่าเริ่มต้น: %u) - New key generation failed. - สร้างกุญแจใหม่ล้มเหลว + Reset all settings changed in the GUI + รีเซตการเปลี่ยนการตั้งค่าทั้งหมดใน GUI - - FreespaceChecker - - - HelpMessageDialog - Intro - + + Welcome + ยินดีต้อนรับ + + + Welcome to %1. + ยินดีต้องรับสู่ %1 + + + As this is the first time the program is launched, you can choose where %1 will store its data. + นี่เป็นการรันโปรแกรมครั้งแรก ท่านสามารถเลือก ว่าจะเก็บข้อมูลไว้ที่ %1 + + + %1 will download and store a copy of the Bitcoin block chain. At least %2GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. + %1 จะดาวน์โหลดและเก็บกอปปี้ชุดหนึ่งของ บล็อกเชน Bitcoin ไว้ ข้อมูลขนานอย่างน้อย %2GB จะเก็บไว้ในไดเร็กทอรี่นี้ และข้อมูลจะมีขนาดใหญ่ขึ้นเรื่อยๆ กระเป๋าเงิน จะเก็บไว้ในไดเร็กทอรี่นี้ด้วย + + + Use the default data directory + ใช้ไดเร็กทอรี่ข้อมูล ที่เป็นค่าเริ่มต้น + + + Use a custom data directory: + ใช้ไดเร็กทอรี่ข้อมูลที่ตั้งค่าเอง: + + + Error: Specified data directory "%1" cannot be created. + ข้อผิดพลาด: ไดเร็กทอรี่ข้อมูลที่ต้องการ "%1" ไม่สามารถสร้างได้ + + + Error + ข้อผิดพลาด + + + %n GB of free space available + %n GB พื้นที่ว่างบนดิสก์ที่ใช้ได้ + + + (of %n GB needed) + (ต้องการพื้นที่ %n GB) + + OpenURIDialog - + + Open URI + เปิด URI + + + Open payment request from URI or file + เปิด การเรียกการชำระเงิน จาก URI หรือ ไฟล์ + + + URI: + URI: + + + Select payment request file + เลือก ไฟล์การเรียกการชำระเงิน + + OptionsDialog Options ตัวเลือก + + &Main + &หลัก + + + Automatically start %1 after logging in to the system. + เริ่มต้นอัตโนมัติ %1 หลังจาก ล็อกอิน เข้าสู่ระบบแล้ว + + + &Start %1 on system login + &เริ่ม %1 ในการล็อกอินระบบ + + + Size of &database cache + ขนาดของ &database cache + + + MB + MB + + + Number of script &verification threads + จำนวนของสคริปท์ &verification threads + + + Accept connections from outside + ยอมรับ การเชื่อมต่อจากภายนอก + + + Allow incoming connections + ยอมให้เชื่อมต่อจากภายนอกได้ + + + IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + IP แอดเดส ของ proxy (เช่น IPv4: 127.0.0.1 / IPv6: ::1) + + + 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. + มินิไมซ์แอพ แทนการออกจากแอพพลิเคชั่น เมื่อวินโดว์ได้รับการปิด เมื่อเลือกตัวเลือกนี้ แอพพลิเคชั่น จะถูกปิด ก็ต่อเมื่อ มีการเลือกเมนู Exit/ออกจากระบบ เท่านั้น + + + 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 |. + URL แบบอื่น (ยกตัวอย่าง เอ็กพลอเลอร์บล็อก) ที่อยู่ใน เมนูรายการ ลำดับ %s ใน URL จะถูกเปลี่ยนด้วย รายการแฮช URL ที่เป็นแบบหลายๆอัน จะถูกแยก โดย เครื่องหมายเส้นบาร์ตั้ง | + + + Third party transaction URLs + URI รายการ แบบของเจ้าอื่นๆ + + + Active command-line options that override above options: + ตัวเลือก command-line แอกทีฟอยู่นี้ จะแทนที่ ตัวเลือกด้านบนนี้: + + + Reset all client options to default. + รีเซต ไคลเอ็นออพชั่น กลับไปเป็นค่าเริ่มต้น + + + &Reset Options + &รีเซต ออพชั่น + + + &Network + &เน็ตเวิร์ก + + + (0 = auto, <0 = leave that many cores free) + (0 = อัตโนมัติ, <0 = ปล่อย คอร์ อิสระ) + + + W&allet + กระเ&ป๋าเงิน + + + Expert + ผู้เชี่ยวชาญ + + + Enable coin &control features + เปิดใช้ coin & รูปแบบการควบคุม + + + 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. + หากท่านไม่เปิดใช้ การใช้เงินทอนที่ยังไม่ยืนยัน เงินทอนจากการทำรายการจะไม่สามารถใช้ได้ จนกว่ารายการที่ทำการ จะได้รับการยืนยันหนึ่งครั้ง และจะกระทบการคำนวณยอดคงเหลือของท่านด้วย + + + &Spend unconfirmed change + &ใช้เงินทอนที่ยังไม่ยืนยัน + + + Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled. + เปิด Bitcoin ไคล์เอ็นท์พอร์ต/client port บน router โดยอัตโนมัติ วิธีนี้ใช้ได้เมื่อ router สนับสนุน UPnP และสถานะเปิดใช้งาน + + + Map port using &UPnP + จองพอร์ต โดยใช้ &UPnP + + + Connect to the Bitcoin network through a SOCKS5 proxy. + เชื่อมต่อกับ Bitcoin เน็ตเวิร์ก ผ่านพร็อกซี่แบบ SOCKS5 + + + &Connect through SOCKS5 proxy (default proxy): + &เชื่อมต่อผ่าน พร็อกซี่ SOCKS5 (พร็อกซี่เริ่มต้น): + + + Proxy &IP: + พร็อกซี่ &IP: + + + &Port: + &พอร์ต + + + Port of the proxy (e.g. 9050) + พอร์ตของพร็อกซี่ (ตัวอย่าง 9050) + + + Used for reaching peers via: + ใช้ในการเข้าถึงอีกฝ่ายหนึ่ง peer โดย: + + + Shows, if the supplied default SOCKS5 proxy is used to reach peers via this network type. + แสดง หากใช้พร็อกซี่ SOCKS5 ที่เป็นค่าเริ่มต้น เพื่อเข้าถึง peer อีกฝ่าย ผ่านทางเน็ตเวิร์กชนิดนี้ + + + IPv4 + IPv4 + + + IPv6 + IPv6 + + + Tor + Tor + OverviewPage @@ -397,9 +773,6 @@ รูป - - PaymentServer - PeerTableModel @@ -410,9 +783,6 @@ จำนวน - - QRImageWidget - RPCConsole @@ -425,47 +795,44 @@ ReceiveRequestDialog + + + SendCoinsDialog - Address - ที่อยู่ + Send Coins + ส่งเหรียญ - Amount - จำนวน + Quantity: + จำนวน: - Label - ชื่อ + Bytes: + ไบต์: - - - RecentRequestsTableModel - Date - วันที่ + Amount: + จำนวน: - Label - ชื่อ + Priority: + ความเร่งด่วน - Amount - จำนวน + Fee: + ค่าธรรมเนียม: - (no label) - (ไม่มีชื่อ) + After Fee: + ส่วนที่เหลือจากค่าธรรมเนียม: - - - SendCoinsDialog - Send Coins - ส่งเหรียญ + Change: + เงินทอน: - (no label) - (ไม่มีชื่อ) + Dust: + เศษ: @@ -491,91 +858,29 @@ TrafficGraphWidget - - TransactionDesc - - Date - วันที่ - - - Amount - จำนวน - - TransactionDescDialog - - TransactionTableModel - - Date - วันที่ - - - Label - ชื่อ - - - - TransactionView - - Today - วันนี้ - - - Exporting Failed - ส่งออกข้อมูลล้มเหลว - - - Comma separated file (*.csv) - คั่นไฟล์ด้วยเครื่องหมายจุลภาค (*.csv) - - - Confirmed - ยืนยันแล้ว - - - Date - วันที่ - - - Label - ชื่อ - - - Address - ที่อยู่ - - UnitDisplayStatusBarControl - WalletFrame - - - WalletModel + bitcoin-core - Send Coins - ส่งเหรียญ + Options: + ตัวเลือก: - - - WalletView - &Export - &ส่งออก + Information + ข้อมูล - Export the data in the current tab to a file - ส่งออกข้อมูลที่อยู่ในแท็บไปที่ไฟล์ + Warning + คำเตือน - - - bitcoin-core - Options: - ตัวเลือก: + Error + ข้อผิดพลาด - + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_tr.ts b/src/qt/locale/bitcoin_tr.ts index 2406776773624..f6ab2ca18b6cf 100644 --- a/src/qt/locale/bitcoin_tr.ts +++ b/src/qt/locale/bitcoin_tr.ts @@ -25,10 +25,6 @@ C&lose K&apat - - &Copy Address - &Adresi Kopyala - Delete the currently selected address from the list Seçili adresi listeden sil @@ -45,73 +41,6 @@ &Delete &Sil - - Choose the address to send coins to - Bitcoin yollanacak adresi seç - - - Choose the address to receive coins with - Bitcoin alınacak adresi seç - - - C&hoose - S&eç - - - Sending addresses - &Gönderme adresleri... - - - Receiving addresses - Alım adresleri - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Bunlar ödemeleri göndermek için kullanacağınız Bitcoin adreslerinizdir. Bitcoin yollamadan önce miktarı ve alıcının alım adresini daima kontrol ediniz. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Bunlar ödemeleri almak için kullanacağınız Bitcoin adreslerinizdir. Her işlem için yeni bir alım adresi kullanmanız tavsiye edilir. - - - Copy &Label - &Etiketi kopyala - - - &Edit - &Düzenle - - - Export Address List - Adres listesini dışa aktar - - - Comma separated file (*.csv) - Virgülle ayrılmış değerler dosyası (*.csv) - - - Exporting Failed - Dışa aktarım başarısız oldu - - - There was an error trying to save the address list to %1. Please try again. - Adres listesinin %1 konumuna kaydedilmesi sırasında bir hata meydana geldi. Lütfen tekrar deneyin. - - - - AddressTableModel - - Label - Etiket - - - Address - Adres - - - (no label) - (etiket yok) - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase Yeni parolayı tekrarlayınız - - Encrypt wallet - Cüzdanı şifrele - - - This operation needs your wallet passphrase to unlock the wallet. - Bu işlem cüzdan kilidini açmak için cüzdan parolanızı gerektirir. - - - Unlock wallet - Cüzdan kilidini aç - - - This operation needs your wallet passphrase to decrypt the wallet. - Bu işlem cüzdanın şifrelemesini açmak için cüzdan parolasını gerektirir. - - - Decrypt wallet - Cüzdanın şifrelemesini aç - - - Change passphrase - Parolayı değiştir - - - Confirm wallet encryption - Cüzdanın şifrelemesini teyit eder - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Uyarı: Eğer cüzdanınızı şifrelerseniz ve parolanızı kaybederseniz, <b>TÜM BİTCOİNLERİNİZİ KAYBEDERSİNİZ</b>! - - - Are you sure you wish to encrypt your wallet? - Cüzdanınızı şifrelemek istediğinizden emin misiniz? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Şifreleme işlemini tamamlamak için Bitcoin Çekirdeği şimdi kapanacaktır. Cüzdanınızı şifrelemenin, Bitcoinlerinizin bilgisayara bulaşan kötücül bir yazılım tarafından çalınmaya karşı tamamen koruyamayacağını unutmayınız. - - - 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. - ÖNEMLİ: Önceden yapmış olduğunuz cüzdan dosyası yedeklemelerinin yeni oluşturulan şifrelenmiş cüzdan dosyası ile değiştirilmeleri gerekir. Güvenlik nedenleriyle yeni, şifrelenmiş cüzdanı kullanmaya başladığınızda eski şifrelenmemiş cüzdan dosyaları işe yaramaz hale gelecektir. - - - Warning: The Caps Lock key is on! - Uyarı: Caps Lock tuşu faal durumda! - - - Wallet encrypted - Cüzdan şifrelendi - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Cüzdan için yeni parolayı giriniz.<br/>Lütfen <b>on ya da daha fazla rastgele karakter</b> veya <b>sekiz ya da daha fazla kelime</b> içeren bir parola kullanınız. - - - Enter the old passphrase and new passphrase to the wallet. - Cüzdan için eski parolayı ve yeni parolayı giriniz. - - - Wallet encryption failed - Cüzdan şifrelemesi başarısız oldu - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Dahili bir hata sebebiyle cüzdan şifrelemesi başarısız oldu. Cüzdanınız şifrelenmedi. - - - The supplied passphrases do not match. - Girilen parolalar birbirleriyle uyumlu değil. - - - Wallet unlock failed - Cüzdan kilidinin açılması başarısız oldu - - - The passphrase entered for the wallet decryption was incorrect. - Cüzdan şifresinin açılması için girilen parola yanlıştı. - - - Wallet decryption failed - Cüzdan şifresinin açılması başarısız oldu - - - Wallet passphrase was successfully changed. - Cüzdan parolası başarılı bir şekilde değiştirildi. - BanTableModel @@ -269,6 +110,14 @@ Quit application Uygulamadan çık + + &About %1 + %1 &hakkında + + + Show information about %1 + %1 hakkında bilgi göster + About &Qt &Qt hakkında @@ -281,6 +130,10 @@ &Options... &Seçenekler... + + Modify configuration options for %1 + %1 için yapılandırma ayarlarını değiştir + &Encrypt Wallet... Cüzdanı &şifrele... @@ -305,14 +158,6 @@ Open &URI... &URI aç... - - Bitcoin Core client - Bitcoin Çekirdeği istemcisi - - - Importing blocks from disk... - Bloklar diskten içe aktarılıyor... - Reindexing blocks on disk... Diskteki bloklar yeniden endeksleniyor... @@ -357,10 +202,6 @@ &Receive &Al - - Show information about Bitcoin Core - Bitcoin Çekirdeği hakkında bilgi göster - &Show / Hide &Göster / Sakla @@ -397,22 +238,10 @@ Tabs toolbar Sekme araç çubuğu - - Bitcoin Core - Bitcoin Çekirdeği - Request payments (generates QR codes and bitcoin: URIs) Ödeme talep et (QR kodu ve bitcoin URI'si oluşturur) - - &About Bitcoin Core - Bitcoin Çekirdeği &hakkında - - - Modify configuration options for Bitcoin Core - Bitcoin Çekirdeği yapılandırma seçeneklerini değiştir - Show the list of used sending addresses and labels Kullanılmış gönderme adresleri ve etiketlerin listesini göster @@ -429,14 +258,18 @@ &Command-line options &Komut satırı seçenekleri - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Bitcoin komut satırı seçeneklerinin listesini elde etmek için Bitcoin Çekirdeği yardım mesajını göster - %n active connection(s) to Bitcoin network Bitcoin şebekesine %n faal bağlantıBitcoin şebekesine %n faal bağlantı + + Indexing blocks on disk... + Bloklar diske indeksleniyor... + + + Processing blocks on disk... + Bloklar diske yazıdırılıyor... + No block source available... Hiçbir blok kaynağı mevcut değil... @@ -493,6 +326,14 @@ Up to date Güncel + + Show the %1 help message to get a list with possible Bitcoin command-line options + Olası Bitcoin komut satırı seçeneklerinin listesini görmek için %1 yardım mesajını göster + + + %1 client + %1 istemcisi + Catching up... Aralık kapatılıyor... @@ -544,13 +385,6 @@ Cüzdan <b>şifrelenmiştir</b> ve şu anda <b>kilitlidir</b> - - ClientModel - - Network Alert - Şebeke hakkında uyarı - - CoinControlDialog @@ -629,150 +463,6 @@ Priority Öncelik - - Copy address - Adresi kopyala - - - Copy label - Etiketi kopyala - - - Copy amount - Meblağı kopyala - - - Copy transaction ID - Muamele kimliğini kopyala - - - Lock unspent - Harcanmamışı kilitle - - - Unlock unspent - Harcanmamışın kilidini aç - - - Copy quantity - Miktarı kopyala - - - Copy fee - Ücreti kopyala - - - Copy after fee - Ücretten sonrakini kopyala - - - Copy bytes - Baytları kopyala - - - Copy priority - Önceliği kopyala - - - Copy dust - Tozu kopyala - - - Copy change - Para üstünü kopyala - - - highest - azami - - - higher - daha yüksek - - - high - yüksek - - - medium-high - orta-yüksek - - - medium - orta - - - low-medium - düşük-orta - - - low - düşük - - - lower - daha düşük - - - lowest - asgari - - - (%1 locked) - (%1 kilitlendi) - - - none - boş - - - This label turns red if the transaction size is greater than 1000 bytes. - Eğer muamele boyutu 1000 bayttan yüksek ise bu etiket kırmızı hale gelir. - - - This label turns red if the priority is smaller than "medium". - Eğer öncelik "ortadan" düşükse bu etiket kırmızı olur. - - - This label turns red if any recipient receives an amount smaller than %1. - Eğer herhangi bir alıcı %1'den düşük bir meblağ alırsa bu etiket kırmızı olur. - - - Can vary +/- %1 satoshi(s) per input. - Giriş başına +/- %1 satoshi olarak değişebilir. - - - yes - evet - - - no - hayır - - - This means a fee of at least %1 per kB is required. - Bu, kB başına en az %1 ücret gerektiği anlamnına gelir. - - - Can vary +/- 1 byte per input. - Girdi başına +/- 1 bayt değişebilir. - - - Transactions with higher priority are more likely to get included into a block. - Yüksek öncelikli muamelelerin bir bloğa dahil olmaları daha olasıdır. - - - (no label) - (boş etiket) - - - change from %1 (%2) - %1 unsurundan para üstü (%2) - - - (change) - (para üstü) - EditAddressDialog @@ -796,38 +486,6 @@ &Address &Adres - - New receiving address - Yeni alım adresi - - - New sending address - Yeni gönderi adresi - - - Edit receiving address - Alım adresini düzenle - - - Edit sending address - Gönderi adresini düzenle - - - The entered address "%1" is already in the address book. - Girilen "%1" adresi hâlihazırda adres defterinde mevcuttur. - - - The entered address "%1" is not a valid Bitcoin address. - Girilen "%1" adresi geçerli bir Bitcoin adresi değildir. - - - Could not unlock wallet. - Cüzdan kilidi açılamadı. - - - New key generation failed. - Yeni anahtar oluşturulması başarısız oldu. - FreespaceChecker @@ -854,10 +512,6 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin Çekirdeği - version sürüm @@ -867,8 +521,8 @@ (%1-bit) - About Bitcoin Core - Bitcoin Çekirdeği hakkında + About %1 + %1 Hakkında Command-line options @@ -907,8 +561,8 @@ Başlatıldığında başlangıç ekranını göster (varsayılan: %u) - Reset all settings changes made over the GUI - Arayüzde yapılan tüm seçenek değişikliklerini sıfırla + Reset all settings changed in the GUI + Grafik arayüzde yapılan tüm seçenek değişikliklerini sıfırla @@ -918,16 +572,16 @@ Hoş geldiniz - Welcome to Bitcoin Core. - Bitcoin Çekirdeğine hoş geldiniz. + Welcome to %1. + %1'a hoş geldiniz. - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - Bu programı ilk kez başlattığınızdan dolayı Bitcoin Çekirdeğinin verilerini nereye saklayacağını seçebilirsiniz. + As this is the first time the program is launched, you can choose where %1 will store its data. + Bu programın ilk kez başlatılmasından dolayı %1 yazılımının verilerini nerede saklayacağını seçebilirsiniz. - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - Bitcoin çekirdeği Bitcoin blok zincirinin bir kopyasını indirip saklayacaktır. Asgari %1GB bouyutunda veri bu klasörde saklanacak ve zamanla bu boyut artacaktır. Cüzdan da bu klasörde saklanacaktır. + %1 will download and store a copy of the Bitcoin block chain. At least %2GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. + %1, Bitcoin blok zincirinin bir kopyasını indirecek ve saklayacaktır. Bu klasörde en az %2GB veri saklanacak ve bu zamanla artacaktır. Cüzdan da bu klasörde saklanacaktır. Use the default data directory @@ -937,10 +591,6 @@ Use a custom data directory: Özel bir veri klasörü kullan: - - Bitcoin Core - Bitcoin Çekirdeği - Error: Specified data directory "%1" cannot be created. Hata: belirtilen "%1" veri klasörü oluşturulamaz. @@ -976,10 +626,6 @@ Select payment request file Ödeme talebi dosyasını seç - - Select payment request file to open - Açılacak ödeme talebi dosyasını seç - OptionsDialog @@ -991,6 +637,14 @@ &Main &Esas ayarlar + + Automatically start %1 after logging in to the system. + Sistemde oturum açıldığında %1 programını otomatik olarak başlat. + + + &Start %1 on system login + &Açılışta %1 açılsın + Size of &database cache &Veritabanı tamponunun boyutu @@ -1019,10 +673,6 @@ 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. Pencere kapatıldığında uygulamadan çıkmak yerine uygulamayı küçültür. Bu seçenek etkinleştirildiğinde, uygulama sadece menüden çıkış seçildiğinde kapanacaktır. - - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - Kullanıcı arayüzünün dili burada belirtilebilir. Bu ayar Bitcoin Çekirdeği tekrar başlatıldığında etkinleşecektir. - 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 |. Muameleler sekmesinde bağlam menüsü unsurları olarak görünen üçüncü taraf bağlantıları (mesela bir blok tarayıcısı). URL'deki %s, muamele hash değeri ile değiştirilecektir. Birden çok bağlantılar düşey çubuklar | ile ayrılacaktır. @@ -1047,14 +697,6 @@ &Network &Şebeke - - Automatically start Bitcoin Core after logging in to the system. - Sistemde oturum açıldığında Bitcoin Çekirdeğini otomatik olarak başlat. - - - &Start Bitcoin Core on system login - Bitcoin Çekirdeğini sistem oturumuyla &başlat - (0 = auto, <0 = leave that many cores free) (0 = otomatik, <0 = bu kadar çekirdeği kullanma) @@ -1139,6 +781,14 @@ &Window &Pencere + + &Hide the icon from the system tray. + İkonu sistem çekmecesinden &sakla + + + Hide tray icon + Sistem çekmecesi ikonunu sakla + Show only a tray icon after minimizing the window. Küçültüldükten sonra sadece çekmece ikonu göster. @@ -1159,6 +809,10 @@ User Interface &language: Kullanıcı arayüzü &lisanı: + + The user interface language can be set here. This setting will take effect after restarting %1. + Kullanıcı arayüzünün dili burada belirtilebilir. Bu ayar %1 tekrar başlatıldığında etkinleşecektir. + &Unit to show amounts in: Meblağları göstermek için &birim: @@ -1284,140 +938,49 @@ - PaymentServer + PeerTableModel - URI handling - URI yönetimi + User Agent + Kullanıcı Yazılımı - Invalid payment address %1 - Geçersiz ödeme adresi %1 + Node/Service + Düğüm/Servis - Payment request rejected - Ödeme talebi reddedildi + Ping Time + Ping Süresi + + + QObject - Payment request network doesn't match client network. - Ödeme talebi şebekesi istemci şebekesine denk gelmiyor. + Amount + Meblağ - Payment request is not initialized. - Ödeme talebi başlatılmamış. + Enter a Bitcoin address (e.g. %1) + Bir Bitcoin adresi giriniz (mesela %1) - Requested payment amount of %1 is too small (considered dust). - Talep edilen %1 meblağında ödeme çok düşüktür (toz olarak kabul edilir). + %1 d + %1 g - Payment request error - Ödeme talebi hatası + %1 h + %1 s - Cannot start bitcoin: click-to-pay handler - Bitcoin başlatılamadı: tıkla-ve-öde yöneticisi + %1 m + %1 d - Payment request fetch URL is invalid: %1 - Ödeme talebini alma URL'i geçersiz: %1 + %1 s + %1 s - URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - URI okunamadı! Sebebi geçersiz bir Bitcoin adresi veya hatalı URI parametreleri olabilir. - - - Payment request file handling - Ödeme talebi dosyası yönetimi - - - Payment request file cannot be read! This can be caused by an invalid payment request file. - Ödeme talebi okunamaz ya da işlenemez! Bunun sebebi geçersiz bir ödeme talebi dosyası olabilir. - - - Payment request expired. - Ödeme talebinin ömrü doldu. - - - Unverified payment requests to custom payment scripts are unsupported. - Özel ödeme betiklerine teyit edilmemiş ödeme talepleri desteklenmez. - - - Invalid payment request. - Geçersiz ödeme talebi. - - - Refund from %1 - %1 öğesinden iade - - - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - %1 ödeme talebi çok büyük (%2 bayt, müsaade edilen %3 bayt). - - - Error communicating with %1: %2 - %1 ile iletişimde hata: %2 - - - Payment request cannot be parsed! - Ödeme talebi ayrıştırılamaz! - - - Bad response from server %1 - %1 sunucusundan hatalı cevap - - - Payment acknowledged - Ödeme teyit edildi - - - Network request error - Şebeke talebi hatası - - - - PeerTableModel - - User Agent - Kullanıcı Yazılımı - - - Node/Service - Düğüm/Servis - - - Ping Time - Ping Süresi - - - - QObject - - Amount - Meblağ - - - Enter a Bitcoin address (e.g. %1) - Bir Bitcoin adresi giriniz (mesela %1) - - - %1 d - %1 g - - - %1 h - %1 s - - - %1 m - %1 d - - - %1 s - %1 s - - - None - Boş + None + Boş N/A @@ -1428,25 +991,6 @@ %1 ms - - QRImageWidget - - &Save Image... - Resmi k&aydet... - - - &Copy Image - Resmi &kopyala - - - Save QR Code - QR kodu kaydet - - - PNG Image (*.png) - PNG resim (*.png) - - RPCConsole @@ -1477,6 +1021,10 @@ Using BerkeleyDB version Kullanılan BerkeleyDB sürümü + + Datadir + Veri konumu + Startup time Başlama zamanı @@ -1513,10 +1061,6 @@ Memory usage Bellek kullanımı - - Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. - Güncel veri klasöründen Bitcoin Çekirdeği hata ayıklama kütük dosyasını açar. Büyük kütük dosyaları için bu birkaç saniye alabilir. - Received Alınan @@ -1565,6 +1109,18 @@ User Agent Kullanıcı Yazılımı + + Open the %1 debug log file from the current data directory. This can take a few seconds for large log files. + Güncel veri klasöründen %1 hata ayıklama kütük dosyasını açar. Büyük kütük dosyaları için bu birkaç saniye alabilir. + + + Decrease font size + Font boyutunu küçült + + + Increase font size + Yazıtipi boyutunu büyült + Services Servisler @@ -1633,10 +1189,6 @@ Out: Dışarı: - - Build date - Derleme tarihi - Debug log file Hata ayıklama kütük dosyası @@ -1674,8 +1226,8 @@ Düğümün Yasağını Kald&ır - Welcome to the Bitcoin Core RPC console. - Bitcoin Çekirdeği RPC konsoluna hoş geldiniz. + Welcome to the %1 RPC console. + %1 RPC konsoluna hoş geldiniz. Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. @@ -1804,18 +1356,6 @@ Remove Kaldır - - Copy label - Etiketi kopyala - - - Copy message - Mesajı kopyala - - - Copy amount - Meblağı kopyala - ReceiveRequestDialog @@ -1835,73 +1375,6 @@ &Save Image... Resmi ka&ydet... - - Request payment to %1 - %1 unsuruna ödeme talep et - - - Payment information - Ödeme bilgisi - - - URI - URI - - - Address - Adres - - - Amount - Meblağ - - - Label - Etiket - - - Message - Mesaj - - - Resulting URI too long, try to reduce the text for label / message. - Sonuç URI çok uzun, etiket ya da mesaj metnini kısaltmayı deneyiniz. - - - Error encoding URI into QR Code. - URI'nin QR koduna kodlanmasında hata oluştu. - - - - RecentRequestsTableModel - - Date - Tarih - - - Label - Etiket - - - Message - Mesaj - - - Amount - Meblağ - - - (no label) - (boş etiket) - - - (no message) - (boş mesaj) - - - (no amount) - (boş meblağ) - SendCoinsDialog @@ -2021,14 +1494,6 @@ fast çabuk - - Send as zero-fee transaction if possible - Mümkünse ücretsiz muamele olarak gönder - - - (confirmation may take longer) - (teyit daha uzun süre alabilir) - Send to multiple recipients at once Birçok alıcıya aynı anda gönder @@ -2061,844 +1526,210 @@ S&end G&önder - - Confirm send coins - Gönderiyi teyit ediniz - - - %1 to %2 - %1 öğesinden %2 unsuruna - - - Copy quantity - Miktarı kopyala - - - Copy amount - Meblağı kopyala - - - Copy fee - Ücreti kopyala - - - Copy after fee - Ücretten sonrakini kopyala - - - Copy bytes - Baytları kopyala - - - Copy priority - Önceliği kopyala - - - Copy change - Para üstünü kopyala - - - Total Amount %1 - Toplam Meblağ %1 - - - or - veya - - - The amount to pay must be larger than 0. - Ödeyeceğiniz tutarın sıfırdan yüksek olması gerekir. - - - The amount exceeds your balance. - Tutar bakiyenizden yüksektir. - - - The total exceeds your balance when the %1 transaction fee is included. - Toplam, %1 muamele ücreti ilâve edildiğinde bakiyenizi geçmektedir. - - - Transaction creation failed! - Muamelenin oluşturulması başarısız oldu! - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - Muamele reddedildi! Cüzdanınızdaki madenî paraların bazıları zaten harcanmış olduğunda bu meydana gelebilir. Örneğin wallet.dat dosyasının bir kopyasını kullandıysanız ve kopyada para harcandığında ancak burada harcandığı işaretlenmediğinde. - - - A fee higher than %1 is considered an absurdly high fee. - %1 tutarından yüksek ücret saçma derecede yüksek bir ücret olarak kabul edilir. - - - Payment request expired. - Ödeme talebinin ömrü doldu. - - - Pay only the required fee of %1 - Sadece gerekli ücret olan %1 tutarını öde - - - Estimated to begin confirmation within %n block(s). - Tahmini olarak %n blok içinde teyide başlanacaktır.Tahmini olarak %n blok içinde teyide başlanacaktır. - - - The recipient address is not valid. Please recheck. - Alıcı adresi geçerli değildir. Lütfen denetleyiniz. - - - Duplicate address found: addresses should only be used once each. - Çift adres bulundu: adresler herbiri için sadece bir kez kullanılmalıdır. - - - Warning: Invalid Bitcoin address - Uyarı: geçersiz Bitcoin adresi - - - (no label) - (boş etiket) - - - Warning: Unknown change address - Uyarı: geçersiz para üstü adresi - - - Copy dust - Tozu kopyala - - - Are you sure you want to send? - Göndermek istediğinizden emin misiniz? - - - added as transaction fee - muamele ücreti olarak eklendi - - - SendCoinsEntry - - A&mount: - Mebla&ğ: - - - Pay &To: - &Şu adrese öde: - - - Enter a label for this address to add it to your address book - Adres defterinize eklemek için bu adrese ilişik bir etiket giriniz - - - &Label: - &Etiket: - - - Choose previously used address - Önceden kullanılmış adres seç - - - This is a normal payment. - Bu, normal bir ödemedir. - - - The Bitcoin address to send the payment to - Ödemenin yollanacağı Bitcoin adresi - - - Alt+A - Alt+A - - - Paste address from clipboard - Panodan adres yapıştır - - - Alt+P - Alt+P - - - Remove this entry - Bu unsuru kaldır - - - 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. - Ücret yollanan meblağdan alınacaktır. Alıcı meblağ alanında girdiğinizden daha az bitcoin alacaktır. Eğer birden çok alıcı seçiliyse ücret eşit olarak bölünecektir. - - - S&ubtract fee from amount - Ücreti meblağdan düş - - - Message: - Mesaj: - - - This is an unauthenticated payment request. - Bu, kimliği doğrulanmamış bir ödeme talebidir. - - - This is an authenticated payment request. - Bu, kimliği doğrulanmış bir ödeme talebidir. - - - Enter a label for this address to add it to the list of used addresses - Kullanılmış adres listesine eklemek için bu adrese bir etiket girin - - - 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. - Bitcoin: URI'siyle ilişkili ve bilginiz için muameleyle saklanacak bir mesaj. Not: Bu mesaj Bitcoin şebekesi üzerinden gönderilmeyecektir. - - - Pay To: - Şu adrese öde: - - - Memo: - Not: - - - - ShutdownWindow - - Bitcoin Core is shutting down... - Bitcoin Çekirdeği kapanıyor... - - - Do not shut down the computer until this window disappears. - Bu pencere kalkıncaya dek bilgisayarı kapatmayınız. - - - - SignVerifyMessageDialog - - Signatures - Sign / Verify a Message - İmzalar - Mesaj İmzala / Kontrol et - - - &Sign Message - Mesaj &imzala - - - 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. - Adreslerinize yollanan bitcoinleri alabileceğiniz ispatlamak için adreslerinizle mesaj/anlaşma imzalayabilirsiniz. Oltalama saldırılarının kimliğinizi imzanızla elde etmeyi deneyebilecekleri için belirsiz ya da rastgele hiçbir şey imzalamamaya dikkat ediniz. Sadece ayrıntılı açıklaması olan ve tümüne katıldığınız ifadeleri imzalayınız. - - - The Bitcoin address to sign the message with - Mesajın imzalanmasında kullanılacak Bitcoin adresi - - - Choose previously used address - Önceden kullanılmış adres seç - - - Alt+A - Alt+A - - - Paste address from clipboard - Panodan adres yapıştır - - - Alt+P - Alt+P - - - Enter the message you want to sign here - İmzalamak istediğiniz mesajı burada giriniz - - - Signature - İmza - - - Copy the current signature to the system clipboard - Güncel imzayı sistem panosuna kopyala - - - Sign the message to prove you own this Bitcoin address - Bu Bitcoin adresinin sizin olduğunu ispatlamak için mesajı imzalayın - - - Sign &Message - &Mesajı imzala - - - Reset all sign message fields - Tüm mesaj alanlarını sıfırla - - - Clear &All - Tümünü &temizle - - - &Verify Message - Mesaj &kontrol et - - - 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! - Alıcının adresini, mesajı (satır sonları, boşluklar, sekmeler vs. karakterleri tam olarak kopyaladığınızdan emin olunuz) ve imzayı aşağıda giriniz. Bir ortadaki adam saldırısı tarafından kandırılmaya mâni olmak için imzadan, imzalı mesajın içeriğini aşan bir anlam çıkarmamaya dikkat ediniz. Bunun sadece imzalayan tarafın adres ile alım yapabildiğini ispatladığını ve herhangi bir muamelenin gönderi tarafını kanıtlayamayacağını unutmayınız! - - - The Bitcoin address the message was signed with - Mesajın imzalanmasında kullanılan Bitcoin adresi - - - Verify the message to ensure it was signed with the specified Bitcoin address - Belirtilen Bitcoin adresi ile imzalandığını doğrulamak için mesajı kontrol et - - - Verify &Message - &Mesaj kontrol et - - - Reset all verify message fields - Tüm mesaj kontrolü alanlarını sıfırla - - - Click "Sign Message" to generate signature - İmzayı oluşturmak için "Mesaj İmzala" unsurunu tıklayın - - - The entered address is invalid. - Girilen adres geçersizdir. - - - Please check the address and try again. - Adresi kontrol edip tekrar deneyiniz. - - - The entered address does not refer to a key. - Girilen adres herhangi bir anahtara işaret etmemektedir. - - - Wallet unlock was cancelled. - Cüzdan kilidinin açılması iptal edildi. - - - Private key for the entered address is not available. - Girilen adres için özel anahtar mevcut değildir. - - - Message signing failed. - Mesajın imzalanması başarısız oldu. - - - Message signed. - Mesaj imzalandı. - - - The signature could not be decoded. - İmzanın kodu çözülemedi. - - - Please check the signature and try again. - İmzayı kontrol edip tekrar deneyiniz. - - - The signature did not match the message digest. - İmza mesajın hash değeri ile eşleşmedi. - - - Message verification failed. - Mesaj doğrulaması başarısız oldu. - - - Message verified. - Mesaj doğrulandı. - - - - SplashScreen - - Bitcoin Core - Bitcoin Çekirdeği - - - The Bitcoin Core developers - Bitcoin Çekirdeği geliştiricileri - - - [testnet] - [testnet] - - - - TrafficGraphWidget - - KB/s - KB/s - - - - TransactionDesc - - Open until %1 - %1 değerine dek açık - - - conflicted - çakışma - - - %1/offline - %1/çevrim dışı - - - %1/unconfirmed - %1/doğrulanmadı - - - %1 confirmations - %1 teyit - - - Status - Durum - - - , broadcast through %n node(s) - , %n düğüm vasıtasıyla yayınlandı, %n düğüm vasıtasıyla yayınlandı - - - Date - Tarih - - - Source - Kaynak - - - Generated - Oluşturuldu - - - From - Gönderen - - - To - Alıcı - - - own address - kendi adresiniz - - - watch-only - sadece-izlenen - - - label - etiket - - - Credit - Gider - - - matures in %n more block(s) - %n ek blok sonrasında olgunlaşacak%n ek blok sonrasında olgunlaşacak - - - not accepted - kabul edilmedi - - - Debit - Gelir - - - Total debit - Toplam gider - - - Total credit - Toplam gelir - - - Transaction fee - Muamele ücreti - - - Net amount - Net meblağ - - - Message - Mesaj - - - Comment - Yorum - - - Transaction ID - Muamele tanımlayıcı - - - Merchant - Tüccar - - - 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. - Oluşturulan bitcoin'lerin harcanabilmelerinden önce %1 blok beklemeleri gerekmektedir. Bu blok, oluşturduğunuzda, blok zincirine eklenmesi için ağda yayınlandı. Zincire eklenmesi başarısız olursa, durumu "kabul edilmedi" olarak değiştirilecek ve harcanamayacaktır. Bu, bazen başka bir düğüm sizden birkaç saniye önce ya da sonra blok oluşturursa meydana gelebilir. - - - Debug information - Hata ayıklama verileri - - - Transaction - Muamele - - - Inputs - Girdiler - - - Amount - Meblağ - - - true - doğru - - - false - yanlış - - - , has not been successfully broadcast yet - , henüz başarılı bir şekilde yayınlanmadı - - - Open for %n more block(s) - %n ilâve blok için açık%n ilâve blok için açık - - - unknown - bilinmiyor - - - - TransactionDescDialog - - Transaction details - Muamele detayları - - - This pane shows a detailed description of the transaction - Bu pano muamelenin ayrıntılı açıklamasını gösterir - - - - TransactionTableModel - - Date - Tarih - - - Type - Tür - - - Immature (%1 confirmations, will be available after %2) - Olgunlaşmamış (%1 teyit, %2 teyit ardından kullanılabilir olacaktır) - - - Open for %n more block(s) - %n ilâve blok için açık%n ilâve blok için açık - - - Open until %1 - %1 değerine dek açık - - - Confirmed (%1 confirmations) - Doğrulandı (%1 teyit) - - - This block was not received by any other nodes and will probably not be accepted! - Bu blok başka hiçbir düğüm tarafından alınmamıştır ve muhtemelen kabul edilmeyecektir! - - - Generated but not accepted - Oluşturuldu ama kabul edilmedi - - - Offline - Çevrim dışı - - - Label - Etiket - - - Unconfirmed - Teyit edilmemiş - - - Confirming (%1 of %2 recommended confirmations) - Teyit ediliyor (tavsiye edilen %2 teyit üzerinden %1 doğrulama) - - - Conflicted - Çakışma - - - Received with - Şununla alındı - - - Received from - Alındığı kişi - - - Sent to - Gönderildiği adres - - - Payment to yourself - Kendinize ödeme - - - Mined - Madenden çıkarılan - - - watch-only - sadece-izlenen - - - (n/a) - (mevcut değil) - + + SendCoinsEntry - Transaction status. Hover over this field to show number of confirmations. - Muamele durumu. Doğrulama sayısını görüntülemek için imleci bu alanda tutunuz. + A&mount: + Mebla&ğ: - Date and time that the transaction was received. - Muamelenin alındığı tarih ve zaman. + Pay &To: + &Şu adrese öde: - Type of transaction. - Muamele türü. + &Label: + &Etiket: - Whether or not a watch-only address is involved in this transaction. - Bu muamelede sadece izlenen bir adresin bulunup bulunmadığı. + Choose previously used address + Önceden kullanılmış adres seç - User-defined intent/purpose of the transaction. - Muamelenin kullanıcı tanımlı niyeti/amacı. + This is a normal payment. + Bu, normal bir ödemedir. - Amount removed from or added to balance. - Bakiyeden alınan ya da bakiyeye eklenen meblağ. + The Bitcoin address to send the payment to + Ödemenin yollanacağı Bitcoin adresi - - - TransactionView - All - Hepsi + Alt+A + Alt+A - Today - Bugün + Paste address from clipboard + Panodan adres yapıştır - This week - Bu hafta + Alt+P + Alt+P - This month - Bu ay + Remove this entry + Bu unsuru kaldır - Last month - Geçen ay + 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. + Ücret yollanan meblağdan alınacaktır. Alıcı meblağ alanında girdiğinizden daha az bitcoin alacaktır. Eğer birden çok alıcı seçiliyse ücret eşit olarak bölünecektir. - This year - Bu sene + S&ubtract fee from amount + Ücreti meblağdan düş - Range... - Aralık... + Message: + Mesaj: - Received with - Şununla alınan + This is an unauthenticated payment request. + Bu, kimliği doğrulanmamış bir ödeme talebidir. - Sent to - Gönderildiği adres + This is an authenticated payment request. + Bu, kimliği doğrulanmış bir ödeme talebidir. - To yourself - Kendinize + Enter a label for this address to add it to the list of used addresses + Kullanılmış adres listesine eklemek için bu adrese bir etiket girin - Mined - Oluşturulan + 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. + Bitcoin: URI'siyle ilişkili ve bilginiz için muameleyle saklanacak bir mesaj. Not: Bu mesaj Bitcoin şebekesi üzerinden gönderilmeyecektir. - Other - Diğer + Pay To: + Şu adrese öde: - Enter address or label to search - Aranacak adres ya da etiket giriniz + Memo: + Not: + + + ShutdownWindow - Min amount - Asgari meblağ + %1 is shutting down... + %1 kapanıyor... - Copy address - Adresi kopyala + Do not shut down the computer until this window disappears. + Bu pencere kalkıncaya dek bilgisayarı kapatmayınız. + + + SignVerifyMessageDialog - Copy label - Etiketi kopyala + Signatures - Sign / Verify a Message + İmzalar - Mesaj İmzala / Kontrol et - Copy amount - Meblağı kopyala + &Sign Message + Mesaj &imzala - Copy transaction ID - Muamele kimliğini kopyala + 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. + Adreslerinize yollanan bitcoinleri alabileceğiniz ispatlamak için adreslerinizle mesaj/anlaşma imzalayabilirsiniz. Oltalama saldırılarının kimliğinizi imzanızla elde etmeyi deneyebilecekleri için belirsiz ya da rastgele hiçbir şey imzalamamaya dikkat ediniz. Sadece ayrıntılı açıklaması olan ve tümüne katıldığınız ifadeleri imzalayınız. - Copy raw transaction - Ham muameleyi kopyala + The Bitcoin address to sign the message with + Mesajın imzalanmasında kullanılacak Bitcoin adresi - Edit label - Etiketi düzenle + Choose previously used address + Önceden kullanılmış adres seç - Show transaction details - Muamele detaylarını göster + Alt+A + Alt+A - Export Transaction History - Muamele tarihçesini dışa aktar + Paste address from clipboard + Panodan adres yapıştır - Watch-only - Sadece izlenen + Alt+P + Alt+P - Exporting Failed - Dışa aktarım başarısız oldu + Enter the message you want to sign here + İmzalamak istediğiniz mesajı burada giriniz - There was an error trying to save the transaction history to %1. - Muamele tarihçesinin %1 konumuna kaydedilmesi sırasında bir hata meydana geldi. + Signature + İmza - Exporting Successful - Dışa aktarım başarılı oldu + Copy the current signature to the system clipboard + Güncel imzayı sistem panosuna kopyala - The transaction history was successfully saved to %1. - Muamele tarihçesi başarılı bir şekilde %1 konumuna kaydedildi. + Sign the message to prove you own this Bitcoin address + Bu Bitcoin adresinin sizin olduğunu ispatlamak için mesajı imzalayın - Comma separated file (*.csv) - Virgülle ayrılmış değerler dosyası (*.csv) + Sign &Message + &Mesajı imzala - Confirmed - Doğrulandı + Reset all sign message fields + Tüm mesaj alanlarını sıfırla - Date - Tarih + Clear &All + Tümünü &temizle - Type - Tür + &Verify Message + Mesaj &kontrol et - Label - Etiket + 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! + Alıcının adresini, mesajı (satır sonları, boşluklar, sekmeler vs. karakterleri tam olarak kopyaladığınızdan emin olunuz) ve imzayı aşağıda giriniz. Bir ortadaki adam saldırısı tarafından kandırılmaya mâni olmak için imzadan, imzalı mesajın içeriğini aşan bir anlam çıkarmamaya dikkat ediniz. Bunun sadece imzalayan tarafın adres ile alım yapabildiğini ispatladığını ve herhangi bir muamelenin gönderi tarafını kanıtlayamayacağını unutmayınız! - Address - Adres + The Bitcoin address the message was signed with + Mesajın imzalanmasında kullanılan Bitcoin adresi - ID - Tanımlayıcı + Verify the message to ensure it was signed with the specified Bitcoin address + Belirtilen Bitcoin adresi ile imzalandığını doğrulamak için mesajı kontrol et - Range: - Aralık: + Verify &Message + &Mesaj kontrol et - to - ilâ + Reset all verify message fields + Tüm mesaj kontrolü alanlarını sıfırla - UnitDisplayStatusBarControl + SplashScreen - Unit to show amounts in. Click to select another unit. - Meblağları göstermek için birim. Başka bir birim seçmek için tıklayınız. + [testnet] + [testnet] - WalletFrame + TrafficGraphWidget - No wallet has been loaded. - Hiçbir cüzdan yüklenmemiştir. + KB/s + KB/s - WalletModel + TransactionDescDialog - Send Coins - Bitcoin yolla + This pane shows a detailed description of the transaction + Bu pano muamelenin ayrıntılı açıklamasını gösterir - WalletView - - &Export - &Dışa aktar - - - Export the data in the current tab to a file - Güncel sekmedeki verileri bir dosyaya aktar - - - Backup Wallet - Cüzdanı Yedekle - - - Wallet Data (*.dat) - Cüzdan verileri (*.dat) - - - Backup Failed - Yedekleme başarısız oldu - - - There was an error trying to save the wallet data to %1. - Cüzdan verilerinin %1 konumuna kaydedilmesi sırasında bir hata meydana geldi. - - - The wallet data was successfully saved to %1. - Cüzdan verileri %1 konumuna başarıyla kaydedildi. - + UnitDisplayStatusBarControl - Backup Successful - Yedekleme başarılı + Unit to show amounts in. Click to select another unit. + Meblağları göstermek için birim. Başka bir birim seçmek için tıklayınız. @@ -2927,14 +1758,6 @@ If <category> is not supplied or if <category> = 1, output all debugging information. Eğer <kategori> belirtilmemişse ya da <kategori> = 1 ise, tüm hata ayıklama verilerini dök. - - Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s) - Tek cüzdan muamelesinde kullanılacak azami toplam ücret (%s olarak); bunu çok düşük olarak ayarlamak büyük muameleleri iptal edebilir (varsayılan: %s) - - - Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. - Lütfen bilgisayarınızın saat ve tarihinin doğru olduğunu kontol ediniz! Saatinizde gecikme varsa Bitcoin Çekirdeği doğru şekilde çalışamaz. - Prune configured below the minimum of %d MiB. Please use a higher number. Budama, asgari değer olan %d MiB'den düşük olarak ayarlanmıştır. Lütfen daha yüksek bir sayı kullanınız. @@ -2975,6 +1798,14 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Dışarıdan gelen bağlantıları kabul et (varsayılan: -proxy veya -connect yoksa 1) + + Bitcoin Core + Bitcoin Çekirdeği + + + The %s developers + %s geliştiricileri + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. -fallbackfee çok yüksek bir değere ayarlanmış! Ücret tahminleri mevcut değilken ödeyebileceğiniz muamele ücretidir bu. @@ -2991,6 +1822,10 @@ Bind to given address and always listen on it. Use [host]:port notation for IPv6 Belirtilen adrese bağlan ve daima ondan dinle. IPv6 için [makine]:port yazımını kullanınız + + Cannot obtain a lock on data directory %s. %s is probably already running. + %s veri dizininde kilit elde edilemedi. %s muhtemelen hâlihazırda çalışmaktadır. + Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup Tüm cüzdan muamelelerini sil ve başlangıçta -rescan ile sadece blok zincirinin parçası olanları geri getir @@ -2999,6 +1834,10 @@ Distributed under the MIT software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>. MIT yazılım lisansı kapsamında yayınlanmıştır, ekteki COPYING dosyasına ya da <http://www.opensource.org/licenses/mit-license.php> adresine bakınız. + + Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + %s dosyasının okunması sırasında bir hata meydana geldi! Tüm anahtarlar doğru bir şekilde okundu, ancak muamele verileri ya da adres defteri unsurları hatalı veya eksik olabilir. + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) Bir cüzdan muamelesi değiştiğinde komutu çalıştır (komuttaki %s muamele kimliği ile değiştirilecektir) @@ -3007,6 +1846,18 @@ Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) Yerel aktarma politikasını ihlal ettiklerinde bile beyaz listedeki eşlerden gelen muamelelerin aktarılmasını zorla (varsayılan: %d) + + Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds) + Müsaade edilen azami medyan eş zamanı değişiklik sınırının ayarlaması. Zamanın yerel perspektifi bu miktar kadar ileri ya da geri eşler tarafından etkilenebilir. (Varsayılan %u saniye) + + + Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s) + Tek cüzdan muamelesinde ya da ham muamelede kullanılacak azami toplam ücret (%s olarak); bunu çok düşük olarak ayarlamak büyük muameleleri iptal edebilir (varsayılan: %s) + + + Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly. + Lütfen bilgisayarınızın saat ve tarihinin doğru olduğunu kontrol ediniz! Saatinizde gecikme varsa %s doğru şekilde çalışamaz. + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) Betik kontrolü iş parçacıklarının sayısını belirler (%u ilâ %d, 0 = otomatik, <0 = bu sayıda çekirdeği kullanma, varsayılan: %d) @@ -3019,14 +1870,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Bu yayın öncesi bir deneme sürümüdür - tüm riski siz üstlenmiş olursunuz - bitcoin oluşturmak ya da ticari uygulamalar için kullanmayınız - - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - Bu bilgisayarda %s unsuruna bağlanılamadı. Bitcoin Çekirdeği muhtemelen hâlihazırda çalışmaktadır. - - - Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. - Desteklenmeyen argüman -whitelistalwaysrelay görmezden gelindi, -whitelistrelay ve/veya -whitelistforcerelay kullanın. - Use UPnP to map the listening port (default: 1 when listening and no -proxy) Dinlenecek portu haritalamak için UPnP kullan (varsayılan: dinlenildiğinde ve -proxy olmadığında 1) @@ -3043,22 +1886,22 @@ Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Uyarı: şebeke tamamen mutabık değil gibi görünüyor! Bazı madenciler sorun yaşıyor gibi görünüyor. - - Warning: Unknown block versions being mined! It's possible unknown rules are in effect - İkaz: bilinmeyen blok sürümü oluşturulmaya çalışılıyor. Bilinmeyen kuralların işlemesi mümkündür. - Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Uyarı: eşlerimizle tamamen mutabık değiliz gibi görünüyor! Güncelleme yapmanız gerekebilir ya da diğer düğümlerin güncelleme yapmaları gerekebilir. - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Uyarı: wallet.dat bozuk, veriler geri kazanıldı! Özgün wallet.dat, wallet.{zamandamgası}.bak olarak %s klasörüne kaydedildi; bakiyeniz ya da muameleleriniz yanlışsa bir yedeklemeden tekrar yüklemeniz gerekir. - Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. Belirtilen ağ maskesi ya da IP adresinden bağlanan eşleri beyaz listeye al. Birden fazla kez belirtilebilir. + + You need to rebuild the database using -reindex-chainstate to change -txindex + -txindex'i değiştirmek için veritabanını -reindex-chainstate kullanarak tekrar inşa etmeniz gerekmektedir + + + %s corrupt, salvage failed + %s bozuk, geri kazanım başarısız oldu + -maxmempool must be at least %d MB -maxmempool asgari %d MB olmalıdır @@ -3071,10 +1914,22 @@ Append comment to the user agent string Kullanıcı aracı zincirine yorumu ekle + + Attempt to recover private keys from a corrupt wallet on startup + Başlangıçta bozuk bir cüzdandan özel anahtarları geri kazanmayı dene + Block creation options: Blok oluşturma seçenekleri: + + Cannot resolve -%s address: '%s' + Çözümlenemedi - %s adres: '%s' + + + Change index out of range + Aralık dışında değişiklik endeksi + Connect only to the specified node(s) Sadece belirtilen düğüme veya düğümlere bağlan @@ -3083,6 +1938,10 @@ Connection options: Bağlantı seçenekleri: + + Copyright (C) %i-%i + Telif hakkı (C) %i-%i + Corrupted block database detected Bozuk blok veritabanı tespit edildi @@ -3127,6 +1986,18 @@ Error initializing wallet database environment %s! %s cüzdan veritabanı ortamının başlatılmasında hata meydana geldi! + + Error loading %s + %s unsurunun yüklenmesinde hata oluştu + + + Error loading %s: Wallet corrupted + %s unsurunun yüklenmesinde hata oluştu: bozuk cüzdan + + + Error loading %s: Wallet requires newer version of %s + %s unsurunun yüklenmesinde hata oluştu: cüzdan %s programının yeni bir sürümüne ihtiyaç duyuyor + Error loading block database Blok veritabanının yüklenmesinde hata @@ -3151,10 +2022,18 @@ Incorrect or no genesis block found. Wrong datadir for network? Yanlış ya da bulunamamış doğuş bloku. Şebeke için yanlış veri klasörü mü? + + Initialization sanity check failed. %s is shutting down. + Başlatma sınaması başarısız oldu. %s kapatılıyor. + Invalid -onion address: '%s' Geçersiz -onion adresi: '%s' + + Invalid amount for -%s=<amount>: '%s' + -%s=<meblağ> için geçersiz meblağ: '%s' + Invalid amount for -fallbackfee=<amount>: '%s' -fallbackfee=<meblağ> için geçersiz meblağ: '%s' @@ -3163,6 +2042,10 @@ Keep the transaction memory pool below <n> megabytes (default: %u) Muamele bellek alanını <n> megabayttan düşük tut (varsayılan: %u) + + Loading banlist... + Yasaklama listesi yükleniyor... + Location of the auth cookie (default: data dir) auth çerezinin konumu (varsayılan: veri klasörü) @@ -3179,6 +2062,10 @@ Only connect to nodes in network <net> (ipv4, ipv6 or onion) Sadece <net> şebekesindeki düğümlere bağlan (ipv4, ipv6 veya onion) + + Print this help message and exit + Bu yardım mesajını yaz ve çık + Print version and exit Sürümü yaz ve çık @@ -3191,6 +2078,14 @@ Prune mode is incompatible with -txindex. Budama kipi -txindex ile uyumsuzdur. + + Rebuild chain state and block index from the blk*.dat files on disk + Zincir durumu ve blok endeksini diskteki blk*.dat dosyalarından yeniden derle + + + Rebuild chain state from the currently indexed blocks + Zincir durumunu güncel olarak endekslenen bloklardan yeniden derle + Set database cache size in megabytes (%d to %d, default: %d) Veritabanı önbellek boyutunu megabayt olarak belirt (%d ilâ %d, varsayılan: %d) @@ -3203,6 +2098,10 @@ Specify wallet file (within data directory) Cüzdan dosyası belirtiniz (veri klasörünün içinde) + + Unable to bind to %s on this computer. %s is probably already running. + Bu bilgisayarda %s unsuruna bağlanılamadı. %s muhtemelen hâlihazırda çalışmaktadır. + Unsupported argument -benchmark ignored, use -debug=bench. Desteklenmeyen -benchmark argümanı görmezden gelindi, -debug=bench kullanınız. @@ -3236,12 +2135,16 @@ %s cüzdan %s veri klasörünün dışında bulunuyor - Wallet options: - Cüzdan seçenekleri: + Wallet debugging/testing options: + Cüzdan hata ayıklama/test etme seçenekleri: - You need to rebuild the database using -reindex to change -txindex - -txindex'i değiştirmek için veritabanını -reindex kullanarak tekrar inşa etmeniz gerekmektedir + Wallet needed to be rewritten: restart %s to complete + Cüzdanın tekrar yazılması gerekiyordu: işlemi tamamlamak için %s programını yeniden başlatınız + + + Wallet options: + Cüzdan seçenekleri: 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 @@ -3255,10 +2158,6 @@ Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces) Belirtilen adrese bağlan ve JSON RPC bağlantıları için dinlemeye geç. IPv6 için [makine]:port imlasını kullanınız. Bu seçenek birden çok kez belirtilebilir (varsayılan: tüm arayüzlere bağlan) - - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - %s veri dizininde kilit elde edilemedi. Bitcoin Çekirdeği muhtemelen hâlihazırda çalışmaktadır. - Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) Yeni dosyaları umask 077 yerine varsayılan izinlerle oluştur (sadece devre dışı cüzdan işlevselliği ile etkilidir) @@ -3303,10 +2202,6 @@ Set maximum size of high-priority/low-fee transactions in bytes (default: %d) Yüksek öncelikli/düşük ücretli muamelelerin azami boyutunu bayt olarak ayarla (varsayılan: %d) - - Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) - Etkinse bitcoin oluşuturulmasına atanan iş parçacığı sayısını ayarla (-1 = tüm çekirdekler, varsayılan: %d) - The transaction amount is too small to send after the fee has been deducted Bu muamele, ücret düşüldükten sonra göndermek için çok düşük @@ -3331,34 +2226,14 @@ Accept public REST requests (default: %u) Herkese açık REST taleplerini kabul et (varsayılan: %u) - - Activating best chain... - En iyi zincir etkinleştiriliyor... - - - Attempt to recover private keys from a corrupt wallet.dat on startup - Başlangıçta bozuk bir wallet.dat dosyasından özel anahtarları geri kazanmayı dene - Automatically create Tor hidden service (default: %d) Otomatik olarak gizli Tor servisi oluştur (varsayılan: %d) - - Cannot resolve -whitebind address: '%s' - -whitebind adresi çözümlenemedi: '%s' - Connect through SOCKS5 proxy SOCKS5 vekil sunucusu vasıtasıyla bağlan - - Copyright (C) 2009-%i The Bitcoin Core Developers - Telif hakkı 2009-%i Bitcoin Çekirdeği Geliştiricileri - - - Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - wallet.dat dosyasının yüklenmesinde hata: Cüzdan Bitcoin Çekirdeğinin daha yeni bir sürümünü gerektirmektedir - Error reading from database, shutting down. Veritabanından okumada hata, kapatılıyor. @@ -3371,22 +2246,6 @@ Information Bilgi - - Initialization sanity check failed. Bitcoin Core is shutting down. - Başlatma sınaması başarısız oldu. Bitcoin Çekirdeği kapatılıyor. - - - Invalid amount for -maxtxfee=<amount>: '%s' - -maxtxfee=<tutar> için geçersiz tutar: '%s' - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - -minrelaytxfee=<amount> için geçersiz meblağ: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - -mintxfee=<amount> için geçersiz meblağ: '%s' - Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) -paytxfee=<tutar>:'%s' unsurunda geçersiz tutar (asgari %s olması lazımdır) @@ -3411,14 +2270,6 @@ RPC server options: RPC sunucu seçenekleri: - - Rebuild block chain index from current blk000??.dat files on startup - Başlangıçta blok zinciri indeksini güncel blk000??.dat dosyalarından tekrar inşa et - - - Receive and display P2P network alerts (default: %u) - P2P ağından gelen önemli uyarıları alın ve gösterin (önseçili değer: %u) - Reducing -maxconnections from %d to %d, because of system limitations. Sistem sınırlamaları sebebiyle -maxconnections %d değerinden %d değerine düşürülmüştür. @@ -3491,10 +2342,6 @@ Username for JSON-RPC connections JSON-RPC bağlantıları için kullanıcı ismi - - Wallet needed to be rewritten: restart Bitcoin Core to complete - Cüzdanın tekrar yazılması gerekmektedir: tamamlamak için Bitcoin Çekirdeğini yeniden başlatın - Warning Uyarı @@ -3515,10 +2362,6 @@ ZeroMQ notification options: ZeroMQ bildirim seçenekleri: - - wallet.dat corrupt, salvage failed - wallet.dat bozuk, geri kazanım başarısız oldu - Password for JSON-RPC connections JSON-RPC bağlantıları için parola @@ -3527,10 +2370,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) En iyi blok değiştiğinde komutu çalıştır (komut için %s parametresi blok hash değeri ile değiştirilecektir) - - This help message - Bu yardım mesajı - Allow DNS lookups for -addnode, -seednode and -connect -addnode, -seednode ve -connect için DNS aramalarına izin ver @@ -3539,10 +2378,6 @@ Loading addresses... Adresler yükleniyor... - - Error loading wallet.dat: Wallet corrupted - wallet.dat dosyasının yüklenmesinde hata oluştu: bozuk cüzdan - (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) (1 = tx meta verilerini tut mesela hesap sahibi ve ödeme talebi bilgileri, 2 = tx meta verilerini at) @@ -3559,10 +2394,6 @@ Do not keep transactions in the mempool longer than <n> hours (default: %u) Muameleleri bellek alanında <n> saatten fazla tutma (varsayılan: %u) - - Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. - wallet.dat dosyasının okunması sırasında bir hata meydana geldi! Tüm anahtarlar doğru bir şekilde okundu, ancak muamele verileri ya da adres defteri unsurları hatalı veya eksik olabilir. - Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) Bundan düşük ücretler (%s/kB olarak) muamele oluşturulması için sıfır değerinde ücret olarak kabul edilir (varsayılan: %s) @@ -3599,6 +2430,10 @@ Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported. Desteklenmeyen -socks argümanı bulundu. SOCKS sürümünün ayarlanması artık mümkün değildir, sadece SOCKS5 vekilleri desteklenmektedir. + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + Desteklenmeyen argüman -whitelistalwaysrelay görmezden gelindi, -whitelistrelay ve/veya -whitelistforcerelay kullanın. + Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s) Eşlere gizli Tor servisleri ile ulaşmak için ayrı SOCKS5 vekil sunucusu kullan (varsayılan: %s) @@ -3608,20 +2443,20 @@ JSON-RPC bağlantıları için kullanıcı ismi ve karmalanmış parola. <userpw> alanı şu biçimdedir: <USERNAME>:<SALT>$<HASH>. Kanonik bir Python betiği share/rpcuser klasöründe bulunabilir. Bu seçenek birden çok kez belirtilebilir. - (default: %s) - (varsayılan: %s) + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + İkaz: bilinmeyen blok sürümü oluşturulmaya çalışılıyor. Bilinmeyen kuralların işlemesi mümkündür. - Always query for peer addresses via DNS lookup (default: %u) - Eş adresleri sorgulaması için daima DNS aramasını kullan (varsayılan: %u) + Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup. + Uyarı: wallet.dat bozuk, veriler geri kazanıldı! Özgün %s, %s olarak %s klasörüne kaydedildi; bakiyeniz ya da muameleleriniz yanlışsa bir yedeklemeden tekrar yüklemeniz gerekir. - Error loading wallet.dat - wallet.dat dosyasının yüklenmesinde hata oluştu + (default: %s) + (varsayılan: %s) - Generate coins (default: %u) - Bitcoin oluştur (varsayılan: %u) + Always query for peer addresses via DNS lookup (default: %u) + Eş adresleri sorgulaması için daima DNS aramasını kullan (varsayılan: %u) How many blocks to check at startup (default: %u, 0 = all) @@ -3707,18 +2542,6 @@ Unknown network specified in -onlynet: '%s' -onlynet için bilinmeyen bir şebeke belirtildi: '%s' - - Cannot resolve -bind address: '%s' - -bind adresi çözümlenemedi: '%s' - - - Cannot resolve -externalip address: '%s' - -externalip adresi çözümlenemedi: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - -paytxfee=<meblağ> için geçersiz meblağ: '%s' - Insufficient funds Yetersiz bakiye diff --git a/src/qt/locale/bitcoin_tr_TR.ts b/src/qt/locale/bitcoin_tr_TR.ts index 979aeea03811f..344309c25fd33 100644 --- a/src/qt/locale/bitcoin_tr_TR.ts +++ b/src/qt/locale/bitcoin_tr_TR.ts @@ -25,10 +25,6 @@ C&lose K&apat - - &Copy Address - &Adresi Kopyala - Delete the currently selected address from the list Seçili adresi listeden sil @@ -45,73 +41,6 @@ &Delete &Sil - - Choose the address to send coins to - Para göndereceğiniz adresi seçin - - - Choose the address to receive coins with - Parayı alacağınız adresi seçin - - - C&hoose - S&eç - - - Sending addresses - Gönderim adresleri - - - Receiving addresses - Alış adresleri - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Bunlar ödeme gönderebileceğiniz Bitcoin adreslerinizdir. Para göndermeden önce mutlaka alıcı adresini ve tutarı kontrol edin. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Bunlar ödeme alabileceğiniz Bitcoin adreslerinizdir. Her işlem için yeni bir adres kullanmanız önerilir. - - - Copy &Label - Kopyala &Etiketle - - - &Edit - &Düzenle - - - Export Address List - Adres Listesini Dışa Aktar - - - Comma separated file (*.csv) - Virgül ile ayrılmış dosya (*.csv) - - - Exporting Failed - Dışa Aktarma Başarısız Oldu - - - There was an error trying to save the address list to %1. Please try again. - Adres listesini %1'e kaydederken bir hata oluştu. Lütfen tekrar deneyin. - - - - AddressTableModel - - Label - Etiket - - - Address - Adres - - - (no label) - (etiket yok) - AskPassphraseDialog @@ -126,15 +55,8 @@ Alış adresleri - - ClientModel - CoinControlDialog - - (no label) - (etiket yok) - EditAddressDialog @@ -146,7 +68,7 @@ &Address Adres - + FreespaceChecker @@ -165,18 +87,12 @@ OverviewPage - - PaymentServer - PeerTableModel QObject - - QRImageWidget - RPCConsole @@ -189,32 +105,9 @@ Copy &Address &Adresi Kopyala - - Address - Adres - - - Label - Etiket - - - - RecentRequestsTableModel - - Label - Etiket - - - (no label) - (etiket yok) - SendCoinsDialog - - (no label) - (etiket yok) - SendCoinsEntry @@ -231,58 +124,12 @@ TrafficGraphWidget - - TransactionDesc - TransactionDescDialog - - TransactionTableModel - - Label - Etiket - - - - TransactionView - - Exporting Failed - Dışa Aktarma Başarısız Oldu - - - Comma separated file (*.csv) - Virgül ile ayrılmış dosya (*.csv) - - - Label - Etiket - - - Address - Adres - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - - WalletView - - &Export - &Dışa Aktar - - - Export the data in the current tab to a file - Seçili sekmedeki veriyi dosya olarak dışa aktar - - bitcoin-core diff --git a/src/qt/locale/bitcoin_uk.ts b/src/qt/locale/bitcoin_uk.ts index 64df7b5ba5780..668e787a6eca8 100644 --- a/src/qt/locale/bitcoin_uk.ts +++ b/src/qt/locale/bitcoin_uk.ts @@ -25,10 +25,6 @@ C&lose З&акрити - - &Copy Address - &Скопіювати адресу - Delete the currently selected address from the list Вилучити вибрані адреси з переліку @@ -45,73 +41,6 @@ &Delete &Видалити - - Choose the address to send coins to - Виберіть адресу для відправлення монет - - - Choose the address to receive coins with - Виберіть адресу для отримання монет - - - C&hoose - &Обрати - - - Sending addresses - Адреси для відправлення - - - Receiving addresses - Адреси для отримання - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Це ваші Bitcoin-адреси для відправлення платежів. Перед відправленням монет завжди перевіряйте суму та адресу прийому. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Це ваша нова Bitcoin адреса для отримання платежів. Рекомендовано використовувати нову адресу для кожної транзакції. - - - Copy &Label - Скопіювати &мітку - - - &Edit - &Редагувати - - - Export Address List - Експортувати список адрес - - - Comma separated file (*.csv) - Значення, розділені комою (*.csv) - - - Exporting Failed - Помилка експорту - - - There was an error trying to save the address list to %1. Please try again. - Виникла помилка при спробі зберігання адрес до %1. Будь ласка спробуйте ще. - - - - AddressTableModel - - Label - Назва - - - Address - Адреса - - - (no label) - (немає назви) - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase Повторіть пароль - - Encrypt wallet - Зашифрувати гаманець - - - This operation needs your wallet passphrase to unlock the wallet. - Ця операція потребує пароль для розблокування гаманця. - - - Unlock wallet - Розблокувати гаманець - - - This operation needs your wallet passphrase to decrypt the wallet. - Ця операція потребує пароль для дешифрування гаманця. - - - Decrypt wallet - Дешифрувати гаманець - - - Change passphrase - Змінити пароль - - - Confirm wallet encryption - Підтвердити шифрування гаманця - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - УВАГА: Якщо ви зашифруєте гаманець і забудете пароль, ви <b>ВТРАТИТЕ ВСІ СВОЇ БІТКОІНИ</b>! - - - Are you sure you wish to encrypt your wallet? - Ви дійсно хочете зашифрувати свій гаманець? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Клієнт «Bitcoin Core» буде закрито для завершення процесу шифрування. Пам'ятайте, що шифрування гаманця не зможе повністю захистити ваші біткоїни від крадіжки якщо ваш комп'ютер буде інфіковано шкідливими програмами. - - - 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. - ВАЖЛИВО: Всі попередні резервні копії, які ви зробили з вашого файлу гаманця повинні бути замінені новоствореним, зашифрованим файлом гаманця. З міркувань безпеки, попередні резервні копії незашифрованого файла гаманця стануть непридатними одразу ж, як тільки ви почнете використовувати новий, зашифрований гаманець. - - - Warning: The Caps Lock key is on! - Увага: Ввімкнено Caps Lock! - - - Wallet encrypted - Гаманець зашифровано - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Введіть нову кодову фразу для гаманця.<br/>Будь ласка, використовуйте кодові фрази що містять <b> щонайменше десять випадкових символів </b> або <b> щонайменше вісім слів </b>. - - - Enter the old passphrase and new passphrase to the wallet. - Введіть старий пароль та новий пароль до гаманця. - - - Wallet encryption failed - Не вдалося зашифрувати гаманець - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Виникла помилка під час шифрування гаманця. Ваш гаманець не було зашифровано. - - - The supplied passphrases do not match. - Введені паролі не співпадають. - - - Wallet unlock failed - Не вдалося розблокувати гаманець - - - The passphrase entered for the wallet decryption was incorrect. - Введений пароль є неправильним. - - - Wallet decryption failed - Не вдалося розшифрувати гаманець - - - Wallet passphrase was successfully changed. - Пароль було успішно змінено. - BanTableModel @@ -269,6 +110,10 @@ Quit application Вийти + + &About %1 + П&ро %1 + About &Qt &Про Qt @@ -305,14 +150,6 @@ Open &URI... Відкрити &URI - - Bitcoin Core client - Клієнт «Bitcoin Core» - - - Importing blocks from disk... - Імпорт блоків з диску... - Reindexing blocks on disk... Переіндексація блоків на диску ... @@ -357,10 +194,6 @@ &Receive &Отримати - - Show information about Bitcoin Core - Показати інформацію про Bitcoin Core - &Show / Hide Показа&ти / Приховати @@ -397,22 +230,10 @@ Tabs toolbar Панель вкладок - - Bitcoin Core - Bitcoin Core - Request payments (generates QR codes and bitcoin: URIs) Створити запит платежу (генерує QR-код та bitcoin: URI) - - &About Bitcoin Core - П&ро Bitcoin Core - - - Modify configuration options for Bitcoin Core - Редагувати параметри Bitcoin Core - Show the list of used sending addresses and labels Показати список адрес і міток, що були використані для відправлення @@ -429,10 +250,6 @@ &Command-line options П&араметри командного рядка - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Показати довідку Bitcoin Core для отримання переліку можливих параметрів командного рядка. - %n active connection(s) to Bitcoin network %n активне з'єднання з мережею Bitcoin%n активні з'єднання з мережею Bitcoin%n активних з'єднань з мережею Bitcoin @@ -544,13 +361,6 @@ <b>Зашифрований</b> гаманець <b>заблоковано</b> - - ClientModel - - Network Alert - Сповіщення мережі - - CoinControlDialog @@ -629,150 +439,6 @@ Priority Пріоритет - - Copy address - Скопіювати адресу - - - Copy label - Скопіювати мітку - - - Copy amount - Скопіювати суму - - - Copy transaction ID - Скопіювати ID транзакції - - - Lock unspent - Заблокувати - - - Unlock unspent - Розблокувати - - - Copy quantity - Скопіювати кількість - - - Copy fee - Скопіювати комісію - - - Copy after fee - Скопіювати після комісії - - - Copy bytes - Скопіювати байти - - - Copy priority - Скопіювати пріорітет - - - Copy dust - Скопіювати пил - - - Copy change - Скопіювати решту - - - highest - найвищий - - - higher - вищий - - - high - високий - - - medium-high - вище за середній - - - medium - середній - - - low-medium - нижче за середній - - - low - низький - - - lower - нижчий - - - lowest - найнижчий - - - (%1 locked) - (%1 заблоковано) - - - none - відсутній - - - This label turns red if the transaction size is greater than 1000 bytes. - Ця позначка стане червоною, якщо розмір транзакції перевищить 1000 байтів. - - - This label turns red if the priority is smaller than "medium". - Ця позначка стане червоною, якщо пріоритет транзакції менше, ніж «середній». - - - This label turns red if any recipient receives an amount smaller than %1. - Ця позначка стане червоною, якщо будь-який отримувач отримає суму, меншу за %1. - - - Can vary +/- %1 satoshi(s) per input. - Може відрізнятися на +/- %1 сатоші за вхід - - - yes - так - - - no - ні - - - This means a fee of at least %1 per kB is required. - Це означає, що необхідно внести комісію (щонайменше %1 за КБ). - - - Can vary +/- 1 byte per input. - Може відрізнятися на +/- 1 байт за вхід. - - - Transactions with higher priority are more likely to get included into a block. - Транзакції з вищим пріоритетом мають більше шансів бути включеними до блоку. - - - (no label) - (немає назви) - - - change from %1 (%2) - решта з %1 (%2) - - - (change) - (решта) - EditAddressDialog @@ -796,38 +462,6 @@ &Address &Адреса - - New receiving address - Нова адреса для отримання - - - New sending address - Нова адреса для відправлення - - - Edit receiving address - Редагувати адресу для отримання - - - Edit sending address - Редагувати адресу для відправлення - - - The entered address "%1" is already in the address book. - Введена адреса «%1» вже присутня в адресній книзі. - - - The entered address "%1" is not a valid Bitcoin address. - Введена адреса «%1» не є коректною адресою в мережі Bitcoin. - - - Could not unlock wallet. - Неможливо розблокувати гаманець. - - - New key generation failed. - Не вдалося згенерувати нові ключі. - FreespaceChecker @@ -854,10 +488,6 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin Core - version версії @@ -866,10 +496,6 @@ (%1-bit) (%1-бітний) - - About Bitcoin Core - Про Bitcoin Core - Command-line options Параметри командного рядка @@ -906,29 +532,13 @@ Show splash screen on startup (default: %u) Показувати заставку під час запуску (типово: %u) - - Reset all settings changes made over the GUI - Скинути налаштування, які було змінено через графічний інтерфейс користувача - - + Intro Welcome Вітання - - Welcome to Bitcoin Core. - Ласкаво просимо в Bitcoin Core. - - - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - Оскільки це перший запуск програми, ви можете обрати де Bitcoin Core буде зберігати дані. - - - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - Bitcoin Core завантажить та збереже копію ланцюжка блоків Bitcoin. Щонайменше %1ГБ даних буде збережено в цьому каталозі. Гаманець теж буде збережено в цьому каталозі. - Use the default data directory Використовувати типовий каталог даних @@ -937,10 +547,6 @@ Use a custom data directory: Використовувати свій каталог даних: - - Bitcoin Core - Bitcoin Core - Error: Specified data directory "%1" cannot be created. Помилка: неможливо створити обраний каталог даних «%1». @@ -976,10 +582,6 @@ Select payment request file Виберіть файл запиту платежу - - Select payment request file to open - Виберіть файл запиту платежу для відкриття - OptionsDialog @@ -1019,10 +621,6 @@ 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. Згортати замість закриття. Якщо ця опція включена, програма закриється лише після вибору відповідного пункту в меню. - - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - Встановлює мову інтерфейсу. Зміни набудуть чинності після перезапуску Bitcoin Core. - 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 |. Сторонні URL (наприклад, block explorer), що з'являться на вкладці транзакцій у вигляді пункту контекстного меню. %s в URL буде замінено на хеш транзакції. Для відокремлення URLів використовуйте вертикальну риску |. @@ -1047,14 +645,6 @@ &Network &Мережа - - Automatically start Bitcoin Core after logging in to the system. - Автоматично запускати Bitcoin Core при вході до системи. - - - &Start Bitcoin Core on system login - &Запускати Bitcoin Core при вході до системи - (0 = auto, <0 = leave that many cores free) (0 = автоматично, <0 = вказує кількість вільних ядер) @@ -1284,182 +874,72 @@ - PaymentServer + PeerTableModel - URI handling - Обробка URI + User Agent + Клієнт користувача - Invalid payment address %1 - Помилка в адресі платежу %1 + Node/Service + Вузол/Сервіс - Payment request rejected - Запит платежу відхилено + Ping Time + Затримка + + + QObject - Payment request network doesn't match client network. - Мережа запиту платежу не є мережею клієнта. + Amount + Кількість - Payment request is not initialized. - Запит платежу не ініціалізовано. + Enter a Bitcoin address (e.g. %1) + Введіть адресу Bitcoin (наприклад %1) - Requested payment amount of %1 is too small (considered dust). - Сума запиту платежу для %1 занадто мала (вважається пилом) + %1 d + %1 д - Payment request error - Помилка запиту платежу + %1 h + %1 г - Cannot start bitcoin: click-to-pay handler - Неможливо запустити bitcoin: обробник click-to-pay + %1 m + %1 х - Payment request fetch URL is invalid: %1 - URL запиту платежу є некоректним: %1 + %1 s + %1 с - URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - Неможливо обробити URI! Причиною цього може бути некоректна Bitcoin-адреса або неправильні параметри URI. + None + Відсутні - Payment request file handling - Обробка файлу запиту платежу + N/A + Н/Д - Payment request file cannot be read! This can be caused by an invalid payment request file. - Неможливо прочитати файл запиту платежу! Ймовірно, файл пошкоджено. + %1 ms + %1 мс + + + RPCConsole - Payment request expired. - Запит платежу прострочено. + Client name + Назва клієнту - Unverified payment requests to custom payment scripts are unsupported. - Неперевірені запити платежів з власними платіжними сценаріями не підтримуються. + N/A + Н/Д - Invalid payment request. - Помилка в запиті платежу. - - - Refund from %1 - Відшкодування з %1 - - - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - Запит платежу %1 занадто великий (%2 байт, дозволено %3 байт). - - - Error communicating with %1: %2 - Помилка зв'язку з %1: %2 - - - Payment request cannot be parsed! - Неможливо розпізнати запит платежу! - - - Bad response from server %1 - Погана відповідь від сервера %1 - - - Payment acknowledged - Платіж підтверджено - - - Network request error - Помилка мережевого запиту - - - - PeerTableModel - - User Agent - Клієнт користувача - - - Node/Service - Вузол/Сервіс - - - Ping Time - Затримка - - - - QObject - - Amount - Кількість - - - Enter a Bitcoin address (e.g. %1) - Введіть адресу Bitcoin (наприклад %1) - - - %1 d - %1 д - - - %1 h - %1 г - - - %1 m - %1 х - - - %1 s - %1 с - - - None - Відсутні - - - N/A - Н/Д - - - %1 ms - %1 мс - - - - QRImageWidget - - &Save Image... - &Зберегти зображення... - - - &Copy Image - &Копіювати зображення - - - Save QR Code - Зберегти QR-код - - - PNG Image (*.png) - Зображення PNG (*.png) - - - - RPCConsole - - Client name - Назва клієнту - - - N/A - Н/Д - - - Client version - Версія клієнту + Client version + Версія клієнту &Information @@ -1513,10 +993,6 @@ Memory usage Використання пам'яті - - Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. - Відкрити файл журналу налагодження Bitcoin Core з поточного каталогу даних. Це може зайняти кілька секунд для великих файлів журналів. - Received Отримано @@ -1633,10 +1109,6 @@ Out: Вихідних: - - Build date - Дата збирання - Debug log file Файл звіту зневадження @@ -1673,10 +1145,6 @@ &Unban Node &Розблокувати Вузол - - Welcome to the Bitcoin Core RPC console. - Вітаємо у RPC-консолі Bitcoin Core. - Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. Використовуйте стрілки вгору вниз для навігації по історії, і <b>Ctrl-L</b> для очищення екрана. @@ -1804,18 +1272,6 @@ Remove Вилучити - - Copy label - Скопіювати мітку - - - Copy message - Скопіювати повідомлення - - - Copy amount - Копіювати кількість - ReceiveRequestDialog @@ -1835,73 +1291,6 @@ &Save Image... &Зберегти зображення... - - Request payment to %1 - Запит платежу на %1 - - - Payment information - Інформація про платіж - - - URI - URI - - - Address - Адреса - - - Amount - Кількість - - - Label - Назва - - - Message - Повідомлення - - - Resulting URI too long, try to reduce the text for label / message. - Кінцевий URI занадто довгий, спробуйте зменшити текст для мітки / повідомлення. - - - Error encoding URI into QR Code. - Помилка при кодуванні URI в QR-код. - - - - RecentRequestsTableModel - - Date - Дата - - - Label - Назва - - - Message - Повідомлення - - - Amount - Кількість - - - (no label) - (немає назви) - - - (no message) - (без повідомлення) - - - (no amount) - (без суми) - SendCoinsDialog @@ -1950,955 +1339,309 @@ Після комісії: - Change: - Решта: - - - If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address. - Якщо це поле активовано, але адреса для решти відсутня або некоректна, то решта буде відправлена на новостворену адресу. - - - Custom change address - Вказати адресу для решти - - - Transaction Fee: - Комісія за передачу: - - - Choose... - Виберіть... - - - collapse fee-settings - згорнути налаштування оплат - - - per kilobyte - за кілобайт - - - If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte. - Якщо комісія встановлюється в 1000 сатоші і розмір транзакції лише 250 байтів, то опція "за кілобайт" встановлює комісію в 250 сатоші, в той час, як "всього щонайменше" - в 1000 сатоші. Для транзакцій більших за кілобайт в обох випадках буде знято комісію за кілобайт. - - - Hide - Приховати - - - total at least - всього щонайменше - - - Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process. - Оплата тільки мінімальної комісії є прийнятною, допоки обсяг транзакцій є меншим простору в блоках. Але майте на увазі, що це може анулювати транзакцію, якщо попит на Bitcoin транзакції стане більшим, ніж мережа зможе обробити. - - - (read the tooltip) - (читати підказки) - - - Recommended: - Рекомендовано: - - - Custom: - Змінено: - - - (Smart fee not initialized yet. This usually takes a few blocks...) - (Розумну оплату ще не ініціалізовано. Це, зазвичай, триває кілька блоків...) - - - Confirmation time: - Час підтвердження: - - - normal - звичайний - - - fast - швидкий - - - Send as zero-fee transaction if possible - Надіслати транзакцію без сплати комісії, якщо це можливо - - - (confirmation may take longer) - (підтвердження може зайняти більше часу) - - - Send to multiple recipients at once - Відправити на декілька адрес - - - Add &Recipient - Дод&ати одержувача - - - Clear all fields of the form. - Очистити всі поля в формі - - - Dust: - Пил: - - - Clear &All - Очистити &все - - - Balance: - Баланс: - - - Confirm the send action - Підтвердити відправлення - - - S&end - &Відправити - - - Confirm send coins - Підтвердіть відправлення - - - %1 to %2 - %1 на %2 - - - Copy quantity - Копіювати кількість - - - Copy amount - Копіювати суму - - - Copy fee - Копіювати комісію - - - Copy after fee - Копіювати після комісії - - - Copy bytes - Копіювати байти - - - Copy priority - Копіювати пріорітет - - - Copy change - Копіювати решту - - - Total Amount %1 - Всього %1 - - - or - або - - - The amount to pay must be larger than 0. - Кількість монет для відправлення повинна бути більше 0. - - - The amount exceeds your balance. - Кількість монет для відправлення перевищує ваш баланс. - - - The total exceeds your balance when the %1 transaction fee is included. - Сума перевищить ваш баланс, якщо комісія %1 буде додана до вашої транзакції. - - - Transaction creation failed! - Не вдалося створити транзакцію! - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - Транзакцію відхилено! Це може статись, якщо декілька монет з вашого гаманця вже використані, наприклад, якщо ви використовуєте одну копію гаманця (wallet.dat), а монети були використані з іншої копії, але не позначені як використані в цій. - - - A fee higher than %1 is considered an absurdly high fee. - Плата вища, ніж %1 вважається шалено високою. - - - Payment request expired. - Запит платежу прострочено. - - - Pay only the required fee of %1 - Сплатіть лише мінімальну комісію у розмірі %1 - - - Estimated to begin confirmation within %n block(s). - Перше підтвердження очікується протягом %n блоку.Перше підтвердження очікується протягом %n блоків.Перше підтвердження очікується протягом %n блоків. - - - The recipient address is not valid. Please recheck. - Адреса отримувача неправильна. Будь ласка, перевірте її. - - - Duplicate address found: addresses should only be used once each. - Знайдено адресу, що дублюється: кожна адреса має бути вказана не більше одного разу. - - - Warning: Invalid Bitcoin address - Увага: Неправильна Bitcoin-адреса - - - (no label) - (немає назви) - - - Warning: Unknown change address - Увага: Невідома адреса для решти - - - Copy dust - Копіювати пил - - - Are you sure you want to send? - Ви впевнені, що хочете відправити? - - - added as transaction fee - додано як комісія за транзакцію - - - - SendCoinsEntry - - A&mount: - &Кількість: - - - Pay &To: - &Отримувач: - - - Enter a label for this address to add it to your address book - Введіть мітку для цієї адреси для додавання її в адресну книгу - - - &Label: - &Мітка: - - - Choose previously used address - Обрати ранiш використовувану адресу - - - This is a normal payment. - Це звичайний платіж. - - - The Bitcoin address to send the payment to - Адреса Bitcoin для відправлення платежу - - - Alt+A - Alt+A - - - Paste address from clipboard - Вставити адресу - - - Alt+P - Alt+P - - - Remove this entry - Видалити цей запис - - - 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. - Комісію буде знято зі вказаної суми. До отримувача надійде менше біткоінів, ніж було вказано в полі кількості. Якщо ж отримувачів декілька - комісію буде розподілено між ними. - - - S&ubtract fee from amount - В&ідняти комісію від суми - - - Message: - Повідомлення: - - - This is an unauthenticated payment request. - Цей запит платежу не є автентифікованим. - - - This is an authenticated payment request. - Цей запит платежу є автентифікованим. - - - Enter a label for this address to add it to the list of used addresses - Введіть мітку для цієї адреси для додавання її в список використаних адрес - - - 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. - Повідомлення, що було додане до bitcoin:URI та буде збережено разом з транзакцією для довідки. Примітка: Це повідомлення не буде відправлено в мережу Bitcoin. - - - Pay To: - Отримувач: - - - Memo: - Нотатка: - - - - ShutdownWindow - - Bitcoin Core is shutting down... - Bitcoin Core вимикається... - - - Do not shut down the computer until this window disappears. - Не вимикайте комп’ютер до зникнення цього вікна. - - - - SignVerifyMessageDialog - - Signatures - Sign / Verify a Message - Підписи - Підпис / Перевірка повідомлення - - - &Sign Message - &Підписати повідомлення - - - 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. - Ви можете підписувати повідомлення/угоди своїми адресами, щоб довести можливість отримання біткоінів, що будуть надіслані на них. Остерігайтеся підписувати будь-що нечітке чи неочікуване, так як за допомогою фішинг-атаки вас можуть спробувати ввести в оману для отримання вашого підпису під чужими словами. Підписуйте лише чіткі твердження, з якими ви повністю згодні. - - - The Bitcoin address to sign the message with - Адреса Bitcoin для підпису цього повідомлення - - - Choose previously used address - Обрати ранiш використовувану адресу - - - Alt+A - Alt+A - - - Paste address from clipboard - Вставити адресу - - - Alt+P - Alt+P - - - Enter the message you want to sign here - Введіть повідомлення, яке ви хочете підписати тут - - - Signature - Підпис - - - Copy the current signature to the system clipboard - Копіювати поточну сигнатуру до системного буферу обміну - - - Sign the message to prove you own this Bitcoin address - Підпишіть повідомлення щоб довести, що ви є власником цієї адреси - - - Sign &Message - &Підписати повідомлення - - - Reset all sign message fields - Скинути всі поля підпису повідомлення - - - Clear &All - Очистити &все - - - &Verify Message - П&еревірити повідомлення - - - 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! - Введіть нижче адресу отримувача, повідомлення (впевніться, що ви точно скопіювали символи завершення рядка, табуляцію, пробіли тощо) та підпис для перевірки повідомлення. Впевніться, що в підпис не було додано зайвих символів: це допоможе уникнути атак типу «людина посередині». Зауважте, що це лише засвідчує можливість отримання транзакцій підписувачем, але не в стані підтвердити джерело жодної транзакції! - - - The Bitcoin address the message was signed with - Адреса Bitcoin, якою було підписано це повідомлення - - - Verify the message to ensure it was signed with the specified Bitcoin address - Перевірте повідомлення для впевненості, що воно підписано вказаною Bitcoin-адресою - - - Verify &Message - Пере&вірити повідомлення - - - Reset all verify message fields - Скинути всі поля перевірки повідомлення - - - Click "Sign Message" to generate signature - Натисніть кнопку «Підписати повідомлення», для отримання підпису - - - The entered address is invalid. - Введена нечинна адреса. - - - Please check the address and try again. - Будь ласка, перевірте адресу та спробуйте ще. - - - The entered address does not refer to a key. - Введена адреса не відноситься до ключа. - - - Wallet unlock was cancelled. - Розблокування гаманця було скасоване. - - - Private key for the entered address is not available. - Приватний ключ для введеної адреси недоступний. - - - Message signing failed. - Не вдалося підписати повідомлення. - - - Message signed. - Повідомлення підписано. - - - The signature could not be decoded. - Підпис не можливо декодувати. - - - Please check the signature and try again. - Будь ласка, перевірте підпис та спробуйте ще. - - - The signature did not match the message digest. - Підпис не збігається з хешем повідомлення. - - - Message verification failed. - Не вдалося перевірити повідомлення. - - - Message verified. - Повідомлення перевірено. - - - - SplashScreen - - Bitcoin Core - Bitcoin Core - - - The Bitcoin Core developers - Розробники Bitcoin Core - - - [testnet] - [тестова мережа] - - - - TrafficGraphWidget - - KB/s - КБ/с - - - - TransactionDesc - - Open until %1 - Відкрито до %1 - - - conflicted - суперечить - - - %1/offline - %1/поза інтернетом - - - %1/unconfirmed - %1/не підтверджено - - - %1 confirmations - %1 підтверджень - - - Status - Статус - - - , broadcast through %n node(s) - , розіслано через %n вузол, розіслано через %n вузли, розіслано через %n вузлів - - - Date - Дата - - - Source - Джерело - - - Generated - Згенеровано - - - From - Відправник - - - To - Отримувач - - - own address - Власна адреса - - - watch-only - тільки спостереження - - - label - Мітка - - - Credit - Кредит - - - matures in %n more block(s) - «дозріє» через %n блок«дозріє» через %n блоки«дозріє» через %n блоків - - - not accepted - не прийнято - - - Debit - Дебет - - - Total debit - Загальний дебет - - - Total credit - Загальний кредит - - - Transaction fee - Комісія за транзакцію - - - Net amount - Загальна сума - - - Message - Повідомлення - - - Comment - Коментар - - - Transaction ID - ID транзакції - - - Merchant - Продавець - - - 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. - Після генерації монет, потрібно зачекати %1 блоків, перш ніж їх можна буде використати. Коли ви згенерували цей блок, його було відправлено в мережу для того, щоб він був доданий до ланцюжка блоків. Якщо ця процедура не вдасться, статус буде змінено на «не підтверджено» і ви не зможете витратити згенеровані монети. Таке може статись, якщо хтось інший згенерував блок на декілька секунд раніше. - - - Debug information - Налагоджувальна інформація - - - Transaction - Транзакція - - - Inputs - Входи - - - Amount - Кількість - - - true - true + Change: + Решта: - false - false + If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address. + Якщо це поле активовано, але адреса для решти відсутня або некоректна, то решта буде відправлена на новостворену адресу. - , has not been successfully broadcast yet - , ще не було успішно розіслано - - - Open for %n more block(s) - Відкрито на %n блокВідкрито на %n блокиВідкрито на %n блоків + Custom change address + Вказати адресу для решти - unknown - невідомо + Transaction Fee: + Комісія за передачу: - - - TransactionDescDialog - Transaction details - Деталі транзакції + Choose... + Виберіть... - This pane shows a detailed description of the transaction - Даний діалог показує детальну статистику по вибраній транзакції + collapse fee-settings + згорнути налаштування оплат - - - TransactionTableModel - Date - Дата + per kilobyte + за кілобайт - Type - Тип + If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte. + Якщо комісія встановлюється в 1000 сатоші і розмір транзакції лише 250 байтів, то опція "за кілобайт" встановлює комісію в 250 сатоші, в той час, як "всього щонайменше" - в 1000 сатоші. Для транзакцій більших за кілобайт в обох випадках буде знято комісію за кілобайт. - Immature (%1 confirmations, will be available after %2) - Незрілі (%1 підтверджень, будуть доступні після %2) - - - Open for %n more block(s) - Відкрито на %n блокВідкрито на %n блокиВідкрито на %n блоків + Hide + Приховати - Open until %1 - Відкрито до %1 + total at least + всього щонайменше - Confirmed (%1 confirmations) - Підтверджено (%1 підтверджень) + Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process. + Оплата тільки мінімальної комісії є прийнятною, допоки обсяг транзакцій є меншим простору в блоках. Але майте на увазі, що це може анулювати транзакцію, якщо попит на Bitcoin транзакції стане більшим, ніж мережа зможе обробити. - This block was not received by any other nodes and will probably not be accepted! - Цей блок не був отриманий жодними іншими вузлами і, ймовірно, не буде прийнятий! + (read the tooltip) + (читати підказки) - Generated but not accepted - Згенеровано, але не підтверджено + Recommended: + Рекомендовано: - Offline - Поза мережею + Custom: + Змінено: - Label - Назва + (Smart fee not initialized yet. This usually takes a few blocks...) + (Розумну оплату ще не ініціалізовано. Це, зазвичай, триває кілька блоків...) - Unconfirmed - Не підтверджено + Confirmation time: + Час підтвердження: - Confirming (%1 of %2 recommended confirmations) - Підтверджується (%1 з %2 рекомендованих підтверджень) + normal + звичайний - Conflicted - Суперечить + fast + швидкий - Received with - Отримані на + Send to multiple recipients at once + Відправити на декілька адрес - Received from - Отримано від + Add &Recipient + Дод&ати одержувача - Sent to - Відправлені на + Clear all fields of the form. + Очистити всі поля в формі - Payment to yourself - Відправлено собі + Dust: + Пил: - Mined - Добуті + Clear &All + Очистити &все - watch-only - тільки спостереження + Balance: + Баланс: - (n/a) - (недоступно) + Confirm the send action + Підтвердити відправлення - Transaction status. Hover over this field to show number of confirmations. - Статус транзакції. Наведіть вказівник на це поле, щоб показати кількість підтверджень. + S&end + &Відправити + + + SendCoinsEntry - Date and time that the transaction was received. - Дата і час, коли транзакцію було отримано. + A&mount: + &Кількість: - Type of transaction. - Тип транзакції. + Pay &To: + &Отримувач: - Whether or not a watch-only address is involved in this transaction. - Показує, чи було залучено адресу для спостереження в цій транзакції. + &Label: + &Мітка: - User-defined intent/purpose of the transaction. - Призначення транзакції (визначається користувачем). + Choose previously used address + Обрати ранiш використовувану адресу - Amount removed from or added to balance. - Сума, додана чи знята з балансу. + This is a normal payment. + Це звичайний платіж. - - - TransactionView - All - Всі + The Bitcoin address to send the payment to + Адреса Bitcoin для відправлення платежу - Today - Сьогодні + Alt+A + Alt+A - This week - На цьому тижні + Paste address from clipboard + Вставити адресу - This month - На цьому місяці + Alt+P + Alt+P - Last month - Минулого місяця + Remove this entry + Видалити цей запис - This year - Цього року + 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. + Комісію буде знято зі вказаної суми. До отримувача надійде менше біткоінів, ніж було вказано в полі кількості. Якщо ж отримувачів декілька - комісію буде розподілено між ними. - Range... - Проміжок... + S&ubtract fee from amount + В&ідняти комісію від суми - Received with - Отримані на + Message: + Повідомлення: - Sent to - Відправлені на + This is an unauthenticated payment request. + Цей запит платежу не є автентифікованим. - To yourself - Відправлені собі + This is an authenticated payment request. + Цей запит платежу є автентифікованим. - Mined - Добуті + Enter a label for this address to add it to the list of used addresses + Введіть мітку для цієї адреси для додавання її в список використаних адрес - Other - Інше + 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. + Повідомлення, що було додане до bitcoin:URI та буде збережено разом з транзакцією для довідки. Примітка: Це повідомлення не буде відправлено в мережу Bitcoin. - Enter address or label to search - Введіть адресу чи мітку для пошуку + Pay To: + Отримувач: - Min amount - Мінімальна сума + Memo: + Нотатка: + + + ShutdownWindow - Copy address - Скопіювати адресу + Do not shut down the computer until this window disappears. + Не вимикайте комп’ютер до зникнення цього вікна. + + + SignVerifyMessageDialog - Copy label - Скопіювати мітку + Signatures - Sign / Verify a Message + Підписи - Підпис / Перевірка повідомлення - Copy amount - Скопіювати суму + &Sign Message + &Підписати повідомлення - Copy transaction ID - Скопіювати ID транзакції + 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. + Ви можете підписувати повідомлення/угоди своїми адресами, щоб довести можливість отримання біткоінів, що будуть надіслані на них. Остерігайтеся підписувати будь-що нечітке чи неочікуване, так як за допомогою фішинг-атаки вас можуть спробувати ввести в оману для отримання вашого підпису під чужими словами. Підписуйте лише чіткі твердження, з якими ви повністю згодні. - Copy raw transaction - Скопіювати RAW транзакцію + The Bitcoin address to sign the message with + Адреса Bitcoin для підпису цього повідомлення - Edit label - Редагувати мітку + Choose previously used address + Обрати ранiш використовувану адресу - Show transaction details - Показати деталі транзакції + Alt+A + Alt+A - Export Transaction History - Експортувати історію транзакцій + Paste address from clipboard + Вставити адресу - Watch-only - Для спостереження + Alt+P + Alt+P - Exporting Failed - Помилка експорту + Enter the message you want to sign here + Введіть повідомлення, яке ви хочете підписати тут - There was an error trying to save the transaction history to %1. - Виникла помилка при спробі зберігання історії транзакцій до %1. + Signature + Підпис - Exporting Successful - Експорт успішно виконано + Copy the current signature to the system clipboard + Копіювати поточну сигнатуру до системного буферу обміну - The transaction history was successfully saved to %1. - Історію транзакцій було успішно збережено до %1. + Sign the message to prove you own this Bitcoin address + Підпишіть повідомлення щоб довести, що ви є власником цієї адреси - Comma separated file (*.csv) - Значення, розділені комою (*.csv) + Sign &Message + &Підписати повідомлення - Confirmed - Підтверджені + Reset all sign message fields + Скинути всі поля підпису повідомлення - Date - Дата + Clear &All + Очистити &все - Type - Тип + &Verify Message + П&еревірити повідомлення - Label - Назва + 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! + Введіть нижче адресу отримувача, повідомлення (впевніться, що ви точно скопіювали символи завершення рядка, табуляцію, пробіли тощо) та підпис для перевірки повідомлення. Впевніться, що в підпис не було додано зайвих символів: це допоможе уникнути атак типу «людина посередині». Зауважте, що це лише засвідчує можливість отримання транзакцій підписувачем, але не в стані підтвердити джерело жодної транзакції! - Address - Адреса + The Bitcoin address the message was signed with + Адреса Bitcoin, якою було підписано це повідомлення - ID - Ідентифікатор + Verify the message to ensure it was signed with the specified Bitcoin address + Перевірте повідомлення для впевненості, що воно підписано вказаною Bitcoin-адресою - Range: - Діапазон від: + Verify &Message + Пере&вірити повідомлення - to - до + Reset all verify message fields + Скинути всі поля перевірки повідомлення - UnitDisplayStatusBarControl + SplashScreen - Unit to show amounts in. Click to select another unit. - Одиниця виміру монет. Натисніть для вибору іншої. + [testnet] + [тестова мережа] - WalletFrame + TrafficGraphWidget - No wallet has been loaded. - Гаманець не завантажувався + KB/s + КБ/с - WalletModel + TransactionDescDialog - Send Coins - Відправити + This pane shows a detailed description of the transaction + Даний діалог показує детальну статистику по вибраній транзакції - WalletView - - &Export - &Експорт - - - Export the data in the current tab to a file - Експортувати дані з поточної вкладки в файл - - - Backup Wallet - Зробити резервне копіювання гаманця - - - Wallet Data (*.dat) - Данi гаманця (*.dat) - - - Backup Failed - Помилка резервного копіювання - - - There was an error trying to save the wallet data to %1. - Виникла помилка при спробі зберегти гаманець в %1. - - - The wallet data was successfully saved to %1. - Дані гаманця успішно збережено в %1. - + UnitDisplayStatusBarControl - Backup Successful - Успішне створення резервної копії + Unit to show amounts in. Click to select another unit. + Одиниця виміру монет. Натисніть для вибору іншої. @@ -2927,14 +1670,6 @@ If <category> is not supplied or if <category> = 1, output all debugging information. Якщо <category> не задано, або ж якщо <category> = 1, виводить всю налагоджувальну інформацію. - - Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s) - Максимальна загальна комісія (в %s) за одну транзакцію; занадто низьке значення може скасувати відправку великих транзакцій (типово: %s) - - - Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. - Будь ласка, перевірте коректність дати і часу на своєму комп'ютері! За наявності значної похибки Bitcoin Core буде працювати неправильно. - Prune configured below the minimum of %d MiB. Please use a higher number. Встановлений розмір ланцюжка блоків є замалим (меншим за %d МіБ). Будь ласка, виберіть більше число. @@ -2975,6 +1710,10 @@ Accept connections from outside (default: 1 if no -proxy or -connect) Приймати підключення ззовні (типово: 1 за відсутності -proxy чи -connect) + + Bitcoin Core + Bitcoin Core + Bind to given address and always listen on it. Use [host]:port notation for IPv6 Прив'язатися до даної адреси та прослуховувати її. Використовуйте запис виду [хост]:порт для IPv6 @@ -3003,10 +1742,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Це тестова збірка пре-релізної версії - використовуйте на свій страх і ризик - не застосовувати для добування монет або торгівлі - - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - Неможливо прив'язатися до %s на цьому комп'ютері. Можливо, Bitcoin Core вже запущено. - Use UPnP to map the listening port (default: 1 when listening and no -proxy) Використовувати UPnP для відображення порту, що прослуховується (типово: 1 при прослуховуванні та за відсутності -proxy) @@ -3027,10 +1762,6 @@ Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. Увага: Наш ланцюжок блоків відрізняється від ланцюжків підключених учасників! Можливо, вам, або іншим вузлам, необхідно оновитися. - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Увага: файл wallet.dat пошкоджено, дані врятовано! Оригінальний wallet.dat збережено як wallet.{timestamp}.bak до %s; якщо Ваш баланс чи транзакції неправильні, Ви можете відновити їх з резервної копії. - Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. Додати учасників, що під'єднуються з заданої підмережі чи IP-адреси, в білий список. Можна вказувати декілька разів. @@ -3195,10 +1926,6 @@ Wallet options: Параметри гаманця: - - You need to rebuild the database using -reindex to change -txindex - Вам необхідно перебудувати базу даних з використанням -reindex для того, щоб змінити -txindex - 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 Дозволити підключення по протоколу JSON-RPC зі вказаного джерела. Правильною для <ip> є окрема IP-адреса (наприклад, 1.2.3.4), IP-адреса та маска підмережі (наприклад, 1.2.3.4/255.255.255.0) або CIDR-адреса (наприклад, 1.2.3.4/24). Цей параметр можна вказувати декілька разів. @@ -3211,10 +1938,6 @@ Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces) Прив'язатися до даної адреси для прослуховування JSON-RPC підключень. Використовуйте запис виду [хост]:порт для IPv6. Цей параметр можна вказувати декілька разів (типово: прив'язуватися до всіх інтерфейсів) - - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - Не вдалося встановити блокування на каталог даних %s. Bitcoin Core, ймовірно, вже запущений. - Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) Створювати нові файли з типовими для системи атрибутами доступу замість маски 077 (діє тільки при вимкненому гаманці) @@ -3259,10 +1982,6 @@ Set maximum size of high-priority/low-fee transactions in bytes (default: %d) Встановити максимальний розмір транзакцій з високим пріоритетом та низькою комісією (в байтах) (типово: %d) - - Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) - Встановити кількість потоків для генерації монет (-1 = кількості ядер, типово: %d) - The transaction amount is too small to send after the fee has been deducted Залишок від суми транзакції зі сплатою комісії занадто малий @@ -3287,34 +2006,14 @@ Accept public REST requests (default: %u) Приймати публічні REST-запити (типово: %u) - - Activating best chain... - Активація найкращого ланцюжка... - - - Attempt to recover private keys from a corrupt wallet.dat on startup - Спочатку спробуйте відновити приватні ключі в пошкодженому wallet.dat - Automatically create Tor hidden service (default: %d) Автоматичне з'єднання з прихованим сервісом Tor (типово: %d) - - Cannot resolve -whitebind address: '%s' - Не вдалося розпізнати адресу для -whitebind: «%s» - Connect through SOCKS5 proxy Підключитись через SOCKS5-проксі - - Copyright (C) 2009-%i The Bitcoin Core Developers - (C) 2009-%i Розробники Bitcoin Core - - - Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - Помилка при завантаженні wallet.dat: Гаманець потребує новішої версії Bitcoin Core - Error reading from database, shutting down. Помилка читання бази даних, припиняю роботу. @@ -3327,22 +2026,6 @@ Information Інформація - - Initialization sanity check failed. Bitcoin Core is shutting down. - Не вдалося пройти базові перевірки під час ініціалізації. Bitcoin Core буде вимкнено. - - - Invalid amount for -maxtxfee=<amount>: '%s' - Неприпустима сума для -maxtxfee = <amount>: «%s» - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - Вказано некоректну суму для параметру -minrelaytxfee: «%s» - - - Invalid amount for -mintxfee=<amount>: '%s' - Вказано некоректну суму для параметру -mintxfee: «%s» - Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) Вказано некоректну суму для параметру -paytxfee: «%s» (повинно бути щонайменше %s) @@ -3367,14 +2050,6 @@ RPC server options: Параметри сервера RPC: - - Rebuild block chain index from current blk000??.dat files on startup - При запуску перебудувати індекс ланцюжка блоків з поточних файлів blk000??.dat - - - Receive and display P2P network alerts (default: %u) - Отримувати та відображати попередження з мережі (типово: %u) - Reducing -maxconnections from %d to %d, because of system limitations. Зменшення значення -maxconnections з %d до %d із-за обмежень системи. @@ -3447,10 +2122,6 @@ Username for JSON-RPC connections Ім'я користувача для JSON-RPC-з'єднань - - Wallet needed to be rewritten: restart Bitcoin Core to complete - Потрібно перезаписати гаманець: перезапустіть Bitcoin Core для завершення - Warning Попередження @@ -3467,10 +2138,6 @@ ZeroMQ notification options: Параметри сповіщень ZeroMQ: - - wallet.dat corrupt, salvage failed - wallet.dat пошкоджено, відновлення не вдалося - Password for JSON-RPC connections Пароль для JSON-RPC-з'єднань @@ -3479,10 +2146,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) Виконати команду, коли з'явиться новий блок (%s в команді змінюється на хеш блоку) - - This help message - Дана довідка - Allow DNS lookups for -addnode, -seednode and -connect Дозволити пошук в DNS для команд -addnode, -seednode та -connect @@ -3491,10 +2154,6 @@ Loading addresses... Завантаження адрес... - - Error loading wallet.dat: Wallet corrupted - Помилка при завантаженні wallet.dat: Гаманець пошкоджено - (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) (1 = утримувати метадані транзакцій (до яких відноситься інформація про власника рахунку та запити платежів), 2 - відкинути) @@ -3511,10 +2170,6 @@ Do not keep transactions in the mempool longer than <n> hours (default: %u) Не тримати транзакції в пам'яті довше <n> годин (типово: %u) - - Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. - Помилка читання wallet.dat! Всі ключі прочитано коректно, але дані транзакцій чи записи адресної книги можуть бути пропущені або пошкоджені. - Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) Комісії (в %s/kB), що менші за вказану, вважатимуться нульовими для створення транзакцій (типово: %s) @@ -3567,14 +2222,6 @@ Always query for peer addresses via DNS lookup (default: %u) Завжди дізнаватися адреси учасників через DNS (типово: %u) - - Error loading wallet.dat - Помилка при завантаженні wallet.dat - - - Generate coins (default: %u) - Генерація монет (типово: %u) - How many blocks to check at startup (default: %u, 0 = all) Скільки блоків перевіряти під час запуску (типово: %u, 0 = всі) @@ -3659,18 +2306,6 @@ Unknown network specified in -onlynet: '%s' Невідома мережа вказана в -onlynet: «%s» - - Cannot resolve -bind address: '%s' - Не вдалося розпізнати адресу для -bind: «%s» - - - Cannot resolve -externalip address: '%s' - Не вдалося розпізнати адресу для -externalip: «%s» - - - Invalid amount for -paytxfee=<amount>: '%s' - Помилка у величині комісії -paytxfee=<amount>: «%s» - Insufficient funds Недостатньо коштів diff --git a/src/qt/locale/bitcoin_ur_PK.ts b/src/qt/locale/bitcoin_ur_PK.ts index e37c87baa84f2..6b43bf63e5102 100644 --- a/src/qt/locale/bitcoin_ur_PK.ts +++ b/src/qt/locale/bitcoin_ur_PK.ts @@ -25,10 +25,6 @@ C&lose بند - - &Copy Address - کاپی پتہ - Delete the currently selected address from the list سلیکٹڈ پتے کو مٹائیں @@ -45,37 +41,6 @@ &Delete مٹا - - Choose the address to send coins to - کوئین وصول کرنے والے کا پتہ - - - Choose the address to receive coins with - کوئین بھیجنے والے کا پتہ - - - C&hoose - چننا - - - Sending addresses - جس پتے پر بھیجنے ہیں - - - - AddressTableModel - - Label - چٹ - - - Address - پتہ - - - (no label) - چٹ کے بغیر - AskPassphraseDialog @@ -91,23 +56,7 @@ Repeat new passphrase نیا پاس فریز دہرائیں - - Encrypt wallet - بٹوے کی رمزنگاری - - - Unlock wallet - بٹوا ان لاک - - - Decrypt wallet - خفیہ کشائی کر یںبٹوے کے - - - Change passphrase - پاس فریز تبدیل کریں - - + BanTableModel @@ -118,9 +67,6 @@ نقص - - ClientModel - CoinControlDialog @@ -135,10 +81,6 @@ Date تاریخ - - (no label) - چٹ کے بغیر - EditAddressDialog @@ -150,7 +92,7 @@ &Address پتہ - + FreespaceChecker @@ -173,9 +115,6 @@ OverviewPage - - PaymentServer - PeerTableModel @@ -186,9 +125,6 @@ رقم - - QRImageWidget - RPCConsole @@ -201,37 +137,6 @@ Copy &Address کاپی پتہ - - Address - پتہ - - - Amount - رقم - - - Label - چٹ - - - - RecentRequestsTableModel - - Date - تاریخ - - - Label - چٹ - - - Amount - رقم - - - (no label) - چٹ کے بغیر - SendCoinsDialog @@ -247,10 +152,6 @@ Balance: بیلنس: - - (no label) - چٹ کے بغیر - SendCoinsEntry @@ -267,120 +168,14 @@ TrafficGraphWidget - - TransactionDesc - - Date - تاریخ - - - Amount - رقم - - TransactionDescDialog - - TransactionTableModel - - Date - تاریخ - - - Type - ٹائپ - - - Label - چٹ - - - Sent to - کو بھیجا - - - (n/a) - (N / A) - - - - TransactionView - - All - تمام - - - Today - آج - - - This week - اس ہفتے - - - This month - اس مہینے - - - Last month - پچھلے مہینے - - - This year - اس سال - - - Range... - دیگر - - - Sent to - کو بھیجا - - - Date - تاریخ - - - Type - ٹائپ - - - Label - چٹ - - - Address - پتہ - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - - WalletView - - &Export - برآمد - - - Export the data in the current tab to a file - موجودہ ڈیٹا کو فائیل میں محفوظ کریں - - bitcoin-core - - This help message - یہ مدد کا پیغام - Insufficient funds ناکافی فنڈز diff --git a/src/qt/locale/bitcoin_uz@Cyrl.ts b/src/qt/locale/bitcoin_uz@Cyrl.ts index a9f9af6683e50..ce33262976d7e 100644 --- a/src/qt/locale/bitcoin_uz@Cyrl.ts +++ b/src/qt/locale/bitcoin_uz@Cyrl.ts @@ -25,10 +25,6 @@ C&lose &Ёпиш - - &Copy Address - Манзилдан &нусха олиш - Delete the currently selected address from the list Жорий танланган манзилни рўйхатдан ўчириш @@ -45,73 +41,6 @@ &Delete &Ўчириш - - Choose the address to send coins to - Тангаларни жўнатиш учун манзилни танланг - - - Choose the address to receive coins with - Тангаларни қабул қилиш учун манзилни танланг - - - C&hoose - &Танлаш - - - Sending addresses - Жўнатиладиган манзиллар - - - Receiving addresses - Қабул қилинадиган манзиллар - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - Улар тўловларни жўнатиш учун сизнинг Bitcoin манзилларингиз. Доимо тангаларни жўнатишдан олдин сумма ва қабул қилувчи манзилни текшириб кўринг. - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - Улар тўловларни қабул қилиш учун сизнинг Bitcoin манзилларингиз. Ҳар бир ўтказма учун янги қабул қилувчи манзилдан фойдаланиш тавсия қилинади. - - - Copy &Label - Нусха олиш ва ёрлиқ - - - &Edit - &Таҳрирлаш - - - Export Address List - Манзил рўйхатини экспорт қилиш - - - Comma separated file (*.csv) - Вергул билан ажратилган файл (*.csv) - - - Exporting Failed - Экспорт қилиб бўлмади - - - There was an error trying to save the address list to %1. Please try again. - Манзил рўйхатини %1.га сақлашда хатолик юз берди. Яна уриниб кўринг. - - - - AddressTableModel - - Label - Ёрлиқ - - - Address - Манзил - - - (no label) - (Ёрлиқ мавжуд эмас) - AskPassphraseDialog @@ -131,86 +60,6 @@ Repeat new passphrase Янги махфий сузни такрорланг - - Encrypt wallet - Ҳамённи қодлаш - - - This operation needs your wallet passphrase to unlock the wallet. - Ушбу операцияни амалга ошириш учун ҳамённи қулфдан чиқариш парол сўзини талаб қилади. - - - Unlock wallet - Ҳамённи қулфдан чиқариш - - - This operation needs your wallet passphrase to decrypt the wallet. - Ушбу операцияни амалга ошириш учун ҳамённи коддан чиқариш парол сўзини талаб қилади. - - - Decrypt wallet - Ҳамённи коддан чиқариш - - - Change passphrase - Махфий сузни узгартириш - - - Confirm wallet encryption - Ҳамённи кодлашни тасдиқлаш - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Диққат: Агар сиз ҳамёнингизни кодласангиз ва махфий сўзингизни унутсангиз, сиз <b>БАРЧА BITCOIN ПУЛЛАРИНГИЗНИ ЙЎҚОТАСИЗ</b>! - - - Are you sure you wish to encrypt your wallet? - Ҳамёнингизни кодлашни ростдан хоҳлайсизми? - - - 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. - МУҲИМ: Сиз қилган олдинги ҳамён файли заҳиралари янги яратилган, кодланган ҳамён файли билан алмаштирилиши керак. Хавфсизлик сабабларига кўра олдинги кодланган ҳамён файли заҳираси янги кодланган ҳамёндан фойдаланишингиз билан яроқсиз ҳолга келади. - - - Warning: The Caps Lock key is on! - Диққат: Caps Lock тугмаси ёқилган! - - - Wallet encrypted - Ҳамёни кодланган - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Ҳамёнга янги махфий сўз киритинг.<br/>Илтимос, <b>ўнта ёки тасодифий белгили</b> махфий сўздан фойдаланинг ёки <b>саккизта ёки кўпроқ сўзлар</b>дан фойдаланинг. - - - Wallet encryption failed - Ҳамённи кодлаш амалга ошмади - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Ҳамённи кодлаш ташқи хато туфайли амалга ошмади. Ҳамёнингиз кодланмади. - - - The supplied passphrases do not match. - Киритилган пароллар мос келмади. - - - Wallet unlock failed - Ҳамённи қулфдан чиқариш амалга ошмади - - - The passphrase entered for the wallet decryption was incorrect. - Ҳамённи коддан чиқариш учун киритилган парол нотўғри. - - - Wallet decryption failed - Ҳамённи коддан чиқариш амалга ошмади - - - Wallet passphrase was successfully changed. - Ҳамён пароли муваффақиятли алмаштирилди. - BanTableModel @@ -289,14 +138,6 @@ Open &URI... Интернет манзилни очиш - - Bitcoin Core client - Bitcoin асос мижози - - - Importing blocks from disk... - Дискдан блоклар импорт қилинмоқда... - Reindexing blocks on disk... Дискдаги блоклар қайта индексланмоқда... @@ -341,10 +182,6 @@ &Receive &Қабул қилиш - - Show information about Bitcoin Core - Bitcoin Core ҳақидаги маълумотларни кўрсатиш - &Show / Hide &Кўрсатиш / Яшириш @@ -381,18 +218,10 @@ Tabs toolbar Ички ойналар асбоблар панели - - Bitcoin Core - Bitcoin Core - Request payments (generates QR codes and bitcoin: URIs) Тўловлар (QR кодлари ва bitcoin ёрдамида яратишлар: URI’лар) сўраш - - &About Bitcoin Core - Bitcoin Core &ҳақида - Show the list of used sending addresses and labels Фойдаланилган жўнатилган манзиллар ва ёрлиқлар рўйхатини кўрсатиш @@ -409,10 +238,6 @@ &Command-line options &Буйруқлар сатри мосламалари - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Мавжуд Bitcoin буйруқлар матни мосламалари билан Bitcoin Core ёрдам хабарларини олиш рўйхатини кўрсатиш - %n active connection(s) to Bitcoin network %n та Bitcoin тармоғига фаол уланиш мавжуд @@ -490,13 +315,6 @@ Ҳамён <b>кодланган</b> ва вақтинча <b>қулфланган</b> - - ClientModel - - Network Alert - Тармоқ огоҳлантиргичи - - CoinControlDialog @@ -563,138 +381,6 @@ Priority Муҳимлиги - - Copy address - Манзилни нусхалаш - - - Copy label - Ёрликни нусхала - - - Copy amount - Кийматни нусхала - - - Copy transaction ID - Ўтказам рақамидан нусха олиш - - - Lock unspent - Сарфланмаганларни қулфлаш - - - Unlock unspent - Сарфланмаганларни қулфдан чиқариш - - - Copy quantity - Нусха сони - - - Copy fee - Нусха солиғи - - - Copy after fee - Нусха солиқдан сўнг - - - Copy bytes - Нусха байти - - - Copy priority - Нусха муҳимлиги - - - Copy dust - Нусха чангги - - - Copy change - Нусха қайтими - - - highest - энг юқори - - - higher - юқорирок - - - high - юқори - - - medium-high - ўртача-юқори - - - medium - ўрта - - - low-medium - паст-юқори - - - low - паст - - - lower - пастроқ - - - lowest - энг паст - - - (%1 locked) - (%1 қулфланган) - - - none - йўқ - - - Can vary +/- %1 satoshi(s) per input. - Ҳар бир кирим +/- %1 сатоши(лар) билан ўзгариши мумкин. - - - yes - ҳа - - - no - йўқ - - - This means a fee of at least %1 per kB is required. - Бу дегани солиқ ҳар кб учун камида %1 талаб қилинади. - - - Can vary +/- 1 byte per input. - Ҳар бир кирим +/- 1 байт билан ўзгариши мумкин. - - - Transactions with higher priority are more likely to get included into a block. - Юқори муҳимликка эга бўлган ўтказмалар тезда блокнинг ичига қўшимча олади. - - - (no label) - (Ёрлик мавжуд эмас) - - - change from %1 (%2) - %1 (%2)дан ўзгартириш - - - (change) - (ўзгартириш) - EditAddressDialog @@ -718,38 +404,6 @@ &Address &Манзил - - New receiving address - Янги кабул килувчи манзил - - - New sending address - Янги жунатилувчи манзил - - - Edit receiving address - Кабул килувчи манзилни тахрирлаш - - - Edit sending address - Жунатилувчи манзилни тахрирлаш - - - The entered address "%1" is already in the address book. - Киритилган "%1" манзили аллақачон манзил китобида. - - - The entered address "%1" is not a valid Bitcoin address. - Киритилган "%1" манзили тўғри Bitcoin манзили эмас. - - - Could not unlock wallet. - Ҳамён қулфдан чиқмади. - - - New key generation failed. - Янги калит яратиш амалга ошмади. - FreespaceChecker @@ -776,10 +430,6 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin Core - version версияси @@ -788,10 +438,6 @@ (%1-bit) (%1-bit) - - About Bitcoin Core - Bitcoin Core ҳақида - Command-line options Буйруқлар сатри мосламалари @@ -811,18 +457,6 @@ Welcome Хуш келибсиз - - Welcome to Bitcoin Core. - "Bitcoin Core"га хуш келибсиз. - - - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - Биринчи марта дастур ишга тушгани каби сиз Bitcoin Core маълумотларини жойлаштирадиган жойни танлашингиз мумкин. - - - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - Bitcoin Core юклаб олинади ва Bitcoin блок занжири нусхаси жойлаштирилади. Камида %1GB маълумот ушбу директорияга жойлаштирилади ва вақт давомида ўсиб боради. Ҳамён ҳам ушбу директорияда жойлашади. - Use the default data directory Стандарт маълумотлар директориясидан фойдаланиш @@ -831,10 +465,6 @@ Use a custom data directory: Бошқа маълумотлар директориясида фойдаланинг: - - Bitcoin Core - Bitcoin Core - Error: Specified data directory "%1" cannot be created. Хато: кўрсатилган "%1" маълумотлар директориясини яратиб бўлмайди. @@ -862,10 +492,6 @@ Select payment request file Тўлов сўрови файлини танлаш - - Select payment request file to open - Очиш учун тўлов сўрови файлини танлаш - OptionsDialog @@ -1057,29 +683,6 @@ Жорий умумий баланс фақат кўринадиган манзилларда - - PaymentServer - - URI handling - URI осилиб қолмоқда - - - Invalid payment address %1 - Нотўғри тўлов манзили %1 - - - Payment request rejected - Тўлов сўрови инкор этилди - - - Payment request network doesn't match client network. - Тўлов сўрови тармоғи мижоз тармоғига мос келмайди. - - - Payment request error - Тўлов сўрови хато - - PeerTableModel @@ -1122,25 +725,6 @@ %1 мс - - QRImageWidget - - &Save Image... - Расмни &сақлаш - - - &Copy Image - Расмдан &нусха олиш - - - Save QR Code - QR кодни сақлаш - - - PNG Image (*.png) - PNG расм (*.png) - - RPCConsole @@ -1259,10 +843,6 @@ Out: Ташқарига: - - Build date - Тузилган санаси - Debug log file Тузатиш журнали файли @@ -1386,18 +966,6 @@ Remove Ўчириш - - Copy label - Ёрликни нусхала - - - Copy message - Хабарни нусхала - - - Copy amount - Кийматни нусхала - ReceiveRequestDialog @@ -1413,99 +981,40 @@ &Save Image... Расмни &сақлаш + + + SendCoinsDialog - Request payment to %1 - %1 дан Тўловни сўраш + Send Coins + Тангаларни жунат - Payment information - Тўлов маълумоти + Coin Control Features + Танга бошқаруви ҳусусиятлари - URI - URI + automatically selected + автоматик тарзда танланган - Address - Манзил + Insufficient funds! + Кам миқдор - Amount - Миқдори + Quantity: + Сони: - Label - Ёрлик + Bytes: + Байт: - Message - Хабар + Amount: + Миқдори: - - - RecentRequestsTableModel - Date - Сана - - - Label - Ёрлик - - - Message - Хабар - - - Amount - Миқдори - - - (no label) - (Ёрлик мавжуд эмас) - - - (no message) - (Хабар йўқ) - - - (no amount) - (Миқдор мавжуд эмас) - - - - SendCoinsDialog - - Send Coins - Тангаларни жунат - - - Coin Control Features - Танга бошқаруви ҳусусиятлари - - - automatically selected - автоматик тарзда танланган - - - Insufficient funds! - Кам миқдор - - - Quantity: - Сони: - - - Bytes: - Байт: - - - Amount: - Миқдори: - - - Priority: - Муҳимлиги: + Priority: + Муҳимлиги: Fee: @@ -1583,74 +1092,6 @@ S&end Жў&натиш - - Confirm send coins - Тангалар жўнаишни тасдиқлаш - - - %1 to %2 - %1 дан %2 - - - Copy quantity - Нусха сони - - - Copy amount - Кийматни нусхала - - - Copy fee - Нусха солиғи - - - Copy after fee - Нусха солиқдан сўнг - - - Copy bytes - Нусха байти - - - Copy priority - Нусха муҳимлиги - - - Copy change - Нусха қайтими - - - or - ёки - - - The amount to pay must be larger than 0. - Тўлов миқдори 0. дан катта бўлиши керак. - - - Warning: Invalid Bitcoin address - Диққат: Нотўғр Bitcoin манзили - - - (no label) - (Ёрлик мавжуд эмас) - - - Warning: Unknown change address - Диққат: Номаълум ўзгариш манзили - - - Copy dust - Нусха чангги - - - Are you sure you want to send? - Жўнатишни хоҳлашингизга ишончингиз комилми? - - - added as transaction fee - ўтказма солиғи қўшилди - SendCoinsEntry @@ -1662,10 +1103,6 @@ Pay &To: &Тўлов олувчи: - - Enter a label for this address to add it to your address book - Манзил китобингизга қўшиш учун ушбу манзил учун ёрлиқ киритинг - &Label: &Ёрлиқ: @@ -1728,21 +1165,9 @@ Clear &All Барчасини & Тозалаш - - Message verified. - Хабар тасдиқланди. - - + SplashScreen - - Bitcoin Core - Bitcoin Core - - - The Bitcoin Core developers - Bitcoin Core дастурчилари - [testnet] [testnet] @@ -1751,358 +1176,16 @@ TrafficGraphWidget - - TransactionDesc - - Open until %1 - %1 гача очиш - - - %1/unconfirmed - %1/тасдиқланмади - - - %1 confirmations - %1 тасдиқлашлар - - - Date - Сана - - - Source - Манба - - - Generated - Яратилган - - - From - Дан - - - To - Га - - - own address - ўз манзили - - - label - ёрлиқ - - - Credit - Кредит (қарз) - - - not accepted - қабул қилинмади - - - Transaction fee - Ўтказма тўлови - - - Net amount - Умумий миқдор - - - Message - Хабар - - - Comment - Шарҳ - - - Transaction ID - ID - - - Merchant - Савдо - - - Transaction - Ўтказма - - - Amount - Миқдори - - - true - рост - - - false - ёлғон - - - , has not been successfully broadcast yet - , ҳалигача трансляция қилингани йўқ - - - unknown - Номаълум - - TransactionDescDialog - - Transaction details - Операция тафсилотлари - This pane shows a detailed description of the transaction Ушбу ойна операциянинг батафсил таърифини кўрсатади - - TransactionTableModel - - Date - Сана - - - Type - Тури - - - Open until %1 - %1 гача очиш - - - Confirmed (%1 confirmations) - Тасдиқланди (%1 та тасдиқ) - - - This block was not received by any other nodes and will probably not be accepted! - Ушбу тўсиқ бирорта бошқа уланишлар томонидан қабул қилинмаган ва тасдиқланмаган! - - - Generated but not accepted - Яратилди, аммо қабул қилинмади - - - Offline - Оффлайн - - - Label - Ёрлиқ - - - Unconfirmed - Тасдиқланмаган - - - Received with - Ёрдамида қабул қилиш - - - Received from - Дан қабул қилиш - - - Sent to - Жўнатиш - - - Payment to yourself - Ўзингизга тўлов - - - Mined - Фойда - - - (n/a) - (қ/қ) - - - Transaction status. Hover over this field to show number of confirmations. - Ўтказма ҳолати. Ушбу майдон бўйлаб тасдиқлашлар сонини кўрсатиш. - - - Date and time that the transaction was received. - Ўтказма қабул қилинган сана ва вақт. - - - Type of transaction. - Пул ўтказмаси тури - - - Amount removed from or added to balance. - Миқдор ўчирилган ёки балансга қўшилган. - - - - TransactionView - - All - Барча - - - Today - Бугун - - - This week - Шу ҳафта - - - This month - Шу ой - - - Last month - Ўтган хафта - - - This year - Шу йил - - - Range... - Оралиқ... - - - Received with - Ёрдамида қабул қилинган - - - Sent to - Жўнатиш - - - To yourself - Ўзингизга - - - Mined - Фойда - - - Other - Бошка - - - Enter address or label to search - Излаш учун манзил ёки ёрлиқни киритинг - - - Min amount - Мин қиймат - - - Copy address - Манзилни нусхалаш - - - Copy label - Ёрликни нусхалаш - - - Copy amount - Кийматни нусхала - - - Copy transaction ID - Ўтказам рақамидан нусха олиш - - - Edit label - Ёрликни тахрирлаш - - - Show transaction details - Ўтказма тафсилотларини кўрсатиш - - - Export Transaction History - Ўтказмалар тарихини экспорт қилиш - - - Watch-only - Фақат кўришга - - - Exporting Failed - Экспорт қилиб бўлмади - - - The transaction history was successfully saved to %1. - Ўтказмалар тарихи %1 га муваффаққиятли сақланди. - - - Comma separated file (*.csv) - Вергул билан ажратилган файл (*.csv) - - - Confirmed - Тасдиқланди - - - Date - Сана - - - Type - Туркум - - - Label - Ёрлик - - - Address - Манзил - - - ID - ID - - - Range: - Оралиқ: - - - to - Кимга - - UnitDisplayStatusBarControl - - WalletFrame - - No wallet has been loaded. - Хали бирорта хамён юкланмади - - - - WalletModel - - Send Coins - Тангаларни жунат - - - - WalletView - - &Export - &Экспорт - - - Export the data in the current tab to a file - Жорий ички ойна ичидаги маълумотларни файлга экспорт қилиш - - bitcoin-core @@ -2121,6 +1204,10 @@ Run in the background as a daemon and accept commands Демон сифатида орқа фонда ишга туширинг ва буйруқларга рози бўлинг + + Bitcoin Core + Bitcoin Core + Connection options: Уланиш кўрсаткичлари: @@ -2141,10 +1228,6 @@ Password for JSON-RPC connections JSON-RPC уланишлари учун парол - - This help message - Бу ёрдам хабари - Loading addresses... Манзиллар юкланмоқда... diff --git a/src/qt/locale/bitcoin_uz@Latn.ts b/src/qt/locale/bitcoin_uz@Latn.ts deleted file mode 100644 index 2e4dabb59fb78..0000000000000 --- a/src/qt/locale/bitcoin_uz@Latn.ts +++ /dev/null @@ -1,169 +0,0 @@ - - - AddressBookPage - - Create a new address - Yangi manzil yaratish - - - &New - &Yangi - - - &Copy - &Nusxalash - - - C&lose - Yo&pish - - - &Copy Address - &Manzillarni nusxalash - - - &Delete - &O'chirish - - - - AddressTableModel - - Label - Yorliq - - - Address - Manzil - - - - AskPassphraseDialog - - - BanTableModel - - - BitcoinGUI - - - ClientModel - - - CoinControlDialog - - - EditAddressDialog - - - FreespaceChecker - - - HelpMessageDialog - - - Intro - - - OpenURIDialog - - - OptionsDialog - - - OverviewPage - - - PaymentServer - - - PeerTableModel - - - QObject - - - QRImageWidget - - - RPCConsole - - - ReceiveCoinsDialog - - - ReceiveRequestDialog - - Address - Manzil - - - Label - Yorliq - - - - RecentRequestsTableModel - - Label - Yorliq - - - - SendCoinsDialog - - - SendCoinsEntry - - - ShutdownWindow - - - SignVerifyMessageDialog - - - SplashScreen - - - TrafficGraphWidget - - - TransactionDesc - - - TransactionDescDialog - - - TransactionTableModel - - Label - Yorliq - - - - TransactionView - - Label - Yorliq - - - Address - Manzil - - - - UnitDisplayStatusBarControl - - - WalletFrame - - - WalletModel - - - WalletView - - - bitcoin-core - - \ No newline at end of file diff --git a/src/qt/locale/bitcoin_vi.ts b/src/qt/locale/bitcoin_vi.ts index 47745a3bc8ed0..e8bf01ab1b726 100644 --- a/src/qt/locale/bitcoin_vi.ts +++ b/src/qt/locale/bitcoin_vi.ts @@ -17,33 +17,10 @@ &Copy Sao chép - - &Copy Address - Sao chép địa chỉ - &Delete &Xóa - - Comma separated file (*.csv) - Tập tin tách biệt bởi dấu phẩy (*.csv) - - - - AddressTableModel - - Label - Nhãn dữ liệu - - - Address - Địa chỉ - - - (no label) - (chưa có nhãn) - AskPassphraseDialog @@ -54,9 +31,6 @@ BitcoinGUI - - ClientModel - CoinControlDialog @@ -67,10 +41,6 @@ Amount Số lượng - - (no label) - (chưa có nhãn) - EditAddressDialog @@ -82,7 +52,7 @@ &Address Địa chỉ - + FreespaceChecker @@ -101,9 +71,6 @@ OverviewPage - - PaymentServer - PeerTableModel @@ -114,9 +81,6 @@ Số lượng - - QRImageWidget - RPCConsole @@ -129,33 +93,6 @@ Copy &Address Sao chép địa chỉ - - Address - Địa chỉ - - - Amount - Số lượng - - - Label - Nhãn dữ liệu - - - - RecentRequestsTableModel - - Label - Nhãn dữ liệu - - - Amount - Số lượng - - - (no label) - (chưa có nhãn) - SendCoinsDialog @@ -163,10 +100,6 @@ Amount: Số lượng: - - (no label) - (chưa có nhãn) - SendCoinsEntry @@ -183,50 +116,12 @@ TrafficGraphWidget - - TransactionDesc - - Amount - Số lượng - - TransactionDescDialog - - TransactionTableModel - - Label - Nhãn dữ liệu - - - - TransactionView - - Comma separated file (*.csv) - Tập tin tách biệt bởi dấu phẩy (*.csv) - - - Label - Nhãn dữ liệu - - - Address - Địa chỉ - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - - WalletView - bitcoin-core diff --git a/src/qt/locale/bitcoin_vi_VN.ts b/src/qt/locale/bitcoin_vi_VN.ts index d55fa618855fd..a4e1588c9320c 100644 --- a/src/qt/locale/bitcoin_vi_VN.ts +++ b/src/qt/locale/bitcoin_vi_VN.ts @@ -25,10 +25,6 @@ C&lose Đó&ng - - &Copy Address - &Copy Địa Chỉ - Delete the currently selected address from the list Xóa địa chỉ hiện tại từ danh sách @@ -45,61 +41,6 @@ &Delete &Xó&a - - Choose the address to send coins to - Chọn địa chỉ để gửi coin tới - - - Choose the address to receive coins with - Chọn địa chỉ để nhận coin - - - C&hoose - C&họn - - - Sending addresses - Địa chỉ gửi - - - Receiving addresses - Địa chỉ nhận - - - Copy &Label - Copy &Nhãn - - - &Edit - &Sửa - - - Export Address List - Xuất Danh Sách Địa Chỉ - - - Comma separated file (*.csv) - Comma separated file (*.csv) - - - Exporting Failed - Xuất Đã Thất Bại - - - - AddressTableModel - - Label - Nhãn - - - Address - Địa chỉ - - - (no label) - (không nhãn) - AskPassphraseDialog @@ -119,23 +60,7 @@ Repeat new passphrase Điền lại passphrase - - Encrypt wallet - Mã hóa ví - - - Unlock wallet - Mở khóa ví - - - Decrypt wallet - Giải mã ví - - - Wallet encrypted - Ví đã được mã hóa - - + BanTableModel @@ -173,10 +98,6 @@ Open &URI... Mở &URI... - - Bitcoin Core client - Bitcoin Core client - Bitcoin Bitcoin @@ -213,14 +134,6 @@ &Help Trợ &giúp - - Bitcoin Core - Bitcoin Core - - - &About Bitcoin Core - &Về Bitcoin Core - %n hour(s) %n giờ @@ -266,13 +179,6 @@ Giao dịch đang tới - - ClientModel - - Network Alert - Network Alert - - CoinControlDialog @@ -319,43 +225,7 @@ Priority Tầm quan trọng - - Copy address - Copy địa chỉ - - - Copy label - Copy nhãn - - - Copy amount - Lượng copy - - - low - thấp - - - lower - thấp hơn - - - lowest - thấp nhất - - - yes - - - - no - không - - - (no label) - (không nhãn) - - + EditAddressDialog @@ -366,7 +236,7 @@ &Address Địa chỉ - + FreespaceChecker @@ -376,18 +246,10 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin Core - version version - - About Bitcoin Core - Về Bitcoin Core - Intro @@ -395,10 +257,6 @@ Welcome Chào mừng - - Bitcoin Core - Bitcoin Core - Error Lỗi @@ -461,9 +319,6 @@ Tổng: - - PaymentServer - PeerTableModel @@ -478,9 +333,6 @@ Lượng - - QRImageWidget - RPCConsole @@ -514,52 +366,13 @@ &Amount: Lượng: - - Copy label - Copy nhãn - - - Copy amount - Lượng copy - - + ReceiveRequestDialog Copy &Address &Copy Địa Chỉ - - Address - Địa chỉ - - - Amount - Lượng - - - Label - Nhãn - - - - RecentRequestsTableModel - - Date - Ngày tháng - - - Label - Nhãn - - - Amount - Lượng - - - (no label) - (không nhãn) - SendCoinsDialog @@ -591,14 +404,6 @@ Change: Thay đổi: - - Copy amount - Lượng copy - - - (no label) - (không nhãn) - SendCoinsEntry @@ -615,104 +420,26 @@ SplashScreen - - Bitcoin Core - Bitcoin Core - TrafficGraphWidget - - TransactionDesc - - Date - Ngày tháng - - - Amount - Lượng - - TransactionDescDialog - - TransactionTableModel - - Date - Ngày tháng - - - Label - Nhãn - - - - TransactionView - - Copy address - Copy địa chỉ - - - Copy label - Copy nhãn - - - Copy amount - Lượng copy - - - Exporting Failed - Xuất Đã Thất Bại - - - Comma separated file (*.csv) - Comma separated file (*.csv) - - - Confirmed - Đã xác nhận - - - Date - Ngày tháng - - - Label - Nhãn - - - Address - Địa chỉ - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - - WalletView - - &Export - X&uất - - - Export the data in the current tab to a file - Xuất dữ liệu trong mục hiện tại ra file - - bitcoin-core Options: Lựa chọn: + + Bitcoin Core + Bitcoin Core + (default: %u) (mặc định: %u) @@ -729,10 +456,6 @@ Warning Chú ý - - This help message - Thông điệp trợ giúp này - Loading addresses... Đang đọc các địa chỉ... diff --git a/src/qt/locale/bitcoin_zh.ts b/src/qt/locale/bitcoin_zh.ts index aeb4faa712283..bceba9dfdd86d 100644 --- a/src/qt/locale/bitcoin_zh.ts +++ b/src/qt/locale/bitcoin_zh.ts @@ -2,9 +2,6 @@ AddressBookPage - - AddressTableModel - AskPassphraseDialog @@ -22,9 +19,6 @@ 警告 - - ClientModel - CoinControlDialog @@ -57,18 +51,12 @@ OverviewPage - - PaymentServer - PeerTableModel QObject - - QRImageWidget - RPCConsole @@ -78,13 +66,6 @@ ReceiveRequestDialog - - RecentRequestsTableModel - - Date - 日期 - - SendCoinsDialog @@ -95,18 +76,6 @@ Choose... 选择... - - Pay only the required fee of %1 - 仅支付全额的%1 - - - The recipient address is not valid. Please recheck. - 收款人地址无效,请再次确认。 - - - Warning: Invalid Bitcoin address - 警告:比特币地址无效 - SendCoinsEntry @@ -123,42 +92,12 @@ TrafficGraphWidget - - TransactionDesc - - Date - 日期 - - TransactionDescDialog - - TransactionTableModel - - Date - 日期 - - - - TransactionView - - Date - 日期 - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - - WalletView - bitcoin-core @@ -177,26 +116,10 @@ Warning 警告 - - wallet.dat corrupt, salvage failed - wallet.dat文件受损,修复失败 - - - This help message - 此条帮助信息 - Loading addresses... 正在载入地址... - - Error loading wallet.dat: Wallet corrupted - wallet.dat文件加载错误:钱包受损 - - - Error loading wallet.dat - wallet.dat文件加载错误 - Insufficient funds 余额不足 diff --git a/src/qt/locale/bitcoin_zh_CN.ts b/src/qt/locale/bitcoin_zh_CN.ts index cc1b03356480e..8f467b79c1cc5 100644 --- a/src/qt/locale/bitcoin_zh_CN.ts +++ b/src/qt/locale/bitcoin_zh_CN.ts @@ -25,10 +25,6 @@ C&lose 关闭(&l) - - &Copy Address - 复制地址(&C) - Delete the currently selected address from the list 从列表中删除选中的地址 @@ -45,73 +41,6 @@ &Delete 删除(&D) - - Choose the address to send coins to - 选择发币地址 - - - Choose the address to receive coins with - 选择收币地址 - - - C&hoose - 选择(&H) - - - Sending addresses - 正在发送地址 - - - Receiving addresses - 正在接收地址 - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - 这是您用来付款的比特币地址。在付款前,请仔细核实付款金额和收款地址。 - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - 这些都是您的比特币地址,可用于收款。建议对每笔交易都使用一个新的地址。 - - - Copy &Label - 复制标签(&L) - - - &Edit - 编辑(&E) - - - Export Address List - 导出地址列表 - - - Comma separated file (*.csv) - 逗号分隔文件 (*.csv) - - - Exporting Failed - 导出失败 - - - There was an error trying to save the address list to %1. Please try again. - 保存地址列表出现 %1错误。请重试。 - - - - AddressTableModel - - Label - 标签 - - - Address - 地址 - - - (no label) - (没有标签) - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase 重复新密码 - - Encrypt wallet - 加密钱包 - - - This operation needs your wallet passphrase to unlock the wallet. - 此操作需要您首先使用密码解锁该钱包。 - - - Unlock wallet - 解锁钱包 - - - This operation needs your wallet passphrase to decrypt the wallet. - 该操作需要您首先使用密码解密钱包。 - - - Decrypt wallet - 解密钱包 - - - Change passphrase - 更改密码 - - - Confirm wallet encryption - 确认加密钱包 - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - 警告:如果您加密了您的钱包,但是忘记了密码,你将会<b>丢失所有的比特币</b>! - - - Are you sure you wish to encrypt your wallet? - 您确定需要为钱包加密吗? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - 比特币核心现在将关闭以完成加密过程。请记住,在您的计算机被恶意软件感染的情况下,加密不能完全保护您的比特币免于被盗。 - - - 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. - 重要提示:您以前备份的钱包文件应该替换成最新生成的加密钱包文件(重新备份)。从安全性上考虑,您以前备份的未加密的钱包文件,在您使用新的加密钱包后将无效,请重新备份。 - - - Warning: The Caps Lock key is on! - 警告:大写锁定键处于打开状态! - - - Wallet encrypted - 钱包已加密 - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - 请输入新的钱包密码. <br/>密码须包含<b>10个以上随机字符</b>,或<b>8个以上单词</b>. - - - Enter the old passphrase and new passphrase to the wallet. - 请输入钱包的旧密码与新密码。 - - - Wallet encryption failed - 钱包加密失败 - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - 由于一个本地错误,加密钱包的操作已经失败。您的钱包没能被加密。 - - - The supplied passphrases do not match. - 密码不匹配。 - - - Wallet unlock failed - 钱包解锁失败 - - - The passphrase entered for the wallet decryption was incorrect. - 用于解密钱包的密码不正确。 - - - Wallet decryption failed - 钱包解密失败。 - - - Wallet passphrase was successfully changed. - 修改钱包密码成功。 - BanTableModel @@ -269,6 +110,10 @@ Quit application 退出程序 + + &About %1 + &关于 %1 + About &Qt 关于Qt(&Q) @@ -305,14 +150,6 @@ Open &URI... 打开 &URI... - - Bitcoin Core client - 比特币核心钱包客户端 - - - Importing blocks from disk... - 正在从磁盘导入数据块... - Reindexing blocks on disk... 正在为数据块重建索引... @@ -357,10 +194,6 @@ &Receive 接收(&R) - - Show information about Bitcoin Core - 显示有关比特币核心钱包信息 - &Show / Hide 显示 / 隐藏(&S) @@ -397,22 +230,10 @@ Tabs toolbar 分页工具栏 - - Bitcoin Core - 比特币核心 - Request payments (generates QR codes and bitcoin: URIs) 请求支付(生成二维码和 bitcoin: URI) - - &About Bitcoin Core - 关于比特币核心(&A) - - - Modify configuration options for Bitcoin Core - 修改比特币核心的配置选项 - Show the list of used sending addresses and labels 显示用过的发送地址和标签的列表 @@ -429,10 +250,6 @@ &Command-line options 命令行选项(&C) - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - 显示比特币核心 程序帮助信息,获取可用的命令行选项 - %n active connection(s) to Bitcoin network %n 个到比特币网络的活动连接 @@ -544,13 +361,6 @@ 钱包已被<b>加密</b>,当前为<b>锁定</b>状态 - - ClientModel - - Network Alert - 网络警报 - - CoinControlDialog @@ -629,150 +439,6 @@ Priority 优先级 - - Copy address - 复制地址 - - - Copy label - 复制标签 - - - Copy amount - 复制金额 - - - Copy transaction ID - 复制交易编号 - - - Lock unspent - 锁定未花费 - - - Unlock unspent - 解锁未花费 - - - Copy quantity - 复制金额 - - - Copy fee - 复制交易费 - - - Copy after fee - 复制含交易费的金额 - - - Copy bytes - 复制字节 - - - Copy priority - 复制优先级 - - - Copy dust - 复制小额 - - - Copy change - 复制零钱 - - - highest - 最高 - - - higher - 更高 - - - high - - - - medium-high - 中高 - - - medium - 中等 - - - low-medium - 中低 - - - low - - - - lower - 更低 - - - lowest - 最低 - - - (%1 locked) - (%1 锁定) - - - none - - - - This label turns red if the transaction size is greater than 1000 bytes. - 如果交易规模大于 1000 字节,此标签将变为红色。 - - - This label turns red if the priority is smaller than "medium". - 如果优先级小于“中等”,此标签将变为红色。 - - - This label turns red if any recipient receives an amount smaller than %1. - 如果任何接收人收到的金额小于 %1,此标签将变为红色。 - - - Can vary +/- %1 satoshi(s) per input. - 可能会有 正负 %1 聪(satoshi)的偏差 - - - yes - - - - no - - - - This means a fee of at least %1 per kB is required. - 这意味着将对交易收取 %1/千字节 的交易费。 - - - Can vary +/- 1 byte per input. - 每笔输入可能会有 正负1字节的偏差。 - - - Transactions with higher priority are more likely to get included into a block. - 交易的优先级越高,被矿工收入数据块的速度也越快。 - - - (no label) - (没有标签) - - - change from %1 (%2) - 来自%1的零钱 (%2) - - - (change) - (零钱) - EditAddressDialog @@ -796,38 +462,6 @@ &Address 地址(&A) - - New receiving address - 新建接收地址 - - - New sending address - 新建发送地址 - - - Edit receiving address - 编辑接收地址 - - - Edit sending address - 编辑发送地址 - - - The entered address "%1" is already in the address book. - 输入的地址“%1”已经存在于地址簿中。 - - - The entered address "%1" is not a valid Bitcoin address. - 您输入的“%1”不是有效的比特币地址。 - - - Could not unlock wallet. - 无法解锁钱包 - - - New key generation failed. - 新的密钥生成失败。 - FreespaceChecker @@ -854,10 +488,6 @@ HelpMessageDialog - - Bitcoin Core - 比特币核心 - version 版本 @@ -866,10 +496,6 @@ (%1-bit) (%1 位) - - About Bitcoin Core - 关于比特币核心 - Command-line options 命令行选项 @@ -906,29 +532,13 @@ Show splash screen on startup (default: %u) 显示启动画面(默认:%u) - - Reset all settings changes made over the GUI - 重置所有图形界面所做的更改 - - + Intro Welcome 欢迎 - - Welcome to Bitcoin Core. - 欢迎使用 比特币核心 程序。 - - - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - 由于这是第一次运行 比特币核心 程序,您可以选择数据存储目录。 - - - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - 比特币核心 程序会下载储存一份数据块链(blockchain)。至少需要 %1 GB的存储空间,随着时间推移会需要更多的存储空间。钱包文件也储存在该目录。 - Use the default data directory 使用默认的数据目录 @@ -937,10 +547,6 @@ Use a custom data directory: 使用自定义的数据目录: - - Bitcoin Core - 比特币核心 - Error: Specified data directory "%1" cannot be created. 错误:无法创建 指定的数据目录 "%1" @@ -976,10 +582,6 @@ Select payment request file 选择付款请求文件 - - Select payment request file to open - 选择需要打开的付款请求文件 - OptionsDialog @@ -1019,10 +621,6 @@ 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. 窗口被关闭时最小化而不是退出应用程序。当此选项启用时,应用程序只会在菜单中选择退出时退出。 - - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - 可以在这里设置用户界面语言。此设置将在重新启动比特币核心后生效。 - 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 |. 出现在交易的选项卡的上下文菜单项的第三方网址 (例如:区块链接查询) 。 %s的URL被替换为交易哈希。多个的URL需要竖线 | 分隔。 @@ -1047,14 +645,6 @@ &Network 网络(&N) - - Automatically start Bitcoin Core after logging in to the system. - 登录到系统后自动启动比特币核心。 - - - &Start Bitcoin Core on system login - 系统登录时启动比特币核心(&S) - (0 = auto, <0 = leave that many cores free) (0 = 自动, <0 = 离开很多免费的核心) @@ -1284,178 +874,68 @@ - PaymentServer + PeerTableModel - URI handling - URI 处理 + User Agent + 用户代理 - Invalid payment address %1 - 无效的付款地址 %1 + Node/Service + 节点/服务 - Payment request rejected - 支付请求被拒绝 + Ping Time + Ping 时间 + + + QObject - Payment request network doesn't match client network. - 付款请求所在的网络与当前客户端所在的网络不匹配。 + Amount + 金额 - Payment request is not initialized. - 支付请求未成形。 + Enter a Bitcoin address (e.g. %1) + 请输入一个比特币地址 (例如 %1) - Requested payment amount of %1 is too small (considered dust). - 请求支付的金额 %1 太小(就像尘埃)。 + %1 d + %1 天 - Payment request error - 支付请求出错 + %1 h + %1 小时 - Cannot start bitcoin: click-to-pay handler - 暂时无法启动比特币:点击支付功能 + %1 m + %1 分钟 - Payment request fetch URL is invalid: %1 - 付款请求URI链接非法: %1 + %1 s + %1 秒 - URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - URI无法解析!原因可能是比特币地址不正确,或者URI参数错误。 + None + - Payment request file handling - 付款请求文件处理 + N/A + 不可用 - Payment request file cannot be read! This can be caused by an invalid payment request file. - 付款请求文件无法读取!可能是付款请求文件不合格。 + %1 ms + %1 毫秒 + + + RPCConsole - Payment request expired. - 支付请求已过期。 + Client name + 客户端名称 - Unverified payment requests to custom payment scripts are unsupported. - 不支持到自定义付款脚本的未验证付款请求。 - - - Invalid payment request. - 无效的支付请求。 - - - Refund from %1 - 退款来自 %1 - - - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - 支付请求 %1 太大 (%2 字节。只允许 %3 字节)。 - - - Error communicating with %1: %2 - %1: %2 通讯出错 - - - Payment request cannot be parsed! - 无法解析 付款请求! - - - Bad response from server %1 - 来自 %1 服务器的错误响应 - - - Payment acknowledged - 支付已到账 - - - Network request error - 网络请求出错 - - - - PeerTableModel - - User Agent - 用户代理 - - - Node/Service - 节点/服务 - - - Ping Time - Ping 时间 - - - - QObject - - Amount - 金额 - - - Enter a Bitcoin address (e.g. %1) - 请输入一个比特币地址 (例如 %1) - - - %1 d - %1 天 - - - %1 h - %1 小时 - - - %1 m - %1 分钟 - - - %1 s - %1 秒 - - - None - - - - N/A - 不可用 - - - %1 ms - %1 毫秒 - - - - QRImageWidget - - &Save Image... - 保存图片(&S)... - - - &Copy Image - 复制图片(&C) - - - Save QR Code - 保存二维码 - - - PNG Image (*.png) - PNG图片(*.png) - - - - RPCConsole - - Client name - 客户端名称 - - - N/A - 不可用 + N/A + 不可用 Client version @@ -1513,10 +993,6 @@ Memory usage 内存使用 - - Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. - 从当前的数据目录打开比特币核心调试日志文件。对于较大的日志文件,这可能需要几秒钟。 - Received 收到 @@ -1629,10 +1105,6 @@ Out: 输出: - - Build date - 创建时间 - Debug log file 调试日志文件 @@ -1669,10 +1141,6 @@ &Unban Node (&U)允许节点连接 - - Welcome to the Bitcoin Core RPC console. - 欢迎使用 比特币核心 RPC 控制台。 - Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. 使用上下方向键浏览历史, <b>Ctrl-L</b>清除屏幕。 @@ -1800,18 +1268,6 @@ Remove 移除 - - Copy label - 复制标签 - - - Copy message - 复制消息 - - - Copy amount - 复制金额 - ReceiveRequestDialog @@ -1831,73 +1287,6 @@ &Save Image... 保存图片(&S)... - - Request payment to %1 - 请求付款到 %1 - - - Payment information - 付款信息 - - - URI - URI - - - Address - 地址 - - - Amount - 金额 - - - Label - 标签 - - - Message - 消息 - - - Resulting URI too long, try to reduce the text for label / message. - URI 太长,请试着精简标签或消息文本。 - - - Error encoding URI into QR Code. - 将 URI 转为二维码失败。 - - - - RecentRequestsTableModel - - Date - 日期 - - - Label - 标签 - - - Message - 消息 - - - Amount - 金额 - - - (no label) - (没有标签) - - - (no message) - (无消息) - - - (no amount) - (无金额) - SendCoinsDialog @@ -1966,935 +1355,289 @@ 选择... - collapse fee-settings - 收起 费用设置 - - - per kilobyte - 每kb - - - If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte. - 如果自定义交易费设置为 1000聪而交易大小只有250字节,则“每千字节" 模式只支付250聪交易费, 而"最少"模式则支付1000聪。 大于1000字节的交易按每千字节付费。 - - - Hide - 隐藏 - - - total at least - 最小额 - - - Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process. - 交易量小时只支付最小交易费是可以的。但是请注意,当交易量大到超出网络可处理时您的交易可能永远无法确认。 - - - (read the tooltip) - (请注意提示信息) - - - Recommended: - 推荐: - - - Custom: - 自定义: - - - (Smart fee not initialized yet. This usually takes a few blocks...) - (智能交易费用 尚未初始化。 需要再下载一些数据块...) - - - Confirmation time: - 确认时间: - - - normal - 一般 - - - fast - 快速 - - - Send as zero-fee transaction if possible - 发送时尽可能 不支付交易费用 - - - (confirmation may take longer) - (确认时间更长) - - - Send to multiple recipients at once - 一次发送给多个接收者 - - - Add &Recipient - 添加收款人(&R) - - - Clear all fields of the form. - 清除此表单的所有字段。 - - - Dust: - 小额: - - - Clear &All - 清除所有(&A) - - - Balance: - 余额: - - - Confirm the send action - 确认发送货币 - - - S&end - 发送(&E) - - - Confirm send coins - 确认发送货币 - - - %1 to %2 - %1 到 %2 - - - Copy quantity - 复制金额 - - - Copy amount - 复制金额 - - - Copy fee - 复制交易费 - - - Copy after fee - 复制含交易费的金额 - - - Copy bytes - 复制字节 - - - Copy priority - 复制优先级 - - - Copy change - 复制零钱 - - - Total Amount %1 - 总金额 %1 - - - or - - - - The amount to pay must be larger than 0. - 支付金额必须大于0。 - - - The amount exceeds your balance. - 金额超出您的账上余额。 - - - The total exceeds your balance when the %1 transaction fee is included. - 计入 %1 交易费后的金额超出您的账上余额。 - - - Transaction creation failed! - 交易创建失败! - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - 错误:该交易被拒绝!发生这种错误的原因可能是:钱包中的比特币已经被用掉,有可能您复制了wallet.dat钱包文件,然后用复制的钱包文件支付了比特币,但是这个钱包文件中没有记录。 - - - A fee higher than %1 is considered an absurdly high fee. - 超过 %1 的交易费被认为是荒谬的高费率。 - - - Payment request expired. - 支付请求已过期。 - - - Pay only the required fee of %1 - 只支付必要费用 %1 - - - Estimated to begin confirmation within %n block(s). - 预计 %n 个数据块后被确认。 - - - The recipient address is not valid. Please recheck. - 接收人地址无效。请重新检查。 - - - Duplicate address found: addresses should only be used once each. - 发现重复地址:每个地址应该只使用一次。 - - - Warning: Invalid Bitcoin address - 警告:无效的比特币地址 - - - (no label) - (没有标签) - - - Warning: Unknown change address - 警告:未知的更改地址 - - - Copy dust - 复制小额 - - - Are you sure you want to send? - 您确定要发出吗? - - - added as transaction fee - 已添加交易费 - - - - SendCoinsEntry - - A&mount: - 金额(&M) - - - Pay &To: - 付给(&T): - - - Enter a label for this address to add it to your address book - 为这个地址输入一个标签,以便将它添加到您的地址簿 - - - &Label: - 标签(&L): - - - Choose previously used address - 选择以前用过的地址 - - - This is a normal payment. - 这是笔正常的支付。 - - - The Bitcoin address to send the payment to - 付款目的地址 - - - Alt+A - Alt+A - - - Paste address from clipboard - 从剪贴板粘贴地址 - - - Alt+P - Alt+P - - - Remove this entry - 移除此项 - - - 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. - 交易费将从发送总额中扣除。接收人将收到比您在金额框中输入的更少的比特币。如果选中了多个收件人,交易费平分。 - - - S&ubtract fee from amount - 从金额中减去交易费(&U) - - - Message: - 消息: - - - This is an unauthenticated payment request. - 这是一个未经验证的支付请求。 - - - This is an authenticated payment request. - 这是一个已经验证的支付请求。 - - - Enter a label for this address to add it to the list of used addresses - 请为此地址输入一个标签以将它加入用过的地址列表 - - - 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. - bitcoin:URI 附带的备注信息,将会和交易一起存储,备查。 注意:该消息不会通过比特币网络传输。 - - - Pay To: - 支付给: - - - Memo: - 便条: - - - - ShutdownWindow - - Bitcoin Core is shutting down... - 比特币核心正在关机... - - - Do not shut down the computer until this window disappears. - 在此窗口消失前不要关闭计算机。 - - - - SignVerifyMessageDialog - - Signatures - Sign / Verify a Message - 签名 - 为消息签名/验证签名消息 - - - &Sign Message - 签名消息(&S) - - - 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. - 您可以用你的地址对消息/协议进行签名,以证明您可以接收发送到该地址的比特币。注意不要对任何模棱两可或者随机的消息进行签名,以免遭受钓鱼式攻击。请确保消息内容准确的表达了您的真实意愿。 - - - The Bitcoin address to sign the message with - 用来对消息签名的地址 - - - Choose previously used address - 选择以前用过的地址 - - - Alt+A - Alt+A - - - Paste address from clipboard - 从剪贴板粘贴地址 - - - Alt+P - Alt+P - - - Enter the message you want to sign here - 请输入您要发送的签名消息 - - - Signature - 签名 - - - Copy the current signature to the system clipboard - 复制当前签名至剪切板 - - - Sign the message to prove you own this Bitcoin address - 签名消息,证明这个地址属于您。 - - - Sign &Message - 消息签名(&M) - - - Reset all sign message fields - 清空所有签名消息栏 - - - Clear &All - 清除所有(&A) - - - &Verify Message - 验证消息(&V) - - - 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! - 请在下面输入接收者地址、消息(确保换行符、空格符、制表符等完全相同)和签名以验证消息。请仔细核对签名信息,以提防中间人攻击。请注意,这只是证明接收方签名的地址,它不能证明任何交易! - - - The Bitcoin address the message was signed with - 消息使用的签名地址 - - - Verify the message to ensure it was signed with the specified Bitcoin address - 验证消息,确保消息是由指定的比特币地址签名过的。 - - - Verify &Message - 验证消息签名(&M) - - - Reset all verify message fields - 清空所有验证消息栏 - - - Click "Sign Message" to generate signature - 单击“签名消息“产生签名。 - - - The entered address is invalid. - 输入的地址非法。 - - - Please check the address and try again. - 请检查地址后重试。 - - - The entered address does not refer to a key. - 输入的地址没有关联的公私钥对。 - - - Wallet unlock was cancelled. - 钱包解锁动作取消。 - - - Private key for the entered address is not available. - 找不到输入地址关联的私钥。 - - - Message signing failed. - 消息签名失败。 - - - Message signed. - 消息已签名。 - - - The signature could not be decoded. - 签名无法解码。 - - - Please check the signature and try again. - 请检查签名后重试。 - - - The signature did not match the message digest. - 签名与消息摘要不匹配。 - - - Message verification failed. - 消息验证失败。 - - - Message verified. - 消息验证成功。 - - - - SplashScreen - - Bitcoin Core - 比特币核心 - - - The Bitcoin Core developers - Bitcoin Core 的开发者 - - - [testnet] - [测试网络] - - - - TrafficGraphWidget - - KB/s - KB/s - - - - TransactionDesc - - Open until %1 - 至 %1 个数据块时开启 - - - conflicted - 发现冲突 - - - %1/offline - %1 / 离线 - - - %1/unconfirmed - %1/未确认 - - - %1 confirmations - %1 已确认 - - - Status - 状态 - - - , broadcast through %n node(s) - , 通过 %n 个节点广播 - - - Date - 日期 - - - Source - - - - Generated - 生成 - - - From - 来自 - - - To - - - - own address - 自己的地址 - - - watch-only - 观察地址(watch-only) - - - label - 标签 - - - Credit - 收入 - - - matures in %n more block(s) - %n 个数据块后成熟(mature) - - - not accepted - 未被接受 - - - Debit - 支出 - - - Total debit - 总收入 - - - Total credit - 总支出 - - - Transaction fee - 交易费 - - - Net amount - 净额 - - - Message - 消息 - - - Comment - 备注 - - - Transaction ID - ID - - - Merchant - 商店 - - - 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. - 生成的比特币在可以使用前必须有 %1 个成熟的区块。当您生成了此区块后,它将被广播到网络中以加入区块链。如果它未成功进入区块链,其状态将变更为“不接受”并且不可使用。这可能偶尔会发生,如果另一个节点比你早几秒钟成功生成一个区块。 - - - Debug information - 调试信息 - - - Transaction - 交易 - - - Inputs - 输入 - - - Amount - 金额 - - - true - 正确 - - - false - 错误 - - - , has not been successfully broadcast yet - ,未被成功广播 - - - Open for %n more block(s) - 再打开 %n 个数据块 - - - unknown - 未知 - - - - TransactionDescDialog - - Transaction details - 交易细节 - - - This pane shows a detailed description of the transaction - 当前面板显示了交易的详细信息 + collapse fee-settings + 收起 费用设置 - - - TransactionTableModel - Date - 日期 + per kilobyte + 每kb - Type - 类别 + If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte. + 如果自定义交易费设置为 1000聪而交易大小只有250字节,则“每千字节" 模式只支付250聪交易费, 而"最少"模式则支付1000聪。 大于1000字节的交易按每千字节付费。 - Immature (%1 confirmations, will be available after %2) - 未成熟 (%1 个确认,将在 %2 个后可用) - - - Open for %n more block(s) - 再打开 %n 个数据块 + Hide + 隐藏 - Open until %1 - 至 %1 个数据块时开启 + total at least + 最小额 - Confirmed (%1 confirmations) - 已确认 (%1 条确认信息) + Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process. + 交易量小时只支付最小交易费是可以的。但是请注意,当交易量大到超出网络可处理时您的交易可能永远无法确认。 - This block was not received by any other nodes and will probably not be accepted! - 此数据块未被任何其他节点接收,可能不被接受! + (read the tooltip) + (请注意提示信息) - Generated but not accepted - 已生成但未被接受 + Recommended: + 推荐: - Offline - 掉线 + Custom: + 自定义: - Label - 标签 + (Smart fee not initialized yet. This usually takes a few blocks...) + (智能交易费用 尚未初始化。 需要再下载一些数据块...) - Unconfirmed - 未确认的 + Confirmation time: + 确认时间: - Confirming (%1 of %2 recommended confirmations) - 确认中 (推荐 %2个确认,已经有 %1个确认) + normal + 一般 - Conflicted - 冲突的 + fast + 快速 - Received with - 接收于 + Send to multiple recipients at once + 一次发送给多个接收者 - Received from - 收款来自 + Add &Recipient + 添加收款人(&R) - Sent to - 发送给 + Clear all fields of the form. + 清除此表单的所有字段。 - Payment to yourself - 付款给自己 + Dust: + 小额: - Mined - 挖矿所得 + Clear &All + 清除所有(&A) - watch-only - 观察地址(watch-only) + Balance: + 余额: - (n/a) - (不可用) + Confirm the send action + 确认发送货币 - Transaction status. Hover over this field to show number of confirmations. - 交易状态。 鼠标移到此区域可显示确认项数量。 + S&end + 发送(&E) + + + SendCoinsEntry - Date and time that the transaction was received. - 接收到交易的时间 + A&mount: + 金额(&M) - Type of transaction. - 交易类别。 + Pay &To: + 付给(&T): - Whether or not a watch-only address is involved in this transaction. - 该交易中是否涉及 观察地址(watch-only address)。 + &Label: + 标签(&L): - User-defined intent/purpose of the transaction. - 用户定义的该交易的意图/目的。 + Choose previously used address + 选择以前用过的地址 - Amount removed from or added to balance. - 从余额添加或移除的金额。 + This is a normal payment. + 这是笔正常的支付。 - - - TransactionView - All - 全部 + The Bitcoin address to send the payment to + 付款目的地址 - Today - 今天 + Alt+A + Alt+A - This week - 本周 + Paste address from clipboard + 从剪贴板粘贴地址 - This month - 本月 + Alt+P + Alt+P - Last month - 上月 + Remove this entry + 移除此项 - This year - 今年 + 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. + 交易费将从发送总额中扣除。接收人将收到比您在金额框中输入的更少的比特币。如果选中了多个收件人,交易费平分。 - Range... - 范围... + S&ubtract fee from amount + 从金额中减去交易费(&U) - Received with - 接收于 + Message: + 消息: - Sent to - 发送给 + This is an unauthenticated payment request. + 这是一个未经验证的支付请求。 - To yourself - 到自己 + This is an authenticated payment request. + 这是一个已经验证的支付请求。 - Mined - 挖矿所得 + Enter a label for this address to add it to the list of used addresses + 请为此地址输入一个标签以将它加入用过的地址列表 - Other - 其他 + 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. + bitcoin:URI 附带的备注信息,将会和交易一起存储,备查。 注意:该消息不会通过比特币网络传输。 - Enter address or label to search - 输入地址或标签进行搜索 + Pay To: + 支付给: - Min amount - 最小金额 + Memo: + 便条: + + + ShutdownWindow - Copy address - 复制地址 + Do not shut down the computer until this window disappears. + 在此窗口消失前不要关闭计算机。 + + + SignVerifyMessageDialog - Copy label - 复制标签 + Signatures - Sign / Verify a Message + 签名 - 为消息签名/验证签名消息 - Copy amount - 复制金额 + &Sign Message + 签名消息(&S) - Copy transaction ID - 复制交易编号 + 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. + 您可以用你的地址对消息/协议进行签名,以证明您可以接收发送到该地址的比特币。注意不要对任何模棱两可或者随机的消息进行签名,以免遭受钓鱼式攻击。请确保消息内容准确的表达了您的真实意愿。 - Copy raw transaction - 复制原始交易 + The Bitcoin address to sign the message with + 用来对消息签名的地址 - Edit label - 编辑标签 + Choose previously used address + 选择以前用过的地址 - Show transaction details - 显示交易详情 + Alt+A + Alt+A - Export Transaction History - 导出交易历史 + Paste address from clipboard + 从剪贴板粘贴地址 - Watch-only - 观察地址(Watch-only) + Alt+P + Alt+P - Exporting Failed - 导出失败 + Enter the message you want to sign here + 请输入您要发送的签名消息 - There was an error trying to save the transaction history to %1. - 导出交易历史到 %1 时发生错误。 + Signature + 签名 - Exporting Successful - 导出成功 + Copy the current signature to the system clipboard + 复制当前签名至剪切板 - The transaction history was successfully saved to %1. - 交易历史已成功保存到 %1。 + Sign the message to prove you own this Bitcoin address + 签名消息,证明这个地址属于您。 - Comma separated file (*.csv) - 逗号分隔文件 (*.csv) + Sign &Message + 消息签名(&M) - Confirmed - 已确认 + Reset all sign message fields + 清空所有签名消息栏 - Date - 日期 + Clear &All + 清除所有(&A) - Type - 类别 + &Verify Message + 验证消息(&V) - Label - 标签 + 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! + 请在下面输入接收者地址、消息(确保换行符、空格符、制表符等完全相同)和签名以验证消息。请仔细核对签名信息,以提防中间人攻击。请注意,这只是证明接收方签名的地址,它不能证明任何交易! - Address - 地址 + The Bitcoin address the message was signed with + 消息使用的签名地址 - ID - ID + Verify the message to ensure it was signed with the specified Bitcoin address + 验证消息,确保消息是由指定的比特币地址签名过的。 - Range: - 范围: + Verify &Message + 验证消息签名(&M) - to - + Reset all verify message fields + 清空所有验证消息栏 - UnitDisplayStatusBarControl + SplashScreen - Unit to show amounts in. Click to select another unit. - 金额单位。单击选择别的单位。 + [testnet] + [测试网络] - WalletFrame + TrafficGraphWidget - No wallet has been loaded. - 没有载入钱包。 + KB/s + KB/s - WalletModel + TransactionDescDialog - Send Coins - 发送比特币 + This pane shows a detailed description of the transaction + 当前面板显示了交易的详细信息 - WalletView - - &Export - 导出(&E) - - - Export the data in the current tab to a file - 导出当前数据到文件 - - - Backup Wallet - 备份钱包 - - - Wallet Data (*.dat) - 钱包文件(*.dat) - - - Backup Failed - 备份失败 - - - There was an error trying to save the wallet data to %1. - 尝试保存钱包数据至 %1 时发生错误。 - - - The wallet data was successfully saved to %1. - 钱包数据成功保存至 %1 。 - + UnitDisplayStatusBarControl - Backup Successful - 备份成功 + Unit to show amounts in. Click to select another unit. + 金额单位。单击选择别的单位。 @@ -2926,14 +1669,6 @@ If <category> is not supplied or if <category> = 1, output all debugging information. 如果<category>未提供或<category> = 1,输出所有调试信息。 - - Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s) - 最大单次转账费用(%s),设置太低可能导致大宗交易失败(默认:%s) - - - Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. - 警请检查电脑的日期时间设置是否正确!时间错误可能会导致比特币客户端运行异常。 - Prune configured below the minimum of %d MiB. Please use a higher number. 修剪值被设置为低于最小值%d MiB,请使用更大的数值。 @@ -2976,6 +1711,10 @@ Accept connections from outside (default: 1 if no -proxy or -connect) 接受来自外部的连接 (缺省: 如果不带 -proxy or -connect 参数设置为1) + + Bitcoin Core + 比特币核心 + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. -fallbackfree 交易费设置得很高!这是在费用估计不可用时你可能会支付的交易费。 @@ -3020,14 +1759,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications 这是测试用的预发布版本 - 请谨慎使用 - 不要用来挖矿,或者在正式商用环境下使用 - - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - 无法 %s的绑定到电脑上,比特币核心钱包可能已经在运行。 - - - Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. - 一个不被支持的参数 -whitelistalwaysrelay 被忽略了。请使用 -whitelistrelay 或者 -whitelistforcerelay. - Use UPnP to map the listening port (default: 1 when listening and no -proxy) 使用UPnP暴露本机监听端口(默认:1 当正在监听且不使用代理) @@ -3044,18 +1775,10 @@ Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. 警告:网络似乎并不完全同意!有些矿工似乎遇到了问题。 - - Warning: Unknown block versions being mined! It's possible unknown rules are in effect - 警告: 未知的区块版本被挖掘!未知规则可能已生效 - Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. 警告:我们的同行似乎不完全同意!您可能需要升级,或者其他节点可能需要升级。 - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - 警告:钱包文件wallet.dat损坏! 原始的钱包文件已经备份到%s目录下并重命名为{timestamp}.bak 。如果您的账户余额或者交易记录不正确,请使用您的钱包备份文件恢复。 - Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. 节点白名单,网络掩码或IP址。可多次指定。 @@ -3240,10 +1963,6 @@ Wallet options: 钱包选项: - - You need to rebuild the database using -reindex to change -txindex - 您需要将 -reindex 改为 -txindex 以重建数据库 - 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 允许来自指定地址的 JSON-RPC 连接。 <ip>为单一IP (如: 1.2.3.4), 网络/掩码 (如: 1.2.3.4/255.255.255.0), 网络/CIDR (如: 1.2.3.4/24)。该选项可多次指定。 @@ -3256,10 +1975,6 @@ Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces) 绑定到指定地址监听 JSON-RPC连接。 IPv6使用[主机]:端口 格式。该选项可多次指定 (默认: 绑定到所有接口) - - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - 无法获取数据目录的 %s. 比特币核心钱包可能已经在运行. - Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) 创建系统默认权限的文件,而不是 umask 077 (只在关闭钱包功能时有效) @@ -3304,10 +2019,6 @@ Set maximum size of high-priority/low-fee transactions in bytes (default: %d) 设置 高优先级/低交易费 交易的最大字节 (缺省: %d) - - Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) - 设置比特币生成线程数 ( -1=所有核, 默认: %d) - The transaction amount is too small to send after the fee has been deducted 在交易费被扣除后发送的交易金额太小 @@ -3332,34 +2043,14 @@ Accept public REST requests (default: %u) 接受公共 REST 请求 (默认: %u) - - Activating best chain... - 正在激活最佳数据链... - - - Attempt to recover private keys from a corrupt wallet.dat on startup - 尝试从启动页上的损坏钱包文件中恢复私钥 - Automatically create Tor hidden service (default: %d) 自动建立Tor隐藏服务 (默认:%d) - - Cannot resolve -whitebind address: '%s' - 无法解析 -whitebind 地址: '%s' - Connect through SOCKS5 proxy 通过 SOCKS5 代理连接 - - Copyright (C) 2009-%i The Bitcoin Core Developers - 版权所有 (C) 2009-%i Bitcoin Core 开发者 - - - Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - 加载wallet.dat错误:需要新版的比特币核心钱包 - Error reading from database, shutting down. 读取数据库出错,关闭中。 @@ -3368,22 +2059,6 @@ Information 信息 - - Initialization sanity check failed. Bitcoin Core is shutting down. - 初始化完整性检查失败。Bitcoin Core 即将关闭。 - - - Invalid amount for -maxtxfee=<amount>: '%s' - -maxtxfee=<amount>: '%s' 的金额无效 - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - -minrelaytxfee=<amount>: '%s' 无效的金额 - - - Invalid amount for -mintxfee=<amount>: '%s' - -mintxfee=<amount>: '%s' 无效的金额 - Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) 无效的金额 -paytxfee=<amount>: '%s' (必须至少为 %s) @@ -3408,14 +2083,6 @@ RPC server options: RPC 服务器选项: - - Rebuild block chain index from current blk000??.dat files on startup - 启动时重新为当前的 blk000??.dat 文件建立索引 - - - Receive and display P2P network alerts (default: %u) - 收到并且显示P2P网络的告警(默认:%u) - Rescan the block chain for missing wallet transactions on startup 重新扫描区块链以查找遗漏的钱包交易 @@ -3476,10 +2143,6 @@ Username for JSON-RPC connections JSON-RPC 连接用户名 - - Wallet needed to be rewritten: restart Bitcoin Core to complete - 钱包需要被改写:重新启动核心钱包来完成 - Warning 警告 @@ -3496,10 +2159,6 @@ ZeroMQ notification options: ZeroMQ 通知选项: - - wallet.dat corrupt, salvage failed - 钱包文件wallet.dat损坏,抢救备份失败 - Password for JSON-RPC connections JSON-RPC 连接密码 @@ -3509,11 +2168,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) 当最佳数据块变化时执行命令 (命令行中的 %s 会被替换成数据块哈希值) - - This help message - 本帮助信息 - - Allow DNS lookups for -addnode, -seednode and -connect 使用 -addnode, -seednode 和 -connect 选项时允许查询DNS @@ -3522,10 +2176,6 @@ Loading addresses... 正在加载地址簿... - - Error loading wallet.dat: Wallet corrupted - wallet.dat 钱包文件加载出错:钱包损坏 - (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) (1 = 保留 tx meta data , 如 account owner 和 payment request information, 2 = 不保留 tx meta data) @@ -3550,10 +2200,18 @@ Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d) 尝试保持上传带宽低于(MiB/24h),0=无限制(默认:%d) + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + 一个不被支持的参数 -whitelistalwaysrelay 被忽略了。请使用 -whitelistrelay 或者 -whitelistforcerelay. + Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s) 通过Tor隐藏服务连接节点时 使用不同的SOCKS5代理 (默认: %s) + + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + 警告: 未知的区块版本被挖掘!未知规则可能已生效 + (default: %s) (默认: %s) @@ -3562,14 +2220,6 @@ Always query for peer addresses via DNS lookup (default: %u) 始终通过 DNS 查询节点地址 (默认: %u) - - Error loading wallet.dat - wallet.dat 钱包文件加载出错 - - - Generate coins (default: %u) - 生成比特币 (默认: %u) - How many blocks to check at startup (default: %u, 0 = all) 启动时检测多少个数据块(默认: %u, 0=所有) @@ -3654,18 +2304,6 @@ Unknown network specified in -onlynet: '%s' -onlynet 指定的是未知网络:%s - - Cannot resolve -bind address: '%s' - 无法解析 -bind 端口地址: '%s' - - - Cannot resolve -externalip address: '%s' - 无法解析 -externalip 地址: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - 非法金额 -paytxfee=<amount>: '%s' - Insufficient funds 金额不足 diff --git a/src/qt/locale/bitcoin_zh_HK.ts b/src/qt/locale/bitcoin_zh_HK.ts index 740a86e117024..aa014db0bd03e 100644 --- a/src/qt/locale/bitcoin_zh_HK.ts +++ b/src/qt/locale/bitcoin_zh_HK.ts @@ -25,10 +25,6 @@ C&lose 關閉 &l - - &Copy Address - 複製位址 &C - Delete the currently selected address from the list 把目前選擇的位址從列表中刪除 @@ -45,73 +41,6 @@ &Delete 刪除 &D - - Choose the address to send coins to - 選擇要付錢過去的位址 - - - Choose the address to receive coins with - 選擇要收錢的位址 - - - C&hoose - 選取 &h - - - Sending addresses - 付款位址 - - - Receiving addresses - 收款位址 - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - 這些是你要付款過去的 Bitcoin 位址。在付款之前,務必要檢查金額和收款位址是否正確。 - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - 這些是你用來收款的 Bitcoin 位址。建議在每次交易時,都使用一個新的收款位址。 - - - Copy &Label - 複製標記 &L - - - &Edit - 編輯 &E - - - Export Address List - 匯出位址清單 - - - Comma separated file (*.csv) - 逗號分隔檔(*.csv) - - - Exporting Failed - 匯出失敗 - - - There was an error trying to save the address list to %1. Please try again. - 儲存位址列表到 %1 時發生錯誤。請再試一次。 - - - - AddressTableModel - - Label - 標記 - - - Address - 位址 - - - (no label) - (無標記) - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase 重複新密碼 - - Encrypt wallet - 加密錢包 - - - This operation needs your wallet passphrase to unlock the wallet. - 這個動作需要你的錢包密碼來將錢包解鎖。 - - - Unlock wallet - 解鎖錢包 - - - This operation needs your wallet passphrase to decrypt the wallet. - 這個動作需要你的錢包密碼來將錢包解密。 - - - Decrypt wallet - 解密錢包 - - - Change passphrase - 改變密碼 - - - Confirm wallet encryption - 確認錢包加密 - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - 警告: 如果把錢包加密後又忘記密碼,你就會<b>失去所有 Bitcoin 了</b>! - - - Are you sure you wish to encrypt your wallet? - 你確定要把錢包加密嗎? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Bitcoin Core 現在要關閉以完成加密程序。請記得將錢包加密不能完全防止你的 Bitcoin 經被入侵電腦的惡意程式偷取。 - - - 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. - 重要: 請改用新產生的加密錢包檔,來取代所以舊錢包檔的備份。為安全計,當你開始使用新的加密錢包檔後,舊錢包檔的備份就不能再使用了。 - - - Warning: The Caps Lock key is on! - 警告: Caps Lock 已啟用! - - - Wallet encrypted - 錢包已加密 - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - 輸入錢包的新密碼。<br/>密碼請用<b>10 個或以上的隨機字元</b>,或是<b>8 個或以上的字詞</b>。 - - - Enter the old passphrase and new passphrase to the wallet. - 請輸入舊密碼和新密碼至錢包。 - - - Wallet encryption failed - 錢包加密失敗 - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - 因內部錯誤導致錢包加密失敗。你的錢包尚未加密。 - - - The supplied passphrases do not match. - 提供的密碼不一樣。 - - - Wallet unlock failed - 錢包解鎖失敗 - - - The passphrase entered for the wallet decryption was incorrect. - 用來解密錢包的密碼不對。 - - - Wallet decryption failed - 錢包解密失敗 - - - Wallet passphrase was successfully changed. - 錢包密碼已成功更改。 - BanTableModel @@ -305,14 +146,6 @@ Open &URI... 開啓網址... &U - - Bitcoin Core client - Bitcoin Core 客戶端 - - - Importing blocks from disk... - 正在從磁碟匯入區塊資料... - Reindexing blocks on disk... 正在為磁碟區塊重建索引... @@ -357,10 +190,6 @@ &Receive 收款 &R - - Show information about Bitcoin Core - 顯示 Bitcoin Core 的相關資訊 - &Show / Hide 顯示 / 隱藏 &S @@ -370,15 +199,8 @@ 顯示或隱藏主視窗 - - ClientModel - CoinControlDialog - - (no label) - (無標記) - EditAddressDialog @@ -401,18 +223,12 @@ OverviewPage - - PaymentServer - PeerTableModel QObject - - QRImageWidget - RPCConsole @@ -421,32 +237,9 @@ ReceiveRequestDialog - - Address - 位址 - - - Label - 標記 - - - - RecentRequestsTableModel - - Label - 標記 - - - (no label) - (無標記) - SendCoinsDialog - - (no label) - (無標記) - SendCoinsEntry @@ -463,58 +256,12 @@ TrafficGraphWidget - - TransactionDesc - TransactionDescDialog - - TransactionTableModel - - Label - 標記 - - - - TransactionView - - Exporting Failed - 匯出失敗 - - - Comma separated file (*.csv) - 逗號分隔檔(*.csv) - - - Label - 標記 - - - Address - 位址 - - UnitDisplayStatusBarControl - - WalletFrame - - - WalletModel - - - WalletView - - &Export - 匯出 &E - - - Export the data in the current tab to a file - 把目前分頁的資料匯出至檔案 - - bitcoin-core diff --git a/src/qt/locale/bitcoin_zh_TW.ts b/src/qt/locale/bitcoin_zh_TW.ts index 107e7034e5bc9..cbdb8f2c0bacf 100644 --- a/src/qt/locale/bitcoin_zh_TW.ts +++ b/src/qt/locale/bitcoin_zh_TW.ts @@ -25,10 +25,6 @@ C&lose 關閉 - - &Copy Address - 複製位址 - Delete the currently selected address from the list 把目前選擇的位址從列表中刪掉 @@ -45,73 +41,6 @@ &Delete 刪掉 - - Choose the address to send coins to - 選擇要付錢過去的位址 - - - Choose the address to receive coins with - 選擇要收錢進來的位址 - - - C&hoose - 選取 - - - Sending addresses - 付款位址 - - - Receiving addresses - 收款位址 - - - These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - 這些是你要付款過去的 Bitcoin 位址。在付錢之前,務必要檢查金額和收款位址是否正確。 - - - These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - 這些是你用來收款的 Bitcoin 位址。建議在每次交易時,都使用一個新的收款位址。 - - - Copy &Label - 複製標記 - - - &Edit - 編輯 - - - Export Address List - 匯出位址清單 - - - Comma separated file (*.csv) - 逗號分隔資料檔(*.csv) - - - Exporting Failed - 匯出失敗 - - - There was an error trying to save the address list to %1. Please try again. - 儲存位址列表到 %1 時發生錯誤。請重試一次。 - - - - AddressTableModel - - Label - 標記 - - - Address - 位址 - - - (no label) - (無標記) - AskPassphraseDialog @@ -131,94 +60,6 @@ Repeat new passphrase 重複新密碼 - - Encrypt wallet - 加密錢包 - - - This operation needs your wallet passphrase to unlock the wallet. - 這個動作需要你的錢包密碼來解鎖錢包。 - - - Unlock wallet - 解鎖錢包 - - - This operation needs your wallet passphrase to decrypt the wallet. - 這個動作需要你的錢包密碼來把錢包解密。 - - - Decrypt wallet - 解密錢包 - - - Change passphrase - 改變密碼 - - - Confirm wallet encryption - 確認錢包加密 - - - Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - 警告: 如果把錢包加密後又忘記密碼,你就會從此<b>失去其中所有的 Bitcoin 了</b>! - - - Are you sure you wish to encrypt your wallet? - 你確定要把錢包加密嗎? - - - Bitcoin Core will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - Bitcoin Core 現在要關閉,好完成加密程序。請注意,加密錢包不能完全防止入侵你的電腦的惡意程式偷取錢幣。 - - - 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. - 重要: 請改用新產生有加密的錢包檔,來取代舊錢包檔的備份。為了安全性的理由,當你開始使用新的有加密的錢包後,舊錢包檔的備份就不能再使用了。 - - - Warning: The Caps Lock key is on! - 警告: 大寫字母鎖定作用中! - - - Wallet encrypted - 錢包已加密 - - - Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - 輸入錢包的新密碼。<br/>密碼請用<b>10 個以上的字元</b>,或是<b>8 個以上的字詞</b>。 - - - Enter the old passphrase and new passphrase to the wallet. - 請輸入錢包的舊密碼和新密碼。 - - - Wallet encryption failed - 錢包加密失敗 - - - Wallet encryption failed due to an internal error. Your wallet was not encrypted. - 因為內部錯誤導致錢包加密失敗。你的錢包還是沒加密。 - - - The supplied passphrases do not match. - 提供的密碼不一樣。 - - - Wallet unlock failed - 錢包解鎖失敗 - - - The passphrase entered for the wallet decryption was incorrect. - 輸入要用來解密錢包的密碼不對。 - - - Wallet decryption failed - 錢包解密失敗 - - - Wallet passphrase was successfully changed. - 錢包密碼改成功了。 - BanTableModel @@ -269,6 +110,14 @@ Quit application 結束應用程式 + + &About %1 + 關於%1 + + + Show information about %1 + 顯示 %1 的相關資訊 + About &Qt 關於 &Qt @@ -281,6 +130,10 @@ &Options... 選項... + + Modify configuration options for %1 + 修改 %1 的設定選項 + &Encrypt Wallet... 加密錢包... @@ -305,14 +158,6 @@ Open &URI... 開啓 URI... - - Bitcoin Core client - Bitcoin Core 客戶端軟體 - - - Importing blocks from disk... - 正在從磁碟匯入區塊資料... - Reindexing blocks on disk... 正在為磁碟裡的區塊重建索引... @@ -357,10 +202,6 @@ &Receive 收款 - - Show information about Bitcoin Core - 顯示 Bitcoin Core 的相關資訊 - &Show / Hide 顯示或隱藏 @@ -397,22 +238,10 @@ Tabs toolbar 分頁工具列 - - Bitcoin Core - Bitcoin Core - Request payments (generates QR codes and bitcoin: URIs) 要求付款(產生 QR Code 和 bitcoin 付款協議的資源識別碼: URI) - - &About Bitcoin Core - 關於 Bitcoin Core - - - Modify configuration options for Bitcoin Core - 修改 Bitcoin Core 的設定選項 - Show the list of used sending addresses and labels 顯示已使用過的付款位址和標記的清單 @@ -429,14 +258,18 @@ &Command-line options 命令列選項 - - Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - 顯示 Bitcoin Core 的說明訊息,來取得可用命令列選項的列表 - %n active connection(s) to Bitcoin network %n 個運作中的 Bitcoin 網路連線 + + Indexing blocks on disk... + 正在為磁碟裡的區塊建立索引... + + + Processing blocks on disk... + 正在處理磁碟裡的區塊資料... + No block source available... 沒有可用的區塊來源... @@ -493,6 +326,14 @@ Up to date 最新狀態 + + Show the %1 help message to get a list with possible Bitcoin command-line options + 顯示 %1 的說明訊息,來取得可用命令列選項的列表 + + + %1 client + %1 客戶端軟體 + Catching up... 正在趕進度... @@ -544,13 +385,6 @@ 錢包<b>已加密</b>並且<b>上鎖中</b> - - ClientModel - - Network Alert - 網路警報 - - CoinControlDialog @@ -629,150 +463,6 @@ Priority 優先度 - - Copy address - 複製位址 - - - Copy label - 複製標記 - - - Copy amount - 複製金額 - - - Copy transaction ID - 複製交易識別碼 - - - Lock unspent - 鎖定不用 - - - Unlock unspent - 解鎖可用 - - - Copy quantity - 複製數目 - - - Copy fee - 複製手續費 - - - Copy after fee - 複製計費後金額 - - - Copy bytes - 複製位元組數 - - - Copy priority - 複製優先度 - - - Copy dust - 複製零散金額 - - - Copy change - 複製找零金額 - - - highest - 最高 - - - higher - 很高 - - - high - - - - medium-high - 中高 - - - medium - 中等 - - - low-medium - 中低 - - - low - - - - lower - 很低 - - - lowest - 最低 - - - (%1 locked) - (鎖定 %1 枚) - - - none - - - - This label turns red if the transaction size is greater than 1000 bytes. - 當交易大小大於 1000 位元組時,文字會變紅色。 - - - This label turns red if the priority is smaller than "medium". - 當優先度低於「中等」時,文字會變紅色。 - - - This label turns red if any recipient receives an amount smaller than %1. - 當任何一個收款金額小於 %1 時,文字會變紅色。 - - - Can vary +/- %1 satoshi(s) per input. - 每組輸入可能有 +/- %1 個 satoshi 的誤差。 - - - yes - - - - no - - - - This means a fee of at least %1 per kB is required. - 表示每一千位元組(kB)需要至少 %1 的手續費。 - - - Can vary +/- 1 byte per input. - 每組輸入可能會誤差多或少 1 個位元組。 - - - Transactions with higher priority are more likely to get included into a block. - 優先度較高的交易比較有可能被接受放進區塊中。 - - - (no label) - (無標記) - - - change from %1 (%2) - 找零前是 %1 (%2) - - - (change) - (找零) - EditAddressDialog @@ -796,38 +486,6 @@ &Address 位址 - - New receiving address - 造新的收款位址 - - - New sending address - 造新的付款位址 - - - Edit receiving address - 編輯收款位址 - - - Edit sending address - 編輯付款位址 - - - The entered address "%1" is already in the address book. - 輸入的位址 %1 在位址簿中已經有了。 - - - The entered address "%1" is not a valid Bitcoin address. - 輸入的位址 %1 並不是有效的 Bitcoin 位址。 - - - Could not unlock wallet. - 沒辦法把錢包解鎖。 - - - New key generation failed. - 產生新的密鑰失敗了。 - FreespaceChecker @@ -854,10 +512,6 @@ HelpMessageDialog - - Bitcoin Core - Bitcoin Core - version 版本 @@ -867,8 +521,8 @@ (%1 位元) - About Bitcoin Core - 關於 Bitcoin Core + About %1 + 關於 %1 Command-line options @@ -907,7 +561,7 @@ 顯示啓動畫面(預設值: %u) - Reset all settings changes made over the GUI + Reset all settings changed in the GUI 重置所有在使用界面更改的設定 @@ -918,16 +572,16 @@ 歡迎 - Welcome to Bitcoin Core. - 歡迎使用 Bitcoin Core + Welcome to %1. + 歡迎使用 %1。 - As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - 因為這是程式第一次啓動,你可以選擇 Bitcoin Core 儲存資料的地方。 + As this is the first time the program is launched, you can choose where %1 will store its data. + 因為這是程式第一次啓動,你可以選擇 %1 儲存資料的地方。 - Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - Bitcoin Core 會下載並儲存一份 Bitcoin 區塊鏈的拷貝。至少有 %1GB 的資料會儲存到這個目錄中,並且還會持續增長。另外錢包資料也會儲存在這個目錄。 + %1 will download and store a copy of the Bitcoin block chain. At least %2GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. + %1 會下載並儲存一份 Bitcoin 區塊鏈的拷貝。至少有 %2GB 的資料會儲存到這個目錄中,並且還會持續增長。另外錢包資料也會儲存在這個目錄。 Use the default data directory @@ -937,10 +591,6 @@ Use a custom data directory: 使用自訂的資料目錄: - - Bitcoin Core - Bitcoin Core - Error: Specified data directory "%1" cannot be created. 錯誤: 無法新增指定的資料目錄: %1 @@ -976,10 +626,6 @@ Select payment request file 選擇付款要求資料檔 - - Select payment request file to open - 選擇要開啟的付款要求資料檔 - OptionsDialog @@ -991,6 +637,14 @@ &Main 主要 + + Automatically start %1 after logging in to the system. + 在登入系統後自動啓動 %1。 + + + &Start %1 on system login + 系統登入時啟動 %1 + Size of &database cache 資料庫快取大小 @@ -1019,10 +673,6 @@ 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. 當視窗關閉時,把應用程式縮到最小,而不是結束。當勾選這個選項時,只能夠用選單中的結束來關掉應用程式。 - - The user interface language can be set here. This setting will take effect after restarting Bitcoin Core. - 可以在這裡設定使用者介面的語言。這個設定在重啓 Bitcoin Core 後才會生效。 - 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 |. 在交易頁籤的情境選單出現的第三方網址連結(URL),比如說區塊探索網站。網址中的 %s 會被取代為交易的雜湊值。可以用直線符號 | 來分隔多個連結。 @@ -1047,14 +697,6 @@ &Network 網路 - - Automatically start Bitcoin Core after logging in to the system. - 在登入系統後自動啓動 Bitcoin Core。 - - - &Start Bitcoin Core on system login - 系統登入時啟動 Bitcoin Core - (0 = auto, <0 = leave that many cores free) (0 表示程式自動決定,小於 0 表示保留處理器核心不用的數目) @@ -1139,13 +781,21 @@ &Window 視窗 + + &Hide the icon from the system tray. + 不在通知區顯示圖示。 + + + Hide tray icon + 不顯示通知區圖示 + Show only a tray icon after minimizing the window. - 視窗縮到最小後只在通知區域顯示圖示。 + 視窗縮到最小後只在通知區顯示圖示。 &Minimize to the tray instead of the taskbar - 縮到最小到通知區域而不是工作列 + 縮到最小到通知區而不是工作列 M&inimize on close @@ -1159,6 +809,10 @@ User Interface &language: 使用界面語言: + + The user interface language can be set here. This setting will take effect after restarting %1. + 可以在這裡設定使用者介面的語言。這個設定在重啓 %1 後才會生效。 + &Unit to show amounts in: 金額顯示單位: @@ -1284,128 +938,37 @@ - PaymentServer + PeerTableModel - URI handling - URI 處理 + User Agent + 使用者代理 - Invalid payment address %1 - 無效的付款位址 %1 + Node/Service + 節點/服務 - Payment request rejected - 付款的要求被拒絕了 + Ping Time + Ping 時間 + + + QObject - Payment request network doesn't match client network. - 付款要求的網路類型跟客戶端不符。 + Amount + 金額 - Payment request is not initialized. - 付款的要求沒有完成初始化。 + Enter a Bitcoin address (e.g. %1) + 輸入 Bitcoin 位址 (比如說 %1) - Requested payment amount of %1 is too small (considered dust). - 要求付款的金額 %1 太少(會被網路認為是沒必要的零散錢)。 + %1 d + %1 天 - Payment request error - 要求付款時發生錯誤 - - - Cannot start bitcoin: click-to-pay handler - 沒辦法啟動 bitcoin 協議的按就付處理器 - - - Payment request fetch URL is invalid: %1 - 取得付款要求的網址連結(URL)無效: %1 - - - URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - 沒辦法解析資源識別碼(URI)!可能是因為 Bitcoin 位址無效,或是 URI 參數格式錯誤。 - - - Payment request file handling - 處理付款要求檔案 - - - Payment request file cannot be read! This can be caused by an invalid payment request file. - 沒辦法讀取付款要求檔案!可能是無效的檔案造成的。 - - - Payment request expired. - 付款的要求過期了。 - - - Unverified payment requests to custom payment scripts are unsupported. - 不支援含有自訂付款指令碼,且沒驗證過的付款要求。 - - - Invalid payment request. - 付款的要求無效。 - - - Refund from %1 - 來自 %1 的退款 - - - Payment request %1 is too large (%2 bytes, allowed %3 bytes). - 付款要求 %1 過大 (%2 位元組, 上限 %3 位元組). - - - Error communicating with %1: %2 - 跟 %1 通訊時發生錯誤: %2 - - - Payment request cannot be parsed! - 沒辦法解析付款要求內容! - - - Bad response from server %1 - 伺服器 %1 的回應有誤 - - - Payment acknowledged - 已確認付款 - - - Network request error - 發出要求時發生網路錯誤 - - - - PeerTableModel - - User Agent - 使用者代理 - - - Node/Service - 節點/服務 - - - Ping Time - Ping 時間 - - - - QObject - - Amount - 金額 - - - Enter a Bitcoin address (e.g. %1) - 輸入 Bitcoin 位址 (比如說 %1) - - - %1 d - %1 天 - - - %1 h - %1 小時 + %1 h + %1 小時 %1 m @@ -1428,25 +991,6 @@ %1 毫秒 - - QRImageWidget - - &Save Image... - 儲存圖片... - - - &Copy Image - 複製圖片 - - - Save QR Code - 儲存 QR Code - - - PNG Image (*.png) - PNG 圖檔(*.png) - - RPCConsole @@ -1477,6 +1021,10 @@ Using BerkeleyDB version 使用 BerkeleyDB 版本 + + Datadir + 資料目錄 + Startup time 啓動時間 @@ -1513,10 +1061,6 @@ Memory usage 記憶體使用量 - - Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files. - 從目前的資料目錄下開啓 Bitcoin Core 的除錯紀錄檔。當紀錄檔很大時,可能會花好幾秒的時間。 - Received 收到 @@ -1565,6 +1109,18 @@ User Agent 使用者代理 + + Open the %1 debug log file from the current data directory. This can take a few seconds for large log files. + 從目前的資料目錄下開啓 %1 的除錯紀錄檔。當紀錄檔很大時,可能會花好幾秒的時間。 + + + Decrease font size + 縮小文字 + + + Increase font size + 放大文字 + Services 服務 @@ -1633,10 +1189,6 @@ Out: 去: - - Build date - 建置日期 - Debug log file 除錯紀錄檔 @@ -1671,11 +1223,11 @@ &Unban Node - 解禁解點連線 + 解禁節點連線 - Welcome to the Bitcoin Core RPC console. - 歡迎使用 Bitcoin Core 的 RPC 主控台。 + Welcome to the %1 RPC console. + 歡迎使用 %1 的 RPC 主控台。 Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. @@ -1804,18 +1356,6 @@ Remove 刪掉 - - Copy label - 複製標記 - - - Copy message - 複製訊息 - - - Copy amount - 複製金額 - ReceiveRequestDialog @@ -1835,73 +1375,6 @@ &Save Image... 儲存圖片... - - Request payment to %1 - 付款給 %1 的要求 - - - Payment information - 付款資訊 - - - URI - URI - - - Address - 位址 - - - Amount - 金額 - - - Label - 標記 - - - Message - 訊息 - - - Resulting URI too long, try to reduce the text for label / message. - 產生的 URI 過長,請試著縮短標記或訊息的文字內容。 - - - Error encoding URI into QR Code. - 把 URI 編碼成 QR Code 時發生錯誤。 - - - - RecentRequestsTableModel - - Date - 日期 - - - Label - 標記 - - - Message - 訊息 - - - Amount - 金額 - - - (no label) - (無標記) - - - (no message) - (無訊息) - - - (no amount) - (無金額) - SendCoinsDialog @@ -2021,14 +1494,6 @@ fast 快速 - - Send as zero-fee transaction if possible - 盡可能送不用付手續費的交易 - - - (confirmation may take longer) - (確認時間可能拉長) - Send to multiple recipients at once 一次付給多個收款人 @@ -2061,118 +1526,6 @@ S&end 付款 - - Confirm send coins - 確認付款金額 - - - %1 to %2 - %1 給 %2 - - - Copy quantity - 複製數目 - - - Copy amount - 複製金額 - - - Copy fee - 複製手續費 - - - Copy after fee - 複製計費後金額 - - - Copy bytes - 複製位元組數 - - - Copy priority - 複製優先度 - - - Copy change - 複製找零金額 - - - Total Amount %1 - 總金額 %1 - - - or - - - - The amount to pay must be larger than 0. - 付款金額必須大於零。 - - - The amount exceeds your balance. - 金額超過餘額了。 - - - The total exceeds your balance when the %1 transaction fee is included. - 包含 %1 的交易手續費後,總金額超過你的餘額了。 - - - Transaction creation failed! - 製造交易失敗了! - - - The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - 交易被拒絕了!有時候會發生這種錯誤,是因為你錢包中的一些錢已經被花掉了。比如說你複製了錢包檔 wallet.dat, 然後用複製的錢包花掉了錢,你現在所用的原來的錢包中,卻沒有那筆錢已經花掉的紀錄。 - - - A fee higher than %1 is considered an absurdly high fee. - 高於 %1 的手續費會被認為是不合理。 - - - Payment request expired. - 付款的要求過期了。 - - - Pay only the required fee of %1 - 只付必要的手續費 %1 - - - Estimated to begin confirmation within %n block(s). - 預計可在 %n 個區塊內開始確認。 - - - The recipient address is not valid. Please recheck. - 收款位址無效。請再檢查看看。 - - - Duplicate address found: addresses should only be used once each. - 發現有重複的位址: 每個位址只能出現一次。 - - - Warning: Invalid Bitcoin address - 警告: Bitcoin 位址無效 - - - (no label) - (無標記) - - - Warning: Unknown change address - 警告: 不明的找零位址 - - - Copy dust - 複製零散金額 - - - Are you sure you want to send? - 你確定要付錢出去嗎? - - - added as transaction fee - 加做交易手續費 - SendCoinsEntry @@ -2184,10 +1537,6 @@ Pay &To: 付給: - - Enter a label for this address to add it to your address book - 請輸入這個位址的標記來把它加進位址簿中 - &Label: 標記: @@ -2205,700 +1554,182 @@ 接收付款的 Bitcoin 位址 - Alt+A - Alt+A - - - Paste address from clipboard - 貼上剪貼簿裡的位址 - - - Alt+P - Alt+P - - - Remove this entry - 刪掉這個項目 - - - 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. - 手續費會從要付款出去的金額中扣掉。因此收款人會收到比輸入的金額還要少的 bitcoin。如果有多個收款人的話,手續費會平均分配來扣除。 - - - S&ubtract fee from amount - 從付款金額減去手續費 - - - Message: - 訊息: - - - This is an unauthenticated payment request. - 這是個沒有驗證過身份的付款要求。 - - - This is an authenticated payment request. - 這是個已經驗證過身份的付款要求。 - - - Enter a label for this address to add it to the list of used addresses - 請輸入這個位址的標記,來把它加進去已使用過位址的清單。 - - - 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. - 附加在 Bitcoin 付款協議的資源識別碼(URI)中的訊息,會和交易內容一起存起來,給你自己做參考。注意: 這個訊息不會送到 Bitcoin 網路上。 - - - Pay To: - 付給: - - - Memo: - 備註: - - - - ShutdownWindow - - Bitcoin Core is shutting down... - 正在關閉 Bitcoin Core 中... - - - Do not shut down the computer until this window disappears. - 在這個視窗不見以前,請不要關掉電腦。 - - - - SignVerifyMessageDialog - - Signatures - Sign / Verify a Message - 簽章 - 簽署或驗證訊息 - - - &Sign Message - 簽署訊息 - - - 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. - 你可以用自己的位址簽署訊息或合約,來證明你可以從該位址收款。但是請小心,不要簽署語意含糊不清,或隨機產生的內容,因為釣魚式詐騙可能會用騙你簽署的手法來冒充是你。只有在語句中的細節你都同意時才簽署。 - - - The Bitcoin address to sign the message with - 用來簽署訊息的 Bitcoin 位址 - - - Choose previously used address - 選擇先前使用過的位址 - - - Alt+A - Alt+A - - - Paste address from clipboard - 貼上剪貼簿裡的位址 - - - Alt+P - Alt+P - - - Enter the message you want to sign here - 請在這裡輸入你想簽署的訊息 - - - Signature - 簽章 - - - Copy the current signature to the system clipboard - 複製目前的簽章到系統剪貼簿 - - - Sign the message to prove you own this Bitcoin address - 簽署這個訊息來證明這個 Bitcoin 位址是你的 - - - Sign &Message - 簽署訊息 - - - Reset all sign message fields - 重設所有訊息簽署欄位 - - - Clear &All - 全部清掉 - - - &Verify Message - 驗證訊息 - - - 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! - 請在下面輸入收款人的位址,訊息(請確定完整複製了所包含的換行,空格,跳位符號等等),以及簽章,來驗證這個訊息。請小心,除了訊息內容以外,不要對簽章本身過度解讀,以避免被用「中間人攻擊法」詐騙。請注意,通過驗證的簽章只能證明簽章人確實可以從該位址收款,不能證明任何交易中的付款人身份! - - - The Bitcoin address the message was signed with - 簽署這個訊息的 Bitcoin 位址 - - - Verify the message to ensure it was signed with the specified Bitcoin address - 驗證這個訊息來確定是用指定的 Bitcoin 位址簽署的 - - - Verify &Message - 驗證訊息 - - - Reset all verify message fields - 重設所有訊息驗證欄位 - - - Click "Sign Message" to generate signature - 請按一下「簽署訊息」來產生簽章 - - - The entered address is invalid. - 輸入的位址無效。 - - - Please check the address and try again. - 請檢查位址是否正確後再試一次。 - - - The entered address does not refer to a key. - 輸入的位址沒有對應到你的任何密鑰。 - - - Wallet unlock was cancelled. - 錢包解鎖已取消。 - - - Private key for the entered address is not available. - 沒有對應輸入位址的密鑰。 - - - Message signing failed. - 訊息簽署失敗。 - - - Message signed. - 訊息簽署好了。 - - - The signature could not be decoded. - 沒辦法把這個簽章解碼。 - - - Please check the signature and try again. - 請檢查簽章是否正確後再試一次。 - - - The signature did not match the message digest. - 這個簽章跟訊息的數位摘要不符。 - - - Message verification failed. - 訊息驗證失敗。 - - - Message verified. - 訊息驗證沒錯。 - - - - SplashScreen - - Bitcoin Core - Bitcoin Core - - - The Bitcoin Core developers - Bitcoin Core 開發人員 - - - [testnet] - [testnet] - - - - TrafficGraphWidget - - KB/s - KB/s - - - - TransactionDesc - - Open until %1 - 到 %1 前可修改 - - - conflicted - 有衝突 - - - %1/offline - %1 次/離線中 - - - %1/unconfirmed - %1 次/未確認 - - - %1 confirmations - 確認 %1 次 - - - Status - 狀態 - - - , broadcast through %n node(s) - ,已公告給 %n 個節點 - - - Date - 日期 - - - Source - 來源 - - - Generated - 生產出來 - - - From - 來源 - - - To - 目的 - - - own address - 自己的位址 - - - watch-only - 只能看 - - - label - 標記 - - - Credit - 入帳 - - - matures in %n more block(s) - 再等 %n 個區塊生出來後成熟 - - - not accepted - 不被接受 - - - Debit - 出帳 - - - Total debit - 出帳總額 - - - Total credit - 入帳總額 - - - Transaction fee - 交易手續費 - - - Net amount - 淨額 - - - Message - 訊息 - - - Comment - 附註 - - - Transaction ID - 交易識別碼 - - - Merchant - 商家 - - - 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. - 生產出來的錢要再等 %1 個區塊生出來後才成熟可以用。當區塊生產出來時會公布到網路上,來被加進區塊鏈。如果加失敗了,狀態就會變成「不被接受」,而且不能夠花。如果在你生產出區塊的幾秒鐘內,也有其他節點生產出來的話,就有可能會發生這種情形。 - - - Debug information - 除錯資訊 - - - Transaction - 交易 - - - Inputs - 輸入 - - - Amount - 金額 - - - true - - - - false - - - - , has not been successfully broadcast yet - ,還沒成功公告出去 - - - Open for %n more block(s) - 到下 %n 個區塊生出來前可修改 - - - unknown - 未知 - - - - TransactionDescDialog - - Transaction details - 交易明細 - - - This pane shows a detailed description of the transaction - 這個版面顯示這次交易的詳細說明 - - - - TransactionTableModel - - Date - 日期 - - - Type - 種類 - - - Immature (%1 confirmations, will be available after %2) - 未成熟(確認 %1 次,會在 %2 次後可用) - - - Open for %n more block(s) - 到下 %n 個區塊生出來前可修改 - - - Open until %1 - 到 %1 前可修改 - - - Confirmed (%1 confirmations) - 已確認(%1 次) - - - This block was not received by any other nodes and will probably not be accepted! - 沒有其他節點收到這個區塊,也許它不會被接受! - - - Generated but not accepted - 生產出來但是不被接受 - - - Offline - 離線中 - - - Label - 標記 - - - Unconfirmed - 未確認 - - - Confirming (%1 of %2 recommended confirmations) - 確認中(已經 %1 次,建議至少 %2 次) - - - Conflicted - 有衝突 - - - Received with - 收款在 - - - Received from - 收款自 - - - Sent to - 付款給 - - - Payment to yourself - 付給自己 - - - Mined - 開採所得 - - - watch-only - 只能看 - - - (n/a) - (不適用) - - - Transaction status. Hover over this field to show number of confirmations. - 交易狀態。把游標停在欄位上會顯示確認次數。 - - - Date and time that the transaction was received. - 收到交易的日期和時間。 - - - Type of transaction. - 交易的種類。 - - - Whether or not a watch-only address is involved in this transaction. - 不論如何有一個只能觀看的地只有參與這次的交易 - - - User-defined intent/purpose of the transaction. - 使用者定義的交易動機或理由。 - - - Amount removed from or added to balance. - 要減掉或加進餘額的金額。 - - - - TransactionView - - All - 全部 + Alt+A + Alt+A - Today - 今天 + Paste address from clipboard + 貼上剪貼簿裡的位址 - This week - 這星期 + Alt+P + Alt+P - This month - 這個月 + Remove this entry + 刪掉這個項目 - Last month - 上個月 + 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. + 手續費會從要付款出去的金額中扣掉。因此收款人會收到比輸入的金額還要少的 bitcoin。如果有多個收款人的話,手續費會平均分配來扣除。 - This year - 今年 + S&ubtract fee from amount + 從付款金額減去手續費 - Range... - 指定範圍... + Message: + 訊息: - Received with - 收款 + This is an unauthenticated payment request. + 這是個沒有驗證過身份的付款要求。 - Sent to - 付款 + This is an authenticated payment request. + 這是個已經驗證過身份的付款要求。 - To yourself - 給自己 + Enter a label for this address to add it to the list of used addresses + 請輸入這個位址的標記,來把它加進去已使用過位址的清單。 - Mined - 開採所得 + 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. + 附加在 Bitcoin 付款協議的資源識別碼(URI)中的訊息,會和交易內容一起存起來,給你自己做參考。注意: 這個訊息不會送到 Bitcoin 網路上。 - Other - 其它 + Pay To: + 付給: - Enter address or label to search - 請輸入要搜尋的位址或標記 + Memo: + 備註: + + + ShutdownWindow - Min amount - 最小金額 + %1 is shutting down... + 正在關閉 %1 中... - Copy address - 複製位址 + Do not shut down the computer until this window disappears. + 在這個視窗不見以前,請不要關掉電腦。 + + + SignVerifyMessageDialog - Copy label - 複製標記 + Signatures - Sign / Verify a Message + 簽章 - 簽署或驗證訊息 - Copy amount - 複製金額 + &Sign Message + 簽署訊息 - Copy transaction ID - 複製交易識別碼 + 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. + 你可以用自己的位址簽署訊息或合約,來證明你可以從該位址收款。但是請小心,不要簽署語意含糊不清,或隨機產生的內容,因為釣魚式詐騙可能會用騙你簽署的手法來冒充是你。只有在語句中的細節你都同意時才簽署。 - Copy raw transaction - 複製交易原始資料 + The Bitcoin address to sign the message with + 用來簽署訊息的 Bitcoin 位址 - Edit label - 編輯標記 + Choose previously used address + 選擇先前使用過的位址 - Show transaction details - 顯示交易明細 + Alt+A + Alt+A - Export Transaction History - 匯出交易記錄 + Paste address from clipboard + 貼上剪貼簿裡的位址 - Watch-only - 只能觀看的 + Alt+P + Alt+P - Exporting Failed - 匯出失敗 + Enter the message you want to sign here + 請在這裡輸入你想簽署的訊息 - There was an error trying to save the transaction history to %1. - 儲存交易記錄到 %1 時發生錯誤。 + Signature + 簽章 - Exporting Successful - 匯出成功 + Copy the current signature to the system clipboard + 複製目前的簽章到系統剪貼簿 - The transaction history was successfully saved to %1. - 交易記錄已經成功儲存到 %1 了。 + Sign the message to prove you own this Bitcoin address + 簽署這個訊息來證明這個 Bitcoin 位址是你的 - Comma separated file (*.csv) - 逗點分隔資料檔(*.csv) + Sign &Message + 簽署訊息 - Confirmed - 已確認 + Reset all sign message fields + 重設所有訊息簽署欄位 - Date - 日期 + Clear &All + 全部清掉 - Type - 種類 + &Verify Message + 驗證訊息 - Label - 標記 + 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! + 請在下面輸入收款人的位址,訊息(請確定完整複製了所包含的換行,空格,跳位符號等等),以及簽章,來驗證這個訊息。請小心,除了訊息內容以外,不要對簽章本身過度解讀,以避免被用「中間人攻擊法」詐騙。請注意,通過驗證的簽章只能證明簽章人確實可以從該位址收款,不能證明任何交易中的付款人身份! - Address - 位址 + The Bitcoin address the message was signed with + 簽署這個訊息的 Bitcoin 位址 - ID - 識別碼 + Verify the message to ensure it was signed with the specified Bitcoin address + 驗證這個訊息來確定是用指定的 Bitcoin 位址簽署的 - Range: - 範圍: + Verify &Message + 驗證訊息 - to - + Reset all verify message fields + 重設所有訊息驗證欄位 - UnitDisplayStatusBarControl + SplashScreen - Unit to show amounts in. Click to select another unit. - 金額顯示單位。可以點選其他單位。 + [testnet] + [testnet] - WalletFrame + TrafficGraphWidget - No wallet has been loaded. - 沒有載入錢包。 + KB/s + KB/s - WalletModel + TransactionDescDialog - Send Coins - 付款 + This pane shows a detailed description of the transaction + 這個版面顯示這次交易的詳細說明 - WalletView - - &Export - 匯出 - - - Export the data in the current tab to a file - 把目前分頁的資料匯出存成檔案 - - - Backup Wallet - 備份錢包 - - - Wallet Data (*.dat) - 錢包資料檔(*.dat) - - - Backup Failed - 備份失敗 - - - There was an error trying to save the wallet data to %1. - 儲存錢包資料到 %1 時發生錯誤。 - - - The wallet data was successfully saved to %1. - 錢包的資料已經成功儲存到 %1 了。 - + UnitDisplayStatusBarControl - Backup Successful - 備份成功 + Unit to show amounts in. Click to select another unit. + 金額顯示單位。可以點選其他單位。 @@ -2928,14 +1759,6 @@ If <category> is not supplied or if <category> = 1, output all debugging information. 如果沒有提供 <category> 或是值為 1 就會輸出所有的除錯資訊。 - - Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s) - 一次錢包交易允許付出最高的總手續費(單位是 %s);設定太低的話,可能會無法進行資料量大的交易(預設值: %s) - - - Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly. - 請檢查電腦日期和時間是否正確!Bitcoin Core 沒辦法在時鐘不準的情況下正常運作。 - Prune configured below the minimum of %d MiB. Please use a higher number. 設定的修剪值小於最小需求的 %d 百萬位元組(MiB)。請指定大一點的數字。 @@ -2976,6 +1799,14 @@ Accept connections from outside (default: 1 if no -proxy or -connect) 是否接受外來連線(預設值: 當沒有 -proxy 或 -connect 時為 1) + + Bitcoin Core + Bitcoin Core + + + The %s developers + %s 開發人員 + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. 警告: -fallbackfee 設定了很高的金額!這是當預估手續費還沒計算出來時,交易付款預設會付的手續費。 @@ -2992,6 +1823,10 @@ Bind to given address and always listen on it. Use [host]:port notation for IPv6 和指定的位址繫結,並且一直在指定位址聽候連線。IPv6 請用 [主機]:通訊埠 這種格式 + + Cannot obtain a lock on data directory %s. %s is probably already running. + 沒辦法鎖定資料目錄 %s。%s 可能已經在執行了。 + Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup 清掉錢包裡的所有交易,並且在下次啟動時,使用 -rescan 來從區塊鏈中復原回來。 @@ -3000,6 +1835,14 @@ Distributed under the MIT software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>. 這套軟體是依據 MIT 軟體授權條款散布,詳情請見附帶的 COPYING 檔案,或是以下網站: <http://www.opensource.org/licenses/mit-license.php>. + + Error loading %s: You can't enable HD on a already existing non-HD wallet + 載入 %s 發生錯誤:不能對已存在的非 HD 錢包啟用 HD 功能。 + + + Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + 讀取錢包檔 %s 時發生錯誤!所有的密鑰都正確讀取了,但是交易資料或位址簿資料可能會缺少或不正確。 + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) 當錢包有交易改變時要執行的指令(指令中的 %s 會被取代成交易識別碼) @@ -3008,6 +1851,22 @@ Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) 強制轉發從白名點節點收到的交易,即使它們違反了本機的轉發準則(預設值: %d) + + Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds) + 跟其他節點的時間差最高可接受的中位數值。本機所認為的時間可能會被其他節點影響,往前或往後在這個值之內。(預設值: %u 秒) + + + Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s) + 允許一次錢包交易或未加工交易付出的最高總手續費(單位是 %s);設定太低的話,可能會無法進行資料量大的交易(預設值: %s) + + + Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly. + 請檢查電腦日期和時間是否正確!%s 沒辦法在時鐘不準的情況下正常運作。 + + + Please contribute if you find %s useful. Visit %s for further information about the software. + 如果你覺得 %s 有用,可以捐助我們。關於這個軟體的更多資訊請見 %s。 + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) 設定指令碼驗證的執行緒數目 (%u 到 %d,0 表示程式自動決定,小於 0 表示保留處理器核心不用的數目,預設值: %d) @@ -3020,14 +1879,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications 這是個還沒發表的測試版本 - 使用請自負風險 - 請不要用來開採或商業應用 - - Unable to bind to %s on this computer. Bitcoin Core is probably already running. - 沒辦法繫結在這台電腦上的 %s 。Bitcoin Core 可能已經在執行了。 - - - Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. - 忽略不支援的參數 -whitelistalwaysrelay,請改用 -whitelistrelay 和 -whitelistforcerelay​ 的組合。 - Use UPnP to map the listening port (default: 1 when listening and no -proxy) 是否要使用「通用即插即用」協定(UPnP),來設定聽候連線的通訊埠的對應(預設值: 當有聽候連線且沒有指定 -proxy 參數時為 1) @@ -3044,22 +1895,22 @@ Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. 警告: 節點網路對於區塊鏈結的決定目前有分歧!看來有些礦工會有問題。 - - Warning: Unknown block versions being mined! It's possible unknown rules are in effect - 警告: 有礦工正在開採不明版本的區塊!這表示有不明的交易規則正在作用中 - Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. 警告: 我們和某些連線的節點對於區塊鏈結的決定不同!你可能需要升級,或是需要等其它的節點升級。 - - Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - 警告: 錢包檔 wallet.dat 壞掉,但資料被拯救回來了!原來的 wallet.dat 會改儲存在 %s, 檔名是 wallet.{timestamp}.bak. 如果餘額或交易資料有誤,你應該要用備份資料復原回來。 - Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. 把來自指定網域或位址的節點放進白名單。這個選項可以設定多次。 + + You need to rebuild the database using -reindex-chainstate to change -txindex + 改變 -txindex 參數後,必須要用 -reindex-chainstate 參數來重建資料庫 + + + %s corrupt, salvage failed + 錢包檔 %s 壞掉了,搶救失敗 + -maxmempool must be at least %d MB 參數 -maxmempool 至少要給 %d 百萬位元組(MB) @@ -3072,10 +1923,22 @@ Append comment to the user agent string 對使用者代理字串添加註解 + + Attempt to recover private keys from a corrupt wallet on startup + 啟動時嘗試從壞掉的錢包檔復原密鑰 + Block creation options: 區塊製造選項: + + Cannot resolve -%s address: '%s' + 沒辦法解析 -%s 參數指定的位址: '%s' + + + Change index out of range + 找零的索引值超出範圍 + Connect only to the specified node(s) 只連線到指定節點(可多個) @@ -3084,6 +1947,10 @@ Connection options: 連線選項: + + Copyright (C) %i-%i + 版權所有 (C) %i-%i + Corrupted block database detected 發現區塊資料庫壞掉了 @@ -3128,6 +1995,22 @@ Error initializing wallet database environment %s! 初始化錢包資料庫環境 %s 時發生錯誤! + + Error loading %s + 載入檔案 %s 時發生錯誤 + + + Error loading %s: Wallet corrupted + 載入檔案 %s 時發生錯誤: 錢包損毀了 + + + Error loading %s: Wallet requires newer version of %s + 載入檔案 %s 時發生錯誤: 這個錢包需要新版的 %s + + + Error loading %s: You can't disable HD on a already existing HD wallet + 載入 %s 發生錯誤:不能對已存在的 HD 錢包停用 HD 功能。 + Error loading block database 載入區塊資料庫時發生錯誤 @@ -3152,10 +2035,18 @@ Incorrect or no genesis block found. Wrong datadir for network? 創世區塊不正確或找不到。資料目錄錯了嗎? + + Initialization sanity check failed. %s is shutting down. + 初始化時的基本檢查失敗了。%s 就要關閉了。 + Invalid -onion address: '%s' 無效的 -onion 位址: '%s' + + Invalid amount for -%s=<amount>: '%s' + 參數 -%s=<金額> 指定的金額無效: '%s' + Invalid amount for -fallbackfee=<amount>: '%s' 設定 -fallbackfee=<金額> 的金額無效: '%s' @@ -3164,6 +2055,10 @@ Keep the transaction memory pool below <n> megabytes (default: %u) 在記憶體暫存池中保持最多 <n> 個百萬位元組的交易(預設值: %u) + + Loading banlist... + 正在載入禁止連線名單中... + Location of the auth cookie (default: data dir) 認證 cookie 資料的位置(預設值: 同資料目錄) @@ -3180,6 +2075,10 @@ Only connect to nodes in network <net> (ipv4, ipv6 or onion) 只和 <net> 網路上的節點連線(ipv4, ipv6, 或 onion) + + Print this help message and exit + 顯示說明訊息後結束 + Print version and exit 顯示版本後結束 @@ -3192,6 +2091,14 @@ Prune mode is incompatible with -txindex. 修剪模式和 -txindex 參數不相容。 + + Rebuild chain state and block index from the blk*.dat files on disk + 從磁碟裡的區塊檔 blk*.dat 重建區塊鏈狀態和區塊索引 + + + Rebuild chain state from the currently indexed blocks + 從目前已編索引的區塊資料重建區塊鏈狀態 + Set database cache size in megabytes (%d to %d, default: %d) 設定資料庫快取大小是多少百萬位元組(MB,範圍: %d 到 %d,預設值: %d) @@ -3204,6 +2111,14 @@ Specify wallet file (within data directory) 指定錢包檔(會在資料目錄中) + + The source code is available from %s. + 原始碼可以在 %s 取得。 + + + Unable to bind to %s on this computer. %s is probably already running. + 沒辦法繫結在這台電腦上的 %s 。%s 可能已經在執行了。 + Unsupported argument -benchmark ignored, use -debug=bench. 忽略了不再支援的 -benchmark 參數,請改用 -debug=bench @@ -3237,12 +2152,16 @@ 錢包檔 %s 沒有在資料目錄 %s 裡面 - Wallet options: - 錢包選項: + Wallet debugging/testing options: + 錢包除錯與測試選項: + + + Wallet needed to be rewritten: restart %s to complete + 錢包需要重寫: 請重新啓動 %s 來完成 - You need to rebuild the database using -reindex to change -txindex - 改變 -txindex 參數後,必須要用 -reindex 參數來重建資料庫 + Wallet options: + 錢包選項: 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 @@ -3256,10 +2175,6 @@ Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces) 和指定的位址繫結以聽候 JSON-RPC 連線。IPv6 請用 [主機]:通訊埠 這種格式。這個選項可以設定多次。(預設值: 跟所有網路界面上的位址繫結) - - Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - 沒辦法鎖定資料目錄 %s。Bitcoin Core 可能已經在執行了。 - Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality) 用系統預設權限來造出新的檔案,而不是用使用者權限罩遮(umask)值 077 (只有在關掉錢包功能時才有作用)。 @@ -3304,10 +2219,6 @@ Set maximum size of high-priority/low-fee transactions in bytes (default: %d) 設定高優先度或低手續費的交易資料大小上限成多少位元組(預設值: %d) - - Set the number of threads for coin generation if enabled (-1 = all cores, default: %d) - 設定產生錢幣的執行緒數目(-1 表示處理器核心數,預設值: %d) - The transaction amount is too small to send after the fee has been deducted 扣除手續費後的交易金額太少而不能傳送 @@ -3316,6 +2227,10 @@ This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard. 此產品也包含了由 OpenSSL Project 所開發的 OpenSSL Toolkit 軟體 <https://www.openssl.org/>, 和由 Eric Young 撰寫的加解密軟體,以及由 Thomas Bernard 所撰寫的 UPnP 軟體。 + + Use hierarchical deterministic key generation (HD) after BIP32. Only has effect during wallet creation/first start + 在 BIP32 開始作用後,啟用階層式可預期性密鑰產生方式(HD)。只有在產生新錢包或第一次啟動時才有作用。 + 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 在白名單中的節點不會因為偵測到阻斷服務攻擊(DoS)而被停用。來自這些節點的交易也一定會被轉發,即使說交易本來就在記憶池裡了也一樣。適用於像是閘道伺服器。 @@ -3332,34 +2247,14 @@ Accept public REST requests (default: %u) 接受公開的REST請求 (預設值: %u) - - Activating best chain... - 啟用最佳鏈結... - - - Attempt to recover private keys from a corrupt wallet.dat on startup - 啟動時嘗試從壞掉的錢包檔 wallet.dat 復原密鑰 - Automatically create Tor hidden service (default: %d) 自動產生 Tor 隱藏服務(預設值: %d) - - Cannot resolve -whitebind address: '%s' - 沒辦法解析 -whitebind 指定的位址: '%s' - Connect through SOCKS5 proxy 透過 SOCKS5 代理伺服器連線 - - Copyright (C) 2009-%i The Bitcoin Core Developers - 版權為 Bitcoin Core 開發人員自西元 2009 至 %i 年起所有 - - - Error loading wallet.dat: Wallet requires newer version of Bitcoin Core - 載入 wallet.dat 檔案時發生錯誤: 這個錢包需要新版的 Bitcoin Core - Error reading from database, shutting down. 讀取資料庫時發生錯誤,要關閉了。 @@ -3372,22 +2267,6 @@ Information 資訊 - - Initialization sanity check failed. Bitcoin Core is shutting down. - 初始化時的基本檢查失敗了。Bitcoin Core 就要關閉了。 - - - Invalid amount for -maxtxfee=<amount>: '%s' - -maxtxfee=<amount>: '%s' 的金額無效 - - - Invalid amount for -minrelaytxfee=<amount>: '%s' - 設定最低轉發手續費 -minrelaytxfee=<金額> 的金額無效: '%s' - - - Invalid amount for -mintxfee=<amount>: '%s' - 設定 -mintxfee=<金額> 的金額無效: '%s' - Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) 設定 -paytxfee=<金額> 的金額無效: '%s' (至少要有 %s) @@ -3412,14 +2291,6 @@ RPC server options: RPC 伺服器選項: - - Rebuild block chain index from current blk000??.dat files on startup - 啟動時從目前的區塊檔 blk000??.dat 重建區塊鏈的索引 - - - Receive and display P2P network alerts (default: %u) - 接收並顯示對等網路(P2P)警示 (預設值: %u) - Reducing -maxconnections from %d to %d, because of system limitations. 因為系統的限制,將 -maxconnections 參數從 %d 降到了 %d @@ -3492,10 +2363,6 @@ Username for JSON-RPC connections JSON-RPC 連線使用者名稱 - - Wallet needed to be rewritten: restart Bitcoin Core to complete - 錢包需要重寫: 請重新啓動 Bitcoin Core 來完成 - Warning 警告 @@ -3516,10 +2383,6 @@ ZeroMQ notification options: ZeroMQ 通知選項: - - wallet.dat corrupt, salvage failed - 錢包檔 weallet.dat 壞掉了,拯救失敗 - Password for JSON-RPC connections JSON-RPC 連線密碼 @@ -3528,10 +2391,6 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) 當最新區塊改變時要執行的指令(指令中的 %s 會被取代成區塊雜湊值) - - This help message - 這些說明訊息 - Allow DNS lookups for -addnode, -seednode and -connect 允許對 -addnode, -seednode, -connect 的參數使用域名查詢 @@ -3540,10 +2399,6 @@ Loading addresses... 正在載入位址資料... - - Error loading wallet.dat: Wallet corrupted - 載入檔案 wallet.dat 時發生錯誤: 錢包損毀了 - (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) (1 表示保留交易描述資料,像是帳戶使用者和付款請求資訊;2 表示丟掉交易描述資料) @@ -3560,10 +2415,6 @@ Do not keep transactions in the mempool longer than <n> hours (default: %u) 不要讓交易留在記憶池中超過 <n> 個小時(預設值: %u) - - Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. - 讀取錢包檔 wallet.dat 時發生錯誤!所有的密鑰都正確讀取了,但是交易資料或位址簿資料可能會缺少或不正確。 - Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) 當製造交易時,如果每千位元組(kB)的手續費比這個值(單位是 %s)低,就視為沒付手續費(預設值: %s) @@ -3600,6 +2451,10 @@ Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported. 找到不再支援的 -socks 參數。現在只支援 SOCKS5 協定的代理伺服器,因此不可以指定 SOCKS 協定版本了。 + + Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay. + 忽略不支援的參數 -whitelistalwaysrelay,請改用 -whitelistrelay 和 -whitelistforcerelay​ 的組合。 + Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s) 使用另外的 SOCK5 代理伺服器,來透過 Tor 隱藏服務跟其他節點聯絡(預設值: %s) @@ -3609,20 +2464,20 @@ JSON-RPC 連線要用的使用者名稱和雜湊密碼。<userpw> 的格式是:<使用者名稱>:<調味值>$<雜湊值>。在 share/rpcuser 目錄下有一個示範的 python 程式。這個選項可以給很多次。 - (default: %s) - (預設值: %s) + Warning: Unknown block versions being mined! It's possible unknown rules are in effect + 警告: 有礦工正在開採不明版本的區塊!這表示有不明的交易規則正在作用中 - Always query for peer addresses via DNS lookup (default: %u) - 是否一定要用域名查詢來搜尋節點(預設值: %u) + Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup. + 警告: 錢包檔壞掉,但資料被救回來了!原來的檔案 %s 改儲存為 %s,在目錄 %s 下。 如果餘額或交易資料有誤的話,你應該要從備份資料復原回來。 - Error loading wallet.dat - 載入錢包檔 wallet.dat 時發生錯誤 + (default: %s) + (預設值: %s) - Generate coins (default: %u) - 生產錢幣(預設值: %u) + Always query for peer addresses via DNS lookup (default: %u) + 是否一定要用域名查詢來搜尋節點(預設值: %u) How many blocks to check at startup (default: %u, 0 = all) @@ -3708,18 +2563,6 @@ Unknown network specified in -onlynet: '%s' 在 -onlynet 指定了不明的網路別: '%s' - - Cannot resolve -bind address: '%s' - 沒辦法解析 -bind 位址: '%s' - - - Cannot resolve -externalip address: '%s' - 沒辦法解析 -externalip 位址: '%s' - - - Invalid amount for -paytxfee=<amount>: '%s' - 設定 -paytxfee=<金額> 的金額無效: '%s' - Insufficient funds 累積金額不足 From 7b01ce254cfa0e8ae7e57a72c57e8ae89f3c1829 Mon Sep 17 00:00:00 2001 From: Matthew King Date: Tue, 28 Jun 2016 12:54:30 +0300 Subject: [PATCH 0581/1802] Favour python over python2 as per PR #7723 --- contrib/devtools/security-check.py | 2 +- contrib/devtools/symbol-check.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/devtools/security-check.py b/contrib/devtools/security-check.py index 24e44cf5d8628..c61d652641767 100755 --- a/contrib/devtools/security-check.py +++ b/contrib/devtools/security-check.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python ''' Perform basic ELF security checks on a series of executables. Exit status will be 0 if successful, and the program will be silent. diff --git a/contrib/devtools/symbol-check.py b/contrib/devtools/symbol-check.py index 8c064a1822b00..8f8685006e115 100755 --- a/contrib/devtools/symbol-check.py +++ b/contrib/devtools/symbol-check.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python # Copyright (c) 2014 Wladimir J. van der Laan # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. From 36f1b9df762f4819e67e060e1624911df9bd59de Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Tue, 28 Jun 2016 10:32:09 -0400 Subject: [PATCH 0582/1802] Tests: Increase sync_blocks() timeouts in pruning.py --- qa/rpc-tests/pruning.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qa/rpc-tests/pruning.py b/qa/rpc-tests/pruning.py index d225e29b500f2..7cbe69c29b2b9 100755 --- a/qa/rpc-tests/pruning.py +++ b/qa/rpc-tests/pruning.py @@ -151,14 +151,14 @@ def reorg_test(self): print("Reconnect nodes") connect_nodes(self.nodes[0], 1) connect_nodes(self.nodes[2], 1) - sync_blocks(self.nodes[0:3]) + sync_blocks(self.nodes[0:3], timeout=120) print("Verify height on node 2:",self.nodes[2].getblockcount()) print("Usage possibly still high bc of stale blocks in block files:", calc_usage(self.prunedir)) print("Mine 220 more blocks so we have requisite history (some blocks will be big and cause pruning of previous chain)") self.nodes[0].generate(220) #node 0 has many large tx's in its mempool from the disconnects - sync_blocks(self.nodes[0:3]) + sync_blocks(self.nodes[0:3], timeout=300) usage = calc_usage(self.prunedir) print("Usage should be below target:", usage) From 14d01309bed59afb08651f2b701ff90371b15b20 Mon Sep 17 00:00:00 2001 From: BtcDrak Date: Tue, 16 Feb 2016 18:29:53 +0000 Subject: [PATCH 0583/1802] Rename OP_NOP3 to OP_CHECKSEQUENCEVERIFY --- doc/release-notes.md | 7 +++- qa/rpc-tests/test_framework/script.py | 8 ++-- src/script/script.cpp | 2 +- src/script/script.h | 4 +- src/test/data/script_tests.json | 24 ++++++------ src/test/data/tx_invalid.json | 28 +++++++------- src/test/data/tx_valid.json | 56 +++++++++++++-------------- 7 files changed, 66 insertions(+), 63 deletions(-) diff --git a/doc/release-notes.md b/doc/release-notes.md index 6e4f390cbcc75..e1f3e2427ea8d 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -113,12 +113,15 @@ git merge commit are mentioned. ### RPC and REST -Asm script outputs now contain OP_CHECKLOCKTIMEVERIFY in place of OP_NOP2 -------------------------------------------------------------------------- +Asm script outputs replacements for OP_NOP2 and OP_NOP3 +------------------------------------------------------- OP_NOP2 has been renamed to OP_CHECKLOCKTIMEVERIFY by [BIP 65](https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki) +OP_NOP3 has been renamed to OP_CHECKSEQUENCEVERIFY by [BIP +112](https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki) + The following outputs are affected by this change: - RPC `getrawtransaction` (in verbose mode) - RPC `decoderawtransaction` diff --git a/qa/rpc-tests/test_framework/script.py b/qa/rpc-tests/test_framework/script.py index 7678228c42bb5..b46c643ccb114 100644 --- a/qa/rpc-tests/test_framework/script.py +++ b/qa/rpc-tests/test_framework/script.py @@ -233,7 +233,7 @@ def __new__(cls, n): # expansion OP_NOP1 = CScriptOp(0xb0) OP_CHECKLOCKTIMEVERIFY = CScriptOp(0xb1) -OP_NOP3 = CScriptOp(0xb2) +OP_CHECKSEQUENCEVERIFY = CScriptOp(0xb2) OP_NOP4 = CScriptOp(0xb3) OP_NOP5 = CScriptOp(0xb4) OP_NOP6 = CScriptOp(0xb5) @@ -360,7 +360,7 @@ def __new__(cls, n): OP_NOP1, OP_CHECKLOCKTIMEVERIFY, - OP_NOP3, + OP_CHECKSEQUENCEVERIFY, OP_NOP4, OP_NOP5, OP_NOP6, @@ -479,7 +479,7 @@ def __new__(cls, n): OP_CHECKMULTISIGVERIFY : 'OP_CHECKMULTISIGVERIFY', OP_NOP1 : 'OP_NOP1', OP_CHECKLOCKTIMEVERIFY : 'OP_CHECKLOCKTIMEVERIFY', - OP_NOP3 : 'OP_NOP3', + OP_CHECKSEQUENCEVERIFY : 'OP_CHECKSEQUENCEVERIFY', OP_NOP4 : 'OP_NOP4', OP_NOP5 : 'OP_NOP5', OP_NOP6 : 'OP_NOP6', @@ -598,7 +598,7 @@ def __new__(cls, n): 'OP_CHECKMULTISIGVERIFY' : OP_CHECKMULTISIGVERIFY, 'OP_NOP1' : OP_NOP1, 'OP_CHECKLOCKTIMEVERIFY' : OP_CHECKLOCKTIMEVERIFY, - 'OP_NOP3' : OP_NOP3, + 'OP_CHECKSEQUENCEVERIFY' : OP_CHECKSEQUENCEVERIFY, 'OP_NOP4' : OP_NOP4, 'OP_NOP5' : OP_NOP5, 'OP_NOP6' : OP_NOP6, diff --git a/src/script/script.cpp b/src/script/script.cpp index da551c23ee678..ddf6775569421 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -132,7 +132,7 @@ const char* GetOpName(opcodetype opcode) // expanson case OP_NOP1 : return "OP_NOP1"; case OP_CHECKLOCKTIMEVERIFY : return "OP_CHECKLOCKTIMEVERIFY"; - case OP_NOP3 : return "OP_NOP3"; + case OP_CHECKSEQUENCEVERIFY : return "OP_CHECKSEQUENCEVERIFY"; case OP_NOP4 : return "OP_NOP4"; case OP_NOP5 : return "OP_NOP5"; case OP_NOP6 : return "OP_NOP6"; diff --git a/src/script/script.h b/src/script/script.h index 71af3754bcd17..278774d32e3ed 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -167,8 +167,8 @@ enum opcodetype OP_NOP1 = 0xb0, OP_CHECKLOCKTIMEVERIFY = 0xb1, OP_NOP2 = OP_CHECKLOCKTIMEVERIFY, - OP_NOP3 = 0xb2, - OP_CHECKSEQUENCEVERIFY = OP_NOP3, + OP_CHECKSEQUENCEVERIFY = 0xb2, + OP_NOP3 = OP_CHECKSEQUENCEVERIFY, OP_NOP4 = 0xb3, OP_NOP5 = 0xb4, OP_NOP6 = 0xb5, diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json index 9b81e0c77ddf7..fcd5457386dda 100644 --- a/src/test/data/script_tests.json +++ b/src/test/data/script_tests.json @@ -232,8 +232,8 @@ ["'abcdefghijklmnopqrstuvwxyz'", "HASH256 0x4c 0x20 0xca139bc10c2f660da42666f72e89a225936fc60f193c161124a672050c434671 EQUAL", "P2SH,STRICTENC", "OK"], -["1","NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 1 EQUAL", "P2SH,STRICTENC", "OK"], -["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_10' EQUAL", "P2SH,STRICTENC", "OK"], +["1","NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 1 EQUAL", "P2SH,STRICTENC", "OK"], +["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_10' EQUAL", "P2SH,STRICTENC", "OK"], ["1", "NOP", "P2SH,STRICTENC,DISCOURAGE_UPGRADABLE_NOPS", "OK", "Discourage NOPx flag allows OP_NOP"], @@ -443,7 +443,7 @@ ["NOP", "NOP1 1", "P2SH,STRICTENC", "OK"], ["NOP", "CHECKLOCKTIMEVERIFY 1", "P2SH,STRICTENC", "OK"], -["NOP", "NOP3 1", "P2SH,STRICTENC", "OK"], +["NOP", "CHECKSEQUENCEVERIFY 1", "P2SH,STRICTENC", "OK"], ["NOP", "NOP4 1", "P2SH,STRICTENC", "OK"], ["NOP", "NOP5 1", "P2SH,STRICTENC", "OK"], ["NOP", "NOP6 1", "P2SH,STRICTENC", "OK"], @@ -701,7 +701,7 @@ ["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "", "OK", "Zero-length S is correctly encoded for DERSIG"], ["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "Negative S is correctly encoded"], -["2147483648", "NOP3", "CHECKSEQUENCEVERIFY", "OK", "CSV passes if stack top bit 1 << 31 is set"], +["2147483648", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "OK", "CSV passes if stack top bit 1 << 31 is set"], ["", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE", "Test the test: we should have an empty stack after scriptSig evaluation"], [" ", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE", "and multiple spaces should not change that."], @@ -857,13 +857,13 @@ ["2 2 LSHIFT", "8 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], ["2 1 RSHIFT", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], -["1", "NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 2 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], -["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_11' EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], +["1", "NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 2 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], +["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_11' EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"], ["Ensure 100% coverage of discouraged NOPS"], ["1", "NOP1", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], ["1", "CHECKLOCKTIMEVERIFY", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], -["1", "NOP3", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], +["1", "CHECKSEQUENCEVERIFY", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], ["1", "NOP4", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], ["1", "NOP5", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], ["1", "NOP6", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], @@ -2119,11 +2119,11 @@ ], ["CHECKSEQUENCEVERIFY tests"], -["", "NOP3", "CHECKSEQUENCEVERIFY", "INVALID_STACK_OPERATION", "CSV automatically fails on a empty stack"], -["-1", "NOP3", "CHECKSEQUENCEVERIFY", "NEGATIVE_LOCKTIME", "CSV automatically fails if stack top is negative"], -["0x0100", "NOP3", "CHECKSEQUENCEVERIFY,MINIMALDATA", "UNKNOWN_ERROR", "CSV fails if stack top is not minimally encoded"], -["0", "NOP3", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME", "CSV fails if stack top bit 1 << 31 is set and the tx version < 2"], -["4294967296", "NOP3", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME", +["", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "INVALID_STACK_OPERATION", "CSV automatically fails on a empty stack"], +["-1", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "NEGATIVE_LOCKTIME", "CSV automatically fails if stack top is negative"], +["0x0100", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY,MINIMALDATA", "UNKNOWN_ERROR", "CSV fails if stack top is not minimally encoded"], +["0", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME", "CSV fails if stack top bit 1 << 31 is set and the tx version < 2"], +["4294967296", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME", "CSV fails if stack top bit 1 << 31 is not set, and tx version < 2"], ["The End"] ] diff --git a/src/test/data/tx_invalid.json b/src/test/data/tx_invalid.json index 05502a83f73b1..f8baee05779c3 100644 --- a/src/test/data/tx_invalid.json +++ b/src/test/data/tx_invalid.json @@ -200,41 +200,41 @@ ["CHECKSEQUENCEVERIFY tests"], ["By-height locks, with argument just beyond txin.nSequence"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000feff40000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["By-time locks, with argument just beyond txin.nSequence (but within numerical boundries)"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194305 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194305 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000feff40000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["Argument missing"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["Argument negative with by-blockheight txin.nSequence=0"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "-1 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "-1 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["Argument negative with by-blocktime txin.nSequence=CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "-1 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "-1 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["Argument/tx height/time mismatch, both versions"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "65535 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "65535 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["6 byte non-minimally-encoded arguments are invalid even if their contents are valid"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x06 0x000000000000 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x06 0x000000000000 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff00000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["Failure due to failing CHECKSEQUENCEVERIFY in scriptSig"], @@ -246,9 +246,9 @@ "0200000001000100000000000000000000000000000000000000000000000000000000000000000000030251b2000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["Failure due to insufficient tx.nVersion (<2)"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKSEQUENCEVERIFY 1"]], "010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 CHECKSEQUENCEVERIFY 1"]], "010000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["Unknown witness program version (with DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)"], diff --git a/src/test/data/tx_valid.json b/src/test/data/tx_valid.json index c9fe4e313a2eb..1ea70135b437b 100644 --- a/src/test/data/tx_valid.json +++ b/src/test/data/tx_valid.json @@ -236,77 +236,77 @@ ["CHECKSEQUENCEVERIFY tests"], ["By-height locks, with argument == 0 and == txin.nSequence"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "65535 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "65535 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff00000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "65535 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "65535 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["By-time locks, with argument == 0 and == txin.nSequence"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff40000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["Upper sequence with upper sequence is fine"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000800100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000800100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000feffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000feffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["Argument 2^31 with various nSequence"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["Argument 2^32-1 with various nSequence"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["Argument 3<<31 with various nSequence"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["5 byte non-minimally-encoded operandss are valid"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x05 0x0000000000 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x05 0x0000000000 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["The argument can be calculated rather than created directly by a PUSHDATA"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194303 1ADD NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194303 1ADD CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 1SUB NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 1SUB CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff00000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["An ADD producing a 5-byte result that sets CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483647 65536 NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483647 65536 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483647 4259840 ADD NOP3 1"]], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483647 4259840 ADD CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["Valid CHECKSEQUENCEVERIFY in scriptSig"], From 18c975c831a3a71b26df43a2617a06840f3aa377 Mon Sep 17 00:00:00 2001 From: BtcDrak Date: Tue, 28 Jun 2016 17:23:32 +0100 Subject: [PATCH 0584/1802] Rename NOP3 to CHECSEQUENCEVERIFY in rpc tests --- qa/rpc-tests/bip68-112-113-p2p.py | 6 +++--- qa/rpc-tests/bip9-softforks.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/qa/rpc-tests/bip68-112-113-p2p.py b/qa/rpc-tests/bip68-112-113-p2p.py index 8ba07043849a6..55b3e2a04a033 100755 --- a/qa/rpc-tests/bip68-112-113-p2p.py +++ b/qa/rpc-tests/bip68-112-113-p2p.py @@ -173,7 +173,7 @@ def create_bip112special(self, input, txversion): tx = self.create_transaction(self.nodes[0], input, self.nodeaddress, Decimal("49.98")) tx.nVersion = txversion signtx = self.sign_transaction(self.nodes[0], tx) - signtx.vin[0].scriptSig = CScript([-1, OP_NOP3, OP_DROP] + list(CScript(signtx.vin[0].scriptSig))) + signtx.vin[0].scriptSig = CScript([-1, OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(signtx.vin[0].scriptSig))) return signtx def create_bip112txs(self, bip112inputs, varyOP_CSV, txversion, locktime_delta = 0): @@ -196,9 +196,9 @@ def create_bip112txs(self, bip112inputs, varyOP_CSV, txversion, locktime_delta = tx.nVersion = txversion signtx = self.sign_transaction(self.nodes[0], tx) if (varyOP_CSV): - signtx.vin[0].scriptSig = CScript([relative_locktimes[b31][b25][b22][b18], OP_NOP3, OP_DROP] + list(CScript(signtx.vin[0].scriptSig))) + signtx.vin[0].scriptSig = CScript([relative_locktimes[b31][b25][b22][b18], OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(signtx.vin[0].scriptSig))) else: - signtx.vin[0].scriptSig = CScript([base_relative_locktime, OP_NOP3, OP_DROP] + list(CScript(signtx.vin[0].scriptSig))) + signtx.vin[0].scriptSig = CScript([base_relative_locktime, OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(signtx.vin[0].scriptSig))) b18txs.append(signtx) b22txs.append(b18txs) b25txs.append(b22txs) diff --git a/qa/rpc-tests/bip9-softforks.py b/qa/rpc-tests/bip9-softforks.py index d7e8e5e5a5588..979d1410c2616 100755 --- a/qa/rpc-tests/bip9-softforks.py +++ b/qa/rpc-tests/bip9-softforks.py @@ -9,7 +9,7 @@ from test_framework.mininode import CTransaction, NetworkThread from test_framework.blocktools import create_coinbase, create_block from test_framework.comptool import TestInstance, TestManager -from test_framework.script import CScript, OP_1NEGATE, OP_NOP3, OP_DROP +from test_framework.script import CScript, OP_1NEGATE, OP_CHECKSEQUENCEVERIFY, OP_DROP from io import BytesIO import time import itertools @@ -220,7 +220,7 @@ def csv_invalidate(self, tx): '''Modify the signature in vin 0 of the tx to fail CSV Prepends -1 CSV DROP in the scriptSig itself. ''' - tx.vin[0].scriptSig = CScript([OP_1NEGATE, OP_NOP3, OP_DROP] + + tx.vin[0].scriptSig = CScript([OP_1NEGATE, OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(tx.vin[0].scriptSig))) def sequence_lock_invalidate(self, tx): From a7897c02f790cd487874f09bc7b4ec31c17968ee Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 28 Jun 2016 18:27:49 +0200 Subject: [PATCH 0585/1802] qt: Remove client name from debug window Remove the client name from the debug window in the GUI. It is already part of the user agent, so adding it separately doesn't add anything. --- src/qt/clientmodel.cpp | 5 --- src/qt/clientmodel.h | 1 - src/qt/forms/debugwindow.ui | 75 +++++++++++++------------------------ src/qt/rpcconsole.cpp | 1 - 4 files changed, 26 insertions(+), 56 deletions(-) diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 108500654b2da..14661b857a5a5 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -179,11 +179,6 @@ bool ClientModel::isReleaseVersion() const return CLIENT_VERSION_IS_RELEASE; } -QString ClientModel::clientName() const -{ - return QString::fromStdString(CLIENT_NAME); -} - QString ClientModel::formatClientStartupTime() const { return QDateTime::fromTime_t(nClientStartupTime).toString(); diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 439680431963e..99fd574b9e14d 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -73,7 +73,6 @@ class ClientModel : public QObject QString formatFullVersion() const; QString formatSubVersion() const; bool isReleaseVersion() const; - QString clientName() const; QString formatClientStartupTime() const; QString dataDir() const; diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui index c17efcf1b367a..9dc641979e084 100644 --- a/src/qt/forms/debugwindow.ui +++ b/src/qt/forms/debugwindow.ui @@ -41,36 +41,13 @@ - - - Client name - - - - - - - IBeamCursor - - - N/A - - - Qt::PlainText - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - Client version - + IBeamCursor @@ -86,7 +63,7 @@ - + User Agent @@ -96,7 +73,7 @@ - + IBeamCursor @@ -112,7 +89,7 @@ - + Using BerkeleyDB version @@ -122,7 +99,7 @@ - + IBeamCursor @@ -138,14 +115,14 @@ - + Datadir - + IBeamCursor @@ -164,14 +141,14 @@ - + Startup time - + IBeamCursor @@ -187,7 +164,7 @@ - + @@ -200,14 +177,14 @@ - + Name - + IBeamCursor @@ -223,14 +200,14 @@ - + Number of connections - + IBeamCursor @@ -246,7 +223,7 @@ - + @@ -259,14 +236,14 @@ - + Current number of blocks - + IBeamCursor @@ -282,14 +259,14 @@ - + Last block time - + IBeamCursor @@ -305,7 +282,7 @@ - + @@ -318,14 +295,14 @@ - + Current number of transactions - + IBeamCursor @@ -341,14 +318,14 @@ - + Memory usage - + IBeamCursor @@ -364,7 +341,7 @@ - + 3 @@ -404,7 +381,7 @@ - + Qt::Vertical diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 11f3e49a06d9b..650ff8b00db84 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -451,7 +451,6 @@ void RPCConsole::setClientModel(ClientModel *model) // Provide initial values ui->clientVersion->setText(model->formatFullVersion()); ui->clientUserAgent->setText(model->formatSubVersion()); - ui->clientName->setText(model->clientName()); ui->dataDir->setText(model->dataDir()); ui->startupTime->setText(model->formatClientStartupTime()); ui->networkName->setText(QString::fromStdString(Params().NetworkIDString())); From 0ce8e99ec8ac0d2a60b577537bf0db747bb8ec50 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 29 Jun 2016 11:01:29 +0200 Subject: [PATCH 0586/1802] windows: Add testnet link to installer --- share/setup.nsi.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/share/setup.nsi.in b/share/setup.nsi.in index c062f96a3059c..a3294a9f66621 100644 --- a/share/setup.nsi.in +++ b/share/setup.nsi.in @@ -92,6 +92,7 @@ Section -post SEC0001 !insertmacro MUI_STARTMENU_WRITE_BEGIN Application CreateDirectory $SMPROGRAMS\$StartMenuGroup CreateShortcut "$SMPROGRAMS\$StartMenuGroup\$(^Name).lnk" $INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@ + CreateShortcut "$SMPROGRAMS\$StartMenuGroup\@PACKAGE_NAME@ (testnet, @WINDOWS_BITS@-bit).lnk" "$INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@" "-testnet" CreateShortcut "$SMPROGRAMS\$StartMenuGroup\Uninstall $(^Name).lnk" $INSTDIR\uninstall.exe !insertmacro MUI_STARTMENU_WRITE_END WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayName "$(^Name)" @@ -135,6 +136,7 @@ Section -un.post UNSEC0001 DeleteRegKey HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\Uninstall $(^Name).lnk" Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\$(^Name).lnk" + Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\@PACKAGE_NAME@ (testnet, @WINDOWS_BITS@-bit).lnk" Delete /REBOOTOK "$SMSTARTUP\Bitcoin.lnk" Delete /REBOOTOK $INSTDIR\uninstall.exe Delete /REBOOTOK $INSTDIR\debug.log From 4f44cb616d98a0e17ae0599e5a58f50f3be2910b Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 29 Jun 2016 17:29:29 +0200 Subject: [PATCH 0587/1802] qt: Network-specific example address Generate an (invalid) example address for in the bitcoin address widgets, based on the network prefix, instead of hardcoding a mainnet address. - `1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L` for mainnet (same as now) - `n2wxQmfexkjwEPgdD6iJA7T7RtzkmHxhFc` for testnet --- src/qt/guiutil.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 4327de9b0c86d..947a4c6821d84 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -107,6 +107,23 @@ QFont fixedPitchFont() #endif } +// Just some dummy data to generate an convincing random-looking (but consistent) address +static const uint8_t dummydata[] = {0xeb,0x15,0x23,0x1d,0xfc,0xeb,0x60,0x92,0x58,0x86,0xb6,0x7d,0x06,0x52,0x99,0x92,0x59,0x15,0xae,0xb1,0x72,0xc0,0x66,0x47}; + +// Generate a dummy address with invalid CRC, starting with the network prefix. +static std::string DummyAddress(const CChainParams ¶ms) +{ + std::vector sourcedata = params.Base58Prefix(CChainParams::PUBKEY_ADDRESS); + sourcedata.insert(sourcedata.end(), dummydata, dummydata + sizeof(dummydata)); + for(int i=0; i<256; ++i) { // Try every trailing byte + std::string s = EncodeBase58(begin_ptr(sourcedata), end_ptr(sourcedata)); + if (!CBitcoinAddress(s).IsValid()) + return s; + sourcedata[sourcedata.size()-1] += 1; + } + return ""; +} + void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent) { parent->setFocusProxy(widget); @@ -115,7 +132,8 @@ void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent) #if QT_VERSION >= 0x040700 // We don't want translators to use own addresses in translations // and this is the only place, where this address is supplied. - widget->setPlaceholderText(QObject::tr("Enter a Bitcoin address (e.g. %1)").arg("1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L")); + widget->setPlaceholderText(QObject::tr("Enter a Bitcoin address (e.g. %1)").arg( + QString::fromStdString(DummyAddress(Params())))); #endif widget->setValidator(new BitcoinAddressEntryValidator(parent)); widget->setCheckValidator(new BitcoinAddressCheckValidator(parent)); From 975a41dcc259c966e1ab952b3681dda2f7b99009 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 29 Jun 2016 13:06:28 +0200 Subject: [PATCH 0588/1802] windows: Add testnet icon for testnet link Overhauled testnet icon by Jonas Schnelli --- share/setup.nsi.in | 2 +- src/Makefile.qt.include | 1 + src/qt/res/bitcoin-qt-res.rc | 1 + src/qt/res/icons/bitcoin_testnet.ico | Bin 0 -> 57251 bytes 4 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 src/qt/res/icons/bitcoin_testnet.ico diff --git a/share/setup.nsi.in b/share/setup.nsi.in index a3294a9f66621..dd42085a27609 100644 --- a/share/setup.nsi.in +++ b/share/setup.nsi.in @@ -92,7 +92,7 @@ Section -post SEC0001 !insertmacro MUI_STARTMENU_WRITE_BEGIN Application CreateDirectory $SMPROGRAMS\$StartMenuGroup CreateShortcut "$SMPROGRAMS\$StartMenuGroup\$(^Name).lnk" $INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@ - CreateShortcut "$SMPROGRAMS\$StartMenuGroup\@PACKAGE_NAME@ (testnet, @WINDOWS_BITS@-bit).lnk" "$INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@" "-testnet" + CreateShortcut "$SMPROGRAMS\$StartMenuGroup\@PACKAGE_NAME@ (testnet, @WINDOWS_BITS@-bit).lnk" "$INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@" "-testnet" "$INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@" 1 CreateShortcut "$SMPROGRAMS\$StartMenuGroup\Uninstall $(^Name).lnk" $INSTDIR\uninstall.exe !insertmacro MUI_STARTMENU_WRITE_END WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayName "$(^Name)" diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 36a21dd06fec1..ca2c7b2eb0d83 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -231,6 +231,7 @@ RES_ICONS = \ qt/res/icons/about.png \ qt/res/icons/about_qt.png \ qt/res/icons/bitcoin.ico \ + qt/res/icons/bitcoin_testnet.ico \ qt/res/icons/bitcoin.png \ qt/res/icons/chevron.png \ qt/res/icons/clock1.png \ diff --git a/src/qt/res/bitcoin-qt-res.rc b/src/qt/res/bitcoin-qt-res.rc index 19c3d5d97d656..94ae2564771fd 100644 --- a/src/qt/res/bitcoin-qt-res.rc +++ b/src/qt/res/bitcoin-qt-res.rc @@ -1,4 +1,5 @@ IDI_ICON1 ICON DISCARDABLE "icons/bitcoin.ico" +IDI_ICON2 ICON DISCARDABLE "icons/bitcoin_testnet.ico" #include // needed for VERSIONINFO #include "../../clientversion.h" // holds the needed client version information diff --git a/src/qt/res/icons/bitcoin_testnet.ico b/src/qt/res/icons/bitcoin_testnet.ico new file mode 100644 index 0000000000000000000000000000000000000000..909194ecd2e10985bbca35c3cd26fd1adb4730b8 GIT binary patch literal 57251 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 N250BL5H*Z+s*3%&l;+rD=4 z$=N?Xmt@->@=D-Q5g?xZ!aPkr`biW3o;rjB@MjAAVZZ9zf|@F~;{dsmb2E;}O5Uv! zNNP99BCTCI^UZ}1na{}kRImEkRqN3dIj97>s=iqgTNkCuhtDIu>H4AV09L2qYE8a% z3V|ICxRx-N1Y1!^vI3Zww0RESwuRV_Z_An4d33LS=&I6ma=5 z$#HCK8scaXARc37H$<72{loKx;-ml32kUR>yF_>*_=!!h*$}=qOn0gPNRSn%Kd`Q_ zRoCFSRzD3F0?`U6$RZtoI_Rt`S_;^_t-@rD>GT=j&Q}m83Ayw+%+44HLIinvkR}8u z6e3#&`5=h6{=dE~=D)oBl52l11CU4gK%fIhaM0)aA0Pq1A?V6e)Go^p+iUA%8`L*S zEo8;EQxzuY%e@W#@?aDD#nKJScY2O?(XoyA%2HKcLkAwXRAZh*ACrgVjh$GQRDN;X z0uEpdaYK;2A5aMG$^ZaB07*naRA8I1*@VmJyd&;S4|J3tnOIr6up))~k!Qt)Ahm;| zdjS}*hU>Mi`;c%`%5kGXw695v;^6)9_2x~lM^(YUO z3Fxp4X{ubvdkyizQG5XiZGv(moiIPkwe!I{9NR=6md#1I!jYCGfbCb(VjO%3FZfr7 z{iJA5N$)U?+Kn`}+h?5kJ6Za~5;Gg4{U?)Nwl^hjjg7${W3$uRI#mEsk2O~$8-S}Y z&`Ch+l!12nEL{Q*`C~y4oMZM^9-=Vm*|LahX9ci~^;sU}to5O^Oqg!_jf2u%9;s+mR!TLWIe5qRnC;|d`15Yt92@>!rf3__0!J%Jl z8+|OKQD$N>{fp%>y*|G(y)m|Irn;;lZGs*?Eu7KJaecfQc{pwe(+WV?ItsIm3&U2q zAq{O>XijCMAYY9Ed(8(}?WCDqwTc9_vQ?M&_sD0SS0w=pwNJ%akWW^gvo)6i$d54i zv2&Xh2+~Z7W8I|7yzt{TM#~HpaFcLykv zWu;rSM#8C!-nw#iI+I!kp(l7It*wI$?Pw*Xp?(Tpb9iE9F_2A?1+9tJV3-!xAEw*# zVP2*I_%Zkq2~dgft-}W346XlJmjYabWPk4y^7g!Au3RhWtV!@QAN@p7MnJK`P7t9S zts^Zfc>&OBspiItqwdPe8{7uDR|SvlqHT5wz&bniE$|WM?2ir31M)^=j0MNT^4H1= zh*cPu0AxfILMvzKw#qZ-@oBf@g10SMC-uhI?1qPK6aY1h`m1*I>-GO`Dw|4P4l2tM zSSoNBEEz!E1dImGZU}~DNdtb{wCG9$6^rJNW<8W+*;t4`PlQtQNqVOa0tG=%*Rt~b z|M{``Z_VURX@&XFKU{YM_@&W`8$CU$z#K0XUAZJLZ;>^+_E%IGZLmr}1s?5=fUVgg zg@CXHgaTBa2P+pVZftB!71|Becj;@q`20RCfT+5zJ*^`GKY)*;QmeYXJ&&tWh4n_B z=-Wyd2OmNV<)C9sD*%~Ao@fQ&)G9ullLo?YVY-iW~5n%Qqa}Z<>W?cpmU;6Qo^nhe}SOMXzK>DD`0oA2I z4NtiFx3E2P761ggCLk=-`s4$k)4Ttlbwel!eky=hm*3_tE?@8V zSDttK-Lvjc`bFI|E2rhMnM?t+Jg9h39(||%3BZdIKu_ZjZ35qN4a!>+5=StWD`H`k z>oW6ypL*9fCjkP-|*q61enIURF2Y-B_wUadnR=aaXGH0p-kA-&Vv1mcA^#)@5`4eSHAFUHen1b=xkCHNlU*;_MIbkIF5^ zFZRkua>Po(!YnOQcqoq{SlJ)&Id&Q+GQ-Kk=3%%gFC&dVS-QzOvq2e`+(3F&M3kaV zf6}_TQ2-zY!b)7O04!+;#H96foq+?{4X{v&R}|vQc*3NU{!yVI9fF@r0iWLkg<*nL zXFX9Y4Z00LQ3)Y0g-rdZUeeOSEq<_Djt#)I)$J~m_YVLOC@qRi8V!KaQ2`MAIEMlN zknDlB6lw*xq_)(pt8ejus|uv#8-aL*7}|ns?R?`Cp7Y0DkoZO)Xr?osE@Dqy+39JC2VGQARWlh%hL763L0@!#j0NO=_2edJtXq||Q zYG<9XLWz_GDnT0V|1Z=A+|v4*L<<1dvO(9xel#;$+-(oB(zi zJM14(UeqEmdt8`AFqUu=l!zrd$6X$6}~8w2df`ImLpJk4xhBGVxfts`wK7z6ce}(-rS84UeuZ7SQqk?t7W&TynRO3 z|EM#p8(@S(od^?Llld%TeS}G0`&HTrnh0CaGtTBk*~uJuf`d=++gTs?7T~yl!{_zh zhHBlviVi#XT(h$df|Neulav6`3GBG6beUR_33TH;k@DcVRS=AuZQqZ9m}K5j=;%*c zeY51Y&Q5|2KU?bq5b*h^*>nUV>mY!5ZhZ)iek=sQhZPVh1dWG=mtn?W~}NGBf_{7?V{KKv(E+~ba9Uy{u75>>eci2Y9`kOV}l1W*rUfMpQ}$14F` zLhAU*)gUUDB-*~@{Qagf@_jTkso90+&8g8@rwSmcaI>T*<(Q$kPzkgpE8ve^6xKnF zELil41*KI2EXVY&>XpK_$05iB3g}u|pkI>>O054^SGLaB`riTxb@JTukrZY=TZVD; zk!Bs~wDOUcX||jVleYBSt|hP zc%iKVTTl;PATLP{?IEvB59!Z`f)IZ5CV`Dgd!(AV`| ziegPR{}QavZma~AKlG6X$2#fTIL$DFKb9|q34YA@-0%bV zag3Em+*2#Q?w;%Wj$Vxzmydwp*?&0B=HX1NX##2VcT$=bmLHqO@nf3b^YN1iWhhQF z0ZRkXb8Q94cs1V1ZusgXIAsN(?d+t68OmdUn?zF6Bb}tPwcf?o$f?T!fhKPtYNRxW zVsJ--V^e7b*f@l}FbnO-qVNj9=Rz6)MY(+Af48H%@ZsW{TnEV%YSP&6Rj3))~ z!NYFSF^)cYMmfaImLq@U-J1NI`41GHagVRQ+nq=s@ZguL|NI^y_|i*Z=y2m`1(>KN zpd+4&17QN#j~|u+XtO7(a^rQWA4lnHxVZ+oR+{t!UQ@Lx57LwsfCw~dPGV_J;+g;z z)Ci%)wPE$el=F9Y!EaBmn7ERq#f<`Py50Lub%S&(JmTe>($ zy>O77S#|zW^pq=^vI3aZMztUw0+AqOcBVt9tgw0jHZBXMWu4~-nkAe4kShkz_7!2+sNBdgn>y$%l%tkrnHb27XyJ1y5Z3L-ArfvW zOZplw0;T4p)LW73|9Jd&y6buV0am>KF9a7sMjD;?1V3nE_Q!Fw@RBRlihcYi;RsND3l|T{@L$IQJ7^jv6Ol)HTXg=H=1ZyOr+K@&P zUo#npeiS$5nRvt-=_59<%_U01gej;6DJ8k|*RaOUa)XOx)XFl+SmccEf!K-9C9y2o%CV zd4*eATz{mal;E_s!0JeNj#TuZ}105WfS6=5fja{bJzzaPO zxLhsgGE%qhJP1U#U7S&&cl)hES{giDjUQNzSXH5Fn6nc!8!| zj1+~CmN)9kbAVzYqz4|5J4$-os?n`(<=7Ute0-D3r+XCq;M+drV-0leak zWn`ojNSBr*+JQE}bwXD&PV-0W77Iw8%04BeP&x4l$~KJiMAxYTu*8+HG-ep;7G z{r8?G&pR(UCUkbRj)M{asNob8;wKF%O+wAs;s=T)bV}a>FRBaqP#-=3lC=IuIst)j zCl2%gd>*g>j>+49@sSL)k?m|p3;l#YJn9SZmr`Tim&*&2>OM3`v^hmL9Rp}h4-Knm%iyrqqE(m;4t9pqWw z!X|aF!|8WaZ9=o!mIHCEpi-=bTBmKn*+_)oTGvkCRUn}Rf&O9b9~5Yn{u*)ZD7BS`@i3I&H_Lu$Lb{pio? z)04P@0^oUY`n`>qCd^@6o`Y!@ID$0^s2qEiL!U8@KFF!u1RH|3nk3ro(rwyw!qxHm z2`L|Avm097Dge^1mrhj=;ly?j6Bmk4kT&rnGYDpBDgp>hD@QA!2}DK-gyonIFd4m+ApyNU?D&uyx8}E zyLa{H+>`zP=tjp!)DnO-083z|m4LMb*0~GZ8&3SBUfsZ}$gE?(BMu zry@9F#zHQ}{R zC?BJM$Q#SpzF-=Bl#R>d9Ew2xaQiJ349=kl9vi&JeSP)s>arkQ4uBsVojO_p^l1%1 z0azt)e)&pw`Pi+lSR0L%8vqx|A;21M&Ph65D=Pr$Aq|$XX{sC|a>%b1L9`?Z6@e{3 zn_-Mc74LJy&^0?^wmCL9YxGW#U``VWkDsiZQb92p7h;eg4S8!CJn04BTMfXnZPp54 z9Q}}{J%?hU5F#Gu0LA*?{(lM%eM_TVSb-SwmcppfjLt_hkGcJw77Eg1SKi zicHHxp~;>Hp1+4OK>a7>ZM^ra{vG#1{(<<3Jz4_f3Hfkz;-~=NQweZSfQsOi!*6$k z^%eekfXKq35>OButA|UycHnNumo0~I*a{tEksTo55E65Q|o`_Uw}oR!9UXTq6cgQxK=_*o=Jn}$WIX3K5bG?kwU=Jcu)vv?>Coz zUX;N1;!VM+ECt8|>u;$9as~Iw6Yq$>1k7^Q=h#^VY}0L+c@f7j_X2F34|}D~eDI+J z!W)G`kTXAMz=i2Pb_&0+bZY7P(T9r%r8M!`G5AqqHwu6pY6Z`I`NTdEn6X5GXU+xU zTVYmEa328tMPVICIc0n3YZfzuF`j-C?dYmNoMwOsQ1sRZXKekCcJKiBVV)o62S5ds zaCU!#JZS>bFuNn409rC?G(d;;;4e;#0I&TP6=qpJlADpIQU7V#r`?|H;}iA*z+1Pj zl@j3P$E{=6xaF0Na+`4DN;G#nLa?!J#wRTUn8v*DtrD>DiDB#uBy2n;=AEHPj=e1X zjy(N^VeH4vx&p8j)L;BRCr`^hz=5RBo1r##MaBXV1yz7MpwN_0g}qUzDXkGbAr#gf zX27Grc>mw}SzQ00lJDbHBS0uW0Cs{Sc$ox2!c2}baXX|e1X}Y_(MT$kMUx_sG%O0> z@UfGBSpGZiRP}h%r9lcR>+95~65v%5_*4M!FCMvGpA%?B4{`|_NkC3g0;H29&x})= zpo^I|nmXx+mnUazmM3EgzV>Z7b);8~asn2t|9SaOg;RtY4&iQ`f;L$HA20Z) z=P={4ZqQ`A5w`I-hl{NQD2(V(!2;j|hj=)zDjMlH$1TO!AGm+;kK<<&z>D$|DUpEO zq^Il`_Lbci*f_dV9vJG^HlcnBXcN)MvSA#7%yakzYGPW8abaC{9|^RmSP%|fNFVjG z?l5mB=eoR+_Q@n{&3{{zY}&X9;Z79*3X&jvJ*4t|({0EEj;0X-L1^cY&UGQz?8qN$ zaXszJf~XwRNQUjiIrGEEWk)>4x4ZC&KGDZ}0;m9(pL9C)E%<2-K#4A? zu5!!d!zShEk|5im{K8T(?Mku&+SMO|6?rGb3HZ2dv}sTR9MkClyd8gWnuvR4w1yi$ zVoaKFoUL7;8wCJ5wxXKc3m`Y0FDz#TbTZBeRvk#}1wd$|Q`tzCSD})Vcs6H(_)IfV zO+ln%{ofD`I$j{00A%Wc)sv2@!f%>la${SZ5bq(s0e65!Czav(2tq$7CV3+ZH?N2 zG1GA~79R2@&DIvkF};KUfK8iCCl8?wpA$)|wsuNCp~?wS?AOwX+B1@f4hY3|LYbt9 zZWI73i2afMWmLYPT?kML2AHOBA)A^Z8(CS?Lr*uN7y=+Ps@hjzRXiirhnK^wp=G+^iO!e8tBJ+4WvE*3-zn=i+G13 zj}>+Vezp&Fa*PmeH&erUNU|VMCwQV2z|CaPqjEu?hZb_E1lrXNTCJS+saPQ+d#le% zo*0uR+^T3(e5VS)OGHr7!S9SdZiS*%1`kuUK)>9fbOrjCcRd9t4oeEQQ!f;a`NgCprhOFpCdms(~1XzaCvLPu;0`SOk zwk+~a)v?du_sDw)3%iWrEmF6iqmwAyOpD;5cq)- zu=FjxX@x;s+}^K`JSTJ@&^V|FK)Nx&IBVfLeHzdf2Vt%7n;+W0>++vic0@*DrOhzk zVRU#Wnw3HsKOrdPF!MuL)SP1%%K2Dn)LnP{-R`o{o7~~v7u>%5lWt%3Np~c-%Z;VS zT`D7119qxm;>(6uN&th|8Mn(`P`$=olD<|I0G9w19p%#azyP z4xQc69%+yTJ@QHmwT#TIF$=8(mHotwzC6!7@OcK{B=u?b;X*{*}u}>bK@+Ck}>qY@kyU<5>*Qz6_XEQ?!O97x^p%TDA zS`BW~(V-YTuHjIgPG3tUvv{uB>#iuh-t`s+-O|)bcTx3~POgEuQ{^M>Kj`n)*@3g4`+*ORv+gDtPJR^mzRR zDWfpdfxsz@n z@Ckmd|HtIR-tA0H4`e^%`yp)9mNaHQe;|k|9BL+%ACuUjb(4jU~^NLvqfzDP7?iJ;?#LuYX zzI1{ZbT}aJ@ipC*sdY*od1&&}x8*_}IypxjH2)Dk-Xqul#ps5^IohXw)EWw>Z?~@j z%0g!?lb_{%jwoM(U?%~eb<|`U#v6&3%j?eBPAUPd-x8l@7;QY6Iiznk;tf!iWC;FH z(UE7C3C|I4LEkPP0D&a}w){XxmjF5=iZvvTyii$br2JSVfHb&}PmK(I&~_o}PQO%n zP>XmaKt&MbZhzXX0yZFKK(inD8Ao8){F8-QhxHHlJg>zlz(@mav`y=X z+Kc#DxFA2O$Gy@(TIfiR@$G=mJasWk>y@HW21)L-imX^8NH~-Ut7k0dV>Hc)y`Dw4?s^=#o2QRE0U_s|<19dsz z!GX(t*Ou;5)1Qy0(gJ{h!=aq@^+bLMa{A2AbLQ*BXB{>#K#3cG;3$lso#dEq(?Xhw zU@&WZmQBouO{sE8-gl69=ht>l_~1z^zDTp3KY>r_Z^Vt|hDGWjhB5{LpJ98MkM)G- zi0^d9=gf_s)_s(SsNaVWnb0L<6gi1UT9agJN=DnOMfaT907NHvA@n(IxT$P-(v1Q@ zSrE2|DuMDz_dsE#yCWpN5Y8zG))K(rdoAsOgR~?e8!wORLnm9@&Uo$5bv!Kq2sX>o zx9zrICkW`mwF{gvhJ<<;+x zl_mRu{Ibq&e6|HX_dej`AtYEooI&GuM#Mc>A)*b(IJOy}=fPaegL8yIAGGx^q5tB1 zq3B~NDfyuY(0)1vFi)o7vk%4&HLd@NNiP6h(CyX&0BKv9DuILF9{cvvix%cSK&!ss z;D+fsSTcB}@|b==g%OJoh&~{)+Cn=6;GvR|ifi>n%y3x^5kue!Ync=e; zd53;l-r6hoA=EQoczJ1)Kq3!lzjYSyj1Ti5-U1Ea$CZzNz4%Ktj)g9G351B9k?JN|gqm%WPUzz=1Q+lf_r2FET9fHhbuA9Jm2`X46uPOZ- zcWLD&x3BW7+v}cm`_s?55&5D{IX&ii&WLE?%h9+=39}G(|IKW~Hgp1hE5HCDMjv-L z7E47}sP(xwjepRs$!>1C-@z`ElImss?R*vbNC6Q1xcqsdAa6g8u6~d=3v$x5ah(7k z`6=X_x3!!CUZ#0~T$}>l_!=32U*nKRmtQ<<_AP%lB}oa;{FjIDUijBvJ+e#k#~73_ z*oLF;&nEfpRspaARKi1RqtO7+Ac#6F2@`ReYmM<(olIfwT>n zs&HExorF;j4k!VD3$yL&)F!vgt#ubwUgatR$Rp!><))-(-J#SjcO?6wzP76l;gtik zRa%q+tOU~1dmW^5S_8?_aD3r-Tjk~M#_GG>^4ywuqm)agxQF<(n7eLl<=@ED1Sr_t;v=ID>d4wK856}|imiB}&6haH&YrVi|0Li4f zL%K;gVm}m*)V?YCr@j71ol{W&DAxpjIj^34u_Owh_XmfKyO$4o6>4X7~rRQ8yjW0Xl$ly*zZZrn=elJYI9h z+&*_Ab9?PZ+1;38jK=miB78oN6baBh*FlP*TR^N0Q2s&otpTsqQdStMb|pQvIo2 zWt#s`0>C1e3e-$UHTirx3ILVzs6O$@;d|Fy)7!T3$t=umEIQXJfv|Q6S+-tqFF*Ze z=}|x9LFn*M4+S|CZVEYl6(AwZ{Pe@Rx;eKrtO6h}un53=c&w|5La3eRe2|nx1dh~ ze>ZKkc?o*>1U|+A$G)D&t|UPi0E(v5@s??XllIalgbTSpdx5u|E|BfbNMcB{K5lADlRP?MGKX zoE?yBW@nJYz*sAwk}kO|^()-+k@H-&#|s?6PhlkJ-~*WS5l%XE@X%?J4o6>4y8K~T z)(P4O10>|HmCroAvSwc`w=W|f^MVZxN3$7be<(_9D8gxdSU!lNK^O$OcyL;X%sF6G(QL#*9yQ%^_yZE zY*p6g!}`A}8?NP3_3ym&cc<}Do=^cGyXr4nZnE%H6aXuNs^bA>s`7q-uMBO^oly$F zH>RNka?+H=f3xZy9{+R}w?RT&@2T(2_^ZUBM+Qurz8q2MzVzL21ig(Xmpi<(^jm)n28EYTtO0sOAP5Asu0 z04NK`ilGRqPkwgzZ(jMUD?g+u3-|{bx79KL=Ko0cgnMH7*W3&4JMyXQf?HBq?ba19 zcI!kTEH7_zgX1eF%!C95fe@Y}o@orzhrlD;sbgOFEDN8G01ADihjA=NpLyW39)_s^ z5RZfB^qJ3=L)=sx`3#l7Geh6>H$O>px%t-)_^8{0n!N=2ahFHtzRgFTlYrlD#!jL^ zTJ+nMXCCY8*m(2bJ^JzEe=BL6c!@tY%NFY>+_}^>lS4Tia*auqNM3wA5!Cyh!`r`@ z8%(`S!VBJoN&rg%{ONn$#K)$Xe6G@8N|V-PDkCbx2YiyY^yYtSAt`iVqFsW5Er8(TIZuoY}V^6Z>coGN#I9nD*z|ePin2oFukoWaIeS< z_{Wb|zx9U~Jb#zu#rx2Ua^M?jcq1?^0tt5KrfLDOPvKJ=sTFW~clocEU79~56hPQj z7(g^awz@S5b^>}hRl`d@pbGp)Ge@$=^&R+yez`|L*2qiC>;C`tz68pyqdfC=zwXzI zcFWr3MV2uh8|MH4%yNvu7;M8p0wg}fOeP#~;0zOB2+lbSL!2;~jYB*nz)6@K6O1vN zfg}j*$k>7y@B-M#whWeRS^LsbOKPcG>gBETegD1RegC`t-s_gs%j@o2@7z~)Yp=iR z`~SbH?yVav14CGzyC_(iJHIAF@N;D`3E2V~2fy4_fiw8?>FM@)dT=vq-OFxNobr{; zxN^&Glzu#6tcNa1elh_uf-Ot#Gw_F?4*Q7tdf>@TX3pL;2`5!wqn0Ya=Jw2n_geIW zT?_bQ0a)eMYUfyKYo+miPW}Hr{B61on>E*^mic7ka-S&!Q06RHOu#C(<@0^tzv}On z|HVWN3KcXNHajM%1=K7D1B55%7fU$d#YPU)9ss}Cg7tu68@AO>20h)+2krClEjvsZ z$Pku~thZ}PZf&r*yuvgDt&(fy+?VCmXzwp~Es&0f#y*aBGe3W?a>iqyX}U&vt9`Tu ze$D-<1q@)<;y3etY|kDHLjX$cPXbTCr$50TzpO)$(-7d1GxP}m4fGtzSOjGn|Hy75 z04K}$c{WPt<27;{T|)K0{KVfJyBBdO@jdX*82l`E!WjV80eWBcf0qBWZDIMU$rvcC z^hBCQOh93>S*{H%NRL7(AAX*S^I{rTVz_GYXq9(;7i6q3ZJlqXgw-O)#3e24ysDX4t4kKkvYlSauf=E43B^HPe@ zHq%dtK{jNBBgaZV+P&fAG31%l0M4qIvtaNUCyfRkZGR=>@ty-!7vl=tvTLPj7C+xk4s(4&ZU_=MS5?&yc?bFb$vXlP0PlhWW*^1}w2?IVdW%)Rd29R$Fj%*&elP+As z8k_7d+@8KU8wQ}#SP50i7{Cv1*t_YEPhN7ooGCA!34>4#8Lv$h(jJ|qI*CN)hV2JN zA(B*lsxD**ZO|IpgOhlBZ+H3E!Lq_d=*^-{4cO7TNG}aM8vu#@eZ^y4MO)gMLdeZ< z8O76mv)F2j+9?JgsZa3txAX>&obz=X>O5>zG^Xt(vDAH2@1r@rxz$)d1&E$?P!R30 zfU9zS8o9?xt9Ykt+cX4-D&@*Y?!V~(pZ+s^!4}>){LadZ7Conzohp!I0tI}s_&cYU z)%3+qc3`8<){|izT#9D{4U&h3gVGz$RT+;juH;%y;W>Iday!z2M~!iYpaZ_r(2qu- zpj}HU5*)k)7TN+3ZRM@JEYl|WQ{7~HwO{Sxsz1Loc<+kO*z3;Jruf=3jrxnWJ+lwm z8=VOYf!{D<(ZfHR27s=o34ZpS`q||c*TMTuv|Dt+^EG!PZ>{!A3-H)GzQT4 zitr-&#i0t@zuA8mvtuXEMB_VM15WL!8bp#TY^zEP1SLVem3Grdid{hz>Ro z8tn+MvulM@`rCkH%RvUUQw+pw1dPkC1YcadJUl*Ig-5p1T27#uKtkz0R2&F4Ec#5) znO_jBz+&Q3JcF<(w=(D|EsS>e9vrhy=E-vpNPp6qrut1i$S?xk=pTmLKN&Nnz5_nX zt_OI_7olUBM(M{&ds^YB3co-#*k5{d^Jk9kL0aO9On{XXm7UdJl-<|HXNI9uk&Zz? zLPb(QX;B&hDd{fBN4f_PkS?VeQ0eZDp*y5QVCaUSV`i8i@1OAAhx_E-dmpUN+G}0w zd#xbE#RMObKz}}Jjivr0yL zqMawR;F~W&R)74wyV2sdxbH$wjh$Q@rSg(SSx!7ON-_t%kY5S&SDIJ={V zWC6{0%EH$>;ZotJlW}l}{imx;Ijd*J(Vfqwttsk6xG!;yXH70G=&v-`y4@`Al~%cq z-+!a?2e>oWf4x{+>-Yfcdh((;DvR3VpWc(Vk4U6@Ys?Rc7yHVD+g-7;Ct@ChW3%O^ zS*)*X%3{lPK^LV_h;WDdX1%$d(CKR>SFDfWGfxSS}5Wp#J zJZ$Xfvn*{j#?I-RRVA}z^m2seLVzFb#R5x6w`f|JW>iD8A2<;L8I|_21CUI?3o`mb z5(3V24f`~f6YI(U7|3}ejlF#`tj^9xM&Tv{_y#m+uK8+YcqhTEQsLPSvSQ9ZA$O7X zoU|?a{t*(F@QNzM#BTSB1MEk&gzVII%KK?VC8{S<_)1D7ya4OraQ7!9?suyGKK9!W z$pjK8)%w6=96k=0i@i18mw|daj)p{2Ea~y-YM(d`ZG%!ixKw&ka6%rRA_@%jp=TOC zi@1k->Q*MkWaFbWqKY(sIS8pip@27)E+zcwkC`Q(Cle3w_;D3YBzB9TcIBYfIny*3 zR6hR+iM$2M2Xj~G=RT&um0OHdGq^l;KX=+H@{%k0Uggy=u50CkOzLFX_j)y7?PlRZ zadLBx1_rN=z1c(?%|An!9U8j{XCvd>ujI(jropdf&EIh#G__jn^Gjj{xIG=h>+fSR zJ~ysh?-86Zg>U;|Fe@I8NMPY77_f3ZG|>A97TDf|P3-6iaV18>-wykz*?kR44b^90 z9sJD%^lg4={^ThofbO@9+_qT=={2rjpS|jFbq*=M3k4bmWM|myOzZ~IYM~Y|J~*-8 z>U}z8tl?k()6#P3ov2Ht)GcWo%5ZN0>c|pN{$MUuVw>r7Pkd;$tY^s)U=*05@rb3}z5N4?ip zmp`b*r1juRO7gUeJdGN9H^(4KIa^#aq5!BE;s6EyggDLHoz8_4qAkDe!t8PUX1rc^ zq)#y`1y+qvrgF4hUmX*YQ3NLAn{Hkv<1*D%JaT)A) zAm2OerNvTt6vSoAfuq<-=P#8ZXg+Q1#YxD9_goDCc3y+8T z7E#ct`%QmIPv7)B5KEndUkp$(NK8^en9d0%(;Qfa!0669*+^)&#w)sHuQxY?W=l@p1tV3<)_8h0`isH$hcd$@|Fr8p=?_!+7{Nm{zXrU#P8Gh| z3;wIUZF)ry%DT*h6!6p*txs|6-kMVxHp-h>IxzAlm@%eJK)gAp{enzRKPQVwl0W3k z0`2I6;d;sN)`AO89d+`GJ4$&6ma5mktbfx%pDScgQBw{CqVigfq14E~X}@vfhZxym zgcEA{8lM|EpsA^N^U}ELu3jJ{s{=O1=AIW%I{uSBv(svX-%XqM%X?sJI>0u#vpL?Z zwC^sMHnKt6X1k;{50}yTD1x~@NElk3nnJSVB*s+P#5%ragCEu zwVa&x`{f%KGKhaY`psK}Ga^5ukM}H8@+uqL9_%NvCGYzZA^5SamL%g<_kX{eu-D}) zzWDnxmnJulZWMVmNXBYJC`SQWY&xGvpqbJ5;hQKJQ#+{*F8bM@ifp} zCG(#oEXYNR_qTB}TXf#ih&z5fu!mo;=nAJCS)E*2pn1&?dn{) z6^{AsY_)U*|J;}DJKA?Uey?pVaCRD^60(pY%K;aSv~f~0x^XRU4Lir$UYZEYJhzax z_A^Y!LiPYS@Qa`jk+GD0DOL6lgqD){mBp=+V^V|x*&=k%RQRt$4>929f`h{7N+@!5 z(QKJ^h4QA=&+tS?A2>!GsG$oK2a8Yp#FE%}ISWPGB7#dXBWm8yU+Rh6`abL)B6;Lg zn}NU=_7Q0{JIN}Hn-2W+Jq7v19o;kIB|r=P(mzyv_Q_(t5FLacE;-hjn%T{*QL|8o z_s?tJ7FyYW%YWUw(UH}Q+bM8}b-h37RE)H!Gi53xc3mIl^z;3J8 zab;+>vF0ype|pl2MV`P-;Noa$n;XBNR9!|IqZDuov_iDHtgJc0VRH1dK~FBpze3N< zf?U68Y7PsgFKL#L&;JSo>eh!V_JZOf^*eTc-EX|TnV=Y-dU6xW@X59-h?icK8VAW3 zMQUnMYR0hIj_tpx-m4HoXeXpuqJSp$E*wkm2;1_Zv!*dM?xVY#_`O|9m0(-Bb#y8>96M21vJknfVKihh=5UHF&6S$rKBo6L; z?kn)>+u-+z)0I>;Qlx?L0GpkkS~~Z&haBTu{YnTX74CDy0a5sUA_q06AkAT zSM{RghyoV=E)`|yRL(3zj--4<)8VhH%z&mv7cTKKNVRG+Ki#1Xw`wo+O`mYJEr;_6 zF+nxD>giNx5S)e5^5s1hT;(E14=Vc33gycSgw2~w<6SC)?GoivyQsedYX4apFdnQZ zr~oVbUeW_3$D%az-@<8B^=#-&^3j%p?byMNBFE^MuVk7}Su75iFbz57{Bj6tr|00* zZ+$8pI23cgdECQDN3dv0`Fe8Z=PNucD(_l2B$Ube^!vy^hf&&scZbl#?|v>9Au@MF zn#pWD5f@8HCNGoZq5LOScOHlR6)!8IW&(jG^w8ax1}fX8{ldO8$s-@U^|OG@?8v-@7mwJ>opOLfKmVhcTy zyw{a)_~T@JM=8iGoAl{&&=OEwN#6;h3LkcE^f}?=KcTY>vOx%uULdtxJpXs>+qxsAg_v z$Eej_B3hvSPaC;oek->ClgIjgDG?vJj7z!cDq^_OZP$Z%BgWqj@Rb1!iF-(9@`P%7 zIhaJ5884GX5Ib z=iK?+xscr@lQ5@^y5WZJIFkp|thXZou-yY*$m@x7AxPG)EJwU0*w0#WCl>x`#W?t@ zV~})Bf7J4o`Bx(N+r^xye267T{;kL2LGMGnLDf_EC6fs+pT<4TjPm`v&Nv(w^n6CD z8rLtIcX?!35C_7%vn7!wR*rv`S`_9Qz_PTjOC@&57oS|euK+7j z+K(cvjFx3uG%j@`UwX$T=9Zyr1sit}5ii5oN;*nZIIF$m(DKjV5G7?9sk>WEF<^SU z@(3-sJTGe&e?JWfxZjb-f{z{{BM61#Q-pSucHpi8BU*fbSp(8vs#M{Bev*zkWBa5} zoc%2a%XSP`PFIikr}qDg<{GsUCAhpWDNBFWO-d`;7!ub>wsub4z13-&b8cHHhWe4U z%NADYaP!;rFL&l{k^ysVv}MTs7;{oB|Cah^0q3!e6pPCaPexu20Dv}J@x6>zjZol^ zZ`aXUB+!Qk5ejPvaOg}n=hwGX3FgIP$dd@mb!Wk4BrkYG6LaVXAI;^ zhNl(=tBvC87FNeC8~CjXF?oL6qV0~Gnquv*C!($t?kH(m6|9V0K9;9F$IH>FG~0A> z;OgaI$i6MmJ#IReIyMRP_s|$F$!qWGuv2~foe_Rn3sABF|zH;$QBPIs<{pY*hp6LiZS#)WWO6V#9|_ zsZ59{!>&FkyI6|)KIabmwfi;dSek(ylZ42w-d25vgOrt3fo?>{9L!_;s^U6S-cLFSW>h3kODS3L6p_Mx25_&Z*H>z4`sbvB6j%(>DfOZK@WPKK3( zMV%ru)7X&j=F@N-d{z*^D8cAr4pzi-X>`RmK3>C95$&MC`7TD_o#Z+1pmOeg^|^~Z zPh$9ohJ^cx9y6 z#iY5x7aB2tc*^BLo8%I2{np`XYW@T4L<0!?sZDL0v#(bn^Ekca0reUzn;uVTFo&Wq zGchUsGq%35726)39tJoB0Y|L1GJltdrpRy_X!Oc?Si7uk)G7IjPGlJEC@u@x@iw}7 zOg8m~E9=@ZgQ78$92;YWzVUyAKr@i|6K^l1+LZ*~eE8i`V>l0^mxGGl`AzbQ7DKF{ zv)k&~KM_0+BcJo%bw|r(DIzEz0F_N!Y)RjAi%5=i7L7@RSA6MHsF$vHg_N883ZcR@;ljI6BI^4ekVbn(;BnGf3KFTqta6=wB< z3&=i?pKtfUHAX`J!`^t*fvG;)wI}4{30;tLWMov7SyO9aP(0xp34^bCJC4VWFIibf zhokZELr4t!m~=wKuI=AJox@ijg!A;ioP~aH53sRMN065k!?o6O9c^#Blzyv}O%ea7WFV z7TZ$kx}nSq9P-_~yeJKTUkx3@`-&j0B-)ThhQTL)J^hiMfAs#5pU*>i z-)(qew1v90W*oPdq+LSvo9hK?DGtxKMh!m=_rYvJQg_U;zc<7_B#(0zx4-#X3$BPX zAS;Z=Y2S)NRnC?=)X@>Qw#UwJ@8BV4tRMCWbT7Qm8_kyVp+rBsExLCd(Zq13xp%&) zvu+jw)PI5&sPaHZxMsoSs2%OOvNr4cqq2)$S_f-YxFBF!*c#wAb%T7)19+NP?O>uU zE}U-HKLHi>OnHjz@oOyPA`OCW-TLeC;q?95+`$)d+YZPyZVerQmS7^<{CZ3J0rbGY z(psWyp86n2HEa@#kS%a($M(Tc6T*u3`DTErDm*@zq?7l(0jFmNVww1DHL(D%2nkeG z=mjN$aV|sd8pO46zG*7HW3Nc)mi^JGt3{`!`$$arOCS|8wCmejAkCwu8fo~MXcglH z4s*Y%RDc0|`!*e#8RQ~Hu{Rx|3~ayUnbvXcKl`Uqs(uuoY-66 z@})qUMV>w0K{XEs4;@=IV!LAb<65oGiEbbDO*;u_Ino{-~Xm~v{n-XuBW ztLTfD8PsFbRGeLbQ}f4+Y5RATx0DW=`!+m|M%e#+(nutPEd3hwGjJS`AEPze1yBI6 z{^FqYQXB8ZMt!6cB|iSS4~rX*%`cUxnL&eN^|2N)u}dU(uJ@8wIFh-z20eu6j_cR z@ZW%)b`(M5o-ixG@o^|In^uxng2i?Kx;;cBxRUec{-X5pORy>UW36EF{3VvT*D9UKj2!H{?$q zfS8EM!Ji2jy-q5Y8qBLwyRJ>OHo~FcSI9}G9N%(f+NqapJbY#pXuD48P%_*4IU;{} zn^D*Gx{~atZ`iF%21xpB@hVcskUw=mIhza-Je+6q;nsa3{8QXe2@*9KM zlnlsZCfiOGdWzVqctOXeqWj`#H??NGAAX{P&b~Ka?O46qy7#xW(;P$jlM4yr6w*ha zjvUXZEi4%M$%D!x83{;d{Quz6 zocRf@XtE5Cvz}7JED6Tczfv~dHL_m1)2O0 zbb;gRYw@=?*}`otHk98H+JPVK2m{6e>0uuQBY^X%tM`{dOgqaH%TsNon3&Nau=v2j z)IBUQIp?($;B%DUuRF+HhEOB<#?u!J?sZje%XhK4=t1sti(~F$u zX`H}J^6EmH?YGDeDM%Rz6f%h&NRka~KJ_F!vu{sCr=y~Pl{V92L*|P|)>Z(#tM6}D z9F3QbcUPN_na=OTQffQO>C&Lm`74*#lb<&^@!-E62>?X_#s-zLc-k@eQ0`^bbop~{ zoaP{tyiN~d=-8Y98|B(~2GMQ_#-FiS6A}KTC=m_7R;`i*qG1Q*|6fK-=k$9e?s)Vl0MRrv6T=UDfXd-lN6TyM2vug%{E@cwCY{!>h1!uvZz#caL z1F0+L&UEN^MQY27i;9F`J5^?#Gw5ABqB?z5;7N zVb~Pze}s5{rO>?(Si28fp0F`JH3Juo?My+uj* z0CsB?!%{-=n!EI|<#S!@3Qn%{P(q4eP?OKB>z{UA z)=ifqUbz8nwXQR(@HjnxGur9y#}Km18+hNU#K4rFjnK_PwqP1iE2e+vnBL1{;pdSW zk7&h)Bkes;S=oDyAt!p! z)Y3aM$G)7}sdqWnyieTvHDYBV5dHkIz7Wyd@SFJX`nxZV*9im7>22;c;lTJ^uMiit zx&2wyD6A2Rw2VhIKHJs&40u$fD(lHEGxppo-*j@(iwX;8{Ot)|FRmt~ReK6eOT9*# z848o-!-kj(s!nY+Hl%`9hT{A+<*9H90;DsYFW0tUFh@_=4JKT28b!NqTM}1-3FtL} zlZzESui0)*|KFeXl6ps_Pzon89k(dT7K&Fz<1+!r zr<~Wf43x}->4V=`bJM;EwKrF;G&h>}MahRFht9qn+3tDG3DW#qsS`!rC3`3+e^V*o zK&&EVG3wq86XCuPCw%}7#-W6_wBetMSbdL8>0-X|;$qbftYY-~_V35G$)yx*=Q8i& zxtV(KxqmQ>L^?4$Q|DhYJX-@H?@#$BUQ)38`+V&JaI@?1iTebB@gU>f-G`PHU$>J9 zY>lqaf@Aa>RSv?|NFQUPr~KT&6`czBq)v_zz;0KDDFvZD7<0F2fz-7n3fDW=CR0qdofSX3I|`x`nf{qjAND@ zRjWAfne44Q-{Q?vf1z<*#^46nkTI|$ow0tPpeRK+I_;hTmxXbt3CR*?UhYRUeu=el zIA0FslUhw#RMY5EexKr~H=5hA00$&a(Rzfvy83Y2R6!=b)Kq%e{voBl11~B>8N}Qh zs--y!E|zxs(-Xve&5vW6*9pF;DU9f#xT)*U$_-#u^f3qleY#cMx2PgN#}vTOhgF^u zcU6Dl*qZBabI+95$BB?hjEcx)?zL)dP^nysd|s{f=0G_ew#__-K2Q zJxJVoL}#kNB?UfysUf9Bt)15s#|&oGT>ov#MxmQ4=~^fpGpXILa>CUe<=r|GB8YmU z%D6uoc(la3a;~T@r>VG@cn9kErtEku);;i+K?quz2VD8Ka(x<9OaneBI67mjX0_I`A zw3#tCX_JHaB8up_MHU z{HIHKPqt?PMCiY6MF%*Djhg7syWRcT-Yz>4UH;_Qy)`Kxv}V6B8>tL$5pP}gz9et@ z9n+(*@y5WSF~Rb63$4#blWx+QAXQ?~XO(uHOAsSeXD^Ls0LeH>ZN25GA?AsHOyRZ` z%NH#+DwCs++Ws2mejY!kcjVs^=RNZKjS5_|f>p5K2f;iZKaBSWsj-Q*X5eCL^l&IB z)%%OiZA&zV4V+H`OC1AToUeNwY3dsq4B@<&AA4(AxG&wMsBbhQ0`UrEozMR>R`M%G z$KNqz-x;o=0;%==aaQpx-ytbf2-LG4aqZ6V?AUnZ&D=R#>VH zYLIB$&Ubxvgsw=t8u619@39!*v`?r^#+x8O7xh4vt1ND9Lsz%&;_pKJPLY2(XdVf1!C`4dzU8-S_hSQ z6+1h8_=jm;Kxj|Av-InQKC}W>%(%#XQ?kcDn*|;B$4v53-vRDBVQ5`Q>+J+8`{v@m zKvNqYq`gCB>RpzA&NFL;8!-7nzEj=ebH|7L_th7mW!N-Wg{|>!c-XjZyVx6Y^m#fU z&;Mtk0evJR+AhJ)x=q9 z&d#yHPeiB%#lb{XH-a7x@VLB7;dEhTRJH+wWV+J$2r`~DMsSAz96FIvyUyeXb!XbS zOsm&r)W0etjW!2oDGO%JVNJJCG@04{&Ia|4d+!B7{6SC91tKK4=*KLo5zgcnPn7Uc zo?A|R#@0}DUDA6E)@yn2G8$f|>1Rb-1bn4ou=*E5t21Yn-1s*n;sY1+Pum4@k zMVm(C|;Kl-d*t-w2V|WV?wt zw*AZq*7WFJf&p+YU9C}r+18~p?*W>80XJ<9A^pzxFBg0aSb(2&`LfgD_>m$iXW|RA zfzk&Kt}Mnn%fsl~4}w;uY6*{Mc5%HH!L7NH%iKtrZ$5G%ZN@i-S2T`21cihXSzYeJ}e35#T^{YvO<}#SI{*2X*+;`Q~ z`5uNN#e7#Fk3HPg30ptQp+Q&`z#%)Pe_0?l7jNiPg^GI#zVPFG!KG{U$!y!Uf3ecK zyMAaOmSVY*+Sv-NU?~{M@gX6+@Yv_yxq`Y^ect@fHZOs)7yqt4#_uG&W9hs?;RBrb z0^Hn@yIlaU;5bS3r2l6jr^1$c!AaLcV4DQIQC^h(iCK^1ZFf1!Xs+n|y>`h&ET9`n zH%}9^Juegl-N}U2v$x^+$1`wA`g{!x*m!8SiAdbe^9*T+GKqBY!0Aac0p2$E)8;zo)a&Ns8OJ%RmL+3gZ;rM-UcC;5DwXwca}a*3qW1t& zVA>Z|{YuNPGRQoj^5O;&)P+F>3N`MXs$Cudj>IRnI0p8v;MeEAJo|%k)6>x(fTY`1 z>v?N`xLFnlIS_l>TXmpuf>trtg+RT=ZM2BH$(um;tDj6!0=&*AL#2Ooq{HA@V1BUJ zGXgc{F>pQ$JVgo4{j3cThkC4gwq`U!b8WhHzcb(N`=q~7>g-_r5&{?nyDiiK)TBU$ z!kHc?j?J2aABk*{v4TGIWq7#nWu2!+UknnU{XZ$&`foWZ^NL+RW2)FSUb#xV@=klP z_|_oiDT1*Z`PnsBm;-L;5^VxKk3XSmxpHKD^&=(++__nNe3lTAPcA5N;xkmB zPW(8bOBiQtZ=(CK@ydU=AB6(=>uF2~!d#wuQ0bh%wla`H+y=GAN9v9+#y_R|ruSEj zxZqqR7%+CR9Xs|S_d%Y_eVG*Ir+t*P&+0xx@~%_8_izVr8}06xUO>5+pl#7H1m2H0{aH-$VT zf&Vzx*m5!gi`*U)dxf7KVt`N#AQuJuwX!~DVIWuUcn|6KL`;x^vT%t;>Kq`iM2_@R zsD?YHRbJwD!C>>^Q~!#&5q2*{9F5GuttlwCqvS1JkCAS+p<(KBXOo4xmo?&3Gu1h5 zEtmghuaa-m>SvuCWMDX+x>{jp;pP;@1c0WZjreWvmlIoNpecWG71<}(puI&Zv=CApG;fMgy$0z;pPj?Ik!B)Ob zF&{(%qZ(I^rv7I4q5i5S)yl5kVL@39xGJ}V|5mb{PEM8wz3ySJ*V>{zhk5HbgFy7O zN%8LKTcTWuJ>G|NjJ!KOogchuz7}5I;0OI`NOD?<+cEc+gdN*Wajha>VX_5?T-5XO zy}1x5StsZ0@(do$^xPJW5($>At9nmC$jZUl^;ci9y>0(5`4ON17ZpvaNpl8umIbMM z<6|G;8tu=M%Q*w03M>WkJPqhX4}pL(-@CkgLM{Zp0;LvbS(hkx{9(hUM2+Izvy=Yk zN^qUlO$kg=z@TrQ>JdjCe2*-W!% Date: Thu, 30 Jun 2016 11:22:31 -0400 Subject: [PATCH 0589/1802] Exclude witness transactions in addPackageTxs() pre-segwit activation --- src/miner.cpp | 13 +++++++++---- src/miner.h | 7 +++++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/miner.cpp b/src/miner.cpp index a3e29431d7552..f2ad1018b2bd0 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -236,14 +236,19 @@ bool BlockAssembler::TestPackage(uint64_t packageSize, int64_t packageSigOpsCost return true; } -// Block size and sigops have already been tested. Check that all transactions -// are final. -bool BlockAssembler::TestPackageFinalityAndSerializedSize(const CTxMemPool::setEntries& package) +// Perform transaction-level checks before adding to block: +// - transaction finality (locktime) +// - premature witness (in case segwit transactions are added to mempool before +// segwit activation) +// - serialized size (in case -blockmaxsize is in use) +bool BlockAssembler::TestPackageTransactions(const CTxMemPool::setEntries& package) { uint64_t nPotentialBlockSize = nBlockSize; // only used with fNeedSizeAccounting BOOST_FOREACH (const CTxMemPool::txiter it, package) { if (!IsFinalTx(it->GetTx(), nHeight, nLockTimeCutoff)) return false; + if (!fIncludeWitness && !it->GetTx().wit.IsNull()) + return false; if (fNeedSizeAccounting) { uint64_t nTxSize = ::GetSerializeSize(it->GetTx(), SER_NETWORK, PROTOCOL_VERSION); if (nPotentialBlockSize + nTxSize >= nBlockMaxSize) { @@ -542,7 +547,7 @@ void BlockAssembler::addPackageTxs() ancestors.insert(iter); // Test if all tx's are Final - if (!TestPackageFinalityAndSerializedSize(ancestors)) { + if (!TestPackageTransactions(ancestors)) { if (fUsingModified) { mapModifiedTx.get().erase(modit); failedTx.insert(iter); diff --git a/src/miner.h b/src/miner.h index bc4da63da074f..9fab55611e829 100644 --- a/src/miner.h +++ b/src/miner.h @@ -192,8 +192,11 @@ class BlockAssembler void onlyUnconfirmed(CTxMemPool::setEntries& testSet); /** Test if a new package would "fit" in the block */ bool TestPackage(uint64_t packageSize, int64_t packageSigOpsCost); - /** Test if a set of transactions are all final */ - bool TestPackageFinalityAndSerializedSize(const CTxMemPool::setEntries& package); + /** Perform checks on each transaction in a package: + * locktime, premature-witness, serialized size (if necessary) + * These checks should always succeed, and they're here + * only as an extra check in case of suboptimal node configuration */ + bool TestPackageTransactions(const CTxMemPool::setEntries& package); /** Return true if given transaction from mapTx has already been evaluated, * or if the transaction's cached data in mapTx is incorrect. */ bool SkipMapTxEntry(CTxMemPool::txiter it, indexed_modified_transaction_set &mapModifiedTx, CTxMemPool::setEntries &failedTx); From d2e46e1b5cf6c08829ec3bb2a923b4ba149ab3b7 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Thu, 30 Jun 2016 11:37:38 -0400 Subject: [PATCH 0590/1802] Remove addScoreTxs() --- src/miner.cpp | 60 --------------------------------------------------- src/miner.h | 6 ++---- 2 files changed, 2 insertions(+), 64 deletions(-) diff --git a/src/miner.cpp b/src/miner.cpp index f2ad1018b2bd0..eb71355e7abc0 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -338,66 +338,6 @@ void BlockAssembler::AddToBlock(CTxMemPool::txiter iter) } } -void BlockAssembler::addScoreTxs() -{ - std::priority_queue, ScoreCompare> clearedTxs; - CTxMemPool::setEntries waitSet; - CTxMemPool::indexed_transaction_set::index::type::iterator mi = mempool.mapTx.get().begin(); - CTxMemPool::txiter iter; - while (!blockFinished && (mi != mempool.mapTx.get().end() || !clearedTxs.empty())) - { - // If no txs that were previously postponed are available to try - // again, then try the next highest score tx - if (clearedTxs.empty()) { - iter = mempool.mapTx.project<0>(mi); - mi++; - } - // If a previously postponed tx is available to try again, then it - // has higher score than all untried so far txs - else { - iter = clearedTxs.top(); - clearedTxs.pop(); - } - - // If tx already in block, skip (added by addPriorityTxs) - if (inBlock.count(iter)) { - continue; - } - - // cannot accept witness transactions into a non-witness block - if (!fIncludeWitness && !iter->GetTx().wit.IsNull()) - continue; - - // If tx is dependent on other mempool txs which haven't yet been included - // then put it in the waitSet - if (isStillDependent(iter)) { - waitSet.insert(iter); - continue; - } - - // If the fee rate is below the min fee rate for mining, then we're done - // adding txs based on score (fee rate) - if (iter->GetModifiedFee() < ::minRelayTxFee.GetFee(iter->GetTxSize()) && nBlockSize >= nBlockMinSize) { - return; - } - - // If this tx fits in the block add it, otherwise keep looping - if (TestForBlock(iter)) { - AddToBlock(iter); - - // This tx was successfully added, so - // add transactions that depend on this one to the priority queue to try again - BOOST_FOREACH(CTxMemPool::txiter child, mempool.GetMemPoolChildren(iter)) - { - if (waitSet.count(child)) { - clearedTxs.push(child); - waitSet.erase(child); - } - } - } - } -} - void BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& alreadyAdded, indexed_modified_transaction_set &mapModifiedTx) { diff --git a/src/miner.h b/src/miner.h index 9fab55611e829..037639b2be841 100644 --- a/src/miner.h +++ b/src/miner.h @@ -157,7 +157,7 @@ class BlockAssembler int64_t nLockTimeCutoff; const CChainParams& chainparams; - // Variables used for addScoreTxs and addPriorityTxs + // Variables used for addPriorityTxs int lastFewTxs; bool blockFinished; @@ -174,14 +174,12 @@ class BlockAssembler void AddToBlock(CTxMemPool::txiter iter); // Methods for how to add transactions to a block. - /** Add transactions based on modified feerate */ - void addScoreTxs(); /** Add transactions based on tx "priority" */ void addPriorityTxs(); /** Add transactions based on feerate including unconfirmed ancestors */ void addPackageTxs(); - // helper function for addScoreTxs and addPriorityTxs + // helper function for addPriorityTxs /** Test if tx will still "fit" in the block */ bool TestForBlock(CTxMemPool::txiter iter); /** Test if tx still has unconfirmed parents not yet in block */ From 27362dda4d583a43ebf687ae097d2f45ba1c4c32 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Thu, 30 Jun 2016 11:41:13 -0400 Subject: [PATCH 0591/1802] Remove -blockminsize option --- src/init.cpp | 1 - src/miner.cpp | 7 +------ src/miner.h | 2 +- src/policy/policy.h | 3 +-- 4 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 5d29f14eb8821..fdf6301d2ade3 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -453,7 +453,6 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageGroup(_("Block creation options:")); strUsage += HelpMessageOpt("-blockmaxcost=", strprintf(_("Set maximum block cost (default: %d)"), DEFAULT_BLOCK_MAX_COST)); - strUsage += HelpMessageOpt("-blockminsize=", strprintf(_("Set minimum block size in bytes (default: %u)"), DEFAULT_BLOCK_MIN_SIZE)); strUsage += HelpMessageOpt("-blockmaxsize=", strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE)); strUsage += HelpMessageOpt("-blockprioritysize=", strprintf(_("Set maximum size of high-priority/low-fee transactions in bytes (default: %d)"), DEFAULT_BLOCK_PRIORITY_SIZE)); if (showDebug) diff --git a/src/miner.cpp b/src/miner.cpp index eb71355e7abc0..8153fb9f9ecdd 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -100,13 +100,8 @@ BlockAssembler::BlockAssembler(const CChainParams& _chainparams) // Limit size to between 1K and MAX_BLOCK_SERIALIZED_SIZE-1K for sanity: nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SERIALIZED_SIZE-1000), nBlockMaxSize)); - // Minimum block size you want to create; block will be filled with free transactions - // until there are no more or the block reaches this size: - nBlockMinSize = GetArg("-blockminsize", DEFAULT_BLOCK_MIN_SIZE); - nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize); - // Whether we need to account for byte usage (in addition to cost usage) - fNeedSizeAccounting = (nBlockMaxSize < MAX_BLOCK_SERIALIZED_SIZE-1000) || (nBlockMinSize > 0); + fNeedSizeAccounting = (nBlockMaxSize < MAX_BLOCK_SERIALIZED_SIZE-1000); } void BlockAssembler::resetBlock() diff --git a/src/miner.h b/src/miner.h index 037639b2be841..d16e37bb599bb 100644 --- a/src/miner.h +++ b/src/miner.h @@ -141,7 +141,7 @@ class BlockAssembler // Configuration parameters for the block size bool fIncludeWitness; - unsigned int nBlockMaxCost, nBlockMaxSize, nBlockMinSize; + unsigned int nBlockMaxCost, nBlockMaxSize; bool fNeedSizeAccounting; // Information on the current status of the block diff --git a/src/policy/policy.h b/src/policy/policy.h index fefb562ff9318..29a8cc57c20ff 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -14,9 +14,8 @@ class CCoinsViewCache; -/** Default for -blockmaxsize and -blockminsize, which control the range of sizes the mining code will create **/ +/** Default for -blockmaxsize, which controls the maximum size of block the mining code will create **/ static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 750000; -static const unsigned int DEFAULT_BLOCK_MIN_SIZE = 0; /** Default for -blockprioritysize, maximum space for zero/low-fee transactions **/ static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 0; /** Default for -blockmaxcost, which control the range of block costs the mining code will create **/ From 20f3cd75f6af8f75de943fef43b4b7769746f732 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 1 Jul 2016 13:22:52 +0200 Subject: [PATCH 0592/1802] wallet: Revert input selection post-pruning This reverts PR #4906, "Coinselection prunes extraneous inputs from ApproximateBestSubset". Apparently the previous behavior of slightly over-estimating the set of inputs was useful in cleaning up UTXOs. See also #7664, #7657, as well as 2016-07-01 discussion on #bitcoin-core-dev IRC. --- src/wallet/test/wallet_tests.cpp | 14 -------------- src/wallet/wallet.cpp | 10 ---------- 2 files changed, 24 deletions(-) diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 0a4f06ba88175..c6c5058984c00 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -349,20 +349,6 @@ BOOST_AUTO_TEST_CASE(ApproximateBestSubset) BOOST_CHECK(wallet.SelectCoinsMinConf(1003 * COIN, 1, 6, vCoins, setCoinsRet, nValueRet)); BOOST_CHECK_EQUAL(nValueRet, 1003 * COIN); BOOST_CHECK_EQUAL(setCoinsRet.size(), 2U); - - empty_wallet(); - - // Test trimming - for (int i = 0; i < 100; i++) - add_coin(10 * COIN); - for (int i = 0; i < 100; i++) - add_coin(1000 * COIN); - - BOOST_CHECK(wallet.SelectCoinsMinConf(100001 * COIN, 1, 6, vCoins, setCoinsRet, nValueRet)); - // We need all 100 larger coins and exactly one small coin. - // Superfluous small coins must be trimmed from the set: - BOOST_CHECK_EQUAL(nValueRet, 100010 * COIN); - BOOST_CHECK_EQUAL(setCoinsRet.size(), 101); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 87b85eeb72301..a0095ebd92e76 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1879,16 +1879,6 @@ static void ApproximateBestSubset(vector= nTargetValue ) - { - vfBest[i] = false; - nBest -= vValue[i].first; - } - } } bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, vector vCoins, From 33336e1aacb36607d0950d681d8e24821e64f8df Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 29 Jun 2016 23:38:33 +0200 Subject: [PATCH 0593/1802] [util] CopyrightHolders: Check for untranslated substitution Also, remove check which is always true --- src/util.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/util.cpp b/src/util.cpp index 9a9209c62140b..ee12f2b443427 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -801,11 +801,10 @@ int GetNumCores() std::string CopyrightHolders(const std::string& strPrefix) { - std::string strCopyrightHolders = strPrefix + _(COPYRIGHT_HOLDERS); - if (strCopyrightHolders.find("%s") != strCopyrightHolders.npos) { - strCopyrightHolders = strprintf(strCopyrightHolders, _(COPYRIGHT_HOLDERS_SUBSTITUTION)); - } - if (strCopyrightHolders.find("Bitcoin Core developers") == strCopyrightHolders.npos) { + std::string strCopyrightHolders = strPrefix + strprintf(_(COPYRIGHT_HOLDERS), _(COPYRIGHT_HOLDERS_SUBSTITUTION)); + + // Check for untranslated substitution to make sure Bitcoin Core copyright is not removed by accident + if (strprintf(COPYRIGHT_HOLDERS, COPYRIGHT_HOLDERS_SUBSTITUTION).find("Bitcoin Core") == std::string::npos) { strCopyrightHolders += "\n" + strPrefix + "The Bitcoin Core developers"; } return strCopyrightHolders; From ab0c35a290b8cb05b9bed0c24627bcc98bb22b2b Mon Sep 17 00:00:00 2001 From: fanquake Date: Tue, 5 Jul 2016 10:24:48 +0800 Subject: [PATCH 0594/1802] [Doc] Update bips.md for CSV softfork. --- doc/bips.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/bips.md b/doc/bips.md index 62bde20d944f4..039d5114fd9f1 100644 --- a/doc/bips.md +++ b/doc/bips.md @@ -18,11 +18,11 @@ BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.13.0**): * [`BIP 61`](https://github.com/bitcoin/bips/blob/master/bip-0061.mediawiki): The 'reject' protocol message (and the protocol version bump to 70002) was added in **v0.9.0** ([PR #3185](https://github.com/bitcoin/bitcoin/pull/3185)). * [`BIP 65`](https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki): The CHECKLOCKTIMEVERIFY softfork was merged in **v0.12.0** ([PR #6351](https://github.com/bitcoin/bitcoin/pull/6351)), and backported to **v0.11.2** and **v0.10.4**. Mempool-only CLTV was added in [PR #6124](https://github.com/bitcoin/bitcoin/pull/6124). * [`BIP 66`](https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki): The strict DER rules and associated version 3 blocks have been implemented since **v0.10.0** ([PR #5713](https://github.com/bitcoin/bitcoin/pull/5713)). -* [`BIP 68`](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki): Sequence locks have been implemented as of **v0.12.1** ([PR #7184](https://github.com/bitcoin/bitcoin/pull/7184)). +* [`BIP 68`](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki): Sequence locks have been implemented as of **v0.12.1** ([PR #7184](https://github.com/bitcoin/bitcoin/pull/7184)), and have been activated since *block 419328*. * [`BIP 70`](https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki) [`71`](https://github.com/bitcoin/bips/blob/master/bip-0071.mediawiki) [`72`](https://github.com/bitcoin/bips/blob/master/bip-0072.mediawiki): Payment Protocol support has been available in Bitcoin Core GUI since **v0.9.0** ([PR #5216](https://github.com/bitcoin/bitcoin/pull/5216)). * [`BIP 111`](https://github.com/bitcoin/bips/blob/master/bip-0111.mediawiki): `NODE_BLOOM` service bit added, and enforced for all peer versions as of **v0.13.0** ([PR #6579](https://github.com/bitcoin/bitcoin/pull/6579) and [PR #6641](https://github.com/bitcoin/bitcoin/pull/6641)). -* [`BIP 112`](https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki): The CHECKSEQUENCEVERIFY opcode has been implemented since **v0.12.1** ([PR #7524](https://github.com/bitcoin/bitcoin/pull/7524)). -* [`BIP 113`](https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki): Median time past lock-time calculations have been implemented since **v0.12.1** ([PR #6566](https://github.com/bitcoin/bitcoin/pull/6566)). +* [`BIP 112`](https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki): The CHECKSEQUENCEVERIFY opcode has been implemented since **v0.12.1** ([PR #7524](https://github.com/bitcoin/bitcoin/pull/7524)) and has been activated since *block 419328*. +* [`BIP 113`](https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki): Median time past lock-time calculations have been implemented since **v0.12.1** ([PR #6566](https://github.com/bitcoin/bitcoin/pull/6566)) and have been activated since *block 419328*. * [`BIP 125`](https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki): Opt-in full replace-by-fee signaling honoured in mempool and mining as of **v0.12.0** ([PR 6871](https://github.com/bitcoin/bitcoin/pull/6871)). * [`BIP 130`](https://github.com/bitcoin/bips/blob/master/bip-0130.mediawiki): direct headers announcement is negotiated with peer versions `>=70012` as of **v0.12.0** ([PR 6494](https://github.com/bitcoin/bitcoin/pull/6494)). * [`BIP 133`](https://github.com/bitcoin/bips/blob/master/bip-0133.mediawiki): feefilter messages are respected and sent for peer versions `>=70013` as of **v0.13.0** ([PR 7542](https://github.com/bitcoin/bitcoin/pull/7542)). From 4fbdc4365ba73e6947dd9052b28818a4a99c0d64 Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Tue, 5 Jul 2016 20:45:14 +0000 Subject: [PATCH 0595/1802] Revert "net: Avoid duplicate getheaders requests." PR #8054 This reverts commit f93c2a1b7ee912f0651ebb4c8a5eca220e434f4a. This can cause synchronization to get stuck. --- src/main.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 6cdd55e3979df..e26a73bc4b6d4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5835,13 +5835,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, return true; } - // If we already know the last header in the message, then it contains - // no new information for us. In this case, we do not request - // more headers later. This prevents multiple chains of redundant - // getheader requests from running in parallel if triggered by incoming - // blocks while the node is still in initial headers sync. - const bool hasNewHeaders = (mapBlockIndex.count(headers.back().GetHash()) == 0); - CBlockIndex *pindexLast = NULL; BOOST_FOREACH(const CBlockHeader& header, headers) { CValidationState state; @@ -5862,7 +5855,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, assert(pindexLast); UpdateBlockAvailability(pfrom->GetId(), pindexLast->GetBlockHash()); - if (nCount == MAX_HEADERS_RESULTS && hasNewHeaders) { + if (nCount == MAX_HEADERS_RESULTS) { // Headers message had its maximum size; the peer may have more headers. // TODO: optimize: if pindexLast is an ancestor of chainActive.Tip or pindexBestHeader, continue // from there instead. From c1d61fbd080bcc29589b8d467df98efb7e89d231 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Tue, 5 Jul 2016 15:50:48 -0400 Subject: [PATCH 0596/1802] Add warning if -blockminsize is used. --- contrib/devtools/check-doc.py | 2 +- src/init.cpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/contrib/devtools/check-doc.py b/contrib/devtools/check-doc.py index 06c9551cebae5..9ea0131ac3aa4 100755 --- a/contrib/devtools/check-doc.py +++ b/contrib/devtools/check-doc.py @@ -21,7 +21,7 @@ REGEX_ARG = re.compile(r'(?:map(?:Multi)?Args(?:\.count\(|\[)|Get(?:Bool)?Arg\()\"(\-[^\"]+?)\"') REGEX_DOC = re.compile(r'HelpMessageOpt\(\"(\-[^\"=]+?)(?:=|\")') # list unsupported, deprecated and duplicate args as they need no documentation -SET_DOC_OPTIONAL = set(['-rpcssl', '-benchmark', '-h', '-help', '-socks', '-tor', '-debugnet', '-whitelistalwaysrelay', '-prematurewitness', '-walletprematurewitness', '-promiscuousmempoolflags']) +SET_DOC_OPTIONAL = set(['-rpcssl', '-benchmark', '-h', '-help', '-socks', '-tor', '-debugnet', '-whitelistalwaysrelay', '-prematurewitness', '-walletprematurewitness', '-promiscuousmempoolflags', '-blockminsize']) def main(): used = check_output(CMD_GREP_ARGS, shell=True) diff --git a/src/init.cpp b/src/init.cpp index fdf6301d2ade3..7f82893286b16 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -876,6 +876,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (GetBoolArg("-whitelistalwaysrelay", false)) InitWarning(_("Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay.")); + if (mapArgs.count("-blockminsize")) + InitWarning("Unsupported argument -blockminsize ignored."); + // Checkmempool and checkblockindex default to true in regtest mode int ratio = std::min(std::max(GetArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0), 1000000); if (ratio != 0) { From 32cab91278651d07a11132b7636dc3d21144e616 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 27 Jun 2016 15:39:28 +0200 Subject: [PATCH 0597/1802] Bump `-dbcache` default to 300MiB Also cap the allocation for the leveldb-specific cache for the UTXO set to 8MiB. This avoids that the extra cache memory goes to the much less effective leveldb cache instead of our application-level cache. --- src/init.cpp | 4 ++-- src/txdb.h | 14 +++++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 5d29f14eb8821..22a6af74e026d 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1216,10 +1216,10 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) nTotalCache = std::max(nTotalCache, nMinDbCache << 20); // total cache cannot be less than nMinDbCache nTotalCache = std::min(nTotalCache, nMaxDbCache << 20); // total cache cannot be greated than nMaxDbcache int64_t nBlockTreeDBCache = nTotalCache / 8; - if (nBlockTreeDBCache > (1 << 21) && !GetBoolArg("-txindex", DEFAULT_TXINDEX)) - nBlockTreeDBCache = (1 << 21); // block tree db cache shouldn't be larger than 2 MiB + nBlockTreeDBCache = std::min(nBlockTreeDBCache, (GetBoolArg("-txindex", DEFAULT_TXINDEX) ? nMaxBlockDBAndTxIndexCache : nMaxBlockDBCache) << 20); nTotalCache -= nBlockTreeDBCache; int64_t nCoinDBCache = std::min(nTotalCache / 2, (nTotalCache / 4) + (1 << 23)); // use 25%-50% of the remainder for disk cache + nCoinDBCache = std::min(nCoinDBCache, nMaxCoinsDBCache << 20); // cap total coins db cache nTotalCache -= nCoinDBCache; nCoinCacheUsage = nTotalCache; // the rest goes to in-memory cache LogPrintf("Cache configuration:\n"); diff --git a/src/txdb.h b/src/txdb.h index ce3c39d7fec11..5b98d2792c50d 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -22,11 +22,19 @@ class CCoinsViewDBCursor; class uint256; //! -dbcache default (MiB) -static const int64_t nDefaultDbCache = 100; -//! max. -dbcache in (MiB) +static const int64_t nDefaultDbCache = 300; +//! max. -dbcache (MiB) static const int64_t nMaxDbCache = sizeof(void*) > 4 ? 16384 : 1024; -//! min. -dbcache in (MiB) +//! min. -dbcache (MiB) static const int64_t nMinDbCache = 4; +//! Max memory allocated to block tree DB specific cache, if no -txindex (MiB) +static const int64_t nMaxBlockDBCache = 2; +//! Max memory allocated to block tree DB specific cache, if -txindex (MiB) +// Unlike for the UTXO database, for the txindex scenario the leveldb cache make +// a meaningful difference: https://github.com/bitcoin/bitcoin/pull/8273#issuecomment-229601991 +static const int64_t nMaxBlockDBAndTxIndexCache = 1024; +//! Max memory allocated to coin DB specific cache (MiB) +static const int64_t nMaxCoinsDBCache = 8; struct CDiskTxPos : public CDiskBlockPos { From efd1d8339ad9a2bb7a164e7475734a90f6fa034c Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 30 Jun 2016 11:01:19 +0200 Subject: [PATCH 0598/1802] doc: Mention dbcache increase in release notes --- doc/release-notes.md | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/doc/release-notes.md b/doc/release-notes.md index 6e4f390cbcc75..df63bb53eee2d 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -41,9 +41,21 @@ report issues about Windows XP to the issue tracker. Notable changes =============== -Example item ----------------- +Database cache memory increased +-------------------------------- + +As a result of growth of the UTXO set, performance with the prior default +database cache of 100 MiB has suffered. +For this reason the default was changed to 300 MiB in this release. + +For nodes on low-memory systems, the database cache can be changed back to +100 MiB (or to another value) by either: + +- Adding `dbcache=100` in bitcoin.conf +- Changing it in the GUI under `Options → Size of database cache` +Note that the database cache setting has the most performance impact +during initial sync of a node, and when catching up after downtime. bitcoin-cli: arguments privacy -------------------------------- From b978701ba1822140452d35f037ce776fdcba0175 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 6 Jul 2016 05:25:57 +0000 Subject: [PATCH 0599/1802] qt: periodic translations update --- src/qt/bitcoinstrings.cpp | 6 -- src/qt/locale/bitcoin_bg.ts | 124 ++++++++++++++++++++++++++++++++- src/qt/locale/bitcoin_da.ts | 12 ++++ src/qt/locale/bitcoin_de.ts | 4 ++ src/qt/locale/bitcoin_en.ts | 48 +++++-------- src/qt/locale/bitcoin_en_GB.ts | 12 ++++ src/qt/locale/bitcoin_es.ts | 12 ++++ src/qt/locale/bitcoin_fr.ts | 16 +++++ src/qt/locale/bitcoin_fr_FR.ts | 24 +++++++ src/qt/locale/bitcoin_ja.ts | 12 ++++ src/qt/locale/bitcoin_ms_MY.ts | 9 +++ src/qt/locale/bitcoin_nl.ts | 2 +- src/qt/locale/bitcoin_ru.ts | 42 ++++++++++- src/qt/locale/bitcoin_ru_RU.ts | 10 ++- src/qt/locale/bitcoin_sv.ts | 12 ++++ src/qt/locale/bitcoin_th_TH.ts | 24 +++++++ src/qt/locale/bitcoin_zh_TW.ts | 12 ++++ 17 files changed, 338 insertions(+), 43 deletions(-) diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp index 7cf32cd34e8f7..9c5b1e09d4524 100644 --- a/src/qt/bitcoinstrings.cpp +++ b/src/qt/bitcoinstrings.cpp @@ -186,12 +186,6 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" "comes in the format: :$. A canonical python script is " "included in share/rpcuser. This option can be specified multiple times"), QT_TRANSLATE_NOOP("bitcoin-core", "" -"WARNING: abnormally high number of blocks generated, %d blocks received in " -"the last %d hours (%d expected)"), -QT_TRANSLATE_NOOP("bitcoin-core", "" -"WARNING: check your network connection, %d blocks received in the last %d " -"hours (%d expected)"), -QT_TRANSLATE_NOOP("bitcoin-core", "" "Warning: The network does not appear to fully agree! Some miners appear to " "be experiencing issues."), QT_TRANSLATE_NOOP("bitcoin-core", "" diff --git a/src/qt/locale/bitcoin_bg.ts b/src/qt/locale/bitcoin_bg.ts index 3bb881318288f..bd85d8c8b0e1f 100644 --- a/src/qt/locale/bitcoin_bg.ts +++ b/src/qt/locale/bitcoin_bg.ts @@ -63,6 +63,10 @@ BanTableModel + + IP/Netmask + IP/Netmask + Banned Until Със забранен достъп до @@ -106,6 +110,14 @@ Quit application Изход от приложението + + &About %1 + Относно %1 + + + Show information about %1 + Покажи информация относно %1 + About &Qt За &Qt @@ -118,6 +130,10 @@ &Options... &Опции... + + Modify configuration options for %1 + Промени настройки за %1 + &Encrypt Wallet... &Шифриране на портфейла... @@ -142,6 +158,10 @@ Open &URI... Отвори &URI... + + Reindexing blocks on disk... + Повторно индексиране на блоковете на диска... + Send coins to a Bitcoin address Изпращане към Биткоин адрес @@ -238,14 +258,46 @@ &Command-line options &Налични команди + + %n active connection(s) to Bitcoin network + %n активна връзка към Биткойн мрежата%n активни връзки към Биткойн мрежата + + + Indexing blocks on disk... + Индексиране на блокове на диска... + + + Processing blocks on disk... + Обработване на блокове на диска... + No block source available... Липсва източник на блоковете... + + Processed %n block(s) of transaction history. + Преработен %n блок от историята с транзакции.Преработени %n блокове от историята с транзакции. + + + %n hour(s) + %n час%n часа + + + %n day(s) + %n ден%n дни + + + %n week(s) + %n седмица%n седмици + %1 and %2 %1 и %2 + + %n year(s) + %n година%n години + %1 behind %1 зад @@ -274,6 +326,14 @@ Up to date Синхронизиран + + Show the %1 help message to get a list with possible Bitcoin command-line options + Покажи %1 помощно съобщение за да получиш лист с възможни Биткойн команди + + + %1 client + %1 клиент + Catching up... Зарежда блокове... @@ -414,6 +474,14 @@ &Label &Име + + The label associated with this address list entry + Етикетът свързан с това въведение в листа с адреси + + + The address associated with this address list entry. This can only be modified for sending addresses. + Адресът свързан с това въведение в листа с адреси. Това може да бъде променено само за адреси за изпращане. + &Address &Адрес @@ -452,6 +520,10 @@ (%1-bit) (%1-битов) + + About %1 + Относно %1 + Command-line options Списък с команди @@ -464,13 +536,45 @@ command-line options Списък с налични команди - + + UI Options: + Опции на интерфейс: + + + Choose data directory on startup (default: %u) + Избери директория за данни при стартирване (по подразбиране: %u) + + + Set language, for example "de_DE" (default: system locale) + Избери език, примерно "de_DE" (по подразбиране: system locale) + + + Start minimized + Стартирай минимизиран + + + Set SSL root certificates for payment request (default: -system-) + Задай SSL root сертификат за молба за изплащане (по подразбиране: -system-) + + + Show splash screen on startup (default: %u) + Покажи splash екран при стартирване (по подразбиране %u) + + + Reset all settings changed in the GUI + Нулиране на всички настройки променени в GUI + + Intro Welcome Добре дошли + + Welcome to %1. + Добре дошли в %1. + Use the default data directory Използване на директория по подразбиране @@ -483,13 +587,29 @@ Error Грешка - + + %n GB of free space available + %n GB свободно пространство на разположение%n GB свободно пространство на разположение + + + (of %n GB needed) + (%n GB е нужен)(%n GB са нужни) + + OpenURIDialog Open URI Отваряне на URI + + Open payment request from URI or file + Отвори молба за изплащане от URI или файл + + + URI: + URI: + OptionsDialog diff --git a/src/qt/locale/bitcoin_da.ts b/src/qt/locale/bitcoin_da.ts index 91903088cf5a4..fd1a4a08638aa 100644 --- a/src/qt/locale/bitcoin_da.ts +++ b/src/qt/locale/bitcoin_da.ts @@ -1878,6 +1878,10 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Dette er en foreløbig testudgivelse - brug på eget ansvar - brug ikke til udvinding eller handelsprogrammer + + Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain + Kan ikke spole databasen tilbage til en tilstand inden en splitning. Du er nødt til at downloade blokkæden igen + Use UPnP to map the listening port (default: 1 when listening and no -proxy) Brug UPnP for at konfigurere den lyttende port (standard: 1 under lytning og ingen -proxy) @@ -2098,10 +2102,18 @@ Rebuild chain state from the currently indexed blocks Genopbyg kædetilstand ud fra de aktuelt indekserede blokke + + Rewinding blocks... + Spoler blokke tilbage… + Set database cache size in megabytes (%d to %d, default: %d) Sæt cache-størrelse for database i megabytes (%d til %d; standard: %d) + + Set maximum block cost (default: %d) + Sæt maksimal blokudgift (standard: %d) + Set maximum block size in bytes (default: %d) Sæt maksimum blokstørrelse i byte (standard: %d) diff --git a/src/qt/locale/bitcoin_de.ts b/src/qt/locale/bitcoin_de.ts index 639bc3cf2f72e..77482c774bb80 100644 --- a/src/qt/locale/bitcoin_de.ts +++ b/src/qt/locale/bitcoin_de.ts @@ -1009,6 +1009,10 @@ Using BerkeleyDB version Verwendete BerkeleyDB-Version + + Datadir + Datenverz + Startup time Startzeit diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts index 9723ffa3949ba..c6f3a4013c48e 100644 --- a/src/qt/locale/bitcoin_en.ts +++ b/src/qt/locale/bitcoin_en.ts @@ -1262,13 +1262,7 @@ RPCConsole - - Client name - Client name - - - - + @@ -1305,7 +1299,7 @@ Client version - + &Information &Information @@ -1320,7 +1314,7 @@ - + Using BerkeleyDB version @@ -1399,7 +1393,7 @@ - + Select a peer to view detailed information. @@ -1550,7 +1544,7 @@ Clear console - + &Disconnect Node @@ -1588,7 +1582,7 @@ - + Welcome to the %1 RPC console. @@ -2232,7 +2226,7 @@ bitcoin-core - + Options: Options: @@ -2257,7 +2251,7 @@ Accept command line and JSON-RPC commands - + If <category> is not supplied or if <category> = 1, output all debugging information. @@ -2282,7 +2276,7 @@ - + Error: A fatal internal error occurred, see debug.log for details @@ -2312,7 +2306,7 @@ Accept connections from outside (default: 1 if no -proxy or -connect) - + Bitcoin Core Bitcoin Core @@ -2423,16 +2417,6 @@ - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) - - - - - WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) - - - - Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. @@ -2782,7 +2766,7 @@ - + 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 @@ -2867,7 +2851,7 @@ - + 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 @@ -3062,12 +3046,12 @@ Password for JSON-RPC connections - + Execute command when the best block changes (%s in cmd is replaced by block hash) Execute command when the best block changes (%s in cmd is replaced by block hash) - + Allow DNS lookups for -addnode, -seednode and -connect Allow DNS lookups for -addnode, -seednode and -connect @@ -3077,7 +3061,7 @@ Loading addresses... - + (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) @@ -3157,7 +3141,7 @@ - + Warning: Unknown block versions being mined! It's possible unknown rules are in effect diff --git a/src/qt/locale/bitcoin_en_GB.ts b/src/qt/locale/bitcoin_en_GB.ts index 89653e7aafd69..226444e9c56c6 100644 --- a/src/qt/locale/bitcoin_en_GB.ts +++ b/src/qt/locale/bitcoin_en_GB.ts @@ -1878,6 +1878,10 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications This is a pre-release test build - use at your own risk - do not use for mining or merchant applications + + Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain + Unable to rewind the database to a pre-fork state. You will need to re-download the blockchain + Use UPnP to map the listening port (default: 1 when listening and no -proxy) Use UPnP to map the listening port (default: 1 when listening and no -proxy) @@ -2098,10 +2102,18 @@ Rebuild chain state from the currently indexed blocks Rebuild chain state from the currently indexed blocks + + Rewinding blocks... + Rewinding blocks... + Set database cache size in megabytes (%d to %d, default: %d) Set database cache size in megabytes (%d to %d, default: %d) + + Set maximum block cost (default: %d) + Set maximum block cost (default: %d) + Set maximum block size in bytes (default: %d) Set maximum block size in bytes (default: %d) diff --git a/src/qt/locale/bitcoin_es.ts b/src/qt/locale/bitcoin_es.ts index fc430e86b3c04..80cbe399321d2 100644 --- a/src/qt/locale/bitcoin_es.ts +++ b/src/qt/locale/bitcoin_es.ts @@ -1877,6 +1877,10 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Esta es una versión de pre-prueba - utilícela bajo su propio riesgo. No la utilice para usos comerciales o de minería. + + Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain + No es posible reconstruir la base de datos a un estado anterior. Debe descargar de nuevo la cadena de bloques. + Use UPnP to map the listening port (default: 1 when listening and no -proxy) Utiliza UPnP para asignar el puerto de escucha (predeterminado: 1 cuando esta escuchando sin -proxy) @@ -2097,10 +2101,18 @@ Rebuild chain state from the currently indexed blocks Reconstruir el estado de la cadena a partir de los bloques indexados + + Rewinding blocks... + Verificando bloques... + Set database cache size in megabytes (%d to %d, default: %d) Asignar tamaño de cache en megabytes (entre %d y %d; predeterminado: %d) + + Set maximum block cost (default: %d) + Establecer tamaño máximo de bloque (por defecto: %d) + Set maximum block size in bytes (default: %d) Establecer tamaño máximo de bloque en bytes (predeterminado: %d) diff --git a/src/qt/locale/bitcoin_fr.ts b/src/qt/locale/bitcoin_fr.ts index fe745f99bf181..5c4f7f2b04ae2 100644 --- a/src/qt/locale/bitcoin_fr.ts +++ b/src/qt/locale/bitcoin_fr.ts @@ -1858,6 +1858,10 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Ceci est une pré-version de test - l'utiliser à vos risques et périls - ne pas l'utiliser pour miner ou pour des applications marchandes + + Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain + Impossible de rebobiner la base de données à un état préfourche. Vous devrez retélécharger la chaîne de blocs + Use UPnP to map the listening port (default: 1 when listening and no -proxy) Utiliser l'UPnP pour mapper le port d'écoute (par défaut : 1 lors de l'écoute et pas de mandataire -proxy) @@ -2070,10 +2074,18 @@ Rebuild chain state from the currently indexed blocks Reconstruire l'état de la chaîne à partir des blocs indexés actuellement + + Rewinding blocks... + Rebobinage des blocs... + Set database cache size in megabytes (%d to %d, default: %d) Définir la taille du cache de la base de données en mégaoctets (%d to %d, default: %d) + + Set maximum block cost (default: %d) + Définir le coût maximal de bloc (par défaut : %d) + Set maximum block size in bytes (default: %d) Définir la taille minimale de bloc en octets (par défaut : %d) @@ -2190,6 +2202,10 @@ This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard. Ce produit comprend des logiciels développés par le projet OpenSSL pour être utilisés dans la boîte à outils OpenSSL <https://www.openssl.org/> et un logiciel cryptographique écrit par Eric Young, ainsi qu'un logiciel UPnP écrit par Thomas Bernard. + + Use hierarchical deterministic key generation (HD) after BIP32. Only has effect during wallet creation/first start + Utiliser une génération de clef hiérarchique déterministe (HD) après BIP32. N'a d'effet que lors de la création/premier lancement du porte-monnaie + 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 Les pairs de la liste blanche ne peuvent pas être bannis DoS et leurs transactions sont toujours relayées, même si elles sont déjà dans le mempool, utile p. ex. pour une passerelle diff --git a/src/qt/locale/bitcoin_fr_FR.ts b/src/qt/locale/bitcoin_fr_FR.ts index f7fd7e6a18e50..08824e113a552 100644 --- a/src/qt/locale/bitcoin_fr_FR.ts +++ b/src/qt/locale/bitcoin_fr_FR.ts @@ -254,6 +254,10 @@ %n active connection(s) to Bitcoin network %n connexion active au réseau Bitcoin%n connexions actives au réseau Bitcoin + + Indexing blocks on disk... + Indexation des blocs sur le disque... + No block source available... Aucun bloc source disponible @@ -306,6 +310,10 @@ Up to date À jour + + %1 client + %1 client + Catching up... Rattrapage... @@ -511,6 +519,10 @@ Welcome Bienvenue + + Welcome to %1. + Bienvenue sur %1. + Use the default data directory Utiliser le répertoire par défaut @@ -641,6 +653,14 @@ &Window &Fenêtre + + &Hide the icon from the system tray. + &Cacher l'icône dans la zone de notification. + + + Hide tray icon + Cacher l'icône de la zone de notification + &Minimize to the tray instead of the taskbar &Minimiser dans la barre système au lieu de la barre des tâches @@ -1326,6 +1346,10 @@ Run in the background as a daemon and accept commands Fonctionner en arrière-plan en tant que démon et accepter les commandes + + Unable to start HTTP server. See debug log for details. + Impossible de démarrer le serveur HTTP. Voir le journal de débogage pour plus de détails. + Bitcoin Core Bitcoin Core diff --git a/src/qt/locale/bitcoin_ja.ts b/src/qt/locale/bitcoin_ja.ts index b2dae186d97c9..460a652e3750a 100644 --- a/src/qt/locale/bitcoin_ja.ts +++ b/src/qt/locale/bitcoin_ja.ts @@ -1878,6 +1878,10 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications これはリリース前のテストビルドです - 各自の責任で利用すること - 採掘や商取引に使用しないでください + + Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain + データベースをフォーク前の状態に巻き戻せませんでした。ブロックチェーンを再ダウンロードする必要があります + Use UPnP to map the listening port (default: 1 when listening and no -proxy) リスン ポートの割当に UPnP を使用 (初期値: リスン中および-proxyが指定されていない場合は1) @@ -2099,10 +2103,18 @@ Rebuild chain state from the currently indexed blocks 既にインデックスされたブロックからチェイン状態を再構築する + + Rewinding blocks... + ブロックを巻き戻しています... + Set database cache size in megabytes (%d to %d, default: %d) データベースのキャッシュサイズをメガバイトで設定 (%dから%d。初期値: %d) + + Set maximum block cost (default: %d) + 最大ブロックコストを設定 (初期値: %d) + Set maximum block size in bytes (default: %d) 最大ブロックサイズをバイトで設定 (初期値: %d) diff --git a/src/qt/locale/bitcoin_ms_MY.ts b/src/qt/locale/bitcoin_ms_MY.ts index de4c32c2df868..acfb38e418c7a 100644 --- a/src/qt/locale/bitcoin_ms_MY.ts +++ b/src/qt/locale/bitcoin_ms_MY.ts @@ -17,6 +17,15 @@ &Copy &Salin + + Delete the currently selected address from the list + Padam alamat semasa yang dipilih dari senaraiyang dipilih dari senarai + + + Export the data in the current tab to a file + +Alihkan fail data ke dalam tab semasa + &Export &Eksport diff --git a/src/qt/locale/bitcoin_nl.ts b/src/qt/locale/bitcoin_nl.ts index 3009c154e334e..2b0cded386d2c 100644 --- a/src/qt/locale/bitcoin_nl.ts +++ b/src/qt/locale/bitcoin_nl.ts @@ -870,7 +870,7 @@ 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. - De weergegeven informatie kan verouderd zijn. Uw portemonnee synchroniseert automaticsh met het Bitcoinnetwerk nadat een verbinding is gelegd, maar dit proces is nog niet voltooid. + De weergegeven informatie kan verouderd zijn. Uw portemonnee synchroniseert automatisch met het Bitcoinnetwerk nadat een verbinding is gelegd, maar dit proces is nog niet voltooid. Watch-only: diff --git a/src/qt/locale/bitcoin_ru.ts b/src/qt/locale/bitcoin_ru.ts index e2949a9482539..750ea7db650a2 100644 --- a/src/qt/locale/bitcoin_ru.ts +++ b/src/qt/locale/bitcoin_ru.ts @@ -130,6 +130,10 @@ &Options... &Параметры + + Modify configuration options for %1 + Изменить конфигурационные настройки для %1 + &Encrypt Wallet... &Зашифровать бумажник... @@ -552,7 +556,11 @@ Show splash screen on startup (default: %u) Показывать экран-заставку при запуске (по умолчанию: %u) - + + Reset all settings changed in the GUI + Сбросить все настройки, измененные в графическом интерфейсе + + Intro @@ -563,6 +571,14 @@ Welcome to %1. Добро пожаловать в %1 + + As this is the first time the program is launched, you can choose where %1 will store its data. + При первом запуске программы вы можете выбрать где %1 будет хранить свои данные. + + + %1 will download and store a copy of the Bitcoin block chain. At least %2GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. + %1 скачает и сохранит копию цепи блоков. Как минимум %2GB будут записаны в этот каталог, и со временем он будет расти. Бумажник также будет сохранен в этом каталоге. + Use the default data directory Использовать каталог данных по умолчанию @@ -617,6 +633,14 @@ &Main &Главная + + Automatically start %1 after logging in to the system. + Автоматически запускать %1 после входа в систему. + + + &Start %1 on system login + &Запускать %1 при входе в систему + Size of &database cache Размер кэша &БД @@ -753,6 +777,10 @@ &Window &Окно + + &Hide the icon from the system tray. + &Скрыть иконку из системного трея. + Hide tray icon Скрыть иконку в трее @@ -777,6 +805,10 @@ User Interface &language: &Язык интерфейса: + + The user interface language can be set here. This setting will take effect after restarting %1. + Здесь можно установить язык пользовательского интерфейса. Настройки вступят в силу после перезагрузки %1 + &Unit to show amounts in: &Отображать суммы в единицах: @@ -985,6 +1017,10 @@ Using BerkeleyDB version Используется версия BerkeleyDB + + Datadir + Каталог для данных + Startup time Время запуска @@ -1069,6 +1105,10 @@ User Agent Юзер-агент + + Open the %1 debug log file from the current data directory. This can take a few seconds for large log files. + Открыть отладочный лог-файл %1 из текущего каталога данных. Это может занять несколько секунд для больших лог-файлов. + Services Сервисы diff --git a/src/qt/locale/bitcoin_ru_RU.ts b/src/qt/locale/bitcoin_ru_RU.ts index a6f9ffccbd776..66419728e2c20 100644 --- a/src/qt/locale/bitcoin_ru_RU.ts +++ b/src/qt/locale/bitcoin_ru_RU.ts @@ -1,6 +1,10 @@ AddressBookPage + + Right-click to edit address or label + Кликните правой кнопкой мыши для редоктирования адреса или ярлыка + Create a new address Создать новый адрес @@ -40,7 +44,11 @@ AskPassphraseDialog - + + Repeat new passphrase + Повторите новый пароль + + BanTableModel diff --git a/src/qt/locale/bitcoin_sv.ts b/src/qt/locale/bitcoin_sv.ts index a637cebe2cd53..6361b5ea5ff87 100644 --- a/src/qt/locale/bitcoin_sv.ts +++ b/src/qt/locale/bitcoin_sv.ts @@ -1874,6 +1874,10 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Detta är ett förhands testbygge - använd på egen risk - använd inte för mining eller handels applikationer + + Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain + Kan inte spola tillbaka databasen till obeskärt läge. Du måste ladda ner blockkedjan igen + Use UPnP to map the listening port (default: 1 when listening and no -proxy) Använd UPnP för att mappa den lyssnande porten (förvalt: 1 när lyssning aktiverat och utan -proxy) @@ -2094,10 +2098,18 @@ Rebuild chain state from the currently indexed blocks Återskapa blockkedjans status från aktuella indexerade block + + Rewinding blocks... + Spolar tillbaka blocken... + Set database cache size in megabytes (%d to %d, default: %d) Sätt databasens cachestorlek i megabyte (%d till %d, förvalt: %d) + + Set maximum block cost (default: %d) + Sätt maximal blockkostnad (förvalt: %d) + Set maximum block size in bytes (default: %d) Sätt maximal blockstorlek i byte (förvalt: %d) diff --git a/src/qt/locale/bitcoin_th_TH.ts b/src/qt/locale/bitcoin_th_TH.ts index 2630939146563..34c75263416b5 100644 --- a/src/qt/locale/bitcoin_th_TH.ts +++ b/src/qt/locale/bitcoin_th_TH.ts @@ -765,6 +765,30 @@ Tor Tor + + Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services. + เชื่อมต่อกับ เครือข่าย Bitcoin ผ่านทาง พร้อกซี่ SOCKS5 แยกต่างหาก สำหรับ Tor เซอร์วิส + + + Use separate SOCKS5 proxy to reach peers via Tor hidden services: + ใช้ พร็อกซี่ SOCKS5 แยก เพื่อเข้าถึง peers ผ่าน Tor เซอร์วิสซ่อน: + + + &Window + &วันโดว์ + + + &Hide the icon from the system tray. + &ซ่อนไอคอน จากเทรย์ระบบ + + + Hide tray icon + ซ่อนไอคอนเทรย์ + + + Show only a tray icon after minimizing the window. + แสดงเทรย์ไอคอน หลังมืนิไมส์วินโดว์ เท่านั้น + OverviewPage diff --git a/src/qt/locale/bitcoin_zh_TW.ts b/src/qt/locale/bitcoin_zh_TW.ts index cbdb8f2c0bacf..c71a37ba986e0 100644 --- a/src/qt/locale/bitcoin_zh_TW.ts +++ b/src/qt/locale/bitcoin_zh_TW.ts @@ -1879,6 +1879,10 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications 這是個還沒發表的測試版本 - 使用請自負風險 - 請不要用來開採或商業應用 + + Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain + 沒辦法將資料庫倒轉回分岔前的狀態。必須要重新下載區塊鍊。 + Use UPnP to map the listening port (default: 1 when listening and no -proxy) 是否要使用「通用即插即用」協定(UPnP),來設定聽候連線的通訊埠的對應(預設值: 當有聽候連線且沒有指定 -proxy 參數時為 1) @@ -2099,10 +2103,18 @@ Rebuild chain state from the currently indexed blocks 從目前已編索引的區塊資料重建區塊鏈狀態 + + Rewinding blocks... + 倒轉回區塊鏈之前的狀態... + Set database cache size in megabytes (%d to %d, default: %d) 設定資料庫快取大小是多少百萬位元組(MB,範圍: %d 到 %d,預設值: %d) + + Set maximum block cost (default: %d) + 設定區塊成本的最大值(預設值: %d) + Set maximum block size in bytes (default: %d) 設定區塊大小上限成多少位元組(預設值: %d) From cf2ef786a1ef78edefd7c1029feb46d1a9061b75 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 6 Jul 2016 17:29:43 -0400 Subject: [PATCH 0600/1802] build: require boost for bench --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 97af58bd7cd85..496e4ad9e7f24 100644 --- a/configure.ac +++ b/configure.ac @@ -583,7 +583,7 @@ BITCOIN_QT_INIT dnl sets $bitcoin_enable_qt, $bitcoin_enable_qt_test, $bitcoin_enable_qt_dbus BITCOIN_QT_CONFIGURE([$use_pkgconfig], [qt5]) -if test x$build_bitcoin_utils$build_bitcoind$bitcoin_enable_qt$use_tests = xnononono; then +if test x$build_bitcoin_utils$build_bitcoind$bitcoin_enable_qt$use_tests$use_bench = xnonononono; then use_boost=no else use_boost=yes From 36ae37a9f910922954d48ed1f3f2177d8b227205 Mon Sep 17 00:00:00 2001 From: Bob McElrath Date: Wed, 6 Jul 2016 19:46:46 -0400 Subject: [PATCH 0601/1802] Rename CTxinWitness -> CTxInWitness --- qa/rpc-tests/p2p-segwit.py | 48 +++++++++++------------ qa/rpc-tests/test_framework/blocktools.py | 2 +- qa/rpc-tests/test_framework/mininode.py | 6 +-- src/core_memusage.h | 4 +- src/primitives/transaction.h | 6 +-- src/test/sigopcount_tests.cpp | 14 +++---- 6 files changed, 40 insertions(+), 40 deletions(-) diff --git a/qa/rpc-tests/p2p-segwit.py b/qa/rpc-tests/p2p-segwit.py index cf78954f286bc..8e4bc989b8eb7 100755 --- a/qa/rpc-tests/p2p-segwit.py +++ b/qa/rpc-tests/p2p-segwit.py @@ -252,7 +252,7 @@ def test_unnecessary_witness_before_segwit_activation(self): tx = CTransaction() tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")) tx.vout.append(CTxOut(self.utxo[0].nValue-1000, CScript([OP_TRUE]))) - tx.wit.vtxinwit.append(CTxinWitness()) + tx.wit.vtxinwit.append(CTxInWitness()) tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([CScriptNum(1)])] # Verify the hash with witness differs from the txid @@ -362,7 +362,7 @@ def test_witness_commitments(self): tx2 = CTransaction() tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b"")) tx2.vout.append(CTxOut(tx.vout[0].nValue-1000, witness_program)) - tx2.wit.vtxinwit.append(CTxinWitness()) + tx2.wit.vtxinwit.append(CTxInWitness()) tx2.wit.vtxinwit[0].scriptWitness.stack = [witness_program] tx2.rehash() @@ -489,7 +489,7 @@ def test_witness_block_size(self): child_tx.vin.append(CTxIn(COutPoint(parent_tx.sha256, i), b"")) child_tx.vout = [CTxOut(value - 100000, CScript([OP_TRUE]))] for i in range(NUM_OUTPUTS): - child_tx.wit.vtxinwit.append(CTxinWitness()) + child_tx.wit.vtxinwit.append(CTxInWitness()) child_tx.wit.vtxinwit[-1].scriptWitness.stack = [b'a'*195]*(2*NUM_DROPS) + [witness_program] child_tx.rehash() self.update_witness_block_with_transactions(block, [parent_tx, child_tx]) @@ -584,7 +584,7 @@ def test_extra_witness_data(self): tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")) tx.vout.append(CTxOut(self.utxo[0].nValue-2000, scriptPubKey)) tx.vout.append(CTxOut(1000, CScript([OP_TRUE]))) # non-witness output - tx.wit.vtxinwit.append(CTxinWitness()) + tx.wit.vtxinwit.append(CTxInWitness()) tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([])] tx.rehash() self.update_witness_block_with_transactions(block, [tx]) @@ -607,7 +607,7 @@ def test_extra_witness_data(self): tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b"")) # witness output tx2.vin.append(CTxIn(COutPoint(tx.sha256, 1), b"")) # non-witness tx2.vout.append(CTxOut(tx.vout[0].nValue, CScript([OP_TRUE]))) - tx2.wit.vtxinwit.extend([CTxinWitness(), CTxinWitness()]) + tx2.wit.vtxinwit.extend([CTxInWitness(), CTxInWitness()]) tx2.wit.vtxinwit[0].scriptWitness.stack = [ CScript([CScriptNum(1)]), CScript([CScriptNum(1)]), witness_program ] tx2.wit.vtxinwit[1].scriptWitness.stack = [ CScript([OP_TRUE]) ] @@ -663,7 +663,7 @@ def test_max_witness_push_length(self): tx2 = CTransaction() tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b"")) tx2.vout.append(CTxOut(tx.vout[0].nValue-1000, CScript([OP_TRUE]))) - tx2.wit.vtxinwit.append(CTxinWitness()) + tx2.wit.vtxinwit.append(CTxInWitness()) # First try a 521-byte stack element tx2.wit.vtxinwit[0].scriptWitness.stack = [ b'a'*(MAX_SCRIPT_ELEMENT_SIZE+1), witness_program ] tx2.rehash() @@ -705,7 +705,7 @@ def test_max_witness_program_length(self): tx2 = CTransaction() tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b"")) tx2.vout.append(CTxOut(tx.vout[0].nValue-1000, CScript([OP_TRUE]))) - tx2.wit.vtxinwit.append(CTxinWitness()) + tx2.wit.vtxinwit.append(CTxInWitness()) tx2.wit.vtxinwit[0].scriptWitness.stack = [b'a']*44 + [long_witness_program] tx2.rehash() @@ -782,7 +782,7 @@ def serialize_with_witness(self): # First try using a too long vtxinwit for i in range(11): - tx2.wit.vtxinwit.append(CTxinWitness()) + tx2.wit.vtxinwit.append(CTxInWitness()) tx2.wit.vtxinwit[i].scriptWitness.stack = [b'a', witness_program] block = self.build_next_block() @@ -798,7 +798,7 @@ def serialize_with_witness(self): self.test_node.test_witness_block(block, accepted=False) # Now make one of the intermediate witnesses be incorrect - tx2.wit.vtxinwit.append(CTxinWitness()) + tx2.wit.vtxinwit.append(CTxInWitness()) tx2.wit.vtxinwit[-1].scriptWitness.stack = [b'a', witness_program] tx2.wit.vtxinwit[5].scriptWitness.stack = [ witness_program ] @@ -825,7 +825,7 @@ def test_witness_tx_relay_before_segwit_activation(self): tx = CTransaction() tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")) tx.vout.append(CTxOut(self.utxo[0].nValue-1000, CScript([OP_TRUE]))) - tx.wit.vtxinwit.append(CTxinWitness()) + tx.wit.vtxinwit.append(CTxInWitness()) tx.wit.vtxinwit[0].scriptWitness.stack = [ b'a' ] tx.rehash() @@ -885,7 +885,7 @@ def test_tx_relay_after_segwit_activation(self): tx = CTransaction() tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")) tx.vout.append(CTxOut(self.utxo[0].nValue-1000, CScript([OP_TRUE]))) - tx.wit.vtxinwit.append(CTxinWitness()) + tx.wit.vtxinwit.append(CTxInWitness()) tx.wit.vtxinwit[0].scriptWitness.stack = [ b'a' ] tx.rehash() @@ -914,7 +914,7 @@ def test_tx_relay_after_segwit_activation(self): tx3 = CTransaction() tx3.vin.append(CTxIn(COutPoint(tx2.sha256, 0), b"")) tx3.vout.append(CTxOut(tx2.vout[0].nValue-1000, CScript([OP_TRUE]))) - tx3.wit.vtxinwit.append(CTxinWitness()) + tx3.wit.vtxinwit.append(CTxInWitness()) tx3.wit.vtxinwit[0].scriptWitness.stack = [CScript([CScriptNum(1)]), witness_program ] tx3.rehash() @@ -1087,7 +1087,7 @@ def test_segwit_versions(self): tx2 = CTransaction() tx2.vin = [CTxIn(COutPoint(tx.sha256, 0), b"")] tx2.vout = [CTxOut(tx.vout[0].nValue-1000, scriptPubKey)] - tx2.wit.vtxinwit.append(CTxinWitness()) + tx2.wit.vtxinwit.append(CTxInWitness()) tx2.wit.vtxinwit[0].scriptWitness.stack = [ witness_program ] tx2.rehash() # Gets accepted to test_node, because standardness of outputs isn't @@ -1102,7 +1102,7 @@ def test_segwit_versions(self): total_value = 0 for i in temp_utxo: tx3.vin.append(CTxIn(COutPoint(i.sha256, i.n), b"")) - tx3.wit.vtxinwit.append(CTxinWitness()) + tx3.wit.vtxinwit.append(CTxInWitness()) total_value += i.nValue tx3.wit.vtxinwit[-1].scriptWitness.stack = [witness_program] tx3.vout.append(CTxOut(total_value - 1000, CScript([OP_TRUE]))) @@ -1140,7 +1140,7 @@ def test_premature_coinbase_witness_spend(self): spend_tx = CTransaction() spend_tx.vin = [CTxIn(COutPoint(block.vtx[0].sha256, 0), b"")] spend_tx.vout = [CTxOut(block.vtx[0].vout[0].nValue, witness_program)] - spend_tx.wit.vtxinwit.append(CTxinWitness()) + spend_tx.wit.vtxinwit.append(CTxInWitness()) spend_tx.wit.vtxinwit[0].scriptWitness.stack = [ witness_program ] spend_tx.rehash() @@ -1200,7 +1200,7 @@ def sign_P2PK_witness_input(script, txTo, inIdx, hashtype, value, key): tx = CTransaction() tx.vin.append(CTxIn(COutPoint(prev_utxo.sha256, prev_utxo.n), b"")) tx.vout.append(CTxOut(prev_utxo.nValue - 1000, scriptPubKey)) - tx.wit.vtxinwit.append(CTxinWitness()) + tx.wit.vtxinwit.append(CTxInWitness()) # Too-large input value sign_P2PK_witness_input(witness_program, tx, 0, hashtype, prev_utxo.nValue+1, key) self.update_witness_block_with_transactions(block, [tx]) @@ -1233,7 +1233,7 @@ def sign_P2PK_witness_input(script, txTo, inIdx, hashtype, value, key): split_value = prev_utxo.nValue // NUM_TESTS for i in range(NUM_TESTS): tx.vout.append(CTxOut(split_value, scriptPubKey)) - tx.wit.vtxinwit.append(CTxinWitness()) + tx.wit.vtxinwit.append(CTxInWitness()) sign_P2PK_witness_input(witness_program, tx, 0, SIGHASH_ALL, prev_utxo.nValue, key) for i in range(NUM_TESTS): temp_utxos.append(UTXO(tx.sha256, i, split_value)) @@ -1255,7 +1255,7 @@ def sign_P2PK_witness_input(script, txTo, inIdx, hashtype, value, key): total_value = 0 for i in range(num_inputs): tx.vin.append(CTxIn(COutPoint(temp_utxos[i].sha256, temp_utxos[i].n), b"")) - tx.wit.vtxinwit.append(CTxinWitness()) + tx.wit.vtxinwit.append(CTxInWitness()) total_value += temp_utxos[i].nValue split_value = total_value // num_outputs for i in range(num_outputs): @@ -1295,7 +1295,7 @@ def sign_P2PK_witness_input(script, txTo, inIdx, hashtype, value, key): tx = CTransaction() tx.vin.append(CTxIn(COutPoint(temp_utxos[0].sha256, temp_utxos[0].n), b"")) tx.vout.append(CTxOut(temp_utxos[0].nValue, scriptPKH)) - tx.wit.vtxinwit.append(CTxinWitness()) + tx.wit.vtxinwit.append(CTxInWitness()) sign_P2PK_witness_input(witness_program, tx, 0, SIGHASH_ALL, temp_utxos[0].nValue, key) tx2 = CTransaction() tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b"")) @@ -1313,7 +1313,7 @@ def sign_P2PK_witness_input(script, txTo, inIdx, hashtype, value, key): # Move the signature to the witness. block.vtx.pop() - tx2.wit.vtxinwit.append(CTxinWitness()) + tx2.wit.vtxinwit.append(CTxInWitness()) tx2.wit.vtxinwit[0].scriptWitness.stack = [signature, pubkey] tx2.vin[0].scriptSig = b"" tx2.rehash() @@ -1333,7 +1333,7 @@ def sign_P2PK_witness_input(script, txTo, inIdx, hashtype, value, key): # the signatures as we go. tx.vin.append(CTxIn(COutPoint(i.sha256, i.n), b"")) tx.vout.append(CTxOut(i.nValue, CScript([OP_TRUE]))) - tx.wit.vtxinwit.append(CTxinWitness()) + tx.wit.vtxinwit.append(CTxInWitness()) sign_P2PK_witness_input(witness_program, tx, index, SIGHASH_SINGLE|SIGHASH_ANYONECANPAY, i.nValue, key) index += 1 block = self.build_next_block() @@ -1393,7 +1393,7 @@ def test_p2sh_witness(self, segwit_activated): # segwit activates. spend_tx.vin[0].scriptSig = scriptSig spend_tx.rehash() - spend_tx.wit.vtxinwit.append(CTxinWitness()) + spend_tx.wit.vtxinwit.append(CTxInWitness()) spend_tx.wit.vtxinwit[0].scriptWitness.stack = [ b'a', witness_program ] # Verify mempool acceptance @@ -1499,7 +1499,7 @@ def test_witness_sigops(self): total_value = 0 for i in range(outputs-1): tx2.vin.append(CTxIn(COutPoint(tx.sha256, i), b"")) - tx2.wit.vtxinwit.append(CTxinWitness()) + tx2.wit.vtxinwit.append(CTxInWitness()) tx2.wit.vtxinwit[-1].scriptWitness.stack = [ witness_program ] total_value += tx.vout[i].nValue tx2.wit.vtxinwit[-1].scriptWitness.stack = [ witness_program_toomany ] @@ -1540,7 +1540,7 @@ def test_witness_sigops(self): block_5 = self.build_next_block() tx2.vout.pop() tx2.vin.append(CTxIn(COutPoint(tx.sha256, outputs-1), b"")) - tx2.wit.vtxinwit.append(CTxinWitness()) + tx2.wit.vtxinwit.append(CTxInWitness()) tx2.wit.vtxinwit[-1].scriptWitness.stack = [ witness_program_justright ] tx2.rehash() self.update_witness_block_with_transactions(block_5, [tx2]) diff --git a/qa/rpc-tests/test_framework/blocktools.py b/qa/rpc-tests/test_framework/blocktools.py index df4fe13e5c1c6..f69958823c9d9 100644 --- a/qa/rpc-tests/test_framework/blocktools.py +++ b/qa/rpc-tests/test_framework/blocktools.py @@ -34,7 +34,7 @@ def add_witness_commitment(block, nonce=0): witness_root = block.calc_witness_merkle_root() witness_commitment = uint256_from_str(hash256(ser_uint256(witness_root)+ser_uint256(witness_nonce))) # witness_nonce should go to coinbase witness. - block.vtx[0].wit.vtxinwit = [CTxinWitness()] + block.vtx[0].wit.vtxinwit = [CTxInWitness()] block.vtx[0].wit.vtxinwit[0].scriptWitness.stack = [ser_uint256(witness_nonce)] # witness commitment is the last OP_RETURN output in coinbase diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index 4548e2e7c080f..cdd5292cd67b8 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -419,7 +419,7 @@ def is_null(self): return True -class CTxinWitness(object): +class CTxInWitness(object): def __init__(self): self.scriptWitness = CScriptWitness() @@ -497,7 +497,7 @@ def deserialize(self, f): else: self.vout = deser_vector(f, CTxOut) if flags != 0: - self.wit.vtxinwit = [CTxinWitness()]*len(self.vin) + self.wit.vtxinwit = [CTxInWitness()]*len(self.vin) self.wit.deserialize(f) self.nLockTime = struct.unpack("::const_iterator it = txwit.vtxinwit.begin(); it != txwit.vtxinwit.end(); it++) { + for (std::vector::const_iterator it = txwit.vtxinwit.begin(); it != txwit.vtxinwit.end(); it++) { mem += RecursiveDynamicUsage(*it); } return mem; diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index e87ad90f0d498..8a2d5dd22c8de 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -213,7 +213,7 @@ class CTxOut std::string ToString() const; }; -class CTxinWitness +class CTxInWitness { public: CScriptWitness scriptWitness; @@ -228,14 +228,14 @@ class CTxinWitness bool IsNull() const { return scriptWitness.IsNull(); } - CTxinWitness() { } + CTxInWitness() { } }; class CTxWitness { public: /** In case vtxinwit is missing, all entries are treated as if they were empty CTxInWitnesses */ - std::vector vtxinwit; + std::vector vtxinwit; ADD_SERIALIZE_METHODS; diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp index 8dea388332b21..e8a63ae60ca81 100644 --- a/src/test/sigopcount_tests.cpp +++ b/src/test/sigopcount_tests.cpp @@ -84,7 +84,7 @@ ScriptError VerifyWithFlag(const CTransaction& output, const CMutableTransaction * and witness such that spendingTx spends output zero of creationTx. * Also inserts creationTx's output into the coins view. */ -void BuildTxs(CMutableTransaction& spendingTx, CCoinsViewCache& coins, CMutableTransaction& creationTx, const CScript& scriptPubKey, const CScript& scriptSig, const CTxinWitness& witness) +void BuildTxs(CMutableTransaction& spendingTx, CCoinsViewCache& coins, CMutableTransaction& creationTx, const CScript& scriptPubKey, const CScript& scriptSig, const CTxInWitness& witness) { creationTx.nVersion = 1; creationTx.vin.resize(1); @@ -133,7 +133,7 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost) // Do not use a valid signature to avoid using wallet operations. CScript scriptSig = CScript() << OP_0 << OP_0; - BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, CTxinWitness()); + BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, CTxInWitness()); // Legacy counting only includes signature operations in scriptSigs and scriptPubKeys // of a transaction and does not take the actual executed sig operations into account. // spendingTx in itself does not contain a signature operation. @@ -151,7 +151,7 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost) CScript scriptPubKey = GetScriptForDestination(CScriptID(redeemScript)); CScript scriptSig = CScript() << OP_0 << OP_0 << ToByteVector(redeemScript); - BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, CTxinWitness()); + BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, CTxInWitness()); assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 2 * WITNESS_SCALE_FACTOR); assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY); } @@ -161,7 +161,7 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost) CScript p2pk = CScript() << ToByteVector(pubkey) << OP_CHECKSIG; CScript scriptPubKey = GetScriptForWitness(p2pk); CScript scriptSig = CScript(); - CTxinWitness witness; + CTxInWitness witness; CScriptWitness scriptWitness; scriptWitness.stack.push_back(vector(0)); scriptWitness.stack.push_back(vector(0)); @@ -193,7 +193,7 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost) CScript scriptSig = GetScriptForWitness(p2pk); CScript scriptPubKey = GetScriptForDestination(CScriptID(scriptSig)); scriptSig = CScript() << ToByteVector(scriptSig); - CTxinWitness witness; + CTxInWitness witness; CScriptWitness scriptWitness; scriptWitness.stack.push_back(vector(0)); scriptWitness.stack.push_back(vector(0)); @@ -209,7 +209,7 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost) CScript witnessScript = CScript() << 1 << ToByteVector(pubkey) << ToByteVector(pubkey) << 2 << OP_CHECKMULTISIGVERIFY; CScript scriptPubKey = GetScriptForWitness(witnessScript); CScript scriptSig = CScript(); - CTxinWitness witness; + CTxInWitness witness; CScriptWitness scriptWitness; scriptWitness.stack.push_back(vector(0)); scriptWitness.stack.push_back(vector(0)); @@ -228,7 +228,7 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost) CScript redeemScript = GetScriptForWitness(witnessScript); CScript scriptPubKey = GetScriptForDestination(CScriptID(redeemScript)); CScript scriptSig = CScript() << ToByteVector(redeemScript); - CTxinWitness witness; + CTxInWitness witness; CScriptWitness scriptWitness; scriptWitness.stack.push_back(vector(0)); scriptWitness.stack.push_back(vector(0)); From fa9976b853dbd04334cd0b5a058b99aa0014e649 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 6 Jul 2016 20:46:22 +0200 Subject: [PATCH 0602/1802] [qa] test_framework: Add wrapper for stop_node --- qa/rpc-tests/test_framework/test_framework.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/qa/rpc-tests/test_framework/test_framework.py b/qa/rpc-tests/test_framework/test_framework.py index 30e8b5755de39..0dfece6b2779a 100755 --- a/qa/rpc-tests/test_framework/test_framework.py +++ b/qa/rpc-tests/test_framework/test_framework.py @@ -20,6 +20,7 @@ sync_blocks, sync_mempools, stop_nodes, + stop_node, wait_bitcoinds, enable_coverage, check_json_precision, @@ -49,6 +50,9 @@ def setup_chain(self): else: initialize_chain(self.options.tmpdir, self.num_nodes) + def stop_node(self, num_node): + stop_node(self.nodes[num_node], num_node) + def setup_nodes(self): return start_nodes(self.num_nodes, self.options.tmpdir) From 1ba3db6a8e9626984fc87314b15dfa2a6c831cb2 Mon Sep 17 00:00:00 2001 From: Christian von Roques Date: Sun, 26 Jun 2016 16:20:12 -0400 Subject: [PATCH 0603/1802] bash-completion: Adapt for 0.12 and 0.13 * separate completion for bitcoind and bitcoin-cli * remove RPC support from bitcoind completion * add completion for bitcoin-tx and bitcoin-qt * rely on autoloading of completions --- contrib/bitcoin-cli.bash-completion | 154 ++++++++++++++++++++++ contrib/bitcoin-tx.bash-completion | 57 ++++++++ contrib/bitcoind.bash-completion | 111 ++-------------- contrib/debian/bitcoin-tx.bash-completion | 1 + contrib/debian/bitcoind.bash-completion | 1 + 5 files changed, 224 insertions(+), 100 deletions(-) create mode 100644 contrib/bitcoin-cli.bash-completion create mode 100644 contrib/bitcoin-tx.bash-completion create mode 100644 contrib/debian/bitcoin-tx.bash-completion diff --git a/contrib/bitcoin-cli.bash-completion b/contrib/bitcoin-cli.bash-completion new file mode 100644 index 0000000000000..732981fe7c5d1 --- /dev/null +++ b/contrib/bitcoin-cli.bash-completion @@ -0,0 +1,154 @@ +# bash programmable completion for bitcoin-cli(1) +# Copyright (c) 2012-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# call $bitcoin-cli for RPC +_bitcoin_rpc() { + # determine already specified args necessary for RPC + local rpcargs=() + for i in ${COMP_LINE}; do + case "$i" in + -conf=*|-datadir=*|-regtest|-rpc*|-testnet) + rpcargs=( "${rpcargs[@]}" "$i" ) + ;; + esac + done + $bitcoin_cli "${rpcargs[@]}" "$@" +} + +# Add wallet accounts to COMPREPLY +_bitcoin_accounts() { + local accounts + accounts=$(_bitcoin_rpc listaccounts | awk -F '"' '{ print $2 }') + COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W "$accounts" -- "$cur" ) ) +} + +_bitcoin_cli() { + local cur prev words=() cword + local bitcoin_cli + + # save and use original argument to invoke bitcoin-cli for -help, help and RPC + # as bitcoin-cli might not be in $PATH + bitcoin_cli="$1" + + COMPREPLY=() + _get_comp_words_by_ref -n = cur prev words cword + + if ((cword > 5)); then + case ${words[cword-5]} in + sendtoaddress) + COMPREPLY=( $( compgen -W "true false" -- "$cur" ) ) + return 0 + ;; + esac + fi + + if ((cword > 4)); then + case ${words[cword-4]} in + importaddress|listtransactions|setban) + COMPREPLY=( $( compgen -W "true false" -- "$cur" ) ) + return 0 + ;; + signrawtransaction) + COMPREPLY=( $( compgen -W "ALL NONE SINGLE ALL|ANYONECANPAY NONE|ANYONECANPAY SINGLE|ANYONECANPAY" -- "$cur" ) ) + return 0 + ;; + esac + fi + + if ((cword > 3)); then + case ${words[cword-3]} in + addmultisigaddress) + _bitcoin_accounts + return 0 + ;; + getbalance|gettxout|importaddress|importpubkey|importprivkey|listreceivedbyaccount|listreceivedbyaddress|listsinceblock) + COMPREPLY=( $( compgen -W "true false" -- "$cur" ) ) + return 0 + ;; + esac + fi + + if ((cword > 2)); then + case ${words[cword-2]} in + addnode) + COMPREPLY=( $( compgen -W "add remove onetry" -- "$cur" ) ) + return 0 + ;; + setban) + COMPREPLY=( $( compgen -W "add remove" -- "$cur" ) ) + return 0 + ;; + fundrawtransaction|getblock|getblockheader|getmempoolancestors|getmempooldescendants|getrawtransaction|gettransaction|listaccounts|listreceivedbyaccount|listreceivedbyaddress|sendrawtransaction) + COMPREPLY=( $( compgen -W "true false" -- "$cur" ) ) + return 0 + ;; + move|setaccount) + _bitcoin_accounts + return 0 + ;; + esac + fi + + case "$prev" in + backupwallet|dumpwallet|importwallet) + _filedir + return 0 + ;; + getaddednodeinfo|getrawmempool|lockunspent|setgenerate) + COMPREPLY=( $( compgen -W "true false" -- "$cur" ) ) + return 0 + ;; + getaccountaddress|getaddressesbyaccount|getbalance|getnewaddress|getreceivedbyaccount|listtransactions|move|sendfrom|sendmany) + _bitcoin_accounts + return 0 + ;; + esac + + case "$cur" in + -conf=*) + cur="${cur#*=}" + _filedir + return 0 + ;; + -datadir=*) + cur="${cur#*=}" + _filedir -d + return 0 + ;; + -*=*) # prevent nonsense completions + return 0 + ;; + *) + local helpopts commands + + # only parse -help if senseful + if [[ -z "$cur" || "$cur" =~ ^- ]]; then + helpopts=$($bitcoin_cli -help 2>&1 | awk '$1 ~ /^-/ { sub(/=.*/, "="); print $1 }' ) + fi + + # only parse help if senseful + if [[ -z "$cur" || "$cur" =~ ^[a-z] ]]; then + commands=$(_bitcoin_rpc help 2>/dev/null | awk '$1 ~ /^[a-z]/ { print $1; }') + fi + + COMPREPLY=( $( compgen -W "$helpopts $commands" -- "$cur" ) ) + + # Prevent space if an argument is desired + if [[ $COMPREPLY == *= ]]; then + compopt -o nospace + fi + return 0 + ;; + esac +} && +complete -F _bitcoin_cli bitcoin-cli + +# Local variables: +# mode: shell-script +# sh-basic-offset: 4 +# sh-indent-comment: t +# indent-tabs-mode: nil +# End: +# ex: ts=4 sw=4 et filetype=sh diff --git a/contrib/bitcoin-tx.bash-completion b/contrib/bitcoin-tx.bash-completion new file mode 100644 index 0000000000000..a83d2979ed3a8 --- /dev/null +++ b/contrib/bitcoin-tx.bash-completion @@ -0,0 +1,57 @@ +# bash programmable completion for bitcoin-tx(1) +# Copyright (c) 2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +_bitcoin_tx() { + local cur prev words=() cword + local bitcoin_tx + + # save and use original argument to invoke bitcoin-tx for -help + # it might not be in $PATH + bitcoin_tx="$1" + + COMPREPLY=() + _get_comp_words_by_ref -n =: cur prev words cword + + case "$cur" in + load=*:*) + cur="${cur#load=*:}" + _filedir + return 0 + ;; + *=*) # prevent attempts to complete other arguments + return 0 + ;; + esac + + if [[ "$cword" == 1 || ( "$prev" != "-create" && "$prev" == -* ) ]]; then + # only options (or an uncompletable hex-string) allowed + # parse bitcoin-tx -help for options + local helpopts + helpopts=$($bitcoin_tx -help | sed -e '/^ -/ p' -e d ) + COMPREPLY=( $( compgen -W "$helpopts" -- "$cur" ) ) + else + # only commands are allowed + # parse -help for commands + local helpcmds + helpcmds=$($bitcoin_tx -help | sed -e '1,/Commands:/d' -e 's/=.*/=/' -e '/^ [a-z]/ p' -e d ) + COMPREPLY=( $( compgen -W "$helpcmds" -- "$cur" ) ) + fi + + # Prevent space if an argument is desired + if [[ $COMPREPLY == *= ]]; then + compopt -o nospace + fi + + return 0 +} && +complete -F _bitcoin_tx bitcoin-tx + +# Local variables: +# mode: shell-script +# sh-basic-offset: 4 +# sh-indent-comment: t +# indent-tabs-mode: nil +# End: +# ex: ts=4 sw=4 et filetype=sh diff --git a/contrib/bitcoind.bash-completion b/contrib/bitcoind.bash-completion index 1338d2f2b5c3b..af87e97d80690 100644 --- a/contrib/bitcoind.bash-completion +++ b/contrib/bitcoind.bash-completion @@ -1,102 +1,21 @@ -# bash programmable completion for bitcoind(1) and bitcoin-cli(1) -# Copyright (c) 2012,2014 Christian von Roques +# bash programmable completion for bitcoind(1) and bitcoin-qt(1) +# Copyright (c) 2012-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. -have bitcoind && { - -# call $bitcoind for RPC -_bitcoin_rpc() { - # determine already specified args necessary for RPC - local rpcargs=() - for i in ${COMP_LINE}; do - case "$i" in - -conf=*|-proxy*|-rpc*) - rpcargs=( "${rpcargs[@]}" "$i" ) - ;; - esac - done - $bitcoind "${rpcargs[@]}" "$@" -} - -# Add bitcoin accounts to COMPREPLY -_bitcoin_accounts() { - local accounts - accounts=$(_bitcoin_rpc listaccounts | awk '/".*"/ { a=$1; gsub(/"/, "", a); print a}') - COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W "$accounts" -- "$cur" ) ) -} - _bitcoind() { local cur prev words=() cword local bitcoind - # save and use original argument to invoke bitcoind - # bitcoind might not be in $PATH + # save and use original argument to invoke bitcoind for -help + # it might not be in $PATH bitcoind="$1" COMPREPLY=() _get_comp_words_by_ref -n = cur prev words cword - if ((cword > 4)); then - case ${words[cword-4]} in - listtransactions) - COMPREPLY=( $( compgen -W "true false" -- "$cur" ) ) - return 0 - ;; - signrawtransaction) - COMPREPLY=( $( compgen -W "ALL NONE SINGLE ALL|ANYONECANPAY NONE|ANYONECANPAY SINGLE|ANYONECANPAY" -- "$cur" ) ) - return 0 - ;; - esac - fi - - if ((cword > 3)); then - case ${words[cword-3]} in - addmultisigaddress) - _bitcoin_accounts - return 0 - ;; - getbalance|gettxout|importaddress|importprivkey|listreceivedbyaccount|listreceivedbyaddress|listsinceblock) - COMPREPLY=( $( compgen -W "true false" -- "$cur" ) ) - return 0 - ;; - esac - fi - - if ((cword > 2)); then - case ${words[cword-2]} in - addnode) - COMPREPLY=( $( compgen -W "add remove onetry" -- "$cur" ) ) - return 0 - ;; - getblock|getrawtransaction|gettransaction|listaccounts|listreceivedbyaccount|listreceivedbyaddress|sendrawtransaction) - COMPREPLY=( $( compgen -W "true false" -- "$cur" ) ) - return 0 - ;; - move|setaccount) - _bitcoin_accounts - return 0 - ;; - esac - fi - - case "$prev" in - backupwallet|dumpwallet|importwallet) - _filedir - return 0 - ;; - getmempool|lockunspent|setgenerate) - COMPREPLY=( $( compgen -W "true false" -- "$cur" ) ) - return 0 - ;; - getaccountaddress|getaddressesbyaccount|getbalance|getnewaddress|getreceivedbyaccount|listtransactions|move|sendfrom|sendmany) - _bitcoin_accounts - return 0 - ;; - esac - case "$cur" in - -conf=*|-pid=*|-loadblock=*|-wallet=*) + -conf=*|-pid=*|-loadblock=*|-rootcertificates=*|-rpccookiefile=*|-wallet=*) cur="${cur#*=}" _filedir return 0 @@ -110,20 +29,14 @@ _bitcoind() { return 0 ;; *) - local helpopts commands - # only parse --help if senseful + # only parse -help if senseful if [[ -z "$cur" || "$cur" =~ ^- ]]; then - helpopts=$($bitcoind --help 2>&1 | awk '$1 ~ /^-/ { sub(/=.*/, "="); print $1 }' ) + local helpopts + helpopts=$($bitcoind -help 2>&1 | awk '$1 ~ /^-/ { sub(/=.*/, "="); print $1 }' ) + COMPREPLY=( $( compgen -W "$helpopts" -- "$cur" ) ) fi - # only parse help if senseful - if [[ -z "$cur" || "$cur" =~ ^[a-z] ]]; then - commands=$(_bitcoin_rpc help 2>/dev/null | awk '$1 ~ /^[a-z]/ { print $1; }') - fi - - COMPREPLY=( $( compgen -W "$helpopts $commands" -- "$cur" ) ) - # Prevent space if an argument is desired if [[ $COMPREPLY == *= ]]; then compopt -o nospace @@ -131,10 +44,8 @@ _bitcoind() { return 0 ;; esac -} - -complete -F _bitcoind bitcoind bitcoin-cli -} +} && +complete -F _bitcoind bitcoind bitcoin-qt # Local variables: # mode: shell-script diff --git a/contrib/debian/bitcoin-tx.bash-completion b/contrib/debian/bitcoin-tx.bash-completion new file mode 100644 index 0000000000000..7acb0b0aea668 --- /dev/null +++ b/contrib/debian/bitcoin-tx.bash-completion @@ -0,0 +1 @@ +contrib/bitcoin-tx.bash-completion bitcoin-tx diff --git a/contrib/debian/bitcoind.bash-completion b/contrib/debian/bitcoind.bash-completion index 0f84707b66cb7..5c69d78fbb0fc 100644 --- a/contrib/debian/bitcoind.bash-completion +++ b/contrib/debian/bitcoind.bash-completion @@ -1 +1,2 @@ contrib/bitcoind.bash-completion bitcoind +contrib/bitcoin-cli.bash-completion bitcoin-cli From 0c928cb13cc9146bb2c0f39d1d3b6e1e660a375d Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 7 Jul 2016 13:46:59 -0400 Subject: [PATCH 0604/1802] build: Fix Qt5PlatformSupport check without pkg-config The non-pkg-config case can't use pkg-config to check the version. Also, make sure that the check is properly guarded in the case of missing pkg-config macros. --- build-aux/m4/bitcoin_qt.m4 | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/build-aux/m4/bitcoin_qt.m4 b/build-aux/m4/bitcoin_qt.m4 index 74d910267462e..d26136cbe9a45 100644 --- a/build-aux/m4/bitcoin_qt.m4 +++ b/build-aux/m4/bitcoin_qt.m4 @@ -331,8 +331,9 @@ AC_DEFUN([_BITCOIN_QT_FIND_STATIC_PLUGINS],[ QT_LIBS="$QT_LIBS -L$qt_plugin_path/accessible" fi fi - m4_ifdef([PKG_CHECK_MODULES],[ if test x$use_pkgconfig = xyes; then + : dnl + m4_ifdef([PKG_CHECK_MODULES],[ PKG_CHECK_MODULES([QTPLATFORM], [Qt5PlatformSupport], [QT_LIBS="$QTPLATFORM_LIBS $QT_LIBS"]) if test x$TARGET_OS = xlinux; then PKG_CHECK_MODULES([X11XCB], [x11-xcb], [QT_LIBS="$X11XCB_LIBS $QT_LIBS"]) @@ -342,12 +343,23 @@ AC_DEFUN([_BITCOIN_QT_FIND_STATIC_PLUGINS],[ elif test x$TARGET_OS = xdarwin; then PKG_CHECK_MODULES([QTPRINT], [Qt5PrintSupport], [QT_LIBS="$QTPRINT_LIBS $QT_LIBS"]) fi + ]) else - if ${PKG_CONFIG} --exists "Qt5Core >= 5.6" 2>/dev/null; then - QT_LIBS="-lQt5PlatformSupport $QT_LIBS" + if test x$TARGET_OS = xwindows; then + AC_CACHE_CHECK(for Qt >= 5.6, bitcoin_cv_need_platformsupport,[AC_COMPILE_IFELSE([AC_LANG_PROGRAM( + [[#include ]],[[ + #if QT_VERSION < 0x050600 + choke; + #endif + ]])], + [bitcoin_cv_need_platformsupport=yes], + [bitcoin_cv_need_platformsupport=no]) + ]) + if test x$bitcoin_cv_need_platformsupport = xyes; then + BITCOIN_QT_CHECK(AC_CHECK_LIB([${QT_LIB_PREFIX}PlatformSupport],[main],,BITCOIN_QT_FAIL(lib$QT_LIB_PREFIXPlatformSupport not found))) + fi fi fi - ]) else if test x$qt_plugin_path != x; then QT_LIBS="$QT_LIBS -L$qt_plugin_path/accessible" From b556beda264308e040f8d88aca4f2f386a0183d9 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 7 Jul 2016 13:47:54 -0400 Subject: [PATCH 0605/1802] build: fix Windows builds without pkg-config - guard PKG_PROG_PKG_CONFIG with an m4_ifdef. If not building for windows, require it - add nops as necessary in case the ifdef reduces the if/then to nothing - AC_SUBST some missing _LIBS. These were split out over time, but not all were properly substituted. They continued to work if pkg-config is installed because it does the AC_SUBST itself --- configure.ac | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/configure.ac b/configure.ac index 97af58bd7cd85..ae09722623f7a 100644 --- a/configure.ac +++ b/configure.ac @@ -79,9 +79,6 @@ AC_PATH_TOOL(OBJCOPY, objcopy) AC_ARG_VAR(PYTHONPATH, Augments the default search path for python module files) -dnl pkg-config check. -PKG_PROG_PKG_CONFIG - # Enable wallet AC_ARG_ENABLE([wallet], [AS_HELP_STRING([--disable-wallet], @@ -375,6 +372,16 @@ case $host in ;; esac +if test x$use_pkgconfig = xyes; then + m4_ifndef([PKG_PROG_PKG_CONFIG], [AC_MSG_ERROR(PKG_PROG_PKG_CONFIG macro not found. Please install pkg-config and re-run autogen.sh.)]) + m4_ifdef([PKG_PROG_PKG_CONFIG], [ + PKG_PROG_PKG_CONFIG + if test x"$PKG_CONFIG" = "x"; then + AC_MSG_ERROR(pkg-config not found.) + fi + ]) +fi + if test x$use_comparison_tool != xno; then AC_SUBST(JAVA_COMPARISON_TOOL, $use_comparison_tool) fi @@ -752,12 +759,7 @@ fi fi if test x$use_pkgconfig = xyes; then - - if test x"$PKG_CONFIG" = "x"; then - AC_MSG_ERROR(pkg-config not found.) - fi - - : #NOP + : dnl m4_ifdef( [PKG_CHECK_MODULES], [ @@ -1058,6 +1060,13 @@ AC_SUBST(TESTDEFS) AC_SUBST(LEVELDB_TARGET_FLAGS) AC_SUBST(MINIUPNPC_CPPFLAGS) AC_SUBST(MINIUPNPC_LIBS) +AC_SUBST(CRYPTO_LIBS) +AC_SUBST(SSL_LIBS) +AC_SUBST(EVENT_LIBS) +AC_SUBST(EVENT_PTHREADS_LIBS) +AC_SUBST(ZMQ_LIBS) +AC_SUBST(PROTOBUF_LIBS) +AC_SUBST(QR_LIBS) AC_CONFIG_FILES([Makefile src/Makefile share/setup.nsi share/qt/Info.plist src/test/buildenv.py]) AC_CONFIG_FILES([qa/pull-tester/run-bitcoind-for-test.sh],[chmod +x qa/pull-tester/run-bitcoind-for-test.sh]) AC_CONFIG_FILES([qa/pull-tester/tests_config.py],[chmod +x qa/pull-tester/tests_config.py]) From bb66a11396335b5f4e5914806fcb2dc6165edf6f Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Thu, 7 Jul 2016 15:49:26 -0400 Subject: [PATCH 0606/1802] Fix DoS vulnerability in mempool acceptance Moves the IsStandard check to happen after the premature-witness check, so that adding a witness to a transaction can't prevent mempool acceptance. Note that this doesn't address the broader category of potential mempool DoS issues that affect transactions after segwit activation. --- src/main.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index b86bbda1b8f9e..2f16a4c8ead26 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1132,11 +1132,6 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C if (tx.IsCoinBase()) return state.DoS(100, false, REJECT_INVALID, "coinbase"); - // Rather not work on nonstandard transactions (unless -testnet/-regtest) - string reason; - if (fRequireStandard && !IsStandardTx(tx, reason)) - return state.DoS(0, false, REJECT_NONSTANDARD, reason); - // Don't relay version 2 transactions until CSV is active, and we can be // sure that such transactions will be mined (unless we're on // -testnet/-regtest). @@ -1150,6 +1145,11 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C return state.DoS(0, false, REJECT_NONSTANDARD, "no-witness-yet", true); } + // Rather not work on nonstandard transactions (unless -testnet/-regtest) + string reason; + if (fRequireStandard && !IsStandardTx(tx, reason)) + return state.DoS(0, false, REJECT_NONSTANDARD, reason); + // Only accept nLockTime-using transactions that can be mined in the next // block; we don't want our mempool filled up with transactions that can't // be mined yet. From fade505e8b0fa37e2d99bf94259250271a9604d4 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 6 Jul 2016 10:36:46 +0200 Subject: [PATCH 0607/1802] [qa] Add wallet-hd test --- qa/pull-tester/rpc-tests.py | 1 + qa/rpc-tests/wallet-hd.py | 77 +++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100755 qa/rpc-tests/wallet-hd.py diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index 37979a933fc29..11b83bac1468d 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -106,6 +106,7 @@ 'walletbackup.py', 'bip68-112-113-p2p.py', 'wallet.py', + 'wallet-hd.py', 'listtransactions.py', 'receivedby.py', 'mempool_resurrect_test.py', diff --git a/qa/rpc-tests/wallet-hd.py b/qa/rpc-tests/wallet-hd.py new file mode 100755 index 0000000000000..845eec027bde2 --- /dev/null +++ b/qa/rpc-tests/wallet-hd.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 +# Copyright (c) 2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import ( + start_nodes, + start_node, + assert_equal, + connect_nodes_bi, +) +import os +import shutil + + +class WalletHDTest(BitcoinTestFramework): + + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 2 + self.node_args = [['-usehd=0'], ['-usehd=1', '-keypool=0']] + + def setup_network(self): + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.node_args) + self.is_network_split = False + connect_nodes_bi(self.nodes, 0, 1) + + def run_test (self): + tmpdir = self.options.tmpdir + + # Import a non-HD private key in the HD wallet + non_hd_add = self.nodes[0].getnewaddress() + self.nodes[1].importprivkey(self.nodes[0].dumpprivkey(non_hd_add)) + + # This should be enough to keep the master key and the non-HD key + self.nodes[1].backupwallet(tmpdir + "hd.bak") + #self.nodes[1].dumpwallet(tmpdir + "hd.dump") + + # Derive some HD addresses and remember the last + # Also send funds to each add + self.nodes[0].generate(101) + hd_add = None + num_hd_adds = 300 + for _ in range(num_hd_adds): + hd_add = self.nodes[1].getnewaddress() + self.nodes[0].sendtoaddress(hd_add, 1) + self.nodes[0].generate(1) + self.nodes[0].sendtoaddress(non_hd_add, 1) + self.nodes[0].generate(1) + + self.sync_all() + assert_equal(self.nodes[1].getbalance(), num_hd_adds + 1) + + print("Restore backup ...") + self.stop_node(1) + os.remove(self.options.tmpdir + "/node1/regtest/wallet.dat") + shutil.copyfile(tmpdir + "hd.bak", tmpdir + "/node1/regtest/wallet.dat") + self.nodes[1] = start_node(1, self.options.tmpdir, self.node_args[1]) + #connect_nodes_bi(self.nodes, 0, 1) + + # Assert that derivation is deterministic + hd_add_2 = None + for _ in range(num_hd_adds): + hd_add_2 = self.nodes[1].getnewaddress() + assert_equal(hd_add, hd_add_2) + + # Needs rescan + self.stop_node(1) + self.nodes[1] = start_node(1, self.options.tmpdir, self.node_args[1] + ['-rescan']) + #connect_nodes_bi(self.nodes, 0, 1) + assert_equal(self.nodes[1].getbalance(), num_hd_adds + 1) + + +if __name__ == '__main__': + WalletHDTest().main () From 099d4b0b65b7dceb14dc4ec5231a60996dff4c69 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 7 Jul 2016 20:09:55 -0400 Subject: [PATCH 0608/1802] gitian: use a wrapped gcc/g++ to avoid the need for a system change C_INCLUDE_PATH and CPLUS_INCLUDE_PATH work globally as though -isystem was used for each invocation. Since that changes the build results, force a rebuild of x86 depends by adding the value to $HOST_ID_SALT. --- contrib/gitian-descriptors/gitian-linux.yml | 40 +++++++++++++++++---- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index a2788c9d76169..6f43119ba24e6 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -33,12 +33,6 @@ remotes: files: [] script: | - #unlock sudo - echo "ubuntu" | sudo -S true - - sudo mkdir -p /usr/include/i386-linux-gnu/ - sudo ln -s /usr/include/x86_64-linux-gnu/asm /usr/include/i386-linux-gnu/asm - WRAP_DIR=$HOME/wrapped HOSTS="i686-pc-linux-gnu x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu" CONFIGFLAGS="--enable-glibc-back-compat --enable-reduce-exports --disable-bench --disable-gui-tests" @@ -90,11 +84,45 @@ script: | create_per-host_faketime_wrappers "2000-01-01 12:00:00" export PATH=${WRAP_DIR}:${PATH} + EXTRA_INCLUDES_BASE=$WRAP_DIR/extra_includes + mkdir -p $EXTRA_INCLUDES_BASE + + # x86 needs /usr/include/i386-linux-gnu/asm pointed to /usr/include/x86_64-linux-gnu/asm, + # but we can't write there. Instead, create a link here and force it to be included in the + # search paths by wrapping gcc/g++. + + mkdir -p $EXTRA_INCLUDES_BASE/i686-pc-linux-gnu + rm -f $WRAP_DIR/extra_includes/i686-pc-linux-gnu/asm + ln -s /usr/include/x86_64-linux-gnu/asm $EXTRA_INCLUDES_BASE/i686-pc-linux-gnu/asm + + for prog in gcc g++; do + rm -f ${WRAP_DIR}/${prog} + cat << EOF > ${WRAP_DIR}/${prog} + #!/bin/bash + REAL="`which -a ${prog} | grep -v ${WRAP_DIR}/${prog} | head -1`" + for var in "\$@" + do + if [ "\$var" = "-m32" ]; then + export C_INCLUDE_PATH="$EXTRA_INCLUDES_BASE/i686-pc-linux-gnu" + export CPLUS_INCLUDE_PATH="$EXTRA_INCLUDES_BASE/i686-pc-linux-gnu" + break + fi + done + \$REAL \$@ + EOF + chmod +x ${WRAP_DIR}/${prog} + done + cd bitcoin BASEPREFIX=`pwd`/depends # Build dependencies for each host for i in $HOSTS; do + EXTRA_INCLUDES="$EXTRA_INCLUDES_BASE/$i" + if [ -d "$EXTRA_INCLUDES" ]; then + export HOST_ID_SALT="$EXTRA_INCLUDES" + fi make ${MAKEOPTS} -C ${BASEPREFIX} HOST="${i}" + unset HOST_ID_SALT done # Faketime for binaries From 46c9620f11acfd2b528959d6cbab324105c3adef Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Thu, 7 Jul 2016 21:18:05 -0400 Subject: [PATCH 0609/1802] Test that unnecessary witnesses can't be used for mempool DoS Check that pre-segwit activation, unnecessary witnesses won't cause a txid to be permanently rejected. --- qa/rpc-tests/p2p-segwit.py | 54 +++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/qa/rpc-tests/p2p-segwit.py b/qa/rpc-tests/p2p-segwit.py index cf78954f286bc..2a2079d5e3ebf 100755 --- a/qa/rpc-tests/p2p-segwit.py +++ b/qa/rpc-tests/p2p-segwit.py @@ -43,6 +43,7 @@ def __init__(self): self.last_pong = msg_pong(0) self.sleep_time = 0.05 self.getdataset = set() + self.last_reject = None def add_connection(self, conn): self.connection = conn @@ -68,7 +69,7 @@ def on_pong(self, conn, message): def on_reject(self, conn, message): self.last_reject = message - #print message + #print (message) # Syncing helpers def sync(self, test_function, timeout=60): @@ -136,13 +137,17 @@ def request_block(self, blockhash, inv_type, timeout=60): self.wait_for_block(blockhash, timeout) return self.last_block - def test_transaction_acceptance(self, tx, with_witness, accepted): + def test_transaction_acceptance(self, tx, with_witness, accepted, reason=None): tx_message = msg_tx(tx) if with_witness: tx_message = msg_witness_tx(tx) self.send_message(tx_message) self.sync_with_ping() assert_equal(tx.hash in self.connection.rpc.getrawmempool(), accepted) + if (reason != None and not accepted): + # Check the rejection reason as well. + with mininode_lock: + assert_equal(self.last_reject.reason, reason) # Test whether a witness block had the correct effect on the tip def test_witness_block(self, block, accepted, with_witness=True): @@ -277,9 +282,52 @@ def test_unnecessary_witness_before_segwit_activation(self): self.test_node.sync_with_ping() assert_equal(self.nodes[0].getbestblockhash(), block.hash) + sync_blocks(self.nodes) + + # Create a p2sh output -- this is so we can pass the standardness + # rules (an anyone-can-spend OP_TRUE would be rejected, if not wrapped + # in P2SH). + p2sh_program = CScript([OP_TRUE]) + p2sh_pubkey = hash160(p2sh_program) + scriptPubKey = CScript([OP_HASH160, p2sh_pubkey, OP_EQUAL]) + + # Now check that unnecessary witnesses can't be used to blind a node + # to a transaction, eg by violating standardness checks. + tx2 = CTransaction() + tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b"")) + tx2.vout.append(CTxOut(tx.vout[0].nValue-1000, scriptPubKey)) + tx2.rehash() + self.test_node.test_transaction_acceptance(tx2, False, True) + self.nodes[0].generate(1) + sync_blocks(self.nodes) + + # We'll add an unnecessary witness to this transaction that would cause + # it to be too large according to IsStandard. + tx3 = CTransaction() + tx3.vin.append(CTxIn(COutPoint(tx2.sha256, 0), CScript([p2sh_program]))) + tx3.vout.append(CTxOut(tx2.vout[0].nValue-1000, scriptPubKey)) + tx3.wit.vtxinwit.append(CTxinWitness()) + tx3.wit.vtxinwit[0].scriptWitness.stack = [b'a'*400000] + tx3.rehash() + self.std_node.test_transaction_acceptance(tx3, True, False, b'no-witness-yet') + + # If we send without witness, it should be accepted. + self.std_node.test_transaction_acceptance(tx3, False, True) + + # Now create a new anyone-can-spend utxo for the next test. + tx4 = CTransaction() + tx4.vin.append(CTxIn(COutPoint(tx3.sha256, 0), CScript([p2sh_program]))) + tx4.vout.append(CTxOut(tx3.vout[0].nValue-1000, CScript([OP_TRUE]))) + tx4.rehash() + self.test_node.test_transaction_acceptance(tx3, False, True) + self.test_node.test_transaction_acceptance(tx4, False, True) + + self.nodes[0].generate(1) + sync_blocks(self.nodes) + # Update our utxo list; we spent the first entry. self.utxo.pop(0) - self.utxo.append(UTXO(tx.sha256, 0, tx.vout[0].nValue)) + self.utxo.append(UTXO(tx4.sha256, 0, tx4.vout[0].nValue)) # Mine enough blocks for segwit's vb state to be 'started'. From 477777f2503e3a56a267556f0fc5091042d93340 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Fri, 8 Jul 2016 12:01:39 +0200 Subject: [PATCH 0610/1802] [rpcwallet] Don't use floating point --- src/wallet/rpcwallet.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 8538f880ff636..2747477fd93e7 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -564,8 +564,8 @@ UniValue getreceivedbyaddress(const UniValue& params, bool fHelp) if (!address.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); CScript scriptPubKey = GetScriptForDestination(address.Get()); - if (!IsMine(*pwalletMain,scriptPubKey)) - return (double)0.0; + if (!IsMine(*pwalletMain, scriptPubKey)) + return ValueFromAmount(0); // Minimum confirmations int nMinDepth = 1; @@ -643,7 +643,7 @@ UniValue getreceivedbyaccount(const UniValue& params, bool fHelp) } } - return (double)nAmount / (double)COIN; + return ValueFromAmount(nAmount); } From d6dc1bc49b958e3c89aa0885ce39ad7a0e0f7493 Mon Sep 17 00:00:00 2001 From: Krzysztof Jurewicz Date: Fri, 8 Jul 2016 22:15:08 +0200 Subject: [PATCH 0611/1802] Fix 0.12 release notes on block relaying The previous information about block relaying in pruned mode suggested that blocks are relayed only to nodes that support BIP 130, which is not true. --- doc/release-notes/release-notes-0.12.0.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/doc/release-notes/release-notes-0.12.0.md b/doc/release-notes/release-notes-0.12.0.md index 1b7bd06ece6a2..cf74a17975207 100644 --- a/doc/release-notes/release-notes-0.12.0.md +++ b/doc/release-notes/release-notes-0.12.0.md @@ -104,9 +104,6 @@ announcing their headers directly, instead of just announcing the hash. In a reorganization, all new headers are sent, instead of just the new tip. This can often prevent an extra roundtrip before the actual block is downloaded. -With this change, pruning nodes are now able to relay new blocks to compatible -peers. - Memory pool limiting -------------------- @@ -188,6 +185,14 @@ the OP_RETURN. The limit on OP_RETURN output size is now applied to the entire serialized scriptPubKey, 83 bytes by default. (the previous 80 byte default plus three bytes overhead) +Relay: New and only new blocks relayed when pruning +--------------------------------------------------- + +When running in pruned mode, the client will now relay new blocks. When +responding to the `getblocks` message, only hashes of blocks that are on disk +and are likely to remain there for some reasonable time window (1 hour) will be +returned (previously all relevant hashes were returned). + Relay and Mining: Priority transactions --------------------------------------- @@ -887,4 +892,3 @@ Thanks to everyone who directly contributed to this release: - zathras-crypto As well as everyone that helped translating on [Transifex](https://www.transifex.com/projects/p/bitcoin/). - From 5b95dd2c256dd7ba3808021adc31bb85b41553c8 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Sat, 9 Jul 2016 11:41:01 +0200 Subject: [PATCH 0612/1802] [Wallet] extend CKeyMetadata with HD keypath --- src/wallet/wallet.cpp | 2 ++ src/wallet/walletdb.h | 13 ++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index a0095ebd92e76..33e516a7f4ef9 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -126,6 +126,8 @@ CPubKey CWallet::GenerateNewKey() // childIndex | BIP32_HARDENED_KEY_LIMIT = derive childIndex in hardened child-index-range // example: 1 | BIP32_HARDENED_KEY_LIMIT == 0x80000001 == 2147483649 externalChainChildKey.Derive(childKey, hdChain.nExternalChainCounter | BIP32_HARDENED_KEY_LIMIT); + metadata.hdKeypath = "m/0'/0'/"+std::to_string(hdChain.nExternalChainCounter)+"'"; + metadata.hdMasterKeyID = hdChain.masterKeyID; // increment childkey index hdChain.nExternalChainCounter++; } while(HaveKey(childKey.key.GetPubKey().GetID())); diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index d083722dd23ac..eaa406857f2e7 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -73,9 +73,13 @@ class CHDChain class CKeyMetadata { public: - static const int CURRENT_VERSION=1; + static const int VERSION_BASIC=1; + static const int VERSION_WITH_HDDATA=10; + static const int CURRENT_VERSION=VERSION_WITH_HDDATA; int nVersion; int64_t nCreateTime; // 0 means unknown + std::string hdKeypath; //optional HD/bip32 keypath + CKeyID hdMasterKeyID; //id of the hd masterkey used to derive this key CKeyMetadata() { @@ -85,6 +89,7 @@ class CKeyMetadata { nVersion = CKeyMetadata::CURRENT_VERSION; nCreateTime = nCreateTime_; + hdKeypath.clear(); } ADD_SERIALIZE_METHODS; @@ -94,12 +99,18 @@ class CKeyMetadata READWRITE(this->nVersion); nVersion = this->nVersion; READWRITE(nCreateTime); + if (this->nVersion >= VERSION_WITH_HDDATA) + { + READWRITE(hdKeypath); + READWRITE(hdMasterKeyID); + } } void SetNull() { nVersion = CKeyMetadata::CURRENT_VERSION; nCreateTime = 0; + hdKeypath.clear(); } }; From b1c7b244e21ba67c38fe3d1a4d1638ca52835ac5 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Sat, 9 Jul 2016 11:41:32 +0200 Subject: [PATCH 0613/1802] [Wallet] report optional HDKeypath/HDMasterKeyId in validateaddress --- src/rpc/misc.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index f2a29416e675d..a8c5bcd177fbc 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -166,6 +166,8 @@ UniValue validateaddress(const UniValue& params, bool fHelp) " \"pubkey\" : \"publickeyhex\", (string) The hex value of the raw public key\n" " \"iscompressed\" : true|false, (boolean) If the address is compressed\n" " \"account\" : \"account\" (string) DEPRECATED. The account associated with the address, \"\" is the default account\n" + " \"hdkeypath\" : \"keypath\" (string, optional) The HD keypath if the key is HD and available\n" + " \"hdmasterkeyid\" : \"\" (string, optional) The Hash160 of the HD master pubkey\n" "}\n" "\nExamples:\n" + HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"") @@ -200,6 +202,12 @@ UniValue validateaddress(const UniValue& params, bool fHelp) ret.pushKVs(detail); if (pwalletMain && pwalletMain->mapAddressBook.count(dest)) ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name)); + CKeyID keyID; + if (pwalletMain && address.GetKeyID(keyID) && pwalletMain->mapKeyMetadata.count(keyID) && !pwalletMain->mapKeyMetadata[keyID].hdKeypath.empty()) + { + ret.push_back(Pair("hdkeypath", pwalletMain->mapKeyMetadata[keyID].hdKeypath)); + ret.push_back(Pair("hdmasterkeyid", pwalletMain->mapKeyMetadata[keyID].hdMasterKeyID.GetHex())); + } #endif } return ret; From 986c2232143e5c2f909f5b27bf74470654faf49c Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Sat, 9 Jul 2016 11:25:02 +0200 Subject: [PATCH 0614/1802] [Wallet] print hd masterkeyid in getwalletinfo --- src/wallet/rpcwallet.cpp | 4 ++++ src/wallet/wallet.h | 1 + 2 files changed, 5 insertions(+) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 8538f880ff636..f4625743b3583 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2269,6 +2269,7 @@ UniValue getwalletinfo(const UniValue& params, bool fHelp) " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n" " \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n" " \"paytxfee\": x.xxxx, (numeric) the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB\n" + " \"masterkeyid\": \"\", (string) the Hash160 of the hd master pubkey\n" "}\n" "\nExamples:\n" + HelpExampleCli("getwalletinfo", "") @@ -2288,6 +2289,9 @@ UniValue getwalletinfo(const UniValue& params, bool fHelp) if (pwalletMain->IsCrypted()) obj.push_back(Pair("unlocked_until", nWalletUnlockTime)); obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK()))); + CKeyID masterKeyID = pwalletMain->GetHDChain().masterKeyID; + if (!masterKeyID.IsNull()) + obj.push_back(Pair("masterkeyid",masterKeyID.GetHex())); return obj; } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 7fc6ce5de5af1..d58cb7b0e4fdd 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -901,6 +901,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface /* Set the current hd master key (will reset the chain child index counters) */ bool SetHDMasterKey(const CKey& key); + const CHDChain& GetHDChain() { return hdChain; } }; /** A key allocated from the key pool. */ From f70808596fb4108e53c8b433820593b88c4fa81b Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Sat, 9 Jul 2016 12:05:30 +0200 Subject: [PATCH 0615/1802] [QA] extend wallet-hd test to cover HD metadata --- qa/rpc-tests/wallet-hd.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/qa/rpc-tests/wallet-hd.py b/qa/rpc-tests/wallet-hd.py index 845eec027bde2..f3ae69e1062d5 100755 --- a/qa/rpc-tests/wallet-hd.py +++ b/qa/rpc-tests/wallet-hd.py @@ -30,6 +30,10 @@ def setup_network(self): def run_test (self): tmpdir = self.options.tmpdir + # Make sure we use hd, keep masterkeyid + masterkeyid = self.nodes[1].getwalletinfo()['masterkeyid'] + assert_equal(len(masterkeyid), 40) + # Import a non-HD private key in the HD wallet non_hd_add = self.nodes[0].getnewaddress() self.nodes[1].importprivkey(self.nodes[0].dumpprivkey(non_hd_add)) @@ -45,6 +49,9 @@ def run_test (self): num_hd_adds = 300 for _ in range(num_hd_adds): hd_add = self.nodes[1].getnewaddress() + hd_info = self.nodes[1].validateaddress(hd_add) + assert_equal(hd_info["hdkeypath"], "m/0'/0'/"+str(_+1)+"'") + assert_equal(hd_info["hdmasterkeyid"], masterkeyid) self.nodes[0].sendtoaddress(hd_add, 1) self.nodes[0].generate(1) self.nodes[0].sendtoaddress(non_hd_add, 1) @@ -64,6 +71,9 @@ def run_test (self): hd_add_2 = None for _ in range(num_hd_adds): hd_add_2 = self.nodes[1].getnewaddress() + hd_info_2 = self.nodes[1].validateaddress(hd_add_2) + assert_equal(hd_info_2["hdkeypath"], "m/0'/0'/"+str(_+1)+"'") + assert_equal(hd_info_2["hdmasterkeyid"], masterkeyid) assert_equal(hd_add, hd_add_2) # Needs rescan From b993671921c0c301f18c542e77d695fdc50ffd91 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Sat, 9 Jul 2016 12:56:56 +0200 Subject: [PATCH 0616/1802] [Wallet] keep HD seed during salvagewallet --- src/wallet/wallet.cpp | 2 +- src/wallet/walletdb.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index a0095ebd92e76..7cb294bec14a6 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3291,7 +3291,7 @@ bool CWallet::InitLoadWallet() if (fFirstRun) { // Create new keyUser and set as default key - if (GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET)) { + if (GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET) && walletInstance->hdChain.masterKeyID.IsNull()) { // generate a new master key CKey key; key.MakeNewKey(true); diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 7bfd4909506f3..72af8ab7b25e6 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -977,7 +977,7 @@ bool CWalletDB::Recover(CDBEnv& dbenv, const std::string& filename, bool fOnlyKe fReadOK = ReadKeyValue(&dummyWallet, ssKey, ssValue, wss, strType, strErr); } - if (!IsKeyType(strType)) + if (!IsKeyType(strType) && strType != "hdchain") continue; if (!fReadOK) { From 4831a16223dbb42da3091e616c47eeb01f53f73b Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 12 Jul 2016 09:36:17 +0000 Subject: [PATCH 0617/1802] qt: periodic translation update Added languages: - `bg_BG`: Bulgarian (Bulgaria) --- src/Makefile.qt.include | 1 + src/qt/bitcoin_locale.qrc | 1 + src/qt/locale/bitcoin_af.ts | 4 - src/qt/locale/bitcoin_ar.ts | 158 ++++++++++++++++-- src/qt/locale/bitcoin_bg.ts | 4 - src/qt/locale/bitcoin_bg_BG.ts | 236 +++++++++++++++++++++++++++ src/qt/locale/bitcoin_ca.ts | 12 -- src/qt/locale/bitcoin_ca@valencia.ts | 12 -- src/qt/locale/bitcoin_ca_ES.ts | 12 -- src/qt/locale/bitcoin_cs.ts | 12 -- src/qt/locale/bitcoin_da.ts | 12 -- src/qt/locale/bitcoin_de.ts | 58 +++++-- src/qt/locale/bitcoin_el_GR.ts | 4 - src/qt/locale/bitcoin_en_GB.ts | 12 -- src/qt/locale/bitcoin_eo.ts | 4 - src/qt/locale/bitcoin_es.ts | 12 -- src/qt/locale/bitcoin_es_CL.ts | 4 - src/qt/locale/bitcoin_es_DO.ts | 4 - src/qt/locale/bitcoin_et.ts | 4 - src/qt/locale/bitcoin_fa.ts | 4 - src/qt/locale/bitcoin_fa_IR.ts | 4 - src/qt/locale/bitcoin_fi.ts | 12 -- src/qt/locale/bitcoin_fr.ts | 12 -- src/qt/locale/bitcoin_fr_FR.ts | 4 - src/qt/locale/bitcoin_gl.ts | 4 - src/qt/locale/bitcoin_he.ts | 4 - src/qt/locale/bitcoin_hr.ts | 4 - src/qt/locale/bitcoin_hu.ts | 4 - src/qt/locale/bitcoin_id_ID.ts | 4 - src/qt/locale/bitcoin_it.ts | 12 -- src/qt/locale/bitcoin_ja.ts | 12 -- src/qt/locale/bitcoin_ka.ts | 4 - src/qt/locale/bitcoin_ko_KR.ts | 12 -- src/qt/locale/bitcoin_la.ts | 4 - src/qt/locale/bitcoin_lt.ts | 4 - src/qt/locale/bitcoin_lv_LV.ts | 4 - src/qt/locale/bitcoin_mn.ts | 4 - src/qt/locale/bitcoin_nb.ts | 12 -- src/qt/locale/bitcoin_nl.ts | 12 -- src/qt/locale/bitcoin_pam.ts | 4 - src/qt/locale/bitcoin_pl.ts | 12 -- src/qt/locale/bitcoin_pt_BR.ts | 60 +++++-- src/qt/locale/bitcoin_pt_PT.ts | 12 -- src/qt/locale/bitcoin_ro_RO.ts | 4 - src/qt/locale/bitcoin_ru.ts | 108 ++++++++++-- src/qt/locale/bitcoin_sk.ts | 12 -- src/qt/locale/bitcoin_sl_SI.ts | 12 -- src/qt/locale/bitcoin_sv.ts | 12 -- src/qt/locale/bitcoin_ta.ts | 4 - src/qt/locale/bitcoin_tr.ts | 12 -- src/qt/locale/bitcoin_uk.ts | 12 -- src/qt/locale/bitcoin_uz@Cyrl.ts | 4 - src/qt/locale/bitcoin_zh_CN.ts | 12 -- src/qt/locale/bitcoin_zh_TW.ts | 14 +- 54 files changed, 574 insertions(+), 422 deletions(-) create mode 100644 src/qt/locale/bitcoin_bg_BG.ts diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index ca2c7b2eb0d83..7730aba375c44 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -8,6 +8,7 @@ QT_TS = \ qt/locale/bitcoin_ar.ts \ qt/locale/bitcoin_be_BY.ts \ qt/locale/bitcoin_bg.ts \ + qt/locale/bitcoin_bg_BG.ts \ qt/locale/bitcoin_ca_ES.ts \ qt/locale/bitcoin_ca.ts \ qt/locale/bitcoin_ca@valencia.ts \ diff --git a/src/qt/bitcoin_locale.qrc b/src/qt/bitcoin_locale.qrc index 54d36ac0118fa..8dd07c3d41777 100644 --- a/src/qt/bitcoin_locale.qrc +++ b/src/qt/bitcoin_locale.qrc @@ -5,6 +5,7 @@ locale/bitcoin_ar.qm locale/bitcoin_be_BY.qm locale/bitcoin_bg.qm + locale/bitcoin_bg_BG.qm locale/bitcoin_ca_ES.qm locale/bitcoin_ca.qm locale/bitcoin_ca@valencia.qm diff --git a/src/qt/locale/bitcoin_af.ts b/src/qt/locale/bitcoin_af.ts index 7c2d294c7e8ff..97ada8dd5c63a 100644 --- a/src/qt/locale/bitcoin_af.ts +++ b/src/qt/locale/bitcoin_af.ts @@ -256,10 +256,6 @@ Bitcoin Core Bitcoin Kern - - WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) - WAARSKUWING: toets die status van u netwerk, %d blokke ontvang in die laaste %d ure (%d verwag) - Do not keep transactions in the mempool longer than <n> hours (default: %u) Moenie transaksies vir langer as <n> ure in die geheuepoel hou nie (verstek: %u) diff --git a/src/qt/locale/bitcoin_ar.ts b/src/qt/locale/bitcoin_ar.ts index 78fd074434316..af62207df2bde 100644 --- a/src/qt/locale/bitcoin_ar.ts +++ b/src/qt/locale/bitcoin_ar.ts @@ -110,10 +110,6 @@ Quit application الخروج من التطبيق - - &About %1 - &عن %1 - Show information about %1 أظهر المعلومات حولة %1 @@ -306,6 +302,20 @@ Catching up... اللحاق بالركب ... + + Date: %1 + + التاريخ %1 + + + + + + Label: %1 + + علامه: %1 + + Sent transaction المعاملات المرسلة @@ -325,10 +335,18 @@ CoinControlDialog + + Coin Selection + اختيار العمله + Quantity: الكمية : + + Bytes: + بايت + Amount: القيمة : @@ -341,6 +359,10 @@ Fee: رسوم : + + Dust: + غبار: + After Fee: بعد الرسوم : @@ -349,9 +371,21 @@ Change: تعديل : + + (un)select all + عدم اختيار الجميع + + + Tree mode + صيغة الشجرة + + + List mode + صيغة القائمة + Amount - المبلغ + مبلغ Received with label @@ -363,11 +397,11 @@ Date - التاريخ + تاريخ Confirmations - تأكيد + تأكيدات Confirmed @@ -388,6 +422,14 @@ &Label &وصف + + The label associated with this address list entry + الملصق المرتبط بقائمة العناوين المدخلة + + + The address associated with this address list entry. This can only be modified for sending addresses. + العنوان المرتبط بقائمة العناوين المدخلة. و التي يمكن تعديلها فقط بواسطة ارسال العناوين + &Address &العنوان @@ -442,6 +484,14 @@ Choose data directory on startup (default: %u) اختر دليل البيانات عند بدء التشغير (افتراضي: %u) + + Set language, for example "de_DE" (default: system locale) + أضع لغة, على سبيل المثال " de_DE " (افتراضي:- مكان النظام) + + + Start minimized + الدخول مصغر + Set SSL root certificates for payment request (default: -system-) أضع شهادة بروتوكول الشبقة الأمنية لطلب المدفوع (افتراضي: -نظام-) @@ -450,7 +500,11 @@ Show splash screen on startup (default: %u) أظهر شاشة البداية عند بدء التشغيل (افتراضي: %u) - + + Reset all settings changed in the GUI + اعد تعديل جميع النظم المتغيرة في GUI + + Intro @@ -472,6 +526,14 @@ OpenURIDialog + + Open URI + افتح URL + + + Open payment request from URI or file + حدد طلب الدفع من ملف او URI + Select payment request file حدد ملف طلب الدفع @@ -527,10 +589,18 @@ Port of the proxy (e.g. 9050) منفذ البروكسي (مثلا 9050) + + Used for reaching peers via: + مستخدم للاتصال بالاصدقاء من خلال: + &Window نافذه + + Hide tray icon + اخفاء لوحة الايقون + &Display &عرض @@ -615,10 +685,6 @@ RPCConsole - - Client name - اسم العميل - N/A غير معروف @@ -663,6 +729,10 @@ Sent تم الإرسال + + &Peers + &اصدقاء + Direction جهة @@ -703,6 +773,22 @@ Out: خارج: + + 1 &hour + 1 &ساعة + + + 1 &day + 1 & يوم + + + 1 &week + 1 & اسبوع + + + 1 &year + 1 & سنة + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. استخدم اسهم الاعلى و الاسفل للتنقل بين السجلات و <b>Ctrl-L</b> لمسح الشاشة @@ -723,6 +809,18 @@ %1 GB %1 قيقا بايت + + never + ابدا + + + Inbound + داخل + + + Outbound + خارجي + Yes نعم @@ -808,6 +906,10 @@ Quantity: الكمية : + + Bytes: + بايت + Amount: القيمة : @@ -836,6 +938,14 @@ Hide إخفاء + + normal + طبيعي + + + fast + سريع + Send to multiple recipients at once إرسال إلى عدة مستلمين في وقت واحد @@ -848,6 +958,10 @@ Clear all fields of the form. مسح كل حقول النموذج المطلوبة + + Dust: + غبار + Clear &All مسح الكل @@ -879,6 +993,18 @@ &Label: &وصف : + + Choose previously used address + اختر عنوانا مستخدم سابقا + + + This is a normal payment. + هذا دفع اعتيادي + + + The Bitcoin address to send the payment to + عنوان البت كوين المرسل اليه الدفع + Alt+A Alt+A @@ -891,6 +1017,10 @@ Alt+P Alt+P + + Remove this entry + ازل هذه المداخله + Message: الرسائل @@ -913,6 +1043,10 @@ &Sign Message &توقيع الرسالة + + Choose previously used address + اختر عنوانا مستخدم سابقا + Alt+A Alt+A diff --git a/src/qt/locale/bitcoin_bg.ts b/src/qt/locale/bitcoin_bg.ts index bd85d8c8b0e1f..acb60cf41c5aa 100644 --- a/src/qt/locale/bitcoin_bg.ts +++ b/src/qt/locale/bitcoin_bg.ts @@ -881,10 +881,6 @@ RPCConsole - - Client name - Име на клиента - N/A Несъществуващ diff --git a/src/qt/locale/bitcoin_bg_BG.ts b/src/qt/locale/bitcoin_bg_BG.ts new file mode 100644 index 0000000000000..4bddb5ff4a8ae --- /dev/null +++ b/src/qt/locale/bitcoin_bg_BG.ts @@ -0,0 +1,236 @@ + + + AddressBookPage + + Right-click to edit address or label + Клик с десен бутон на мишката за промяна на адрес или етикет + + + Create a new address + Създай нов адрес + + + &New + Нов + + + Copy the currently selected address to the system clipboard + Копирай текущо избрания адрес към клипборда + + + &Copy + Копирай + + + C&lose + Затвори + + + Delete the currently selected address from the list + Изтрий текущо избрания адрес от листа + + + Export the data in the current tab to a file + Изнеси данните в избрания раздел към файл + + + &Export + Изнеси + + + &Delete + Изтрий + + + + AskPassphraseDialog + + Passphrase Dialog + Диалог за пропуск + + + Enter passphrase + Въведи парола + + + New passphrase + Нова парола + + + Repeat new passphrase + Повтори парола + + + + BanTableModel + + IP/Netmask + IP/Мрежова маска + + + Banned Until + Блокиран до + + + + BitcoinGUI + + Sign &message... + Подпиши съобщение... + + + Synchronizing with network... + Синхронизиране с мрежата... + + + &Overview + Преглед + + + Node + Възел + + + Show general overview of wallet + Покажи общ преглед на портфейла + + + &Transactions + Транзакции + + + Browse transaction history + Разгледай история на транзакциите + + + E&xit + Изход + + + Quit application + Излез от приложението + + + &About %1 + За %1 + + + Show information about %1 + Покажи информация за %1 + + + About &Qt + Относно Qt + + + Show information about Qt + Покажи информация отностно Qt + + + &Options... + Настройки... + + + Modify configuration options for %1 + Промени конфигурации за %1 + + + &Encrypt Wallet... + Криптирай портфейл + + + &Backup Wallet... + Направи резервно копие на портфейла... + + + &Change Passphrase... + Промени паролата... + + + &Sending addresses... + Адреси за пращане... + + + &Receiving addresses... + Адреси за получаване... + + + Open &URI... + Отвори URI + + + Reindexing blocks on disk... + Повторно индексиране на блоковете на диска... + + + + CoinControlDialog + + + EditAddressDialog + + + FreespaceChecker + + + HelpMessageDialog + + + Intro + + + OpenURIDialog + + + OptionsDialog + + + OverviewPage + + + PeerTableModel + + + QObject + + + RPCConsole + + + ReceiveCoinsDialog + + + ReceiveRequestDialog + + + SendCoinsDialog + + + SendCoinsEntry + + + ShutdownWindow + + + SignVerifyMessageDialog + + + SplashScreen + + + TrafficGraphWidget + + + TransactionDescDialog + + + UnitDisplayStatusBarControl + + + bitcoin-core + + Bitcoin Core + Биткойн ядро + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_ca.ts b/src/qt/locale/bitcoin_ca.ts index 3eb384868ed43..ed259c4d08de9 100644 --- a/src/qt/locale/bitcoin_ca.ts +++ b/src/qt/locale/bitcoin_ca.ts @@ -925,10 +925,6 @@ RPCConsole - - Client name - Nom del client - N/A N/A @@ -1738,14 +1734,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Aquesta és una versió de pre-llançament - utilitza-la sota la teva responsabilitat - No usar per a minería o aplicacions de compra-venda - - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) - AVÍS: s'ha generat un nombre anòmalament alt de blocs, %d blocs rebuts en les darreres %d hores (se n'esperaven %d) - - - WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) - AVÍS: comproveu la vostra connexió a la xarxa, %d blocs rebuts en les darreres %d hores (se n'esperaven %d) - Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Avís: la xarxa no sembla que hi estigui plenament d'acord. Alguns miners sembla que estan experimentant problemes. diff --git a/src/qt/locale/bitcoin_ca@valencia.ts b/src/qt/locale/bitcoin_ca@valencia.ts index 1fdf0249a5b73..df0f750a61352 100644 --- a/src/qt/locale/bitcoin_ca@valencia.ts +++ b/src/qt/locale/bitcoin_ca@valencia.ts @@ -869,10 +869,6 @@ RPCConsole - - Client name - Nom del client - N/A N/A @@ -1570,14 +1566,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Esta és una versió de pre-llançament - utilitza-la sota la teva responsabilitat - No usar per a minería o aplicacions de compra-venda - - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) - AVÍS: s'ha generat un nombre anòmalament alt de blocs, %d blocs rebuts en les darreres %d hores (se n'esperaven %d) - - - WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) - AVÍS: comproveu la vostra connexió a la xarxa, %d blocs rebuts en les darreres %d hores (se n'esperaven %d) - Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Avís: la xarxa no pareix que hi estiga plenament d'acord. Alguns miners pareix que estan experimentant problemes. diff --git a/src/qt/locale/bitcoin_ca_ES.ts b/src/qt/locale/bitcoin_ca_ES.ts index 30004e10e405a..f985a6928d938 100644 --- a/src/qt/locale/bitcoin_ca_ES.ts +++ b/src/qt/locale/bitcoin_ca_ES.ts @@ -925,10 +925,6 @@ RPCConsole - - Client name - Nom del client - N/A N/A @@ -1734,14 +1730,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Aquesta és una versió de pre-llançament - utilitza-la sota la teva responsabilitat - No usar per a minería o aplicacions de compra-venda - - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) - AVÍS: s'ha generat un nombre anòmalament alt de blocs, %d blocs rebuts en les darreres %d hores (se n'esperaven %d) - - - WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) - AVÍS: comproveu la vostra connexió a la xarxa, %d blocs rebuts en les darreres %d hores (se n'esperaven %d) - Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Avís: la xarxa no sembla que hi estigui plenament d'acord. Alguns miners sembla que estan experimentant problemes. diff --git a/src/qt/locale/bitcoin_cs.ts b/src/qt/locale/bitcoin_cs.ts index d76839723fc0e..2dfa295ce078f 100644 --- a/src/qt/locale/bitcoin_cs.ts +++ b/src/qt/locale/bitcoin_cs.ts @@ -917,10 +917,6 @@ RPCConsole - - Client name - Název klienta - N/A N/A @@ -1714,14 +1710,6 @@ Use UPnP to map the listening port (default: 1 when listening and no -proxy) Použít UPnP k namapování naslouchacího portu (výchozí: 1, pokud naslouchá a nepoužívá -proxy) - - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) - UPOZORNĚNÍ: vygenerováno nezvykle mnoho bloků – přijato %d bloků jen za posledních %d hodin (očekáváno %d) - - - WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) - UPOZORNĚNÍ: zkontroluj své spojení do sítě – bylo přijato %d bloků za posledních %d hodin (očekáváno %d) - Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Upozornění: Síť podle všeho není v konzistentním stavu. Někteří těžaři jsou zřejmě v potížích. diff --git a/src/qt/locale/bitcoin_da.ts b/src/qt/locale/bitcoin_da.ts index fd1a4a08638aa..d298c81bd453d 100644 --- a/src/qt/locale/bitcoin_da.ts +++ b/src/qt/locale/bitcoin_da.ts @@ -993,10 +993,6 @@ RPCConsole - - Client name - Klientnavn - N/A N/A @@ -1886,14 +1882,6 @@ Use UPnP to map the listening port (default: 1 when listening and no -proxy) Brug UPnP for at konfigurere den lyttende port (standard: 1 under lytning og ingen -proxy) - - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) - ADVARSEL: unormalt mange blokke er genereret; %d blokke er modtaget i løbet af de seneste %d timer (%d forventet) - - - WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) - ADVARSEL: tjek din netværksforbindelse; %d blokke er modtaget i løbet af de seneste %d timer (%d forventet) - Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Advarsel: Netværket ser ikke ud til at være fuldt ud enige! Enkelte minere ser ud til at opleve problemer. diff --git a/src/qt/locale/bitcoin_de.ts b/src/qt/locale/bitcoin_de.ts index 77482c774bb80..f38f4c10f7148 100644 --- a/src/qt/locale/bitcoin_de.ts +++ b/src/qt/locale/bitcoin_de.ts @@ -781,6 +781,14 @@ &Window &Programmfenster + + &Hide the icon from the system tray. + &Das Icon im System Tray verstecken. + + + Hide tray icon + Tray Icon verstecken + Show only a tray icon after minimizing the window. Nur ein Symbol im Infobereich anzeigen, nachdem das Programmfenster minimiert wurde. @@ -981,10 +989,6 @@ RPCConsole - - Client name - Clientname - N/A k.A. @@ -1011,7 +1015,7 @@ Datadir - Datenverz + Datenverzeichnis Startup time @@ -1097,6 +1101,10 @@ User Agent User-Agent + + Open the %1 debug log file from the current data directory. This can take a few seconds for large log files. + Öffnet die %1-Debugprotokolldatei aus dem aktuellen Datenverzeichnis. Dies kann bei großen Protokolldateien einige Sekunden dauern. + Decrease font size Schrift verkleinern @@ -1790,6 +1798,10 @@ Bind to given address and always listen on it. Use [host]:port notation for IPv6 An die angegebene Adresse binden und immer abhören. Für IPv6 "[Host]:Port"-Notation verwenden + + Cannot obtain a lock on data directory %s. %s is probably already running. + Datenverzeichnis %s kann nicht gesperrt werden. Evtl. wurde %s bereits gestartet. + Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup Alle Wallet-Transaktionen löschen und nur diese Teilbereiche der Blockkette durch -rescan beim Starten wiederherstellen @@ -1806,6 +1818,14 @@ Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) Leite Transaktionen von Peers auf der Positivliste auf jeden Fall weiter, auch wenn sie die lokale Weiterleitungsregeln verletzen (Standardeinstellung: %d) + + Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly. + Bitte korrigieren Sie die Datums- und Uhrzeiteinstellungen Ihres Computers, da %s ansonsten nicht ordnungsgemäß funktionieren wird. + + + Please contribute if you find %s useful. Visit %s for further information about the software. + Wenn sie %s nützlich finden, sind Helfer sehr gern gesehen. Besuchen Sie %s um mehr über das Softwareprojekt zu erfahren. + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) Maximale Anzahl an Skript-Verifizierungs-Threads festlegen (%u bis %d, 0 = automatisch, <0 = so viele Kerne frei lassen, Standard: %d) @@ -1822,14 +1842,6 @@ Use UPnP to map the listening port (default: 1 when listening and no -proxy) UPnP verwenden, um eine Portweiterleitung einzurichten (Standard: 1, wenn abgehört wird und -proxy nicht gesetzt ist) - - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) - Warnung: Es wurde eine ungewöhnlich hohe Anzahl Blöcke erzeugt, %d Blöcke wurden in den letzten %d Stunden empfangen (%d wurden erwartet). - - - WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) - Warnung: Überprüpfen Sie ihre Netzwerkverbindung, %d Blöcke wurden in den letzten %d Stunden empfangen (%d wurden erwartet). - Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Warnung: Das Netzwerk scheint nicht vollständig übereinzustimmen! Einige Miner scheinen Probleme zu haben. @@ -1842,6 +1854,14 @@ Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. Gegenstellen die sich von der angegebenen Netzmaske oder IP-Adresse aus verbinden immer zulassen. Kann mehrmals angegeben werden. + + You need to rebuild the database using -reindex-chainstate to change -txindex + Sie müssen die Datenbank mit Hilfe von -reindex-chainstate neu aufbauen, um -txindex zu verändern + + + %s corrupt, salvage failed + %s beschädigt, Datenrettung fehlgeschlagen + -maxmempool must be at least %d MB -maxmempool muss mindestens %d MB betragen @@ -1854,6 +1874,10 @@ Append comment to the user agent string Hänge ein Kommentar zur User Agent-Zeichenkette an + + Attempt to recover private keys from a corrupt wallet on startup + Es wird versucht, private Schlüssel beim Starten aus einem beschädigtem Wallet wiederherzustellen + Block creation options: Blockerzeugungsoptionen: @@ -1918,6 +1942,14 @@ Error loading %s Fehler beim Laden von %s + + Error loading %s: Wallet corrupted + Fehler beim Laden von %s: Das Wallet ist beschädigt + + + Error loading %s: Wallet requires newer version of %s + Fehler beim Laden von %s: Das Wallet benötigt eine neuere Version von %s + Error loading block database Fehler beim Laden der Blockdatenbank diff --git a/src/qt/locale/bitcoin_el_GR.ts b/src/qt/locale/bitcoin_el_GR.ts index 59779692d9028..2814e4f6e7a0e 100644 --- a/src/qt/locale/bitcoin_el_GR.ts +++ b/src/qt/locale/bitcoin_el_GR.ts @@ -834,10 +834,6 @@ RPCConsole - - Client name - Όνομα Πελάτη - N/A Μη διαθέσιμο diff --git a/src/qt/locale/bitcoin_en_GB.ts b/src/qt/locale/bitcoin_en_GB.ts index 226444e9c56c6..1893aaca09b22 100644 --- a/src/qt/locale/bitcoin_en_GB.ts +++ b/src/qt/locale/bitcoin_en_GB.ts @@ -993,10 +993,6 @@ RPCConsole - - Client name - Client name - N/A N/A @@ -1886,14 +1882,6 @@ Use UPnP to map the listening port (default: 1 when listening and no -proxy) Use UPnP to map the listening port (default: 1 when listening and no -proxy) - - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) - - - WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) - WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) - Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. diff --git a/src/qt/locale/bitcoin_eo.ts b/src/qt/locale/bitcoin_eo.ts index 043b28abc6ac6..4471aeb72e6e7 100644 --- a/src/qt/locale/bitcoin_eo.ts +++ b/src/qt/locale/bitcoin_eo.ts @@ -741,10 +741,6 @@ RPCConsole - - Client name - Nomo de kliento - N/A neaplikebla diff --git a/src/qt/locale/bitcoin_es.ts b/src/qt/locale/bitcoin_es.ts index 80cbe399321d2..c67016637b516 100644 --- a/src/qt/locale/bitcoin_es.ts +++ b/src/qt/locale/bitcoin_es.ts @@ -989,10 +989,6 @@ RPCConsole - - Client name - Nombre del cliente - N/A N/D @@ -1885,14 +1881,6 @@ Use UPnP to map the listening port (default: 1 when listening and no -proxy) Utiliza UPnP para asignar el puerto de escucha (predeterminado: 1 cuando esta escuchando sin -proxy) - - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) - ADVERTENCIA: anormalmente alto número de bloques generado, %d bloques recibidos en las últimas horas %d (%d espera) - - - WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) - ADVERTENCIA: comprueba tu conexión de red, %d bloques recibidos en las últimas %d horas (%d esperados) - Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Atención: ¡Parece que la red no está totalmente de acuerdo! Algunos mineros están presentando inconvenientes. diff --git a/src/qt/locale/bitcoin_es_CL.ts b/src/qt/locale/bitcoin_es_CL.ts index ff0fce61192f7..188641d6e7ace 100644 --- a/src/qt/locale/bitcoin_es_CL.ts +++ b/src/qt/locale/bitcoin_es_CL.ts @@ -457,10 +457,6 @@ RPCConsole - - Client name - Nombre del cliente - N/A N/A diff --git a/src/qt/locale/bitcoin_es_DO.ts b/src/qt/locale/bitcoin_es_DO.ts index 3f4380840a068..ba963d2b8042f 100644 --- a/src/qt/locale/bitcoin_es_DO.ts +++ b/src/qt/locale/bitcoin_es_DO.ts @@ -639,10 +639,6 @@ RPCConsole - - Client name - Nombre del cliente - N/A N/D diff --git a/src/qt/locale/bitcoin_et.ts b/src/qt/locale/bitcoin_et.ts index e861d4e472312..0d659fd71951b 100644 --- a/src/qt/locale/bitcoin_et.ts +++ b/src/qt/locale/bitcoin_et.ts @@ -541,10 +541,6 @@ RPCConsole - - Client name - Kliendi nimi - N/A N/A diff --git a/src/qt/locale/bitcoin_fa.ts b/src/qt/locale/bitcoin_fa.ts index 5bebb35822c23..8bf727a0cd645 100644 --- a/src/qt/locale/bitcoin_fa.ts +++ b/src/qt/locale/bitcoin_fa.ts @@ -729,10 +729,6 @@ RPCConsole - - Client name - نام کلاینت - N/A ناموجود diff --git a/src/qt/locale/bitcoin_fa_IR.ts b/src/qt/locale/bitcoin_fa_IR.ts index b329612ded011..8faa3ce659266 100644 --- a/src/qt/locale/bitcoin_fa_IR.ts +++ b/src/qt/locale/bitcoin_fa_IR.ts @@ -299,10 +299,6 @@ RPCConsole - - Client name - نام کنسول RPC - Client version ویرایش کنسول RPC diff --git a/src/qt/locale/bitcoin_fi.ts b/src/qt/locale/bitcoin_fi.ts index c2226e9b985f2..b7b3115e251eb 100644 --- a/src/qt/locale/bitcoin_fi.ts +++ b/src/qt/locale/bitcoin_fi.ts @@ -929,10 +929,6 @@ RPCConsole - - Client name - Pääteohjelman nimi - N/A Ei saatavilla @@ -1718,14 +1714,6 @@ Use UPnP to map the listening port (default: 1 when listening and no -proxy) Käytä UPnP:ta kuuntelevan portin kartoitukseen (oletus: 1 kun kuunnellaan ja -proxy ei käytössä) - - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) - VAROITUS: epätavallisen monta lohkoa generoitu, vastaanotettu %d lohkoa viimeisen %d tunnin aikana (odotettavissa %d) - - - WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) - VAROITUS: tarkista verkkoyhteytesi, vastaanotettu %d lohkoa viimeisen %d tunnin aikana (odotettavissa %d) - Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Varoitus: Tietoverkko ei ole sovussa! Luohijat näyttävät kokevan virhetilanteita. diff --git a/src/qt/locale/bitcoin_fr.ts b/src/qt/locale/bitcoin_fr.ts index 5c4f7f2b04ae2..0b538d76642ed 100644 --- a/src/qt/locale/bitcoin_fr.ts +++ b/src/qt/locale/bitcoin_fr.ts @@ -993,10 +993,6 @@ RPCConsole - - Client name - Nom du client - N/A N.D. @@ -1866,14 +1862,6 @@ Use UPnP to map the listening port (default: 1 when listening and no -proxy) Utiliser l'UPnP pour mapper le port d'écoute (par défaut : 1 lors de l'écoute et pas de mandataire -proxy) - - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) - AVERTISSEMENT : un nombre anormalement élevé de blocs a été généré, %d blocs reçus durant les %d dernières heures (%d attendus) - - - WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) - AVERTISSEMENT : vérifiez votre connexion réseau, %d blocs reçus durant les %d dernières heures (%d attendus) - Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Avertissement : le réseau ne semble pas totalement d'accord ! Quelques mineurs semblent éprouver des difficultés. diff --git a/src/qt/locale/bitcoin_fr_FR.ts b/src/qt/locale/bitcoin_fr_FR.ts index 08824e113a552..a6f6ac4fd100a 100644 --- a/src/qt/locale/bitcoin_fr_FR.ts +++ b/src/qt/locale/bitcoin_fr_FR.ts @@ -809,10 +809,6 @@ RPCConsole - - Client name - Nom du client - N/A N/A diff --git a/src/qt/locale/bitcoin_gl.ts b/src/qt/locale/bitcoin_gl.ts index f3673b6dc74f8..9aa7b5509646e 100644 --- a/src/qt/locale/bitcoin_gl.ts +++ b/src/qt/locale/bitcoin_gl.ts @@ -595,10 +595,6 @@ RPCConsole - - Client name - Nome do cliente - N/A N/A diff --git a/src/qt/locale/bitcoin_he.ts b/src/qt/locale/bitcoin_he.ts index fbe16364eb82a..4a293c1c3f227 100644 --- a/src/qt/locale/bitcoin_he.ts +++ b/src/qt/locale/bitcoin_he.ts @@ -827,10 +827,6 @@ RPCConsole - - Client name - שם לקוח - N/A לא זמין diff --git a/src/qt/locale/bitcoin_hr.ts b/src/qt/locale/bitcoin_hr.ts index 0d8d3d5c99e78..f5accfb0b8fe8 100644 --- a/src/qt/locale/bitcoin_hr.ts +++ b/src/qt/locale/bitcoin_hr.ts @@ -657,10 +657,6 @@ RPCConsole - - Client name - Ime klijenta - N/A N/A diff --git a/src/qt/locale/bitcoin_hu.ts b/src/qt/locale/bitcoin_hu.ts index bddc430f22312..9eb0cf76c4319 100644 --- a/src/qt/locale/bitcoin_hu.ts +++ b/src/qt/locale/bitcoin_hu.ts @@ -805,10 +805,6 @@ RPCConsole - - Client name - Kliens néve - N/A Nem elérhető diff --git a/src/qt/locale/bitcoin_id_ID.ts b/src/qt/locale/bitcoin_id_ID.ts index fe07ab7a29045..feb6f690c4595 100644 --- a/src/qt/locale/bitcoin_id_ID.ts +++ b/src/qt/locale/bitcoin_id_ID.ts @@ -853,10 +853,6 @@ RPCConsole - - Client name - Nama Klien - N/A T/S diff --git a/src/qt/locale/bitcoin_it.ts b/src/qt/locale/bitcoin_it.ts index b92dbb2cb3b34..55bc9c3c82470 100644 --- a/src/qt/locale/bitcoin_it.ts +++ b/src/qt/locale/bitcoin_it.ts @@ -930,10 +930,6 @@ Per specificare più URL separarli con una barra verticale "|". RPCConsole - - Client name - Nome del client - N/A N/D @@ -1747,14 +1743,6 @@ Per specificare più URL separarli con una barra verticale "|". Use UPnP to map the listening port (default: 1 when listening and no -proxy) Utilizza UPnP per mappare la porta in ascolto (default: 1 quando in ascolto e -proxy non è specificato) - - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) - ATTENZIONE, il numero di blocchi generati è insolitamente elevato: %d blocchi ricevuti nelle ultime %d ore (%d previsti) - - - WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) - ATTENZIONE, si consiglia di verificare la connessione di rete: %d blocchi ricevuti nelle ultime %d ore (%d previsti) - Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Attenzione: La rete non sembra trovarsi in pieno consenso! Alcuni minatori sembrano riscontrare problemi. diff --git a/src/qt/locale/bitcoin_ja.ts b/src/qt/locale/bitcoin_ja.ts index 460a652e3750a..4948cc30675e9 100644 --- a/src/qt/locale/bitcoin_ja.ts +++ b/src/qt/locale/bitcoin_ja.ts @@ -993,10 +993,6 @@ RPCConsole - - Client name - クライアント名 - N/A N/A @@ -1886,14 +1882,6 @@ Use UPnP to map the listening port (default: 1 when listening and no -proxy) リスン ポートの割当に UPnP を使用 (初期値: リスン中および-proxyが指定されていない場合は1) - - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) - 警告:異常に多くの数のブロックが生成されています。%d ブロックが最近 %d 時間以内に受け取られました。(期待値: %d) - - - WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) - 警告:ネットワーク接続を確認してください。%d ブロックが最近 %d 時間以内にに受け取られました。(期待値: %d) - Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. 警告: ネットワークは完全に同意しないみたいです。マイナーは何かの問題を経験してるみたいなんです。 diff --git a/src/qt/locale/bitcoin_ka.ts b/src/qt/locale/bitcoin_ka.ts index 22e7651f6344d..80508be8eeb82 100644 --- a/src/qt/locale/bitcoin_ka.ts +++ b/src/qt/locale/bitcoin_ka.ts @@ -663,10 +663,6 @@ RPCConsole - - Client name - კლიენტი - N/A მიუწვდ. diff --git a/src/qt/locale/bitcoin_ko_KR.ts b/src/qt/locale/bitcoin_ko_KR.ts index 11e5d35af2465..012632c0e0a9f 100644 --- a/src/qt/locale/bitcoin_ko_KR.ts +++ b/src/qt/locale/bitcoin_ko_KR.ts @@ -925,10 +925,6 @@ RPCConsole - - Client name - 클라이언트 이름 - N/A 없음 @@ -1758,14 +1754,6 @@ Use UPnP to map the listening port (default: 1 when listening and no -proxy) 리슨(Listen) 포트를 할당하기 위해 UPnP 사용 (기본값: 열려있거나 -proxy 옵션을 사용하지 않을 시 1) - - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) - 경고: 비정상적으로 많은 블록이 생성되고 있습니다. %d 블록은 마지막 %d에 수신되었습니다 (%d 예측됨) - - - WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) - 경고: 네트워크 연결을 확인해 주세요. %d 블록은 마지막 %d에 수신되었습니다 (%d 예측됨) - Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. 경고 : 모든 네트워크가 동의해야 하나, 일부 채굴자들에게 문제가 있는 것으로 보입니다. diff --git a/src/qt/locale/bitcoin_la.ts b/src/qt/locale/bitcoin_la.ts index ebaddba7e930e..dc532fe011933 100644 --- a/src/qt/locale/bitcoin_la.ts +++ b/src/qt/locale/bitcoin_la.ts @@ -443,10 +443,6 @@ RPCConsole - - Client name - Nomen clientis - N/A N/A diff --git a/src/qt/locale/bitcoin_lt.ts b/src/qt/locale/bitcoin_lt.ts index 9e98baa77af73..1f6cda1f52b66 100644 --- a/src/qt/locale/bitcoin_lt.ts +++ b/src/qt/locale/bitcoin_lt.ts @@ -563,10 +563,6 @@ RPCConsole - - Client name - Kliento pavadinimas - N/A nėra diff --git a/src/qt/locale/bitcoin_lv_LV.ts b/src/qt/locale/bitcoin_lv_LV.ts index bac58756952ab..38333531e4816 100644 --- a/src/qt/locale/bitcoin_lv_LV.ts +++ b/src/qt/locale/bitcoin_lv_LV.ts @@ -651,10 +651,6 @@ RPCConsole - - Client name - Klienta vārds - N/A N/A diff --git a/src/qt/locale/bitcoin_mn.ts b/src/qt/locale/bitcoin_mn.ts index e38320ac5d271..d9ef0d127b8c9 100644 --- a/src/qt/locale/bitcoin_mn.ts +++ b/src/qt/locale/bitcoin_mn.ts @@ -291,10 +291,6 @@ RPCConsole - - Client name - Клиентийн нэр - N/A Алга Байна diff --git a/src/qt/locale/bitcoin_nb.ts b/src/qt/locale/bitcoin_nb.ts index b5ffdb2e10253..4538fd6e1e8c1 100644 --- a/src/qt/locale/bitcoin_nb.ts +++ b/src/qt/locale/bitcoin_nb.ts @@ -929,10 +929,6 @@ RPCConsole - - Client name - Klientnavn - N/A - @@ -1746,14 +1742,6 @@ Use UPnP to map the listening port (default: 1 when listening and no -proxy) Bruk UPnP for lytteport (standardverdi: 1 ved lytting og uten -proxy) - - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) - ADVARSEL: unormalt høyt antall blokker generert, %d blokker mottatt de siste %d timene (%d forventet) - - - WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) - ADVARSEL: kontroller nettverkstilkoblingen, mottok %d blokker i de siste %d timene (%d forventet) - Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Advarsel: Nettverket ser ikke ut til å være enig! Noen minere ser ut til å ha problemer. diff --git a/src/qt/locale/bitcoin_nl.ts b/src/qt/locale/bitcoin_nl.ts index 2b0cded386d2c..781c5a8fd6672 100644 --- a/src/qt/locale/bitcoin_nl.ts +++ b/src/qt/locale/bitcoin_nl.ts @@ -993,10 +993,6 @@ RPCConsole - - Client name - Clientnaam - N/A N.v.t. @@ -1870,14 +1866,6 @@ Use UPnP to map the listening port (default: 1 when listening and no -proxy) Gebruik UPnP om de luisterende poort te mappen (standaard: 1 als er geluisterd worden en geen -proxy is meegegeven) - - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) - WAARSCHUWING: abnormaal hoog aantal blokken is gegenereerd, %d blokken ontvangen in de laatste %d uren (%d verwacht) - - - WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) - WAARSCHUWING: controleer uw netwerkverbinding, %d blokken ontvangen in de laatste %d uren (%d verwacht) - Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Waarschuwing: Het lijkt erop dat het netwerk geen consensus kan vinden! Sommige delvers lijken problemen te ondervinden. diff --git a/src/qt/locale/bitcoin_pam.ts b/src/qt/locale/bitcoin_pam.ts index 12151a576c984..53515433384c3 100644 --- a/src/qt/locale/bitcoin_pam.ts +++ b/src/qt/locale/bitcoin_pam.ts @@ -427,10 +427,6 @@ RPCConsole - - Client name - Lagyu ning kliente - N/A N/A diff --git a/src/qt/locale/bitcoin_pl.ts b/src/qt/locale/bitcoin_pl.ts index 6d41cbeef227e..a88e505b398b4 100644 --- a/src/qt/locale/bitcoin_pl.ts +++ b/src/qt/locale/bitcoin_pl.ts @@ -993,10 +993,6 @@ RPCConsole - - Client name - Nazwa klienta - N/A NIEDOSTĘPNE @@ -1839,14 +1835,6 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw Use UPnP to map the listening port (default: 1 when listening and no -proxy) Użyj UPnP do mapowania portu nasłuchu (domyślnie: 1 gdy nasłuchuje i brak -proxy) - - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) - UWAGA: nienaturalnie duża liczba wygenerowanych bloków, %d bloków otrzymano w ostatnich %d godzinach (%d oczekiwanych) - - - WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) - UWAGA: sprawdź swoje połączenie sieciowe, %d bloków otrzymano w ostatnich %d godzinach (%d oczekiwanych) - Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Ostrzeżenie: Sieć nie wydaje się w pełni zgodna! Niektórzy górnicy wydają się doświadczać problemów. diff --git a/src/qt/locale/bitcoin_pt_BR.ts b/src/qt/locale/bitcoin_pt_BR.ts index fe9dd66269ff5..29414303920ed 100644 --- a/src/qt/locale/bitcoin_pt_BR.ts +++ b/src/qt/locale/bitcoin_pt_BR.ts @@ -114,6 +114,10 @@ &About %1 &About %1 + + Show information about %1 + Mostrar informações sobre %1 + About &Qt Sobre &Qt @@ -571,6 +575,14 @@ Welcome to %1. Bem vindo ao %1 + + As this is the first time the program is launched, you can choose where %1 will store its data. + Como essa é a primeira vez que o programa é executado, você pode escolher onde %1 armazenará seus dados. + + + %1 will download and store a copy of the Bitcoin block chain. At least %2GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. + O %1 irá baixar e armazenar uma cópia do block chain do Bitcoin. Pelo menos %2GB de dados serão armazenados neste diretório, e ele crescerá ao longo do tempo. A carteira também será armazenada neste diretório. + Use the default data directory Use o diretório de dados padrão @@ -981,10 +993,6 @@ RPCConsole - - Client name - Nome do cliente - N/A N/A @@ -1009,6 +1017,10 @@ Using BerkeleyDB version Versão do BerkeleyDB + + Datadir + Datadir + Startup time Horário de inicialização @@ -1093,6 +1105,10 @@ User Agent User Agent + + Open the %1 debug log file from the current data directory. This can take a few seconds for large log files. + Abrir o arquivo de log de depuração do %1 localizado no diretório atual de dados. Isso pode levar alguns segundos para arquivos de log grandes. + Decrease font size Diminuir o tamanho da fonte @@ -1794,6 +1810,10 @@ Bind to given address and always listen on it. Use [host]:port notation for IPv6 Vincular ao endereço fornecido e sempre escutar nele. Use a notação [host]:port para IPv6 + + Cannot obtain a lock on data directory %s. %s is probably already running. + Não foi possível obter exclusividade de escrita no endereço %s. O %s provavelmente já está sendo executado. + Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup Apaga todas as transações da carteira e somente recupera essas partes da blockchain usando o comando -rescan na inicialização @@ -1802,6 +1822,14 @@ Distributed under the MIT software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>. Distribuido sob a licença MIT software license. Veja os termos em <http://www.opensource.org/licenses/mit-license.php>. + + Error loading %s: You can't enable HD on a already existing non-HD wallet + Erro ao carregar %s. Não é permitido habilitar HD em carteiras não-HD pre existentes. + + + Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Erro ao ler arquivo %s! Todas as chaves foram lidas corretamente, mas os dados de transação ou o livro de endereos podem estar faltando ou incorretos. + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) Executa um comando quando uma transação da carteira mudar (%s no comando será substituído por TxID) @@ -1810,6 +1838,22 @@ Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) Força a retransmissão de transações de pares da lista branca, mesmo quando violam a política local de retransmissão (default: %d) + + Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds) + A mediana máxima permitida de peer time compensa o ajuste. Perspectiva local de horário pode ser influenciada por pares à frente ou atrás neste montante. (padrão: %u segundos) + + + Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s) + Preço máximo total (in %s) aplicado a uma única transação de carteira ou transação crua; aplicar isto tão baixo pode abortar grandes transações (padrão: %s) + + + Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly. + Por favor verifique que 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ão corretamente. + + + Please contribute if you find %s useful. Visit %s for further information about the software. + Por favor contribua se você entender que %s é útil. Visite %s para mais informações sobre o software. + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) Define o número de threads de verificação de script (%u a %d, 0 = automático, <0 = número de cores deixados livres, padrão: %d) @@ -1826,14 +1870,6 @@ Use UPnP to map the listening port (default: 1 when listening and no -proxy) Use UPnP para mapear a porta escutada (padrão: 1 quando escutando e sem -proxy) - - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) - AVISO: números estranhamente altos de blocos gerados, %d blocos recebidos nas últimas %d horas (%d esperados) - - - WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) - ATENÇÃO: verifique sua conexão %d blocos recebidos nas últimas %d horas (%d tempo estimado) - Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Atenção: A rede não parecem concordar plenamente! Alguns mineiros parecem estar enfrentando problemas. diff --git a/src/qt/locale/bitcoin_pt_PT.ts b/src/qt/locale/bitcoin_pt_PT.ts index 16b912dfdc57b..f63bfece69cc5 100644 --- a/src/qt/locale/bitcoin_pt_PT.ts +++ b/src/qt/locale/bitcoin_pt_PT.ts @@ -962,10 +962,6 @@ RPCConsole - - Client name - Nome do Cliente - N/A N/D @@ -1811,14 +1807,6 @@ Use UPnP to map the listening port (default: 1 when listening and no -proxy) Utilizar UPnP para mapear a porta de escuta (predefinição: 1 quando escutar e sem -proxy) - - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) - AVISO: gerado um número anormalmente elevado de blocos, %d blocos recebidos nas últimas %d horas (%d esperados) - - - WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) - AVISO: verifique a sua conexão à rede, %d blocos recebidos nas últimas %d horas (%d esperados) - Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Aviso: A rede não parece estar completamente de acordo! Parece que alguns mineiros estão com dificuldades técnicas. diff --git a/src/qt/locale/bitcoin_ro_RO.ts b/src/qt/locale/bitcoin_ro_RO.ts index e6f591aa9e67c..489ed07639189 100644 --- a/src/qt/locale/bitcoin_ro_RO.ts +++ b/src/qt/locale/bitcoin_ro_RO.ts @@ -913,10 +913,6 @@ RPCConsole - - Client name - Nume client - N/A indisponibil diff --git a/src/qt/locale/bitcoin_ru.ts b/src/qt/locale/bitcoin_ru.ts index 750ea7db650a2..60f5d5dfa2a4c 100644 --- a/src/qt/locale/bitcoin_ru.ts +++ b/src/qt/locale/bitcoin_ru.ts @@ -989,10 +989,6 @@ RPCConsole - - Client name - Имя клиента - N/A Н/Д @@ -1109,6 +1105,14 @@ Open the %1 debug log file from the current data directory. This can take a few seconds for large log files. Открыть отладочный лог-файл %1 из текущего каталога данных. Это может занять несколько секунд для больших лог-файлов. + + Decrease font size + Уменьшить размер текста + + + Increase font size + Увеличить размер текста + Services Сервисы @@ -1213,6 +1217,10 @@ &Unban Node &Разблокировать узел + + Welcome to the %1 RPC console. + Добро пожаловать в консоль RPC %1. + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. Используйте стрелки вверх и вниз для просмотра истории и <b>Ctrl-L</b> для очистки экрана. @@ -1592,6 +1600,10 @@ ShutdownWindow + + %1 is shutting down... + %1 выключается... + Do not shut down the computer until this window disappears. Не выключайте компьютер, пока это окно не исчезнет. @@ -1782,10 +1794,22 @@ Bitcoin Core Bitcoin Core + + The %s developers + Разработчики %s + + + -fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available. + Установлено очень большое значение -fallbackfee! Это комиссия за транзацию, которую вы можете заплатить, если оценка размера комиссии не доступна. + Bind to given address and always listen on it. Use [host]:port notation for IPv6 Привязаться к указанному адресу и всегда прослушивать только его. Используйте [хост]:порт для IPv6 + + Cannot obtain a lock on data directory %s. %s is probably already running. + Невозможно заблокировать каталог данных %s. %s возможно уже работает. + Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup Удалить все транзакции бумажника с возможностью восстановить эти части цепи блоков с помощью -rescan при запуске @@ -1794,6 +1818,10 @@ Distributed under the MIT software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>. Распространяется под лицензией MIT, см. приложенный файл COPYING или <http://www.opensource.org/licenses/mit-license.php>. + + Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Ошибка чтения %s! Все ключи прочитаны верно, но данные транзакций или записи адресной книги могут отсутствовать или быть неправильными. + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) Выполнить команду, когда меняется транзакция в бумажнике (%s в команде заменяется на TxID) @@ -1802,6 +1830,10 @@ Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d) Всегда разрешать транзакции, полученные от участников из белого списка (по умолчанию: %d) + + Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly. + Пожалуйста убедитесь в корректности установки времени и даты на вашем компьютере! Если время установлено неверно, %s не будет работать правильно. + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) Задать число потоков проверки скрипта (от %u до %d, 0=авто, <0 = оставить столько ядер свободными, по умолчанию: %d) @@ -1818,14 +1850,6 @@ Use UPnP to map the listening port (default: 1 when listening and no -proxy) Использовать UPnP для проброса порта (по умолчанию: 1, если используется прослушивание и нет -proxy) - - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) - ВНИМАНИЕ: сгенерировано ненормально большое число блоков, %d блоков получено за последние %d часов (ожидалось %d) - - - WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) - ВНИМАНИЕ: проверьте сетевое подключение, получено %d блоков за последние %d часов (ожидалось %d) - Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Внимание: похоже, в сети нет полного согласия! Некоторый майнеры, возможно, испытывают проблемы. @@ -1838,6 +1862,10 @@ Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times. Вносить в белый список участников, подключающихся с указанной маски сети или IP. Можно использовать многократно. + + %s corrupt, salvage failed + %s поврежден, восстановить не удалось + -maxmempool must be at least %d MB -maxmempool должен быть как минимум %d MB @@ -1850,6 +1878,10 @@ Append comment to the user agent string Добавить комментарий к строке пользовательского агента + + Attempt to recover private keys from a corrupt wallet on startup + Попытаться восстановить приватные ключи из повреждённого бумажника при запуске + Block creation options: Параметры создания блоков: @@ -1862,6 +1894,10 @@ Connection options: Параметры подключения: + + Copyright (C) %i-%i + Copyright (C) %i-%i + Corrupted block database detected БД блоков повреждена @@ -1906,6 +1942,14 @@ Error loading %s Ошибка загрузки %s + + Error loading %s: Wallet corrupted + Ошибка загрузки %s: Бумажник поврежден + + + Error loading %s: Wallet requires newer version of %s + Ошибка загрузки %s: Для бумажника требуется более новая версия %s + Error loading block database Ошибка чтения базы данных блоков @@ -1934,10 +1978,18 @@ Invalid -onion address: '%s' Неверный -onion адрес: '%s' + + Invalid amount for -%s=<amount>: '%s' + Неверная сумма для -%s=<amount>: '%s' + Keep the transaction memory pool below <n> megabytes (default: %u) Сбрасывать транзакции из памяти на диск каждые <n> мегабайт (по умолчанию: %u) + + Loading banlist... + Загрузка банлиста... + Location of the auth cookie (default: data dir) Расположение куки входы(по умолчанию: data dir) @@ -1950,6 +2002,10 @@ Only connect to nodes in network <net> (ipv4, ipv6 or onion) Соединяться только по сети <net> (ipv4, ipv6 или onion) + + Print this help message and exit + Вывести эту справку и выйти + Print version and exit Написать версию и выйти @@ -1962,10 +2018,18 @@ Prune mode is incompatible with -txindex. Режим удаления блоков несовместим с -txindex. + + Rebuild chain state from the currently indexed blocks + Перестроить индекс цепи из текущих индексированных блоков + Set database cache size in megabytes (%d to %d, default: %d) Установить размер кэша БД в мегабайтах(от %d до %d, по умолчанию: %d) + + Set maximum block cost (default: %d) + Задать максимальную стоимость блока (по умолчанию: %d) + Set maximum block size in bytes (default: %d) Задать максимальный размер блока в байтах (по умолчанию: %d) @@ -1974,6 +2038,14 @@ Specify wallet file (within data directory) Укажите файл бумажника (внутри каталога данных) + + The source code is available from %s. + Исходный код доступен в %s. + + + Unable to bind to %s on this computer. %s is probably already running. + Невозможно привязаться к %s на этом компьютере. Возможно, %s уже работает. + Unsupported argument -benchmark ignored, use -debug=bench. Неподдерживаемый аргумент -benchmark проигнорирован, используйте -debug=bench. @@ -2006,6 +2078,14 @@ Wallet %s resides outside data directory %s Бумажник %s располагается вне каталога данных %s + + Wallet debugging/testing options: + Параметры отладки/тестирования бумажника: + + + Wallet needed to be rewritten: restart %s to complete + Необходимо перезаписать бумажник, перезапустите %s для завершения операции. + Wallet options: Настройки бумажника: @@ -2306,6 +2386,10 @@ Warning: Unknown block versions being mined! It's possible unknown rules are in effect Внимание: Получена неизвестная версия блока! Возможно неизвестные правила вступили в силу. + + Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup. + Внимание: Файл бумажника поврежден, данные восстановлены! Оригинальный %s сохранен как %s в %s; Если баланс или транзакции некорректны, вы должны восстановить файл из резервной копии. + (default: %s) (по умолчанию: %s) diff --git a/src/qt/locale/bitcoin_sk.ts b/src/qt/locale/bitcoin_sk.ts index e2b8a0201599b..a4f0ebcb4e17c 100644 --- a/src/qt/locale/bitcoin_sk.ts +++ b/src/qt/locale/bitcoin_sk.ts @@ -929,10 +929,6 @@ RPCConsole - - Client name - Meno klienta - N/A nie je k dispozícii @@ -1707,14 +1703,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Toto je pred-testovacia verzia - použitie je na vlastné riziko - nepoužívajte na tvorbu bitcoin ani obchodovanie. - - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) - VAROVANIE: príliš veľa vygenerovaných blokov; %d prijatých blokov v posledných %d hodinách (očakávaných %d) - - - WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) - VAROVANIE: skontrolujte sieťové pripojenie, %d prijatých blokov za posledných %d hodín (očakávané %d) - Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Varovanie: Javí sa že sieť sieť úplne nesúhlasí! Niektorí mineri zjavne majú ťažkosti. diff --git a/src/qt/locale/bitcoin_sl_SI.ts b/src/qt/locale/bitcoin_sl_SI.ts index 155be7bb27144..16ef20ea3a061 100644 --- a/src/qt/locale/bitcoin_sl_SI.ts +++ b/src/qt/locale/bitcoin_sl_SI.ts @@ -869,10 +869,6 @@ RPCConsole - - Client name - Ime odjemalca - N/A Neznano @@ -1566,14 +1562,6 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications To je preizkusna različica še neizdanega programa. Uporabljate jo na lastno odgovornost. Programa ne uporabljajte je za rudarjenje ali trgovske aplikacije. - - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) - OPOZORILO: Generirano je bilo nenavadno veliko število blokov. Št. prejetih blokov: %d v št. ur: %d (pričakovanih je %d blokov) - - - WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) - OPOZORILO: Preverite vašo omrežno povezavo. Št. prejetih blokov: %d v št. ur: %d (pričakovanih je %d blokov) - Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Opozorilo: Trenutno na omrežju ni videti konsenza! Videti je, kot da bi imeli nekateri rudarji težave. diff --git a/src/qt/locale/bitcoin_sv.ts b/src/qt/locale/bitcoin_sv.ts index 6361b5ea5ff87..ee46974d8b4e5 100644 --- a/src/qt/locale/bitcoin_sv.ts +++ b/src/qt/locale/bitcoin_sv.ts @@ -993,10 +993,6 @@ RPCConsole - - Client name - Klientnamn - N/A ej tillgänglig @@ -1882,14 +1878,6 @@ Use UPnP to map the listening port (default: 1 when listening and no -proxy) Använd UPnP för att mappa den lyssnande porten (förvalt: 1 när lyssning aktiverat och utan -proxy) - - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) - Varning: Onormalt antal block block genererade. %d block mottagna senaste %d timmarna (%d förväntade) - - - WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) - Varning: Kontrollera din närverksanslutning. %d block mottagna senaste %d timmarna, (%d förväntade) - Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Varning: Nätverket verkar inte vara helt överens! Några miners verkar ha problem. diff --git a/src/qt/locale/bitcoin_ta.ts b/src/qt/locale/bitcoin_ta.ts index 6878d23fe22ea..921171c5449b2 100644 --- a/src/qt/locale/bitcoin_ta.ts +++ b/src/qt/locale/bitcoin_ta.ts @@ -371,10 +371,6 @@ RPCConsole - - Client name - வாடிக்கையாளர் பெயர் - N/A N/A diff --git a/src/qt/locale/bitcoin_tr.ts b/src/qt/locale/bitcoin_tr.ts index f6ab2ca18b6cf..bbd0117404c22 100644 --- a/src/qt/locale/bitcoin_tr.ts +++ b/src/qt/locale/bitcoin_tr.ts @@ -993,10 +993,6 @@ RPCConsole - - Client name - İstemci ismi - N/A Mevcut değil @@ -1874,14 +1870,6 @@ Use UPnP to map the listening port (default: 1 when listening and no -proxy) Dinlenecek portu haritalamak için UPnP kullan (varsayılan: dinlenildiğinde ve -proxy olmadığında 1) - - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) - İKAZ: anormal yüksek sayıda blok oluşturulmuştur, %d blok son %d saat içinde alınmıştır (%d bekleniyordu) - - - WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) - İKAZ: ağ bağlantınızı kontrol ediniz, %d blok son %d saat içinde alınmıştır (%d bekleniyordu) - Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Uyarı: şebeke tamamen mutabık değil gibi görünüyor! Bazı madenciler sorun yaşıyor gibi görünüyor. diff --git a/src/qt/locale/bitcoin_uk.ts b/src/qt/locale/bitcoin_uk.ts index 668e787a6eca8..a06cc9e0921a8 100644 --- a/src/qt/locale/bitcoin_uk.ts +++ b/src/qt/locale/bitcoin_uk.ts @@ -929,10 +929,6 @@ RPCConsole - - Client name - Назва клієнту - N/A Н/Д @@ -1746,14 +1742,6 @@ Use UPnP to map the listening port (default: 1 when listening and no -proxy) Використовувати UPnP для відображення порту, що прослуховується (типово: 1 при прослуховуванні та за відсутності -proxy) - - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) - УВАГА: аномально висока кількість згенерованих блоків, %d блок(ів) було отримано за останні %d годин(и) (має бути %d) - - - WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) - УВАГА: перевірте ваше мережеве з'єднання, %d блок(ів) було отримано за останні %d годин(и) (має бути %d) - Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Увага: Частина мережі використовує інший головний ланцюжок! Деякі добувачі, можливо, зазнають проблем. diff --git a/src/qt/locale/bitcoin_uz@Cyrl.ts b/src/qt/locale/bitcoin_uz@Cyrl.ts index ce33262976d7e..0062abfc1d444 100644 --- a/src/qt/locale/bitcoin_uz@Cyrl.ts +++ b/src/qt/locale/bitcoin_uz@Cyrl.ts @@ -727,10 +727,6 @@ RPCConsole - - Client name - Мижоз номи - N/A Тўғри келмайди diff --git a/src/qt/locale/bitcoin_zh_CN.ts b/src/qt/locale/bitcoin_zh_CN.ts index 8f467b79c1cc5..92a7006d30fdf 100644 --- a/src/qt/locale/bitcoin_zh_CN.ts +++ b/src/qt/locale/bitcoin_zh_CN.ts @@ -929,10 +929,6 @@ RPCConsole - - Client name - 客户端名称 - N/A 不可用 @@ -1763,14 +1759,6 @@ Use UPnP to map the listening port (default: 1 when listening and no -proxy) 使用UPnP暴露本机监听端口(默认:1 当正在监听且不使用代理) - - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) - 警告:数据块生成数量异常,最近 %d 小时收到了 %d 个数据块(预期为 %d 个) - - - WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) - 警告:请检查您的网络连接,最近 %d 小时收到了 %d 个数据块(预期为 %d 个) - Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. 警告:网络似乎并不完全同意!有些矿工似乎遇到了问题。 diff --git a/src/qt/locale/bitcoin_zh_TW.ts b/src/qt/locale/bitcoin_zh_TW.ts index c71a37ba986e0..ab56f96795a50 100644 --- a/src/qt/locale/bitcoin_zh_TW.ts +++ b/src/qt/locale/bitcoin_zh_TW.ts @@ -993,10 +993,6 @@ RPCConsole - - Client name - 客戶端軟體名稱 - N/A 未知 @@ -1865,7 +1861,7 @@ Please contribute if you find %s useful. Visit %s for further information about the software. - 如果你覺得 %s 有用,可以捐助我們。關於這個軟體的更多資訊請見 %s。 + 如果你覺得 %s 有用,可以幫助我們。關於這個軟體的更多資訊請見 %s。 Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) @@ -1887,14 +1883,6 @@ Use UPnP to map the listening port (default: 1 when listening and no -proxy) 是否要使用「通用即插即用」協定(UPnP),來設定聽候連線的通訊埠的對應(預設值: 當有聽候連線且沒有指定 -proxy 參數時為 1) - - WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected) - 警告: 收到了不尋常地多的 %d 個區塊在過去 %d 小時內生產出來(預期是 %d 個) - - - WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) - 警告: 請檢查你的網路連線狀況,收到了 %d 個區塊是在過去 %d 小時內生產出來(預期是 %d 個) - Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. 警告: 節點網路對於區塊鏈結的決定目前有分歧!看來有些礦工會有問題。 From 96fa95361f68dd8169fa60e73290afae47445299 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Wed, 6 Jul 2016 21:18:38 -0400 Subject: [PATCH 0618/1802] Improve handling of unconnecting headers When processing a headers message that looks like a block announcement, send peer a getheaders if the headers message won't connect. Apply DoS points after too many consecutive unconnecting headers messages. --- src/main.cpp | 38 +++++++++++++++++++++++++++++++++++++- src/main.h | 3 +++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index b86bbda1b8f9e..dd71ee551028b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -276,6 +276,8 @@ struct CNodeState { CBlockIndex *pindexLastCommonBlock; //! The best header we have sent our peer. CBlockIndex *pindexBestHeaderSent; + //! Length of current-streak of unconnecting headers announcements + int nUnconnectingHeaders; //! Whether we've started headers synchronization with this peer. bool fSyncStarted; //! Since when we're stalling block download progress (in microseconds), or 0. @@ -304,6 +306,7 @@ struct CNodeState { hashLastUnknownBlock.SetNull(); pindexLastCommonBlock = NULL; pindexBestHeaderSent = NULL; + nUnconnectingHeaders = 0; fSyncStarted = false; nStallingSince = 0; nDownloadingSince = 0; @@ -5773,6 +5776,35 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, return true; } + CNodeState *nodestate = State(pfrom->GetId()); + + // If this looks like it could be a block announcement (nCount < + // MAX_BLOCKS_TO_ANNOUNCE), use special logic for handling headers that + // don't connect: + // - Send a getheaders message in response to try to connect the chain. + // - The peer can send up to MAX_UNCONNECTING_HEADERS in a row that + // don't connect before giving DoS points + // - Once a headers message is received that is valid and does connect, + // nUnconnectingHeaders gets reset back to 0. + if (mapBlockIndex.find(headers[0].hashPrevBlock) == mapBlockIndex.end() && nCount < MAX_BLOCKS_TO_ANNOUNCE) { + nodestate->nUnconnectingHeaders++; + pfrom->PushMessage(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), uint256()); + LogPrint("net", "received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d, nUnconnectingHeaders=%d)\n", + headers[0].GetHash().ToString(), + headers[0].hashPrevBlock.ToString(), + pindexBestHeader->nHeight, + pfrom->id, nodestate->nUnconnectingHeaders); + // Set hashLastUnknownBlock for this peer, so that if we + // eventually get the headers - even from a different peer - + // we can use this peer to download. + UpdateBlockAvailability(pfrom->GetId(), headers.back().GetHash()); + + if (nodestate->nUnconnectingHeaders % MAX_UNCONNECTING_HEADERS == 0) { + Misbehaving(pfrom->GetId(), 20); + } + return true; + } + CBlockIndex *pindexLast = NULL; BOOST_FOREACH(const CBlockHeader& header, headers) { CValidationState state; @@ -5790,6 +5822,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } } + if (nodestate->nUnconnectingHeaders > 0) { + LogPrint("net", "peer=%d: resetting nUnconnectingHeaders (%d -> 0)\n", pfrom->id, nodestate->nUnconnectingHeaders); + } + nodestate->nUnconnectingHeaders = 0; + assert(pindexLast); UpdateBlockAvailability(pfrom->GetId(), pindexLast->GetBlockHash()); @@ -5802,7 +5839,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } bool fCanDirectFetch = CanDirectFetch(chainparams.GetConsensus()); - CNodeState *nodestate = State(pfrom->GetId()); // If this set of headers is valid and ends in a block with at least as // much work as our tip, download as much as possible. if (fCanDirectFetch && pindexLast->IsValid(BLOCK_VALID_TREE) && chainActive.Tip()->nChainWork <= pindexLast->nChainWork) { diff --git a/src/main.h b/src/main.h index 7ea570d859792..65ae2488f9095 100644 --- a/src/main.h +++ b/src/main.h @@ -138,6 +138,9 @@ static const bool DEFAULT_FEEFILTER = true; /** Maximum number of headers to announce when relaying blocks with headers message.*/ static const unsigned int MAX_BLOCKS_TO_ANNOUNCE = 8; +/** Maximum number of unconnecting headers announcements before DoS score */ +static const int MAX_UNCONNECTING_HEADERS = 10; + static const bool DEFAULT_PEERBLOOMFILTERS = true; struct BlockHasher From e91cf4b210db72ed020612a04b55e9715d8f9831 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Wed, 6 Jul 2016 21:19:32 -0400 Subject: [PATCH 0619/1802] Add test for handling of unconnecting headers --- qa/rpc-tests/sendheaders.py | 105 ++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/qa/rpc-tests/sendheaders.py b/qa/rpc-tests/sendheaders.py index 6ab17d59b3878..c3f3180b6bca3 100755 --- a/qa/rpc-tests/sendheaders.py +++ b/qa/rpc-tests/sendheaders.py @@ -63,6 +63,21 @@ Expect: getdata request for 14 more blocks. f. Announce 1 more header that builds on that fork. Expect: no response. + +Part 5: Test handling of headers that don't connect. +a. Repeat 10 times: + 1. Announce a header that doesn't connect. + Expect: getheaders message + 2. Send headers chain. + Expect: getdata for the missing blocks, tip update. +b. Then send 9 more headers that don't connect. + Expect: getheaders message each time. +c. Announce a header that does connect. + Expect: no response. +d. Announce 49 headers that don't connect. + Expect: getheaders message each time. +e. Announce one more that doesn't connect. + Expect: disconnect. ''' class BaseNode(NodeConnCB): @@ -77,6 +92,8 @@ def __init__(self): self.last_getdata = None self.sleep_time = 0.05 self.block_announced = False + self.last_getheaders = None + self.disconnected = False def clear_last_announcement(self): with mininode_lock: @@ -127,6 +144,12 @@ def on_getdata(self, conn, message): def on_pong(self, conn, message): self.last_pong = message + def on_getheaders(self, conn, message): + self.last_getheaders = message + + def on_close(self, conn): + self.disconnected = True + # Test whether the last announcement we received had the # right header or the right inv # inv and headers should be lists of block hashes @@ -178,6 +201,11 @@ def wait_for_block(self, blockhash, timeout=60): self.sync(test_function, timeout) return + def wait_for_getheaders(self, timeout=60): + test_function = lambda: self.last_getheaders != None + self.sync(test_function, timeout) + return + def wait_for_getdata(self, hash_list, timeout=60): if hash_list == []: return @@ -186,6 +214,11 @@ def wait_for_getdata(self, hash_list, timeout=60): self.sync(test_function, timeout) return + def wait_for_disconnect(self, timeout=60): + test_function = lambda: self.disconnected + self.sync(test_function, timeout) + return + def send_header_for_blocks(self, new_blocks): headers_message = msg_headers() headers_message.headers = [ CBlockHeader(b) for b in new_blocks ] @@ -510,6 +543,78 @@ def run_test(self): print("Part 4: success!") + # Now deliver all those blocks we announced. + [ test_node.send_message(msg_block(x)) for x in blocks ] + + print("Part 5: Testing handling of unconnecting headers") + # First we test that receipt of an unconnecting header doesn't prevent + # chain sync. + for i in range(10): + test_node.last_getdata = None + blocks = [] + # Create two more blocks. + for j in range(2): + blocks.append(create_block(tip, create_coinbase(height), block_time)) + blocks[-1].solve() + tip = blocks[-1].sha256 + block_time += 1 + height += 1 + # Send the header of the second block -> this won't connect. + with mininode_lock: + test_node.last_getheaders = None + test_node.send_header_for_blocks([blocks[1]]) + test_node.wait_for_getheaders(timeout=1) + test_node.send_header_for_blocks(blocks) + test_node.wait_for_getdata([x.sha256 for x in blocks]) + [ test_node.send_message(msg_block(x)) for x in blocks ] + test_node.sync_with_ping() + assert_equal(int(self.nodes[0].getbestblockhash(), 16), blocks[1].sha256) + + blocks = [] + # Now we test that if we repeatedly don't send connecting headers, we + # don't go into an infinite loop trying to get them to connect. + MAX_UNCONNECTING_HEADERS = 10 + for j in range(MAX_UNCONNECTING_HEADERS+1): + blocks.append(create_block(tip, create_coinbase(height), block_time)) + blocks[-1].solve() + tip = blocks[-1].sha256 + block_time += 1 + height += 1 + + for i in range(1, MAX_UNCONNECTING_HEADERS): + # Send a header that doesn't connect, check that we get a getheaders. + with mininode_lock: + test_node.last_getheaders = None + test_node.send_header_for_blocks([blocks[i]]) + test_node.wait_for_getheaders(timeout=1) + + # Next header will connect, should re-set our count: + test_node.send_header_for_blocks([blocks[0]]) + + # Remove the first two entries (blocks[1] would connect): + blocks = blocks[2:] + + # Now try to see how many unconnecting headers we can send + # before we get disconnected. Should be 5*MAX_UNCONNECTING_HEADERS + for i in range(5*MAX_UNCONNECTING_HEADERS - 1): + # Send a header that doesn't connect, check that we get a getheaders. + with mininode_lock: + test_node.last_getheaders = None + test_node.send_header_for_blocks([blocks[i%len(blocks)]]) + test_node.wait_for_getheaders(timeout=1) + + # Eventually this stops working. + with mininode_lock: + self.last_getheaders = None + test_node.send_header_for_blocks([blocks[-1]]) + + # Should get disconnected + test_node.wait_for_disconnect() + with mininode_lock: + self.last_getheaders = True + + print("Part 5: success!") + # Finally, check that the inv node never received a getdata request, # throughout the test assert_equal(inv_node.last_getdata, None) From e37b16a75c1ff86d515ef3050d2c76432ea71225 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Tue, 12 Jul 2016 13:27:09 +1000 Subject: [PATCH 0620/1802] transaction: clarify witness branches --- src/primitives/transaction.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index e87ad90f0d498..18402ac4536e6 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -290,6 +290,8 @@ struct CMutableTransaction; */ template inline void SerializeTransaction(TxType& tx, Stream& s, Operation ser_action, int nType, int nVersion) { + const bool fAllowWitness = !(nVersion & SERIALIZE_TRANSACTION_NO_WITNESS); + READWRITE(*const_cast(&tx.nVersion)); unsigned char flags = 0; if (ser_action.ForRead()) { @@ -298,7 +300,7 @@ inline void SerializeTransaction(TxType& tx, Stream& s, Operation ser_action, in const_cast(&tx.wit)->SetNull(); /* Try to read the vin. In case the dummy is there, this will be read as an empty vector. */ READWRITE(*const_cast*>(&tx.vin)); - if (tx.vin.size() == 0 && !(nVersion & SERIALIZE_TRANSACTION_NO_WITNESS)) { + if (tx.vin.size() == 0 && fAllowWitness) { /* We read a dummy or an empty vin. */ READWRITE(flags); if (flags != 0) { @@ -309,7 +311,7 @@ inline void SerializeTransaction(TxType& tx, Stream& s, Operation ser_action, in /* We read a non-empty vin. Assume a normal vout follows. */ READWRITE(*const_cast*>(&tx.vout)); } - if ((flags & 1) && !(nVersion & SERIALIZE_TRANSACTION_NO_WITNESS)) { + if ((flags & 1) && fAllowWitness) { /* The witness flag is present, and we support witnesses. */ flags ^= 1; const_cast(&tx.wit)->vtxinwit.resize(tx.vin.size()); @@ -322,7 +324,7 @@ inline void SerializeTransaction(TxType& tx, Stream& s, Operation ser_action, in } else { // Consistency check assert(tx.wit.vtxinwit.size() <= tx.vin.size()); - if (!(nVersion & SERIALIZE_TRANSACTION_NO_WITNESS)) { + if (fAllowWitness) { /* Check whether witnesses need to be serialized. */ if (!tx.wit.IsNull()) { flags |= 1; From 66668c420a23936cb228737f982ee58c08211071 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 14 Jul 2016 10:30:03 +0200 Subject: [PATCH 0621/1802] [qa] Solve merge conflict of 4324bd237c3147fc153ba5046c211f03e8ac956a --- qa/rpc-tests/p2p-segwit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qa/rpc-tests/p2p-segwit.py b/qa/rpc-tests/p2p-segwit.py index 9d64c5fe3633a..b30d41af92935 100755 --- a/qa/rpc-tests/p2p-segwit.py +++ b/qa/rpc-tests/p2p-segwit.py @@ -306,7 +306,7 @@ def test_unnecessary_witness_before_segwit_activation(self): tx3 = CTransaction() tx3.vin.append(CTxIn(COutPoint(tx2.sha256, 0), CScript([p2sh_program]))) tx3.vout.append(CTxOut(tx2.vout[0].nValue-1000, scriptPubKey)) - tx3.wit.vtxinwit.append(CTxinWitness()) + tx3.wit.vtxinwit.append(CTxInWitness()) tx3.wit.vtxinwit[0].scriptWitness.stack = [b'a'*400000] tx3.rehash() self.std_node.test_transaction_acceptance(tx3, True, False, b'no-witness-yet') From 68d7682b9f8c0f548e0a9ef03296320b8ae3960d Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 15 Jul 2016 10:33:25 +0200 Subject: [PATCH 0622/1802] [Wallet] ensure CKeyMetadata.hdMasterKeyID will be cleared during SetNull() --- src/wallet/walletdb.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index eaa406857f2e7..42179f2288782 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -87,9 +87,8 @@ class CKeyMetadata } CKeyMetadata(int64_t nCreateTime_) { - nVersion = CKeyMetadata::CURRENT_VERSION; + SetNull(); nCreateTime = nCreateTime_; - hdKeypath.clear(); } ADD_SERIALIZE_METHODS; @@ -111,6 +110,7 @@ class CKeyMetadata nVersion = CKeyMetadata::CURRENT_VERSION; nCreateTime = 0; hdKeypath.clear(); + hdMasterKeyID.SetNull(); } }; From 7945088d413819d8cf1772fd25e0f355c84c64d6 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 15 Jul 2016 10:34:08 +0200 Subject: [PATCH 0623/1802] [Wallet] comsetic non-code changes for the HD feature --- qa/rpc-tests/wallet-hd.py | 4 ++-- src/wallet/rpcwallet.cpp | 4 ++-- src/wallet/wallet.h | 6 +++--- src/wallet/walletdb.h | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/qa/rpc-tests/wallet-hd.py b/qa/rpc-tests/wallet-hd.py index f3ae69e1062d5..c738ee2207e5a 100755 --- a/qa/rpc-tests/wallet-hd.py +++ b/qa/rpc-tests/wallet-hd.py @@ -47,10 +47,10 @@ def run_test (self): self.nodes[0].generate(101) hd_add = None num_hd_adds = 300 - for _ in range(num_hd_adds): + for i in range(num_hd_adds): hd_add = self.nodes[1].getnewaddress() hd_info = self.nodes[1].validateaddress(hd_add) - assert_equal(hd_info["hdkeypath"], "m/0'/0'/"+str(_+1)+"'") + assert_equal(hd_info["hdkeypath"], "m/0'/0'/"+str(i+1)+"'") assert_equal(hd_info["hdmasterkeyid"], masterkeyid) self.nodes[0].sendtoaddress(hd_add, 1) self.nodes[0].generate(1) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index f4625743b3583..960d193e5d4d5 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2269,7 +2269,7 @@ UniValue getwalletinfo(const UniValue& params, bool fHelp) " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n" " \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n" " \"paytxfee\": x.xxxx, (numeric) the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB\n" - " \"masterkeyid\": \"\", (string) the Hash160 of the hd master pubkey\n" + " \"masterkeyid\": \"\", (string) the Hash160 of the HD master pubkey\n" "}\n" "\nExamples:\n" + HelpExampleCli("getwalletinfo", "") @@ -2291,7 +2291,7 @@ UniValue getwalletinfo(const UniValue& params, bool fHelp) obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK()))); CKeyID masterKeyID = pwalletMain->GetHDChain().masterKeyID; if (!masterKeyID.IsNull()) - obj.push_back(Pair("masterkeyid",masterKeyID.GetHex())); + obj.push_back(Pair("masterkeyid", masterKeyID.GetHex())); return obj; } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index d58cb7b0e4fdd..e9d669a7d1e30 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -577,7 +577,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface void SyncMetaData(std::pair); - /* the hd chain data model (external chain counters) */ + /* the HD chain data model (external chain counters) */ CHDChain hdChain; public: @@ -896,10 +896,10 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface bool BackupWallet(const std::string& strDest); - /* Set the hd chain model (chain child index counters) */ + /* Set the HD chain model (chain child index counters) */ bool SetHDChain(const CHDChain& chain, bool memonly); - /* Set the current hd master key (will reset the chain child index counters) */ + /* Set the current HD master key (will reset the chain child index counters) */ bool SetHDMasterKey(const CKey& key); const CHDChain& GetHDChain() { return hdChain; } }; diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 42179f2288782..5addd5c5c0225 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -41,7 +41,7 @@ enum DBErrors DB_NEED_REWRITE }; -/* simple hd chain data model */ +/* simple HD chain data model */ class CHDChain { public: @@ -79,7 +79,7 @@ class CKeyMetadata int nVersion; int64_t nCreateTime; // 0 means unknown std::string hdKeypath; //optional HD/bip32 keypath - CKeyID hdMasterKeyID; //id of the hd masterkey used to derive this key + CKeyID hdMasterKeyID; //id of the HD masterkey used to derive this key CKeyMetadata() { From fae596f0e421148b797197baff089a87b3193dbd Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 30 Jun 2016 14:49:59 +0200 Subject: [PATCH 0624/1802] [qa] Sort scripts by time for pull_tester and don't overwrite setup_chain --- qa/pull-tester/rpc-tests.py | 5 +++-- qa/rpc-tests/p2p-mempool.py | 7 +++++-- qa/rpc-tests/p2p-segwit.py | 7 +++++-- qa/rpc-tests/segwit.py | 7 ++++--- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index 37979a933fc29..2aa131041a02b 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -110,6 +110,8 @@ 'receivedby.py', 'mempool_resurrect_test.py', 'txn_doublespend.py --mineblock', + 'p2p-segwit.py', + 'segwit.py', 'txn_clone.py', 'getchaintips.py', 'rawtransactions.py', @@ -131,13 +133,12 @@ 'disablewallet.py', 'sendheaders.py', 'keypool.py', + 'p2p-mempool.py', 'prioritise_transaction.py', 'invalidblockrequest.py', 'invalidtxrequest.py', 'abandonconflict.py', 'p2p-versionbits-warning.py', - 'p2p-segwit.py', - 'segwit.py', 'importprunedfunds.py', 'signmessages.py', ] diff --git a/qa/rpc-tests/p2p-mempool.py b/qa/rpc-tests/p2p-mempool.py index 5d2daf39f8288..5c5d778f429b9 100755 --- a/qa/rpc-tests/p2p-mempool.py +++ b/qa/rpc-tests/p2p-mempool.py @@ -72,8 +72,11 @@ def send_mempool(self): self.send_message(msg_mempool()) class P2PMempoolTests(BitcoinTestFramework): - def setup_chain(self): - initialize_chain_clean(self.options.tmpdir, 2) + + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 2 def setup_network(self): # Start a node with maxuploadtarget of 200 MB (/24h) diff --git a/qa/rpc-tests/p2p-segwit.py b/qa/rpc-tests/p2p-segwit.py index cf78954f286bc..c67b7724516aa 100755 --- a/qa/rpc-tests/p2p-segwit.py +++ b/qa/rpc-tests/p2p-segwit.py @@ -163,8 +163,11 @@ def __init__(self, sha256, n, nValue): class SegWitTest(BitcoinTestFramework): - def setup_chain(self): - initialize_chain_clean(self.options.tmpdir, 3) + + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 3 def add_options(self, parser): parser.add_option("--oldbinary", dest="oldbinary", diff --git a/qa/rpc-tests/segwit.py b/qa/rpc-tests/segwit.py index d4c9a8afed32c..f88230cbb9892 100755 --- a/qa/rpc-tests/segwit.py +++ b/qa/rpc-tests/segwit.py @@ -71,9 +71,10 @@ def getutxo(txid): class SegWitTest(BitcoinTestFramework): - def setup_chain(self): - print("Initializing test directory "+self.options.tmpdir) - initialize_chain_clean(self.options.tmpdir, 3) + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 3 def setup_network(self): self.nodes = [] From a3e19846519952a3d22e387031258a88ec24d280 Mon Sep 17 00:00:00 2001 From: NicolasDorier Date: Fri, 15 Jul 2016 14:20:13 +0900 Subject: [PATCH 0625/1802] Consensus: Trivial transform BOOST_FOREACH into for loop --- src/main.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 62f1cd1517722..5e8a6d50fb24b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -785,7 +785,7 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime) return true; if ((int64_t)tx.nLockTime < ((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64_t)nBlockHeight : nBlockTime)) return true; - BOOST_FOREACH(const CTxIn& txin, tx.vin) { + for (const auto& txin : tx.vin) { if (!(txin.nSequence == CTxIn::SEQUENCE_FINAL)) return false; } @@ -999,11 +999,11 @@ bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp, bool unsigned int GetLegacySigOpCount(const CTransaction& tx) { unsigned int nSigOps = 0; - BOOST_FOREACH(const CTxIn& txin, tx.vin) + for (const auto& txin : tx.vin) { nSigOps += txin.scriptSig.GetSigOpCount(false); } - BOOST_FOREACH(const CTxOut& txout, tx.vout) + for (const auto& txout : tx.vout) { nSigOps += txout.scriptPubKey.GetSigOpCount(false); } @@ -1061,7 +1061,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state) // Check for negative or overflow output values CAmount nValueOut = 0; - BOOST_FOREACH(const CTxOut& txout, tx.vout) + for (const auto& txout : tx.vout) { if (txout.nValue < 0) return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-negative"); @@ -1074,7 +1074,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state) // Check for duplicate inputs set vInOutPoints; - BOOST_FOREACH(const CTxIn& txin, tx.vin) + for (const auto& txin : tx.vin) { if (vInOutPoints.count(txin.prevout)) return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-duplicate"); @@ -1088,7 +1088,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state) } else { - BOOST_FOREACH(const CTxIn& txin, tx.vin) + for (const auto& txin : tx.vin) if (txin.prevout.IsNull()) return state.DoS(10, false, REJECT_INVALID, "bad-txns-prevout-null"); } @@ -3401,13 +3401,13 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P return state.DoS(100, false, REJECT_INVALID, "bad-cb-multiple", false, "more than one coinbase"); // Check transactions - BOOST_FOREACH(const CTransaction& tx, block.vtx) + for (const auto& tx : block.vtx) if (!CheckTransaction(tx, state)) return state.Invalid(false, state.GetRejectCode(), state.GetRejectReason(), strprintf("Transaction check failed (tx hash %s) %s", tx.GetHash().ToString(), state.GetDebugMessage())); unsigned int nSigOps = 0; - BOOST_FOREACH(const CTransaction& tx, block.vtx) + for (const auto& tx : block.vtx) { nSigOps += GetLegacySigOpCount(tx); } @@ -3538,7 +3538,7 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn : block.GetBlockTime(); // Check that all transactions are finalized - BOOST_FOREACH(const CTransaction& tx, block.vtx) { + for (const auto& tx : block.vtx) { if (!IsFinalTx(tx, nHeight, nLockTimeCutoff)) { return state.DoS(10, false, REJECT_INVALID, "bad-txns-nonfinal", false, "non-final transaction"); } From 6f3d616dc8d6840c2293ffadd8cc3209f1100193 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Tim=C3=B3n?= Date: Sun, 17 Jul 2016 01:34:35 +0200 Subject: [PATCH 0626/1802] Trivial: Make CBlockIndex param const in ContextualCheckBlockHeader and ContextualCheckBlock --- src/main.cpp | 4 ++-- src/main.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 62f1cd1517722..34ab23914cb15 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3499,7 +3499,7 @@ std::vector GenerateCoinbaseCommitment(CBlock& block, const CBloc return commitment; } -bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex * const pindexPrev, int64_t nAdjustedTime) +bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev, int64_t nAdjustedTime) { // Check proof of work if (block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams)) @@ -3522,7 +3522,7 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta return true; } -bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex * const pindexPrev) +bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const CBlockIndex* pindexPrev) { const int nHeight = pindexPrev == NULL ? 0 : pindexPrev->nHeight + 1; const Consensus::Params& consensusParams = Params().GetConsensus(); diff --git a/src/main.h b/src/main.h index 7ea570d859792..561f2eceea4d8 100644 --- a/src/main.h +++ b/src/main.h @@ -444,8 +444,8 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P /** Context-dependent validity checks. * By "context", we mean only the previous block headers, but not the UTXO * set; UTXO-related validity checks are done in ConnectBlock(). */ -bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex* pindexPrev, int64_t nAdjustedTime); -bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex *pindexPrev); +bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev, int64_t nAdjustedTime); +bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const CBlockIndex* pindexPrev); /** Apply the effects of this block (with given index) on the UTXO set represented by coins. * Validity checks that depend on the UTXO set are also done; ConnectBlock() From 38c4c8b7012ceeee3b6591d6a80b5f13ee20fbd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Tim=C3=B3n?= Date: Sun, 17 Jul 2016 02:34:06 +0200 Subject: [PATCH 0627/1802] Trivial: Segwit: Don't call IsWitnessEnabled from ContextualCheckBlock --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 62f1cd1517722..21092ca2db665 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3564,7 +3564,7 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn // {0xaa, 0x21, 0xa9, 0xed}, and the following 32 bytes are SHA256^2(witness root, witness nonce). In case there are // multiple, the last one is used. bool fHaveWitness = false; - if (IsWitnessEnabled(pindexPrev, consensusParams)) { + if (VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT, versionbitscache) == THRESHOLD_ACTIVE) { int commitpos = GetWitnessCommitmentIndex(block); if (commitpos != -1) { bool malleated = false; From faa59318db48a0acc4b0ccff56b63cc05455c61f Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 18 Jul 2016 10:55:46 +0200 Subject: [PATCH 0628/1802] [doc] gbuild: Set memory explicitly (default is too low) --- doc/release-process.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/release-process.md b/doc/release-process.md index 35ee1edae1175..41c1ac8556b1a 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -112,16 +112,16 @@ The gbuild invocations below DO NOT DO THIS by default. ### Build and sign Bitcoin Core for Linux, Windows, and OS X: pushd ./gitian-builder - ./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml + ./bin/gbuild --memory 3000 --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml ./bin/gsign --signer $SIGNER --release ${VERSION}-linux --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml mv build/out/bitcoin-*.tar.gz build/out/src/bitcoin-*.tar.gz ../ - ./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-win.yml + ./bin/gbuild --memory 3000 --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-win.yml ./bin/gsign --signer $SIGNER --release ${VERSION}-win-unsigned --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win.yml mv build/out/bitcoin-*-win-unsigned.tar.gz inputs/bitcoin-win-unsigned.tar.gz mv build/out/bitcoin-*.zip build/out/bitcoin-*.exe ../ - ./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml + ./bin/gbuild --memory 3000 --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml ./bin/gsign --signer $SIGNER --release ${VERSION}-osx-unsigned --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml mv build/out/bitcoin-*-osx-unsigned.tar.gz inputs/bitcoin-osx-unsigned.tar.gz mv build/out/bitcoin-*.tar.gz build/out/bitcoin-*.dmg ../ From 8cef5bd58ac33ad4207d00c0696438706e8f035e Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 18 Jul 2016 10:56:25 +0200 Subject: [PATCH 0629/1802] mining: Improve `-blockmaxcost` help message One-word replacement to #8354. --- src/init.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/init.cpp b/src/init.cpp index d127ecd48f551..509bc45f516db 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -452,7 +452,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-mempoolreplacement", strprintf(_("Enable transaction replacement in the memory pool (default: %u)"), DEFAULT_ENABLE_REPLACEMENT)); strUsage += HelpMessageGroup(_("Block creation options:")); - strUsage += HelpMessageOpt("-blockmaxcost=", strprintf(_("Set maximum block cost (default: %d)"), DEFAULT_BLOCK_MAX_COST)); + strUsage += HelpMessageOpt("-blockmaxcost=", strprintf(_("Set maximum BIP141 block cost (default: %d)"), DEFAULT_BLOCK_MAX_COST)); strUsage += HelpMessageOpt("-blockmaxsize=", strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE)); strUsage += HelpMessageOpt("-blockprioritysize=", strprintf(_("Set maximum size of high-priority/low-fee transactions in bytes (default: %d)"), DEFAULT_BLOCK_PRIORITY_SIZE)); if (showDebug) From e4382fbef56a0e04b0ed834e8b3a3a16f81db149 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 18 Jul 2016 10:12:16 +0000 Subject: [PATCH 0630/1802] qt: periodic translations update --- src/qt/bitcoinstrings.cpp | 3 +- src/qt/locale/bitcoin_de.ts | 4 ++ src/qt/locale/bitcoin_en.ts | 43 +++++++++----------- src/qt/locale/bitcoin_es_MX.ts | 12 ++++++ src/qt/locale/bitcoin_es_UY.ts | 2 +- src/qt/locale/bitcoin_fa.ts | 74 ++++++++++++++++++++++++++++++++-- src/qt/locale/bitcoin_pl.ts | 2 +- src/qt/locale/bitcoin_pt_BR.ts | 4 ++ src/qt/locale/bitcoin_pt_PT.ts | 8 ++++ src/qt/locale/bitcoin_tr.ts | 32 +++++++++++++++ 10 files changed, 153 insertions(+), 31 deletions(-) diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp index 9c5b1e09d4524..bca5b72827f31 100644 --- a/src/qt/bitcoinstrings.cpp +++ b/src/qt/bitcoinstrings.cpp @@ -311,9 +311,8 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Send trace/debug info to console instead of d QT_TRANSLATE_NOOP("bitcoin-core", "Send transactions as zero-fee transactions if possible (default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "Set database cache size in megabytes (%d to %d, default: %d)"), QT_TRANSLATE_NOOP("bitcoin-core", "Set key pool size to (default: %u)"), -QT_TRANSLATE_NOOP("bitcoin-core", "Set maximum block cost (default: %d)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Set maximum BIP141 block cost (default: %d)"), QT_TRANSLATE_NOOP("bitcoin-core", "Set maximum block size in bytes (default: %d)"), -QT_TRANSLATE_NOOP("bitcoin-core", "Set minimum block size in bytes (default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "Set the number of threads to service RPC calls (default: %d)"), QT_TRANSLATE_NOOP("bitcoin-core", "Show all debugging options (usage: --help -help-debug)"), QT_TRANSLATE_NOOP("bitcoin-core", "Shrink debug.log file on client startup (default: 1 when no -debug)"), diff --git a/src/qt/locale/bitcoin_de.ts b/src/qt/locale/bitcoin_de.ts index f38f4c10f7148..2708324d172e1 100644 --- a/src/qt/locale/bitcoin_de.ts +++ b/src/qt/locale/bitcoin_de.ts @@ -2006,6 +2006,10 @@ Only connect to nodes in network <net> (ipv4, ipv6 or onion) Nur zu Knoten des Netzwerktyps <net> verbinden (ipv4, ipv6 oder onion) + + Print this help message and exit + Drucke diese Hilfemeldung und beende + Print version and exit Gibt die Versionsnummer aus und beendet das Programm diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts index c6f3a4013c48e..79c3e87b2b10a 100644 --- a/src/qt/locale/bitcoin_en.ts +++ b/src/qt/locale/bitcoin_en.ts @@ -1218,12 +1218,12 @@ Amount - + Enter a Bitcoin address (e.g. %1) - + %1 d @@ -2231,22 +2231,22 @@ Options: - + Specify data directory Specify data directory - + Connect to a node to retrieve peer addresses, and disconnect Connect to a node to retrieve peer addresses, and disconnect - + Specify your own public address Specify your own public address - + Accept command line and JSON-RPC commands Accept command line and JSON-RPC commands @@ -2296,12 +2296,12 @@ Run in the background as a daemon and accept commands - + Unable to start HTTP server. See debug log for details. - + Accept connections from outside (default: 1 if no -proxy or -connect) Accept connections from outside (default: 1 if no -proxy or -connect) @@ -2686,17 +2686,12 @@ - - Set maximum block cost (default: %d) - - - - + Set maximum block size in bytes (default: %d) - + Specify wallet file (within data directory) Specify wallet file (within data directory) @@ -2766,7 +2761,7 @@ - + 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 @@ -2946,7 +2941,12 @@ - + + Set maximum BIP141 block cost (default: %d) + + + + Show all debugging options (usage: --help -help-debug) @@ -3041,7 +3041,7 @@ - + Password for JSON-RPC connections Password for JSON-RPC connections @@ -3227,11 +3227,6 @@ - Set minimum block size in bytes (default: %u) - - - - Set the number of threads to service RPC calls (default: %d) @@ -3266,7 +3261,7 @@ Unknown network specified in -onlynet: '%s' - + Insufficient funds Insufficient funds diff --git a/src/qt/locale/bitcoin_es_MX.ts b/src/qt/locale/bitcoin_es_MX.ts index 26432190a27cd..0a6ea1e1dd112 100644 --- a/src/qt/locale/bitcoin_es_MX.ts +++ b/src/qt/locale/bitcoin_es_MX.ts @@ -44,6 +44,10 @@ AskPassphraseDialog + + Passphrase Dialog + Dialogo de contraseña + Enter passphrase Ingrese la contraseña @@ -59,6 +63,10 @@ BanTableModel + + IP/Netmask + IP/Máscara de red + BitcoinGUI @@ -178,6 +186,10 @@ &Receive &Recibir + + &Show / Hide + &Mostrar / Ocultar + &File &Archivo diff --git a/src/qt/locale/bitcoin_es_UY.ts b/src/qt/locale/bitcoin_es_UY.ts index 8d361620de1b3..c565a63cd885f 100644 --- a/src/qt/locale/bitcoin_es_UY.ts +++ b/src/qt/locale/bitcoin_es_UY.ts @@ -108,7 +108,7 @@ Send coins to a Bitcoin address - Enviar monedas a una dirección BItCoin + Enviar monedas a una dirección Bitcoin Change the passphrase used for wallet encryption diff --git a/src/qt/locale/bitcoin_fa.ts b/src/qt/locale/bitcoin_fa.ts index 8bf727a0cd645..98543ded461bb 100644 --- a/src/qt/locale/bitcoin_fa.ts +++ b/src/qt/locale/bitcoin_fa.ts @@ -67,7 +67,11 @@ IP/Netmask آی‌پی/نت‌ماسک - + + Banned Until + مسدود شده تا + + BitcoinGUI @@ -110,6 +114,10 @@ &About %1 &حدود%1 + + Show information about %1 + نمایش اطلاعات دربارهٔ %1 + About &Qt دربارهٔ &کیوت @@ -510,6 +518,10 @@ OpenURIDialog + + Open URI + بازکردن آدرس + OptionsDialog @@ -525,6 +537,10 @@ Accept connections from outside پذیرش اتصالات از بیرون + + Allow incoming connections + اجازه دادن به اتصالات دریافتی + Reset all client options to default. بازنشانی تمام تنظیمات به پیش‌فرض. @@ -691,7 +707,11 @@ PeerTableModel - + + Ping Time + زمان پینگ + + QObject @@ -797,6 +817,14 @@ Last Receive آخرین دریافتی + + Ping Time + زمان پینگ + + + Ping Wait + انتظار پینگ + Last block time زمان آخرین بلوک @@ -833,6 +861,22 @@ Type <b>help</b> for an overview of available commands. برای نمایش یک مرور کلی از دستورات ممکن، عبارت <b>help</b> را بنویسید. + + %1 B + %1 بایت + + + %1 KB + %1 کیلوبایت + + + %1 MB + %1 مگابایت + + + %1 GB + %1 گیگابایت + never هرگز @@ -887,7 +931,11 @@ Copy &Address &کپی نشانی - + + &Save Image... + &ذخیره عکس... + + SendCoinsDialog @@ -934,6 +982,18 @@ Hide پنهان کردن + + Recommended: + توصیه شده: + + + Custom: + سفارشی: + + + Confirmation time: + روز تایید: + normal نرمال @@ -1024,6 +1084,10 @@ ShutdownWindow + + %1 is shutting down... + %1 در حال خاموش شدن است... + SignVerifyMessageDialog @@ -1250,6 +1314,10 @@ Wallet options: گزینه‌های کیف پول: + + (default: %u) + (پیش‌فرض %u) + Information اطلاعات diff --git a/src/qt/locale/bitcoin_pl.ts b/src/qt/locale/bitcoin_pl.ts index a88e505b398b4..09f748b83cbf8 100644 --- a/src/qt/locale/bitcoin_pl.ts +++ b/src/qt/locale/bitcoin_pl.ts @@ -300,7 +300,7 @@ %1 behind - %1 wstecz + %1 za Last received block was generated %1 ago. diff --git a/src/qt/locale/bitcoin_pt_BR.ts b/src/qt/locale/bitcoin_pt_BR.ts index 29414303920ed..ee48c673413da 100644 --- a/src/qt/locale/bitcoin_pt_BR.ts +++ b/src/qt/locale/bitcoin_pt_BR.ts @@ -1894,6 +1894,10 @@ Append comment to the user agent string Adiciona comentário ao user-agent do navegador + + Attempt to recover private keys from a corrupt wallet on startup + Tentando recuperar a chape privada da carteira corrompida ao inicializar + Block creation options: Opções de criação de blocos: diff --git a/src/qt/locale/bitcoin_pt_PT.ts b/src/qt/locale/bitcoin_pt_PT.ts index f63bfece69cc5..eed262e010ee6 100644 --- a/src/qt/locale/bitcoin_pt_PT.ts +++ b/src/qt/locale/bitcoin_pt_PT.ts @@ -617,6 +617,10 @@ &Main &Principal + + Automatically start %1 after logging in to the system. + Começar o %1 automaticamente ao iniciar a sessão no sistema. + &Start %1 on system login &Iniciar o %1 no início de sessão do sistema @@ -1831,6 +1835,10 @@ Append comment to the user agent string Anexar um comentário para a entrada de agente do utilizador + + Attempt to recover private keys from a corrupt wallet on startup + Tentar reuperar as chaves privadas de um "wallet" ao iniciar + Block creation options: Opções da criação de bloco: diff --git a/src/qt/locale/bitcoin_tr.ts b/src/qt/locale/bitcoin_tr.ts index bbd0117404c22..e3a811b504e99 100644 --- a/src/qt/locale/bitcoin_tr.ts +++ b/src/qt/locale/bitcoin_tr.ts @@ -1830,6 +1830,10 @@ Distributed under the MIT software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>. MIT yazılım lisansı kapsamında yayınlanmıştır, ekteki COPYING dosyasına ya da <http://www.opensource.org/licenses/mit-license.php> adresine bakınız. + + Error loading %s: You can't enable HD on a already existing non-HD wallet + %s yüklenmesinde hata: zaten var olan ve HD olmayan bir cüzdanda HD etkinleştirilemez. + Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect. %s dosyasının okunması sırasında bir hata meydana geldi! Tüm anahtarlar doğru bir şekilde okundu, ancak muamele verileri ya da adres defteri unsurları hatalı veya eksik olabilir. @@ -1854,6 +1858,10 @@ Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly. Lütfen bilgisayarınızın saat ve tarihinin doğru olduğunu kontrol ediniz! Saatinizde gecikme varsa %s doğru şekilde çalışamaz. + + Please contribute if you find %s useful. Visit %s for further information about the software. + %s programını faydalı buluyorsanız lütfen katkıda bulununuz. Yazılım hakkında daha fazla bilgi için %s adresini ziyaret ediniz. + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) Betik kontrolü iş parçacıklarının sayısını belirler (%u ilâ %d, 0 = otomatik, <0 = bu sayıda çekirdeği kullanma, varsayılan: %d) @@ -1866,6 +1874,10 @@ This is a pre-release test build - use at your own risk - do not use for mining or merchant applications Bu yayın öncesi bir deneme sürümüdür - tüm riski siz üstlenmiş olursunuz - bitcoin oluşturmak ya da ticari uygulamalar için kullanmayınız + + Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain + Veritabanını çatallama öncesi duruma geri sarmak mümkün değil. Blok zincirini tekrar indirmeniz gerekmektedir + Use UPnP to map the listening port (default: 1 when listening and no -proxy) Dinlenecek portu haritalamak için UPnP kullan (varsayılan: dinlenildiğinde ve -proxy olmadığında 1) @@ -1986,6 +1998,10 @@ Error loading %s: Wallet requires newer version of %s %s unsurunun yüklenmesinde hata oluştu: cüzdan %s programının yeni bir sürümüne ihtiyaç duyuyor + + Error loading %s: You can't disable HD on a already existing HD wallet + %s yüklenmesinde hata: zaten var olan HD bir cüzdanda HD devre dışı bırakılamaz. + Error loading block database Blok veritabanının yüklenmesinde hata @@ -2074,10 +2090,18 @@ Rebuild chain state from the currently indexed blocks Zincir durumunu güncel olarak endekslenen bloklardan yeniden derle + + Rewinding blocks... + Bloklar geri sarılıyor... + Set database cache size in megabytes (%d to %d, default: %d) Veritabanı önbellek boyutunu megabayt olarak belirt (%d ilâ %d, varsayılan: %d) + + Set maximum block cost (default: %d) + Azami blok maliyetini ayarla (varsayılan: %d) + Set maximum block size in bytes (default: %d) Azami blok boyutunu bayt olarak ayarla (varsayılan: %d) @@ -2086,6 +2110,10 @@ Specify wallet file (within data directory) Cüzdan dosyası belirtiniz (veri klasörünün içinde) + + The source code is available from %s. + Kaynak kod şuradan elde edilebilir: %s. + Unable to bind to %s on this computer. %s is probably already running. Bu bilgisayarda %s unsuruna bağlanılamadı. %s muhtemelen hâlihazırda çalışmaktadır. @@ -2198,6 +2226,10 @@ This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard. Bu ürün OpenSSL projesi tarafından OpenSSL araç takımı (http://www.openssl.org/) için geliştirilen yazılımlar, Eric Young (eay@cryptsoft.com) tarafından hazırlanmış şifreleme yazılımları ve Thomas Bernard tarafından programlanmış UPnP yazılımı içerir. + + Use hierarchical deterministic key generation (HD) after BIP32. Only has effect during wallet creation/first start + BIP32'den sonra hiyerarşik determinist (HD) anahtar üretimini kullan. Sadece cüzdan oluşturulmasında/ilk başlamada etkiye sahiptir. + 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 Beyaz listeye alınan eşler DoS yasaklamasına uğramazlar ve muameleleri zaten mempool'da olsalar da daima aktarılır, bu mesela bir geçit için kullanışlıdır From 6c0336c7723da274c8312b82ed2a138f5d57158f Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 18 Jul 2016 12:21:52 +0200 Subject: [PATCH 0631/1802] build: bump version to 0.13.99 Now that 0.13 branch has been split off, master is 0.13.99 (pre-0.14). --- configure.ac | 2 +- doc/Doxyfile | 2 +- doc/README.md | 2 +- doc/README_windows.txt | 2 +- src/clientversion.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index 011af6bd1bd8e..78d63f92729dd 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 0) -define(_CLIENT_VERSION_MINOR, 12) +define(_CLIENT_VERSION_MINOR, 13) define(_CLIENT_VERSION_REVISION, 99) define(_CLIENT_VERSION_BUILD, 0) define(_CLIENT_VERSION_IS_RELEASE, false) diff --git a/doc/Doxyfile b/doc/Doxyfile index 428fba98e1ba7..22850db835429 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -34,7 +34,7 @@ PROJECT_NAME = Bitcoin # This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = 0.12.99 +PROJECT_NUMBER = 0.13.99 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer diff --git a/doc/README.md b/doc/README.md index c30f29452b786..09a507c9ce6e9 100644 --- a/doc/README.md +++ b/doc/README.md @@ -1,4 +1,4 @@ -Bitcoin Core 0.12.99 +Bitcoin Core 0.13.99 ===================== Setup diff --git a/doc/README_windows.txt b/doc/README_windows.txt index 2d1c4503c9177..74a05138a4280 100644 --- a/doc/README_windows.txt +++ b/doc/README_windows.txt @@ -1,4 +1,4 @@ -Bitcoin Core 0.12.99 +Bitcoin Core 0.13.99 ===================== Intro diff --git a/src/clientversion.h b/src/clientversion.h index 47263d5344f3c..53ad460346466 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -15,7 +15,7 @@ //! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it #define CLIENT_VERSION_MAJOR 0 -#define CLIENT_VERSION_MINOR 12 +#define CLIENT_VERSION_MINOR 13 #define CLIENT_VERSION_REVISION 99 #define CLIENT_VERSION_BUILD 0 From 5e3557b8e36308a27dbeb528569abe638c4d01dd Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 18 Jul 2016 14:00:05 +0200 Subject: [PATCH 0632/1802] doc: Clean out release notes Now that 0.13 has branched, release notes for 0.13 should be maintained there, and the release notes file on master is for 0.14 release notes. --- doc/release-notes.md | 145 +++---------------------------------------- 1 file changed, 8 insertions(+), 137 deletions(-) diff --git a/doc/release-notes.md b/doc/release-notes.md index 3d2baaaaeaae1..343bd0846ecc0 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -41,81 +41,7 @@ report issues about Windows XP to the issue tracker. Notable changes =============== -Database cache memory increased --------------------------------- - -As a result of growth of the UTXO set, performance with the prior default -database cache of 100 MiB has suffered. -For this reason the default was changed to 300 MiB in this release. - -For nodes on low-memory systems, the database cache can be changed back to -100 MiB (or to another value) by either: - -- Adding `dbcache=100` in bitcoin.conf -- Changing it in the GUI under `Options → Size of database cache` - -Note that the database cache setting has the most performance impact -during initial sync of a node, and when catching up after downtime. - -bitcoin-cli: arguments privacy --------------------------------- - -The RPC command line client gained a new argument, `-stdin` -to read extra arguments from standard input, one per line until EOF/Ctrl-D. -For example: - - $ echo -e "mysecretcode\n120" | src/bitcoin-cli -stdin walletpassphrase - -It is recommended to use this for sensitive information such as wallet -passphrases, as command-line arguments can usually be read from the process -table by any user on the system. - -RPC low-level changes ----------------------- - -- `gettxoutsetinfo` UTXO hash (`hash_serialized`) has changed. There was a divergence between - 32-bit and 64-bit platforms, and the txids were missing in the hashed data. This has been - fixed, but this means that the output will be different than from previous versions. - -- Full UTF-8 support in the RPC API. Non-ASCII characters in, for example, - wallet labels have always been malformed because they weren't taken into account - properly in JSON RPC processing. This is no longer the case. This also affects - the GUI debug console. - -C++11 and Python 3 -------------------- - -Various code modernizations have been done. The Bitcoin Core code base has -started using C++11. This means that a C++11-capable compiler is now needed for -building. Effectively this means GCC 4.7 or higher, or Clang 3.3 or higher. - -When cross-compiling for a target that doesn't have C++11 libraries, configure with -`./configure --enable-glibc-back-compat ... LDFLAGS=-static-libstdc++`. - -For running the functional tests in `qa/rpc-tests`, Python3.4 or higher is now -required. - -Linux ARM builds ------------------- - -Due to popular request, Linux ARM builds have been added to the uploaded -executables. - -The following extra files can be found in the download directory or torrent: - -- `bitcoin-${VERSION}-arm-linux-gnueabihf.tar.gz`: Linux binaries for the most - common 32-bit ARM architecture. -- `bitcoin-${VERSION}-aarch64-linux-gnu.tar.gz`: Linux binaries for the most - common 64-bit ARM architecture. - -ARM builds are still experimental. If you have problems on a certain device or -Linux distribution combination please report them on the bug tracker, it may be -possible to resolve them. - -Note that Android is not considered ARM Linux in this context. The executables -are not expected to work out of the box on Android. - -0.13.0 Change log +0.14.0 Change log ================= Detailed release notes follow. This overview includes changes that affect @@ -125,83 +51,28 @@ git merge commit are mentioned. ### RPC and REST -Asm script outputs replacements for OP_NOP2 and OP_NOP3 -------------------------------------------------------- - -OP_NOP2 has been renamed to OP_CHECKLOCKTIMEVERIFY by [BIP -65](https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki) - -OP_NOP3 has been renamed to OP_CHECKSEQUENCEVERIFY by [BIP -112](https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki) - -The following outputs are affected by this change: -- RPC `getrawtransaction` (in verbose mode) -- RPC `decoderawtransaction` -- RPC `decodescript` -- REST `/rest/tx/` (JSON format) -- REST `/rest/block/` (JSON format when including extended tx details) -- `bitcoin-tx -json` - -New mempool information RPC calls ---------------------------------- - -RPC calls have been added to output detailed statistics for individual mempool -entries, as well as to calculate the in-mempool ancestors or descendants of a -transaction: see `getmempoolentry`, `getmempoolancestors`, `getmempooldescendants`. - -### ZMQ - -Each ZMQ notification now contains an up-counting sequence number that allows -listeners to detect lost notifications. -The sequence number is always the last element in a multi-part ZMQ notification and -therefore backward compatible. -Each message type has its own counter. -(https://github.com/bitcoin/bitcoin/pull/7762) - ### Configuration and command-line options ### Block and transaction handling ### P2P protocol and network code -The p2p alert system has been removed in #7692 and the 'alert' message is no longer supported. - - -Fee filtering of invs (BIP 133) ------------------------------------- - -The optional new p2p message "feefilter" is implemented and the protocol -version is bumped to 70013. Upon receiving a feefilter message from a peer, -a node will not send invs for any transactions which do not meet the filter -feerate. [BIP 133](https://github.com/bitcoin/bips/blob/master/bip-0133.mediawiki) - ### Validation ### Build system ### Wallet -Hierarchical Deterministic Key Generation ------------------------------------------ -Newly created wallets will use hierarchical deterministic key generation -according to BIP32 (keypath m/0'/0'/k'). -Existing wallets will still use traditional key generation. - -Backups of HD wallets, regardless of when they have been created, can -therefore be used to re-generate all possible private keys, even the -ones which haven't already been generated during the time of the backup. - -HD key generation for new wallets can be disabled by `-usehd=0`. Keep in -mind that this flag only has affect on newly created wallets. -You can't disable HD key generation once you have created a HD wallet. - -There is no distinction between internal (change) and external keys. - -[Pull request](https://github.com/bitcoin/bitcoin/pull/8035/files), [BIP 32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) - ### GUI ### Tests ### Miscellaneous +Credits +======= + +Thanks to everyone who directly contributed to this release: + + +As well as everyone that helped translating on [Transifex](https://www.transifex.com/projects/p/bitcoin/). From 682aa0f289c550c029733966a2ce3449e4a471df Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Mon, 18 Jul 2016 12:40:28 -0400 Subject: [PATCH 0633/1802] Scale legacy sigop count in CreateNewBlock --- src/miner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/miner.cpp b/src/miner.cpp index 8153fb9f9ecdd..3f6fe915a7a7f 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -187,7 +187,7 @@ CBlockTemplate* BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn) UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev); pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, chainparams.GetConsensus()); pblock->nNonce = 0; - pblocktemplate->vTxSigOpsCost[0] = GetLegacySigOpCount(pblock->vtx[0]); + pblocktemplate->vTxSigOpsCost[0] = WITNESS_SCALE_FACTOR * GetLegacySigOpCount(pblock->vtx[0]); CValidationState state; if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) { From 2c06bae39edfaa9c0855d83377ad8fda09e4fa08 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Mon, 18 Jul 2016 13:28:26 -0400 Subject: [PATCH 0634/1802] Rename "block cost" to "block weight" --- qa/rpc-tests/p2p-segwit.py | 6 ++--- src/consensus/consensus.h | 4 ++-- src/init.cpp | 2 +- src/main.cpp | 12 +++++----- src/main.h | 2 +- src/miner.cpp | 42 +++++++++++++++++----------------- src/miner.h | 4 ++-- src/policy/policy.cpp | 10 ++++---- src/policy/policy.h | 12 +++++----- src/primitives/block.cpp | 6 ++--- src/primitives/block.h | 4 ++-- src/primitives/transaction.cpp | 4 ++-- src/primitives/transaction.h | 4 ++-- src/rpc/blockchain.cpp | 4 ++-- src/rpc/mining.cpp | 12 +++++----- src/txmempool.cpp | 4 ++-- src/txmempool.h | 4 ++-- src/wallet/wallet.cpp | 2 +- 18 files changed, 69 insertions(+), 69 deletions(-) diff --git a/qa/rpc-tests/p2p-segwit.py b/qa/rpc-tests/p2p-segwit.py index b30d41af92935..fa2c5d1f05e24 100755 --- a/qa/rpc-tests/p2p-segwit.py +++ b/qa/rpc-tests/p2p-segwit.py @@ -1065,12 +1065,12 @@ def test_block_relay(self, segwit_activated): assert_equal(wit_block.serialize(False), non_wit_block.serialize()) assert_equal(wit_block.serialize(True), block.serialize(True)) - # Test size, vsize, cost + # Test size, vsize, weight rpc_details = self.nodes[0].getblock(block.hash, True) assert_equal(rpc_details["size"], len(block.serialize(True))) assert_equal(rpc_details["strippedsize"], len(block.serialize(False))) - cost = 3*len(block.serialize(False)) + len(block.serialize(True)) - assert_equal(rpc_details["cost"], cost) + weight = 3*len(block.serialize(False)) + len(block.serialize(True)) + assert_equal(rpc_details["weight"], weight) # Upgraded node should not ask for blocks from unupgraded block4 = self.build_next_block(nVersion=4) diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h index 81f40593b21a6..690856586604e 100644 --- a/src/consensus/consensus.h +++ b/src/consensus/consensus.h @@ -10,8 +10,8 @@ /** The maximum allowed size for a serialized block, in bytes (only for buffer size limits) */ static const unsigned int MAX_BLOCK_SERIALIZED_SIZE = 4000000; -/** The maximum allowed cost for a block, see BIP 141 (network rule) */ -static const unsigned int MAX_BLOCK_COST = 4000000; +/** The maximum allowed weight for a block, see BIP 141 (network rule) */ +static const unsigned int MAX_BLOCK_WEIGHT = 4000000; /** The maximum allowed size for a block excluding witness data, in bytes (network rule) */ static const unsigned int MAX_BLOCK_BASE_SIZE = 1000000; /** The maximum allowed number of signature check operations in a block (network rule) */ diff --git a/src/init.cpp b/src/init.cpp index 509bc45f516db..312dfe1699c08 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -452,7 +452,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-mempoolreplacement", strprintf(_("Enable transaction replacement in the memory pool (default: %u)"), DEFAULT_ENABLE_REPLACEMENT)); strUsage += HelpMessageGroup(_("Block creation options:")); - strUsage += HelpMessageOpt("-blockmaxcost=", strprintf(_("Set maximum BIP141 block cost (default: %d)"), DEFAULT_BLOCK_MAX_COST)); + strUsage += HelpMessageOpt("-blockmaxweight=", strprintf(_("Set maximum BIP141 block weight (default: %d)"), DEFAULT_BLOCK_MAX_WEIGHT)); strUsage += HelpMessageOpt("-blockmaxsize=", strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE)); strUsage += HelpMessageOpt("-blockprioritysize=", strprintf(_("Set maximum size of high-priority/low-fee transactions in bytes (default: %d)"), DEFAULT_BLOCK_PRIORITY_SIZE)); if (showDebug) diff --git a/src/main.cpp b/src/main.cpp index 73fbe53afb64a..fe19895f5fbcc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -694,8 +694,8 @@ bool AddOrphanTx(const CTransaction& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(c // have been mined or received. // 100 orphans, each of which is at most 99,999 bytes big is // at most 10 megabytes of orphans and somewhat more byprev index (in the worst case): - unsigned int sz = GetTransactionCost(tx); - if (sz >= MAX_STANDARD_TX_COST) + unsigned int sz = GetTransactionWeight(tx); + if (sz >= MAX_STANDARD_TX_WEIGHT) { LogPrint("mempool", "ignoring large orphan tx (size: %u, hash: %s)\n", sz, hash.ToString()); return false; @@ -3596,13 +3596,13 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn } // After the coinbase witness nonce and commitment are verified, - // we can check if the block cost passes (before we've checked the - // coinbase witness, it would be possible for the cost to be too + // we can check if the block weight passes (before we've checked the + // coinbase witness, it would be possible for the weight to be too // large by filling up the coinbase witness, which doesn't change // the block hash, so we couldn't mark the block as permanently // failed). - if (GetBlockCost(block) > MAX_BLOCK_COST) { - return state.DoS(100, error("ContextualCheckBlock(): cost limit failed"), REJECT_INVALID, "bad-blk-cost"); + if (GetBlockWeight(block) > MAX_BLOCK_WEIGHT) { + return state.DoS(100, error("ContextualCheckBlock(): weight limit failed"), REJECT_INVALID, "bad-blk-weight"); } return true; diff --git a/src/main.h b/src/main.h index 65ae2488f9095..27121890f6d70 100644 --- a/src/main.h +++ b/src/main.h @@ -155,7 +155,7 @@ typedef boost::unordered_map BlockMap; extern BlockMap mapBlockIndex; extern uint64_t nLastBlockTx; extern uint64_t nLastBlockSize; -extern uint64_t nLastBlockCost; +extern uint64_t nLastBlockWeight; extern const std::string strMessageMagic; extern CWaitableCriticalSection csBestBlock; extern CConditionVariable cvBlockChange; diff --git a/src/miner.cpp b/src/miner.cpp index 8153fb9f9ecdd..25a5becf93efa 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -45,7 +45,7 @@ using namespace std; uint64_t nLastBlockTx = 0; uint64_t nLastBlockSize = 0; -uint64_t nLastBlockCost = 0; +uint64_t nLastBlockWeight = 0; class ScoreCompare { @@ -77,30 +77,30 @@ BlockAssembler::BlockAssembler(const CChainParams& _chainparams) : chainparams(_chainparams) { // Block resource limits - // If neither -blockmaxsize or -blockmaxcost is given, limit to DEFAULT_BLOCK_MAX_* + // If neither -blockmaxsize or -blockmaxweight is given, limit to DEFAULT_BLOCK_MAX_* // If only one is given, only restrict the specified resource. // If both are given, restrict both. - nBlockMaxCost = DEFAULT_BLOCK_MAX_COST; + nBlockMaxWeight = DEFAULT_BLOCK_MAX_WEIGHT; nBlockMaxSize = DEFAULT_BLOCK_MAX_SIZE; - bool fCostSet = false; - if (mapArgs.count("-blockmaxcost")) { - nBlockMaxCost = GetArg("-blockmaxcost", DEFAULT_BLOCK_MAX_COST); + bool fWeightSet = false; + if (mapArgs.count("-blockmaxweight")) { + nBlockMaxWeight = GetArg("-blockmaxweight", DEFAULT_BLOCK_MAX_WEIGHT); nBlockMaxSize = MAX_BLOCK_SERIALIZED_SIZE; - fCostSet = true; + fWeightSet = true; } if (mapArgs.count("-blockmaxsize")) { nBlockMaxSize = GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE); - if (!fCostSet) { - nBlockMaxCost = nBlockMaxSize * WITNESS_SCALE_FACTOR; + if (!fWeightSet) { + nBlockMaxWeight = nBlockMaxSize * WITNESS_SCALE_FACTOR; } } - // Limit cost to between 4K and MAX_BLOCK_COST-4K for sanity: - nBlockMaxCost = std::max((unsigned int)4000, std::min((unsigned int)(MAX_BLOCK_COST-4000), nBlockMaxCost)); + // Limit weight to between 4K and MAX_BLOCK_WEIGHT-4K for sanity: + nBlockMaxWeight = std::max((unsigned int)4000, std::min((unsigned int)(MAX_BLOCK_WEIGHT-4000), nBlockMaxWeight)); // Limit size to between 1K and MAX_BLOCK_SERIALIZED_SIZE-1K for sanity: nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SERIALIZED_SIZE-1000), nBlockMaxSize)); - // Whether we need to account for byte usage (in addition to cost usage) + // Whether we need to account for byte usage (in addition to weight usage) fNeedSizeAccounting = (nBlockMaxSize < MAX_BLOCK_SERIALIZED_SIZE-1000); } @@ -110,7 +110,7 @@ void BlockAssembler::resetBlock() // Reserve space for coinbase tx nBlockSize = 1000; - nBlockCost = 4000; + nBlockWeight = 4000; nBlockSigOpsCost = 400; fIncludeWitness = false; @@ -167,7 +167,7 @@ CBlockTemplate* BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn) nLastBlockTx = nBlockTx; nLastBlockSize = nBlockSize; - nLastBlockCost = nBlockCost; + nLastBlockWeight = nBlockWeight; LogPrintf("CreateNewBlock(): total size %u txs: %u fees: %ld sigops %d\n", nBlockSize, nBlockTx, nFees, nBlockSigOpsCost); // Create coinbase transaction. @@ -223,8 +223,8 @@ void BlockAssembler::onlyUnconfirmed(CTxMemPool::setEntries& testSet) bool BlockAssembler::TestPackage(uint64_t packageSize, int64_t packageSigOpsCost) { - // TODO: switch to cost-based accounting for packages instead of vsize-based accounting. - if (nBlockCost + WITNESS_SCALE_FACTOR * packageSize >= nBlockMaxCost) + // TODO: switch to weight-based accounting for packages instead of vsize-based accounting. + if (nBlockWeight + WITNESS_SCALE_FACTOR * packageSize >= nBlockMaxWeight) return false; if (nBlockSigOpsCost + packageSigOpsCost >= MAX_BLOCK_SIGOPS_COST) return false; @@ -257,17 +257,17 @@ bool BlockAssembler::TestPackageTransactions(const CTxMemPool::setEntries& packa bool BlockAssembler::TestForBlock(CTxMemPool::txiter iter) { - if (nBlockCost + iter->GetTxCost() >= nBlockMaxCost) { + if (nBlockWeight + iter->GetTxWeight() >= nBlockMaxWeight) { // If the block is so close to full that no more txs will fit // or if we've tried more than 50 times to fill remaining space // then flag that the block is finished - if (nBlockCost > nBlockMaxCost - 400 || lastFewTxs > 50) { + if (nBlockWeight > nBlockMaxWeight - 400 || lastFewTxs > 50) { blockFinished = true; return false; } - // Once we're within 4000 cost of a full block, only look at 50 more txs + // Once we're within 4000 weight of a full block, only look at 50 more txs // to try to fill the remaining space. - if (nBlockCost > nBlockMaxCost - 4000) { + if (nBlockWeight > nBlockMaxWeight - 4000) { lastFewTxs++; } return false; @@ -315,7 +315,7 @@ void BlockAssembler::AddToBlock(CTxMemPool::txiter iter) if (fNeedSizeAccounting) { nBlockSize += ::GetSerializeSize(iter->GetTx(), SER_NETWORK, PROTOCOL_VERSION); } - nBlockCost += iter->GetTxCost(); + nBlockWeight += iter->GetTxWeight(); ++nBlockTx; nBlockSigOpsCost += iter->GetSigOpCost(); nFees += iter->GetFee(); diff --git a/src/miner.h b/src/miner.h index d16e37bb599bb..11753f5e43787 100644 --- a/src/miner.h +++ b/src/miner.h @@ -141,11 +141,11 @@ class BlockAssembler // Configuration parameters for the block size bool fIncludeWitness; - unsigned int nBlockMaxCost, nBlockMaxSize; + unsigned int nBlockMaxWeight, nBlockMaxSize; bool fNeedSizeAccounting; // Information on the current status of the block - uint64_t nBlockCost; + uint64_t nBlockWeight; uint64_t nBlockSize; uint64_t nBlockTx; uint64_t nBlockSigOpsCost; diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index f2148bfe1057d..8617db00c8608 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -64,8 +64,8 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason) // almost as much to process as they cost the sender in fees, because // computing signature hashes is O(ninputs*txsize). Limiting transactions // to MAX_STANDARD_TX_SIZE mitigates CPU exhaustion attacks. - unsigned int sz = GetTransactionCost(tx); - if (sz >= MAX_STANDARD_TX_COST) { + unsigned int sz = GetTransactionWeight(tx); + if (sz >= MAX_STANDARD_TX_WEIGHT) { reason = "tx-size"; return false; } @@ -151,12 +151,12 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs) return true; } -int64_t GetVirtualTransactionSize(int64_t nCost) +int64_t GetVirtualTransactionSize(int64_t nWeight) { - return (nCost + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR; + return (nWeight + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR; } int64_t GetVirtualTransactionSize(const CTransaction& tx) { - return GetVirtualTransactionSize(GetTransactionCost(tx)); + return GetVirtualTransactionSize(GetTransactionWeight(tx)); } diff --git a/src/policy/policy.h b/src/policy/policy.h index 29a8cc57c20ff..f5f8652fb5a72 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -18,10 +18,10 @@ class CCoinsViewCache; static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 750000; /** Default for -blockprioritysize, maximum space for zero/low-fee transactions **/ static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 0; -/** Default for -blockmaxcost, which control the range of block costs the mining code will create **/ -static const unsigned int DEFAULT_BLOCK_MAX_COST = 3000000; -/** The maximum size for transactions we're willing to relay/mine */ -static const unsigned int MAX_STANDARD_TX_COST = 400000; +/** Default for -blockmaxweight, which controls the range of block weights the mining code will create **/ +static const unsigned int DEFAULT_BLOCK_MAX_WEIGHT = 3000000; +/** The maximum weight for transactions we're willing to relay/mine */ +static const unsigned int MAX_STANDARD_TX_WEIGHT = 400000; /** Maximum number of signature check operations in an IsStandard() P2SH script */ static const unsigned int MAX_P2SH_SIGOPS = 15; /** The maximum number of sigops we're willing to relay/mine in a single tx */ @@ -66,8 +66,8 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason); */ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs); -/** Compute the virtual transaction size (cost reinterpreted as bytes). */ -int64_t GetVirtualTransactionSize(int64_t nCost); +/** Compute the virtual transaction size (weight reinterpreted as bytes). */ +int64_t GetVirtualTransactionSize(int64_t nWeight); int64_t GetVirtualTransactionSize(const CTransaction& tx); #endif // BITCOIN_POLICY_POLICY_H diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp index df900388f2678..0e6ab4dd718b3 100644 --- a/src/primitives/block.cpp +++ b/src/primitives/block.cpp @@ -32,11 +32,11 @@ std::string CBlock::ToString() const return s.str(); } -int64_t GetBlockCost(const CBlock& block) +int64_t GetBlockWeight(const CBlock& block) { - // This implements the cost = (stripped_size * 4) + witness_size formula, + // This implements the weight = (stripped_size * 4) + witness_size formula, // using only serialization with and without witness data. As witness_size // is equal to total_size - stripped_size, this formula is identical to: - // cost = (stripped_size * 3) + total_size. + // weight = (stripped_size * 3) + total_size. return ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION); } diff --git a/src/primitives/block.h b/src/primitives/block.h index e2a309e63d821..72dfed985ae93 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -154,7 +154,7 @@ struct CBlockLocator } }; -/** Compute the consensus-critical block cost (see BIP 141). */ -int64_t GetBlockCost(const CBlock& tx); +/** Compute the consensus-critical block weight (see BIP 141). */ +int64_t GetBlockWeight(const CBlock& tx); #endif // BITCOIN_PRIMITIVES_BLOCK_H diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index 7f10409c05397..8d6380564365e 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -121,7 +121,7 @@ unsigned int CTransaction::CalculateModifiedSize(unsigned int nTxSize) const // Providing any more cleanup incentive than making additional inputs free would // risk encouraging people to create junk outputs to redeem later. if (nTxSize == 0) - nTxSize = (GetTransactionCost(*this) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR; + nTxSize = (GetTransactionWeight(*this) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR; for (std::vector::const_iterator it(vin.begin()); it != vin.end(); ++it) { unsigned int offset = 41U + std::min(110U, (unsigned int)it->scriptSig.size()); @@ -149,7 +149,7 @@ std::string CTransaction::ToString() const return str; } -int64_t GetTransactionCost(const CTransaction& tx) +int64_t GetTransactionWeight(const CTransaction& tx) { return ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR -1) + ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); } diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 8a2d5dd22c8de..d37890667f9dd 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -459,7 +459,7 @@ struct CMutableTransaction uint256 GetHash() const; }; -/** Compute the cost of a transaction, as defined by BIP 141 */ -int64_t GetTransactionCost(const CTransaction &tx); +/** Compute the weight of a transaction, as defined by BIP 141 */ +int64_t GetTransactionWeight(const CTransaction &tx); #endif // BITCOIN_PRIMITIVES_TRANSACTION_H diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 20eefa1c574c5..9dc896b7af281 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -101,7 +101,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx result.push_back(Pair("confirmations", confirmations)); result.push_back(Pair("strippedsize", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS))); result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION))); - result.push_back(Pair("cost", (int)::GetBlockCost(block))); + result.push_back(Pair("weight", (int)::GetBlockWeight(block))); result.push_back(Pair("height", blockindex->nHeight)); result.push_back(Pair("version", block.nVersion)); result.push_back(Pair("versionHex", strprintf("%08x", block.nVersion))); @@ -559,7 +559,7 @@ UniValue getblock(const UniValue& params, bool fHelp) " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n" " \"size\" : n, (numeric) The block size\n" " \"strippedsize\" : n, (numeric) The block size excluding witness data\n" - " \"cost\" : n (numeric) The block cost\n" + " \"weight\" : n (numeric) The block weight (BIP 141)\n" " \"height\" : n, (numeric) The block height or index\n" " \"version\" : n, (numeric) The block version\n" " \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n" diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 4c4e5997818ef..92ca4bab6bc1e 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -224,7 +224,7 @@ UniValue getmininginfo(const UniValue& params, bool fHelp) "{\n" " \"blocks\": nnn, (numeric) The current block\n" " \"currentblocksize\": nnn, (numeric) The last block size\n" - " \"currentblockcost\": nnn, (numeric) The last block cost\n" + " \"currentblockweight\": nnn, (numeric) The last block weight\n" " \"currentblocktx\": nnn, (numeric) The last block transaction\n" " \"difficulty\": xxx.xxxxx (numeric) The current difficulty\n" " \"errors\": \"...\" (string) Current errors\n" @@ -243,7 +243,7 @@ UniValue getmininginfo(const UniValue& params, bool fHelp) UniValue obj(UniValue::VOBJ); obj.push_back(Pair("blocks", (int)chainActive.Height())); obj.push_back(Pair("currentblocksize", (uint64_t)nLastBlockSize)); - obj.push_back(Pair("currentblockcost", (uint64_t)nLastBlockCost)); + obj.push_back(Pair("currentblockweight", (uint64_t)nLastBlockWeight)); obj.push_back(Pair("currentblocktx", (uint64_t)nLastBlockTx)); obj.push_back(Pair("difficulty", (double)GetDifficulty())); obj.push_back(Pair("errors", GetWarnings("statusbar"))); @@ -358,7 +358,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) " ],\n" " \"fee\": n, (numeric) difference in value between transaction inputs and outputs (in Satoshis); for coinbase transactions, this is a negative Number of the total collected block fees (ie, not including the block subsidy); if key is not present, fee is unknown and clients MUST NOT assume there isn't one\n" " \"sigops\" : n, (numeric) total SigOps cost, as counted for purposes of block limits; if key is not present, sigop cost is unknown and clients MUST NOT assume it is zero\n" - " \"cost\" : n, (numeric) total transaction size cost, as counted for purposes of block limits\n" + " \"weight\" : n, (numeric) total transaction weight, as counted for purposes of block limits\n" " \"required\" : true|false (boolean) if provided and true, this transaction must be in the final block\n" " }\n" " ,...\n" @@ -377,7 +377,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) " \"noncerange\" : \"00000000ffffffff\", (string) A range of valid nonces\n" " \"sigoplimit\" : n, (numeric) cost limit of sigops in blocks\n" " \"sizelimit\" : n, (numeric) limit of block size\n" - " \"costlimit\" : n, (numeric) limit of block cost\n" + " \"weightlimit\" : n, (numeric) limit of block weight\n" " \"curtime\" : ttt, (numeric) current timestamp in seconds since epoch (Jan 1 1970 GMT)\n" " \"bits\" : \"xxx\", (string) compressed target of next block\n" " \"height\" : n (numeric) The height of the next block\n" @@ -575,7 +575,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) int index_in_template = i - 1; entry.push_back(Pair("fee", pblocktemplate->vTxFees[index_in_template])); entry.push_back(Pair("sigops", pblocktemplate->vTxSigOpsCost[index_in_template])); - entry.push_back(Pair("cost", GetTransactionCost(tx))); + entry.push_back(Pair("weight", GetTransactionWeight(tx))); transactions.push_back(entry); } @@ -659,7 +659,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) result.push_back(Pair("noncerange", "00000000ffffffff")); result.push_back(Pair("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS_COST)); result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SERIALIZED_SIZE)); - result.push_back(Pair("costlimit", (int64_t)MAX_BLOCK_COST)); + result.push_back(Pair("weightlimit", (int64_t)MAX_BLOCK_WEIGHT)); result.push_back(Pair("curtime", pblock->GetBlockTime())); result.push_back(Pair("bits", strprintf("%08x", pblock->nBits))); result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1))); diff --git a/src/txmempool.cpp b/src/txmempool.cpp index a48a6d94659b5..691baa674403f 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -28,7 +28,7 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee, hadNoDependencies(poolHasNoInputsOf), inChainInputValue(_inChainInputValue), spendsCoinbase(_spendsCoinbase), sigOpCost(_sigOpsCost), lockPoints(lp) { - nTxCost = GetTransactionCost(_tx); + nTxWeight = GetTransactionWeight(_tx); nModSize = _tx.CalculateModifiedSize(GetTxSize()); nUsageSize = RecursiveDynamicUsage(*tx) + memusage::DynamicUsage(tx); @@ -75,7 +75,7 @@ void CTxMemPoolEntry::UpdateLockPoints(const LockPoints& lp) size_t CTxMemPoolEntry::GetTxSize() const { - return GetVirtualTransactionSize(nTxCost); + return GetVirtualTransactionSize(nTxWeight); } // Update the given tx for any in-mempool descendants. diff --git a/src/txmempool.h b/src/txmempool.h index e5a500e19d433..2c2127f326de2 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -78,7 +78,7 @@ class CTxMemPoolEntry private: std::shared_ptr tx; CAmount nFee; //!< Cached to avoid expensive parent-transaction lookups - size_t nTxCost; //!< ... and avoid recomputing tx cost (also used for GetTxSize()) + size_t nTxWeight; //!< ... and avoid recomputing tx weight (also used for GetTxSize()) size_t nModSize; //!< ... and modified size for priority size_t nUsageSize; //!< ... and total memory usage int64_t nTime; //!< Local time when entering the mempool @@ -122,7 +122,7 @@ class CTxMemPoolEntry double GetPriority(unsigned int currentHeight) const; const CAmount& GetFee() const { return nFee; } size_t GetTxSize() const; - size_t GetTxCost() const { return nTxCost; } + size_t GetTxWeight() const { return nTxWeight; } int64_t GetTime() const { return nTime; } unsigned int GetHeight() const { return entryHeight; } bool WasClearAtEntry() const { return hadNoDependencies; } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 46ed542158167..4b6d98025d55b 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2356,7 +2356,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt *static_cast(&wtxNew) = CTransaction(txNew); // Limit size - if (GetTransactionCost(txNew) >= MAX_STANDARD_TX_COST) + if (GetTransactionWeight(txNew) >= MAX_STANDARD_TX_WEIGHT) { strFailReason = _("Transaction too large"); return false; From a4f137f367a898dc3acddc778c4fe9c53ac303c9 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 15 Jul 2016 11:42:47 +0200 Subject: [PATCH 0635/1802] [Wallet] Ensure <0.13 clients can't open HD wallets --- src/wallet/wallet.cpp | 3 +++ src/wallet/wallet.h | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 46ed542158167..ae0a546ea1b38 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3299,6 +3299,9 @@ bool CWallet::InitLoadWallet() key.MakeNewKey(true); if (!walletInstance->SetHDMasterKey(key)) throw std::runtime_error("CWallet::GenerateNewKey(): Storing master key failed"); + + // ensure this wallet.dat can only be opened by clients supporting HD + walletInstance->SetMinVersion(FEATURE_HD); } CPubKey newDefaultKey; if (walletInstance->GetKeyFromPool(newDefaultKey)) { diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index e9d669a7d1e30..3a3cb6d8514c0 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -78,7 +78,8 @@ enum WalletFeature FEATURE_WALLETCRYPT = 40000, // wallet encryption FEATURE_COMPRPUBKEY = 60000, // compressed public keys - FEATURE_LATEST = 60000 + FEATURE_HD = 130000, // Hierarchical key derivation after BIP32 (HD Wallet) + FEATURE_LATEST = FEATURE_COMPRPUBKEY // HD is optional, use FEATURE_COMPRPUBKEY as latest version }; From fbc60703a53c1544054fe6ba0753d23d0508f4e9 Mon Sep 17 00:00:00 2001 From: Thomas Snider Date: Mon, 18 Jul 2016 19:39:46 -0700 Subject: [PATCH 0636/1802] [trivial] Switched constants to sizeof() --- src/key.h | 28 ++++++++++++++++------------ src/pubkey.h | 11 +++++++---- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/key.h b/src/key.h index b4f48d59f5b08..0f58e24a49aeb 100644 --- a/src/key.h +++ b/src/key.h @@ -15,7 +15,7 @@ #include -/** +/** * secp256k1: * const unsigned int PRIVATE_KEY_SIZE = 279; * const unsigned int PUBLIC_KEY_SIZE = 65; @@ -45,6 +45,8 @@ class CKey //! The actual byte data unsigned char vch[32]; + static_assert(sizeof(vch) == 32, "vch must be 32 bytes in length to not break serialization"); + //! Check whether the 32-byte array pointed to be vch is valid keydata. bool static Check(const unsigned char* vch); @@ -70,20 +72,19 @@ class CKey friend bool operator==(const CKey& a, const CKey& b) { - return a.fCompressed == b.fCompressed && a.size() == b.size() && - memcmp(&a.vch[0], &b.vch[0], a.size()) == 0; + return a.fCompressed == b.fCompressed && + a.size() == b.size() && + memcmp(&a.vch[0], &b.vch[0], a.size()) == 0; } //! Initialize using begin and end iterators to byte data. template void Set(const T pbegin, const T pend, bool fCompressedIn) { - if (pend - pbegin != 32) { + if (pend - pbegin != sizeof(vch)) { fValid = false; - return; - } - if (Check(&pbegin[0])) { - memcpy(vch, (unsigned char*)&pbegin[0], 32); + } else if (Check(&pbegin[0])) { + memcpy(vch, (unsigned char*)&pbegin[0], sizeof(vch)); fValid = true; fCompressed = fCompressedIn; } else { @@ -92,7 +93,7 @@ class CKey } //! Simple read-only vector-like interface. - unsigned int size() const { return (fValid ? 32 : 0); } + unsigned int size() const { return (fValid ? sizeof(vch) : 0); } const unsigned char* begin() const { return vch; } const unsigned char* end() const { return vch + size(); } @@ -110,7 +111,7 @@ class CKey /** * Convert the private key to a CPrivKey (serialized OpenSSL private key data). - * This is expensive. + * This is expensive. */ CPrivKey GetPrivKey() const; @@ -160,8 +161,11 @@ struct CExtKey { friend bool operator==(const CExtKey& a, const CExtKey& b) { - return a.nDepth == b.nDepth && memcmp(&a.vchFingerprint[0], &b.vchFingerprint[0], 4) == 0 && a.nChild == b.nChild && - a.chaincode == b.chaincode && a.key == b.key; + return a.nDepth == b.nDepth && + memcmp(&a.vchFingerprint[0], &b.vchFingerprint[0], sizeof(vchFingerprint)) == 0 && + a.nChild == b.nChild && + a.chaincode == b.chaincode && + a.key == b.key; } void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const; diff --git a/src/pubkey.h b/src/pubkey.h index db5444ea9d745..aebfdbc826628 100644 --- a/src/pubkey.h +++ b/src/pubkey.h @@ -13,7 +13,7 @@ #include #include -/** +/** * secp256k1: * const unsigned int PRIVATE_KEY_SIZE = 279; * const unsigned int PUBLIC_KEY_SIZE = 65; @@ -156,7 +156,7 @@ class CPubKey /* * Check syntactic correctness. - * + * * Note that this is consensus critical as CheckSig() calls it! */ bool IsValid() const @@ -203,8 +203,11 @@ struct CExtPubKey { friend bool operator==(const CExtPubKey &a, const CExtPubKey &b) { - return a.nDepth == b.nDepth && memcmp(&a.vchFingerprint[0], &b.vchFingerprint[0], 4) == 0 && a.nChild == b.nChild && - a.chaincode == b.chaincode && a.pubkey == b.pubkey; + return a.nDepth == b.nDepth && + memcmp(&a.vchFingerprint[0], &b.vchFingerprint[0], sizeof(vchFingerprint)) == 0 && + a.nChild == b.nChild && + a.chaincode == b.chaincode && + a.pubkey == b.pubkey; } void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const; From ab942c15bd3854650afa810d7c22d7fd30d346c1 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 18 Jul 2016 20:57:20 +0200 Subject: [PATCH 0637/1802] Treat high-sigop transactions as larger rather than rejecting them --- src/init.cpp | 2 +- src/main.cpp | 3 +-- src/main.h | 2 -- src/policy/policy.cpp | 10 ++++++---- src/policy/policy.h | 8 ++++++-- src/txmempool.cpp | 2 +- 6 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 312dfe1699c08..8d4a2cafbfbb1 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -446,7 +446,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageGroup(_("Node relay options:")); if (showDebug) strUsage += HelpMessageOpt("-acceptnonstdtxn", strprintf("Relay and mine \"non-standard\" transactions (%sdefault: %u)", "testnet/regtest only; ", !Params(CBaseChainParams::TESTNET).RequireStandard())); - strUsage += HelpMessageOpt("-bytespersigop", strprintf(_("Minimum bytes per sigop in transactions we relay and mine (default: %u)"), DEFAULT_BYTES_PER_SIGOP)); + strUsage += HelpMessageOpt("-bytespersigop", strprintf(_("Equivalent bytes per sigop in transactions for relay and mining (default: %u)"), DEFAULT_BYTES_PER_SIGOP)); strUsage += HelpMessageOpt("-datacarrier", strprintf(_("Relay and mine data carrier transactions (default: %u)"), DEFAULT_ACCEPT_DATACARRIER)); strUsage += HelpMessageOpt("-datacarriersize", strprintf(_("Maximum size of data in data carrier transactions we relay and mine (default: %u)"), MAX_OP_RETURN_RELAY)); strUsage += HelpMessageOpt("-mempoolreplacement", strprintf(_("Enable transaction replacement in the memory pool (default: %u)"), DEFAULT_ENABLE_REPLACEMENT)); diff --git a/src/main.cpp b/src/main.cpp index fe19895f5fbcc..e07d99ab06210 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -74,7 +74,6 @@ bool fHavePruned = false; bool fPruneMode = false; bool fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG; bool fRequireStandard = true; -unsigned int nBytesPerSigOp = DEFAULT_BYTES_PER_SIGOP; bool fCheckBlockIndex = false; bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED; size_t nCoinCacheUsage = 5000 * 300; @@ -1296,7 +1295,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C // itself can contain sigops MAX_STANDARD_TX_SIGOPS is less than // MAX_BLOCK_SIGOPS; we still consider this an invalid rather than // merely non-standard transaction. - if ((nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST) || (nBytesPerSigOp && nSigOpsCost > nSize * WITNESS_SCALE_FACTOR / nBytesPerSigOp)) + if (nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST) return state.DoS(0, false, REJECT_NONSTANDARD, "bad-txns-too-many-sigops", false, strprintf("%d", nSigOpsCost)); diff --git a/src/main.h b/src/main.h index 27121890f6d70..631dc00d05dce 100644 --- a/src/main.h +++ b/src/main.h @@ -124,7 +124,6 @@ static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60; /** Default for -permitbaremultisig */ static const bool DEFAULT_PERMIT_BAREMULTISIG = true; -static const unsigned int DEFAULT_BYTES_PER_SIGOP = 20; static const bool DEFAULT_CHECKPOINTS_ENABLED = true; static const bool DEFAULT_TXINDEX = false; static const unsigned int DEFAULT_BANSCORE_THRESHOLD = 100; @@ -165,7 +164,6 @@ extern int nScriptCheckThreads; extern bool fTxIndex; extern bool fIsBareMultisigStd; extern bool fRequireStandard; -extern unsigned int nBytesPerSigOp; extern bool fCheckBlockIndex; extern bool fCheckpointsEnabled; extern size_t nCoinCacheUsage; diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index 8617db00c8608..0cd3ac7119715 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -151,12 +151,14 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs) return true; } -int64_t GetVirtualTransactionSize(int64_t nWeight) +unsigned int nBytesPerSigOp = DEFAULT_BYTES_PER_SIGOP; + +int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost) { - return (nWeight + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR; + return (std::max(nWeight, nSigOpCost * nBytesPerSigOp) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR; } -int64_t GetVirtualTransactionSize(const CTransaction& tx) +int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t nSigOpCost) { - return GetVirtualTransactionSize(GetTransactionWeight(tx)); + return GetVirtualTransactionSize(GetTransactionWeight(tx), nSigOpCost); } diff --git a/src/policy/policy.h b/src/policy/policy.h index f5f8652fb5a72..b82c9e66b8852 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -28,6 +28,8 @@ static const unsigned int MAX_P2SH_SIGOPS = 15; static const unsigned int MAX_STANDARD_TX_SIGOPS_COST = MAX_BLOCK_SIGOPS_COST/5; /** Default for -maxmempool, maximum megabytes of mempool memory usage */ static const unsigned int DEFAULT_MAX_MEMPOOL_SIZE = 300; +/** Default for -bytespersigop */ +static const unsigned int DEFAULT_BYTES_PER_SIGOP = 20; /** * Standard script verification flags that standard transactions will comply * with. However scripts violating these flags may still be present in valid @@ -66,8 +68,10 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason); */ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs); +extern unsigned int nBytesPerSigOp; + /** Compute the virtual transaction size (weight reinterpreted as bytes). */ -int64_t GetVirtualTransactionSize(int64_t nWeight); -int64_t GetVirtualTransactionSize(const CTransaction& tx); +int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost); +int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t nSigOpCost = 0); #endif // BITCOIN_POLICY_POLICY_H diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 691baa674403f..82827b8e4f193 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -75,7 +75,7 @@ void CTxMemPoolEntry::UpdateLockPoints(const LockPoints& lp) size_t CTxMemPoolEntry::GetTxSize() const { - return GetVirtualTransactionSize(nTxWeight); + return GetVirtualTransactionSize(nTxWeight, sigOpCost); } // Update the given tx for any in-mempool descendants. From 3b3ce25df6cc84cd1e75a7ec20fc7da8d2ef76e0 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 19 Jul 2016 15:41:36 -0400 Subject: [PATCH 0638/1802] build: fix non-deterministic biplist The non-deterministic ordering produced by biplist ends up in the .DS_Store file that is included in the OSX dmg. --- depends/packages/native_biplist.mk | 5 ++++ .../patches/native_biplist/sorted_list.patch | 29 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 depends/patches/native_biplist/sorted_list.patch diff --git a/depends/packages/native_biplist.mk b/depends/packages/native_biplist.mk index eb8672d556a9c..3c6e8900f6646 100644 --- a/depends/packages/native_biplist.mk +++ b/depends/packages/native_biplist.mk @@ -4,6 +4,11 @@ $(package)_download_path=https://pypi.python.org/packages/source/b/biplist $(package)_file_name=biplist-$($(package)_version).tar.gz $(package)_sha256_hash=b57cadfd26e4754efdf89e9e37de87885f9b5c847b2615688ca04adfaf6ca604 $(package)_install_libdir=$(build_prefix)/lib/python/dist-packages +$(package)_patches=sorted_list.patch + +define $(package)_preprocess_cmds + patch -p1 < $($(package)_patch_dir)/sorted_list.patch +endef define $(package)_build_cmds python setup.py build diff --git a/depends/patches/native_biplist/sorted_list.patch b/depends/patches/native_biplist/sorted_list.patch new file mode 100644 index 0000000000000..89abdb1b71ff8 --- /dev/null +++ b/depends/patches/native_biplist/sorted_list.patch @@ -0,0 +1,29 @@ +--- a/biplist/__init__.py 2014-10-26 19:03:11.000000000 +0000 ++++ b/biplist/__init__.py 2016-07-19 19:30:17.663521999 +0000 +@@ -541,7 +541,7 @@ + return HashableWrapper(n) + elif isinstance(root, dict): + n = {} +- for key, value in iteritems(root): ++ for key, value in sorted(iteritems(root)): + n[self.wrapRoot(key)] = self.wrapRoot(value) + return HashableWrapper(n) + elif isinstance(root, list): +@@ -616,7 +616,7 @@ + elif isinstance(obj, dict): + size = proc_size(len(obj)) + self.incrementByteCount('dictBytes', incr=1+size) +- for key, value in iteritems(obj): ++ for key, value in sorted(iteritems(obj)): + check_key(key) + self.computeOffsets(key, asReference=True) + self.computeOffsets(value, asReference=True) +@@ -714,7 +714,7 @@ + keys = [] + values = [] + objectsToWrite = [] +- for key, value in iteritems(obj): ++ for key, value in sorted(iteritems(obj)): + keys.append(key) + values.append(value) + for key in keys: From 6523fcaab2f0808d4e47b9cb9ebbef7ed69a309e Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Tue, 19 Jul 2016 22:30:17 -0700 Subject: [PATCH 0639/1802] Move SetMinVersion for FEATURE_HD to SetHDMasterKey --- src/wallet/wallet.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index a76085de3093a..5908dfeaceae6 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1170,6 +1170,9 @@ bool CWallet::SetHDMasterKey(const CKey& key) { LOCK(cs_wallet); + // ensure this wallet.dat can only be opened by clients supporting HD + SetMinVersion(FEATURE_HD); + // store the key as normal "key"/"ckey" object // in the database // key metadata is not required @@ -3299,9 +3302,6 @@ bool CWallet::InitLoadWallet() key.MakeNewKey(true); if (!walletInstance->SetHDMasterKey(key)) throw std::runtime_error("CWallet::GenerateNewKey(): Storing master key failed"); - - // ensure this wallet.dat can only be opened by clients supporting HD - walletInstance->SetMinVersion(FEATURE_HD); } CPubKey newDefaultKey; if (walletInstance->GetKeyFromPool(newDefaultKey)) { From 2f32c82b3d128e42f15e22e00e4ef680d327365f Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Mon, 22 Feb 2016 16:21:27 +0100 Subject: [PATCH 0640/1802] [Qt] show network/chain errors in the GUI --- src/main.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index fe19895f5fbcc..0e7d172fbb92d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4647,6 +4647,7 @@ std::string GetWarnings(const std::string& strFor) string strStatusBar; string strRPC; string strGUI; + const string uiAlertSeperator = "
"; if (!CLIENT_VERSION_IS_RELEASE) { strStatusBar = "This is a pre-release test build - use at your own risk - do not use for mining or merchant applications"; @@ -4659,18 +4660,19 @@ std::string GetWarnings(const std::string& strFor) // Misc warnings like out of disk space and clock is wrong if (strMiscWarning != "") { - strStatusBar = strGUI = strMiscWarning; + strStatusBar = strMiscWarning; + strGUI += (strGUI.empty() ? "" : uiAlertSeperator) + strMiscWarning; } if (fLargeWorkForkFound) { strStatusBar = strRPC = "Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues."; - strGUI = _("Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues."); + strGUI += strGUI.empty() ? "" : uiAlertSeperator + _("Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues."); } else if (fLargeWorkInvalidChainFound) { strStatusBar = strRPC = "Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade."; - strGUI = _("Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade."); + strGUI += strGUI.empty() ? "" : uiAlertSeperator + _("Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade."); } if (strFor == "gui") From a615386552f9981dc024cc4a0df758f8b0fda4d8 Mon Sep 17 00:00:00 2001 From: fanquake Date: Wed, 22 Jun 2016 17:56:07 +0800 Subject: [PATCH 0641/1802] [depends] ZeroMQ 4.1.5 --- configure.ac | 9 ++++++++ depends/packages/packages.mk | 5 +---- depends/packages/zeromq.mk | 15 +++++++++---- ...d3957725acd34aa8b8d011585812f3369411.patch | 22 +++++++++++++++++++ ...45c12e0b100cd38acecc16ce7db02905e27c.patch | 22 +++++++++++++++++++ 5 files changed, 65 insertions(+), 8 deletions(-) create mode 100644 depends/patches/zeromq/9114d3957725acd34aa8b8d011585812f3369411.patch create mode 100644 depends/patches/zeromq/9e6745c12e0b100cd38acecc16ce7db02905e27c.patch diff --git a/configure.ac b/configure.ac index 78d63f92729dd..ef58cfc40d19d 100644 --- a/configure.ac +++ b/configure.ac @@ -816,6 +816,15 @@ else AC_DEFINE_UNQUOTED([ENABLE_ZMQ],[0],[Define to 1 to enable ZMQ functions]) fi + if test "x$use_zmq" = "xyes"; then + dnl Assume libzmq was built for static linking + case $host in + *mingw*) + ZMQ_CFLAGS="$ZMQ_CFLAGS -DZMQ_STATIC" + ;; + esac + fi + BITCOIN_QT_CHECK(AC_CHECK_LIB([protobuf] ,[main],[PROTOBUF_LIBS=-lprotobuf], BITCOIN_QT_FAIL(libprotobuf not found))) if test x$use_qr != xno; then BITCOIN_QT_CHECK([AC_CHECK_LIB([qrencode], [main],[QR_LIBS=-lqrencode], [have_qrencode=no])]) diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk index ac43ef4a2e304..ba2a05248c04e 100644 --- a/depends/packages/packages.mk +++ b/depends/packages/packages.mk @@ -1,6 +1,4 @@ -packages:=boost openssl libevent -darwin_packages:=zeromq -linux_packages:=zeromq +packages:=boost openssl libevent zeromq native_packages := native_ccache native_comparisontool qt_native_packages = native_protobuf @@ -12,7 +10,6 @@ qt_i686_linux_packages:=$(qt_x86_64_linux_packages) qt_darwin_packages=qt qt_mingw32_packages=qt - wallet_packages=bdb upnp_packages=miniupnpc diff --git a/depends/packages/zeromq.mk b/depends/packages/zeromq.mk index f8901f72c26c6..01146c26f69bc 100644 --- a/depends/packages/zeromq.mk +++ b/depends/packages/zeromq.mk @@ -1,15 +1,22 @@ package=zeromq -$(package)_version=4.1.4 -$(package)_download_path=http://download.zeromq.org +$(package)_version=4.1.5 +$(package)_download_path=https://github.com/zeromq/zeromq4-1/releases/download/v$($(package)_version)/ $(package)_file_name=$(package)-$($(package)_version).tar.gz -$(package)_sha256_hash=e99f44fde25c2e4cb84ce440f87ca7d3fe3271c2b8cfbc67d55e4de25e6fe378 +$(package)_sha256_hash=04aac57f081ffa3a2ee5ed04887be9e205df3a7ddade0027460b8042432bdbcf +$(package)_patches=9114d3957725acd34aa8b8d011585812f3369411.patch 9e6745c12e0b100cd38acecc16ce7db02905e27c.patch define $(package)_set_vars - $(package)_config_opts=--without-documentation --disable-shared --without-libsodium + $(package)_config_opts=--without-documentation --disable-shared --without-libsodium --disable-curve $(package)_config_opts_linux=--with-pic $(package)_cxxflags=-std=c++11 endef +define $(package)_preprocess_cmds + patch -p1 < $($(package)_patch_dir)/9114d3957725acd34aa8b8d011585812f3369411.patch && \ + patch -p1 < $($(package)_patch_dir)/9e6745c12e0b100cd38acecc16ce7db02905e27c.patch && \ + ./autogen.sh +endef + define $(package)_config_cmds $($(package)_autoconf) endef diff --git a/depends/patches/zeromq/9114d3957725acd34aa8b8d011585812f3369411.patch b/depends/patches/zeromq/9114d3957725acd34aa8b8d011585812f3369411.patch new file mode 100644 index 0000000000000..f704b3d94fda8 --- /dev/null +++ b/depends/patches/zeromq/9114d3957725acd34aa8b8d011585812f3369411.patch @@ -0,0 +1,22 @@ +From 9114d3957725acd34aa8b8d011585812f3369411 Mon Sep 17 00:00:00 2001 +From: Jeroen Ooms +Date: Tue, 20 Oct 2015 13:10:38 +0200 +Subject: [PATCH] enable static libraries on mingw + +--- + configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index 393505b..e92131a 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -265,7 +265,7 @@ case "${host_os}" in + libzmq_dso_visibility="no" + + if test "x$enable_static" = "xyes"; then +- AC_MSG_ERROR([Building static libraries is not supported under MinGW32]) ++ CPPFLAGS="-DZMQ_STATIC" + fi + + # Set FD_SETSIZE to 1024 \ No newline at end of file diff --git a/depends/patches/zeromq/9e6745c12e0b100cd38acecc16ce7db02905e27c.patch b/depends/patches/zeromq/9e6745c12e0b100cd38acecc16ce7db02905e27c.patch new file mode 100644 index 0000000000000..9aff2c179a198 --- /dev/null +++ b/depends/patches/zeromq/9e6745c12e0b100cd38acecc16ce7db02905e27c.patch @@ -0,0 +1,22 @@ +From 9e6745c12e0b100cd38acecc16ce7db02905e27c Mon Sep 17 00:00:00 2001 +From: David Millard +Date: Tue, 10 May 2016 13:53:53 -0700 +Subject: [PATCH] Fix autotools for static MinGW builds + +--- + configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index 5a0fa14..def6ea7 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -259,7 +259,7 @@ case "${host_os}" in + libzmq_dso_visibility="no" + + if test "x$enable_static" = "xyes"; then +- CPPFLAGS="-DZMQ_STATIC" ++ CPPFLAGS="-DZMQ_STATIC $CPPFLAGS" + fi + + # Set FD_SETSIZE to 1024 \ No newline at end of file From 208d37f116611fb43e16965369b6d654c9e18984 Mon Sep 17 00:00:00 2001 From: fanquake Date: Sun, 12 Jun 2016 11:11:24 +0800 Subject: [PATCH 0642/1802] [trivial] Remove URLs from About dialog translations --- src/init.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 312dfe1699c08..fac279059c257 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -481,7 +481,7 @@ std::string LicenseInfo() { const std::string URL_SOURCE_CODE = ""; const std::string URL_WEBSITE = ""; - // todo: remove urls from translations on next change + return CopyrightHolders(strprintf(_("Copyright (C) %i-%i"), 2009, COPYRIGHT_YEAR) + " ") + "\n" + "\n" + strprintf(_("Please contribute if you find %s useful. " @@ -493,9 +493,9 @@ std::string LicenseInfo() "\n" + "\n" + _("This is experimental software.") + "\n" + - _("Distributed under the MIT software license, see the accompanying file COPYING or .") + "\n" + + strprintf(_("Distributed under the MIT software license, see the accompanying file %s or %s"), "COPYING", "") + "\n" + "\n" + - _("This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.") + + strprintf(_("This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard."), "") + "\n"; } From 7821889bce171ba44b27efe21439526e2aa7eb71 Mon Sep 17 00:00:00 2001 From: NicolasDorier Date: Fri, 15 Jul 2016 00:02:59 +0900 Subject: [PATCH 0643/1802] Consensus: Remove calls to error() from ContextualCheckBlock --- src/main.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 60c597797d56c..90c6f57eff4a6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3576,11 +3576,11 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn // already does not permit it, it is impossible to trigger in the // witness tree. if (block.vtx[0].wit.vtxinwit.size() != 1 || block.vtx[0].wit.vtxinwit[0].scriptWitness.stack.size() != 1 || block.vtx[0].wit.vtxinwit[0].scriptWitness.stack[0].size() != 32) { - return state.DoS(100, error("%s : invalid witness nonce size", __func__), REJECT_INVALID, "bad-witness-nonce-size", true); + return state.DoS(100, false, REJECT_INVALID, "bad-witness-nonce-size", true, strprintf("%s : invalid witness nonce size", __func__)); } CHash256().Write(hashWitness.begin(), 32).Write(&block.vtx[0].wit.vtxinwit[0].scriptWitness.stack[0][0], 32).Finalize(hashWitness.begin()); if (memcmp(hashWitness.begin(), &block.vtx[0].vout[commitpos].scriptPubKey[6], 32)) { - return state.DoS(100, error("%s : witness merkle commitment mismatch", __func__), REJECT_INVALID, "bad-witness-merkle-match", true); + return state.DoS(100, false, REJECT_INVALID, "bad-witness-merkle-match", true, strprintf("%s : witness merkle commitment mismatch", __func__)); } fHaveWitness = true; } @@ -3590,7 +3590,7 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn if (!fHaveWitness) { for (size_t i = 0; i < block.vtx.size(); i++) { if (!block.vtx[i].wit.IsNull()) { - return state.DoS(100, error("%s : unexpected witness data found", __func__), REJECT_INVALID, "unexpected-witness", true); + return state.DoS(100, false, REJECT_INVALID, "unexpected-witness", true, strprintf("%s : unexpected witness data found", __func__)); } } } @@ -3602,7 +3602,7 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn // the block hash, so we couldn't mark the block as permanently // failed). if (GetBlockWeight(block) > MAX_BLOCK_WEIGHT) { - return state.DoS(100, error("ContextualCheckBlock(): weight limit failed"), REJECT_INVALID, "bad-blk-weight"); + return state.DoS(100, false, REJECT_INVALID, "bad-blk-weight", false, strprintf("%s : weight limit failed", __func__)); } return true; From b50e1ac298363a7733069f82709674d3a8cb3058 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 21 Jul 2016 21:52:30 +0200 Subject: [PATCH 0644/1802] [Wallet] Correct hdmasterkeyid/masterkeyid name confusion --- qa/rpc-tests/wallet-hd.py | 2 +- src/wallet/rpcwallet.cpp | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/qa/rpc-tests/wallet-hd.py b/qa/rpc-tests/wallet-hd.py index c738ee2207e5a..c11da1e9a9989 100755 --- a/qa/rpc-tests/wallet-hd.py +++ b/qa/rpc-tests/wallet-hd.py @@ -31,7 +31,7 @@ def run_test (self): tmpdir = self.options.tmpdir # Make sure we use hd, keep masterkeyid - masterkeyid = self.nodes[1].getwalletinfo()['masterkeyid'] + masterkeyid = self.nodes[1].getwalletinfo()['hdmasterkeyid'] assert_equal(len(masterkeyid), 40) # Import a non-HD private key in the HD wallet diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index b4831ad795093..4087b8e77b7a2 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2260,16 +2260,16 @@ UniValue getwalletinfo(const UniValue& params, bool fHelp) "Returns an object containing various wallet state info.\n" "\nResult:\n" "{\n" - " \"walletversion\": xxxxx, (numeric) the wallet version\n" - " \"balance\": xxxxxxx, (numeric) the total confirmed balance of the wallet in " + CURRENCY_UNIT + "\n" - " \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed balance of the wallet in " + CURRENCY_UNIT + "\n" - " \"immature_balance\": xxxxxx, (numeric) the total immature balance of the wallet in " + CURRENCY_UNIT + "\n" - " \"txcount\": xxxxxxx, (numeric) the total number of transactions in the wallet\n" - " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n" - " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n" - " \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n" - " \"paytxfee\": x.xxxx, (numeric) the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB\n" - " \"masterkeyid\": \"\", (string) the Hash160 of the HD master pubkey\n" + " \"walletversion\": xxxxx, (numeric) the wallet version\n" + " \"balance\": xxxxxxx, (numeric) the total confirmed balance of the wallet in " + CURRENCY_UNIT + "\n" + " \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed balance of the wallet in " + CURRENCY_UNIT + "\n" + " \"immature_balance\": xxxxxx, (numeric) the total immature balance of the wallet in " + CURRENCY_UNIT + "\n" + " \"txcount\": xxxxxxx, (numeric) the total number of transactions in the wallet\n" + " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n" + " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n" + " \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n" + " \"paytxfee\": x.xxxx, (numeric) the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB\n" + " \"hdmasterkeyid\": \"\", (string) the Hash160 of the HD master pubkey\n" "}\n" "\nExamples:\n" + HelpExampleCli("getwalletinfo", "") @@ -2291,7 +2291,7 @@ UniValue getwalletinfo(const UniValue& params, bool fHelp) obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK()))); CKeyID masterKeyID = pwalletMain->GetHDChain().masterKeyID; if (!masterKeyID.IsNull()) - obj.push_back(Pair("masterkeyid", masterKeyID.GetHex())); + obj.push_back(Pair("hdmasterkeyid", masterKeyID.GetHex())); return obj; } From 1ffaff2f747af683513d6d74a7241d41e3f6e051 Mon Sep 17 00:00:00 2001 From: Johnson Lau Date: Wed, 20 Jul 2016 18:31:45 +0800 Subject: [PATCH 0645/1802] Make witness v0 outputs non-standard before segwit activation --- src/main.cpp | 5 +++-- src/policy/policy.cpp | 9 ++++++--- src/policy/policy.h | 4 ++-- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index fe19895f5fbcc..70f0a424755a2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1144,13 +1144,14 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C } // Reject transactions with witness before segregated witness activates (override with -prematurewitness) - if (!GetBoolArg("-prematurewitness",false) && !tx.wit.IsNull() && !IsWitnessEnabled(chainActive.Tip(), Params().GetConsensus())) { + bool witnessEnabled = IsWitnessEnabled(chainActive.Tip(), Params().GetConsensus()); + if (!GetBoolArg("-prematurewitness",false) && !tx.wit.IsNull() && !witnessEnabled) { return state.DoS(0, false, REJECT_NONSTANDARD, "no-witness-yet", true); } // Rather not work on nonstandard transactions (unless -testnet/-regtest) string reason; - if (fRequireStandard && !IsStandardTx(tx, reason)) + if (fRequireStandard && !IsStandardTx(tx, reason, witnessEnabled)) return state.DoS(0, false, REJECT_NONSTANDARD, reason); // Only accept nLockTime-using transactions that can be mined in the next diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index 8617db00c8608..de3996bb4a480 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -31,7 +31,7 @@ * DUP CHECKSIG DROP ... repeated 100 times... OP_1 */ -bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType) +bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType, const bool witnessEnabled) { std::vector > vSolutions; if (!Solver(scriptPubKey, whichType, vSolutions)) @@ -49,11 +49,14 @@ bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType) } else if (whichType == TX_NULL_DATA && (!fAcceptDatacarrier || scriptPubKey.size() > nMaxDatacarrierBytes)) return false; + + else if (!witnessEnabled && (whichType == TX_WITNESS_V0_KEYHASH || whichType == TX_WITNESS_V0_SCRIPTHASH)) + return false; return whichType != TX_NONSTANDARD; } -bool IsStandardTx(const CTransaction& tx, std::string& reason) +bool IsStandardTx(const CTransaction& tx, std::string& reason, const bool witnessEnabled) { if (tx.nVersion > CTransaction::MAX_STANDARD_VERSION || tx.nVersion < 1) { reason = "version"; @@ -92,7 +95,7 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason) unsigned int nDataOut = 0; txnouttype whichType; BOOST_FOREACH(const CTxOut& txout, tx.vout) { - if (!::IsStandard(txout.scriptPubKey, whichType)) { + if (!::IsStandard(txout.scriptPubKey, whichType, witnessEnabled)) { reason = "scriptpubkey"; return false; } diff --git a/src/policy/policy.h b/src/policy/policy.h index f5f8652fb5a72..ad209d0306e2b 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -53,12 +53,12 @@ static const unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_ static const unsigned int STANDARD_LOCKTIME_VERIFY_FLAGS = LOCKTIME_VERIFY_SEQUENCE | LOCKTIME_MEDIAN_TIME_PAST; -bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType); +bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType, const bool witnessEnabled = false); /** * Check for standard transaction types * @return True if all outputs (scriptPubKeys) use only standard transaction forms */ -bool IsStandardTx(const CTransaction& tx, std::string& reason); +bool IsStandardTx(const CTransaction& tx, std::string& reason, const bool witnessEnabled = false); /** * Check for standard transaction types * @param[in] mapInputs Map of previous transactions that have outputs we're spending From c59c434b7d1211c13f7904b9bc675e16910a1c0a Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Fri, 22 Jul 2016 11:09:45 -0400 Subject: [PATCH 0646/1802] qa: Add test for standardness of segwit v0 outputs --- qa/rpc-tests/p2p-segwit.py | 78 ++++++++++++++++++++++++++++++++++++++ src/policy/policy.cpp | 2 +- 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/qa/rpc-tests/p2p-segwit.py b/qa/rpc-tests/p2p-segwit.py index fa2c5d1f05e24..cd02692b1e88c 100755 --- a/qa/rpc-tests/p2p-segwit.py +++ b/qa/rpc-tests/p2p-segwit.py @@ -1086,6 +1086,82 @@ def test_block_relay(self, segwit_activated): self.old_node.announce_tx_and_wait_for_getdata(block4.vtx[0]) assert(block4.sha256 not in self.old_node.getdataset) + # V0 segwit outputs should be standard after activation, but not before. + def test_standardness_v0(self, segwit_activated): + print("\tTesting standardness of v0 outputs (%s activation)" % ("after" if segwit_activated else "before")) + assert(len(self.utxo)) + + witness_program = CScript([OP_TRUE]) + witness_hash = sha256(witness_program) + scriptPubKey = CScript([OP_0, witness_hash]) + + p2sh_pubkey = hash160(witness_program) + p2sh_scriptPubKey = CScript([OP_HASH160, p2sh_pubkey, OP_EQUAL]) + + # First prepare a p2sh output (so that spending it will pass standardness) + p2sh_tx = CTransaction() + p2sh_tx.vin = [CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")] + p2sh_tx.vout = [CTxOut(self.utxo[0].nValue-1000, p2sh_scriptPubKey)] + p2sh_tx.rehash() + + # Mine it on test_node to create the confirmed output. + self.test_node.test_transaction_acceptance(p2sh_tx, with_witness=True, accepted=True) + self.nodes[0].generate(1) + sync_blocks(self.nodes) + + # Now test standardness of v0 P2WSH outputs. + # Start by creating a transaction with two outputs. + tx = CTransaction() + tx.vin = [CTxIn(COutPoint(p2sh_tx.sha256, 0), CScript([witness_program]))] + tx.vout = [CTxOut(p2sh_tx.vout[0].nValue-10000, scriptPubKey)] + tx.vout.append(CTxOut(8000, scriptPubKey)) # Might burn this later + tx.rehash() + + self.std_node.test_transaction_acceptance(tx, with_witness=True, accepted=segwit_activated) + + # Now create something that looks like a P2PKH output. This won't be spendable. + scriptPubKey = CScript([OP_0, hash160(witness_hash)]) + tx2 = CTransaction() + if segwit_activated: + # if tx was accepted, then we spend the second output. + tx2.vin = [CTxIn(COutPoint(tx.sha256, 1), b"")] + tx2.vout = [CTxOut(7000, scriptPubKey)] + tx2.wit.vtxinwit.append(CTxInWitness()) + tx2.wit.vtxinwit[0].scriptWitness.stack = [witness_program] + else: + # if tx wasn't accepted, we just re-spend the p2sh output we started with. + tx2.vin = [CTxIn(COutPoint(p2sh_tx.sha256, 0), CScript([witness_program]))] + tx2.vout = [CTxOut(p2sh_tx.vout[0].nValue-1000, scriptPubKey)] + tx2.rehash() + + self.std_node.test_transaction_acceptance(tx2, with_witness=True, accepted=segwit_activated) + + # Now update self.utxo for later tests. + tx3 = CTransaction() + if segwit_activated: + # tx and tx2 were both accepted. Don't bother trying to reclaim the + # P2PKH output; just send tx's first output back to an anyone-can-spend. + sync_mempools(self.nodes) + tx3.vin = [CTxIn(COutPoint(tx.sha256, 0), b"")] + tx3.vout = [CTxOut(tx.vout[0].nValue-1000, CScript([OP_TRUE]))] + tx3.wit.vtxinwit.append(CTxInWitness()) + tx3.wit.vtxinwit[0].scriptWitness.stack = [witness_program] + tx3.rehash() + self.test_node.test_transaction_acceptance(tx3, with_witness=True, accepted=True) + else: + # tx and tx2 didn't go anywhere; just clean up the p2sh_tx output. + tx3.vin = [CTxIn(COutPoint(p2sh_tx.sha256, 0), CScript([witness_program]))] + tx3.vout = [CTxOut(p2sh_tx.vout[0].nValue-1000, witness_program)] + tx3.rehash() + self.test_node.test_transaction_acceptance(tx3, with_witness=True, accepted=True) + + self.nodes[0].generate(1) + sync_blocks(self.nodes) + self.utxo.pop(0) + self.utxo.append(UTXO(tx3.sha256, 0, tx3.vout[0].nValue)) + assert_equal(len(self.nodes[1].getrawmempool()), 0) + + # Verify that future segwit upgraded transactions are non-standard, # but valid in blocks. Can run this before and after segwit activation. def test_segwit_versions(self): @@ -1658,6 +1734,7 @@ def run_test(self): self.test_witness_tx_relay_before_segwit_activation() self.test_block_relay(segwit_activated=False) self.test_p2sh_witness(segwit_activated=False) + self.test_standardness_v0(segwit_activated=False) sync_blocks(self.nodes) @@ -1679,6 +1756,7 @@ def run_test(self): self.test_witness_input_length() self.test_block_relay(segwit_activated=True) self.test_tx_relay_after_segwit_activation() + self.test_standardness_v0(segwit_activated=True) self.test_segwit_versions() self.test_premature_coinbase_witness_spend() self.test_signature_version_1() diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index de3996bb4a480..57df1f0b1956b 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -49,7 +49,7 @@ bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType, const bool w } else if (whichType == TX_NULL_DATA && (!fAcceptDatacarrier || scriptPubKey.size() > nMaxDatacarrierBytes)) return false; - + else if (!witnessEnabled && (whichType == TX_WITNESS_V0_KEYHASH || whichType == TX_WITNESS_V0_SCRIPTHASH)) return false; From 122786d0e0170c73536360b705af711e1338adbf Mon Sep 17 00:00:00 2001 From: NicolasDorier Date: Fri, 22 Jul 2016 08:27:55 +0900 Subject: [PATCH 0647/1802] Consensus: Remove ISM --- qa/rpc-tests/bip65-cltv-p2p.py | 40 +++++++++++++++---------------- qa/rpc-tests/bip65-cltv.py | 3 ++- qa/rpc-tests/bipdersig-p2p.py | 42 ++++++++++++++++---------------- src/chainparams.cpp | 17 ++++++------- src/consensus/params.h | 8 +++---- src/main.cpp | 44 ++++++++++------------------------ src/rpc/blockchain.cpp | 36 +++++++++++++--------------- 7 files changed, 83 insertions(+), 107 deletions(-) diff --git a/qa/rpc-tests/bip65-cltv-p2p.py b/qa/rpc-tests/bip65-cltv-p2p.py index 754b6873b71ff..e903b2fbf07b3 100755 --- a/qa/rpc-tests/bip65-cltv-p2p.py +++ b/qa/rpc-tests/bip65-cltv-p2p.py @@ -71,9 +71,9 @@ def get_tests(self): self.nodeaddress = self.nodes[0].getnewaddress() self.last_block_time = int(time.time()) - ''' 98 more version 3 blocks ''' + ''' 398 more version 3 blocks ''' test_blocks = [] - for i in range(98): + for i in range(398): block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1) block.nVersion = 3 block.rehash() @@ -118,24 +118,6 @@ def get_tests(self): height += 1 yield TestInstance([[block, True]]) - ''' - Check that the new CLTV rules are enforced in the 751st version 4 - block. - ''' - spendtx = self.create_transaction(self.nodes[0], - self.coinbase_blocks[1], self.nodeaddress, 1.0) - cltv_invalidate(spendtx) - spendtx.rehash() - - block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1) - block.nVersion = 4 - block.vtx.append(spendtx) - block.hashMerkleRoot = block.calc_merkle_root() - block.rehash() - block.solve() - self.last_block_time += 1 - yield TestInstance([[block, False]]) - ''' Mine 199 new version blocks on last valid tip ''' test_blocks = [] for i in range(199): @@ -169,6 +151,24 @@ def get_tests(self): height += 1 yield TestInstance([[block, True]]) + ''' + Check that the new CLTV rules are enforced in the 951st version 4 + block. + ''' + spendtx = self.create_transaction(self.nodes[0], + self.coinbase_blocks[1], self.nodeaddress, 1.0) + cltv_invalidate(spendtx) + spendtx.rehash() + + block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1) + block.nVersion = 4 + block.vtx.append(spendtx) + block.hashMerkleRoot = block.calc_merkle_root() + block.rehash() + block.solve() + self.last_block_time += 1 + yield TestInstance([[block, False]]) + ''' Mine 1 old version block, should be invalid ''' block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1) block.nVersion = 3 diff --git a/qa/rpc-tests/bip65-cltv.py b/qa/rpc-tests/bip65-cltv.py index abba7fc20e7d9..baa77b92a05bb 100755 --- a/qa/rpc-tests/bip65-cltv.py +++ b/qa/rpc-tests/bip65-cltv.py @@ -30,7 +30,8 @@ def run_test(self): cnt = self.nodes[0].getblockcount() # Mine some old-version blocks - self.nodes[1].generate(100) + self.nodes[1].generate(200) + cnt += 100 self.sync_all() if (self.nodes[0].getblockcount() != cnt + 100): raise AssertionError("Failed to mine 100 version=3 blocks") diff --git a/qa/rpc-tests/bipdersig-p2p.py b/qa/rpc-tests/bipdersig-p2p.py index 4e4936a4ae6de..3bad5af5e67a4 100755 --- a/qa/rpc-tests/bipdersig-p2p.py +++ b/qa/rpc-tests/bipdersig-p2p.py @@ -79,9 +79,9 @@ def get_tests(self): self.nodeaddress = self.nodes[0].getnewaddress() self.last_block_time = int(time.time()) - ''' 98 more version 2 blocks ''' + ''' 298 more version 2 blocks ''' test_blocks = [] - for i in range(98): + for i in range(298): block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1) block.nVersion = 2 block.rehash() @@ -124,25 +124,7 @@ def get_tests(self): self.last_block_time += 1 self.tip = block.sha256 height += 1 - yield TestInstance([[block, True]]) - - ''' - Check that the new DERSIG rules are enforced in the 751st version 3 - block. - ''' - spendtx = self.create_transaction(self.nodes[0], - self.coinbase_blocks[1], self.nodeaddress, 1.0) - unDERify(spendtx) - spendtx.rehash() - - block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1) - block.nVersion = 3 - block.vtx.append(spendtx) - block.hashMerkleRoot = block.calc_merkle_root() - block.rehash() - block.solve() - self.last_block_time += 1 - yield TestInstance([[block, False]]) + yield TestInstance([[block, True]]) ''' Mine 199 new version blocks on last valid tip ''' test_blocks = [] @@ -177,6 +159,24 @@ def get_tests(self): height += 1 yield TestInstance([[block, True]]) + ''' + Check that the new DERSIG rules are enforced in the 951st version 3 + block. + ''' + spendtx = self.create_transaction(self.nodes[0], + self.coinbase_blocks[1], self.nodeaddress, 1.0) + unDERify(spendtx) + spendtx.rehash() + + block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1) + block.nVersion = 3 + block.vtx.append(spendtx) + block.hashMerkleRoot = block.calc_merkle_root() + block.rehash() + block.solve() + self.last_block_time += 1 + yield TestInstance([[block, False]]) + ''' Mine 1 old version block, should be invalid ''' block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1) block.nVersion = 2 diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 86bef1e105006..c7c8ce73d99f5 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -71,11 +71,10 @@ class CMainParams : public CChainParams { CMainParams() { strNetworkID = "main"; consensus.nSubsidyHalvingInterval = 210000; - consensus.nMajorityEnforceBlockUpgrade = 750; - consensus.nMajorityRejectBlockOutdated = 950; - consensus.nMajorityWindow = 1000; consensus.BIP34Height = 227931; consensus.BIP34Hash = uint256S("0x000000000000024b89b42a942fe0d9fea3bb44ab7bd1b19115dd6a759c0808b8"); + consensus.BIP65Height = 388381; // 000000000000000004c2b624ed5d7756c508d90fd0da2c7c679febfa6c4735f0 + consensus.BIP66Height = 363725; // 00000000000000000379eaa19dce8c9b722d46ae6a57c2f1a988119488b50931 consensus.powLimit = uint256S("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks consensus.nPowTargetSpacing = 10 * 60; @@ -167,11 +166,10 @@ class CTestNetParams : public CChainParams { CTestNetParams() { strNetworkID = "test"; consensus.nSubsidyHalvingInterval = 210000; - consensus.nMajorityEnforceBlockUpgrade = 51; - consensus.nMajorityRejectBlockOutdated = 75; - consensus.nMajorityWindow = 100; consensus.BIP34Height = 21111; consensus.BIP34Hash = uint256S("0x0000000023b3a96d3484e5abb3755c413e7d41500f8e2a5c3f0dd01299cd8ef8"); + consensus.BIP65Height = 581885; // 00000000007f6655f22f98e72ed80d8b06dc761d5da09df0fa1dc4be4f861eb6 + consensus.BIP66Height = 330776; // 000000002104c8c45e99a8853285a3b592602a3ccde2b832481da85e9e4ba182 consensus.powLimit = uint256S("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks consensus.nPowTargetSpacing = 10 * 60; @@ -247,11 +245,10 @@ class CRegTestParams : public CChainParams { CRegTestParams() { strNetworkID = "regtest"; consensus.nSubsidyHalvingInterval = 150; - consensus.nMajorityEnforceBlockUpgrade = 750; - consensus.nMajorityRejectBlockOutdated = 950; - consensus.nMajorityWindow = 1000; - consensus.BIP34Height = -1; // BIP34 has not necessarily activated on regtest + consensus.BIP34Height = 100000000; // BIP34 has not activated on regtest (far in the future so block v1 are not rejected in tests) consensus.BIP34Hash = uint256(); + consensus.BIP65Height = 1351; // BIP65 activated on regtest (Used in rpc activation tests) + consensus.BIP66Height = 1251; // BIP66 activated on regtest (Used in rpc activation tests) consensus.powLimit = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks consensus.nPowTargetSpacing = 10 * 60; diff --git a/src/consensus/params.h b/src/consensus/params.h index 822ec87d69e86..5b2f49184fc3f 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -39,13 +39,13 @@ struct BIP9Deployment { struct Params { uint256 hashGenesisBlock; int nSubsidyHalvingInterval; - /** Used to check majorities for block version upgrade */ - int nMajorityEnforceBlockUpgrade; - int nMajorityRejectBlockOutdated; - int nMajorityWindow; /** Block height and hash at which BIP34 becomes active */ int BIP34Height; uint256 BIP34Hash; + /** Block height at which BIP65 becomes active */ + int BIP65Height; + /** Block height at which BIP66 becomes active */ + int BIP66Height; /** * Minimum blocks including miner confirmation of the total of 2016 blocks in a retargetting period, * (nPowTargetTimespan / nPowTargetSpacing) which is also used for BIP9 deployments. diff --git a/src/main.cpp b/src/main.cpp index 124bc57e7d14e..e92dbd72feaa1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -107,11 +107,6 @@ map mapOrphanTransactions GUARDED_BY(cs_main); map::iterator, IteratorComparator>> mapOrphanTransactionsByPrev GUARDED_BY(cs_main); void EraseOrphansFor(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main); -/** - * Returns true if there are nRequired or more blocks of minVersion or above - * in the last Consensus::Params::nMajorityWindow blocks, starting at pstart and going backwards. - */ -static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned nRequired, const Consensus::Params& consensusParams); static void CheckBlockIndex(const Consensus::Params& consensusParams); /** Constant stuff for coinbase transactions we create: */ @@ -2372,15 +2367,13 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin unsigned int flags = fStrictPayToScriptHash ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE; - // Start enforcing the DERSIG (BIP66) rules, for block.nVersion=3 blocks, - // when 75% of the network has upgraded: - if (block.nVersion >= 3 && IsSuperMajority(3, pindex->pprev, chainparams.GetConsensus().nMajorityEnforceBlockUpgrade, chainparams.GetConsensus())) { + // Start enforcing the DERSIG (BIP66) rule + if (pindex->nHeight >= chainparams.GetConsensus().BIP66Height) { flags |= SCRIPT_VERIFY_DERSIG; } - // Start enforcing CHECKLOCKTIMEVERIFY, (BIP65) for block.nVersion=4 - // blocks, when 75% of the network has upgraded: - if (block.nVersion >= 4 && IsSuperMajority(4, pindex->pprev, chainparams.GetConsensus().nMajorityEnforceBlockUpgrade, chainparams.GetConsensus())) { + // Start enforcing CHECKLOCKTIMEVERIFY (BIP65) rule + if (pindex->nHeight >= chainparams.GetConsensus().BIP65Height) { flags |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY; } @@ -3504,6 +3497,7 @@ std::vector GenerateCoinbaseCommitment(CBlock& block, const CBloc bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev, int64_t nAdjustedTime) { + const int nHeight = pindexPrev == NULL ? 0 : pindexPrev->nHeight + 1; // Check proof of work if (block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams)) return state.DoS(100, false, REJECT_INVALID, "bad-diffbits", false, "incorrect proof of work"); @@ -3517,10 +3511,12 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta return state.Invalid(false, REJECT_INVALID, "time-too-new", "block timestamp too far in the future"); // Reject outdated version blocks when 95% (75% on testnet) of the network has upgraded: - for (int32_t version = 2; version < 5; ++version) // check for version 2, 3 and 4 upgrades - if (block.nVersion < version && IsSuperMajority(version, pindexPrev, consensusParams.nMajorityRejectBlockOutdated, consensusParams)) - return state.Invalid(false, REJECT_OBSOLETE, strprintf("bad-version(0x%08x)", version - 1), - strprintf("rejected nVersion=0x%08x block", version - 1)); + // check for version 2, 3 and 4 upgrades + if((block.nVersion < 2 && nHeight >= consensusParams.BIP34Height) || + (block.nVersion < 3 && nHeight >= consensusParams.BIP66Height) || + (block.nVersion < 4 && nHeight >= consensusParams.BIP65Height)) + return state.Invalid(false, REJECT_OBSOLETE, strprintf("bad-version(0x%08x)", block.nVersion), + strprintf("rejected nVersion=0x%08x block", block.nVersion)); return true; } @@ -3547,9 +3543,8 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const CB } } - // Enforce block.nVersion=2 rule that the coinbase starts with serialized block height - // if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet): - if (block.nVersion >= 2 && IsSuperMajority(2, pindexPrev, consensusParams.nMajorityEnforceBlockUpgrade, consensusParams)) + // Enforce rule that the coinbase starts with serialized block height + if (nHeight >= consensusParams.BIP34Height) { CScript expect = CScript() << nHeight; if (block.vtx[0].vin[0].scriptSig.size() < expect.size() || @@ -3722,19 +3717,6 @@ static bool AcceptBlock(const CBlock& block, CValidationState& state, const CCha return true; } -static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned nRequired, const Consensus::Params& consensusParams) -{ - unsigned int nFound = 0; - for (int i = 0; i < consensusParams.nMajorityWindow && nFound < nRequired && pstart != NULL; i++) - { - if (pstart->nVersion >= minVersion) - ++nFound; - pstart = pstart->pprev; - } - return (nFound >= nRequired); -} - - bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp) { { diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 9dc896b7af281..e3c32d905af74 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -817,22 +817,23 @@ UniValue verifychain(const UniValue& params, bool fHelp) } /** Implementation of IsSuperMajority with better feedback */ -static UniValue SoftForkMajorityDesc(int minVersion, CBlockIndex* pindex, int nRequired, const Consensus::Params& consensusParams) +static UniValue SoftForkMajorityDesc(int version, CBlockIndex* pindex, const Consensus::Params& consensusParams) { - int nFound = 0; - CBlockIndex* pstart = pindex; - for (int i = 0; i < consensusParams.nMajorityWindow && pstart != NULL; i++) + UniValue rv(UniValue::VOBJ); + bool activated = false; + switch(version) { - if (pstart->nVersion >= minVersion) - ++nFound; - pstart = pstart->pprev; + case 2: + activated = pindex->nHeight >= consensusParams.BIP34Height; + break; + case 3: + activated = pindex->nHeight >= consensusParams.BIP66Height; + break; + case 4: + activated = pindex->nHeight >= consensusParams.BIP65Height; + break; } - - UniValue rv(UniValue::VOBJ); - rv.push_back(Pair("status", nFound >= nRequired)); - rv.push_back(Pair("found", nFound)); - rv.push_back(Pair("required", nRequired)); - rv.push_back(Pair("window", consensusParams.nMajorityWindow)); + rv.push_back(Pair("status", activated)); return rv; } @@ -841,8 +842,7 @@ static UniValue SoftForkDesc(const std::string &name, int version, CBlockIndex* UniValue rv(UniValue::VOBJ); rv.push_back(Pair("id", name)); rv.push_back(Pair("version", version)); - rv.push_back(Pair("enforce", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityEnforceBlockUpgrade, consensusParams))); - rv.push_back(Pair("reject", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityRejectBlockOutdated, consensusParams))); + rv.push_back(Pair("reject", SoftForkMajorityDesc(version, pindex, consensusParams))); return rv; } @@ -897,13 +897,9 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) " {\n" " \"id\": \"xxxx\", (string) name of softfork\n" " \"version\": xx, (numeric) block version\n" - " \"enforce\": { (object) progress toward enforcing the softfork rules for new-version blocks\n" + " \"reject\": { (object) progress toward rejecting pre-softfork blocks\n" " \"status\": xx, (boolean) true if threshold reached\n" - " \"found\": xx, (numeric) number of blocks with the new version found\n" - " \"required\": xx, (numeric) number of blocks required to trigger\n" - " \"window\": xx, (numeric) maximum size of examined window of recent blocks\n" " },\n" - " \"reject\": { ... } (object) progress toward rejecting pre-softfork blocks (same fields as \"enforce\")\n" " }, ...\n" " ],\n" " \"bip9_softforks\": { (object) status of BIP9 softforks in progress\n" From cc021ef4862ee8c67453aebf746b98b591e4fc99 Mon Sep 17 00:00:00 2001 From: lizhi Date: Sun, 24 Jul 2016 10:49:07 +0800 Subject: [PATCH 0648/1802] remove outdated legacy code CheckSignatureElement is not used,it be replaced by eccrypto::CheckSignatureElement. --- src/key.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/key.h b/src/key.h index b4f48d59f5b08..4e5e208928d59 100644 --- a/src/key.h +++ b/src/key.h @@ -146,9 +146,6 @@ class CKey //! Load private key and check that public key matches. bool Load(CPrivKey& privkey, CPubKey& vchPubKey, bool fSkipCheck); - - //! Check whether an element of a signature (r or s) is valid. - static bool CheckSignatureElement(const unsigned char* vch, int len, bool half); }; struct CExtKey { From 0ff4375c93bd159233282de5a33ad2e6c1e79841 Mon Sep 17 00:00:00 2001 From: whythat Date: Mon, 25 Jul 2016 01:30:28 +0300 Subject: [PATCH 0649/1802] [qa]: add parsing for ':' argument form to rpc_url() --- qa/rpc-tests/test_framework/util.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index 32fe79efc38be..8aa34265c5447 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -171,7 +171,15 @@ def rpc_auth_pair(n): def rpc_url(i, rpchost=None): rpc_u, rpc_p = rpc_auth_pair(i) - return "http://%s:%s@%s:%d" % (rpc_u, rpc_p, rpchost or '127.0.0.1', rpc_port(i)) + host = '127.0.0.1' + port = rpc_port(i) + if rpchost: + parts = rpchost.split(':') + if len(parts) == 2: + host, port = parts + else: + host = rpchost + return "http://%s:%s@%s:%d" % (rpc_u, rpc_p, host, int(port)) def wait_for_bitcoind_start(process, url, i): ''' From 9bbb414b800cf71f93f15d2cb5d4cf32c72294e6 Mon Sep 17 00:00:00 2001 From: whythat Date: Mon, 25 Jul 2016 01:31:05 +0300 Subject: [PATCH 0650/1802] [qa]: enable rpcbind_test --- qa/pull-tester/rpc-tests.py | 2 +- qa/rpc-tests/rpcbind_test.py | 219 +++++++++++++++-------------------- 2 files changed, 93 insertions(+), 128 deletions(-) diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index 11b83bac1468d..84ab9d92c5090 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -158,7 +158,7 @@ 'txn_clone.py --mineblock', 'forknotify.py', 'invalidateblock.py', -# 'rpcbind_test.py', #temporary, bug in libevent, see #6655 + 'rpcbind_test.py', 'smartfees.py', 'maxblocksinflight.py', 'p2p-acceptblock.py', diff --git a/qa/rpc-tests/rpcbind_test.py b/qa/rpc-tests/rpcbind_test.py index 572273566b63a..bf1cc8712611a 100755 --- a/qa/rpc-tests/rpcbind_test.py +++ b/qa/rpc-tests/rpcbind_test.py @@ -5,143 +5,108 @@ # Test for -rpcbind, as well as -rpcallowip and -rpcconnect -# TODO extend this test from the test framework (like all other tests) - import tempfile import traceback +from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * from test_framework.netutil import * -def run_bind_test(tmpdir, allow_ips, connect_to, addresses, expected): - ''' - Start a node with requested rpcallowip and rpcbind parameters, - then try to connect, and check if the set of bound addresses - matches the expected set. - ''' - expected = [(addr_to_hex(addr), port) for (addr, port) in expected] - base_args = ['-disablewallet', '-nolisten'] - if allow_ips: - base_args += ['-rpcallowip=' + x for x in allow_ips] - binds = ['-rpcbind='+addr for addr in addresses] - nodes = start_nodes(self.num_nodes, tmpdir, [base_args + binds], connect_to) - try: - pid = bitcoind_processes[0].pid - assert_equal(set(get_bind_addrs(pid)), set(expected)) - finally: - stop_nodes(nodes) - wait_bitcoinds() - -def run_allowip_test(tmpdir, allow_ips, rpchost, rpcport): - ''' - Start a node with rpcwallow IP, and request getinfo - at a non-localhost IP. - ''' - base_args = ['-disablewallet', '-nolisten'] + ['-rpcallowip='+x for x in allow_ips] - nodes = start_nodes(self.num_nodes, tmpdir, [base_args]) - try: - # connect to node through non-loopback interface - url = "http://rt:rt@%s:%d" % (rpchost, rpcport,) - node = get_rpc_proxy(url, 1) - node.getinfo() - finally: - node = None # make sure connection will be garbage collected and closed - stop_nodes(nodes) - wait_bitcoinds() - - -def run_test(tmpdir): - assert(sys.platform.startswith('linux')) # due to OS-specific network stats queries, this test works only on Linux - # find the first non-loopback interface for testing - non_loopback_ip = None - for name,ip in all_interfaces(): - if ip != '127.0.0.1': - non_loopback_ip = ip - break - if non_loopback_ip is None: - assert(not 'This test requires at least one non-loopback IPv4 interface') - print("Using interface %s for testing" % non_loopback_ip) +class RPCBindTest(BitcoinTestFramework): - defaultport = rpc_port(0) + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 1 - # check default without rpcallowip (IPv4 and IPv6 localhost) - run_bind_test(tmpdir, None, '127.0.0.1', [], - [('127.0.0.1', defaultport), ('::1', defaultport)]) - # check default with rpcallowip (IPv6 any) - run_bind_test(tmpdir, ['127.0.0.1'], '127.0.0.1', [], - [('::0', defaultport)]) - # check only IPv4 localhost (explicit) - run_bind_test(tmpdir, ['127.0.0.1'], '127.0.0.1', ['127.0.0.1'], - [('127.0.0.1', defaultport)]) - # check only IPv4 localhost (explicit) with alternative port - run_bind_test(tmpdir, ['127.0.0.1'], '127.0.0.1:32171', ['127.0.0.1:32171'], - [('127.0.0.1', 32171)]) - # check only IPv4 localhost (explicit) with multiple alternative ports on same host - run_bind_test(tmpdir, ['127.0.0.1'], '127.0.0.1:32171', ['127.0.0.1:32171', '127.0.0.1:32172'], - [('127.0.0.1', 32171), ('127.0.0.1', 32172)]) - # check only IPv6 localhost (explicit) - run_bind_test(tmpdir, ['[::1]'], '[::1]', ['[::1]'], - [('::1', defaultport)]) - # check both IPv4 and IPv6 localhost (explicit) - run_bind_test(tmpdir, ['127.0.0.1'], '127.0.0.1', ['127.0.0.1', '[::1]'], - [('127.0.0.1', defaultport), ('::1', defaultport)]) - # check only non-loopback interface - run_bind_test(tmpdir, [non_loopback_ip], non_loopback_ip, [non_loopback_ip], - [(non_loopback_ip, defaultport)]) - - # Check that with invalid rpcallowip, we are denied - run_allowip_test(tmpdir, [non_loopback_ip], non_loopback_ip, defaultport) - try: - run_allowip_test(tmpdir, ['1.1.1.1'], non_loopback_ip, defaultport) - assert(not 'Connection not denied by rpcallowip as expected') - except ValueError: + def setup_network(self): pass -def main(): - import optparse - - parser = optparse.OptionParser(usage="%prog [options]") - parser.add_option("--nocleanup", dest="nocleanup", default=False, action="store_true", - help="Leave bitcoinds and test.* datadir on exit or error") - parser.add_option("--srcdir", dest="srcdir", default="../../src", - help="Source directory containing bitcoind/bitcoin-cli (default: %default%)") - parser.add_option("--tmpdir", dest="tmpdir", default=tempfile.mkdtemp(prefix="test"), - help="Root directory for datadirs") - (options, args) = parser.parse_args() - - os.environ['PATH'] = options.srcdir+":"+os.environ['PATH'] - - check_json_precision() - - success = False - nodes = [] - try: - print("Initializing test directory "+options.tmpdir) - if not os.path.isdir(options.tmpdir): - os.makedirs(options.tmpdir) - initialize_chain(options.tmpdir) - - run_test(options.tmpdir) - - success = True - - except AssertionError as e: - print("Assertion failed: "+e.message) - except Exception as e: - print("Unexpected exception caught during testing: "+str(e)) - traceback.print_tb(sys.exc_info()[2]) - - if not options.nocleanup: - print("Cleaning up") - wait_bitcoinds() - shutil.rmtree(options.tmpdir) + def setup_nodes(self): + pass - if success: - print("Tests successful") - sys.exit(0) - else: - print("Failed") - sys.exit(1) + def run_bind_test(self, allow_ips, connect_to, addresses, expected): + ''' + Start a node with requested rpcallowip and rpcbind parameters, + then try to connect, and check if the set of bound addresses + matches the expected set. + ''' + expected = [(addr_to_hex(addr), port) for (addr, port) in expected] + base_args = ['-disablewallet', '-nolisten'] + if allow_ips: + base_args += ['-rpcallowip=' + x for x in allow_ips] + binds = ['-rpcbind='+addr for addr in addresses] + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [base_args + binds], connect_to) + try: + pid = bitcoind_processes[0].pid + assert_equal(set(get_bind_addrs(pid)), set(expected)) + finally: + stop_nodes(self.nodes) + wait_bitcoinds() + + def run_allowip_test(self, allow_ips, rpchost, rpcport): + ''' + Start a node with rpcwallow IP, and request getinfo + at a non-localhost IP. + ''' + base_args = ['-disablewallet', '-nolisten'] + ['-rpcallowip='+x for x in allow_ips] + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [base_args]) + try: + # connect to node through non-loopback interface + node = get_rpc_proxy(rpc_url(0, "%s:%d" % (rpchost, rpcport)), 0) + node.getinfo() + finally: + node = None # make sure connection will be garbage collected and closed + stop_nodes(self.nodes) + wait_bitcoinds() + + def run_test(self): + # due to OS-specific network stats queries, this test works only on Linux + assert(sys.platform.startswith('linux')) + # find the first non-loopback interface for testing + non_loopback_ip = None + for name,ip in all_interfaces(): + if ip != '127.0.0.1': + non_loopback_ip = ip + break + if non_loopback_ip is None: + assert(not 'This test requires at least one non-loopback IPv4 interface') + print("Using interface %s for testing" % non_loopback_ip) + + defaultport = rpc_port(0) + + # check default without rpcallowip (IPv4 and IPv6 localhost) + self.run_bind_test(None, '127.0.0.1', [], + [('127.0.0.1', defaultport), ('::1', defaultport)]) + # check default with rpcallowip (IPv6 any) + self.run_bind_test(['127.0.0.1'], '127.0.0.1', [], + [('::0', defaultport)]) + # check only IPv4 localhost (explicit) + self.run_bind_test(['127.0.0.1'], '127.0.0.1', ['127.0.0.1'], + [('127.0.0.1', defaultport)]) + # check only IPv4 localhost (explicit) with alternative port + self.run_bind_test(['127.0.0.1'], '127.0.0.1:32171', ['127.0.0.1:32171'], + [('127.0.0.1', 32171)]) + # check only IPv4 localhost (explicit) with multiple alternative ports on same host + self.run_bind_test(['127.0.0.1'], '127.0.0.1:32171', ['127.0.0.1:32171', '127.0.0.1:32172'], + [('127.0.0.1', 32171), ('127.0.0.1', 32172)]) + # check only IPv6 localhost (explicit) + self.run_bind_test(['[::1]'], '[::1]', ['[::1]'], + [('::1', defaultport)]) + # check both IPv4 and IPv6 localhost (explicit) + self.run_bind_test(['127.0.0.1'], '127.0.0.1', ['127.0.0.1', '[::1]'], + [('127.0.0.1', defaultport), ('::1', defaultport)]) + # check only non-loopback interface + self.run_bind_test([non_loopback_ip], non_loopback_ip, [non_loopback_ip], + [(non_loopback_ip, defaultport)]) + + # Check that with invalid rpcallowip, we are denied + self.run_allowip_test([non_loopback_ip], non_loopback_ip, defaultport) + try: + self.run_allowip_test(['1.1.1.1'], non_loopback_ip, defaultport) + assert(not 'Connection not denied by rpcallowip as expected') + except JSONRPCException: + pass if __name__ == '__main__': - main() + RPCBindTest ().main () From 1de2a46632946990a7863020b61172232f8c5796 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Tue, 26 Jul 2016 16:50:48 -0400 Subject: [PATCH 0651/1802] Ignore GETBLOCKTXN requests for unknown blocks Don't disconnect peers, or else we leak information that could be used for fingerprinting. --- src/main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 052b739326a5a..4675127ec37ac 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5343,7 +5343,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, BlockMap::iterator it = mapBlockIndex.find(req.blockhash); if (it == mapBlockIndex.end() || !(it->second->nStatus & BLOCK_HAVE_DATA)) { - Misbehaving(pfrom->GetId(), 100); LogPrintf("Peer %d sent us a getblocktxn for a block we don't have", pfrom->id); return true; } From 1d06e49834814eed45e07393dcffd7b6683311b2 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Tue, 26 Jul 2016 16:52:35 -0400 Subject: [PATCH 0652/1802] Ignore CMPCTBLOCK messages for pruned blocks Also ignores CMPCTBLOCK announcements that have too little work. This is to prevent disk-exhaustion DoS. --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 4675127ec37ac..b41a719552ec8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5626,8 +5626,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, std::vector vInv(1); vInv[0] = CInv(MSG_BLOCK, cmpctblock.header.GetHash()); pfrom->PushMessage(NetMsgType::GETDATA, vInv); - return true; } + return true; } // If we're not close to tip yet, give up and let parallel block fetch work its magic From 77c912d21c8cd153f4503c65225a5a46990cc85a Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Wed, 15 Jun 2016 10:49:29 +0200 Subject: [PATCH 0653/1802] [Wallet] add HD xpriv to dumpwallet --- src/wallet/rpcdump.cpp | 29 ++++++++++++++++++++++++++--- src/wallet/wallet.h | 2 +- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index d55cc68dc0309..6647d3297fad2 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -602,19 +602,42 @@ UniValue dumpwallet(const UniValue& params, bool fHelp) file << strprintf("# * Best block at time of backup was %i (%s),\n", chainActive.Height(), chainActive.Tip()->GetBlockHash().ToString()); file << strprintf("# mined on %s\n", EncodeDumpTime(chainActive.Tip()->GetBlockTime())); file << "\n"; + + // add the base58check encoded extended master if the wallet uses HD + CKeyID masterKeyID = pwalletMain->GetHDChain().masterKeyID; + if (!masterKeyID.IsNull()) + { + CKey key; + if (pwalletMain->GetKey(masterKeyID, key)) + { + CExtKey masterKey; + masterKey.SetMaster(key.begin(), key.size()); + + CBitcoinExtKey b58extkey; + b58extkey.SetKey(masterKey); + + file << "# extended private masterkey: " << b58extkey.ToString() << "\n\n"; + } + } for (std::vector >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) { const CKeyID &keyid = it->second; std::string strTime = EncodeDumpTime(it->first); std::string strAddr = CBitcoinAddress(keyid).ToString(); CKey key; if (pwalletMain->GetKey(keyid, key)) { + file << strprintf("%s %s ", CBitcoinSecret(key).ToString(), strTime); if (pwalletMain->mapAddressBook.count(keyid)) { - file << strprintf("%s %s label=%s # addr=%s\n", CBitcoinSecret(key).ToString(), strTime, EncodeDumpString(pwalletMain->mapAddressBook[keyid].name), strAddr); + file << strprintf("label=%s", EncodeDumpString(pwalletMain->mapAddressBook[keyid].name)); + } else if (keyid == masterKeyID) { + file << "hdmaster=1"; } else if (setKeyPool.count(keyid)) { - file << strprintf("%s %s reserve=1 # addr=%s\n", CBitcoinSecret(key).ToString(), strTime, strAddr); + file << "reserve=1"; + } else if (pwalletMain->mapKeyMetadata[keyid].hdKeypath == "m") { + file << "inactivehdmaster=1"; } else { - file << strprintf("%s %s change=1 # addr=%s\n", CBitcoinSecret(key).ToString(), strTime, strAddr); + file << "change=1"; } + file << strprintf(" # addr=%s%s\n", strAddr, (pwalletMain->mapKeyMetadata[keyid].hdKeypath.size() > 0 ? " hdkeypath="+pwalletMain->mapKeyMetadata[keyid].hdKeypath : "")); } } file << "\n"; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 3a3cb6d8514c0..efed2ba11df02 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -899,10 +899,10 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface /* Set the HD chain model (chain child index counters) */ bool SetHDChain(const CHDChain& chain, bool memonly); + const CHDChain& GetHDChain() { return hdChain; } /* Set the current HD master key (will reset the chain child index counters) */ bool SetHDMasterKey(const CKey& key); - const CHDChain& GetHDChain() { return hdChain; } }; /** A key allocated from the key pool. */ From c8664eeac75fb87282dc69049cfa23d583742629 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Tim=C3=B3n?= Date: Sun, 17 Jul 2016 05:49:46 +0200 Subject: [PATCH 0654/1802] Trivial: pass Consensus::Params& instead of CChainParams& in ContextualCheckBlock --- src/main.cpp | 8 ++++---- src/main.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 124bc57e7d14e..b7a20c78d59ab 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3525,10 +3525,9 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta return true; } -bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const CBlockIndex* pindexPrev) +bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev) { const int nHeight = pindexPrev == NULL ? 0 : pindexPrev->nHeight + 1; - const Consensus::Params& consensusParams = Params().GetConsensus(); // Start enforcing BIP113 (Median Time Past) using versionbits logic. int nLockTimeFlags = 0; @@ -3689,7 +3688,8 @@ static bool AcceptBlock(const CBlock& block, CValidationState& state, const CCha } if (fNewBlock) *fNewBlock = true; - if ((!CheckBlock(block, state, chainparams.GetConsensus(), GetAdjustedTime())) || !ContextualCheckBlock(block, state, pindex->pprev)) { + if (!CheckBlock(block, state, chainparams.GetConsensus(), GetAdjustedTime()) || + !ContextualCheckBlock(block, state, chainparams.GetConsensus(), pindex->pprev)) { if (state.IsInvalid() && !state.CorruptionPossible()) { pindex->nStatus |= BLOCK_FAILED_VALID; setDirtyBlockIndex.insert(pindex); @@ -3780,7 +3780,7 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, return error("%s: Consensus::ContextualCheckBlockHeader: %s", __func__, FormatStateMessage(state)); if (!CheckBlock(block, state, chainparams.GetConsensus(), fCheckPOW, fCheckMerkleRoot)) return error("%s: Consensus::CheckBlock: %s", __func__, FormatStateMessage(state)); - if (!ContextualCheckBlock(block, state, pindexPrev)) + if (!ContextualCheckBlock(block, state, chainparams.GetConsensus(), pindexPrev)) return error("%s: Consensus::ContextualCheckBlock: %s", __func__, FormatStateMessage(state)); if (!ConnectBlock(block, state, &indexDummy, viewNew, chainparams, true)) return false; diff --git a/src/main.h b/src/main.h index feaaaad750b1c..262e94b9f8f52 100644 --- a/src/main.h +++ b/src/main.h @@ -448,7 +448,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P * By "context", we mean only the previous block headers, but not the UTXO * set; UTXO-related validity checks are done in ConnectBlock(). */ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev, int64_t nAdjustedTime); -bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const CBlockIndex* pindexPrev); +bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev); /** Apply the effects of this block (with given index) on the UTXO set represented by coins. * Validity checks that depend on the UTXO set are also done; ConnectBlock() From d12b732ac287a1ed7543481b79801c9afc333b7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Tim=C3=B3n?= Date: Wed, 27 Jul 2016 22:42:13 +0200 Subject: [PATCH 0655/1802] libconsensus: Expose a flag for BIP112 We added the segwit one, but we forgot CHECKSEQUENCEVERIFY --- src/script/bitcoinconsensus.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/script/bitcoinconsensus.h b/src/script/bitcoinconsensus.h index 6f868d0d6d6ab..f73a8e30bc6c4 100644 --- a/src/script/bitcoinconsensus.h +++ b/src/script/bitcoinconsensus.h @@ -51,6 +51,7 @@ enum bitcoinconsensus_SCRIPT_FLAGS_VERIFY_P2SH = (1U << 0), // evaluate P2SH (BIP16) subscripts bitcoinconsensus_SCRIPT_FLAGS_VERIFY_DERSIG = (1U << 2), // enforce strict DER (BIP66) compliance bitcoinconsensus_SCRIPT_FLAGS_VERIFY_CHECKLOCKTIMEVERIFY = (1U << 9), // enable CHECKLOCKTIMEVERIFY (BIP65) + bitcoinconsensus_SCRIPT_FLAGS_VERIFY_CHECKSEQUENCEVERIFY = (1U << 10), // enable CHECKSEQUENCEVERIFY (BIP112) bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS = (1U << 11), // enable WITNESS (BIP141) }; From d3af342276f29d2bd162628eb4b669599633e39e Mon Sep 17 00:00:00 2001 From: Kaz Wesley Date: Wed, 27 Jul 2016 16:27:07 -0700 Subject: [PATCH 0656/1802] prepend license statement to indirectmap Add statement about MIT licensing to indirectmap.h. I forgot the license preamble when I originally wrote the file. --- src/indirectmap.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/indirectmap.h b/src/indirectmap.h index 28e1e8deddbde..76da4a6bd5575 100644 --- a/src/indirectmap.h +++ b/src/indirectmap.h @@ -1,3 +1,7 @@ +// Copyright (c) 2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + #ifndef BITCOIN_INDIRECTMAP_H #define BITCOIN_INDIRECTMAP_H From 893f379ba0befef5301208b6bee8206ac4e76329 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 26 Jul 2016 14:01:36 +0200 Subject: [PATCH 0657/1802] [Qt] Add dbcache migration path --- src/qt/optionsmodel.cpp | 21 +++++++++++++++++++++ src/qt/optionsmodel.h | 4 +++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index cc2cbc0e66419..684db71a8ce03 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -43,6 +43,8 @@ void OptionsModel::Init(bool resetSettings) if (resetSettings) Reset(); + checkAndMigrate(); + QSettings settings; // Ensure restart flag is unset on client startup @@ -429,3 +431,22 @@ bool OptionsModel::isRestartRequired() QSettings settings; return settings.value("fRestartRequired", false).toBool(); } + +void OptionsModel::checkAndMigrate() +{ + // Migration of default values + // Check if the QSettings container was already loaded with this client version + QSettings settings; + static const char strSettingsVersionKey[] = "nSettingsVersion"; + int settingsVersion = settings.contains(strSettingsVersionKey) ? settings.value(strSettingsVersionKey).toInt() : 0; + if (settingsVersion < CLIENT_VERSION) + { + // -dbcache was bumped from 100 to 300 in 0.13 + // see https://github.com/bitcoin/bitcoin/pull/8273 + // force people to upgrade to the new value if they are using 100MB + if (settingsVersion < 130000 && settings.contains("nDatabaseCache") && settings.value("nDatabaseCache").toLongLong() == 100) + settings.setValue("nDatabaseCache", (qint64)nDefaultDbCache); + + settings.setValue(strSettingsVersionKey, CLIENT_VERSION); + } +} \ No newline at end of file diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index 3b491ceac2cde..b23b5f2607a6c 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -84,9 +84,11 @@ class OptionsModel : public QAbstractListModel /* settings that were overriden by command-line */ QString strOverriddenByCommandLine; - /// Add option to list of GUI options overridden through command line/config file + // Add option to list of GUI options overridden through command line/config file void addOverriddenOption(const std::string &option); + // Check settings version and upgrade default values if required + void checkAndMigrate(); Q_SIGNALS: void displayUnitChanged(int unit); void coinControlFeaturesChanged(bool); From 2266b43e3317a889b9150e614169acda50383bf5 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 21 Jul 2016 21:19:02 +0200 Subject: [PATCH 0658/1802] Port from 0.13: Create a new HD seed after encrypting the wallet Forward-ports two commits from 0.13: - [0.13] Create a new HD seed after encrypting the wallet - [Wallet] Add CKeyMetadata record for HDMasterKey(s), factor out HD key generation Github-Pull: #8389 Rebased-From: f142c11ac634df487cc4bc65a5f1c9a3e3563dd9 de45c065f0648c4c41b57cb492420ceeed29dd11 --- qa/rpc-tests/keypool.py | 10 ++++++++ src/wallet/rpcwallet.cpp | 2 +- src/wallet/wallet.cpp | 52 ++++++++++++++++++++++++++++++++-------- src/wallet/wallet.h | 5 +++- 4 files changed, 57 insertions(+), 12 deletions(-) diff --git a/qa/rpc-tests/keypool.py b/qa/rpc-tests/keypool.py index c75303ecbfc31..fa3947656809c 100755 --- a/qa/rpc-tests/keypool.py +++ b/qa/rpc-tests/keypool.py @@ -12,6 +12,11 @@ class KeyPoolTest(BitcoinTestFramework): def run_test(self): nodes = self.nodes + addr_before_encrypting = nodes[0].getnewaddress() + addr_before_encrypting_data = nodes[0].validateaddress(addr_before_encrypting) + wallet_info_old = nodes[0].getwalletinfo() + assert(addr_before_encrypting_data['hdmasterkeyid'] == wallet_info_old['hdmasterkeyid']) + # Encrypt wallet and wait to terminate nodes[0].encryptwallet('test') bitcoind_processes[0].wait() @@ -19,6 +24,11 @@ def run_test(self): nodes[0] = start_node(0, self.options.tmpdir) # Keep creating keys addr = nodes[0].getnewaddress() + addr_data = nodes[0].validateaddress(addr) + wallet_info = nodes[0].getwalletinfo() + assert(addr_before_encrypting_data['hdmasterkeyid'] != wallet_info['hdmasterkeyid']) + assert(addr_data['hdmasterkeyid'] == wallet_info['hdmasterkeyid']) + try: addr = nodes[0].getnewaddress() raise AssertionError('Keypool should be exhausted after one address') diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 4087b8e77b7a2..a90807e5141b7 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2081,7 +2081,7 @@ UniValue encryptwallet(const UniValue& params, bool fHelp) // slack space in .dat files; that is bad if the old data is // unencrypted private keys. So: StartShutdown(); - return "wallet encrypted; Bitcoin server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup."; + return "wallet encrypted; Bitcoin server stopping, restart to run with encrypted wallet. The keypool has been flushed and a new HD seed was generated (if you are using HD). You need to make a new backup."; } UniValue lockunspent(const UniValue& params, bool fHelp) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 5908dfeaceae6..e5ee5063a5d31 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -626,6 +626,15 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) Lock(); Unlock(strWalletPassphrase); + + // if we are using HD, replace the HD master key (seed) with a new one + if (!hdChain.masterKeyID.IsNull()) { + CKey key; + CPubKey masterPubKey = GenerateNewHDMasterKey(); + if (!SetHDMasterKey(masterPubKey)) + return false; + } + NewKeyPool(); Lock(); @@ -1166,20 +1175,43 @@ CAmount CWallet::GetChange(const CTransaction& tx) const return nChange; } -bool CWallet::SetHDMasterKey(const CKey& key) +CPubKey CWallet::GenerateNewHDMasterKey() +{ + CKey key; + key.MakeNewKey(true); + + int64_t nCreationTime = GetTime(); + CKeyMetadata metadata(nCreationTime); + + // calculate the pubkey + CPubKey pubkey = key.GetPubKey(); + assert(key.VerifyPubKey(pubkey)); + + // set the hd keypath to "m" -> Master, refers the masterkeyid to itself + metadata.hdKeypath = "m"; + metadata.hdMasterKeyID = pubkey.GetID(); + + { + LOCK(cs_wallet); + + // mem store the metadata + mapKeyMetadata[pubkey.GetID()] = metadata; + + // write the key&metadata to the database + if (!AddKeyPubKey(key, pubkey)) + throw std::runtime_error("CWallet::GenerateNewKey(): AddKey failed"); + } + + return pubkey; +} + +bool CWallet::SetHDMasterKey(const CPubKey& pubkey) { LOCK(cs_wallet); // ensure this wallet.dat can only be opened by clients supporting HD SetMinVersion(FEATURE_HD); - // store the key as normal "key"/"ckey" object - // in the database - // key metadata is not required - CPubKey pubkey = key.GetPubKey(); - if (!AddKeyPubKey(key, pubkey)) - throw std::runtime_error("CWallet::GenerateNewKey(): AddKey failed"); - // store the keyid (hash160) together with // the child index counter in the database // as a hdchain object @@ -3299,8 +3331,8 @@ bool CWallet::InitLoadWallet() if (GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET) && walletInstance->hdChain.masterKeyID.IsNull()) { // generate a new master key CKey key; - key.MakeNewKey(true); - if (!walletInstance->SetHDMasterKey(key)) + CPubKey masterPubKey = walletInstance->GenerateNewHDMasterKey(); + if (!walletInstance->SetHDMasterKey(masterPubKey)) throw std::runtime_error("CWallet::GenerateNewKey(): Storing master key failed"); } CPubKey newDefaultKey; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index efed2ba11df02..0c95fdf4b04d8 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -901,8 +901,11 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface bool SetHDChain(const CHDChain& chain, bool memonly); const CHDChain& GetHDChain() { return hdChain; } + /* Generates a new HD master key (will not be activated) */ + CPubKey GenerateNewHDMasterKey(); + /* Set the current HD master key (will reset the chain child index counters) */ - bool SetHDMasterKey(const CKey& key); + bool SetHDMasterKey(const CPubKey& key); }; /** A key allocated from the key pool. */ From 54af51d98d0b38f08c58dd589bff81883aee2854 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 28 Jul 2016 14:59:13 +0200 Subject: [PATCH 0659/1802] [QA] Add walletdump RPC test (including HD- & encryption-tests) --- qa/pull-tester/rpc-tests.py | 1 + qa/rpc-tests/wallet-dump.py | 120 ++++++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100755 qa/rpc-tests/wallet-dump.py diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index 11b83bac1468d..5900fa51e34b4 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -107,6 +107,7 @@ 'bip68-112-113-p2p.py', 'wallet.py', 'wallet-hd.py', + 'wallet-dump.py', 'listtransactions.py', 'receivedby.py', 'mempool_resurrect_test.py', diff --git a/qa/rpc-tests/wallet-dump.py b/qa/rpc-tests/wallet-dump.py new file mode 100755 index 0000000000000..dd675f57fc46a --- /dev/null +++ b/qa/rpc-tests/wallet-dump.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +# Copyright (c) 2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * +import os +import shutil + + +class WalletDumpTest(BitcoinTestFramework): + + def __init__(self): + super().__init__() + self.setup_clean_chain = False + self.num_nodes = 1 + + def setup_network(self, split=False): + extra_args = [["-keypool=100"]] + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args) + + def run_test (self): + tmpdir = self.options.tmpdir + + #generate 20 addresses to compare against the dump + test_addr_count = 20 + addrs = [] + for i in range(0,test_addr_count): + addr = self.nodes[0].getnewaddress() + vaddr= self.nodes[0].validateaddress(addr) #required to get hd keypath + addrs.append(vaddr) + + # dump unencrypted wallet + self.nodes[0].dumpwallet(tmpdir + "/node0/wallet.unencrypted.dump") + + #open file + inputfile = open(tmpdir + "/node0/wallet.unencrypted.dump") + found_addr = 0 + found_addr_chg = 0 + found_addr_rsv = 0 + hdmasteraddr = "" + for line in inputfile: + #only read non comment lines + if line[0] != "#" and len(line) > 10: + #split out some data + keyLabel, comment = line.split("#") + key = keyLabel.split(" ")[0] + keytype = keyLabel.split(" ")[2] + if len(comment) > 1: + addrKeypath = comment.split(" addr=")[1] + addr = addrKeypath.split(" ")[0] + keypath = "" + if keytype != "hdmaster=1": + keypath = addrKeypath.rstrip().split("hdkeypath=")[1] + else: + #keep hd master for later comp. + hdmasteraddr = addr + + #count key types + for addrObj in addrs: + if (addrObj['address'] == addr and addrObj['hdkeypath'] == keypath and keytype == "label="): + found_addr+=1 + break + elif (keytype == "change=1"): + found_addr_chg+=1 + break + elif (keytype == "reserve=1"): + found_addr_rsv+=1 + break + assert(found_addr == test_addr_count) #all keys must be in the dump + assert(found_addr_chg == 50) #50 blocks where mined + assert(found_addr_rsv == 100) #100 reserve keys (keypool) + + #encrypt wallet, restart, unlock and dump + self.nodes[0].encryptwallet('test') + bitcoind_processes[0].wait() + self.nodes[0] = start_node(0, self.options.tmpdir) + self.nodes[0].walletpassphrase('test', 10) + self.nodes[0].dumpwallet(tmpdir + "/node0/wallet.encrypted.dump") + + #open dump done with an encrypted wallet + inputfile = open(tmpdir + "/node0/wallet.encrypted.dump") + found_addr = 0 + found_addr_chg = 0 + found_addr_rsv = 0 + for line in inputfile: + if line[0] != "#" and len(line) > 10: + keyLabel, comment = line.split("#") + key = keyLabel.split(" ")[0] + keytype = keyLabel.split(" ")[2] + if len(comment) > 1: + addrKeypath = comment.split(" addr=")[1] + addr = addrKeypath.split(" ")[0] + keypath = "" + if keytype != "hdmaster=1": + keypath = addrKeypath.rstrip().split("hdkeypath=")[1] + else: + #ensure we have generated a new hd master key + assert(hdmasteraddr != addr) + if keytype == "inactivehdmaster=1": + #ensure the old master is still available + assert(hdmasteraddr == addr) + for addrObj in addrs: + if (addrObj['address'] == addr and addrObj['hdkeypath'] == keypath and keytype == "label="): + found_addr+=1 + break + elif (keytype == "change=1"): + found_addr_chg+=1 + break + elif (keytype == "reserve=1"): + found_addr_rsv+=1 + break + + assert(found_addr == test_addr_count) + assert(found_addr_chg == 150) #old reserve keys are marked as change now + assert(found_addr_rsv == 100) #keypool size + +if __name__ == '__main__': + WalletDumpTest().main () From 8bfd70817bf8b8b07b81660e47c88dd122b7423f Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Thu, 28 Jul 2016 14:27:19 -0400 Subject: [PATCH 0660/1802] Enable size accounting in mining unit tests --- src/test/miner_tests.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index fd581db52ea28..15fceb963a59f 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -181,9 +181,7 @@ void TestPackageSelection(const CChainParams& chainparams, CScript scriptPubKey, // NOTE: These tests rely on CreateNewBlock doing its own self-validation! BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) { - // Disable size accounting (CPFP does not support it) - mapArgs["-blockmaxsize"] = strprintf("%u", MAX_BLOCK_SERIALIZED_SIZE); - + // Note that by default, these tests run with size accounting enabled. const CChainParams& chainparams = Params(CBaseChainParams::MAIN); CScript scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG; CBlockTemplate *pblocktemplate; From a6cc299541fc9df5af010ce63eb1dd34d8c4b6e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Tim=C3=B3n?= Date: Sat, 16 Jul 2016 20:57:42 +0200 Subject: [PATCH 0661/1802] Mempool: Use Consensus::CheckTxInputs direclty over main::CheckInputs --- src/main.h | 13 +++++++++++++ src/txmempool.cpp | 9 +++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/main.h b/src/main.h index 7ea570d859792..b60bb05e187f6 100644 --- a/src/main.h +++ b/src/main.h @@ -351,9 +351,22 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi /** Apply the effects of this transaction on the UTXO set represented by view */ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight); +/** Transaction validation functions */ + /** Context-independent validity checks */ bool CheckTransaction(const CTransaction& tx, CValidationState& state); +namespace Consensus { + +/** + * Check whether all inputs of this transaction are valid (no double spends and amounts) + * This does not modify the UTXO set. This does not check scripts and sigs. + * Preconditions: tx.IsCoinBase() is false. + */ +bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight); + +} // namespace Consensus + /** * Check if transaction is final and can be included in a block with the * specified height and time. Consensus critical. diff --git a/src/txmempool.cpp b/src/txmempool.cpp index a48a6d94659b5..b30022bd66714 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -657,6 +657,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const uint64_t innerUsage = 0; CCoinsViewCache mempoolDuplicate(const_cast(pcoins)); + const int64_t nSpendHeight = GetSpendHeight(mempoolDuplicate); LOCK(cs); list waitingOnDependants; @@ -737,7 +738,9 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const waitingOnDependants.push_back(&(*it)); else { CValidationState state; - assert(CheckInputs(tx, state, mempoolDuplicate, false, 0, false, NULL)); + bool fCheckResult = tx.IsCoinBase() || + Consensus::CheckTxInputs(tx, state, mempoolDuplicate, nSpendHeight); + assert(fCheckResult); UpdateCoins(tx, mempoolDuplicate, 1000000); } } @@ -751,7 +754,9 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const stepsSinceLastRemove++; assert(stepsSinceLastRemove < waitingOnDependants.size()); } else { - assert(CheckInputs(entry->GetTx(), state, mempoolDuplicate, false, 0, false, NULL)); + bool fCheckResult = entry->GetTx().IsCoinBase() || + Consensus::CheckTxInputs(entry->GetTx(), state, mempoolDuplicate, nSpendHeight); + assert(fCheckResult); UpdateCoins(entry->GetTx(), mempoolDuplicate, 1000000); stepsSinceLastRemove = 0; } From 755aa05174e06effd758eeb78c5af9fb465e9611 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 28 Jul 2016 17:52:51 -0400 Subject: [PATCH 0662/1802] httpserver: use a future rather than relying on boost's try_join_for --- src/httpserver.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/httpserver.cpp b/src/httpserver.cpp index 812940eaf9861..7150f96ed7f46 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -302,13 +303,14 @@ static void http_reject_request_cb(struct evhttp_request* req, void*) } /** Event dispatcher thread */ -static void ThreadHTTP(struct event_base* base, struct evhttp* http) +static bool ThreadHTTP(struct event_base* base, struct evhttp* http) { RenameThread("bitcoin-http"); LogPrint("http", "Entering http event loop\n"); event_base_dispatch(base); // Event loop will be interrupted by InterruptHTTPServer() LogPrint("http", "Exited http event loop\n"); + return event_base_got_break(base) == 0; } /** Bind HTTP server to specified addresses */ @@ -438,13 +440,16 @@ bool InitHTTPServer() } boost::thread threadHTTP; +std::future threadResult; bool StartHTTPServer() { LogPrint("http", "Starting HTTP server\n"); int rpcThreads = std::max((long)GetArg("-rpcthreads", DEFAULT_HTTP_THREADS), 1L); LogPrintf("HTTP: starting %d worker threads\n", rpcThreads); - threadHTTP = boost::thread(boost::bind(&ThreadHTTP, eventBase, eventHTTP)); + std::packaged_task task(ThreadHTTP); + threadResult = task.get_future(); + threadHTTP = boost::thread(std::bind(std::move(task), eventBase, eventHTTP)); for (int i = 0; i < rpcThreads; i++) boost::thread(boost::bind(&HTTPWorkQueueRun, workQueue)); @@ -482,15 +487,11 @@ void StopHTTPServer() // master that appears to be solved, so in the future that solution // could be used again (if desirable). // (see discussion in https://github.com/bitcoin/bitcoin/pull/6990) -#if BOOST_VERSION >= 105000 - if (!threadHTTP.try_join_for(boost::chrono::milliseconds(2000))) { -#else - if (!threadHTTP.timed_join(boost::posix_time::milliseconds(2000))) { -#endif + if (threadResult.valid() && threadResult.wait_for(std::chrono::milliseconds(2000)) == std::future_status::timeout) { LogPrintf("HTTP event loop did not exit within allotted time, sending loopbreak\n"); event_base_loopbreak(eventBase); - threadHTTP.join(); } + threadHTTP.join(); } if (eventHTTP) { evhttp_free(eventHTTP); From d3773ca9aeb0d2f12dc0c5a0726778050c8cb455 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 28 Jul 2016 18:21:00 -0400 Subject: [PATCH 0663/1802] httpserver: explicitly detach worker threads When using std::thread in place of boost::thread, letting the threads destruct results in a std::terminate. According to the docs, the same thing should be be happening in later boost versions: http://www.boost.org/doc/libs/1_55_0/doc/html/thread/thread_management.html#thread.thread_management.thread.destructor I'm unsure why this hasn't blown up already, but explicitly detaching can't hurt. --- src/httpserver.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/httpserver.cpp b/src/httpserver.cpp index 7150f96ed7f46..8d0d3c1584662 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -451,8 +451,10 @@ bool StartHTTPServer() threadResult = task.get_future(); threadHTTP = boost::thread(std::bind(std::move(task), eventBase, eventHTTP)); - for (int i = 0; i < rpcThreads; i++) - boost::thread(boost::bind(&HTTPWorkQueueRun, workQueue)); + for (int i = 0; i < rpcThreads; i++) { + boost::thread rpc_worker(HTTPWorkQueueRun, workQueue); + rpc_worker.detach(); + } return true; } From 7e87033447149e54d9b5ab2f90ad3a7ed094d784 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 28 Jul 2016 18:31:25 -0400 Subject: [PATCH 0664/1802] httpserver: replace boost threads with std along with mutex/condvar/bind/etc. httpserver handles its own interruption, so there's no reason not to use std threading. While we're at it, may as well kill the BOOST_FOREACH's as well. --- src/httpserver.cpp | 39 ++++++++++++++++++--------------------- src/httpserver.h | 10 ++++------ 2 files changed, 22 insertions(+), 27 deletions(-) diff --git a/src/httpserver.cpp b/src/httpserver.cpp index 8d0d3c1584662..be7a6a1ddee86 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -35,9 +35,6 @@ #endif #endif -#include // for to_lower() -#include - /** Maximum size of http request (request line + headers) */ static const size_t MAX_HEADERS_SIZE = 8192; @@ -69,8 +66,8 @@ class WorkQueue { private: /** Mutex protects entire object */ - CWaitableCriticalSection cs; - CConditionVariable cond; + std::mutex cs; + std::condition_variable cond; std::deque> queue; bool running; size_t maxDepth; @@ -83,12 +80,12 @@ class WorkQueue WorkQueue &wq; ThreadCounter(WorkQueue &w): wq(w) { - boost::lock_guard lock(wq.cs); + std::lock_guard lock(wq.cs); wq.numThreads += 1; } ~ThreadCounter() { - boost::lock_guard lock(wq.cs); + std::lock_guard lock(wq.cs); wq.numThreads -= 1; wq.cond.notify_all(); } @@ -109,7 +106,7 @@ class WorkQueue /** Enqueue a work item */ bool Enqueue(WorkItem* item) { - boost::unique_lock lock(cs); + std::unique_lock lock(cs); if (queue.size() >= maxDepth) { return false; } @@ -124,7 +121,7 @@ class WorkQueue while (running) { std::unique_ptr i; { - boost::unique_lock lock(cs); + std::unique_lock lock(cs); while (running && queue.empty()) cond.wait(lock); if (!running) @@ -138,14 +135,14 @@ class WorkQueue /** Interrupt and exit loops */ void Interrupt() { - boost::unique_lock lock(cs); + std::unique_lock lock(cs); running = false; cond.notify_all(); } /** Wait for worker threads to exit */ void WaitExit() { - boost::unique_lock lock(cs); + std::unique_lock lock(cs); while (numThreads > 0) cond.wait(lock); } @@ -153,7 +150,7 @@ class WorkQueue /** Return current depth of queue */ size_t Depth() { - boost::unique_lock lock(cs); + std::unique_lock lock(cs); return queue.size(); } }; @@ -190,7 +187,7 @@ static bool ClientAllowed(const CNetAddr& netaddr) { if (!netaddr.IsValid()) return false; - BOOST_FOREACH (const CSubNet& subnet, rpc_allow_subnets) + for(const CSubNet& subnet : rpc_allow_subnets) if (subnet.Match(netaddr)) return true; return false; @@ -204,7 +201,7 @@ static bool InitHTTPAllowList() rpc_allow_subnets.push_back(CSubNet("::1")); // always allow IPv6 localhost if (mapMultiArgs.count("-rpcallowip")) { const std::vector& vAllow = mapMultiArgs["-rpcallowip"]; - BOOST_FOREACH (std::string strAllow, vAllow) { + for (std::string strAllow : vAllow) { CSubNet subnet(strAllow); if (!subnet.IsValid()) { uiInterface.ThreadSafeMessageBox( @@ -216,7 +213,7 @@ static bool InitHTTPAllowList() } } std::string strAllowed; - BOOST_FOREACH (const CSubNet& subnet, rpc_allow_subnets) + for (const CSubNet& subnet : rpc_allow_subnets) strAllowed += subnet.ToString() + " "; LogPrint("http", "Allowing HTTP connections from: %s\n", strAllowed); return true; @@ -439,7 +436,7 @@ bool InitHTTPServer() return true; } -boost::thread threadHTTP; +std::thread threadHTTP; std::future threadResult; bool StartHTTPServer() @@ -449,10 +446,10 @@ bool StartHTTPServer() LogPrintf("HTTP: starting %d worker threads\n", rpcThreads); std::packaged_task task(ThreadHTTP); threadResult = task.get_future(); - threadHTTP = boost::thread(std::bind(std::move(task), eventBase, eventHTTP)); + threadHTTP = std::thread(std::move(task), eventBase, eventHTTP); for (int i = 0; i < rpcThreads; i++) { - boost::thread rpc_worker(HTTPWorkQueueRun, workQueue); + std::thread rpc_worker(HTTPWorkQueueRun, workQueue); rpc_worker.detach(); } return true; @@ -463,7 +460,7 @@ void InterruptHTTPServer() LogPrint("http", "Interrupting HTTP server\n"); if (eventHTTP) { // Unlisten sockets - BOOST_FOREACH (evhttp_bound_socket *socket, boundSockets) { + for (evhttp_bound_socket *socket : boundSockets) { evhttp_del_accept_socket(eventHTTP, socket); } // Reject requests on current connections @@ -520,7 +517,7 @@ static void httpevent_callback_fn(evutil_socket_t, short, void* data) delete self; } -HTTPEvent::HTTPEvent(struct event_base* base, bool deleteWhenTriggered, const boost::function& handler): +HTTPEvent::HTTPEvent(struct event_base* base, bool deleteWhenTriggered, const std::function& handler): deleteWhenTriggered(deleteWhenTriggered), handler(handler) { ev = event_new(base, -1, 0, httpevent_callback_fn, this); @@ -602,7 +599,7 @@ void HTTPRequest::WriteReply(int nStatus, const std::string& strReply) assert(evb); evbuffer_add(evb, strReply.data(), strReply.size()); HTTPEvent* ev = new HTTPEvent(eventBase, true, - boost::bind(evhttp_send_reply, req, nStatus, (const char*)NULL, (struct evbuffer *)NULL)); + std::bind(evhttp_send_reply, req, nStatus, (const char*)NULL, (struct evbuffer *)NULL)); ev->trigger(0); replySent = true; req = 0; // transferred back to main thread diff --git a/src/httpserver.h b/src/httpserver.h index 20a119cc5c9ca..0e30e666a6b42 100644 --- a/src/httpserver.h +++ b/src/httpserver.h @@ -7,9 +7,7 @@ #include #include -#include -#include -#include +#include static const int DEFAULT_HTTP_THREADS=4; static const int DEFAULT_HTTP_WORKQUEUE=16; @@ -35,7 +33,7 @@ void InterruptHTTPServer(); void StopHTTPServer(); /** Handler for requests to a certain HTTP path */ -typedef boost::function HTTPRequestHandler; +typedef std::function HTTPRequestHandler; /** Register handler for prefix. * If multiple handlers match a prefix, the first-registered one will * be invoked. @@ -132,7 +130,7 @@ class HTTPEvent * deleteWhenTriggered deletes this event object after the event is triggered (and the handler called) * handler is the handler to call when the event is triggered. */ - HTTPEvent(struct event_base* base, bool deleteWhenTriggered, const boost::function& handler); + HTTPEvent(struct event_base* base, bool deleteWhenTriggered, const std::function& handler); ~HTTPEvent(); /** Trigger the event. If tv is 0, trigger it immediately. Otherwise trigger it after @@ -141,7 +139,7 @@ class HTTPEvent void trigger(struct timeval* tv); bool deleteWhenTriggered; - boost::function handler; + std::function handler; private: struct event* ev; }; From 56c87e92110f05d7452f1e85bf755246ffc77206 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Mon, 25 Jul 2016 17:22:37 -0400 Subject: [PATCH 0665/1802] Allow changing BIP9 parameters on regtest --- src/chainparams.cpp | 11 +++++++++++ src/chainparams.h | 5 +++++ src/init.cpp | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 86bef1e105006..d6032440e3bb2 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -303,6 +303,12 @@ class CRegTestParams : public CChainParams { base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x35)(0x87)(0xCF).convert_to_container >(); base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x35)(0x83)(0x94).convert_to_container >(); } + + void UpdateBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout) + { + consensus.vDeployments[d].nStartTime = nStartTime; + consensus.vDeployments[d].nTimeout = nTimeout; + } }; static CRegTestParams regTestParams; @@ -330,4 +336,9 @@ void SelectParams(const std::string& network) SelectBaseParams(network); pCurrentParams = &Params(network); } + +void UpdateRegtestBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout) +{ + regTestParams.UpdateBIP9Parameters(d, nStartTime, nTimeout); +} diff --git a/src/chainparams.h b/src/chainparams.h index 638893e9ad9b4..0c3820b7c6e72 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -112,4 +112,9 @@ CChainParams& Params(const std::string& chain); */ void SelectParams(const std::string& chain); +/** + * Allows modifying the BIP9 regtest parameters. + */ +void UpdateRegtestBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout); + #endif // BITCOIN_CHAINPARAMS_H diff --git a/src/init.cpp b/src/init.cpp index 8d4a2cafbfbb1..5dc3ac023ccf8 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -410,6 +410,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-limitancestorsize=", strprintf("Do not accept transactions whose size with all in-mempool ancestors exceeds kilobytes (default: %u)", DEFAULT_ANCESTOR_SIZE_LIMIT)); strUsage += HelpMessageOpt("-limitdescendantcount=", strprintf("Do not accept transactions if any ancestor would have or more in-mempool descendants (default: %u)", DEFAULT_DESCENDANT_LIMIT)); strUsage += HelpMessageOpt("-limitdescendantsize=", strprintf("Do not accept transactions if any ancestor would have more than kilobytes of in-mempool descendants (default: %u).", DEFAULT_DESCENDANT_SIZE_LIMIT)); + strUsage += HelpMessageOpt("-bip9params=deployment:start:end", "Use given start/end times for specified bip9 deployment (regtest-only)"); } string debugCategories = "addrman, alert, bench, coindb, db, http, libevent, lock, mempool, mempoolrej, net, proxy, prune, rand, reindex, rpc, selectcoins, tor, zmq"; // Don't translate these and qt below if (mode == HMM_BITCOIN_QT) @@ -975,6 +976,41 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) fEnableReplacement = (std::find(vstrReplacementModes.begin(), vstrReplacementModes.end(), "fee") != vstrReplacementModes.end()); } + if (!mapMultiArgs["-bip9params"].empty()) { + // Allow overriding bip9 parameters for testing + if (!Params().MineBlocksOnDemand()) { + return InitError("BIP9 parameters may only be overridden on regtest."); + } + const vector& deployments = mapMultiArgs["-bip9params"]; + for (auto i : deployments) { + std::vector vDeploymentParams; + boost::split(vDeploymentParams, i, boost::is_any_of(":")); + if (vDeploymentParams.size() != 3) { + return InitError("BIP9 parameters malformed, expecting deployment:start:end"); + } + int64_t nStartTime, nTimeout; + if (!ParseInt64(vDeploymentParams[1], &nStartTime)) { + return InitError(strprintf("Invalid nStartTime (%s)", vDeploymentParams[1])); + } + if (!ParseInt64(vDeploymentParams[2], &nTimeout)) { + return InitError(strprintf("Invalid nTimeout (%s)", vDeploymentParams[2])); + } + bool found = false; + for (int i=0; i<(int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++i) + { + if (vDeploymentParams[0].compare(VersionBitsDeploymentInfo[i].name) == 0) { + UpdateRegtestBIP9Parameters(Consensus::DeploymentPos(i), nStartTime, nTimeout); + found = true; + LogPrintf("Setting BIP9 activation parameters for %s to start=%ld, timeout=%ld\n", vDeploymentParams[0], nStartTime, nTimeout); + break; + } + } + if (!found) { + return InitError(strprintf("Invalid deployment (%s)", vDeploymentParams[0])); + } + } + } + // ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log // Initialize elliptic curve code From 9c8593d2b4e25ef628172ceadbedf0ef078d01ef Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 27 Jun 2016 16:06:17 +0200 Subject: [PATCH 0666/1802] Implement SipHash in Python --- qa/rpc-tests/test_framework/siphash.py | 64 ++++++++++++++++++++++++++ src/test/hash_tests.cpp | 4 ++ 2 files changed, 68 insertions(+) create mode 100644 qa/rpc-tests/test_framework/siphash.py diff --git a/qa/rpc-tests/test_framework/siphash.py b/qa/rpc-tests/test_framework/siphash.py new file mode 100644 index 0000000000000..9c0574bd93175 --- /dev/null +++ b/qa/rpc-tests/test_framework/siphash.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +# Copyright (c) 2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# +# siphash.py - Specialized SipHash-2-4 implementations +# +# This implements SipHash-2-4 for 256-bit integers. + +def rotl64(n, b): + return n >> (64 - b) | (n & ((1 << (64 - b)) - 1)) << b + +def siphash_round(v0, v1, v2, v3): + v0 = (v0 + v1) & ((1 << 64) - 1) + v1 = rotl64(v1, 13) + v1 ^= v0 + v0 = rotl64(v0, 32) + v2 = (v2 + v3) & ((1 << 64) - 1) + v3 = rotl64(v3, 16) + v3 ^= v2 + v0 = (v0 + v3) & ((1 << 64) - 1) + v3 = rotl64(v3, 21) + v3 ^= v0 + v2 = (v2 + v1) & ((1 << 64) - 1) + v1 = rotl64(v1, 17) + v1 ^= v2 + v2 = rotl64(v2, 32) + return (v0, v1, v2, v3) + +def siphash256(k0, k1, h): + n0 = h & ((1 << 64) - 1) + n1 = (h >> 64) & ((1 << 64) - 1) + n2 = (h >> 128) & ((1 << 64) - 1) + n3 = (h >> 192) & ((1 << 64) - 1) + v0 = 0x736f6d6570736575 ^ k0 + v1 = 0x646f72616e646f6d ^ k1 + v2 = 0x6c7967656e657261 ^ k0 + v3 = 0x7465646279746573 ^ k1 ^ n0 + v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3) + v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3) + v0 ^= n0 + v3 ^= n1 + v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3) + v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3) + v0 ^= n1 + v3 ^= n2 + v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3) + v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3) + v0 ^= n2 + v3 ^= n3 + v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3) + v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3) + v0 ^= n3 + v3 ^= 0x2000000000000000 + v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3) + v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3) + v0 ^= 0x2000000000000000 + v2 ^= 0xFF + v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3) + v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3) + v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3) + v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3) + return v0 ^ v1 ^ v2 ^ v3 diff --git a/src/test/hash_tests.cpp b/src/test/hash_tests.cpp index 82d61209b5e50..fa9624f13daf5 100644 --- a/src/test/hash_tests.cpp +++ b/src/test/hash_tests.cpp @@ -122,6 +122,10 @@ BOOST_AUTO_TEST_CASE(siphash) hasher3.Write(uint64_t(x)|(uint64_t(x+1)<<8)|(uint64_t(x+2)<<16)|(uint64_t(x+3)<<24)| (uint64_t(x+4)<<32)|(uint64_t(x+5)<<40)|(uint64_t(x+6)<<48)|(uint64_t(x+7)<<56)); } + + CHashWriter ss(SER_DISK, CLIENT_VERSION); + ss << CTransaction(); + BOOST_CHECK_EQUAL(SipHashUint256(1, 2, ss.GetHash()), 0x79751e980c2a0a35ULL); } BOOST_AUTO_TEST_SUITE_END() From a8689fdf8e10300b73750161a73a23467ecd1efe Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Fri, 17 Jun 2016 21:17:25 -0400 Subject: [PATCH 0667/1802] Tests: refactor compact size serialization in mininode --- qa/rpc-tests/test_framework/mininode.py | 97 +++++++------------------ 1 file changed, 25 insertions(+), 72 deletions(-) diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index cdd5292cd67b8..67aaab698e952 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -74,8 +74,19 @@ def ripemd160(s): def hash256(s): return sha256(sha256(s)) +def ser_compact_size(l): + r = b"" + if l < 253: + r = struct.pack("B", l) + elif l < 0x10000: + r = struct.pack(" Date: Tue, 12 Jul 2016 16:04:38 -0400 Subject: [PATCH 0668/1802] Add support for compactblocks to mininode --- qa/rpc-tests/test_framework/mininode.py | 276 +++++++++++++++++++++++- 1 file changed, 272 insertions(+), 4 deletions(-) diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index 67aaab698e952..caffab35351df 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -36,9 +36,10 @@ from threading import Thread import logging import copy +from test_framework.siphash import siphash256 BIP0031_VERSION = 60000 -MY_VERSION = 60001 # past bip-31 for ping/pong +MY_VERSION = 70014 # past bip-31 for ping/pong MY_SUBVERSION = b"/python-mininode-tester:0.0.3/" MAX_INV_SZ = 50000 @@ -52,7 +53,7 @@ NODE_WITNESS = (1 << 3) # Keep our own socket map for asyncore, so that we can track disconnects -# ourselves (to workaround an issue with closing an asyncore socket when +# ourselves (to workaround an issue with closing an asyncore socket when # using select) mininode_socket_map = dict() @@ -247,7 +248,8 @@ class CInv(object): 1: "TX", 2: "Block", 1|MSG_WITNESS_FLAG: "WitnessTx", - 2|MSG_WITNESS_FLAG : "WitnessBlock" + 2|MSG_WITNESS_FLAG : "WitnessBlock", + 4: "CompactBlock" } def __init__(self, t=0, h=0): @@ -734,6 +736,187 @@ def __repr__(self): % (len(self.vchMsg), len(self.vchSig)) +class PrefilledTransaction(object): + def __init__(self, index=0, tx = None): + self.index = index + self.tx = tx + + def deserialize(self, f): + self.index = deser_compact_size(f) + self.tx = CTransaction() + self.tx.deserialize(f) + + def serialize(self, with_witness=False): + r = b"" + r += ser_compact_size(self.index) + if with_witness: + r += self.tx.serialize_with_witness() + else: + r += self.tx.serialize_without_witness() + return r + + def __repr__(self): + return "PrefilledTransaction(index=%d, tx=%s)" % (self.index, repr(self.tx)) + +# This is what we send on the wire, in a cmpctblock message. +class P2PHeaderAndShortIDs(object): + def __init__(self): + self.header = CBlockHeader() + self.nonce = 0 + self.shortids_length = 0 + self.shortids = [] + self.prefilled_txn_length = 0 + self.prefilled_txn = [] + + def deserialize(self, f): + self.header.deserialize(f) + self.nonce = struct.unpack(" Date: Tue, 12 Jul 2016 16:05:02 -0400 Subject: [PATCH 0669/1802] Add p2p test for BIP 152 (compact blocks) --- qa/pull-tester/rpc-tests.py | 1 + qa/rpc-tests/p2p-compactblocks.py | 608 ++++++++++++++++++++++++++++++ 2 files changed, 609 insertions(+) create mode 100755 qa/rpc-tests/p2p-compactblocks.py diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index 11b83bac1468d..c4b11bc51b1e3 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -141,6 +141,7 @@ 'segwit.py', 'importprunedfunds.py', 'signmessages.py', + 'p2p-compactblocks.py', ] if ENABLE_ZMQ: testScripts.append('zmq_test.py') diff --git a/qa/rpc-tests/p2p-compactblocks.py b/qa/rpc-tests/p2p-compactblocks.py new file mode 100755 index 0000000000000..7fe7ecc16c6e1 --- /dev/null +++ b/qa/rpc-tests/p2p-compactblocks.py @@ -0,0 +1,608 @@ +#!/usr/bin/env python3 +# Copyright (c) 2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +from test_framework.mininode import * +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * +from test_framework.blocktools import create_block, create_coinbase +from test_framework.siphash import siphash256 +from test_framework.script import CScript, OP_TRUE + +''' +CompactBlocksTest -- test compact blocks (BIP 152) +''' + + +# TestNode: A peer we use to send messages to bitcoind, and store responses. +class TestNode(SingleNodeConnCB): + def __init__(self): + SingleNodeConnCB.__init__(self) + self.last_sendcmpct = None + self.last_headers = None + self.last_inv = None + self.last_cmpctblock = None + self.block_announced = False + self.last_getdata = None + self.last_getblocktxn = None + self.last_block = None + self.last_blocktxn = None + + def on_sendcmpct(self, conn, message): + self.last_sendcmpct = message + + def on_block(self, conn, message): + self.last_block = message + + def on_cmpctblock(self, conn, message): + self.last_cmpctblock = message + self.block_announced = True + + def on_headers(self, conn, message): + self.last_headers = message + self.block_announced = True + + def on_inv(self, conn, message): + self.last_inv = message + self.block_announced = True + + def on_getdata(self, conn, message): + self.last_getdata = message + + def on_getblocktxn(self, conn, message): + self.last_getblocktxn = message + + def on_blocktxn(self, conn, message): + self.last_blocktxn = message + + # Requires caller to hold mininode_lock + def received_block_announcement(self): + return self.block_announced + + def clear_block_announcement(self): + with mininode_lock: + self.block_announced = False + self.last_inv = None + self.last_headers = None + self.last_cmpctblock = None + + def get_headers(self, locator, hashstop): + msg = msg_getheaders() + msg.locator.vHave = locator + msg.hashstop = hashstop + self.connection.send_message(msg) + + def send_header_for_blocks(self, new_blocks): + headers_message = msg_headers() + headers_message.headers = [CBlockHeader(b) for b in new_blocks] + self.send_message(headers_message) + + +class CompactBlocksTest(BitcoinTestFramework): + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 1 + self.utxos = [] + + def setup_network(self): + self.nodes = [] + + # Turn off segwit in this test, as compact blocks don't currently work + # with segwit. (After BIP 152 is updated to support segwit, we can + # test behavior with and without segwit enabled by adding a second node + # to the test.) + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [["-debug", "-logtimemicros=1", "-bip9params=segwit:0:0"]]) + + def build_block_on_tip(self): + height = self.nodes[0].getblockcount() + tip = self.nodes[0].getbestblockhash() + mtp = self.nodes[0].getblockheader(tip)['mediantime'] + block = create_block(int(tip, 16), create_coinbase(height + 1), mtp + 1) + block.solve() + return block + + # Create 10 more anyone-can-spend utxo's for testing. + def make_utxos(self): + block = self.build_block_on_tip() + self.test_node.send_and_ping(msg_block(block)) + assert(int(self.nodes[0].getbestblockhash(), 16) == block.sha256) + self.nodes[0].generate(100) + + total_value = block.vtx[0].vout[0].nValue + out_value = total_value // 10 + tx = CTransaction() + tx.vin.append(CTxIn(COutPoint(block.vtx[0].sha256, 0), b'')) + for i in range(10): + tx.vout.append(CTxOut(out_value, CScript([OP_TRUE]))) + tx.rehash() + + block2 = self.build_block_on_tip() + block2.vtx.append(tx) + block2.hashMerkleRoot = block2.calc_merkle_root() + block2.solve() + self.test_node.send_and_ping(msg_block(block2)) + assert_equal(int(self.nodes[0].getbestblockhash(), 16), block2.sha256) + self.utxos.extend([[tx.sha256, i, out_value] for i in range(10)]) + return + + # Test "sendcmpct": + # - No compact block announcements or getdata(MSG_CMPCT_BLOCK) unless + # sendcmpct is sent. + # - If sendcmpct is sent with version > 0, the message is ignored. + # - If sendcmpct is sent with boolean 0, then block announcements are not + # made with compact blocks. + # - If sendcmpct is then sent with boolean 1, then new block announcements + # are made with compact blocks. + def test_sendcmpct(self): + print("Testing SENDCMPCT p2p message... ") + + # Make sure we get a version 0 SENDCMPCT message from our peer + def received_sendcmpct(): + return (self.test_node.last_sendcmpct is not None) + got_message = wait_until(received_sendcmpct, timeout=30) + assert(got_message) + assert_equal(self.test_node.last_sendcmpct.version, 1) + + tip = int(self.nodes[0].getbestblockhash(), 16) + + def check_announcement_of_new_block(node, peer, predicate): + self.test_node.clear_block_announcement() + node.generate(1) + got_message = wait_until(peer.received_block_announcement, timeout=30) + assert(got_message) + with mininode_lock: + assert(predicate) + + # We shouldn't get any block announcements via cmpctblock yet. + check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is None) + + # Try one more time, this time after requesting headers. + self.test_node.clear_block_announcement() + self.test_node.get_headers(locator=[tip], hashstop=0) + wait_until(self.test_node.received_block_announcement, timeout=30) + self.test_node.clear_block_announcement() + + check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is None and self.test_node.last_inv is not None) + + # Now try a SENDCMPCT message with too-high version + sendcmpct = msg_sendcmpct() + sendcmpct.version = 2 + self.test_node.send_message(sendcmpct) + + check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is None) + + # Now try a SENDCMPCT message with valid version, but announce=False + self.test_node.send_message(msg_sendcmpct()) + check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is None) + + # Finally, try a SENDCMPCT message with announce=True + sendcmpct.version = 1 + sendcmpct.announce = True + self.test_node.send_message(sendcmpct) + check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is not None) + + # Try one more time + check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is not None) + + # Try one more time, after turning on sendheaders + self.test_node.send_message(msg_sendheaders()) + check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is not None) + + # Now turn off announcements + sendcmpct.announce = False + check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is None and self.test_node.last_headers is not None) + + # This test actually causes bitcoind to (reasonably!) disconnect us, so do this last. + def test_invalid_cmpctblock_message(self): + print("Testing invalid index in cmpctblock message...") + self.nodes[0].generate(101) + block = self.build_block_on_tip() + + cmpct_block = P2PHeaderAndShortIDs() + cmpct_block.header = CBlockHeader(block) + cmpct_block.prefilled_txn_length = 1 + # This index will be too high + prefilled_txn = PrefilledTransaction(1, block.vtx[0]) + cmpct_block.prefilled_txn = [prefilled_txn] + self.test_node.send_and_ping(msg_cmpctblock(cmpct_block)) + assert(int(self.nodes[0].getbestblockhash(), 16) == block.hashPrevBlock) + + # Compare the generated shortids to what we expect based on BIP 152, given + # bitcoind's choice of nonce. + def test_compactblock_construction(self): + print("Testing compactblock headers and shortIDs are correct...") + + # Generate a bunch of transactions. + self.nodes[0].generate(101) + num_transactions = 25 + address = self.nodes[0].getnewaddress() + for i in range(num_transactions): + self.nodes[0].sendtoaddress(address, 0.1) + + # Now mine a block, and look at the resulting compact block. + self.test_node.clear_block_announcement() + block_hash = int(self.nodes[0].generate(1)[0], 16) + + # Store the raw block in our internal format. + block = FromHex(CBlock(), self.nodes[0].getblock("%02x" % block_hash, False)) + [tx.calc_sha256() for tx in block.vtx] + block.rehash() + + # Don't care which type of announcement came back for this test; just + # request the compact block if we didn't get one yet. + wait_until(self.test_node.received_block_announcement, timeout=30) + + with mininode_lock: + if self.test_node.last_cmpctblock is None: + self.test_node.clear_block_announcement() + inv = CInv(4, block_hash) # 4 == "CompactBlock" + self.test_node.send_message(msg_getdata([inv])) + + wait_until(self.test_node.received_block_announcement, timeout=30) + + # Now we should have the compactblock + header_and_shortids = None + with mininode_lock: + assert(self.test_node.last_cmpctblock is not None) + # Convert the on-the-wire representation to absolute indexes + header_and_shortids = HeaderAndShortIDs(self.test_node.last_cmpctblock.header_and_shortids) + + # Check that we got the right block! + header_and_shortids.header.calc_sha256() + assert_equal(header_and_shortids.header.sha256, block_hash) + + # Make sure the prefilled_txn appears to have included the coinbase + assert(len(header_and_shortids.prefilled_txn) >= 1) + assert_equal(header_and_shortids.prefilled_txn[0].index, 0) + + # Check that all prefilled_txn entries match what's in the block. + for entry in header_and_shortids.prefilled_txn: + entry.tx.calc_sha256() + assert_equal(entry.tx.sha256, block.vtx[entry.index].sha256) + + # Check that the cmpctblock message announced all the transactions. + assert_equal(len(header_and_shortids.prefilled_txn) + len(header_and_shortids.shortids), len(block.vtx)) + + # And now check that all the shortids are as expected as well. + # Determine the siphash keys to use. + [k0, k1] = header_and_shortids.get_siphash_keys() + + index = 0 + while index < len(block.vtx): + if (len(header_and_shortids.prefilled_txn) > 0 and + header_and_shortids.prefilled_txn[0].index == index): + # Already checked prefilled transactions above + header_and_shortids.prefilled_txn.pop(0) + else: + shortid = calculate_shortid(k0, k1, block.vtx[index].sha256) + assert_equal(shortid, header_and_shortids.shortids[0]) + header_and_shortids.shortids.pop(0) + index += 1 + + # Test that bitcoind requests compact blocks when we announce new blocks + # via header or inv, and that responding to getblocktxn causes the block + # to be successfully reconstructed. + def test_compactblock_requests(self): + print("Testing compactblock requests... ") + + # Try announcing a block with an inv or header, expect a compactblock + # request + for announce in ["inv", "header"]: + block = self.build_block_on_tip() + with mininode_lock: + self.test_node.last_getdata = None + + if announce == "inv": + self.test_node.send_message(msg_inv([CInv(2, block.sha256)])) + else: + self.test_node.send_header_for_blocks([block]) + success = wait_until(lambda: self.test_node.last_getdata is not None, timeout=30) + assert(success) + assert_equal(len(self.test_node.last_getdata.inv), 1) + assert_equal(self.test_node.last_getdata.inv[0].type, 4) + assert_equal(self.test_node.last_getdata.inv[0].hash, block.sha256) + + # Send back a compactblock message that omits the coinbase + comp_block = HeaderAndShortIDs() + comp_block.header = CBlockHeader(block) + comp_block.nonce = 0 + comp_block.shortids = [1] # this is useless, and wrong + self.test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) + assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.hashPrevBlock) + # Expect a getblocktxn message. + with mininode_lock: + assert(self.test_node.last_getblocktxn is not None) + absolute_indexes = self.test_node.last_getblocktxn.block_txn_request.to_absolute() + assert_equal(absolute_indexes, [0]) # should be a coinbase request + + # Send the coinbase, and verify that the tip advances. + msg = msg_blocktxn() + msg.block_transactions.blockhash = block.sha256 + msg.block_transactions.transactions = [block.vtx[0]] + self.test_node.send_and_ping(msg) + assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256) + + # Create a chain of transactions from given utxo, and add to a new block. + def build_block_with_transactions(self, utxo, num_transactions): + block = self.build_block_on_tip() + + for i in range(num_transactions): + tx = CTransaction() + tx.vin.append(CTxIn(COutPoint(utxo[0], utxo[1]), b'')) + tx.vout.append(CTxOut(utxo[2] - 1000, CScript([OP_TRUE]))) + tx.rehash() + utxo = [tx.sha256, 0, tx.vout[0].nValue] + block.vtx.append(tx) + + block.hashMerkleRoot = block.calc_merkle_root() + block.solve() + return block + + # Test that we only receive getblocktxn requests for transactions that the + # node needs, and that responding to them causes the block to be + # reconstructed. + def test_getblocktxn_requests(self): + print("Testing getblocktxn requests...") + + # First try announcing compactblocks that won't reconstruct, and verify + # that we receive getblocktxn messages back. + utxo = self.utxos.pop(0) + + block = self.build_block_with_transactions(utxo, 5) + self.utxos.append([block.vtx[-1].sha256, 0, block.vtx[-1].vout[0].nValue]) + + comp_block = HeaderAndShortIDs() + comp_block.initialize_from_block(block) + + self.test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) + with mininode_lock: + assert(self.test_node.last_getblocktxn is not None) + absolute_indexes = self.test_node.last_getblocktxn.block_txn_request.to_absolute() + assert_equal(absolute_indexes, [1, 2, 3, 4, 5]) + msg = msg_blocktxn() + msg.block_transactions = BlockTransactions(block.sha256, block.vtx[1:]) + self.test_node.send_and_ping(msg) + assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256) + + utxo = self.utxos.pop(0) + block = self.build_block_with_transactions(utxo, 5) + self.utxos.append([block.vtx[-1].sha256, 0, block.vtx[-1].vout[0].nValue]) + + # Now try interspersing the prefilled transactions + comp_block.initialize_from_block(block, prefill_list=[0, 1, 5]) + self.test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) + with mininode_lock: + assert(self.test_node.last_getblocktxn is not None) + absolute_indexes = self.test_node.last_getblocktxn.block_txn_request.to_absolute() + assert_equal(absolute_indexes, [2, 3, 4]) + msg.block_transactions = BlockTransactions(block.sha256, block.vtx[2:5]) + self.test_node.send_and_ping(msg) + assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256) + + # Now try giving one transaction ahead of time. + utxo = self.utxos.pop(0) + block = self.build_block_with_transactions(utxo, 5) + self.utxos.append([block.vtx[-1].sha256, 0, block.vtx[-1].vout[0].nValue]) + self.test_node.send_and_ping(msg_tx(block.vtx[1])) + assert(block.vtx[1].hash in self.nodes[0].getrawmempool()) + + # Prefill 4 out of the 6 transactions, and verify that only the one + # that was not in the mempool is requested. + comp_block.initialize_from_block(block, prefill_list=[0, 2, 3, 4]) + self.test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) + with mininode_lock: + assert(self.test_node.last_getblocktxn is not None) + absolute_indexes = self.test_node.last_getblocktxn.block_txn_request.to_absolute() + assert_equal(absolute_indexes, [5]) + + msg.block_transactions = BlockTransactions(block.sha256, [block.vtx[5]]) + self.test_node.send_and_ping(msg) + assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256) + + # Now provide all transactions to the node before the block is + # announced and verify reconstruction happens immediately. + utxo = self.utxos.pop(0) + block = self.build_block_with_transactions(utxo, 10) + self.utxos.append([block.vtx[-1].sha256, 0, block.vtx[-1].vout[0].nValue]) + for tx in block.vtx[1:]: + self.test_node.send_message(msg_tx(tx)) + self.test_node.sync_with_ping() + # Make sure all transactions were accepted. + mempool = self.nodes[0].getrawmempool() + for tx in block.vtx[1:]: + assert(tx.hash in mempool) + + # Clear out last request. + with mininode_lock: + self.test_node.last_getblocktxn = None + + # Send compact block + comp_block.initialize_from_block(block, prefill_list=[0]) + self.test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) + with mininode_lock: + # Shouldn't have gotten a request for any transaction + assert(self.test_node.last_getblocktxn is None) + # Tip should have updated + assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256) + + # Incorrectly responding to a getblocktxn shouldn't cause the block to be + # permanently failed. + def test_incorrect_blocktxn_response(self): + print("Testing handling of incorrect blocktxn responses...") + + if (len(self.utxos) == 0): + self.make_utxos() + utxo = self.utxos.pop(0) + + block = self.build_block_with_transactions(utxo, 10) + self.utxos.append([block.vtx[-1].sha256, 0, block.vtx[-1].vout[0].nValue]) + # Relay the first 5 transactions from the block in advance + for tx in block.vtx[1:6]: + self.test_node.send_message(msg_tx(tx)) + self.test_node.sync_with_ping() + # Make sure all transactions were accepted. + mempool = self.nodes[0].getrawmempool() + for tx in block.vtx[1:6]: + assert(tx.hash in mempool) + + # Send compact block + comp_block = HeaderAndShortIDs() + comp_block.initialize_from_block(block, prefill_list=[0]) + self.test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) + absolute_indexes = [] + with mininode_lock: + assert(self.test_node.last_getblocktxn is not None) + absolute_indexes = self.test_node.last_getblocktxn.block_txn_request.to_absolute() + assert_equal(absolute_indexes, [6, 7, 8, 9, 10]) + + # Now give an incorrect response. + # Note that it's possible for bitcoind to be smart enough to know we're + # lying, since it could check to see if the shortid matches what we're + # sending, and eg disconnect us for misbehavior. If that behavior + # change were made, we could just modify this test by having a + # different peer provide the block further down, so that we're still + # verifying that the block isn't marked bad permanently. This is good + # enough for now. + msg = msg_blocktxn() + msg.block_transactions = BlockTransactions(block.sha256, [block.vtx[5]] + block.vtx[7:]) + self.test_node.send_and_ping(msg) + + # Tip should not have updated + assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.hashPrevBlock) + + # We should receive a getdata request + success = wait_until(lambda: self.test_node.last_getdata is not None, timeout=10) + assert(success) + assert_equal(len(self.test_node.last_getdata.inv), 1) + assert_equal(self.test_node.last_getdata.inv[0].type, 2) + assert_equal(self.test_node.last_getdata.inv[0].hash, block.sha256) + + # Deliver the block + self.test_node.send_and_ping(msg_block(block)) + assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256) + + def test_getblocktxn_handler(self): + print("Testing getblocktxn handler...") + + # bitcoind won't respond for blocks whose height is more than 15 blocks + # deep. + MAX_GETBLOCKTXN_DEPTH = 15 + chain_height = self.nodes[0].getblockcount() + current_height = chain_height + while (current_height >= chain_height - MAX_GETBLOCKTXN_DEPTH): + block_hash = self.nodes[0].getblockhash(current_height) + block = FromHex(CBlock(), self.nodes[0].getblock(block_hash, False)) + + msg = msg_getblocktxn() + msg.block_txn_request = BlockTransactionsRequest(int(block_hash, 16), []) + num_to_request = random.randint(1, len(block.vtx)) + msg.block_txn_request.from_absolute(sorted(random.sample(range(len(block.vtx)), num_to_request))) + self.test_node.send_message(msg) + success = wait_until(lambda: self.test_node.last_blocktxn is not None, timeout=10) + assert(success) + + [tx.calc_sha256() for tx in block.vtx] + with mininode_lock: + assert_equal(self.test_node.last_blocktxn.block_transactions.blockhash, int(block_hash, 16)) + all_indices = msg.block_txn_request.to_absolute() + for index in all_indices: + tx = self.test_node.last_blocktxn.block_transactions.transactions.pop(0) + tx.calc_sha256() + assert_equal(tx.sha256, block.vtx[index].sha256) + self.test_node.last_blocktxn = None + current_height -= 1 + + # Next request should be ignored, as we're past the allowed depth. + block_hash = self.nodes[0].getblockhash(current_height) + msg.block_txn_request = BlockTransactionsRequest(int(block_hash, 16), [0]) + self.test_node.send_and_ping(msg) + with mininode_lock: + assert_equal(self.test_node.last_blocktxn, None) + + def test_compactblocks_not_at_tip(self): + print("Testing compactblock requests/announcements not at chain tip...") + + # Test that requesting old compactblocks doesn't work. + MAX_CMPCTBLOCK_DEPTH = 11 + new_blocks = [] + for i in range(MAX_CMPCTBLOCK_DEPTH): + self.test_node.clear_block_announcement() + new_blocks.append(self.nodes[0].generate(1)[0]) + wait_until(self.test_node.received_block_announcement, timeout=30) + + self.test_node.clear_block_announcement() + self.test_node.send_message(msg_getdata([CInv(4, int(new_blocks[0], 16))])) + success = wait_until(lambda: self.test_node.last_cmpctblock is not None, timeout=30) + assert(success) + + self.test_node.clear_block_announcement() + self.nodes[0].generate(1) + wait_until(self.test_node.received_block_announcement, timeout=30) + self.test_node.clear_block_announcement() + self.test_node.send_message(msg_getdata([CInv(4, int(new_blocks[0], 16))])) + success = wait_until(lambda: self.test_node.last_block is not None, timeout=30) + assert(success) + with mininode_lock: + self.test_node.last_block.block.calc_sha256() + assert_equal(self.test_node.last_block.block.sha256, int(new_blocks[0], 16)) + + # Generate an old compactblock, and verify that it's not accepted. + cur_height = self.nodes[0].getblockcount() + hashPrevBlock = int(self.nodes[0].getblockhash(cur_height-5), 16) + block = self.build_block_on_tip() + block.hashPrevBlock = hashPrevBlock + block.solve() + + comp_block = HeaderAndShortIDs() + comp_block.initialize_from_block(block) + self.test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) + + tips = self.nodes[0].getchaintips() + found = False + for x in tips: + if x["hash"] == block.hash: + assert_equal(x["status"], "headers-only") + found = True + break + assert(found) + + # Requesting this block via getblocktxn should silently fail + # (to avoid fingerprinting attacks). + msg = msg_getblocktxn() + msg.block_txn_request = BlockTransactionsRequest(block.sha256, [0]) + with mininode_lock: + self.test_node.last_blocktxn = None + self.test_node.send_and_ping(msg) + with mininode_lock: + assert(self.test_node.last_blocktxn is None) + + def run_test(self): + # Setup the p2p connections and start up the network thread. + self.test_node = TestNode() + + connections = [] + connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], self.test_node)) + self.test_node.add_connection(connections[0]) + + NetworkThread().start() # Start up network handling in another thread + + # Test logic begins here + self.test_node.wait_for_verack() + + # We will need UTXOs to construct transactions in later tests. + self.make_utxos() + + self.test_sendcmpct() + self.test_compactblock_construction() + self.test_compactblock_requests() + self.test_getblocktxn_requests() + self.test_getblocktxn_handler() + self.test_compactblocks_not_at_tip() + self.test_incorrect_blocktxn_response() + self.test_invalid_cmpctblock_message() + + +if __name__ == '__main__': + CompactBlocksTest().main() From 5c9e49d12c931f9c7ddaac0144739dcd7263e554 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 29 Jul 2016 17:42:12 +0200 Subject: [PATCH 0670/1802] net: Ignore `notfound` P2P messages --- src/main.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 622ec51422ae6..81f09515f30de 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6145,6 +6145,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } } + else if (strCommand == NetMsgType::NOTFOUND) { + // We do not care about the NOTFOUND message, but logging an Unknown Command + // message would be undesirable as we transmit it ourselves. + } + else { // Ignore unknown commands for extensibility LogPrint("net", "Unknown command \"%s\" from peer=%d\n", SanitizeString(strCommand), pfrom->id); From 00f09c920c2e8906d2260251be6d1d2fa1bbb29d Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Tue, 7 Jun 2016 21:25:31 -0700 Subject: [PATCH 0671/1802] Split CWallet::AddToWallet into AddToWallet and LoadToWallet. This removes the fFromLoadWallet flag in AddToWallet. These were already effectively two methods. --- src/wallet/rpcdump.cpp | 2 +- src/wallet/test/accounting_tests.cpp | 6 +- src/wallet/wallet.cpp | 222 ++++++++++++++------------- src/wallet/wallet.h | 3 +- src/wallet/walletdb.cpp | 2 +- 5 files changed, 119 insertions(+), 116 deletions(-) diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 6647d3297fad2..9d403a453889f 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -310,7 +310,7 @@ UniValue importprunedfunds(const UniValue& params, bool fHelp) if (pwalletMain->IsMine(tx)) { CWalletDB walletdb(pwalletMain->strWalletFile, "r+", false); - pwalletMain->AddToWallet(wtx, false, &walletdb); + pwalletMain->AddToWallet(wtx, &walletdb); return NullUniValue; } diff --git a/src/wallet/test/accounting_tests.cpp b/src/wallet/test/accounting_tests.cpp index d075b2b641a1b..8aad568c93cc6 100644 --- a/src/wallet/test/accounting_tests.cpp +++ b/src/wallet/test/accounting_tests.cpp @@ -48,7 +48,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) pwalletMain->AddAccountingEntry(ae, walletdb); wtx.mapValue["comment"] = "z"; - pwalletMain->AddToWallet(wtx, false, &walletdb); + pwalletMain->AddToWallet(wtx, &walletdb); vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]); vpwtx[0]->nTimeReceived = (unsigned int)1333333335; vpwtx[0]->nOrderPos = -1; @@ -90,7 +90,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) --tx.nLockTime; // Just to change the hash :) *static_cast(&wtx) = CTransaction(tx); } - pwalletMain->AddToWallet(wtx, false, &walletdb); + pwalletMain->AddToWallet(wtx, &walletdb); vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]); vpwtx[1]->nTimeReceived = (unsigned int)1333333336; @@ -100,7 +100,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) --tx.nLockTime; // Just to change the hash :) *static_cast(&wtx) = CTransaction(tx); } - pwalletMain->AddToWallet(wtx, false, &walletdb); + pwalletMain->AddToWallet(wtx, &walletdb); vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]); vpwtx[2]->nTimeReceived = (unsigned int)1333333329; vpwtx[2]->nOrderPos = -1; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index e5ee5063a5d31..68ce26eaa8ae0 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -741,138 +741,140 @@ void CWallet::MarkDirty() } } -bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletDB* pwalletdb) +bool CWallet::AddToWallet(const CWalletTx& wtxIn, CWalletDB* pwalletdb) { uint256 hash = wtxIn.GetHash(); - if (fFromLoadWallet) - { - mapWallet[hash] = wtxIn; - CWalletTx& wtx = mapWallet[hash]; - wtx.BindWallet(this); + LOCK(cs_wallet); + // Inserts only if not already there, returns tx inserted or tx found + pair::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn)); + CWalletTx& wtx = (*ret.first).second; + wtx.BindWallet(this); + bool fInsertedNew = ret.second; + if (fInsertedNew) + { + wtx.nTimeReceived = GetAdjustedTime(); + wtx.nOrderPos = IncOrderPosNext(pwalletdb); wtxOrdered.insert(make_pair(wtx.nOrderPos, TxPair(&wtx, (CAccountingEntry*)0))); - AddToSpends(hash); - BOOST_FOREACH(const CTxIn& txin, wtx.vin) { - if (mapWallet.count(txin.prevout.hash)) { - CWalletTx& prevtx = mapWallet[txin.prevout.hash]; - if (prevtx.nIndex == -1 && !prevtx.hashUnset()) { - MarkConflicted(prevtx.hashBlock, wtx.GetHash()); - } - } - } - } - else - { - LOCK(cs_wallet); - // Inserts only if not already there, returns tx inserted or tx found - pair::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn)); - CWalletTx& wtx = (*ret.first).second; - wtx.BindWallet(this); - bool fInsertedNew = ret.second; - if (fInsertedNew) - { - wtx.nTimeReceived = GetAdjustedTime(); - wtx.nOrderPos = IncOrderPosNext(pwalletdb); - wtxOrdered.insert(make_pair(wtx.nOrderPos, TxPair(&wtx, (CAccountingEntry*)0))); - - wtx.nTimeSmart = wtx.nTimeReceived; - if (!wtxIn.hashUnset()) + + wtx.nTimeSmart = wtx.nTimeReceived; + if (!wtxIn.hashUnset()) + { + if (mapBlockIndex.count(wtxIn.hashBlock)) { - if (mapBlockIndex.count(wtxIn.hashBlock)) + int64_t latestNow = wtx.nTimeReceived; + int64_t latestEntry = 0; { - int64_t latestNow = wtx.nTimeReceived; - int64_t latestEntry = 0; + // Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future + int64_t latestTolerated = latestNow + 300; + const TxItems & txOrdered = wtxOrdered; + for (TxItems::const_reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) { - // Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future - int64_t latestTolerated = latestNow + 300; - const TxItems & txOrdered = wtxOrdered; - for (TxItems::const_reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) + CWalletTx *const pwtx = (*it).second.first; + if (pwtx == &wtx) + continue; + CAccountingEntry *const pacentry = (*it).second.second; + int64_t nSmartTime; + if (pwtx) { - CWalletTx *const pwtx = (*it).second.first; - if (pwtx == &wtx) - continue; - CAccountingEntry *const pacentry = (*it).second.second; - int64_t nSmartTime; - if (pwtx) - { - nSmartTime = pwtx->nTimeSmart; - if (!nSmartTime) - nSmartTime = pwtx->nTimeReceived; - } - else - nSmartTime = pacentry->nTime; - if (nSmartTime <= latestTolerated) - { - latestEntry = nSmartTime; - if (nSmartTime > latestNow) - latestNow = nSmartTime; - break; - } + nSmartTime = pwtx->nTimeSmart; + if (!nSmartTime) + nSmartTime = pwtx->nTimeReceived; + } + else + nSmartTime = pacentry->nTime; + if (nSmartTime <= latestTolerated) + { + latestEntry = nSmartTime; + if (nSmartTime > latestNow) + latestNow = nSmartTime; + break; } } - - int64_t blocktime = mapBlockIndex[wtxIn.hashBlock]->GetBlockTime(); - wtx.nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow)); } - else - LogPrintf("AddToWallet(): found %s in block %s not in index\n", - wtxIn.GetHash().ToString(), - wtxIn.hashBlock.ToString()); + + int64_t blocktime = mapBlockIndex[wtxIn.hashBlock]->GetBlockTime(); + wtx.nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow)); } - AddToSpends(hash); + else + LogPrintf("AddToWallet(): found %s in block %s not in index\n", + wtxIn.GetHash().ToString(), + wtxIn.hashBlock.ToString()); } + AddToSpends(hash); + } - bool fUpdated = false; - if (!fInsertedNew) + bool fUpdated = false; + if (!fInsertedNew) + { + // Merge + if (!wtxIn.hashUnset() && wtxIn.hashBlock != wtx.hashBlock) { - // Merge - if (!wtxIn.hashUnset() && wtxIn.hashBlock != wtx.hashBlock) - { - wtx.hashBlock = wtxIn.hashBlock; - fUpdated = true; - } - // If no longer abandoned, update - if (wtxIn.hashBlock.IsNull() && wtx.isAbandoned()) - { - wtx.hashBlock = wtxIn.hashBlock; - fUpdated = true; - } - if (wtxIn.nIndex != -1 && (wtxIn.nIndex != wtx.nIndex)) - { - wtx.nIndex = wtxIn.nIndex; - fUpdated = true; - } - if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe) - { - wtx.fFromMe = wtxIn.fFromMe; - fUpdated = true; - } + wtx.hashBlock = wtxIn.hashBlock; + fUpdated = true; } + // If no longer abandoned, update + if (wtxIn.hashBlock.IsNull() && wtx.isAbandoned()) + { + wtx.hashBlock = wtxIn.hashBlock; + fUpdated = true; + } + if (wtxIn.nIndex != -1 && (wtxIn.nIndex != wtx.nIndex)) + { + wtx.nIndex = wtxIn.nIndex; + fUpdated = true; + } + if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe) + { + wtx.fFromMe = wtxIn.fFromMe; + fUpdated = true; + } + } - //// debug print - LogPrintf("AddToWallet %s %s%s\n", wtxIn.GetHash().ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : "")); + //// debug print + LogPrintf("AddToWallet %s %s%s\n", wtxIn.GetHash().ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : "")); - // Write to disk - if (fInsertedNew || fUpdated) - if (!pwalletdb->WriteTx(wtx)) - return false; + // Write to disk + if (fInsertedNew || fUpdated) + if (!pwalletdb->WriteTx(wtx)) + return false; - // Break debit/credit balance caches: - wtx.MarkDirty(); + // Break debit/credit balance caches: + wtx.MarkDirty(); - // Notify UI of new or updated transaction - NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED); + // Notify UI of new or updated transaction + NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED); - // notify an external script when a wallet transaction comes in or is updated - std::string strCmd = GetArg("-walletnotify", ""); + // notify an external script when a wallet transaction comes in or is updated + std::string strCmd = GetArg("-walletnotify", ""); - if ( !strCmd.empty()) - { - boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex()); - boost::thread t(runCommand, strCmd); // thread runs free - } + if ( !strCmd.empty()) + { + boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex()); + boost::thread t(runCommand, strCmd); // thread runs free + } + + return true; +} + +bool CWallet::LoadToWallet(const CWalletTx& wtxIn) +{ + uint256 hash = wtxIn.GetHash(); + mapWallet[hash] = wtxIn; + CWalletTx& wtx = mapWallet[hash]; + wtx.BindWallet(this); + wtxOrdered.insert(make_pair(wtx.nOrderPos, TxPair(&wtx, (CAccountingEntry*)0))); + AddToSpends(hash); + BOOST_FOREACH(const CTxIn& txin, wtx.vin) { + if (mapWallet.count(txin.prevout.hash)) { + CWalletTx& prevtx = mapWallet[txin.prevout.hash]; + if (prevtx.nIndex == -1 && !prevtx.hashUnset()) { + MarkConflicted(prevtx.hashBlock, wtx.GetHash()); + } + } } + return true; } @@ -913,7 +915,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl // this is safe, as in case of a crash, we rescan the necessary blocks on startup through our SetBestChain-mechanism CWalletDB walletdb(strWalletFile, "r+", false); - return AddToWallet(wtx, false, &walletdb); + return AddToWallet(wtx, &walletdb); } } return false; @@ -2456,7 +2458,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) // Add tx to wallet, because if it has change it's also ours, // otherwise just for transaction history. - AddToWallet(wtxNew, false, pwalletdb); + AddToWallet(wtxNew, pwalletdb); // Notify that old coins are spent set setCoins; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 0c95fdf4b04d8..3bbacaae5786f 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -729,7 +729,8 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface bool GetAccountPubkey(CPubKey &pubKey, std::string strAccount, bool bForceNew = false); void MarkDirty(); - bool AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletDB* pwalletdb); + bool AddToWallet(const CWalletTx& wtxIn, CWalletDB* pwalletdb); + bool LoadToWallet(const CWalletTx& wtxIn); void SyncTransaction(const CTransaction& tx, const CBlockIndex *pindex, const CBlock* pblock); bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate); int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false); diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 72af8ab7b25e6..543522ca6485c 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -400,7 +400,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, if (wtx.nOrderPos == -1) wss.fAnyUnordered = true; - pwallet->AddToWallet(wtx, true, NULL); + pwallet->LoadToWallet(wtx); } else if (strType == "acentry") { From 867f842f1e5a385aeb2093f802d6f37a84d0fe5d Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Tue, 7 Jun 2016 21:41:03 -0700 Subject: [PATCH 0672/1802] Remove CWalletDB* parameter from CWallet::AddToWallet --- src/wallet/rpcdump.cpp | 3 +-- src/wallet/test/accounting_tests.cpp | 6 +++--- src/wallet/wallet.cpp | 19 +++++++++---------- src/wallet/wallet.h | 2 +- 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 9d403a453889f..fe8b53ceb0c1a 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -309,8 +309,7 @@ UniValue importprunedfunds(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); if (pwalletMain->IsMine(tx)) { - CWalletDB walletdb(pwalletMain->strWalletFile, "r+", false); - pwalletMain->AddToWallet(wtx, &walletdb); + pwalletMain->AddToWallet(wtx, false); return NullUniValue; } diff --git a/src/wallet/test/accounting_tests.cpp b/src/wallet/test/accounting_tests.cpp index 8aad568c93cc6..a6cada46a226c 100644 --- a/src/wallet/test/accounting_tests.cpp +++ b/src/wallet/test/accounting_tests.cpp @@ -48,7 +48,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) pwalletMain->AddAccountingEntry(ae, walletdb); wtx.mapValue["comment"] = "z"; - pwalletMain->AddToWallet(wtx, &walletdb); + pwalletMain->AddToWallet(wtx); vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]); vpwtx[0]->nTimeReceived = (unsigned int)1333333335; vpwtx[0]->nOrderPos = -1; @@ -90,7 +90,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) --tx.nLockTime; // Just to change the hash :) *static_cast(&wtx) = CTransaction(tx); } - pwalletMain->AddToWallet(wtx, &walletdb); + pwalletMain->AddToWallet(wtx); vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]); vpwtx[1]->nTimeReceived = (unsigned int)1333333336; @@ -100,7 +100,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) --tx.nLockTime; // Just to change the hash :) *static_cast(&wtx) = CTransaction(tx); } - pwalletMain->AddToWallet(wtx, &walletdb); + pwalletMain->AddToWallet(wtx); vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]); vpwtx[2]->nTimeReceived = (unsigned int)1333333329; vpwtx[2]->nOrderPos = -1; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 68ce26eaa8ae0..63a3baea04957 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -741,11 +741,14 @@ void CWallet::MarkDirty() } } -bool CWallet::AddToWallet(const CWalletTx& wtxIn, CWalletDB* pwalletdb) +bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose) { + LOCK(cs_wallet); + + CWalletDB walletdb(strWalletFile, "r+", fFlushOnClose); + uint256 hash = wtxIn.GetHash(); - LOCK(cs_wallet); // Inserts only if not already there, returns tx inserted or tx found pair::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn)); CWalletTx& wtx = (*ret.first).second; @@ -754,7 +757,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, CWalletDB* pwalletdb) if (fInsertedNew) { wtx.nTimeReceived = GetAdjustedTime(); - wtx.nOrderPos = IncOrderPosNext(pwalletdb); + wtx.nOrderPos = IncOrderPosNext(&walletdb); wtxOrdered.insert(make_pair(wtx.nOrderPos, TxPair(&wtx, (CAccountingEntry*)0))); wtx.nTimeSmart = wtx.nTimeReceived; @@ -836,7 +839,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, CWalletDB* pwalletdb) // Write to disk if (fInsertedNew || fUpdated) - if (!pwalletdb->WriteTx(wtx)) + if (!walletdb.WriteTx(wtx)) return false; // Break debit/credit balance caches: @@ -911,11 +914,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl if (pblock) wtx.SetMerkleBranch(*pblock); - // Do not flush the wallet here for performance reasons - // this is safe, as in case of a crash, we rescan the necessary blocks on startup through our SetBestChain-mechanism - CWalletDB walletdb(strWalletFile, "r+", false); - - return AddToWallet(wtx, &walletdb); + return AddToWallet(wtx, false); } } return false; @@ -2458,7 +2457,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) // Add tx to wallet, because if it has change it's also ours, // otherwise just for transaction history. - AddToWallet(wtxNew, pwalletdb); + AddToWallet(wtxNew); // Notify that old coins are spent set setCoins; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 3bbacaae5786f..236ef85114e1a 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -729,7 +729,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface bool GetAccountPubkey(CPubKey &pubKey, std::string strAccount, bool bForceNew = false); void MarkDirty(); - bool AddToWallet(const CWalletTx& wtxIn, CWalletDB* pwalletdb); + bool AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose=true); bool LoadToWallet(const CWalletTx& wtxIn); void SyncTransaction(const CTransaction& tx, const CBlockIndex *pindex, const CBlock* pblock); bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate); From 5723bb44ce2c6bb14114aa7f211160702a47ac91 Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Wed, 8 Jun 2016 16:20:59 -0700 Subject: [PATCH 0673/1802] Remove unused pwalletdb from CWallet::AddToWallet --- src/wallet/wallet.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 63a3baea04957..ee9254050ce78 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2447,11 +2447,6 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) LOCK2(cs_main, cs_wallet); LogPrintf("CommitTransaction:\n%s", wtxNew.ToString()); { - // This is only to keep the database open to defeat the auto-flush for the - // duration of this scope. This is the only place where this optimization - // maybe makes sense; please don't do it anywhere else. - CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r+") : NULL; - // Take key pair from key pool so it won't be used again reservekey.KeepKey(); @@ -2467,9 +2462,6 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) coin.BindWallet(this); NotifyTransactionChanged(this, coin.GetHash(), CT_UPDATED); } - - if (fFileBacked) - delete pwalletdb; } // Track how many getdata requests our transaction gets From 0fd2a33648ccde4b989f1d69529daea4d88b14a2 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 22 Jul 2016 15:57:25 +0200 Subject: [PATCH 0674/1802] Use a signal to continue init after genesis activation --- src/init.cpp | 40 +++++++++++++++++++++++++++++---------- src/main.cpp | 2 -- src/test/test_bitcoin.cpp | 5 +++++ 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 8d4a2cafbfbb1..4458c8331b613 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -510,6 +510,21 @@ static void BlockNotifyCallback(bool initialSync, const CBlockIndex *pBlockIndex boost::thread t(runCommand, strCmd); // thread runs free } +static bool fHaveGenesis = false; +static boost::mutex cs_GenesisWait; +static CConditionVariable condvar_GenesisWait; + +static void BlockNotifyGenesisWait(bool, const CBlockIndex *pBlockIndex) +{ + if (pBlockIndex != NULL) { + { + boost::unique_lock lock_GenesisWait(cs_GenesisWait); + fHaveGenesis = true; + } + condvar_GenesisWait.notify_all(); + } +} + struct CImportingNow { CImportingNow() { @@ -1286,7 +1301,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) break; } - if (!fReindex) { + if (!fReindex && chainActive.Tip() != NULL) { uiInterface.InitMessage(_("Rewinding blocks...")); if (!RewindBlockIndex(chainparams)) { strLoadError = _("Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain"); @@ -1403,6 +1418,14 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // ********************************************************* Step 10: import blocks + // Either install a handler to notify us when genesis activates, or set fHaveGenesis directly. + // No locking, as this happens before any background thread is started. + if (chainActive.Tip() == NULL) { + uiInterface.NotifyBlockTip.connect(BlockNotifyGenesisWait); + } else { + fHaveGenesis = true; + } + if (mapArgs.count("-blocknotify")) uiInterface.NotifyBlockTip.connect(BlockNotifyCallback); @@ -1412,19 +1435,16 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) BOOST_FOREACH(const std::string& strFile, mapMultiArgs["-loadblock"]) vImportFiles.push_back(strFile); } + threadGroup.create_thread(boost::bind(&ThreadImport, vImportFiles)); // Wait for genesis block to be processed - bool fHaveGenesis = false; - while (!fHaveGenesis && !fRequestShutdown) { - { - LOCK(cs_main); - fHaveGenesis = (chainActive.Tip() != NULL); - } - - if (!fHaveGenesis) { - MilliSleep(10); + { + boost::unique_lock lock(cs_GenesisWait); + while (!fHaveGenesis) { + condvar_GenesisWait.wait(lock); } + uiInterface.NotifyBlockTip.disconnect(BlockNotifyGenesisWait); } // ********************************************************* Step 11: start node diff --git a/src/main.cpp b/src/main.cpp index 622ec51422ae6..f8eab7eb3f8e5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4331,8 +4331,6 @@ bool InitBlockIndex(const CChainParams& chainparams) CBlockIndex *pindex = AddToBlockIndex(block); if (!ReceivedBlockTransactions(block, state, pindex, blockPos)) return error("LoadBlockIndex(): genesis block not accepted"); - if (!ActivateBestChain(state, chainparams, &block)) - return error("LoadBlockIndex(): genesis block cannot be activated"); // Force a chainstate write so that when we VerifyDB in a moment, it doesn't check stale data return FlushStateToDisk(state, FLUSH_STATE_ALWAYS); } catch (const std::runtime_error& e) { diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index 856f9b842300c..056f2982cf1eb 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -60,6 +60,11 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha pcoinsdbview = new CCoinsViewDB(1 << 23, true); pcoinsTip = new CCoinsViewCache(pcoinsdbview); InitBlockIndex(chainparams); + { + CValidationState state; + bool ok = ActivateBestChain(state, chainparams); + BOOST_CHECK(ok); + } nScriptCheckThreads = 3; for (int i=0; i < nScriptCheckThreads-1; i++) threadGroup.create_thread(&ThreadScriptCheck); From aa59f2ed3f378c02159e41ff3ae2df76ef850577 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 22 Jul 2016 16:01:12 +0200 Subject: [PATCH 0675/1802] Add extra message to avoid a long 'Loading banlist' --- src/net.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/net.cpp b/src/net.cpp index 4cbc43e4d8425..6a1ba41613192 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2050,6 +2050,8 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler) DumpBanlist(); } + uiInterface.InitMessage(_("Starting network threads...")); + fAddressesInitialized = true; if (semOutbound == NULL) { From 9d4eb9ad99f7c3abf7abaeaf7ea51f98f9445e75 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 22 Jul 2016 16:01:51 +0200 Subject: [PATCH 0676/1802] Do diskspace check before import thread is started --- src/init.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 4458c8331b613..44d8c16d9553d 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1418,6 +1418,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // ********************************************************* Step 10: import blocks + if (!CheckDiskSpace()) + return false; + // Either install a handler to notify us when genesis activates, or set fHaveGenesis directly. // No locking, as this happens before any background thread is started. if (chainActive.Tip() == NULL) { @@ -1449,9 +1452,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // ********************************************************* Step 11: start node - if (!CheckDiskSpace()) - return false; - if (!strErrors.str().empty()) return InitError(strErrors.str()); From 29c2d99bc937c7288b64ab8778dc5f4fd74b4f82 Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Sat, 30 Jul 2016 11:27:48 -0700 Subject: [PATCH 0677/1802] Make CWallet::fFileBacked private. --- src/wallet/wallet.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 0c95fdf4b04d8..9dfb87e1448f5 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -581,6 +581,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface /* the HD chain data model (external chain counters) */ CHDChain hdChain; + bool fFileBacked; public: /* * Main wallet lock. @@ -591,7 +592,6 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface */ mutable CCriticalSection cs_wallet; - bool fFileBacked; std::string strWalletFile; std::set setKeyPool; From 31d6b1d5f0414d8b356d8cb9c99961d8a04d6c0a Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 31 May 2016 13:05:52 -0400 Subject: [PATCH 0678/1802] net: Split resolving out of CNetAddr --- src/net.cpp | 11 ++- src/netbase.cpp | 26 +++---- src/netbase.h | 3 +- src/qt/rpcconsole.cpp | 5 +- src/rpc/net.cpp | 7 +- src/test/addrman_tests.cpp | 62 +++++++++------ src/test/net_tests.cpp | 4 +- src/test/netbase_tests.cpp | 154 ++++++++++++++++++++----------------- 8 files changed, 153 insertions(+), 119 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 4cbc43e4d8425..8725346fe89f3 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1396,8 +1396,11 @@ void ThreadMapPort() { if(externalIPAddress[0]) { - LogPrintf("UPnP: ExternalIPAddress = %s\n", externalIPAddress); - AddLocal(CNetAddr(externalIPAddress), LOCAL_UPNP); + CNetAddr resolved; + if(LookupHost(externalIPAddress, resolved, false)) { + LogPrintf("UPnP: ExternalIPAddress = %s\n", resolved.ToString().c_str()); + AddLocal(resolved, LOCAL_UPNP); + } } else LogPrintf("UPnP: GetExternalIPAddress failed.\n"); @@ -1623,7 +1626,9 @@ void ThreadOpenConnections() static bool done = false; if (!done) { LogPrintf("Adding fixed seed nodes as DNS doesn't seem to be available.\n"); - addrman.Add(convertSeed6(Params().FixedSeeds()), CNetAddr("127.0.0.1")); + CNetAddr local; + LookupHost("127.0.0.1", local, false); + addrman.Add(convertSeed6(Params().FixedSeeds()), local); done = true; } } diff --git a/src/netbase.cpp b/src/netbase.cpp index e2a516986c116..bb16dd0439cd2 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -195,6 +195,16 @@ bool LookupHost(const char *pszName, std::vector& vIP, unsigned int nM return LookupIntern(strHost.c_str(), vIP, nMaxSolutions, fAllowLookup); } +bool LookupHost(const char *pszName, CNetAddr& addr, bool fAllowLookup) +{ + std::vector vIP; + LookupHost(pszName, vIP, 1, fAllowLookup); + if(vIP.empty()) + return false; + addr = vIP.front(); + return true; +} + bool Lookup(const char *pszName, std::vector& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions) { if (pszName[0] == 0) @@ -695,22 +705,6 @@ CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr, const uint32_t scope) scopeId = scope; } -CNetAddr::CNetAddr(const char *pszIp) -{ - Init(); - std::vector vIP; - if (LookupHost(pszIp, vIP, 1, false)) - *this = vIP[0]; -} - -CNetAddr::CNetAddr(const std::string &strIp) -{ - Init(); - std::vector vIP; - if (LookupHost(strIp.c_str(), vIP, 1, false)) - *this = vIP[0]; -} - unsigned int CNetAddr::GetByte(int n) const { return ip[15-n]; diff --git a/src/netbase.h b/src/netbase.h index 65187a17cfd54..0deca02ca669a 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -49,8 +49,6 @@ class CNetAddr public: CNetAddr(); CNetAddr(const struct in_addr& ipv4Addr); - explicit CNetAddr(const char *pszIp); - explicit CNetAddr(const std::string &strIp); void Init(); void SetIP(const CNetAddr& ip); @@ -207,6 +205,7 @@ bool IsProxy(const CNetAddr &addr); bool SetNameProxy(const proxyType &addrProxy); bool HaveNameProxy(); bool LookupHost(const char *pszName, std::vector& vIP, unsigned int nMaxSolutions, bool fAllowLookup); +bool LookupHost(const char *pszName, CNetAddr& addr, bool fAllowLookup); bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLookup); bool Lookup(const char *pszName, std::vector& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions); bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0); diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 650ff8b00db84..e7df4f2dfafce 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -898,7 +898,10 @@ void RPCConsole::banSelectedNode(int bantime) int port = 0; SplitHostPort(nStr, port, addr); - CNode::Ban(CNetAddr(addr), BanReasonManuallyAdded, bantime); + CNetAddr resolved; + if(!LookupHost(addr.c_str(), resolved, false)) + return; + CNode::Ban(resolved, BanReasonManuallyAdded, bantime); clearSelectedNode(); clientModel->getBanTableModel()->refresh(); diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index b85c7b2e1aaa5..c23becd4a97de 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -494,8 +494,11 @@ UniValue setban(const UniValue& params, bool fHelp) if (params[0].get_str().find("/") != string::npos) isSubnet = true; - if (!isSubnet) - netAddr = CNetAddr(params[0].get_str()); + if (!isSubnet) { + CNetAddr resolved; + LookupHost(params[0].get_str().c_str(), resolved, false); + netAddr = resolved; + } else subNet = CSubNet(params[0].get_str()); diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp index b6cec24b5752a..fd9666f532e98 100644 --- a/src/test/addrman_tests.cpp +++ b/src/test/addrman_tests.cpp @@ -50,6 +50,18 @@ class CAddrManTest : public CAddrMan } }; +static CNetAddr ResolveIP(const char* ip) +{ + CNetAddr addr; + BOOST_CHECK_MESSAGE(LookupHost(ip, addr, false), strprintf("failed to resolve: %s", ip)); + return addr; +} + +static CNetAddr ResolveIP(std::string ip) +{ + return ResolveIP(ip.c_str()); +} + BOOST_FIXTURE_TEST_SUITE(addrman_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(addrman_simple) @@ -59,7 +71,7 @@ BOOST_AUTO_TEST_CASE(addrman_simple) // Set addrman addr placement to be deterministic. addrman.MakeDeterministic(); - CNetAddr source = CNetAddr("252.2.2.2"); + CNetAddr source = ResolveIP("252.2.2.2"); // Test 1: Does Addrman respond correctly when empty. BOOST_CHECK(addrman.size() == 0); @@ -100,7 +112,7 @@ BOOST_AUTO_TEST_CASE(addrman_ports) // Set addrman addr placement to be deterministic. addrman.MakeDeterministic(); - CNetAddr source = CNetAddr("252.2.2.2"); + CNetAddr source = ResolveIP("252.2.2.2"); BOOST_CHECK(addrman.size() == 0); @@ -132,7 +144,7 @@ BOOST_AUTO_TEST_CASE(addrman_select) // Set addrman addr placement to be deterministic. addrman.MakeDeterministic(); - CNetAddr source = CNetAddr("252.2.2.2"); + CNetAddr source = ResolveIP("252.2.2.2"); // Test 9: Select from new with 1 addr in new. CService addr1 = CService("250.1.1.1", 8333); @@ -160,20 +172,20 @@ BOOST_AUTO_TEST_CASE(addrman_select) CService addr3 = CService("250.3.2.2", 9999); CService addr4 = CService("250.3.3.3", 9999); - addrman.Add(CAddress(addr2, NODE_NONE), CService("250.3.1.1", 8333)); - addrman.Add(CAddress(addr3, NODE_NONE), CService("250.3.1.1", 8333)); - addrman.Add(CAddress(addr4, NODE_NONE), CService("250.4.1.1", 8333)); + addrman.Add(CAddress(addr2, NODE_NONE), CService("250.3.1.1", 8333), NODE_NONE); + addrman.Add(CAddress(addr3, NODE_NONE), CService("250.3.1.1", 8333), NODE_NONE); + addrman.Add(CAddress(addr4, NODE_NONE), CService("250.4.1.1", 8333), NODE_NONE); // Add three addresses to tried table. CService addr5 = CService("250.4.4.4", 8333); CService addr6 = CService("250.4.5.5", 7777); CService addr7 = CService("250.4.6.6", 8333); - addrman.Add(CAddress(addr5, NODE_NONE), CService("250.3.1.1", 8333)); + addrman.Add(CAddress(addr5, NODE_NONE), CService("250.3.1.1", 8333), NODE_NONE); addrman.Good(CAddress(addr5, NODE_NONE)); - addrman.Add(CAddress(addr6, NODE_NONE), CService("250.3.1.1", 8333)); + addrman.Add(CAddress(addr6, NODE_NONE), CService("250.3.1.1", 8333), NODE_NONE); addrman.Good(CAddress(addr6, NODE_NONE)); - addrman.Add(CAddress(addr7, NODE_NONE), CService("250.1.1.3", 8333)); + addrman.Add(CAddress(addr7, NODE_NONE), CService("250.1.1.3", 8333), NODE_NONE); addrman.Good(CAddress(addr7, NODE_NONE)); // Test 11: 6 addrs + 1 addr from last test = 7. @@ -193,7 +205,7 @@ BOOST_AUTO_TEST_CASE(addrman_new_collisions) // Set addrman addr placement to be deterministic. addrman.MakeDeterministic(); - CNetAddr source = CNetAddr("252.2.2.2"); + CNetAddr source = ResolveIP("252.2.2.2"); BOOST_CHECK(addrman.size() == 0); @@ -222,7 +234,7 @@ BOOST_AUTO_TEST_CASE(addrman_tried_collisions) // Set addrman addr placement to be deterministic. addrman.MakeDeterministic(); - CNetAddr source = CNetAddr("252.2.2.2"); + CNetAddr source = ResolveIP("252.2.2.2"); BOOST_CHECK(addrman.size() == 0); @@ -259,8 +271,8 @@ BOOST_AUTO_TEST_CASE(addrman_find) CAddress addr2 = CAddress(CService("250.1.2.1", 9999), NODE_NONE); CAddress addr3 = CAddress(CService("251.255.2.1", 8333), NODE_NONE); - CNetAddr source1 = CNetAddr("250.1.2.1"); - CNetAddr source2 = CNetAddr("250.1.2.2"); + CNetAddr source1 = ResolveIP("250.1.2.1"); + CNetAddr source2 = ResolveIP("250.1.2.2"); addrman.Add(addr1, source1); addrman.Add(addr2, source2); @@ -295,7 +307,7 @@ BOOST_AUTO_TEST_CASE(addrman_create) BOOST_CHECK(addrman.size() == 0); CAddress addr1 = CAddress(CService("250.1.2.1", 8333), NODE_NONE); - CNetAddr source1 = CNetAddr("250.1.2.1"); + CNetAddr source1 = ResolveIP("250.1.2.1"); int nId; CAddrInfo* pinfo = addrman.Create(addr1, source1, &nId); @@ -318,7 +330,7 @@ BOOST_AUTO_TEST_CASE(addrman_delete) BOOST_CHECK(addrman.size() == 0); CAddress addr1 = CAddress(CService("250.1.2.1", 8333), NODE_NONE); - CNetAddr source1 = CNetAddr("250.1.2.1"); + CNetAddr source1 = ResolveIP("250.1.2.1"); int nId; addrman.Create(addr1, source1, &nId); @@ -354,8 +366,8 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr) addr4.nTime = GetAdjustedTime(); CAddress addr5 = CAddress(CService("252.254.4.5", 8333), NODE_NONE); addr5.nTime = GetAdjustedTime(); - CNetAddr source1 = CNetAddr("250.1.2.1"); - CNetAddr source2 = CNetAddr("250.2.3.3"); + CNetAddr source1 = ResolveIP("250.1.2.1"); + CNetAddr source2 = ResolveIP("250.2.3.3"); // Test 23: Ensure GetAddr works with new addresses. addrman.Add(addr1, source1); @@ -382,7 +394,7 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr) // Ensure that for all addrs in addrman, isTerrible == false. addr.nTime = GetAdjustedTime(); - addrman.Add(addr, CNetAddr(strAddr)); + addrman.Add(addr, ResolveIP(strAddr)); if (i % 8 == 0) addrman.Good(addr); } @@ -406,7 +418,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket) CAddress addr1 = CAddress(CService("250.1.1.1", 8333), NODE_NONE); CAddress addr2 = CAddress(CService("250.1.1.1", 9999), NODE_NONE); - CNetAddr source1 = CNetAddr("250.1.1.1"); + CNetAddr source1 = ResolveIP("250.1.1.1"); CAddrInfo info1 = CAddrInfo(addr1, source1); @@ -432,7 +444,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket) for (int i = 0; i < 255; i++) { CAddrInfo infoi = CAddrInfo( CAddress(CService("250.1.1." + boost::to_string(i)), NODE_NONE), - CNetAddr("250.1.1." + boost::to_string(i))); + ResolveIP("250.1.1." + boost::to_string(i))); int bucket = infoi.GetTriedBucket(nKey1); buckets.insert(bucket); } @@ -444,7 +456,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket) for (int j = 0; j < 255; j++) { CAddrInfo infoj = CAddrInfo( CAddress(CService("250." + boost::to_string(j) + ".1.1"), NODE_NONE), - CNetAddr("250." + boost::to_string(j) + ".1.1")); + ResolveIP("250." + boost::to_string(j) + ".1.1")); int bucket = infoj.GetTriedBucket(nKey1); buckets.insert(bucket); } @@ -463,7 +475,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket) CAddress addr1 = CAddress(CService("250.1.2.1", 8333), NODE_NONE); CAddress addr2 = CAddress(CService("250.1.2.1", 9999), NODE_NONE); - CNetAddr source1 = CNetAddr("250.1.2.1"); + CNetAddr source1 = ResolveIP("250.1.2.1"); CAddrInfo info1 = CAddrInfo(addr1, source1); @@ -485,7 +497,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket) for (int i = 0; i < 255; i++) { CAddrInfo infoi = CAddrInfo( CAddress(CService("250.1.1." + boost::to_string(i)), NODE_NONE), - CNetAddr("250.1.1." + boost::to_string(i))); + ResolveIP("250.1.1." + boost::to_string(i))); int bucket = infoi.GetNewBucket(nKey1); buckets.insert(bucket); } @@ -498,7 +510,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket) CAddrInfo infoj = CAddrInfo(CAddress( CService( boost::to_string(250 + (j / 255)) + "." + boost::to_string(j % 256) + ".1.1"), NODE_NONE), - CNetAddr("251.4.1.1")); + ResolveIP("251.4.1.1")); int bucket = infoj.GetNewBucket(nKey1); buckets.insert(bucket); } @@ -510,7 +522,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket) for (int p = 0; p < 255; p++) { CAddrInfo infoj = CAddrInfo( CAddress(CService("250.1.1.1"), NODE_NONE), - CNetAddr("250." + boost::to_string(p) + ".1.1")); + ResolveIP("250." + boost::to_string(p) + ".1.1")); int bucket = infoj.GetNewBucket(nKey1); buckets.insert(bucket); } diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index d005d6a1633e9..511073499e245 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -52,7 +52,9 @@ class CAddrManCorrupted : public CAddrManSerializationMock s << nUBuckets; CAddress addr = CAddress(CService("252.1.1.1", 7777), NODE_NONE); - CAddrInfo info = CAddrInfo(addr, CNetAddr("252.2.2.2")); + CNetAddr resolved; + LookupHost("252.2.2.2", resolved, false); + CAddrInfo info = CAddrInfo(addr, resolved); s << info; } }; diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index 4168f75e9a420..556c64f2297fa 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -14,37 +14,47 @@ using namespace std; BOOST_FIXTURE_TEST_SUITE(netbase_tests, BasicTestingSetup) +static CNetAddr ResolveIP(const char* ip) +{ + CNetAddr addr; + LookupHost(ip, addr, false); + return addr; +} + BOOST_AUTO_TEST_CASE(netbase_networks) { - BOOST_CHECK(CNetAddr("127.0.0.1").GetNetwork() == NET_UNROUTABLE); - BOOST_CHECK(CNetAddr("::1").GetNetwork() == NET_UNROUTABLE); - BOOST_CHECK(CNetAddr("8.8.8.8").GetNetwork() == NET_IPV4); - BOOST_CHECK(CNetAddr("2001::8888").GetNetwork() == NET_IPV6); - BOOST_CHECK(CNetAddr("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetNetwork() == NET_TOR); + BOOST_CHECK(ResolveIP("127.0.0.1").GetNetwork() == NET_UNROUTABLE); + BOOST_CHECK(ResolveIP("::1").GetNetwork() == NET_UNROUTABLE); + BOOST_CHECK(ResolveIP("8.8.8.8").GetNetwork() == NET_IPV4); + BOOST_CHECK(ResolveIP("2001::8888").GetNetwork() == NET_IPV6); + BOOST_CHECK(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetNetwork() == NET_TOR); + } BOOST_AUTO_TEST_CASE(netbase_properties) { - BOOST_CHECK(CNetAddr("127.0.0.1").IsIPv4()); - BOOST_CHECK(CNetAddr("::FFFF:192.168.1.1").IsIPv4()); - BOOST_CHECK(CNetAddr("::1").IsIPv6()); - BOOST_CHECK(CNetAddr("10.0.0.1").IsRFC1918()); - BOOST_CHECK(CNetAddr("192.168.1.1").IsRFC1918()); - BOOST_CHECK(CNetAddr("172.31.255.255").IsRFC1918()); - BOOST_CHECK(CNetAddr("2001:0DB8::").IsRFC3849()); - BOOST_CHECK(CNetAddr("169.254.1.1").IsRFC3927()); - BOOST_CHECK(CNetAddr("2002::1").IsRFC3964()); - BOOST_CHECK(CNetAddr("FC00::").IsRFC4193()); - BOOST_CHECK(CNetAddr("2001::2").IsRFC4380()); - BOOST_CHECK(CNetAddr("2001:10::").IsRFC4843()); - BOOST_CHECK(CNetAddr("FE80::").IsRFC4862()); - BOOST_CHECK(CNetAddr("64:FF9B::").IsRFC6052()); - BOOST_CHECK(CNetAddr("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").IsTor()); - BOOST_CHECK(CNetAddr("127.0.0.1").IsLocal()); - BOOST_CHECK(CNetAddr("::1").IsLocal()); - BOOST_CHECK(CNetAddr("8.8.8.8").IsRoutable()); - BOOST_CHECK(CNetAddr("2001::1").IsRoutable()); - BOOST_CHECK(CNetAddr("127.0.0.1").IsValid()); + + BOOST_CHECK(ResolveIP("127.0.0.1").IsIPv4()); + BOOST_CHECK(ResolveIP("::FFFF:192.168.1.1").IsIPv4()); + BOOST_CHECK(ResolveIP("::1").IsIPv6()); + BOOST_CHECK(ResolveIP("10.0.0.1").IsRFC1918()); + BOOST_CHECK(ResolveIP("192.168.1.1").IsRFC1918()); + BOOST_CHECK(ResolveIP("172.31.255.255").IsRFC1918()); + BOOST_CHECK(ResolveIP("2001:0DB8::").IsRFC3849()); + BOOST_CHECK(ResolveIP("169.254.1.1").IsRFC3927()); + BOOST_CHECK(ResolveIP("2002::1").IsRFC3964()); + BOOST_CHECK(ResolveIP("FC00::").IsRFC4193()); + BOOST_CHECK(ResolveIP("2001::2").IsRFC4380()); + BOOST_CHECK(ResolveIP("2001:10::").IsRFC4843()); + BOOST_CHECK(ResolveIP("FE80::").IsRFC4862()); + BOOST_CHECK(ResolveIP("64:FF9B::").IsRFC6052()); + BOOST_CHECK(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").IsTor()); + BOOST_CHECK(ResolveIP("127.0.0.1").IsLocal()); + BOOST_CHECK(ResolveIP("::1").IsLocal()); + BOOST_CHECK(ResolveIP("8.8.8.8").IsRoutable()); + BOOST_CHECK(ResolveIP("2001::1").IsRoutable()); + BOOST_CHECK(ResolveIP("127.0.0.1").IsValid()); + } bool static TestSplitHost(string test, string host, int port) @@ -95,44 +105,47 @@ BOOST_AUTO_TEST_CASE(netbase_lookupnumeric) BOOST_AUTO_TEST_CASE(onioncat_test) { + // values from https://web.archive.org/web/20121122003543/http://www.cypherpunk.at/onioncat/wiki/OnionCat - CNetAddr addr1("5wyqrzbvrdsumnok.onion"); - CNetAddr addr2("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca"); + CNetAddr addr1(ResolveIP("5wyqrzbvrdsumnok.onion")); + CNetAddr addr2(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca")); BOOST_CHECK(addr1 == addr2); BOOST_CHECK(addr1.IsTor()); BOOST_CHECK(addr1.ToStringIP() == "5wyqrzbvrdsumnok.onion"); BOOST_CHECK(addr1.IsRoutable()); + } BOOST_AUTO_TEST_CASE(subnet_test) { + BOOST_CHECK(CSubNet("1.2.3.0/24") == CSubNet("1.2.3.0/255.255.255.0")); BOOST_CHECK(CSubNet("1.2.3.0/24") != CSubNet("1.2.4.0/255.255.255.0")); - BOOST_CHECK(CSubNet("1.2.3.0/24").Match(CNetAddr("1.2.3.4"))); - BOOST_CHECK(!CSubNet("1.2.2.0/24").Match(CNetAddr("1.2.3.4"))); - BOOST_CHECK(CSubNet("1.2.3.4").Match(CNetAddr("1.2.3.4"))); - BOOST_CHECK(CSubNet("1.2.3.4/32").Match(CNetAddr("1.2.3.4"))); - BOOST_CHECK(!CSubNet("1.2.3.4").Match(CNetAddr("5.6.7.8"))); - BOOST_CHECK(!CSubNet("1.2.3.4/32").Match(CNetAddr("5.6.7.8"))); - BOOST_CHECK(CSubNet("::ffff:127.0.0.1").Match(CNetAddr("127.0.0.1"))); - BOOST_CHECK(CSubNet("1:2:3:4:5:6:7:8").Match(CNetAddr("1:2:3:4:5:6:7:8"))); - BOOST_CHECK(!CSubNet("1:2:3:4:5:6:7:8").Match(CNetAddr("1:2:3:4:5:6:7:9"))); - BOOST_CHECK(CSubNet("1:2:3:4:5:6:7:0/112").Match(CNetAddr("1:2:3:4:5:6:7:1234"))); - BOOST_CHECK(CSubNet("192.168.0.1/24").Match(CNetAddr("192.168.0.2"))); - BOOST_CHECK(CSubNet("192.168.0.20/29").Match(CNetAddr("192.168.0.18"))); - BOOST_CHECK(CSubNet("1.2.2.1/24").Match(CNetAddr("1.2.2.4"))); - BOOST_CHECK(CSubNet("1.2.2.110/31").Match(CNetAddr("1.2.2.111"))); - BOOST_CHECK(CSubNet("1.2.2.20/26").Match(CNetAddr("1.2.2.63"))); + BOOST_CHECK(CSubNet("1.2.3.0/24").Match(ResolveIP("1.2.3.4"))); + BOOST_CHECK(!CSubNet("1.2.2.0/24").Match(ResolveIP("1.2.3.4"))); + BOOST_CHECK(CSubNet("1.2.3.4").Match(ResolveIP("1.2.3.4"))); + BOOST_CHECK(CSubNet("1.2.3.4/32").Match(ResolveIP("1.2.3.4"))); + BOOST_CHECK(!CSubNet("1.2.3.4").Match(ResolveIP("5.6.7.8"))); + BOOST_CHECK(!CSubNet("1.2.3.4/32").Match(ResolveIP("5.6.7.8"))); + BOOST_CHECK(CSubNet("::ffff:127.0.0.1").Match(ResolveIP("127.0.0.1"))); + BOOST_CHECK(CSubNet("1:2:3:4:5:6:7:8").Match(ResolveIP("1:2:3:4:5:6:7:8"))); + BOOST_CHECK(!CSubNet("1:2:3:4:5:6:7:8").Match(ResolveIP("1:2:3:4:5:6:7:9"))); + BOOST_CHECK(CSubNet("1:2:3:4:5:6:7:0/112").Match(ResolveIP("1:2:3:4:5:6:7:1234"))); + BOOST_CHECK(CSubNet("192.168.0.1/24").Match(ResolveIP("192.168.0.2"))); + BOOST_CHECK(CSubNet("192.168.0.20/29").Match(ResolveIP("192.168.0.18"))); + BOOST_CHECK(CSubNet("1.2.2.1/24").Match(ResolveIP("1.2.2.4"))); + BOOST_CHECK(CSubNet("1.2.2.110/31").Match(ResolveIP("1.2.2.111"))); + BOOST_CHECK(CSubNet("1.2.2.20/26").Match(ResolveIP("1.2.2.63"))); // All-Matching IPv6 Matches arbitrary IPv4 and IPv6 - BOOST_CHECK(CSubNet("::/0").Match(CNetAddr("1:2:3:4:5:6:7:1234"))); - BOOST_CHECK(CSubNet("::/0").Match(CNetAddr("1.2.3.4"))); + BOOST_CHECK(CSubNet("::/0").Match(ResolveIP("1:2:3:4:5:6:7:1234"))); + BOOST_CHECK(CSubNet("::/0").Match(ResolveIP("1.2.3.4"))); // All-Matching IPv4 does not Match IPv6 - BOOST_CHECK(!CSubNet("0.0.0.0/0").Match(CNetAddr("1:2:3:4:5:6:7:1234"))); + BOOST_CHECK(!CSubNet("0.0.0.0/0").Match(ResolveIP("1:2:3:4:5:6:7:1234"))); // Invalid subnets Match nothing (not even invalid addresses) - BOOST_CHECK(!CSubNet().Match(CNetAddr("1.2.3.4"))); - BOOST_CHECK(!CSubNet("").Match(CNetAddr("4.5.6.7"))); - BOOST_CHECK(!CSubNet("bloop").Match(CNetAddr("0.0.0.0"))); - BOOST_CHECK(!CSubNet("bloop").Match(CNetAddr("hab"))); + BOOST_CHECK(!CSubNet().Match(ResolveIP("1.2.3.4"))); + BOOST_CHECK(!CSubNet("").Match(ResolveIP("4.5.6.7"))); + BOOST_CHECK(!CSubNet("bloop").Match(ResolveIP("0.0.0.0"))); + BOOST_CHECK(!CSubNet("bloop").Match(ResolveIP("hab"))); // Check valid/invalid BOOST_CHECK(CSubNet("1.2.3.0/0").IsValid()); BOOST_CHECK(!CSubNet("1.2.3.0/-1").IsValid()); @@ -146,15 +159,15 @@ BOOST_AUTO_TEST_CASE(subnet_test) BOOST_CHECK(!CSubNet("fuzzy").IsValid()); //CNetAddr constructor test - BOOST_CHECK(CSubNet(CNetAddr("127.0.0.1")).IsValid()); - BOOST_CHECK(CSubNet(CNetAddr("127.0.0.1")).Match(CNetAddr("127.0.0.1"))); - BOOST_CHECK(!CSubNet(CNetAddr("127.0.0.1")).Match(CNetAddr("127.0.0.2"))); - BOOST_CHECK(CSubNet(CNetAddr("127.0.0.1")).ToString() == "127.0.0.1/32"); + BOOST_CHECK(CSubNet(ResolveIP("127.0.0.1")).IsValid()); + BOOST_CHECK(CSubNet(ResolveIP("127.0.0.1")).Match(ResolveIP("127.0.0.1"))); + BOOST_CHECK(!CSubNet(ResolveIP("127.0.0.1")).Match(ResolveIP("127.0.0.2"))); + BOOST_CHECK(CSubNet(ResolveIP("127.0.0.1")).ToString() == "127.0.0.1/32"); - BOOST_CHECK(CSubNet(CNetAddr("1:2:3:4:5:6:7:8")).IsValid()); - BOOST_CHECK(CSubNet(CNetAddr("1:2:3:4:5:6:7:8")).Match(CNetAddr("1:2:3:4:5:6:7:8"))); - BOOST_CHECK(!CSubNet(CNetAddr("1:2:3:4:5:6:7:8")).Match(CNetAddr("1:2:3:4:5:6:7:9"))); - BOOST_CHECK(CSubNet(CNetAddr("1:2:3:4:5:6:7:8")).ToString() == "1:2:3:4:5:6:7:8/128"); + BOOST_CHECK(CSubNet(ResolveIP("1:2:3:4:5:6:7:8")).IsValid()); + BOOST_CHECK(CSubNet(ResolveIP("1:2:3:4:5:6:7:8")).Match(ResolveIP("1:2:3:4:5:6:7:8"))); + BOOST_CHECK(!CSubNet(ResolveIP("1:2:3:4:5:6:7:8")).Match(ResolveIP("1:2:3:4:5:6:7:9"))); + BOOST_CHECK(CSubNet(ResolveIP("1:2:3:4:5:6:7:8")).ToString() == "1:2:3:4:5:6:7:8/128"); CSubNet subnet = CSubNet("1.2.3.4/255.255.255.255"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/32"); @@ -233,22 +246,25 @@ BOOST_AUTO_TEST_CASE(subnet_test) BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/255.255.232.0"); subnet = CSubNet("1:2:3:4:5:6:7:8/ffff:ffff:ffff:fffe:ffff:ffff:ffff:ff0f"); BOOST_CHECK_EQUAL(subnet.ToString(), "1:2:3:4:5:6:7:8/ffff:ffff:ffff:fffe:ffff:ffff:ffff:ff0f"); + } BOOST_AUTO_TEST_CASE(netbase_getgroup) { - BOOST_CHECK(CNetAddr("127.0.0.1").GetGroup() == boost::assign::list_of(0)); // Local -> !Routable() - BOOST_CHECK(CNetAddr("257.0.0.1").GetGroup() == boost::assign::list_of(0)); // !Valid -> !Routable() - BOOST_CHECK(CNetAddr("10.0.0.1").GetGroup() == boost::assign::list_of(0)); // RFC1918 -> !Routable() - BOOST_CHECK(CNetAddr("169.254.1.1").GetGroup() == boost::assign::list_of(0)); // RFC3927 -> !Routable() - BOOST_CHECK(CNetAddr("1.2.3.4").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // IPv4 - BOOST_CHECK(CNetAddr("::FFFF:0:102:304").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC6145 - BOOST_CHECK(CNetAddr("64:FF9B::102:304").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC6052 - BOOST_CHECK(CNetAddr("2002:102:304:9999:9999:9999:9999:9999").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC3964 - BOOST_CHECK(CNetAddr("2001:0:9999:9999:9999:9999:FEFD:FCFB").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC4380 - BOOST_CHECK(CNetAddr("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetGroup() == boost::assign::list_of((unsigned char)NET_TOR)(239)); // Tor - BOOST_CHECK(CNetAddr("2001:470:abcd:9999:9999:9999:9999:9999").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV6)(32)(1)(4)(112)(175)); //he.net - BOOST_CHECK(CNetAddr("2001:2001:9999:9999:9999:9999:9999:9999").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV6)(32)(1)(32)(1)); //IPv6 + + BOOST_CHECK(ResolveIP("127.0.0.1").GetGroup() == boost::assign::list_of(0)); // Local -> !Routable() + BOOST_CHECK(ResolveIP("257.0.0.1").GetGroup() == boost::assign::list_of(0)); // !Valid -> !Routable() + BOOST_CHECK(ResolveIP("10.0.0.1").GetGroup() == boost::assign::list_of(0)); // RFC1918 -> !Routable() + BOOST_CHECK(ResolveIP("169.254.1.1").GetGroup() == boost::assign::list_of(0)); // RFC3927 -> !Routable() + BOOST_CHECK(ResolveIP("1.2.3.4").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // IPv4 + BOOST_CHECK(ResolveIP("::FFFF:0:102:304").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC6145 + BOOST_CHECK(ResolveIP("64:FF9B::102:304").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC6052 + BOOST_CHECK(ResolveIP("2002:102:304:9999:9999:9999:9999:9999").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC3964 + BOOST_CHECK(ResolveIP("2001:0:9999:9999:9999:9999:FEFD:FCFB").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC4380 + BOOST_CHECK(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetGroup() == boost::assign::list_of((unsigned char)NET_TOR)(239)); // Tor + BOOST_CHECK(ResolveIP("2001:470:abcd:9999:9999:9999:9999:9999").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV6)(32)(1)(4)(112)(175)); //he.net + BOOST_CHECK(ResolveIP("2001:2001:9999:9999:9999:9999:9999:9999").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV6)(32)(1)(32)(1)); //IPv6 + } BOOST_AUTO_TEST_SUITE_END() From f96c7c4d91f3c09d26658bc9c15aa561689fa2d4 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 31 May 2016 13:51:11 -0400 Subject: [PATCH 0679/1802] net: Split resolving out of CService --- src/httpserver.cpp | 2 +- src/init.cpp | 8 ++- src/net.cpp | 17 ++++--- src/netbase.cpp | 34 +------------ src/netbase.h | 4 -- src/qt/optionsdialog.cpp | 4 +- src/test/addrman_tests.cpp | 100 +++++++++++++++++++++---------------- src/test/net_tests.cpp | 19 ++++--- src/torcontrol.cpp | 7 +-- 9 files changed, 94 insertions(+), 101 deletions(-) diff --git a/src/httpserver.cpp b/src/httpserver.cpp index be7a6a1ddee86..57aa134b38fc3 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -614,7 +614,7 @@ CService HTTPRequest::GetPeer() const char* address = ""; uint16_t port = 0; evhttp_connection_get_peer(con, (char**)&address, &port); - peer = CService(address, port); + LookupNumeric(address, peer, port); } return peer; } diff --git a/src/init.cpp b/src/init.cpp index 8d4a2cafbfbb1..77ecf05f1db90 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1096,7 +1096,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) std::string proxyArg = GetArg("-proxy", ""); SetLimited(NET_TOR); if (proxyArg != "" && proxyArg != "0") { - proxyType addrProxy = proxyType(CService(proxyArg, 9050), proxyRandomize); + CService resolved; + LookupNumeric(proxyArg.c_str(), resolved, 9050); + proxyType addrProxy = proxyType(resolved, proxyRandomize); if (!addrProxy.IsValid()) return InitError(strprintf(_("Invalid -proxy address: '%s'"), proxyArg)); @@ -1115,7 +1117,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (onionArg == "0") { // Handle -noonion/-onion=0 SetLimited(NET_TOR); // set onions as unreachable } else { - proxyType addrOnion = proxyType(CService(onionArg, 9050), proxyRandomize); + CService resolved; + LookupNumeric(onionArg.c_str(), resolved, 9050); + proxyType addrOnion = proxyType(resolved, proxyRandomize); if (!addrOnion.IsValid()) return InitError(strprintf(_("Invalid -onion address: '%s'"), onionArg)); SetProxy(NET_TOR, addrOnion); diff --git a/src/net.cpp b/src/net.cpp index 8725346fe89f3..e44bdafc79889 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -175,7 +175,7 @@ static std::vector convertSeed6(const std::vector &vSeedsIn // one by discovery. CAddress GetLocalAddress(const CNetAddr *paddrPeer) { - CAddress ret(CService("0.0.0.0",GetListenPort()), NODE_NONE); + CAddress ret(CService(CNetAddr(),GetListenPort()), NODE_NONE); CService addr; if (GetLocal(addr, paddrPeer)) { @@ -494,7 +494,7 @@ void CNode::PushVersion() int nBestHeight = GetNodeSignals().GetHeight().get_value_or(0); int64_t nTime = (fInbound ? GetAdjustedTime() : GetTime()); - CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0", 0), addr.nServices)); + CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService(), addr.nServices)); CAddress addrMe = GetLocalAddress(&addr); GetRandBytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce)); if (fLogIPs) @@ -1727,7 +1727,8 @@ std::vector GetAddedNodeInfo() } BOOST_FOREACH(const std::string& strAddNode, lAddresses) { - CService service(strAddNode, Params().GetDefaultPort()); + CService service; + LookupNumeric(strAddNode.c_str(), service, Params().GetDefaultPort()); if (service.IsValid()) { // strAddNode is an IP:port auto it = mapConnected.find(service); @@ -1765,7 +1766,8 @@ void ThreadOpenAddedConnections() CSemaphoreGrant grant(*semOutbound); // If strAddedNode is an IP/port, decode it immediately, so // OpenNetworkConnection can detect existing connections to that IP/port. - CService service(info.strAddedNode, Params().GetDefaultPort()); + CService service; + LookupNumeric(info.strAddedNode.c_str(), service, Params().GetDefaultPort()); OpenNetworkConnection(CAddress(service, NODE_NONE), false, &grant, info.strAddedNode.c_str(), false); MilliSleep(500); } @@ -2063,8 +2065,11 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler) semOutbound = new CSemaphore(nMaxOutbound); } - if (pnodeLocalHost == NULL) - pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices)); + if (pnodeLocalHost == NULL) { + CNetAddr local; + LookupHost("127.0.0.1", local, false); + pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService(local, 0), nLocalServices)); + } Discover(threadGroup); diff --git a/src/netbase.cpp b/src/netbase.cpp index bb16dd0439cd2..2e7a4f758a39e 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -639,7 +639,7 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest } } - addr = CService("0.0.0.0:0"); + addr = CService(); if (!HaveNameProxy()) return false; @@ -1124,38 +1124,6 @@ bool CService::SetSockAddr(const struct sockaddr *paddr) } } -CService::CService(const char *pszIpPort) -{ - Init(); - CService ip; - if (Lookup(pszIpPort, ip, 0, false)) - *this = ip; -} - -CService::CService(const char *pszIpPort, int portDefault) -{ - Init(); - CService ip; - if (Lookup(pszIpPort, ip, portDefault, false)) - *this = ip; -} - -CService::CService(const std::string &strIpPort) -{ - Init(); - CService ip; - if (Lookup(strIpPort.c_str(), ip, 0, false)) - *this = ip; -} - -CService::CService(const std::string &strIpPort, int portDefault) -{ - Init(); - CService ip; - if (Lookup(strIpPort.c_str(), ip, portDefault, false)) - *this = ip; -} - unsigned short CService::GetPort() const { return port; diff --git a/src/netbase.h b/src/netbase.h index 0deca02ca669a..97b96f69cc55e 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -152,10 +152,6 @@ class CService : public CNetAddr CService(const CNetAddr& ip, unsigned short port); CService(const struct in_addr& ipv4Addr, unsigned short port); CService(const struct sockaddr_in& addr); - explicit CService(const char *pszIpPort, int portDefault); - explicit CService(const char *pszIpPort); - explicit CService(const std::string& strIpPort, int portDefault); - explicit CService(const std::string& strIpPort); void Init(); void SetPort(unsigned short portIn); unsigned short GetPort() const; diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index f2db3988991a0..e419e4d9ee579 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -327,7 +327,9 @@ QValidator::State ProxyAddressValidator::validate(QString &input, int &pos) cons { Q_UNUSED(pos); // Validate the proxy - proxyType addrProxy = proxyType(CService(input.toStdString(), 9050), true); + CService serv; + LookupNumeric(input.toStdString().c_str(), serv, 9050); + proxyType addrProxy = proxyType(serv, true); if (addrProxy.IsValid()) return QValidator::Acceptable; diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp index fd9666f532e98..b84d00856bd66 100644 --- a/src/test/addrman_tests.cpp +++ b/src/test/addrman_tests.cpp @@ -62,6 +62,18 @@ static CNetAddr ResolveIP(std::string ip) return ResolveIP(ip.c_str()); } +static CService ResolveService(const char* ip, int port = 0) +{ + CService serv; + BOOST_CHECK_MESSAGE(Lookup(ip, serv, port, false), strprintf("failed to resolve: %s:%i", ip, port)); + return serv; +} + +static CService ResolveService(std::string ip, int port = 0) +{ + return ResolveService(ip.c_str(), port); +} + BOOST_FIXTURE_TEST_SUITE(addrman_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(addrman_simple) @@ -79,7 +91,7 @@ BOOST_AUTO_TEST_CASE(addrman_simple) BOOST_CHECK(addr_null.ToString() == "[::]:0"); // Test 2: Does Addrman::Add work as expected. - CService addr1 = CService("250.1.1.1", 8333); + CService addr1 = ResolveService("250.1.1.1", 8333); addrman.Add(CAddress(addr1, NODE_NONE), source); BOOST_CHECK(addrman.size() == 1); CAddrInfo addr_ret1 = addrman.Select(); @@ -87,14 +99,14 @@ BOOST_AUTO_TEST_CASE(addrman_simple) // Test 3: Does IP address deduplication work correctly. // Expected dup IP should not be added. - CService addr1_dup = CService("250.1.1.1", 8333); + CService addr1_dup = ResolveService("250.1.1.1", 8333); addrman.Add(CAddress(addr1_dup, NODE_NONE), source); BOOST_CHECK(addrman.size() == 1); // Test 5: New table has one addr and we add a diff addr we should // have two addrs. - CService addr2 = CService("250.1.1.2", 8333); + CService addr2 = ResolveService("250.1.1.2", 8333); addrman.Add(CAddress(addr2, NODE_NONE), source); BOOST_CHECK(addrman.size() == 2); @@ -117,11 +129,11 @@ BOOST_AUTO_TEST_CASE(addrman_ports) BOOST_CHECK(addrman.size() == 0); // Test 7; Addr with same IP but diff port does not replace existing addr. - CService addr1 = CService("250.1.1.1", 8333); + CService addr1 = ResolveService("250.1.1.1", 8333); addrman.Add(CAddress(addr1, NODE_NONE), source); BOOST_CHECK(addrman.size() == 1); - CService addr1_port = CService("250.1.1.1", 8334); + CService addr1_port = ResolveService("250.1.1.1", 8334); addrman.Add(CAddress(addr1_port, NODE_NONE), source); BOOST_CHECK(addrman.size() == 1); CAddrInfo addr_ret2 = addrman.Select(); @@ -147,7 +159,7 @@ BOOST_AUTO_TEST_CASE(addrman_select) CNetAddr source = ResolveIP("252.2.2.2"); // Test 9: Select from new with 1 addr in new. - CService addr1 = CService("250.1.1.1", 8333); + CService addr1 = ResolveService("250.1.1.1", 8333); addrman.Add(CAddress(addr1, NODE_NONE), source); BOOST_CHECK(addrman.size() == 1); @@ -168,24 +180,24 @@ BOOST_AUTO_TEST_CASE(addrman_select) // Add three addresses to new table. - CService addr2 = CService("250.3.1.1", 8333); - CService addr3 = CService("250.3.2.2", 9999); - CService addr4 = CService("250.3.3.3", 9999); + CService addr2 = ResolveService("250.3.1.1", 8333); + CService addr3 = ResolveService("250.3.2.2", 9999); + CService addr4 = ResolveService("250.3.3.3", 9999); - addrman.Add(CAddress(addr2, NODE_NONE), CService("250.3.1.1", 8333), NODE_NONE); - addrman.Add(CAddress(addr3, NODE_NONE), CService("250.3.1.1", 8333), NODE_NONE); - addrman.Add(CAddress(addr4, NODE_NONE), CService("250.4.1.1", 8333), NODE_NONE); + addrman.Add(CAddress(addr2, NODE_NONE), ResolveService("250.3.1.1", 8333)); + addrman.Add(CAddress(addr3, NODE_NONE), ResolveService("250.3.1.1", 8333)); + addrman.Add(CAddress(addr4, NODE_NONE), ResolveService("250.4.1.1", 8333)); // Add three addresses to tried table. - CService addr5 = CService("250.4.4.4", 8333); - CService addr6 = CService("250.4.5.5", 7777); - CService addr7 = CService("250.4.6.6", 8333); + CService addr5 = ResolveService("250.4.4.4", 8333); + CService addr6 = ResolveService("250.4.5.5", 7777); + CService addr7 = ResolveService("250.4.6.6", 8333); - addrman.Add(CAddress(addr5, NODE_NONE), CService("250.3.1.1", 8333), NODE_NONE); + addrman.Add(CAddress(addr5, NODE_NONE), ResolveService("250.3.1.1", 8333)); addrman.Good(CAddress(addr5, NODE_NONE)); - addrman.Add(CAddress(addr6, NODE_NONE), CService("250.3.1.1", 8333), NODE_NONE); + addrman.Add(CAddress(addr6, NODE_NONE), ResolveService("250.3.1.1", 8333)); addrman.Good(CAddress(addr6, NODE_NONE)); - addrman.Add(CAddress(addr7, NODE_NONE), CService("250.1.1.3", 8333), NODE_NONE); + addrman.Add(CAddress(addr7, NODE_NONE), ResolveService("250.1.1.3", 8333)); addrman.Good(CAddress(addr7, NODE_NONE)); // Test 11: 6 addrs + 1 addr from last test = 7. @@ -210,7 +222,7 @@ BOOST_AUTO_TEST_CASE(addrman_new_collisions) BOOST_CHECK(addrman.size() == 0); for (unsigned int i = 1; i < 18; i++) { - CService addr = CService("250.1.1." + boost::to_string(i)); + CService addr = ResolveService("250.1.1." + boost::to_string(i)); addrman.Add(CAddress(addr, NODE_NONE), source); //Test 13: No collision in new table yet. @@ -218,11 +230,11 @@ BOOST_AUTO_TEST_CASE(addrman_new_collisions) } //Test 14: new table collision! - CService addr1 = CService("250.1.1.18"); + CService addr1 = ResolveService("250.1.1.18"); addrman.Add(CAddress(addr1, NODE_NONE), source); BOOST_CHECK(addrman.size() == 17); - CService addr2 = CService("250.1.1.19"); + CService addr2 = ResolveService("250.1.1.19"); addrman.Add(CAddress(addr2, NODE_NONE), source); BOOST_CHECK(addrman.size() == 18); } @@ -239,7 +251,7 @@ BOOST_AUTO_TEST_CASE(addrman_tried_collisions) BOOST_CHECK(addrman.size() == 0); for (unsigned int i = 1; i < 80; i++) { - CService addr = CService("250.1.1." + boost::to_string(i)); + CService addr = ResolveService("250.1.1." + boost::to_string(i)); addrman.Add(CAddress(addr, NODE_NONE), source); addrman.Good(CAddress(addr, NODE_NONE)); @@ -249,11 +261,11 @@ BOOST_AUTO_TEST_CASE(addrman_tried_collisions) } //Test 16: tried table collision! - CService addr1 = CService("250.1.1.80"); + CService addr1 = ResolveService("250.1.1.80"); addrman.Add(CAddress(addr1, NODE_NONE), source); BOOST_CHECK(addrman.size() == 79); - CService addr2 = CService("250.1.1.81"); + CService addr2 = ResolveService("250.1.1.81"); addrman.Add(CAddress(addr2, NODE_NONE), source); BOOST_CHECK(addrman.size() == 80); } @@ -267,9 +279,9 @@ BOOST_AUTO_TEST_CASE(addrman_find) BOOST_CHECK(addrman.size() == 0); - CAddress addr1 = CAddress(CService("250.1.2.1", 8333), NODE_NONE); - CAddress addr2 = CAddress(CService("250.1.2.1", 9999), NODE_NONE); - CAddress addr3 = CAddress(CService("251.255.2.1", 8333), NODE_NONE); + CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE); + CAddress addr2 = CAddress(ResolveService("250.1.2.1", 9999), NODE_NONE); + CAddress addr3 = CAddress(ResolveService("251.255.2.1", 8333), NODE_NONE); CNetAddr source1 = ResolveIP("250.1.2.1"); CNetAddr source2 = ResolveIP("250.1.2.2"); @@ -306,7 +318,7 @@ BOOST_AUTO_TEST_CASE(addrman_create) BOOST_CHECK(addrman.size() == 0); - CAddress addr1 = CAddress(CService("250.1.2.1", 8333), NODE_NONE); + CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE); CNetAddr source1 = ResolveIP("250.1.2.1"); int nId; @@ -329,7 +341,7 @@ BOOST_AUTO_TEST_CASE(addrman_delete) BOOST_CHECK(addrman.size() == 0); - CAddress addr1 = CAddress(CService("250.1.2.1", 8333), NODE_NONE); + CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE); CNetAddr source1 = ResolveIP("250.1.2.1"); int nId; @@ -356,15 +368,15 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr) vector vAddr1 = addrman.GetAddr(); BOOST_CHECK(vAddr1.size() == 0); - CAddress addr1 = CAddress(CService("250.250.2.1", 8333), NODE_NONE); + CAddress addr1 = CAddress(ResolveService("250.250.2.1", 8333), NODE_NONE); addr1.nTime = GetAdjustedTime(); // Set time so isTerrible = false - CAddress addr2 = CAddress(CService("250.251.2.2", 9999), NODE_NONE); + CAddress addr2 = CAddress(ResolveService("250.251.2.2", 9999), NODE_NONE); addr2.nTime = GetAdjustedTime(); - CAddress addr3 = CAddress(CService("251.252.2.3", 8333), NODE_NONE); + CAddress addr3 = CAddress(ResolveService("251.252.2.3", 8333), NODE_NONE); addr3.nTime = GetAdjustedTime(); - CAddress addr4 = CAddress(CService("252.253.3.4", 8333), NODE_NONE); + CAddress addr4 = CAddress(ResolveService("252.253.3.4", 8333), NODE_NONE); addr4.nTime = GetAdjustedTime(); - CAddress addr5 = CAddress(CService("252.254.4.5", 8333), NODE_NONE); + CAddress addr5 = CAddress(ResolveService("252.254.4.5", 8333), NODE_NONE); addr5.nTime = GetAdjustedTime(); CNetAddr source1 = ResolveIP("250.1.2.1"); CNetAddr source2 = ResolveIP("250.2.3.3"); @@ -390,7 +402,7 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr) int octet2 = (i / 256) % 256; int octet3 = (i / (256 * 2)) % 256; string strAddr = boost::to_string(octet1) + "." + boost::to_string(octet2) + "." + boost::to_string(octet3) + ".23"; - CAddress addr = CAddress(CService(strAddr), NODE_NONE); + CAddress addr = CAddress(ResolveService(strAddr), NODE_NONE); // Ensure that for all addrs in addrman, isTerrible == false. addr.nTime = GetAdjustedTime(); @@ -415,8 +427,8 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket) // Set addrman addr placement to be deterministic. addrman.MakeDeterministic(); - CAddress addr1 = CAddress(CService("250.1.1.1", 8333), NODE_NONE); - CAddress addr2 = CAddress(CService("250.1.1.1", 9999), NODE_NONE); + CAddress addr1 = CAddress(ResolveService("250.1.1.1", 8333), NODE_NONE); + CAddress addr2 = CAddress(ResolveService("250.1.1.1", 9999), NODE_NONE); CNetAddr source1 = ResolveIP("250.1.1.1"); @@ -443,7 +455,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket) set buckets; for (int i = 0; i < 255; i++) { CAddrInfo infoi = CAddrInfo( - CAddress(CService("250.1.1." + boost::to_string(i)), NODE_NONE), + CAddress(ResolveService("250.1.1." + boost::to_string(i)), NODE_NONE), ResolveIP("250.1.1." + boost::to_string(i))); int bucket = infoi.GetTriedBucket(nKey1); buckets.insert(bucket); @@ -455,7 +467,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket) buckets.clear(); for (int j = 0; j < 255; j++) { CAddrInfo infoj = CAddrInfo( - CAddress(CService("250." + boost::to_string(j) + ".1.1"), NODE_NONE), + CAddress(ResolveService("250." + boost::to_string(j) + ".1.1"), NODE_NONE), ResolveIP("250." + boost::to_string(j) + ".1.1")); int bucket = infoj.GetTriedBucket(nKey1); buckets.insert(bucket); @@ -472,8 +484,8 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket) // Set addrman addr placement to be deterministic. addrman.MakeDeterministic(); - CAddress addr1 = CAddress(CService("250.1.2.1", 8333), NODE_NONE); - CAddress addr2 = CAddress(CService("250.1.2.1", 9999), NODE_NONE); + CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE); + CAddress addr2 = CAddress(ResolveService("250.1.2.1", 9999), NODE_NONE); CNetAddr source1 = ResolveIP("250.1.2.1"); @@ -496,7 +508,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket) set buckets; for (int i = 0; i < 255; i++) { CAddrInfo infoi = CAddrInfo( - CAddress(CService("250.1.1." + boost::to_string(i)), NODE_NONE), + CAddress(ResolveService("250.1.1." + boost::to_string(i)), NODE_NONE), ResolveIP("250.1.1." + boost::to_string(i))); int bucket = infoi.GetNewBucket(nKey1); buckets.insert(bucket); @@ -508,7 +520,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket) buckets.clear(); for (int j = 0; j < 4 * 255; j++) { CAddrInfo infoj = CAddrInfo(CAddress( - CService( + ResolveService( boost::to_string(250 + (j / 255)) + "." + boost::to_string(j % 256) + ".1.1"), NODE_NONE), ResolveIP("251.4.1.1")); int bucket = infoj.GetNewBucket(nKey1); @@ -521,7 +533,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket) buckets.clear(); for (int p = 0; p < 255; p++) { CAddrInfo infoj = CAddrInfo( - CAddress(CService("250.1.1.1"), NODE_NONE), + CAddress(ResolveService("250.1.1.1"), NODE_NONE), ResolveIP("250." + boost::to_string(p) + ".1.1")); int bucket = infoj.GetNewBucket(nKey1); buckets.insert(bucket); diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index 511073499e245..fca1a16b2dc81 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -51,7 +51,9 @@ class CAddrManCorrupted : public CAddrManSerializationMock int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30); s << nUBuckets; - CAddress addr = CAddress(CService("252.1.1.1", 7777), NODE_NONE); + CService serv; + Lookup("252.1.1.1", serv, 7777, false); + CAddress addr = CAddress(serv, NODE_NONE); CNetAddr resolved; LookupHost("252.2.2.2", resolved, false); CAddrInfo info = CAddrInfo(addr, resolved); @@ -76,14 +78,17 @@ BOOST_AUTO_TEST_CASE(caddrdb_read) CAddrManUncorrupted addrmanUncorrupted; addrmanUncorrupted.MakeDeterministic(); - CService addr1 = CService("250.7.1.1", 8333); - CService addr2 = CService("250.7.2.2", 9999); - CService addr3 = CService("250.7.3.3", 9999); + CService addr1, addr2, addr3; + Lookup("250.7.1.1", addr1, 8333, false); + Lookup("250.7.2.2", addr2, 9999, false); + Lookup("250.7.3.3", addr3, 9999, false); // Add three addresses to new table. - addrmanUncorrupted.Add(CAddress(addr1, NODE_NONE), CService("252.5.1.1", 8333)); - addrmanUncorrupted.Add(CAddress(addr2, NODE_NONE), CService("252.5.1.1", 8333)); - addrmanUncorrupted.Add(CAddress(addr3, NODE_NONE), CService("252.5.1.1", 8333)); + CService source; + Lookup("252.5.1.1", source, 8333, false); + addrmanUncorrupted.Add(CAddress(addr1, NODE_NONE), source); + addrmanUncorrupted.Add(CAddress(addr2, NODE_NONE), source); + addrmanUncorrupted.Add(CAddress(addr3, NODE_NONE), source); // Test that the de-serialization does not throw an exception. CDataStream ssPeers1 = AddrmanToStream(addrmanUncorrupted); diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index 0d6b655675ded..d3d782747fd2c 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -437,8 +437,7 @@ void TorController::add_onion_cb(TorControlConnection& conn, const TorControlRep if ((i = m.find("PrivateKey")) != m.end()) private_key = i->second; } - - service = CService(service_id+".onion", GetListenPort()); + LookupNumeric(std::string(service_id+".onion").c_str(), service, GetListenPort()); LogPrintf("tor: Got service ID %s, advertising service %s\n", service_id, service.ToString()); if (WriteBinaryFile(GetPrivateKeyFile(), private_key)) { LogPrint("tor", "tor: Cached service private key to %s\n", GetPrivateKeyFile()); @@ -462,7 +461,9 @@ void TorController::auth_cb(TorControlConnection& conn, const TorControlReply& r // Now that we know Tor is running setup the proxy for onion addresses // if -onion isn't set to something else. if (GetArg("-onion", "") == "") { - proxyType addrOnion = proxyType(CService("127.0.0.1", 9050), true); + CService resolved; + assert(LookupNumeric("127.0.0.1", resolved, 9050)); + proxyType addrOnion = proxyType(resolved, true); SetProxy(NET_TOR, addrOnion); SetLimited(NET_TOR, false); } From b8db185952c815444b7052092472ef9af3a42e89 Mon Sep 17 00:00:00 2001 From: Chris Stewart Date: Fri, 29 Jul 2016 11:52:48 -0500 Subject: [PATCH 0680/1802] Update README.md Updating documentation for adding new unit test files Removing unneeded sentence from README Removing uint160_tests.cpp as it DNE Formatting command line instructions to use `` fixing 80 char formatting issue in README fixing more nits --- src/test/README.md | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/test/README.md b/src/test/README.md index b2d6be14f14fd..61462642bfb9c 100644 --- a/src/test/README.md +++ b/src/test/README.md @@ -5,18 +5,15 @@ sense to simply use this framework rather than require developers to configure some other framework (we want as few impediments to creating unit tests as possible). -The build system is setup to compile an executable called "test_bitcoin" +The build system is setup to compile an executable called `test_bitcoin` that runs all of the unit tests. The main source file is called -test_bitcoin.cpp, which simply includes other files that contain the -actual unit tests (outside of a couple required preprocessor -directives). The pattern is to create one test file for each class or -source file for which you want to create unit tests. The file naming -convention is "_tests.cpp" and such files should wrap -their tests in a test suite called "_tests". For an -examples of this pattern, examine uint160_tests.cpp and -uint256_tests.cpp. - -Add the source files to /src/Makefile.test.include to add them to the build. +test_bitcoin.cpp. To add a new unit test file to our test suite you need +to add the file to `src/Makefile.test.include`. The pattern is to create +one test file for each class or source file for which you want to create +unit tests. The file naming convention is `_tests.cpp` +and such files should wrap their tests in a test suite +called `_tests`. For an example of this pattern, +examine `uint256_tests.cpp`. For further reading, I found the following website to be helpful in explaining how the boost unit test framework works: @@ -31,5 +28,5 @@ example, to run just the getarg_tests verbosely: test_bitcoin --run_test=getarg_tests/doubledash -Run test_bitcoin --help for the full list. +Run `test_bitcoin --help` for the full list. From b6c3ff3daed432e71d1c5bfe2357c4bb9fdc862a Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 31 May 2016 15:50:24 -0400 Subject: [PATCH 0681/1802] net: Split resolving out of CSubNet --- src/httpserver.cpp | 11 ++- src/init.cpp | 3 +- src/netbase.cpp | 94 ++++++++++++++--------- src/netbase.h | 4 +- src/qt/rpcconsole.cpp | 3 +- src/rpc/net.cpp | 2 +- src/test/netbase_tests.cpp | 149 +++++++++++++++++++------------------ 7 files changed, 152 insertions(+), 114 deletions(-) diff --git a/src/httpserver.cpp b/src/httpserver.cpp index 57aa134b38fc3..2c5bc2c7923c3 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -197,12 +197,17 @@ static bool ClientAllowed(const CNetAddr& netaddr) static bool InitHTTPAllowList() { rpc_allow_subnets.clear(); - rpc_allow_subnets.push_back(CSubNet("127.0.0.0/8")); // always allow IPv4 local subnet - rpc_allow_subnets.push_back(CSubNet("::1")); // always allow IPv6 localhost + CNetAddr localv4; + CNetAddr localv6; + LookupHost("127.0.0.1", localv4, false); + LookupHost("::1", localv6, false); + rpc_allow_subnets.push_back(CSubNet(localv4, 8)); // always allow IPv4 local subnet + rpc_allow_subnets.push_back(CSubNet(localv6)); // always allow IPv6 localhost if (mapMultiArgs.count("-rpcallowip")) { const std::vector& vAllow = mapMultiArgs["-rpcallowip"]; for (std::string strAllow : vAllow) { - CSubNet subnet(strAllow); + CSubNet subnet; + LookupSubNet(strAllow.c_str(), subnet); if (!subnet.IsValid()) { uiInterface.ThreadSafeMessageBox( strprintf("Invalid -rpcallowip subnet specification: %s. Valid 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).", strAllow), diff --git a/src/init.cpp b/src/init.cpp index 77ecf05f1db90..8b94e2dbfb126 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1083,7 +1083,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (mapArgs.count("-whitelist")) { BOOST_FOREACH(const std::string& net, mapMultiArgs["-whitelist"]) { - CSubNet subnet(net); + CSubNet subnet; + LookupSubNet(net.c_str(), subnet); if (!subnet.IsValid()) return InitError(strprintf(_("Invalid netmask specified in -whitelist: '%s'"), net)); CNode::AddWhitelistedRange(subnet); diff --git a/src/netbase.cpp b/src/netbase.cpp index 2e7a4f758a39e..52badcd98f5f8 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -1214,63 +1214,85 @@ CSubNet::CSubNet(): memset(netmask, 0, sizeof(netmask)); } -CSubNet::CSubNet(const std::string &strSubnet) +CSubNet::CSubNet(const CNetAddr &addr, int32_t mask) { - size_t slash = strSubnet.find_last_of('/'); - std::vector vIP; + valid = true; + network = addr; + // Default to /32 (IPv4) or /128 (IPv6), i.e. match single address + memset(netmask, 255, sizeof(netmask)); + // IPv4 addresses start at offset 12, and first 12 bytes must match, so just offset n + const int astartofs = network.IsIPv4() ? 12 : 0; + + int32_t n = mask; + if(n >= 0 && n <= (128 - astartofs*8)) // Only valid if in range of bits of address + { + n += astartofs*8; + // Clear bits [n..127] + for (; n < 128; ++n) + netmask[n>>3] &= ~(1<<(7-(n&7))); + } else + valid = false; + + // Normalize network according to netmask + for(int x=0; x<16; ++x) + network.ip[x] &= netmask[x]; +} + +CSubNet::CSubNet(const CNetAddr &addr, const CNetAddr &mask) +{ valid = true; + network = addr; // Default to /32 (IPv4) or /128 (IPv6), i.e. match single address memset(netmask, 255, sizeof(netmask)); + // IPv4 addresses start at offset 12, and first 12 bytes must match, so just offset n + const int astartofs = network.IsIPv4() ? 12 : 0; + + for(int x=astartofs; x<16; ++x) + netmask[x] = mask.ip[x]; + + // Normalize network according to netmask + for(int x=0; x<16; ++x) + network.ip[x] &= netmask[x]; +} + + +bool LookupSubNet(const char* pszName, CSubNet& ret) +{ + std::string strSubnet(pszName); + size_t slash = strSubnet.find_last_of('/'); + std::vector vIP; + std::string strAddress = strSubnet.substr(0, slash); if (LookupHost(strAddress.c_str(), vIP, 1, false)) { - network = vIP[0]; + CNetAddr network = vIP[0]; if (slash != strSubnet.npos) { std::string strNetmask = strSubnet.substr(slash + 1); int32_t n; // IPv4 addresses start at offset 12, and first 12 bytes must match, so just offset n - const int astartofs = network.IsIPv4() ? 12 : 0; - if (ParseInt32(strNetmask, &n)) // If valid number, assume /24 symtex - { - if(n >= 0 && n <= (128 - astartofs*8)) // Only valid if in range of bits of address - { - n += astartofs*8; - // Clear bits [n..127] - for (; n < 128; ++n) - netmask[n>>3] &= ~(1<<(7-(n&7))); - } - else - { - valid = false; - } + if (ParseInt32(strNetmask, &n)) { // If valid number, assume /24 syntax + ret = CSubNet(network, n); + return ret.IsValid(); } else // If not a valid number, try full netmask syntax { - if (LookupHost(strNetmask.c_str(), vIP, 1, false)) // Never allow lookup for netmask - { - // Copy only the *last* four bytes in case of IPv4, the rest of the mask should stay 1's as - // we don't want pchIPv4 to be part of the mask. - for(int x=astartofs; x<16; ++x) - netmask[x] = vIP[0].ip[x]; - } - else - { - valid = false; + // Never allow lookup for netmask + if (LookupHost(strNetmask.c_str(), vIP, 1, false)) { + ret = CSubNet(network, vIP[0]); + return ret.IsValid(); } } } + else + { + ret = CSubNet(network); + return ret.IsValid(); + } } - else - { - valid = false; - } - - // Normalize network according to netmask - for(int x=0; x<16; ++x) - network.ip[x] &= netmask[x]; + return false; } CSubNet::CSubNet(const CNetAddr &addr): diff --git a/src/netbase.h b/src/netbase.h index 97b96f69cc55e..26807ae69733a 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -117,7 +117,8 @@ class CSubNet public: CSubNet(); - explicit CSubNet(const std::string &strSubnet); + CSubNet(const CNetAddr &addr, int32_t mask); + CSubNet(const CNetAddr &addr, const CNetAddr &mask); //constructor for single ip subnet (/32 or /128) explicit CSubNet(const CNetAddr &addr); @@ -205,6 +206,7 @@ bool LookupHost(const char *pszName, CNetAddr& addr, bool fAllowLookup); bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLookup); bool Lookup(const char *pszName, std::vector& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions); bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0); +bool LookupSubNet(const char *pszName, CSubNet& subnet); bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed = 0); bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout, bool *outProxyConnectionFailed = 0); /** Return readable error string for a network error code */ diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index e7df4f2dfafce..21eda07ddffd0 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -915,8 +915,9 @@ void RPCConsole::unbanSelectedNode() // Get currently selected ban address QString strNode = GUIUtil::getEntryData(ui->banlistWidget, 0, BanTableModel::Address); - CSubNet possibleSubnet(strNode.toStdString()); + CSubNet possibleSubnet; + LookupSubNet(strNode.toStdString().c_str(), possibleSubnet); if (possibleSubnet.IsValid()) { CNode::Unban(possibleSubnet); diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index c23becd4a97de..58cf4a56e05ec 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -500,7 +500,7 @@ UniValue setban(const UniValue& params, bool fHelp) netAddr = resolved; } else - subNet = CSubNet(params[0].get_str()); + LookupSubNet(params[0].get_str().c_str(), subNet); if (! (isSubnet ? subNet.IsValid() : netAddr.IsValid()) ) throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Invalid IP/Subnet"); diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index 556c64f2297fa..34b1ebb7a428d 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -21,6 +21,13 @@ static CNetAddr ResolveIP(const char* ip) return addr; } +static CSubNet ResolveSubNet(const char* subnet) +{ + CSubNet ret; + LookupSubNet(subnet, ret); + return ret; +} + BOOST_AUTO_TEST_CASE(netbase_networks) { BOOST_CHECK(ResolveIP("127.0.0.1").GetNetwork() == NET_UNROUTABLE); @@ -119,44 +126,44 @@ BOOST_AUTO_TEST_CASE(onioncat_test) BOOST_AUTO_TEST_CASE(subnet_test) { - BOOST_CHECK(CSubNet("1.2.3.0/24") == CSubNet("1.2.3.0/255.255.255.0")); - BOOST_CHECK(CSubNet("1.2.3.0/24") != CSubNet("1.2.4.0/255.255.255.0")); - BOOST_CHECK(CSubNet("1.2.3.0/24").Match(ResolveIP("1.2.3.4"))); - BOOST_CHECK(!CSubNet("1.2.2.0/24").Match(ResolveIP("1.2.3.4"))); - BOOST_CHECK(CSubNet("1.2.3.4").Match(ResolveIP("1.2.3.4"))); - BOOST_CHECK(CSubNet("1.2.3.4/32").Match(ResolveIP("1.2.3.4"))); - BOOST_CHECK(!CSubNet("1.2.3.4").Match(ResolveIP("5.6.7.8"))); - BOOST_CHECK(!CSubNet("1.2.3.4/32").Match(ResolveIP("5.6.7.8"))); - BOOST_CHECK(CSubNet("::ffff:127.0.0.1").Match(ResolveIP("127.0.0.1"))); - BOOST_CHECK(CSubNet("1:2:3:4:5:6:7:8").Match(ResolveIP("1:2:3:4:5:6:7:8"))); - BOOST_CHECK(!CSubNet("1:2:3:4:5:6:7:8").Match(ResolveIP("1:2:3:4:5:6:7:9"))); - BOOST_CHECK(CSubNet("1:2:3:4:5:6:7:0/112").Match(ResolveIP("1:2:3:4:5:6:7:1234"))); - BOOST_CHECK(CSubNet("192.168.0.1/24").Match(ResolveIP("192.168.0.2"))); - BOOST_CHECK(CSubNet("192.168.0.20/29").Match(ResolveIP("192.168.0.18"))); - BOOST_CHECK(CSubNet("1.2.2.1/24").Match(ResolveIP("1.2.2.4"))); - BOOST_CHECK(CSubNet("1.2.2.110/31").Match(ResolveIP("1.2.2.111"))); - BOOST_CHECK(CSubNet("1.2.2.20/26").Match(ResolveIP("1.2.2.63"))); + BOOST_CHECK(ResolveSubNet("1.2.3.0/24") == ResolveSubNet("1.2.3.0/255.255.255.0")); + BOOST_CHECK(ResolveSubNet("1.2.3.0/24") != ResolveSubNet("1.2.4.0/255.255.255.0")); + BOOST_CHECK(ResolveSubNet("1.2.3.0/24").Match(ResolveIP("1.2.3.4"))); + BOOST_CHECK(!ResolveSubNet("1.2.2.0/24").Match(ResolveIP("1.2.3.4"))); + BOOST_CHECK(ResolveSubNet("1.2.3.4").Match(ResolveIP("1.2.3.4"))); + BOOST_CHECK(ResolveSubNet("1.2.3.4/32").Match(ResolveIP("1.2.3.4"))); + BOOST_CHECK(!ResolveSubNet("1.2.3.4").Match(ResolveIP("5.6.7.8"))); + BOOST_CHECK(!ResolveSubNet("1.2.3.4/32").Match(ResolveIP("5.6.7.8"))); + BOOST_CHECK(ResolveSubNet("::ffff:127.0.0.1").Match(ResolveIP("127.0.0.1"))); + BOOST_CHECK(ResolveSubNet("1:2:3:4:5:6:7:8").Match(ResolveIP("1:2:3:4:5:6:7:8"))); + BOOST_CHECK(!ResolveSubNet("1:2:3:4:5:6:7:8").Match(ResolveIP("1:2:3:4:5:6:7:9"))); + BOOST_CHECK(ResolveSubNet("1:2:3:4:5:6:7:0/112").Match(ResolveIP("1:2:3:4:5:6:7:1234"))); + BOOST_CHECK(ResolveSubNet("192.168.0.1/24").Match(ResolveIP("192.168.0.2"))); + BOOST_CHECK(ResolveSubNet("192.168.0.20/29").Match(ResolveIP("192.168.0.18"))); + BOOST_CHECK(ResolveSubNet("1.2.2.1/24").Match(ResolveIP("1.2.2.4"))); + BOOST_CHECK(ResolveSubNet("1.2.2.110/31").Match(ResolveIP("1.2.2.111"))); + BOOST_CHECK(ResolveSubNet("1.2.2.20/26").Match(ResolveIP("1.2.2.63"))); // All-Matching IPv6 Matches arbitrary IPv4 and IPv6 - BOOST_CHECK(CSubNet("::/0").Match(ResolveIP("1:2:3:4:5:6:7:1234"))); - BOOST_CHECK(CSubNet("::/0").Match(ResolveIP("1.2.3.4"))); + BOOST_CHECK(ResolveSubNet("::/0").Match(ResolveIP("1:2:3:4:5:6:7:1234"))); + BOOST_CHECK(ResolveSubNet("::/0").Match(ResolveIP("1.2.3.4"))); // All-Matching IPv4 does not Match IPv6 - BOOST_CHECK(!CSubNet("0.0.0.0/0").Match(ResolveIP("1:2:3:4:5:6:7:1234"))); + BOOST_CHECK(!ResolveSubNet("0.0.0.0/0").Match(ResolveIP("1:2:3:4:5:6:7:1234"))); // Invalid subnets Match nothing (not even invalid addresses) BOOST_CHECK(!CSubNet().Match(ResolveIP("1.2.3.4"))); - BOOST_CHECK(!CSubNet("").Match(ResolveIP("4.5.6.7"))); - BOOST_CHECK(!CSubNet("bloop").Match(ResolveIP("0.0.0.0"))); - BOOST_CHECK(!CSubNet("bloop").Match(ResolveIP("hab"))); + BOOST_CHECK(!ResolveSubNet("").Match(ResolveIP("4.5.6.7"))); + BOOST_CHECK(!ResolveSubNet("bloop").Match(ResolveIP("0.0.0.0"))); + BOOST_CHECK(!ResolveSubNet("bloop").Match(ResolveIP("hab"))); // Check valid/invalid - BOOST_CHECK(CSubNet("1.2.3.0/0").IsValid()); - BOOST_CHECK(!CSubNet("1.2.3.0/-1").IsValid()); - BOOST_CHECK(CSubNet("1.2.3.0/32").IsValid()); - BOOST_CHECK(!CSubNet("1.2.3.0/33").IsValid()); - BOOST_CHECK(CSubNet("1:2:3:4:5:6:7:8/0").IsValid()); - BOOST_CHECK(CSubNet("1:2:3:4:5:6:7:8/33").IsValid()); - BOOST_CHECK(!CSubNet("1:2:3:4:5:6:7:8/-1").IsValid()); - BOOST_CHECK(CSubNet("1:2:3:4:5:6:7:8/128").IsValid()); - BOOST_CHECK(!CSubNet("1:2:3:4:5:6:7:8/129").IsValid()); - BOOST_CHECK(!CSubNet("fuzzy").IsValid()); + BOOST_CHECK(ResolveSubNet("1.2.3.0/0").IsValid()); + BOOST_CHECK(!ResolveSubNet("1.2.3.0/-1").IsValid()); + BOOST_CHECK(ResolveSubNet("1.2.3.0/32").IsValid()); + BOOST_CHECK(!ResolveSubNet("1.2.3.0/33").IsValid()); + BOOST_CHECK(ResolveSubNet("1:2:3:4:5:6:7:8/0").IsValid()); + BOOST_CHECK(ResolveSubNet("1:2:3:4:5:6:7:8/33").IsValid()); + BOOST_CHECK(!ResolveSubNet("1:2:3:4:5:6:7:8/-1").IsValid()); + BOOST_CHECK(ResolveSubNet("1:2:3:4:5:6:7:8/128").IsValid()); + BOOST_CHECK(!ResolveSubNet("1:2:3:4:5:6:7:8/129").IsValid()); + BOOST_CHECK(!ResolveSubNet("fuzzy").IsValid()); //CNetAddr constructor test BOOST_CHECK(CSubNet(ResolveIP("127.0.0.1")).IsValid()); @@ -169,82 +176,82 @@ BOOST_AUTO_TEST_CASE(subnet_test) BOOST_CHECK(!CSubNet(ResolveIP("1:2:3:4:5:6:7:8")).Match(ResolveIP("1:2:3:4:5:6:7:9"))); BOOST_CHECK(CSubNet(ResolveIP("1:2:3:4:5:6:7:8")).ToString() == "1:2:3:4:5:6:7:8/128"); - CSubNet subnet = CSubNet("1.2.3.4/255.255.255.255"); + CSubNet subnet = ResolveSubNet("1.2.3.4/255.255.255.255"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/32"); - subnet = CSubNet("1.2.3.4/255.255.255.254"); + subnet = ResolveSubNet("1.2.3.4/255.255.255.254"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/31"); - subnet = CSubNet("1.2.3.4/255.255.255.252"); + subnet = ResolveSubNet("1.2.3.4/255.255.255.252"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/30"); - subnet = CSubNet("1.2.3.4/255.255.255.248"); + subnet = ResolveSubNet("1.2.3.4/255.255.255.248"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/29"); - subnet = CSubNet("1.2.3.4/255.255.255.240"); + subnet = ResolveSubNet("1.2.3.4/255.255.255.240"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/28"); - subnet = CSubNet("1.2.3.4/255.255.255.224"); + subnet = ResolveSubNet("1.2.3.4/255.255.255.224"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/27"); - subnet = CSubNet("1.2.3.4/255.255.255.192"); + subnet = ResolveSubNet("1.2.3.4/255.255.255.192"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/26"); - subnet = CSubNet("1.2.3.4/255.255.255.128"); + subnet = ResolveSubNet("1.2.3.4/255.255.255.128"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/25"); - subnet = CSubNet("1.2.3.4/255.255.255.0"); + subnet = ResolveSubNet("1.2.3.4/255.255.255.0"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/24"); - subnet = CSubNet("1.2.3.4/255.255.254.0"); + subnet = ResolveSubNet("1.2.3.4/255.255.254.0"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.2.0/23"); - subnet = CSubNet("1.2.3.4/255.255.252.0"); + subnet = ResolveSubNet("1.2.3.4/255.255.252.0"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/22"); - subnet = CSubNet("1.2.3.4/255.255.248.0"); + subnet = ResolveSubNet("1.2.3.4/255.255.248.0"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/21"); - subnet = CSubNet("1.2.3.4/255.255.240.0"); + subnet = ResolveSubNet("1.2.3.4/255.255.240.0"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/20"); - subnet = CSubNet("1.2.3.4/255.255.224.0"); + subnet = ResolveSubNet("1.2.3.4/255.255.224.0"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/19"); - subnet = CSubNet("1.2.3.4/255.255.192.0"); + subnet = ResolveSubNet("1.2.3.4/255.255.192.0"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/18"); - subnet = CSubNet("1.2.3.4/255.255.128.0"); + subnet = ResolveSubNet("1.2.3.4/255.255.128.0"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/17"); - subnet = CSubNet("1.2.3.4/255.255.0.0"); + subnet = ResolveSubNet("1.2.3.4/255.255.0.0"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/16"); - subnet = CSubNet("1.2.3.4/255.254.0.0"); + subnet = ResolveSubNet("1.2.3.4/255.254.0.0"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/15"); - subnet = CSubNet("1.2.3.4/255.252.0.0"); + subnet = ResolveSubNet("1.2.3.4/255.252.0.0"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/14"); - subnet = CSubNet("1.2.3.4/255.248.0.0"); + subnet = ResolveSubNet("1.2.3.4/255.248.0.0"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/13"); - subnet = CSubNet("1.2.3.4/255.240.0.0"); + subnet = ResolveSubNet("1.2.3.4/255.240.0.0"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/12"); - subnet = CSubNet("1.2.3.4/255.224.0.0"); + subnet = ResolveSubNet("1.2.3.4/255.224.0.0"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/11"); - subnet = CSubNet("1.2.3.4/255.192.0.0"); + subnet = ResolveSubNet("1.2.3.4/255.192.0.0"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/10"); - subnet = CSubNet("1.2.3.4/255.128.0.0"); + subnet = ResolveSubNet("1.2.3.4/255.128.0.0"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/9"); - subnet = CSubNet("1.2.3.4/255.0.0.0"); + subnet = ResolveSubNet("1.2.3.4/255.0.0.0"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/8"); - subnet = CSubNet("1.2.3.4/254.0.0.0"); + subnet = ResolveSubNet("1.2.3.4/254.0.0.0"); BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/7"); - subnet = CSubNet("1.2.3.4/252.0.0.0"); + subnet = ResolveSubNet("1.2.3.4/252.0.0.0"); BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/6"); - subnet = CSubNet("1.2.3.4/248.0.0.0"); + subnet = ResolveSubNet("1.2.3.4/248.0.0.0"); BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/5"); - subnet = CSubNet("1.2.3.4/240.0.0.0"); + subnet = ResolveSubNet("1.2.3.4/240.0.0.0"); BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/4"); - subnet = CSubNet("1.2.3.4/224.0.0.0"); + subnet = ResolveSubNet("1.2.3.4/224.0.0.0"); BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/3"); - subnet = CSubNet("1.2.3.4/192.0.0.0"); + subnet = ResolveSubNet("1.2.3.4/192.0.0.0"); BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/2"); - subnet = CSubNet("1.2.3.4/128.0.0.0"); + subnet = ResolveSubNet("1.2.3.4/128.0.0.0"); BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/1"); - subnet = CSubNet("1.2.3.4/0.0.0.0"); + subnet = ResolveSubNet("1.2.3.4/0.0.0.0"); BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/0"); - subnet = CSubNet("1:2:3:4:5:6:7:8/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); + subnet = ResolveSubNet("1:2:3:4:5:6:7:8/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); BOOST_CHECK_EQUAL(subnet.ToString(), "1:2:3:4:5:6:7:8/128"); - subnet = CSubNet("1:2:3:4:5:6:7:8/ffff:0000:0000:0000:0000:0000:0000:0000"); + subnet = ResolveSubNet("1:2:3:4:5:6:7:8/ffff:0000:0000:0000:0000:0000:0000:0000"); BOOST_CHECK_EQUAL(subnet.ToString(), "1::/16"); - subnet = CSubNet("1:2:3:4:5:6:7:8/0000:0000:0000:0000:0000:0000:0000:0000"); + subnet = ResolveSubNet("1:2:3:4:5:6:7:8/0000:0000:0000:0000:0000:0000:0000:0000"); BOOST_CHECK_EQUAL(subnet.ToString(), "::/0"); - subnet = CSubNet("1.2.3.4/255.255.232.0"); + subnet = ResolveSubNet("1.2.3.4/255.255.232.0"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/255.255.232.0"); - subnet = CSubNet("1:2:3:4:5:6:7:8/ffff:ffff:ffff:fffe:ffff:ffff:ffff:ff0f"); + subnet = ResolveSubNet("1:2:3:4:5:6:7:8/ffff:ffff:ffff:fffe:ffff:ffff:ffff:ff0f"); BOOST_CHECK_EQUAL(subnet.ToString(), "1:2:3:4:5:6:7:8/ffff:ffff:ffff:fffe:ffff:ffff:ffff:ff0f"); } From 1017b8a960d8bca41adebdad9982511a479689ce Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 31 May 2016 18:18:41 -0400 Subject: [PATCH 0682/1802] net: Add direct tests for new CSubNet constructors --- src/test/netbase_tests.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index 34b1ebb7a428d..7a8584f0f4322 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -171,12 +171,26 @@ BOOST_AUTO_TEST_CASE(subnet_test) BOOST_CHECK(!CSubNet(ResolveIP("127.0.0.1")).Match(ResolveIP("127.0.0.2"))); BOOST_CHECK(CSubNet(ResolveIP("127.0.0.1")).ToString() == "127.0.0.1/32"); + CSubNet subnet = CSubNet(ResolveIP("1.2.3.4"), 32); + BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/32"); + subnet = CSubNet(ResolveIP("1.2.3.4"), 8); + BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/8"); + subnet = CSubNet(ResolveIP("1.2.3.4"), 0); + BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/0"); + + subnet = CSubNet(ResolveIP("1.2.3.4"), ResolveIP("255.255.255.255")); + BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/32"); + subnet = CSubNet(ResolveIP("1.2.3.4"), ResolveIP("255.0.0.0")); + BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/8"); + subnet = CSubNet(ResolveIP("1.2.3.4"), ResolveIP("0.0.0.0")); + BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/0"); + BOOST_CHECK(CSubNet(ResolveIP("1:2:3:4:5:6:7:8")).IsValid()); BOOST_CHECK(CSubNet(ResolveIP("1:2:3:4:5:6:7:8")).Match(ResolveIP("1:2:3:4:5:6:7:8"))); BOOST_CHECK(!CSubNet(ResolveIP("1:2:3:4:5:6:7:8")).Match(ResolveIP("1:2:3:4:5:6:7:9"))); BOOST_CHECK(CSubNet(ResolveIP("1:2:3:4:5:6:7:8")).ToString() == "1:2:3:4:5:6:7:8/128"); - CSubNet subnet = ResolveSubNet("1.2.3.4/255.255.255.255"); + subnet = ResolveSubNet("1.2.3.4/255.255.255.255"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/32"); subnet = ResolveSubNet("1.2.3.4/255.255.255.254"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/31"); From 21e5b96ff417f304e624052f629e2b030984180f Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 31 May 2016 17:25:03 -0400 Subject: [PATCH 0683/1802] net: move CNetAddr/CService/CSubNet out of netbase --- src/Makefile.am | 2 + src/netaddress.cpp | 716 +++++++++++++++++++++++++++++++++++++++++++++ src/netaddress.h | 171 +++++++++++ src/netbase.cpp | 705 -------------------------------------------- src/netbase.h | 158 +--------- 5 files changed, 890 insertions(+), 862 deletions(-) create mode 100644 src/netaddress.cpp create mode 100644 src/netaddress.h diff --git a/src/Makefile.am b/src/Makefile.am index e3eaacdb4c983..0a35a052c24ab 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -106,6 +106,7 @@ BITCOIN_CORE_H = \ miner.h \ net.h \ netbase.h \ + netaddress.h \ noui.h \ policy/fees.h \ policy/policy.h \ @@ -289,6 +290,7 @@ libbitcoin_common_a_SOURCES = \ core_write.cpp \ key.cpp \ keystore.cpp \ + netaddress.cpp \ netbase.cpp \ protocol.cpp \ scheduler.cpp \ diff --git a/src/netaddress.cpp b/src/netaddress.cpp new file mode 100644 index 0000000000000..7000ce3f0acce --- /dev/null +++ b/src/netaddress.cpp @@ -0,0 +1,716 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifdef HAVE_CONFIG_H +#include "config/bitcoin-config.h" +#endif + +#include "netaddress.h" +#include "hash.h" +#include "utilstrencodings.h" +#include "tinyformat.h" + +static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff }; +static const unsigned char pchOnionCat[] = {0xFD,0x87,0xD8,0x7E,0xEB,0x43}; + +void CNetAddr::Init() +{ + memset(ip, 0, sizeof(ip)); + scopeId = 0; +} + +void CNetAddr::SetIP(const CNetAddr& ipIn) +{ + memcpy(ip, ipIn.ip, sizeof(ip)); +} + +void CNetAddr::SetRaw(Network network, const uint8_t *ip_in) +{ + switch(network) + { + case NET_IPV4: + memcpy(ip, pchIPv4, 12); + memcpy(ip+12, ip_in, 4); + break; + case NET_IPV6: + memcpy(ip, ip_in, 16); + break; + default: + assert(!"invalid network"); + } +} + +bool CNetAddr::SetSpecial(const std::string &strName) +{ + if (strName.size()>6 && strName.substr(strName.size() - 6, 6) == ".onion") { + std::vector vchAddr = DecodeBase32(strName.substr(0, strName.size() - 6).c_str()); + if (vchAddr.size() != 16-sizeof(pchOnionCat)) + return false; + memcpy(ip, pchOnionCat, sizeof(pchOnionCat)); + for (unsigned int i=0; i<16-sizeof(pchOnionCat); i++) + ip[i + sizeof(pchOnionCat)] = vchAddr[i]; + return true; + } + return false; +} + +CNetAddr::CNetAddr() +{ + Init(); +} + +CNetAddr::CNetAddr(const struct in_addr& ipv4Addr) +{ + SetRaw(NET_IPV4, (const uint8_t*)&ipv4Addr); +} + +CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr, const uint32_t scope) +{ + SetRaw(NET_IPV6, (const uint8_t*)&ipv6Addr); + scopeId = scope; +} + +unsigned int CNetAddr::GetByte(int n) const +{ + return ip[15-n]; +} + +bool CNetAddr::IsIPv4() const +{ + return (memcmp(ip, pchIPv4, sizeof(pchIPv4)) == 0); +} + +bool CNetAddr::IsIPv6() const +{ + return (!IsIPv4() && !IsTor()); +} + +bool CNetAddr::IsRFC1918() const +{ + return IsIPv4() && ( + GetByte(3) == 10 || + (GetByte(3) == 192 && GetByte(2) == 168) || + (GetByte(3) == 172 && (GetByte(2) >= 16 && GetByte(2) <= 31))); +} + +bool CNetAddr::IsRFC2544() const +{ + return IsIPv4() && GetByte(3) == 198 && (GetByte(2) == 18 || GetByte(2) == 19); +} + +bool CNetAddr::IsRFC3927() const +{ + return IsIPv4() && (GetByte(3) == 169 && GetByte(2) == 254); +} + +bool CNetAddr::IsRFC6598() const +{ + return IsIPv4() && GetByte(3) == 100 && GetByte(2) >= 64 && GetByte(2) <= 127; +} + +bool CNetAddr::IsRFC5737() const +{ + return IsIPv4() && ((GetByte(3) == 192 && GetByte(2) == 0 && GetByte(1) == 2) || + (GetByte(3) == 198 && GetByte(2) == 51 && GetByte(1) == 100) || + (GetByte(3) == 203 && GetByte(2) == 0 && GetByte(1) == 113)); +} + +bool CNetAddr::IsRFC3849() const +{ + return GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x0D && GetByte(12) == 0xB8; +} + +bool CNetAddr::IsRFC3964() const +{ + return (GetByte(15) == 0x20 && GetByte(14) == 0x02); +} + +bool CNetAddr::IsRFC6052() const +{ + static const unsigned char pchRFC6052[] = {0,0x64,0xFF,0x9B,0,0,0,0,0,0,0,0}; + return (memcmp(ip, pchRFC6052, sizeof(pchRFC6052)) == 0); +} + +bool CNetAddr::IsRFC4380() const +{ + return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0 && GetByte(12) == 0); +} + +bool CNetAddr::IsRFC4862() const +{ + static const unsigned char pchRFC4862[] = {0xFE,0x80,0,0,0,0,0,0}; + return (memcmp(ip, pchRFC4862, sizeof(pchRFC4862)) == 0); +} + +bool CNetAddr::IsRFC4193() const +{ + return ((GetByte(15) & 0xFE) == 0xFC); +} + +bool CNetAddr::IsRFC6145() const +{ + static const unsigned char pchRFC6145[] = {0,0,0,0,0,0,0,0,0xFF,0xFF,0,0}; + return (memcmp(ip, pchRFC6145, sizeof(pchRFC6145)) == 0); +} + +bool CNetAddr::IsRFC4843() const +{ + return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x00 && (GetByte(12) & 0xF0) == 0x10); +} + +bool CNetAddr::IsTor() const +{ + return (memcmp(ip, pchOnionCat, sizeof(pchOnionCat)) == 0); +} + +bool CNetAddr::IsLocal() const +{ + // IPv4 loopback + if (IsIPv4() && (GetByte(3) == 127 || GetByte(3) == 0)) + return true; + + // IPv6 loopback (::1/128) + static const unsigned char pchLocal[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; + if (memcmp(ip, pchLocal, 16) == 0) + return true; + + return false; +} + +bool CNetAddr::IsMulticast() const +{ + return (IsIPv4() && (GetByte(3) & 0xF0) == 0xE0) + || (GetByte(15) == 0xFF); +} + +bool CNetAddr::IsValid() const +{ + // Cleanup 3-byte shifted addresses caused by garbage in size field + // of addr messages from versions before 0.2.9 checksum. + // Two consecutive addr messages look like this: + // header20 vectorlen3 addr26 addr26 addr26 header20 vectorlen3 addr26 addr26 addr26... + // so if the first length field is garbled, it reads the second batch + // of addr misaligned by 3 bytes. + if (memcmp(ip, pchIPv4+3, sizeof(pchIPv4)-3) == 0) + return false; + + // unspecified IPv6 address (::/128) + unsigned char ipNone[16] = {}; + if (memcmp(ip, ipNone, 16) == 0) + return false; + + // documentation IPv6 address + if (IsRFC3849()) + return false; + + if (IsIPv4()) + { + // INADDR_NONE + uint32_t ipNone = INADDR_NONE; + if (memcmp(ip+12, &ipNone, 4) == 0) + return false; + + // 0 + ipNone = 0; + if (memcmp(ip+12, &ipNone, 4) == 0) + return false; + } + + return true; +} + +bool CNetAddr::IsRoutable() const +{ + return IsValid() && !(IsRFC1918() || IsRFC2544() || IsRFC3927() || IsRFC4862() || IsRFC6598() || IsRFC5737() || (IsRFC4193() && !IsTor()) || IsRFC4843() || IsLocal()); +} + +enum Network CNetAddr::GetNetwork() const +{ + if (!IsRoutable()) + return NET_UNROUTABLE; + + if (IsIPv4()) + return NET_IPV4; + + if (IsTor()) + return NET_TOR; + + return NET_IPV6; +} + +std::string CNetAddr::ToStringIP() const +{ + if (IsTor()) + return EncodeBase32(&ip[6], 10) + ".onion"; + CService serv(*this, 0); + struct sockaddr_storage sockaddr; + socklen_t socklen = sizeof(sockaddr); + if (serv.GetSockAddr((struct sockaddr*)&sockaddr, &socklen)) { + char name[1025] = ""; + if (!getnameinfo((const struct sockaddr*)&sockaddr, socklen, name, sizeof(name), NULL, 0, NI_NUMERICHOST)) + return std::string(name); + } + if (IsIPv4()) + return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0)); + else + return strprintf("%x:%x:%x:%x:%x:%x:%x:%x", + GetByte(15) << 8 | GetByte(14), GetByte(13) << 8 | GetByte(12), + GetByte(11) << 8 | GetByte(10), GetByte(9) << 8 | GetByte(8), + GetByte(7) << 8 | GetByte(6), GetByte(5) << 8 | GetByte(4), + GetByte(3) << 8 | GetByte(2), GetByte(1) << 8 | GetByte(0)); +} + +std::string CNetAddr::ToString() const +{ + return ToStringIP(); +} + +bool operator==(const CNetAddr& a, const CNetAddr& b) +{ + return (memcmp(a.ip, b.ip, 16) == 0); +} + +bool operator!=(const CNetAddr& a, const CNetAddr& b) +{ + return (memcmp(a.ip, b.ip, 16) != 0); +} + +bool operator<(const CNetAddr& a, const CNetAddr& b) +{ + return (memcmp(a.ip, b.ip, 16) < 0); +} + +bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const +{ + if (!IsIPv4()) + return false; + memcpy(pipv4Addr, ip+12, 4); + return true; +} + +bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const +{ + memcpy(pipv6Addr, ip, 16); + return true; +} + +// get canonical identifier of an address' group +// no two connections will be attempted to addresses with the same group +std::vector CNetAddr::GetGroup() const +{ + std::vector vchRet; + int nClass = NET_IPV6; + int nStartByte = 0; + int nBits = 16; + + // all local addresses belong to the same group + if (IsLocal()) + { + nClass = 255; + nBits = 0; + } + + // all unroutable addresses belong to the same group + if (!IsRoutable()) + { + nClass = NET_UNROUTABLE; + nBits = 0; + } + // for IPv4 addresses, '1' + the 16 higher-order bits of the IP + // includes mapped IPv4, SIIT translated IPv4, and the well-known prefix + else if (IsIPv4() || IsRFC6145() || IsRFC6052()) + { + nClass = NET_IPV4; + nStartByte = 12; + } + // for 6to4 tunnelled addresses, use the encapsulated IPv4 address + else if (IsRFC3964()) + { + nClass = NET_IPV4; + nStartByte = 2; + } + // for Teredo-tunnelled IPv6 addresses, use the encapsulated IPv4 address + else if (IsRFC4380()) + { + vchRet.push_back(NET_IPV4); + vchRet.push_back(GetByte(3) ^ 0xFF); + vchRet.push_back(GetByte(2) ^ 0xFF); + return vchRet; + } + else if (IsTor()) + { + nClass = NET_TOR; + nStartByte = 6; + nBits = 4; + } + // for he.net, use /36 groups + else if (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x04 && GetByte(12) == 0x70) + nBits = 36; + // for the rest of the IPv6 network, use /32 groups + else + nBits = 32; + + vchRet.push_back(nClass); + while (nBits >= 8) + { + vchRet.push_back(GetByte(15 - nStartByte)); + nStartByte++; + nBits -= 8; + } + if (nBits > 0) + vchRet.push_back(GetByte(15 - nStartByte) | ((1 << (8 - nBits)) - 1)); + + return vchRet; +} + +uint64_t CNetAddr::GetHash() const +{ + uint256 hash = Hash(&ip[0], &ip[16]); + uint64_t nRet; + memcpy(&nRet, &hash, sizeof(nRet)); + return nRet; +} + +// private extensions to enum Network, only returned by GetExtNetwork, +// and only used in GetReachabilityFrom +static const int NET_UNKNOWN = NET_MAX + 0; +static const int NET_TEREDO = NET_MAX + 1; +int static GetExtNetwork(const CNetAddr *addr) +{ + if (addr == NULL) + return NET_UNKNOWN; + if (addr->IsRFC4380()) + return NET_TEREDO; + return addr->GetNetwork(); +} + +/** Calculates a metric for how reachable (*this) is from a given partner */ +int CNetAddr::GetReachabilityFrom(const CNetAddr *paddrPartner) const +{ + enum Reachability { + REACH_UNREACHABLE, + REACH_DEFAULT, + REACH_TEREDO, + REACH_IPV6_WEAK, + REACH_IPV4, + REACH_IPV6_STRONG, + REACH_PRIVATE + }; + + if (!IsRoutable()) + return REACH_UNREACHABLE; + + int ourNet = GetExtNetwork(this); + int theirNet = GetExtNetwork(paddrPartner); + bool fTunnel = IsRFC3964() || IsRFC6052() || IsRFC6145(); + + switch(theirNet) { + case NET_IPV4: + switch(ourNet) { + default: return REACH_DEFAULT; + case NET_IPV4: return REACH_IPV4; + } + case NET_IPV6: + switch(ourNet) { + default: return REACH_DEFAULT; + case NET_TEREDO: return REACH_TEREDO; + case NET_IPV4: return REACH_IPV4; + case NET_IPV6: return fTunnel ? REACH_IPV6_WEAK : REACH_IPV6_STRONG; // only prefer giving our IPv6 address if it's not tunnelled + } + case NET_TOR: + switch(ourNet) { + default: return REACH_DEFAULT; + case NET_IPV4: return REACH_IPV4; // Tor users can connect to IPv4 as well + case NET_TOR: return REACH_PRIVATE; + } + case NET_TEREDO: + switch(ourNet) { + default: return REACH_DEFAULT; + case NET_TEREDO: return REACH_TEREDO; + case NET_IPV6: return REACH_IPV6_WEAK; + case NET_IPV4: return REACH_IPV4; + } + case NET_UNKNOWN: + case NET_UNROUTABLE: + default: + switch(ourNet) { + default: return REACH_DEFAULT; + case NET_TEREDO: return REACH_TEREDO; + case NET_IPV6: return REACH_IPV6_WEAK; + case NET_IPV4: return REACH_IPV4; + case NET_TOR: return REACH_PRIVATE; // either from Tor, or don't care about our address + } + } +} + +void CService::Init() +{ + port = 0; +} + +CService::CService() +{ + Init(); +} + +CService::CService(const CNetAddr& cip, unsigned short portIn) : CNetAddr(cip), port(portIn) +{ +} + +CService::CService(const struct in_addr& ipv4Addr, unsigned short portIn) : CNetAddr(ipv4Addr), port(portIn) +{ +} + +CService::CService(const struct in6_addr& ipv6Addr, unsigned short portIn) : CNetAddr(ipv6Addr), port(portIn) +{ +} + +CService::CService(const struct sockaddr_in& addr) : CNetAddr(addr.sin_addr), port(ntohs(addr.sin_port)) +{ + assert(addr.sin_family == AF_INET); +} + +CService::CService(const struct sockaddr_in6 &addr) : CNetAddr(addr.sin6_addr, addr.sin6_scope_id), port(ntohs(addr.sin6_port)) +{ + assert(addr.sin6_family == AF_INET6); +} + +bool CService::SetSockAddr(const struct sockaddr *paddr) +{ + switch (paddr->sa_family) { + case AF_INET: + *this = CService(*(const struct sockaddr_in*)paddr); + return true; + case AF_INET6: + *this = CService(*(const struct sockaddr_in6*)paddr); + return true; + default: + return false; + } +} + +unsigned short CService::GetPort() const +{ + return port; +} + +bool operator==(const CService& a, const CService& b) +{ + return (CNetAddr)a == (CNetAddr)b && a.port == b.port; +} + +bool operator!=(const CService& a, const CService& b) +{ + return (CNetAddr)a != (CNetAddr)b || a.port != b.port; +} + +bool operator<(const CService& a, const CService& b) +{ + return (CNetAddr)a < (CNetAddr)b || ((CNetAddr)a == (CNetAddr)b && a.port < b.port); +} + +bool CService::GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const +{ + if (IsIPv4()) { + if (*addrlen < (socklen_t)sizeof(struct sockaddr_in)) + return false; + *addrlen = sizeof(struct sockaddr_in); + struct sockaddr_in *paddrin = (struct sockaddr_in*)paddr; + memset(paddrin, 0, *addrlen); + if (!GetInAddr(&paddrin->sin_addr)) + return false; + paddrin->sin_family = AF_INET; + paddrin->sin_port = htons(port); + return true; + } + if (IsIPv6()) { + if (*addrlen < (socklen_t)sizeof(struct sockaddr_in6)) + return false; + *addrlen = sizeof(struct sockaddr_in6); + struct sockaddr_in6 *paddrin6 = (struct sockaddr_in6*)paddr; + memset(paddrin6, 0, *addrlen); + if (!GetIn6Addr(&paddrin6->sin6_addr)) + return false; + paddrin6->sin6_scope_id = scopeId; + paddrin6->sin6_family = AF_INET6; + paddrin6->sin6_port = htons(port); + return true; + } + return false; +} + +std::vector CService::GetKey() const +{ + std::vector vKey; + vKey.resize(18); + memcpy(&vKey[0], ip, 16); + vKey[16] = port / 0x100; + vKey[17] = port & 0x0FF; + return vKey; +} + +std::string CService::ToStringPort() const +{ + return strprintf("%u", port); +} + +std::string CService::ToStringIPPort() const +{ + if (IsIPv4() || IsTor()) { + return ToStringIP() + ":" + ToStringPort(); + } else { + return "[" + ToStringIP() + "]:" + ToStringPort(); + } +} + +std::string CService::ToString() const +{ + return ToStringIPPort(); +} + +void CService::SetPort(unsigned short portIn) +{ + port = portIn; +} + +CSubNet::CSubNet(): + valid(false) +{ + memset(netmask, 0, sizeof(netmask)); +} + +CSubNet::CSubNet(const CNetAddr &addr, int32_t mask) +{ + valid = true; + network = addr; + // Default to /32 (IPv4) or /128 (IPv6), i.e. match single address + memset(netmask, 255, sizeof(netmask)); + + // IPv4 addresses start at offset 12, and first 12 bytes must match, so just offset n + const int astartofs = network.IsIPv4() ? 12 : 0; + + int32_t n = mask; + if(n >= 0 && n <= (128 - astartofs*8)) // Only valid if in range of bits of address + { + n += astartofs*8; + // Clear bits [n..127] + for (; n < 128; ++n) + netmask[n>>3] &= ~(1<<(7-(n&7))); + } else + valid = false; + + // Normalize network according to netmask + for(int x=0; x<16; ++x) + network.ip[x] &= netmask[x]; +} + +CSubNet::CSubNet(const CNetAddr &addr, const CNetAddr &mask) +{ + valid = true; + network = addr; + // Default to /32 (IPv4) or /128 (IPv6), i.e. match single address + memset(netmask, 255, sizeof(netmask)); + + // IPv4 addresses start at offset 12, and first 12 bytes must match, so just offset n + const int astartofs = network.IsIPv4() ? 12 : 0; + + for(int x=astartofs; x<16; ++x) + netmask[x] = mask.ip[x]; + + // Normalize network according to netmask + for(int x=0; x<16; ++x) + network.ip[x] &= netmask[x]; +} + +CSubNet::CSubNet(const CNetAddr &addr): + valid(addr.IsValid()) +{ + memset(netmask, 255, sizeof(netmask)); + network = addr; +} + +bool CSubNet::Match(const CNetAddr &addr) const +{ + if (!valid || !addr.IsValid()) + return false; + for(int x=0; x<16; ++x) + if ((addr.ip[x] & netmask[x]) != network.ip[x]) + return false; + return true; +} + +static inline int NetmaskBits(uint8_t x) +{ + switch(x) { + case 0x00: return 0; break; + case 0x80: return 1; break; + case 0xc0: return 2; break; + case 0xe0: return 3; break; + case 0xf0: return 4; break; + case 0xf8: return 5; break; + case 0xfc: return 6; break; + case 0xfe: return 7; break; + case 0xff: return 8; break; + default: return -1; break; + } +} + +std::string CSubNet::ToString() const +{ + /* Parse binary 1{n}0{N-n} to see if mask can be represented as /n */ + int cidr = 0; + bool valid_cidr = true; + int n = network.IsIPv4() ? 12 : 0; + for (; n < 16 && netmask[n] == 0xff; ++n) + cidr += 8; + if (n < 16) { + int bits = NetmaskBits(netmask[n]); + if (bits < 0) + valid_cidr = false; + else + cidr += bits; + ++n; + } + for (; n < 16 && valid_cidr; ++n) + if (netmask[n] != 0x00) + valid_cidr = false; + + /* Format output */ + std::string strNetmask; + if (valid_cidr) { + strNetmask = strprintf("%u", cidr); + } else { + if (network.IsIPv4()) + strNetmask = strprintf("%u.%u.%u.%u", netmask[12], netmask[13], netmask[14], netmask[15]); + else + strNetmask = strprintf("%x:%x:%x:%x:%x:%x:%x:%x", + netmask[0] << 8 | netmask[1], netmask[2] << 8 | netmask[3], + netmask[4] << 8 | netmask[5], netmask[6] << 8 | netmask[7], + netmask[8] << 8 | netmask[9], netmask[10] << 8 | netmask[11], + netmask[12] << 8 | netmask[13], netmask[14] << 8 | netmask[15]); + } + + return network.ToString() + "/" + strNetmask; +} + +bool CSubNet::IsValid() const +{ + return valid; +} + +bool operator==(const CSubNet& a, const CSubNet& b) +{ + return a.valid == b.valid && a.network == b.network && !memcmp(a.netmask, b.netmask, 16); +} + +bool operator!=(const CSubNet& a, const CSubNet& b) +{ + return !(a==b); +} + +bool operator<(const CSubNet& a, const CSubNet& b) +{ + return (a.network < b.network || (a.network == b.network && memcmp(a.netmask, b.netmask, 16) < 0)); +} diff --git a/src/netaddress.h b/src/netaddress.h new file mode 100644 index 0000000000000..9330fe3328582 --- /dev/null +++ b/src/netaddress.h @@ -0,0 +1,171 @@ +// Copyright (c) 2009-2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_NETADDRESS_H +#define BITCOIN_NETADDRESS_H + +#if defined(HAVE_CONFIG_H) +#include "config/bitcoin-config.h" +#endif + +#include "compat.h" +#include "serialize.h" + +#include +#include +#include + +enum Network +{ + NET_UNROUTABLE = 0, + NET_IPV4, + NET_IPV6, + NET_TOR, + + NET_MAX, +}; + +/** IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96)) */ +class CNetAddr +{ + protected: + unsigned char ip[16]; // in network byte order + uint32_t scopeId; // for scoped/link-local ipv6 addresses + + public: + CNetAddr(); + CNetAddr(const struct in_addr& ipv4Addr); + void Init(); + void SetIP(const CNetAddr& ip); + + /** + * Set raw IPv4 or IPv6 address (in network byte order) + * @note Only NET_IPV4 and NET_IPV6 are allowed for network. + */ + void SetRaw(Network network, const uint8_t *data); + + bool SetSpecial(const std::string &strName); // for Tor addresses + bool IsIPv4() const; // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0) + bool IsIPv6() const; // IPv6 address (not mapped IPv4, not Tor) + bool IsRFC1918() const; // IPv4 private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12) + bool IsRFC2544() const; // IPv4 inter-network communcations (192.18.0.0/15) + bool IsRFC6598() const; // IPv4 ISP-level NAT (100.64.0.0/10) + bool IsRFC5737() const; // IPv4 documentation addresses (192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24) + bool IsRFC3849() const; // IPv6 documentation address (2001:0DB8::/32) + bool IsRFC3927() const; // IPv4 autoconfig (169.254.0.0/16) + bool IsRFC3964() const; // IPv6 6to4 tunnelling (2002::/16) + bool IsRFC4193() const; // IPv6 unique local (FC00::/7) + bool IsRFC4380() const; // IPv6 Teredo tunnelling (2001::/32) + bool IsRFC4843() const; // IPv6 ORCHID (2001:10::/28) + bool IsRFC4862() const; // IPv6 autoconfig (FE80::/64) + bool IsRFC6052() const; // IPv6 well-known prefix (64:FF9B::/96) + bool IsRFC6145() const; // IPv6 IPv4-translated address (::FFFF:0:0:0/96) + bool IsTor() const; + bool IsLocal() const; + bool IsRoutable() const; + bool IsValid() const; + bool IsMulticast() const; + enum Network GetNetwork() const; + std::string ToString() const; + std::string ToStringIP() const; + unsigned int GetByte(int n) const; + uint64_t GetHash() const; + bool GetInAddr(struct in_addr* pipv4Addr) const; + std::vector GetGroup() const; + int GetReachabilityFrom(const CNetAddr *paddrPartner = NULL) const; + + CNetAddr(const struct in6_addr& pipv6Addr, const uint32_t scope = 0); + bool GetIn6Addr(struct in6_addr* pipv6Addr) const; + + friend bool operator==(const CNetAddr& a, const CNetAddr& b); + friend bool operator!=(const CNetAddr& a, const CNetAddr& b); + friend bool operator<(const CNetAddr& a, const CNetAddr& b); + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + READWRITE(FLATDATA(ip)); + } + + friend class CSubNet; +}; + +class CSubNet +{ + protected: + /// Network (base) address + CNetAddr network; + /// Netmask, in network byte order + uint8_t netmask[16]; + /// Is this value valid? (only used to signal parse errors) + bool valid; + + public: + CSubNet(); + CSubNet(const CNetAddr &addr, int32_t mask); + CSubNet(const CNetAddr &addr, const CNetAddr &mask); + + //constructor for single ip subnet (/32 or /128) + explicit CSubNet(const CNetAddr &addr); + + bool Match(const CNetAddr &addr) const; + + std::string ToString() const; + bool IsValid() const; + + friend bool operator==(const CSubNet& a, const CSubNet& b); + friend bool operator!=(const CSubNet& a, const CSubNet& b); + friend bool operator<(const CSubNet& a, const CSubNet& b); + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + READWRITE(network); + READWRITE(FLATDATA(netmask)); + READWRITE(FLATDATA(valid)); + } +}; + +/** A combination of a network address (CNetAddr) and a (TCP) port */ +class CService : public CNetAddr +{ + protected: + unsigned short port; // host order + + public: + CService(); + CService(const CNetAddr& ip, unsigned short port); + CService(const struct in_addr& ipv4Addr, unsigned short port); + CService(const struct sockaddr_in& addr); + void Init(); + void SetPort(unsigned short portIn); + unsigned short GetPort() const; + bool GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const; + bool SetSockAddr(const struct sockaddr* paddr); + friend bool operator==(const CService& a, const CService& b); + friend bool operator!=(const CService& a, const CService& b); + friend bool operator<(const CService& a, const CService& b); + std::vector GetKey() const; + std::string ToString() const; + std::string ToStringPort() const; + std::string ToStringIPPort() const; + + CService(const struct in6_addr& ipv6Addr, unsigned short port); + CService(const struct sockaddr_in6& addr); + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + READWRITE(FLATDATA(ip)); + unsigned short portN = htons(port); + READWRITE(FLATDATA(portN)); + if (ser_action.ForRead()) + port = ntohs(portN); + } +}; + +#endif // BITCOIN_NETADDRESS_H diff --git a/src/netbase.cpp b/src/netbase.cpp index 52badcd98f5f8..c2294a078da51 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -42,8 +42,6 @@ static CCriticalSection cs_proxyInfos; int nConnectTimeout = DEFAULT_CONNECT_TIMEOUT; bool fNameLookup = DEFAULT_NAME_LOOKUP; -static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff }; - // Need ample time for negotiation for very slow proxies such as Tor (milliseconds) static const int SOCKS5_RECV_TIMEOUT = 20 * 1000; @@ -646,618 +644,6 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest return ConnectThroughProxy(nameProxy, strDest, port, hSocketRet, nTimeout, outProxyConnectionFailed); } -void CNetAddr::Init() -{ - memset(ip, 0, sizeof(ip)); - scopeId = 0; -} - -void CNetAddr::SetIP(const CNetAddr& ipIn) -{ - memcpy(ip, ipIn.ip, sizeof(ip)); -} - -void CNetAddr::SetRaw(Network network, const uint8_t *ip_in) -{ - switch(network) - { - case NET_IPV4: - memcpy(ip, pchIPv4, 12); - memcpy(ip+12, ip_in, 4); - break; - case NET_IPV6: - memcpy(ip, ip_in, 16); - break; - default: - assert(!"invalid network"); - } -} - -static const unsigned char pchOnionCat[] = {0xFD,0x87,0xD8,0x7E,0xEB,0x43}; - -bool CNetAddr::SetSpecial(const std::string &strName) -{ - if (strName.size()>6 && strName.substr(strName.size() - 6, 6) == ".onion") { - std::vector vchAddr = DecodeBase32(strName.substr(0, strName.size() - 6).c_str()); - if (vchAddr.size() != 16-sizeof(pchOnionCat)) - return false; - memcpy(ip, pchOnionCat, sizeof(pchOnionCat)); - for (unsigned int i=0; i<16-sizeof(pchOnionCat); i++) - ip[i + sizeof(pchOnionCat)] = vchAddr[i]; - return true; - } - return false; -} - -CNetAddr::CNetAddr() -{ - Init(); -} - -CNetAddr::CNetAddr(const struct in_addr& ipv4Addr) -{ - SetRaw(NET_IPV4, (const uint8_t*)&ipv4Addr); -} - -CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr, const uint32_t scope) -{ - SetRaw(NET_IPV6, (const uint8_t*)&ipv6Addr); - scopeId = scope; -} - -unsigned int CNetAddr::GetByte(int n) const -{ - return ip[15-n]; -} - -bool CNetAddr::IsIPv4() const -{ - return (memcmp(ip, pchIPv4, sizeof(pchIPv4)) == 0); -} - -bool CNetAddr::IsIPv6() const -{ - return (!IsIPv4() && !IsTor()); -} - -bool CNetAddr::IsRFC1918() const -{ - return IsIPv4() && ( - GetByte(3) == 10 || - (GetByte(3) == 192 && GetByte(2) == 168) || - (GetByte(3) == 172 && (GetByte(2) >= 16 && GetByte(2) <= 31))); -} - -bool CNetAddr::IsRFC2544() const -{ - return IsIPv4() && GetByte(3) == 198 && (GetByte(2) == 18 || GetByte(2) == 19); -} - -bool CNetAddr::IsRFC3927() const -{ - return IsIPv4() && (GetByte(3) == 169 && GetByte(2) == 254); -} - -bool CNetAddr::IsRFC6598() const -{ - return IsIPv4() && GetByte(3) == 100 && GetByte(2) >= 64 && GetByte(2) <= 127; -} - -bool CNetAddr::IsRFC5737() const -{ - return IsIPv4() && ((GetByte(3) == 192 && GetByte(2) == 0 && GetByte(1) == 2) || - (GetByte(3) == 198 && GetByte(2) == 51 && GetByte(1) == 100) || - (GetByte(3) == 203 && GetByte(2) == 0 && GetByte(1) == 113)); -} - -bool CNetAddr::IsRFC3849() const -{ - return GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x0D && GetByte(12) == 0xB8; -} - -bool CNetAddr::IsRFC3964() const -{ - return (GetByte(15) == 0x20 && GetByte(14) == 0x02); -} - -bool CNetAddr::IsRFC6052() const -{ - static const unsigned char pchRFC6052[] = {0,0x64,0xFF,0x9B,0,0,0,0,0,0,0,0}; - return (memcmp(ip, pchRFC6052, sizeof(pchRFC6052)) == 0); -} - -bool CNetAddr::IsRFC4380() const -{ - return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0 && GetByte(12) == 0); -} - -bool CNetAddr::IsRFC4862() const -{ - static const unsigned char pchRFC4862[] = {0xFE,0x80,0,0,0,0,0,0}; - return (memcmp(ip, pchRFC4862, sizeof(pchRFC4862)) == 0); -} - -bool CNetAddr::IsRFC4193() const -{ - return ((GetByte(15) & 0xFE) == 0xFC); -} - -bool CNetAddr::IsRFC6145() const -{ - static const unsigned char pchRFC6145[] = {0,0,0,0,0,0,0,0,0xFF,0xFF,0,0}; - return (memcmp(ip, pchRFC6145, sizeof(pchRFC6145)) == 0); -} - -bool CNetAddr::IsRFC4843() const -{ - return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x00 && (GetByte(12) & 0xF0) == 0x10); -} - -bool CNetAddr::IsTor() const -{ - return (memcmp(ip, pchOnionCat, sizeof(pchOnionCat)) == 0); -} - -bool CNetAddr::IsLocal() const -{ - // IPv4 loopback - if (IsIPv4() && (GetByte(3) == 127 || GetByte(3) == 0)) - return true; - - // IPv6 loopback (::1/128) - static const unsigned char pchLocal[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; - if (memcmp(ip, pchLocal, 16) == 0) - return true; - - return false; -} - -bool CNetAddr::IsMulticast() const -{ - return (IsIPv4() && (GetByte(3) & 0xF0) == 0xE0) - || (GetByte(15) == 0xFF); -} - -bool CNetAddr::IsValid() const -{ - // Cleanup 3-byte shifted addresses caused by garbage in size field - // of addr messages from versions before 0.2.9 checksum. - // Two consecutive addr messages look like this: - // header20 vectorlen3 addr26 addr26 addr26 header20 vectorlen3 addr26 addr26 addr26... - // so if the first length field is garbled, it reads the second batch - // of addr misaligned by 3 bytes. - if (memcmp(ip, pchIPv4+3, sizeof(pchIPv4)-3) == 0) - return false; - - // unspecified IPv6 address (::/128) - unsigned char ipNone[16] = {}; - if (memcmp(ip, ipNone, 16) == 0) - return false; - - // documentation IPv6 address - if (IsRFC3849()) - return false; - - if (IsIPv4()) - { - // INADDR_NONE - uint32_t ipNone = INADDR_NONE; - if (memcmp(ip+12, &ipNone, 4) == 0) - return false; - - // 0 - ipNone = 0; - if (memcmp(ip+12, &ipNone, 4) == 0) - return false; - } - - return true; -} - -bool CNetAddr::IsRoutable() const -{ - return IsValid() && !(IsRFC1918() || IsRFC2544() || IsRFC3927() || IsRFC4862() || IsRFC6598() || IsRFC5737() || (IsRFC4193() && !IsTor()) || IsRFC4843() || IsLocal()); -} - -enum Network CNetAddr::GetNetwork() const -{ - if (!IsRoutable()) - return NET_UNROUTABLE; - - if (IsIPv4()) - return NET_IPV4; - - if (IsTor()) - return NET_TOR; - - return NET_IPV6; -} - -std::string CNetAddr::ToStringIP() const -{ - if (IsTor()) - return EncodeBase32(&ip[6], 10) + ".onion"; - CService serv(*this, 0); - struct sockaddr_storage sockaddr; - socklen_t socklen = sizeof(sockaddr); - if (serv.GetSockAddr((struct sockaddr*)&sockaddr, &socklen)) { - char name[1025] = ""; - if (!getnameinfo((const struct sockaddr*)&sockaddr, socklen, name, sizeof(name), NULL, 0, NI_NUMERICHOST)) - return std::string(name); - } - if (IsIPv4()) - return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0)); - else - return strprintf("%x:%x:%x:%x:%x:%x:%x:%x", - GetByte(15) << 8 | GetByte(14), GetByte(13) << 8 | GetByte(12), - GetByte(11) << 8 | GetByte(10), GetByte(9) << 8 | GetByte(8), - GetByte(7) << 8 | GetByte(6), GetByte(5) << 8 | GetByte(4), - GetByte(3) << 8 | GetByte(2), GetByte(1) << 8 | GetByte(0)); -} - -std::string CNetAddr::ToString() const -{ - return ToStringIP(); -} - -bool operator==(const CNetAddr& a, const CNetAddr& b) -{ - return (memcmp(a.ip, b.ip, 16) == 0); -} - -bool operator!=(const CNetAddr& a, const CNetAddr& b) -{ - return (memcmp(a.ip, b.ip, 16) != 0); -} - -bool operator<(const CNetAddr& a, const CNetAddr& b) -{ - return (memcmp(a.ip, b.ip, 16) < 0); -} - -bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const -{ - if (!IsIPv4()) - return false; - memcpy(pipv4Addr, ip+12, 4); - return true; -} - -bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const -{ - memcpy(pipv6Addr, ip, 16); - return true; -} - -// get canonical identifier of an address' group -// no two connections will be attempted to addresses with the same group -std::vector CNetAddr::GetGroup() const -{ - std::vector vchRet; - int nClass = NET_IPV6; - int nStartByte = 0; - int nBits = 16; - - // all local addresses belong to the same group - if (IsLocal()) - { - nClass = 255; - nBits = 0; - } - - // all unroutable addresses belong to the same group - if (!IsRoutable()) - { - nClass = NET_UNROUTABLE; - nBits = 0; - } - // for IPv4 addresses, '1' + the 16 higher-order bits of the IP - // includes mapped IPv4, SIIT translated IPv4, and the well-known prefix - else if (IsIPv4() || IsRFC6145() || IsRFC6052()) - { - nClass = NET_IPV4; - nStartByte = 12; - } - // for 6to4 tunnelled addresses, use the encapsulated IPv4 address - else if (IsRFC3964()) - { - nClass = NET_IPV4; - nStartByte = 2; - } - // for Teredo-tunnelled IPv6 addresses, use the encapsulated IPv4 address - else if (IsRFC4380()) - { - vchRet.push_back(NET_IPV4); - vchRet.push_back(GetByte(3) ^ 0xFF); - vchRet.push_back(GetByte(2) ^ 0xFF); - return vchRet; - } - else if (IsTor()) - { - nClass = NET_TOR; - nStartByte = 6; - nBits = 4; - } - // for he.net, use /36 groups - else if (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x04 && GetByte(12) == 0x70) - nBits = 36; - // for the rest of the IPv6 network, use /32 groups - else - nBits = 32; - - vchRet.push_back(nClass); - while (nBits >= 8) - { - vchRet.push_back(GetByte(15 - nStartByte)); - nStartByte++; - nBits -= 8; - } - if (nBits > 0) - vchRet.push_back(GetByte(15 - nStartByte) | ((1 << (8 - nBits)) - 1)); - - return vchRet; -} - -uint64_t CNetAddr::GetHash() const -{ - uint256 hash = Hash(&ip[0], &ip[16]); - uint64_t nRet; - memcpy(&nRet, &hash, sizeof(nRet)); - return nRet; -} - -// private extensions to enum Network, only returned by GetExtNetwork, -// and only used in GetReachabilityFrom -static const int NET_UNKNOWN = NET_MAX + 0; -static const int NET_TEREDO = NET_MAX + 1; -int static GetExtNetwork(const CNetAddr *addr) -{ - if (addr == NULL) - return NET_UNKNOWN; - if (addr->IsRFC4380()) - return NET_TEREDO; - return addr->GetNetwork(); -} - -/** Calculates a metric for how reachable (*this) is from a given partner */ -int CNetAddr::GetReachabilityFrom(const CNetAddr *paddrPartner) const -{ - enum Reachability { - REACH_UNREACHABLE, - REACH_DEFAULT, - REACH_TEREDO, - REACH_IPV6_WEAK, - REACH_IPV4, - REACH_IPV6_STRONG, - REACH_PRIVATE - }; - - if (!IsRoutable()) - return REACH_UNREACHABLE; - - int ourNet = GetExtNetwork(this); - int theirNet = GetExtNetwork(paddrPartner); - bool fTunnel = IsRFC3964() || IsRFC6052() || IsRFC6145(); - - switch(theirNet) { - case NET_IPV4: - switch(ourNet) { - default: return REACH_DEFAULT; - case NET_IPV4: return REACH_IPV4; - } - case NET_IPV6: - switch(ourNet) { - default: return REACH_DEFAULT; - case NET_TEREDO: return REACH_TEREDO; - case NET_IPV4: return REACH_IPV4; - case NET_IPV6: return fTunnel ? REACH_IPV6_WEAK : REACH_IPV6_STRONG; // only prefer giving our IPv6 address if it's not tunnelled - } - case NET_TOR: - switch(ourNet) { - default: return REACH_DEFAULT; - case NET_IPV4: return REACH_IPV4; // Tor users can connect to IPv4 as well - case NET_TOR: return REACH_PRIVATE; - } - case NET_TEREDO: - switch(ourNet) { - default: return REACH_DEFAULT; - case NET_TEREDO: return REACH_TEREDO; - case NET_IPV6: return REACH_IPV6_WEAK; - case NET_IPV4: return REACH_IPV4; - } - case NET_UNKNOWN: - case NET_UNROUTABLE: - default: - switch(ourNet) { - default: return REACH_DEFAULT; - case NET_TEREDO: return REACH_TEREDO; - case NET_IPV6: return REACH_IPV6_WEAK; - case NET_IPV4: return REACH_IPV4; - case NET_TOR: return REACH_PRIVATE; // either from Tor, or don't care about our address - } - } -} - -void CService::Init() -{ - port = 0; -} - -CService::CService() -{ - Init(); -} - -CService::CService(const CNetAddr& cip, unsigned short portIn) : CNetAddr(cip), port(portIn) -{ -} - -CService::CService(const struct in_addr& ipv4Addr, unsigned short portIn) : CNetAddr(ipv4Addr), port(portIn) -{ -} - -CService::CService(const struct in6_addr& ipv6Addr, unsigned short portIn) : CNetAddr(ipv6Addr), port(portIn) -{ -} - -CService::CService(const struct sockaddr_in& addr) : CNetAddr(addr.sin_addr), port(ntohs(addr.sin_port)) -{ - assert(addr.sin_family == AF_INET); -} - -CService::CService(const struct sockaddr_in6 &addr) : CNetAddr(addr.sin6_addr, addr.sin6_scope_id), port(ntohs(addr.sin6_port)) -{ - assert(addr.sin6_family == AF_INET6); -} - -bool CService::SetSockAddr(const struct sockaddr *paddr) -{ - switch (paddr->sa_family) { - case AF_INET: - *this = CService(*(const struct sockaddr_in*)paddr); - return true; - case AF_INET6: - *this = CService(*(const struct sockaddr_in6*)paddr); - return true; - default: - return false; - } -} - -unsigned short CService::GetPort() const -{ - return port; -} - -bool operator==(const CService& a, const CService& b) -{ - return (CNetAddr)a == (CNetAddr)b && a.port == b.port; -} - -bool operator!=(const CService& a, const CService& b) -{ - return (CNetAddr)a != (CNetAddr)b || a.port != b.port; -} - -bool operator<(const CService& a, const CService& b) -{ - return (CNetAddr)a < (CNetAddr)b || ((CNetAddr)a == (CNetAddr)b && a.port < b.port); -} - -bool CService::GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const -{ - if (IsIPv4()) { - if (*addrlen < (socklen_t)sizeof(struct sockaddr_in)) - return false; - *addrlen = sizeof(struct sockaddr_in); - struct sockaddr_in *paddrin = (struct sockaddr_in*)paddr; - memset(paddrin, 0, *addrlen); - if (!GetInAddr(&paddrin->sin_addr)) - return false; - paddrin->sin_family = AF_INET; - paddrin->sin_port = htons(port); - return true; - } - if (IsIPv6()) { - if (*addrlen < (socklen_t)sizeof(struct sockaddr_in6)) - return false; - *addrlen = sizeof(struct sockaddr_in6); - struct sockaddr_in6 *paddrin6 = (struct sockaddr_in6*)paddr; - memset(paddrin6, 0, *addrlen); - if (!GetIn6Addr(&paddrin6->sin6_addr)) - return false; - paddrin6->sin6_scope_id = scopeId; - paddrin6->sin6_family = AF_INET6; - paddrin6->sin6_port = htons(port); - return true; - } - return false; -} - -std::vector CService::GetKey() const -{ - std::vector vKey; - vKey.resize(18); - memcpy(&vKey[0], ip, 16); - vKey[16] = port / 0x100; - vKey[17] = port & 0x0FF; - return vKey; -} - -std::string CService::ToStringPort() const -{ - return strprintf("%u", port); -} - -std::string CService::ToStringIPPort() const -{ - if (IsIPv4() || IsTor()) { - return ToStringIP() + ":" + ToStringPort(); - } else { - return "[" + ToStringIP() + "]:" + ToStringPort(); - } -} - -std::string CService::ToString() const -{ - return ToStringIPPort(); -} - -void CService::SetPort(unsigned short portIn) -{ - port = portIn; -} - -CSubNet::CSubNet(): - valid(false) -{ - memset(netmask, 0, sizeof(netmask)); -} - -CSubNet::CSubNet(const CNetAddr &addr, int32_t mask) -{ - valid = true; - network = addr; - // Default to /32 (IPv4) or /128 (IPv6), i.e. match single address - memset(netmask, 255, sizeof(netmask)); - - // IPv4 addresses start at offset 12, and first 12 bytes must match, so just offset n - const int astartofs = network.IsIPv4() ? 12 : 0; - - int32_t n = mask; - if(n >= 0 && n <= (128 - astartofs*8)) // Only valid if in range of bits of address - { - n += astartofs*8; - // Clear bits [n..127] - for (; n < 128; ++n) - netmask[n>>3] &= ~(1<<(7-(n&7))); - } else - valid = false; - - // Normalize network according to netmask - for(int x=0; x<16; ++x) - network.ip[x] &= netmask[x]; -} - -CSubNet::CSubNet(const CNetAddr &addr, const CNetAddr &mask) -{ - valid = true; - network = addr; - // Default to /32 (IPv4) or /128 (IPv6), i.e. match single address - memset(netmask, 255, sizeof(netmask)); - - // IPv4 addresses start at offset 12, and first 12 bytes must match, so just offset n - const int astartofs = network.IsIPv4() ? 12 : 0; - - for(int x=astartofs; x<16; ++x) - netmask[x] = mask.ip[x]; - - // Normalize network according to netmask - for(int x=0; x<16; ++x) - network.ip[x] &= netmask[x]; -} - - bool LookupSubNet(const char* pszName, CSubNet& ret) { std::string strSubnet(pszName); @@ -1295,97 +681,6 @@ bool LookupSubNet(const char* pszName, CSubNet& ret) return false; } -CSubNet::CSubNet(const CNetAddr &addr): - valid(addr.IsValid()) -{ - memset(netmask, 255, sizeof(netmask)); - network = addr; -} - -bool CSubNet::Match(const CNetAddr &addr) const -{ - if (!valid || !addr.IsValid()) - return false; - for(int x=0; x<16; ++x) - if ((addr.ip[x] & netmask[x]) != network.ip[x]) - return false; - return true; -} - -static inline int NetmaskBits(uint8_t x) -{ - switch(x) { - case 0x00: return 0; break; - case 0x80: return 1; break; - case 0xc0: return 2; break; - case 0xe0: return 3; break; - case 0xf0: return 4; break; - case 0xf8: return 5; break; - case 0xfc: return 6; break; - case 0xfe: return 7; break; - case 0xff: return 8; break; - default: return -1; break; - } -} - -std::string CSubNet::ToString() const -{ - /* Parse binary 1{n}0{N-n} to see if mask can be represented as /n */ - int cidr = 0; - bool valid_cidr = true; - int n = network.IsIPv4() ? 12 : 0; - for (; n < 16 && netmask[n] == 0xff; ++n) - cidr += 8; - if (n < 16) { - int bits = NetmaskBits(netmask[n]); - if (bits < 0) - valid_cidr = false; - else - cidr += bits; - ++n; - } - for (; n < 16 && valid_cidr; ++n) - if (netmask[n] != 0x00) - valid_cidr = false; - - /* Format output */ - std::string strNetmask; - if (valid_cidr) { - strNetmask = strprintf("%u", cidr); - } else { - if (network.IsIPv4()) - strNetmask = strprintf("%u.%u.%u.%u", netmask[12], netmask[13], netmask[14], netmask[15]); - else - strNetmask = strprintf("%x:%x:%x:%x:%x:%x:%x:%x", - netmask[0] << 8 | netmask[1], netmask[2] << 8 | netmask[3], - netmask[4] << 8 | netmask[5], netmask[6] << 8 | netmask[7], - netmask[8] << 8 | netmask[9], netmask[10] << 8 | netmask[11], - netmask[12] << 8 | netmask[13], netmask[14] << 8 | netmask[15]); - } - - return network.ToString() + "/" + strNetmask; -} - -bool CSubNet::IsValid() const -{ - return valid; -} - -bool operator==(const CSubNet& a, const CSubNet& b) -{ - return a.valid == b.valid && a.network == b.network && !memcmp(a.netmask, b.netmask, 16); -} - -bool operator!=(const CSubNet& a, const CSubNet& b) -{ - return !(a==b); -} - -bool operator<(const CSubNet& a, const CSubNet& b) -{ - return (a.network < b.network || (a.network == b.network && memcmp(a.netmask, b.netmask, 16) < 0)); -} - #ifdef WIN32 std::string NetworkErrorString(int err) { diff --git a/src/netbase.h b/src/netbase.h index 26807ae69733a..d0abd5e954ef4 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -10,6 +10,7 @@ #endif #include "compat.h" +#include "netaddress.h" #include "serialize.h" #include @@ -24,163 +25,6 @@ static const int DEFAULT_CONNECT_TIMEOUT = 5000; //! -dns default static const int DEFAULT_NAME_LOOKUP = true; -#ifdef WIN32 -// In MSVC, this is defined as a macro, undefine it to prevent a compile and link error -#undef SetPort -#endif - -enum Network -{ - NET_UNROUTABLE = 0, - NET_IPV4, - NET_IPV6, - NET_TOR, - - NET_MAX, -}; - -/** IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96)) */ -class CNetAddr -{ - protected: - unsigned char ip[16]; // in network byte order - uint32_t scopeId; // for scoped/link-local ipv6 addresses - - public: - CNetAddr(); - CNetAddr(const struct in_addr& ipv4Addr); - void Init(); - void SetIP(const CNetAddr& ip); - - /** - * Set raw IPv4 or IPv6 address (in network byte order) - * @note Only NET_IPV4 and NET_IPV6 are allowed for network. - */ - void SetRaw(Network network, const uint8_t *data); - - bool SetSpecial(const std::string &strName); // for Tor addresses - bool IsIPv4() const; // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0) - bool IsIPv6() const; // IPv6 address (not mapped IPv4, not Tor) - bool IsRFC1918() const; // IPv4 private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12) - bool IsRFC2544() const; // IPv4 inter-network communcations (192.18.0.0/15) - bool IsRFC6598() const; // IPv4 ISP-level NAT (100.64.0.0/10) - bool IsRFC5737() const; // IPv4 documentation addresses (192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24) - bool IsRFC3849() const; // IPv6 documentation address (2001:0DB8::/32) - bool IsRFC3927() const; // IPv4 autoconfig (169.254.0.0/16) - bool IsRFC3964() const; // IPv6 6to4 tunnelling (2002::/16) - bool IsRFC4193() const; // IPv6 unique local (FC00::/7) - bool IsRFC4380() const; // IPv6 Teredo tunnelling (2001::/32) - bool IsRFC4843() const; // IPv6 ORCHID (2001:10::/28) - bool IsRFC4862() const; // IPv6 autoconfig (FE80::/64) - bool IsRFC6052() const; // IPv6 well-known prefix (64:FF9B::/96) - bool IsRFC6145() const; // IPv6 IPv4-translated address (::FFFF:0:0:0/96) - bool IsTor() const; - bool IsLocal() const; - bool IsRoutable() const; - bool IsValid() const; - bool IsMulticast() const; - enum Network GetNetwork() const; - std::string ToString() const; - std::string ToStringIP() const; - unsigned int GetByte(int n) const; - uint64_t GetHash() const; - bool GetInAddr(struct in_addr* pipv4Addr) const; - std::vector GetGroup() const; - int GetReachabilityFrom(const CNetAddr *paddrPartner = NULL) const; - - CNetAddr(const struct in6_addr& pipv6Addr, const uint32_t scope = 0); - bool GetIn6Addr(struct in6_addr* pipv6Addr) const; - - friend bool operator==(const CNetAddr& a, const CNetAddr& b); - friend bool operator!=(const CNetAddr& a, const CNetAddr& b); - friend bool operator<(const CNetAddr& a, const CNetAddr& b); - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(FLATDATA(ip)); - } - - friend class CSubNet; -}; - -class CSubNet -{ - protected: - /// Network (base) address - CNetAddr network; - /// Netmask, in network byte order - uint8_t netmask[16]; - /// Is this value valid? (only used to signal parse errors) - bool valid; - - public: - CSubNet(); - CSubNet(const CNetAddr &addr, int32_t mask); - CSubNet(const CNetAddr &addr, const CNetAddr &mask); - - //constructor for single ip subnet (/32 or /128) - explicit CSubNet(const CNetAddr &addr); - - bool Match(const CNetAddr &addr) const; - - std::string ToString() const; - bool IsValid() const; - - friend bool operator==(const CSubNet& a, const CSubNet& b); - friend bool operator!=(const CSubNet& a, const CSubNet& b); - friend bool operator<(const CSubNet& a, const CSubNet& b); - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(network); - READWRITE(FLATDATA(netmask)); - READWRITE(FLATDATA(valid)); - } -}; - -/** A combination of a network address (CNetAddr) and a (TCP) port */ -class CService : public CNetAddr -{ - protected: - unsigned short port; // host order - - public: - CService(); - CService(const CNetAddr& ip, unsigned short port); - CService(const struct in_addr& ipv4Addr, unsigned short port); - CService(const struct sockaddr_in& addr); - void Init(); - void SetPort(unsigned short portIn); - unsigned short GetPort() const; - bool GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const; - bool SetSockAddr(const struct sockaddr* paddr); - friend bool operator==(const CService& a, const CService& b); - friend bool operator!=(const CService& a, const CService& b); - friend bool operator<(const CService& a, const CService& b); - std::vector GetKey() const; - std::string ToString() const; - std::string ToStringPort() const; - std::string ToStringIPPort() const; - - CService(const struct in6_addr& ipv6Addr, unsigned short port); - CService(const struct sockaddr_in6& addr); - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(FLATDATA(ip)); - unsigned short portN = htons(port); - READWRITE(FLATDATA(portN)); - if (ser_action.ForRead()) - port = ntohs(portN); - } -}; - class proxyType { public: From 21ba407a7369a0229b8a8554dee0da63a64e6639 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 31 May 2016 17:42:38 -0400 Subject: [PATCH 0684/1802] net: narrow include scope after moving to netaddress Net functionality is no longer needed for CAddress/CAddrman/etc. now that CNetAddr/CService/CSubNet are dumb storage classes. --- src/addrman.h | 2 +- src/init.cpp | 1 + src/net.cpp | 1 + src/net.h | 2 +- src/protocol.h | 2 +- src/qt/optionsmodel.cpp | 1 + src/qt/rpcconsole.cpp | 1 + src/test/addrman_tests.cpp | 1 + src/test/net_tests.cpp | 1 + src/timedata.cpp | 2 +- src/torcontrol.cpp | 1 + src/wallet/rpcwallet.cpp | 1 - 12 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/addrman.h b/src/addrman.h index 1caf540758797..9bab39049d7ab 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -6,7 +6,7 @@ #ifndef BITCOIN_ADDRMAN_H #define BITCOIN_ADDRMAN_H -#include "netbase.h" +#include "netaddress.h" #include "protocol.h" #include "random.h" #include "sync.h" diff --git a/src/init.cpp b/src/init.cpp index 8b94e2dbfb126..4f5eeeffe67e7 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -21,6 +21,7 @@ #include "key.h" #include "main.h" #include "miner.h" +#include "netbase.h" #include "net.h" #include "policy/policy.h" #include "rpc/server.h" diff --git a/src/net.cpp b/src/net.cpp index e44bdafc79889..e9bb406e976c5 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -17,6 +17,7 @@ #include "crypto/sha256.h" #include "hash.h" #include "primitives/transaction.h" +#include "netbase.h" #include "scheduler.h" #include "ui_interface.h" #include "utilstrencodings.h" diff --git a/src/net.h b/src/net.h index 41315fc9b9fcc..ea03defc408cf 100644 --- a/src/net.h +++ b/src/net.h @@ -10,7 +10,7 @@ #include "bloom.h" #include "compat.h" #include "limitedmap.h" -#include "netbase.h" +#include "netaddress.h" #include "protocol.h" #include "random.h" #include "streams.h" diff --git a/src/protocol.h b/src/protocol.h index 15f27e2d2fbcb..015215b2a668b 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -10,7 +10,7 @@ #ifndef BITCOIN_PROTOCOL_H #define BITCOIN_PROTOCOL_H -#include "netbase.h" +#include "netaddress.h" #include "serialize.h" #include "uint256.h" #include "version.h" diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 684db71a8ce03..d33ab682770f0 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -15,6 +15,7 @@ #include "init.h" #include "main.h" // For DEFAULT_SCRIPTCHECK_THREADS #include "net.h" +#include "netbase.h" #include "txdb.h" // for -dbcache defaults #ifdef ENABLE_WALLET diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 21eda07ddffd0..bcaa9164c91ba 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -16,6 +16,7 @@ #include "bantablemodel.h" #include "chainparams.h" +#include "netbase.h" #include "rpc/server.h" #include "rpc/client.h" #include "util.h" diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp index b84d00856bd66..5f150e4812af5 100644 --- a/src/test/addrman_tests.cpp +++ b/src/test/addrman_tests.cpp @@ -7,6 +7,7 @@ #include #include "hash.h" +#include "netbase.h" #include "random.h" using namespace std; diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index fca1a16b2dc81..6511e6ffa24f1 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -9,6 +9,7 @@ #include "serialize.h" #include "streams.h" #include "net.h" +#include "netbase.h" #include "chainparams.h" using namespace std; diff --git a/src/timedata.cpp b/src/timedata.cpp index b6bcf86fbf261..25fc494121d4d 100644 --- a/src/timedata.cpp +++ b/src/timedata.cpp @@ -8,7 +8,7 @@ #include "timedata.h" -#include "netbase.h" +#include "netaddress.h" #include "sync.h" #include "ui_interface.h" #include "util.h" diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index d3d782747fd2c..c7f96270050ac 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -4,6 +4,7 @@ #include "torcontrol.h" #include "utilstrencodings.h" +#include "netbase.h" #include "net.h" #include "util.h" #include "crypto/hmac_sha256.h" diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index a90807e5141b7..aa0a9374c1991 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -10,7 +10,6 @@ #include "init.h" #include "main.h" #include "net.h" -#include "netbase.h" #include "policy/rbf.h" #include "rpc/server.h" #include "timedata.h" From ff8d279a78fef40224665353624771cd970c6095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Fri, 27 May 2016 08:00:56 +0200 Subject: [PATCH 0685/1802] Do not shadow member variables --- src/httprpc.cpp | 2 +- src/httpserver.cpp | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/httprpc.cpp b/src/httprpc.cpp index 04d3386e9a922..6a6c5276cc1e5 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -45,7 +45,7 @@ class HTTPRPCTimer : public RPCTimerBase class HTTPRPCTimerInterface : public RPCTimerInterface { public: - HTTPRPCTimerInterface(struct event_base* base) : base(base) + HTTPRPCTimerInterface(struct event_base* _base) : base(_base) { } const char* Name() diff --git a/src/httpserver.cpp b/src/httpserver.cpp index be7a6a1ddee86..64ccb263edfce 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -42,8 +42,8 @@ static const size_t MAX_HEADERS_SIZE = 8192; class HTTPWorkItem : public HTTPClosure { public: - HTTPWorkItem(std::unique_ptr req, const std::string &path, const HTTPRequestHandler& func): - req(std::move(req)), path(path), func(func) + HTTPWorkItem(std::unique_ptr _req, const std::string &_path, const HTTPRequestHandler& _func): + req(std::move(_req)), path(_path), func(_func) { } void operator()() @@ -92,8 +92,8 @@ class WorkQueue }; public: - WorkQueue(size_t maxDepth) : running(true), - maxDepth(maxDepth), + WorkQueue(size_t _maxDepth) : running(true), + maxDepth(_maxDepth), numThreads(0) { } @@ -158,8 +158,8 @@ class WorkQueue struct HTTPPathHandler { HTTPPathHandler() {} - HTTPPathHandler(std::string prefix, bool exactMatch, HTTPRequestHandler handler): - prefix(prefix), exactMatch(exactMatch), handler(handler) + HTTPPathHandler(std::string _prefix, bool _exactMatch, HTTPRequestHandler _handler): + prefix(_prefix), exactMatch(_exactMatch), handler(_handler) { } std::string prefix; @@ -517,8 +517,8 @@ static void httpevent_callback_fn(evutil_socket_t, short, void* data) delete self; } -HTTPEvent::HTTPEvent(struct event_base* base, bool deleteWhenTriggered, const std::function& handler): - deleteWhenTriggered(deleteWhenTriggered), handler(handler) +HTTPEvent::HTTPEvent(struct event_base* base, bool _deleteWhenTriggered, const std::function& _handler): + deleteWhenTriggered(_deleteWhenTriggered), handler(_handler) { ev = event_new(base, -1, 0, httpevent_callback_fn, this); assert(ev); @@ -534,7 +534,7 @@ void HTTPEvent::trigger(struct timeval* tv) else evtimer_add(ev, tv); // trigger after timeval passed } -HTTPRequest::HTTPRequest(struct evhttp_request* req) : req(req), +HTTPRequest::HTTPRequest(struct evhttp_request* _req) : req(_req), replySent(false) { } From 7fdbce9de43c600776e00a2f2042d302cfa4e411 Mon Sep 17 00:00:00 2001 From: fanquake Date: Mon, 1 Aug 2016 09:30:32 +0800 Subject: [PATCH 0686/1802] [doc] Increase recommended memory in gitian build guide --- doc/gitian-building.md | 2 +- doc/gitian-building/create_vm_memsize.png | Bin 89475 -> 22158 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/gitian-building.md b/doc/gitian-building.md index 7796a5fc9c151..938f92ff1281f 100644 --- a/doc/gitian-building.md +++ b/doc/gitian-building.md @@ -55,7 +55,7 @@ In the VirtualBox GUI click "New" and choose the following parameters in the wiz ![](gitian-building/create_vm_memsize.png) -- Memory Size: at least 1024MB, anything less will really slow down the build. +- Memory Size: at least 3000MB, anything less and the build might not complete. ![](gitian-building/create_vm_hard_disk.png) diff --git a/doc/gitian-building/create_vm_memsize.png b/doc/gitian-building/create_vm_memsize.png index 5abfee5337058f9bd638a79416040bd6c6496194..6f42cda73f3cabb02e39ae0309ac67f419a168c7 100644 GIT binary patch literal 22158 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%0A-nL7Zl65qAwp5y$_efz^}#|Q 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 FV1lysU>^Vg literal 89475 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

(1ib00c7Uh`P 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%0D`!``7%Iy`oE2(Ay6%F`o0ngQ6nw&sA0b06X z#*NT^_<661=B>ryy_TG&ojwav{C937;%VT-*;bVL@H)6uv=;cdL1@U`ib>mgq>tlq zRLm`S;U#M7-f@lK%ih$?6zvQSQh>5Z#%eDB+ji1R?K_sQuY0#ILSdM%c~ERN@zc23DNg%Hi@;j(4xdQcdT8 z8ATxNc}f9tmr*fnvw<7Gyvp;*p^R%JR`GBepg|`pLN-b#<{-bjOfZ$PMAj`^C}cW7 z0hB9`39BuN+2rgUEqZhk!9!eFW}s)UM9`pKz+)AFng94a-uS47N4q;a-%d9MPuD)s zF;YK2AJpGclUmyEA1rN|+6`Yh9t=f&vcqUqHyQQ1vFZ21B3ozY;73!;HbH8lLU!U| znY=D;O$`Hb^EQTv%-Si?CZgOiwGFxQD<=RF!?2tY<#C3eY|$2-6q|(=vsy&b?QRnl zvl(#Lj9jw_hLh$KGLl057$*Wm6K-Tqmn*o5fbQPhp3*MTkg` z8l_awv!@b##NkRh3u!i4Ags@kGy`=C-4&+Yn5f1!xT>w~*%;DwM$4C1*g}B*+~AQ7 z1r7G$Vrf&Z2z1C!K--6zo8z#@48M6$yPD?t=cl(2HbMa6lA9-bg4P1K$9pY0h_WV z*CdApo>O0IG^~1xMT$=+REliexO4p-^k)d0aZwM^6}a-XbxFd~ft94F=6EU;&BC6{ zVK}l9JwQuYzs_N8vm}H&p%kW*^IB>4mqh4uPhS7D8;_hPgk&v6Sk~c#H12Jh!%5eD zJFkFBMGe^p`~@z{Pyh?Pu*cPySDVa)o^e4LTLkBe2NcZ-;aEiz;Xuv>A8ZETgoZx7 z61rNZ*@C|h4iMb6fFfi8X4w+xH{Vn_>eZ~fm(PNp8ayY17rf4V>y*V((1WJ&j|ci+ zjK2y93(Xv6;ST;J&8C4pd*U2C%v~jL-Ef%!lqtE09UC0ZYf*5VR^DExnXc1L-D>_s zQ6E+SqvbY2JEP%?Br>tAgF-qP&4tOL*!d5e1rs9_MjQWU zyx^jd(V~uxO{dMxM<29^n}clZcnGN_(w5DM6+RaYyr^^b3Mbl3Mq%+q!Le*WJ9iXM zR60^-IM67E>d2^!wD1lp*(N9&mpjS5S4%4LKhdo@@FVF5FZ7F3lAa%exTA1WD*b1ry{fjU=!M(3QjJFo5l0Cn6@>{ zu>rWZ>f0BW{IrQZ*G4SLRth7jmPrMs{{PR$3b1O%jd>M zcFP{)H;0qt9c^l4Z_MVD3H6XZKyWe+HdaK%#Dq5_n8%)~L_^WZ3)8gH#BHbE5dhr_ zQDQ#TdxW7bnMPr!C32A&CybM25+H$x%_+Co&XUc}VvHPA)J;>RKONmDv4~26hY0ya zW~k5jjAoO?myc}G3b(v!$t(*JZqZoJFvMK#RmV&YdnAp&c$mO`H ztfpQD=a1u)s>RdPJm^J!1ieAy8O})vvy6z5_XRUVOz^bk?oSnrB8R;}QLofUhl|=I zq!47JRB(XdynP9&4J#GrE(tu(ZL;4qK8F?WQNY^W3o|)6oN3`xo-w9rv`_d@-S_hI zoX^8d+Lm8hS|l&n(p0w>2vAb!cnA>??1iSbN%RQ$5hWtZhB)25z3c>2cz)TPv^ex- zKw|tPNE;L0@VvozIywG570c^Hw~D2*_E4mu{*9$;Qj@U0-(3spJmL%V|3ApncUg3N zNhCSQACBeKHnn9>Un(iSj!WRRRZ?L5G1WwG&OIonbrGTVVcndgCp)wG$4ilFl+wEg z5_-dT)aB(iDn&TR1F034CcUDJf7>el1uqKn^ddY6baQNhf=I;i8WFXSdMd_*)9XpS zwzKmsQYw5QIhCspBO+#+^1s`~7NCiN8~Jmb+=;awk)krbbZtBxc|6+_{~w3<-~2_C z-~Qm>8|FEx$geaa6G&)ren1>5||m>&pKN`KYk&$l$bjvv=6VYbbw~ Nih`zmjjYA{{{SC4x1s<5 From fa4439d3554435bdf0ef47861835f10d41bcdc1a Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 31 Jul 2016 15:35:46 +0200 Subject: [PATCH 0687/1802] [qa] Rework hd wallet dump test --- qa/rpc-tests/wallet-dump.py | 144 ++++++++++++++++-------------------- 1 file changed, 64 insertions(+), 80 deletions(-) diff --git a/qa/rpc-tests/wallet-dump.py b/qa/rpc-tests/wallet-dump.py index dd675f57fc46a..6028d2c20b191 100755 --- a/qa/rpc-tests/wallet-dump.py +++ b/qa/rpc-tests/wallet-dump.py @@ -4,9 +4,52 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * -import os -import shutil +from test_framework.util import (start_nodes, start_node, assert_equal, bitcoind_processes) + + +def read_dump(file_name, addrs, hd_master_addr_old): + """ + Read the given dump, count the addrs that match, count change and reserve. + Also check that the old hd_master is inactive + """ + with open(file_name) as inputfile: + found_addr = 0 + found_addr_chg = 0 + found_addr_rsv = 0 + hd_master_addr_ret = None + for line in inputfile: + # only read non comment lines + if line[0] != "#" and len(line) > 10: + # split out some data + key_label, comment = line.split("#") + # key = key_label.split(" ")[0] + keytype = key_label.split(" ")[2] + if len(comment) > 1: + addr_keypath = comment.split(" addr=")[1] + addr = addr_keypath.split(" ")[0] + keypath = None + if keytype == "inactivehdmaster=1": + # ensure the old master is still available + assert(hd_master_addr_old == addr) + elif keytype == "hdmaster=1": + # ensure we have generated a new hd master key + assert(hd_master_addr_old != addr) + hd_master_addr_ret = addr + else: + keypath = addr_keypath.rstrip().split("hdkeypath=")[1] + + # count key types + for addrObj in addrs: + if addrObj['address'] == addr and addrObj['hdkeypath'] == keypath and keytype == "label=": + found_addr += 1 + break + elif keytype == "change=1": + found_addr_chg += 1 + break + elif keytype == "reserve=1": + found_addr_rsv += 1 + break + return found_addr, found_addr_chg, found_addr_rsv, hd_master_addr_ret class WalletDumpTest(BitcoinTestFramework): @@ -15,106 +58,47 @@ def __init__(self): super().__init__() self.setup_clean_chain = False self.num_nodes = 1 + self.extra_args = [["-keypool=90"]] def setup_network(self, split=False): - extra_args = [["-keypool=100"]] - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args) + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args) def run_test (self): tmpdir = self.options.tmpdir - #generate 20 addresses to compare against the dump + # generate 20 addresses to compare against the dump test_addr_count = 20 addrs = [] for i in range(0,test_addr_count): addr = self.nodes[0].getnewaddress() vaddr= self.nodes[0].validateaddress(addr) #required to get hd keypath addrs.append(vaddr) + # Should be a no-op: + self.nodes[0].keypoolrefill() # dump unencrypted wallet self.nodes[0].dumpwallet(tmpdir + "/node0/wallet.unencrypted.dump") - #open file - inputfile = open(tmpdir + "/node0/wallet.unencrypted.dump") - found_addr = 0 - found_addr_chg = 0 - found_addr_rsv = 0 - hdmasteraddr = "" - for line in inputfile: - #only read non comment lines - if line[0] != "#" and len(line) > 10: - #split out some data - keyLabel, comment = line.split("#") - key = keyLabel.split(" ")[0] - keytype = keyLabel.split(" ")[2] - if len(comment) > 1: - addrKeypath = comment.split(" addr=")[1] - addr = addrKeypath.split(" ")[0] - keypath = "" - if keytype != "hdmaster=1": - keypath = addrKeypath.rstrip().split("hdkeypath=")[1] - else: - #keep hd master for later comp. - hdmasteraddr = addr - - #count key types - for addrObj in addrs: - if (addrObj['address'] == addr and addrObj['hdkeypath'] == keypath and keytype == "label="): - found_addr+=1 - break - elif (keytype == "change=1"): - found_addr_chg+=1 - break - elif (keytype == "reserve=1"): - found_addr_rsv+=1 - break - assert(found_addr == test_addr_count) #all keys must be in the dump - assert(found_addr_chg == 50) #50 blocks where mined - assert(found_addr_rsv == 100) #100 reserve keys (keypool) + found_addr, found_addr_chg, found_addr_rsv, hd_master_addr_unenc = \ + read_dump(tmpdir + "/node0/wallet.unencrypted.dump", addrs, None) + assert_equal(found_addr, test_addr_count) # all keys must be in the dump + assert_equal(found_addr_chg, 50) # 50 blocks where mined + assert_equal(found_addr_rsv, 90 + 1) # keypool size (TODO: fix off-by-one) #encrypt wallet, restart, unlock and dump self.nodes[0].encryptwallet('test') bitcoind_processes[0].wait() - self.nodes[0] = start_node(0, self.options.tmpdir) + self.nodes[0] = start_node(0, self.options.tmpdir, self.extra_args[0]) self.nodes[0].walletpassphrase('test', 10) + # Should be a no-op: + self.nodes[0].keypoolrefill() self.nodes[0].dumpwallet(tmpdir + "/node0/wallet.encrypted.dump") - #open dump done with an encrypted wallet - inputfile = open(tmpdir + "/node0/wallet.encrypted.dump") - found_addr = 0 - found_addr_chg = 0 - found_addr_rsv = 0 - for line in inputfile: - if line[0] != "#" and len(line) > 10: - keyLabel, comment = line.split("#") - key = keyLabel.split(" ")[0] - keytype = keyLabel.split(" ")[2] - if len(comment) > 1: - addrKeypath = comment.split(" addr=")[1] - addr = addrKeypath.split(" ")[0] - keypath = "" - if keytype != "hdmaster=1": - keypath = addrKeypath.rstrip().split("hdkeypath=")[1] - else: - #ensure we have generated a new hd master key - assert(hdmasteraddr != addr) - if keytype == "inactivehdmaster=1": - #ensure the old master is still available - assert(hdmasteraddr == addr) - for addrObj in addrs: - if (addrObj['address'] == addr and addrObj['hdkeypath'] == keypath and keytype == "label="): - found_addr+=1 - break - elif (keytype == "change=1"): - found_addr_chg+=1 - break - elif (keytype == "reserve=1"): - found_addr_rsv+=1 - break - - assert(found_addr == test_addr_count) - assert(found_addr_chg == 150) #old reserve keys are marked as change now - assert(found_addr_rsv == 100) #keypool size + found_addr, found_addr_chg, found_addr_rsv, hd_master_addr_enc = \ + read_dump(tmpdir + "/node0/wallet.encrypted.dump", addrs, hd_master_addr_unenc) + assert_equal(found_addr, test_addr_count) + assert_equal(found_addr_chg, 90 + 1 + 50) # old reserve keys are marked as change now + assert_equal(found_addr_rsv, 90 + 1) # keypool size (TODO: fix off-by-one) if __name__ == '__main__': WalletDumpTest().main () From 2c517b3928a68c6e36b18262081a401a741cd4cd Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Mon, 1 Aug 2016 12:40:38 -0400 Subject: [PATCH 0688/1802] Fix p2p-feefilter.py for changed tx relay behavior --- qa/rpc-tests/p2p-feefilter.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/qa/rpc-tests/p2p-feefilter.py b/qa/rpc-tests/p2p-feefilter.py index cd0501a3140c3..96d99d38a73c1 100755 --- a/qa/rpc-tests/p2p-feefilter.py +++ b/qa/rpc-tests/p2p-feefilter.py @@ -62,6 +62,7 @@ def setup_network(self): def run_test(self): node1 = self.nodes[1] + node0 = self.nodes[0] # Get out of IBD node1.generate(1) sync_blocks(self.nodes) @@ -91,8 +92,17 @@ def run_test(self): node1.settxfee(Decimal("0.00010000")) [node1.sendtoaddress(node1.getnewaddress(), 1) for x in range(3)] sync_mempools(self.nodes) # must be sure node 0 has received all txs - time.sleep(10) # wait 10 secs to be sure its doesn't relay any - assert(allInvsMatch([], test_node)) + + # Send one transaction from node0 that should be received, so that we + # we can sync the test on receipt (if node1's txs were relayed, they'd + # be received by the time this node0 tx is received). This is + # unfortunately reliant on the current relay behavior where we batch up + # to 35 entries in an inv, which means that when this next transaction + # is eligible for relay, the prior transactions from node1 are eligible + # as well. + node0.settxfee(Decimal("0.00020000")) + txids = [node0.sendtoaddress(node0.getnewaddress(), 1)] + assert(allInvsMatch(txids, test_node)) test_node.clear_invs() # Remove fee filter and check that txs are received again From 115265bb1060533bc1b73a10c5ca17ad64fbaf45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Tue, 2 Aug 2016 10:26:05 +0200 Subject: [PATCH 0689/1802] Trivial: bip -> BIP in help text and comment --- src/init.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 5dc3ac023ccf8..a3560afef8c8e 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -410,7 +410,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-limitancestorsize=", strprintf("Do not accept transactions whose size with all in-mempool ancestors exceeds kilobytes (default: %u)", DEFAULT_ANCESTOR_SIZE_LIMIT)); strUsage += HelpMessageOpt("-limitdescendantcount=", strprintf("Do not accept transactions if any ancestor would have or more in-mempool descendants (default: %u)", DEFAULT_DESCENDANT_LIMIT)); strUsage += HelpMessageOpt("-limitdescendantsize=", strprintf("Do not accept transactions if any ancestor would have more than kilobytes of in-mempool descendants (default: %u).", DEFAULT_DESCENDANT_SIZE_LIMIT)); - strUsage += HelpMessageOpt("-bip9params=deployment:start:end", "Use given start/end times for specified bip9 deployment (regtest-only)"); + strUsage += HelpMessageOpt("-bip9params=deployment:start:end", "Use given start/end times for specified BIP9 deployment (regtest-only)"); } string debugCategories = "addrman, alert, bench, coindb, db, http, libevent, lock, mempool, mempoolrej, net, proxy, prune, rand, reindex, rpc, selectcoins, tor, zmq"; // Don't translate these and qt below if (mode == HMM_BITCOIN_QT) @@ -977,7 +977,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) } if (!mapMultiArgs["-bip9params"].empty()) { - // Allow overriding bip9 parameters for testing + // Allow overriding BIP9 parameters for testing if (!Params().MineBlocksOnDemand()) { return InitError("BIP9 parameters may only be overridden on regtest."); } From 0fc00bea5d24f4a6715f7069adb7b7396c981308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Tue, 2 Aug 2016 10:26:54 +0200 Subject: [PATCH 0690/1802] Do not shadow previous local variable --- src/init.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index a3560afef8c8e..cb3dfe3aa49af 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -996,10 +996,10 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) return InitError(strprintf("Invalid nTimeout (%s)", vDeploymentParams[2])); } bool found = false; - for (int i=0; i<(int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++i) + for (int j=0; j<(int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) { - if (vDeploymentParams[0].compare(VersionBitsDeploymentInfo[i].name) == 0) { - UpdateRegtestBIP9Parameters(Consensus::DeploymentPos(i), nStartTime, nTimeout); + if (vDeploymentParams[0].compare(VersionBitsDeploymentInfo[j].name) == 0) { + UpdateRegtestBIP9Parameters(Consensus::DeploymentPos(j), nStartTime, nTimeout); found = true; LogPrintf("Setting BIP9 activation parameters for %s to start=%ld, timeout=%ld\n", vDeploymentParams[0], nStartTime, nTimeout); break; From cce3024c23aceb097ac32c00f84e613bf94e9995 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Wed, 3 Aug 2016 19:45:24 +0200 Subject: [PATCH 0691/1802] Do not shadow local variable, cleanup --- src/blockencodings.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/blockencodings.h b/src/blockencodings.h index b980e9e28660f..349fcbd50f8c7 100644 --- a/src/blockencodings.h +++ b/src/blockencodings.h @@ -53,11 +53,11 @@ class BlockTransactionsRequest { } uint16_t offset = 0; - for (size_t i = 0; i < indexes.size(); i++) { - if (uint64_t(indexes[i]) + uint64_t(offset) > std::numeric_limits::max()) + for (size_t j = 0; j < indexes.size(); j++) { + if (uint64_t(indexes[j]) + uint64_t(offset) > std::numeric_limits::max()) throw std::ios_base::failure("indexes overflowed 16 bits"); - indexes[i] = indexes[i] + offset; - offset = indexes[i] + 1; + indexes[j] = indexes[j] + offset; + offset = indexes[j] + 1; } } else { for (size_t i = 0; i < indexes.size(); i++) { From 8945384bca00f74ba85c98a52925c254c49025a5 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 4 Aug 2016 16:37:49 -0400 Subject: [PATCH 0692/1802] net: Have LookupNumeric return a CService directly Also fix up a few small issues: - Lookup with "badip:port" now sets the port to 0 - Don't allow assert to have side-effects --- src/httpserver.cpp | 2 +- src/init.cpp | 6 ++---- src/net.cpp | 6 ++---- src/netbase.cpp | 9 +++++++-- src/netbase.h | 2 +- src/qt/optionsdialog.cpp | 3 +-- src/test/netbase_tests.cpp | 6 ++---- src/torcontrol.cpp | 5 ++--- 8 files changed, 18 insertions(+), 21 deletions(-) diff --git a/src/httpserver.cpp b/src/httpserver.cpp index 2c5bc2c7923c3..2bb4be564ea94 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -619,7 +619,7 @@ CService HTTPRequest::GetPeer() const char* address = ""; uint16_t port = 0; evhttp_connection_get_peer(con, (char**)&address, &port); - LookupNumeric(address, peer, port); + peer = LookupNumeric(address, port); } return peer; } diff --git a/src/init.cpp b/src/init.cpp index 4f5eeeffe67e7..04d7ed0ea3ff1 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1098,8 +1098,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) std::string proxyArg = GetArg("-proxy", ""); SetLimited(NET_TOR); if (proxyArg != "" && proxyArg != "0") { - CService resolved; - LookupNumeric(proxyArg.c_str(), resolved, 9050); + CService resolved(LookupNumeric(proxyArg.c_str(), 9050)); proxyType addrProxy = proxyType(resolved, proxyRandomize); if (!addrProxy.IsValid()) return InitError(strprintf(_("Invalid -proxy address: '%s'"), proxyArg)); @@ -1119,8 +1118,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (onionArg == "0") { // Handle -noonion/-onion=0 SetLimited(NET_TOR); // set onions as unreachable } else { - CService resolved; - LookupNumeric(onionArg.c_str(), resolved, 9050); + CService resolved(LookupNumeric(onionArg.c_str(), 9050)); proxyType addrOnion = proxyType(resolved, proxyRandomize); if (!addrOnion.IsValid()) return InitError(strprintf(_("Invalid -onion address: '%s'"), onionArg)); diff --git a/src/net.cpp b/src/net.cpp index e9bb406e976c5..fc44a0f17cb20 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1728,8 +1728,7 @@ std::vector GetAddedNodeInfo() } BOOST_FOREACH(const std::string& strAddNode, lAddresses) { - CService service; - LookupNumeric(strAddNode.c_str(), service, Params().GetDefaultPort()); + CService service(LookupNumeric(strAddNode.c_str(), Params().GetDefaultPort())); if (service.IsValid()) { // strAddNode is an IP:port auto it = mapConnected.find(service); @@ -1767,8 +1766,7 @@ void ThreadOpenAddedConnections() CSemaphoreGrant grant(*semOutbound); // If strAddedNode is an IP/port, decode it immediately, so // OpenNetworkConnection can detect existing connections to that IP/port. - CService service; - LookupNumeric(info.strAddedNode.c_str(), service, Params().GetDefaultPort()); + CService service(LookupNumeric(info.strAddedNode.c_str(), Params().GetDefaultPort())); OpenNetworkConnection(CAddress(service, NODE_NONE), false, &grant, info.strAddedNode.c_str(), false); MilliSleep(500); } diff --git a/src/netbase.cpp b/src/netbase.cpp index c2294a078da51..4f243ec6f5397 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -231,9 +231,14 @@ bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLoo return true; } -bool LookupNumeric(const char *pszName, CService& addr, int portDefault) +CService LookupNumeric(const char *pszName, int portDefault) { - return Lookup(pszName, addr, portDefault, false); + CService addr; + // "1.2:345" will fail to resolve the ip, but will still set the port. + // If the ip fails to resolve, re-init the result. + if(!Lookup(pszName, addr, portDefault, false)) + addr = CService(); + return addr; } struct timeval MillisToTimeval(int64_t nTimeout) diff --git a/src/netbase.h b/src/netbase.h index d0abd5e954ef4..bb12019a8216b 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -49,7 +49,7 @@ bool LookupHost(const char *pszName, std::vector& vIP, unsigned int nM bool LookupHost(const char *pszName, CNetAddr& addr, bool fAllowLookup); bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLookup); bool Lookup(const char *pszName, std::vector& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions); -bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0); +CService LookupNumeric(const char *pszName, int portDefault = 0); bool LookupSubNet(const char *pszName, CSubNet& subnet); bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed = 0); bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout, bool *outProxyConnectionFailed = 0); diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index e419e4d9ee579..f73bb87064088 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -327,8 +327,7 @@ QValidator::State ProxyAddressValidator::validate(QString &input, int &pos) cons { Q_UNUSED(pos); // Validate the proxy - CService serv; - LookupNumeric(input.toStdString().c_str(), serv, 9050); + CService serv(LookupNumeric(input.toStdString().c_str(), 9050)); proxyType addrProxy = proxyType(serv, true); if (addrProxy.IsValid()) return QValidator::Acceptable; diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index 7a8584f0f4322..18ad5dc90bf4e 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -93,9 +93,7 @@ BOOST_AUTO_TEST_CASE(netbase_splithost) bool static TestParse(string src, string canon) { - CService addr; - if (!LookupNumeric(src.c_str(), addr, 65535)) - return canon == ""; + CService addr(LookupNumeric(src.c_str(), 65535)); return canon == addr.ToString(); } @@ -107,7 +105,7 @@ BOOST_AUTO_TEST_CASE(netbase_lookupnumeric) BOOST_CHECK(TestParse("::", "[::]:65535")); BOOST_CHECK(TestParse("[::]:8333", "[::]:8333")); BOOST_CHECK(TestParse("[127.0.0.1]", "127.0.0.1:65535")); - BOOST_CHECK(TestParse(":::", "")); + BOOST_CHECK(TestParse(":::", "[::]:0")); } BOOST_AUTO_TEST_CASE(onioncat_test) diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index c7f96270050ac..99c45d489cb21 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -438,7 +438,7 @@ void TorController::add_onion_cb(TorControlConnection& conn, const TorControlRep if ((i = m.find("PrivateKey")) != m.end()) private_key = i->second; } - LookupNumeric(std::string(service_id+".onion").c_str(), service, GetListenPort()); + service = LookupNumeric(std::string(service_id+".onion").c_str(), GetListenPort()); LogPrintf("tor: Got service ID %s, advertising service %s\n", service_id, service.ToString()); if (WriteBinaryFile(GetPrivateKeyFile(), private_key)) { LogPrint("tor", "tor: Cached service private key to %s\n", GetPrivateKeyFile()); @@ -462,8 +462,7 @@ void TorController::auth_cb(TorControlConnection& conn, const TorControlReply& r // Now that we know Tor is running setup the proxy for onion addresses // if -onion isn't set to something else. if (GetArg("-onion", "") == "") { - CService resolved; - assert(LookupNumeric("127.0.0.1", resolved, 9050)); + CService resolved(LookupNumeric("127.0.0.1", 9050)); proxyType addrOnion = proxyType(resolved, true); SetProxy(NET_TOR, addrOnion); SetLimited(NET_TOR, false); From 65f4532f13a89cacc4909072601d71ee7ebae5c5 Mon Sep 17 00:00:00 2001 From: Jameson Lopp Date: Thu, 4 Aug 2016 17:33:59 -0400 Subject: [PATCH 0693/1802] document return value of networkhashps for getmininginfo RPC endpoint --- src/rpc/mining.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 92ca4bab6bc1e..3214e724bbef1 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -227,10 +227,11 @@ UniValue getmininginfo(const UniValue& params, bool fHelp) " \"currentblockweight\": nnn, (numeric) The last block weight\n" " \"currentblocktx\": nnn, (numeric) The last block transaction\n" " \"difficulty\": xxx.xxxxx (numeric) The current difficulty\n" - " \"errors\": \"...\" (string) Current errors\n" + " \"errors\": \"...\" (string) Current errors\n" + " \"networkhashps\": nnn, (numeric) The network hashes per second\n" " \"pooledtx\": n (numeric) The size of the mem pool\n" " \"testnet\": true|false (boolean) If using testnet or not\n" - " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n" + " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n" "}\n" "\nExamples:\n" + HelpExampleCli("getmininginfo", "") From f13c1bae529cd6e45b4e4b1768a6ab953870fd29 Mon Sep 17 00:00:00 2001 From: Michael Rotarius Date: Fri, 5 Aug 2016 18:34:32 +0200 Subject: [PATCH 0694/1802] Move AdvertiseLocal debug output to net category --- src/main.cpp | 4 ++-- src/net.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 3a07190a6210f..0f7a9e55b39b4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4999,11 +4999,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, CAddress addr = GetLocalAddress(&pfrom->addr); if (addr.IsRoutable()) { - LogPrintf("ProcessMessages: advertising address %s\n", addr.ToString()); + LogPrint("net", "ProcessMessages: advertising address %s\n", addr.ToString()); pfrom->PushAddress(addr); } else if (IsPeerAddrLocalGood(pfrom)) { addr.SetIP(pfrom->addrLocal); - LogPrintf("ProcessMessages: advertising address %s\n", addr.ToString()); + LogPrint("net", "ProcessMessages: advertising address %s\n", addr.ToString()); pfrom->PushAddress(addr); } } diff --git a/src/net.cpp b/src/net.cpp index 4bbe5059df188..c159198ac6f7f 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -216,7 +216,7 @@ void AdvertiseLocal(CNode *pnode) } if (addrLocal.IsRoutable()) { - LogPrintf("AdvertiseLocal: advertising address %s\n", addrLocal.ToString()); + LogPrint("net", "AdvertiseLocal: advertising address %s\n", addrLocal.ToString()); pnode->PushAddress(addrLocal); } } From a159f25e19b8d921e30742f5ba87ef12803d991d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Fri, 5 Aug 2016 20:03:01 +0200 Subject: [PATCH 0695/1802] Remove redundand (and shadowing) declaration --- src/test/blockencodings_tests.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp index 3884bf3fe37c3..d2392cfb22f0d 100644 --- a/src/test/blockencodings_tests.cpp +++ b/src/test/blockencodings_tests.cpp @@ -283,7 +283,6 @@ BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest) std::vector vtx_missing; BOOST_CHECK(partialBlock.FillBlock(block2, vtx_missing) == READ_STATUS_OK); BOOST_CHECK_EQUAL(block.GetHash().ToString(), block2.GetHash().ToString()); - bool mutated; BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block2, &mutated).ToString()); BOOST_CHECK(!mutated); } From 4a35e0f34c0d1c2bbcae6d7b6d691fb0df946dfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Fri, 5 Aug 2016 21:17:50 +0200 Subject: [PATCH 0696/1802] Do not shadow members in dbwrapper --- src/dbwrapper.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/dbwrapper.h b/src/dbwrapper.h index a0779d3ab9918..47bdb31b5b888 100644 --- a/src/dbwrapper.h +++ b/src/dbwrapper.h @@ -52,9 +52,9 @@ class CDBBatch public: /** - * @param[in] parent CDBWrapper that this batch is to be submitted to + * @param[in] _parent CDBWrapper that this batch is to be submitted to */ - CDBBatch(const CDBWrapper &parent) : parent(parent) { }; + CDBBatch(const CDBWrapper &_parent) : parent(_parent) { }; template void Write(const K& key, const V& value) @@ -94,11 +94,11 @@ class CDBIterator public: /** - * @param[in] parent Parent CDBWrapper instance. - * @param[in] piterIn The original leveldb iterator. + * @param[in] _parent Parent CDBWrapper instance. + * @param[in] _piter The original leveldb iterator. */ - CDBIterator(const CDBWrapper &parent, leveldb::Iterator *piterIn) : - parent(parent), piter(piterIn) { }; + CDBIterator(const CDBWrapper &_parent, leveldb::Iterator *_piter) : + parent(_parent), piter(_piter) { }; ~CDBIterator(); bool Valid(); From 33d15a3a76d073986337adcd62646d93e7ba223f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Sat, 6 Aug 2016 10:54:29 +0200 Subject: [PATCH 0697/1802] Do not shadow LOCK's criticalblock variable for LOCK inside LOCK --- src/sync.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sync.h b/src/sync.h index 0c58fb6b4e94c..77339107494eb 100644 --- a/src/sync.h +++ b/src/sync.h @@ -171,7 +171,10 @@ class SCOPED_LOCKABLE CMutexLock typedef CMutexLock CCriticalBlock; -#define LOCK(cs) CCriticalBlock criticalblock(cs, #cs, __FILE__, __LINE__) +#define PASTE(x, y) x ## y +#define PASTE2(x, y) PASTE(x, y) + +#define LOCK(cs) CCriticalBlock PASTE2(criticalblock, __COUNTER__)(cs, #cs, __FILE__, __LINE__) #define LOCK2(cs1, cs2) CCriticalBlock criticalblock1(cs1, #cs1, __FILE__, __LINE__), criticalblock2(cs2, #cs2, __FILE__, __LINE__) #define TRY_LOCK(cs, name) CCriticalBlock name(cs, #cs, __FILE__, __LINE__, true) From 05242e937d3fc0144029ccf3b14f98662400dd60 Mon Sep 17 00:00:00 2001 From: adlawren Date: Sat, 6 Aug 2016 23:58:30 -0700 Subject: [PATCH 0698/1802] Fix minimize and close bugs refs #8225 To ensure the GUI closes when the "Minimize on close" window option is disabled, and the "Minimize to the tray instead of the taskbar" window option is enbaled, remove a check made against the "Minimize to the tray instead of the taskbar" value, made during GUI closure. To ensure the GUI minimizes to the taskbar when the "Minimize on close" window option is enabled, and the "Minimize to the tray instead of the taskbar" window option is disabled, minimize the GUI and ignore the closure event. --- src/qt/bitcoingui.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 9042e3b56a3b8..2afefb733edcf 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -902,17 +902,22 @@ void BitcoinGUI::closeEvent(QCloseEvent *event) #ifndef Q_OS_MAC // Ignored on Mac if(clientModel && clientModel->getOptionsModel()) { - if(!clientModel->getOptionsModel()->getMinimizeToTray() && - !clientModel->getOptionsModel()->getMinimizeOnClose()) + if(!clientModel->getOptionsModel()->getMinimizeOnClose()) { // close rpcConsole in case it was open to make some space for the shutdown window rpcConsole->close(); QApplication::quit(); } + else + { + QMainWindow::showMinimized(); + event->ignore(); + } } -#endif +#else QMainWindow::closeEvent(event); +#endif } void BitcoinGUI::showEvent(QShowEvent *event) From fa2d68f79c459b505652728c3d8da60679f98ae3 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Fri, 8 Jul 2016 17:59:06 +0200 Subject: [PATCH 0699/1802] [qa] Adjust timeouts for micro-optimization of run time --- qa/rpc-tests/test_framework/util.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index 32fe79efc38be..31fa19dd33a63 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -121,7 +121,7 @@ def hex_str_to_bytes(hex_str): def str_to_b64str(string): return b64encode(string.encode('utf-8')).decode('ascii') -def sync_blocks(rpc_connections, wait=1, timeout=60): +def sync_blocks(rpc_connections, wait=0.125, timeout=60): """ Wait until everybody has the same tip """ @@ -133,7 +133,7 @@ def sync_blocks(rpc_connections, wait=1, timeout=60): timeout -= wait raise AssertionError("Block sync failed") -def sync_mempools(rpc_connections, wait=1, timeout=60): +def sync_mempools(rpc_connections, wait=0.5, timeout=60): """ Wait until everybody has the same transactions in their memory pools From fad8cf63e5f6a2e26b44dbf2bbdd7df901c4e6f4 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 7 Aug 2016 23:06:27 +0200 Subject: [PATCH 0700/1802] [qa] Use single cache dir for chains --- .gitignore | 3 +-- qa/pull-tester/rpc-tests.py | 1 + qa/rpc-tests/test_framework/test_framework.py | 4 +++- qa/rpc-tests/test_framework/util.py | 20 +++++++++---------- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index ce40019dc314f..892b2a3e08e0c 100644 --- a/.gitignore +++ b/.gitignore @@ -103,10 +103,9 @@ linux-build win32-build qa/pull-tester/run-bitcoind-for-test.sh qa/pull-tester/tests_config.py -qa/pull-tester/cache/* qa/pull-tester/test.*/* qa/tmp -cache/ +qa/cache/* share/BitcoindComparisonTool.jar !src/leveldb*/Makefile diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index 2aa131041a02b..05b41ae989162 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -192,6 +192,7 @@ def runtests(): coverage = RPCCoverage() print("Initializing coverage directory at %s\n" % coverage.dir) flags = ["--srcdir=%s/src" % BUILDDIR] + passon_args + flags.append("--cachedir=%s/qa/cache" % BUILDDIR) if coverage: flags.append(coverage.flag) diff --git a/qa/rpc-tests/test_framework/test_framework.py b/qa/rpc-tests/test_framework/test_framework.py index 30e8b5755de39..ced9521234062 100755 --- a/qa/rpc-tests/test_framework/test_framework.py +++ b/qa/rpc-tests/test_framework/test_framework.py @@ -47,7 +47,7 @@ def setup_chain(self): if self.setup_clean_chain: initialize_chain_clean(self.options.tmpdir, self.num_nodes) else: - initialize_chain(self.options.tmpdir, self.num_nodes) + initialize_chain(self.options.tmpdir, self.num_nodes, self.options.cachedir) def setup_nodes(self): return start_nodes(self.num_nodes, self.options.tmpdir) @@ -108,6 +108,8 @@ def main(self): help="Don't stop bitcoinds after the test execution") parser.add_option("--srcdir", dest="srcdir", default=os.path.normpath(os.path.dirname(os.path.realpath(__file__))+"/../../../src"), help="Source directory containing bitcoind/bitcoin-cli (default: %default)") + parser.add_option("--cachedir", dest="cachedir", default=os.path.normpath(os.path.dirname(os.path.realpath(__file__))+"/../../cache"), + help="Directory for caching pregenerated datadirs") parser.add_option("--tmpdir", dest="tmpdir", default=tempfile.mkdtemp(prefix="test"), help="Root directory for datadirs") parser.add_option("--tracerpc", dest="trace_rpc", default=False, action="store_true", diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index 31fa19dd33a63..3e10f13bb317e 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -193,7 +193,7 @@ def wait_for_bitcoind_start(process, url, i): raise # unkown JSON RPC exception time.sleep(0.25) -def initialize_chain(test_dir, num_nodes): +def initialize_chain(test_dir, num_nodes, cachedir): """ Create a cache of a 200-block-long chain (with wallet) for MAX_NODES Afterward, create num_nodes copies from the cache @@ -202,7 +202,7 @@ def initialize_chain(test_dir, num_nodes): assert num_nodes <= MAX_NODES create_cache = False for i in range(MAX_NODES): - if not os.path.isdir(os.path.join('cache', 'node'+str(i))): + if not os.path.isdir(os.path.join(cachedir, 'node'+str(i))): create_cache = True break @@ -210,12 +210,12 @@ def initialize_chain(test_dir, num_nodes): #find and delete old cache directories if any exist for i in range(MAX_NODES): - if os.path.isdir(os.path.join("cache","node"+str(i))): - shutil.rmtree(os.path.join("cache","node"+str(i))) + if os.path.isdir(os.path.join(cachedir,"node"+str(i))): + shutil.rmtree(os.path.join(cachedir,"node"+str(i))) # Create cache directories, run bitcoinds: for i in range(MAX_NODES): - datadir=initialize_datadir("cache", i) + datadir=initialize_datadir(cachedir, i) args = [ os.getenv("BITCOIND", "bitcoind"), "-server", "-keypool=1", "-datadir="+datadir, "-discover=0" ] if i > 0: args.append("-connect=127.0.0.1:"+str(p2p_port(0))) @@ -257,13 +257,13 @@ def initialize_chain(test_dir, num_nodes): wait_bitcoinds() disable_mocktime() for i in range(MAX_NODES): - os.remove(log_filename("cache", i, "debug.log")) - os.remove(log_filename("cache", i, "db.log")) - os.remove(log_filename("cache", i, "peers.dat")) - os.remove(log_filename("cache", i, "fee_estimates.dat")) + os.remove(log_filename(cachedir, i, "debug.log")) + os.remove(log_filename(cachedir, i, "db.log")) + os.remove(log_filename(cachedir, i, "peers.dat")) + os.remove(log_filename(cachedir, i, "fee_estimates.dat")) for i in range(num_nodes): - from_dir = os.path.join("cache", "node"+str(i)) + from_dir = os.path.join(cachedir, "node"+str(i)) to_dir = os.path.join(test_dir, "node"+str(i)) shutil.copytree(from_dir, to_dir) initialize_datadir(test_dir, i) # Overwrite port/rpcport in bitcoin.conf From 25400c4de18fe63a0b1051cc158b62f6c8c7ba90 Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Wed, 3 Aug 2016 19:28:39 -0700 Subject: [PATCH 0701/1802] Account wallet feature RPC tests. --- qa/pull-tester/rpc-tests.py | 1 + qa/rpc-tests/wallet-accounts.py | 94 +++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100755 qa/rpc-tests/wallet-accounts.py diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index f65a3eefc3937..ed509463435c1 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -106,6 +106,7 @@ 'walletbackup.py', 'bip68-112-113-p2p.py', 'wallet.py', + 'wallet-accounts.py', 'wallet-hd.py', 'wallet-dump.py', 'listtransactions.py', diff --git a/qa/rpc-tests/wallet-accounts.py b/qa/rpc-tests/wallet-accounts.py new file mode 100755 index 0000000000000..c51181e4f8e9b --- /dev/null +++ b/qa/rpc-tests/wallet-accounts.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 +# Copyright (c) 2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import ( + start_nodes, + start_node, + assert_equal, + connect_nodes_bi, +) + + +class WalletAccountsTest(BitcoinTestFramework): + + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 1 + self.node_args = [[]] + + def setup_network(self): + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.node_args) + self.is_network_split = False + + def run_test (self): + node = self.nodes[0] + # Check that there's no UTXO on any of the nodes + assert_equal(len(node.listunspent()), 0) + + node.generate(101) + + assert_equal(node.getbalance(), 50) + + accounts = ["a","b","c","d","e"] + amount_to_send = 1.0 + account_addresses = dict() + for account in accounts: + address = node.getaccountaddress(account) + account_addresses[account] = address + + node.getnewaddress(account) + assert_equal(node.getaccount(address), account) + assert(address in node.getaddressesbyaccount(account)) + + node.sendfrom("", address, amount_to_send) + + node.generate(1) + + for i in range(len(accounts)): + from_account = accounts[i] + to_account = accounts[(i+1)%len(accounts)] + to_address = account_addresses[to_account] + node.sendfrom(from_account, to_address, amount_to_send) + + node.generate(1) + + for account in accounts: + address = node.getaccountaddress(account) + assert(address != account_addresses[account]) + assert_equal(node.getreceivedbyaccount(account), 2) + node.move(account, "", node.getbalance(account)) + + node.generate(101) + + expected_account_balances = {"": 5200} + for account in accounts: + expected_account_balances[account] = 0 + + assert_equal(node.listaccounts(), expected_account_balances) + + assert_equal(node.getbalance(""), 5200) + + for account in accounts: + address = node.getaccountaddress("") + node.setaccount(address, account) + assert(address in node.getaddressesbyaccount(account)) + assert(address not in node.getaddressesbyaccount("")) + + for account in accounts: + addresses = [] + for x in range(10): + addresses.append(node.getnewaddress()) + multisig_address = node.addmultisigaddress(5, addresses, account) + node.sendfrom("", multisig_address, 50) + + node.generate(101) + + for account in accounts: + assert_equal(node.getbalance(account), 50) + +if __name__ == '__main__': + WalletAccountsTest().main () From 9578333ec456bbfaccfecf9ea561c421f3a5d547 Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Wed, 3 Aug 2016 16:37:02 -0700 Subject: [PATCH 0702/1802] Remove rpc_wallet_tests.cpp --- src/Makefile.test.include | 3 +- src/wallet/test/rpc_wallet_tests.cpp | 229 --------------------------- 2 files changed, 1 insertion(+), 231 deletions(-) delete mode 100644 src/wallet/test/rpc_wallet_tests.cpp diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 27e7694748c2a..0748d1a39d232 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -97,8 +97,7 @@ BITCOIN_TESTS += \ wallet/test/wallet_test_fixture.h \ wallet/test/accounting_tests.cpp \ wallet/test/wallet_tests.cpp \ - wallet/test/crypto_tests.cpp \ - wallet/test/rpc_wallet_tests.cpp + wallet/test/crypto_tests.cpp endif test_test_bitcoin_SOURCES = $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES) diff --git a/src/wallet/test/rpc_wallet_tests.cpp b/src/wallet/test/rpc_wallet_tests.cpp deleted file mode 100644 index 4e7d177f51855..0000000000000 --- a/src/wallet/test/rpc_wallet_tests.cpp +++ /dev/null @@ -1,229 +0,0 @@ -// Copyright (c) 2013-2015 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "rpc/server.h" -#include "rpc/client.h" - -#include "base58.h" -#include "main.h" -#include "wallet/wallet.h" - -#include "wallet/test/wallet_test_fixture.h" - -#include -#include - -#include - -using namespace std; - -extern UniValue createArgs(int nRequired, const char* address1 = NULL, const char* address2 = NULL); -extern UniValue CallRPC(string args); - -extern CWallet* pwalletMain; - -BOOST_FIXTURE_TEST_SUITE(rpc_wallet_tests, WalletTestingSetup) - -BOOST_AUTO_TEST_CASE(rpc_addmultisig) -{ - rpcfn_type addmultisig = tableRPC["addmultisigaddress"]->actor; - - // old, 65-byte-long: - const char address1Hex[] = "0434e3e09f49ea168c5bbf53f877ff4206923858aab7c7e1df25bc263978107c95e35065a27ef6f1b27222db0ec97e0e895eaca603d3ee0d4c060ce3d8a00286c8"; - // new, compressed: - const char address2Hex[] = "0388c2037017c62240b6b72ac1a2a5f94da790596ebd06177c8572752922165cb4"; - - UniValue v; - CBitcoinAddress address; - BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex), false)); - address.SetString(v.get_str()); - BOOST_CHECK(address.IsValid() && address.IsScript()); - - BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex, address2Hex), false)); - address.SetString(v.get_str()); - BOOST_CHECK(address.IsValid() && address.IsScript()); - - BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(2, address1Hex, address2Hex), false)); - address.SetString(v.get_str()); - BOOST_CHECK(address.IsValid() && address.IsScript()); - - BOOST_CHECK_THROW(addmultisig(createArgs(0), false), runtime_error); - BOOST_CHECK_THROW(addmultisig(createArgs(1), false), runtime_error); - BOOST_CHECK_THROW(addmultisig(createArgs(2, address1Hex), false), runtime_error); - - BOOST_CHECK_THROW(addmultisig(createArgs(1, ""), false), runtime_error); - BOOST_CHECK_THROW(addmultisig(createArgs(1, "NotAValidPubkey"), false), runtime_error); - - string short1(address1Hex, address1Hex + sizeof(address1Hex) - 2); // last byte missing - BOOST_CHECK_THROW(addmultisig(createArgs(2, short1.c_str()), false), runtime_error); - - string short2(address1Hex + 1, address1Hex + sizeof(address1Hex)); // first byte missing - BOOST_CHECK_THROW(addmultisig(createArgs(2, short2.c_str()), false), runtime_error); -} - -BOOST_AUTO_TEST_CASE(rpc_wallet) -{ - // Test RPC calls for various wallet statistics - UniValue r; - CPubKey demoPubkey; - CBitcoinAddress demoAddress; - UniValue retValue; - string strAccount = "walletDemoAccount"; - CBitcoinAddress setaccountDemoAddress; - { - LOCK(pwalletMain->cs_wallet); - - demoPubkey = pwalletMain->GenerateNewKey(); - demoAddress = CBitcoinAddress(CTxDestination(demoPubkey.GetID())); - string strPurpose = "receive"; - BOOST_CHECK_NO_THROW({ /*Initialize Wallet with an account */ - CWalletDB walletdb(pwalletMain->strWalletFile); - CAccount account; - account.vchPubKey = demoPubkey; - pwalletMain->SetAddressBook(account.vchPubKey.GetID(), strAccount, strPurpose); - walletdb.WriteAccount(strAccount, account); - }); - - CPubKey setaccountDemoPubkey = pwalletMain->GenerateNewKey(); - setaccountDemoAddress = CBitcoinAddress(CTxDestination(setaccountDemoPubkey.GetID())); - } - /********************************* - * setaccount - *********************************/ - BOOST_CHECK_NO_THROW(CallRPC("setaccount " + setaccountDemoAddress.ToString() + " nullaccount")); - /* 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ is not owned by the test wallet. */ - BOOST_CHECK_THROW(CallRPC("setaccount 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ nullaccount"), runtime_error); - BOOST_CHECK_THROW(CallRPC("setaccount"), runtime_error); - /* 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4X (33 chars) is an illegal address (should be 34 chars) */ - BOOST_CHECK_THROW(CallRPC("setaccount 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4X nullaccount"), runtime_error); - - - /********************************* - * getbalance - *********************************/ - BOOST_CHECK_NO_THROW(CallRPC("getbalance")); - BOOST_CHECK_NO_THROW(CallRPC("getbalance " + demoAddress.ToString())); - - /********************************* - * listunspent - *********************************/ - BOOST_CHECK_NO_THROW(CallRPC("listunspent")); - BOOST_CHECK_THROW(CallRPC("listunspent string"), runtime_error); - BOOST_CHECK_THROW(CallRPC("listunspent 0 string"), runtime_error); - BOOST_CHECK_THROW(CallRPC("listunspent 0 1 not_array"), runtime_error); - BOOST_CHECK_THROW(CallRPC("listunspent 0 1 [] extra"), runtime_error); - BOOST_CHECK_NO_THROW(r = CallRPC("listunspent 0 1 []")); - BOOST_CHECK(r.get_array().empty()); - - /********************************* - * listreceivedbyaddress - *********************************/ - BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress")); - BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress 0")); - BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress not_int"), runtime_error); - BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 not_bool"), runtime_error); - BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress 0 true")); - BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 true extra"), runtime_error); - - /********************************* - * listreceivedbyaccount - *********************************/ - BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount")); - BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount 0")); - BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount not_int"), runtime_error); - BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 not_bool"), runtime_error); - BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount 0 true")); - BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 true extra"), runtime_error); - - /********************************* - * listsinceblock - *********************************/ - BOOST_CHECK_NO_THROW(CallRPC("listsinceblock")); - - /********************************* - * listtransactions - *********************************/ - BOOST_CHECK_NO_THROW(CallRPC("listtransactions")); - BOOST_CHECK_NO_THROW(CallRPC("listtransactions " + demoAddress.ToString())); - BOOST_CHECK_NO_THROW(CallRPC("listtransactions " + demoAddress.ToString() + " 20")); - BOOST_CHECK_NO_THROW(CallRPC("listtransactions " + demoAddress.ToString() + " 20 0")); - BOOST_CHECK_THROW(CallRPC("listtransactions " + demoAddress.ToString() + " not_int"), runtime_error); - - /********************************* - * listlockunspent - *********************************/ - BOOST_CHECK_NO_THROW(CallRPC("listlockunspent")); - - /********************************* - * listaccounts - *********************************/ - BOOST_CHECK_NO_THROW(CallRPC("listaccounts")); - - /********************************* - * listaddressgroupings - *********************************/ - BOOST_CHECK_NO_THROW(CallRPC("listaddressgroupings")); - - /********************************* - * getrawchangeaddress - *********************************/ - BOOST_CHECK_NO_THROW(CallRPC("getrawchangeaddress")); - - /********************************* - * getnewaddress - *********************************/ - BOOST_CHECK_NO_THROW(CallRPC("getnewaddress")); - BOOST_CHECK_NO_THROW(CallRPC("getnewaddress getnewaddress_demoaccount")); - - /********************************* - * getaccountaddress - *********************************/ - BOOST_CHECK_NO_THROW(CallRPC("getaccountaddress \"\"")); - BOOST_CHECK_NO_THROW(CallRPC("getaccountaddress accountThatDoesntExists")); // Should generate a new account - BOOST_CHECK_NO_THROW(retValue = CallRPC("getaccountaddress " + strAccount)); - BOOST_CHECK(CBitcoinAddress(retValue.get_str()).Get() == demoAddress.Get()); - - /********************************* - * getaccount - *********************************/ - BOOST_CHECK_THROW(CallRPC("getaccount"), runtime_error); - BOOST_CHECK_NO_THROW(CallRPC("getaccount " + demoAddress.ToString())); - - /********************************* - * signmessage + verifymessage - *********************************/ - BOOST_CHECK_NO_THROW(retValue = CallRPC("signmessage " + demoAddress.ToString() + " mymessage")); - BOOST_CHECK_THROW(CallRPC("signmessage"), runtime_error); - /* Should throw error because this address is not loaded in the wallet */ - BOOST_CHECK_THROW(CallRPC("signmessage 1QFqqMUD55ZV3PJEJZtaKCsQmjLT6JkjvJ mymessage"), runtime_error); - - /* missing arguments */ - BOOST_CHECK_THROW(CallRPC("verifymessage " + demoAddress.ToString()), runtime_error); - BOOST_CHECK_THROW(CallRPC("verifymessage " + demoAddress.ToString() + " " + retValue.get_str()), runtime_error); - /* Illegal address */ - BOOST_CHECK_THROW(CallRPC("verifymessage 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4X " + retValue.get_str() + " mymessage"), runtime_error); - /* wrong address */ - BOOST_CHECK(CallRPC("verifymessage 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ " + retValue.get_str() + " mymessage").get_bool() == false); - /* Correct address and signature but wrong message */ - BOOST_CHECK(CallRPC("verifymessage " + demoAddress.ToString() + " " + retValue.get_str() + " wrongmessage").get_bool() == false); - /* Correct address, message and signature*/ - BOOST_CHECK(CallRPC("verifymessage " + demoAddress.ToString() + " " + retValue.get_str() + " mymessage").get_bool() == true); - - /********************************* - * getaddressesbyaccount - *********************************/ - BOOST_CHECK_THROW(CallRPC("getaddressesbyaccount"), runtime_error); - BOOST_CHECK_NO_THROW(retValue = CallRPC("getaddressesbyaccount " + strAccount)); - UniValue arr = retValue.get_array(); - BOOST_CHECK(arr.size() > 0); - BOOST_CHECK(CBitcoinAddress(arr[0].get_str()).Get() == demoAddress.Get()); - - /********************************* - * fundrawtransaction - *********************************/ - BOOST_CHECK_THROW(CallRPC("fundrawtransaction 28z"), runtime_error); - BOOST_CHECK_THROW(CallRPC("fundrawtransaction 01000000000180969800000000001976a91450ce0a4b0ee0ddeb633da85199728b940ac3fe9488ac00000000"), runtime_error); -} - -BOOST_AUTO_TEST_SUITE_END() From 160f895a80660e4e3904a2624e4110960d051902 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Mon, 8 Aug 2016 21:16:40 +0000 Subject: [PATCH 0703/1802] Bugfix: Use pre-BIP141 sigops until segwit activates --- src/rpc/mining.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 92ca4bab6bc1e..2479e5d5953d2 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -546,6 +546,9 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) UpdateTime(pblock, consensusParams, pindexPrev); pblock->nNonce = 0; + // NOTE: If at some point we support pre-segwit miners post-segwit-activation, this needs to take segwit support into consideration + const bool fPreSegWit = (THRESHOLD_ACTIVE != VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT, versionbitscache)); + UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal"); UniValue transactions(UniValue::VARR); @@ -574,7 +577,12 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) int index_in_template = i - 1; entry.push_back(Pair("fee", pblocktemplate->vTxFees[index_in_template])); - entry.push_back(Pair("sigops", pblocktemplate->vTxSigOpsCost[index_in_template])); + int64_t nTxSigOps = pblocktemplate->vTxSigOpsCost[index_in_template]; + if (fPreSegWit) { + assert(nTxSigOps % WITNESS_SCALE_FACTOR == 0); + nTxSigOps /= WITNESS_SCALE_FACTOR; + } + entry.push_back(Pair("sigops", nTxSigOps)); entry.push_back(Pair("weight", GetTransactionWeight(tx))); transactions.push_back(entry); @@ -657,7 +665,12 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1)); result.push_back(Pair("mutable", aMutable)); result.push_back(Pair("noncerange", "00000000ffffffff")); - result.push_back(Pair("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS_COST)); + int64_t nSigOpLimit = MAX_BLOCK_SIGOPS_COST; + if (fPreSegWit) { + assert(nSigOpLimit % WITNESS_SCALE_FACTOR == 0); + nSigOpLimit /= WITNESS_SCALE_FACTOR; + } + result.push_back(Pair("sigoplimit", nSigOpLimit)); result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SERIALIZED_SIZE)); result.push_back(Pair("weightlimit", (int64_t)MAX_BLOCK_WEIGHT)); result.push_back(Pair("curtime", pblock->GetBlockTime())); From 239cbd2e5c2a36843b45b356e9aea6e8d35f0968 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Mon, 8 Aug 2016 21:58:36 +0000 Subject: [PATCH 0704/1802] qa/rpc-tests/segwit: Test GBT sigops before and after activation --- qa/rpc-tests/segwit.py | 52 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/qa/rpc-tests/segwit.py b/qa/rpc-tests/segwit.py index d4c9a8afed32c..097e119f3239b 100755 --- a/qa/rpc-tests/segwit.py +++ b/qa/rpc-tests/segwit.py @@ -69,6 +69,11 @@ def getutxo(txid): utxo["txid"] = txid return utxo +def find_unspent(node, min_value): + for utxo in node.listunspent(): + if utxo['amount'] >= min_value: + return utxo + class SegWitTest(BitcoinTestFramework): def setup_chain(self): @@ -117,8 +122,21 @@ def fail_mine(self, node, txid, sign, redeem_script=""): sync_blocks(self.nodes) def run_test(self): - self.nodes[0].generate(160) #block 160 - + self.nodes[0].generate(161) #block 161 + + print("Verify sigops are counted in GBT with pre-BIP141 rules before the fork") + txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1) + tmpl = self.nodes[0].getblocktemplate({}) + assert(tmpl['sigoplimit'] == 20000) + assert(tmpl['transactions'][0]['hash'] == txid) + assert(tmpl['transactions'][0]['sigops'] == 2) + tmpl = self.nodes[0].getblocktemplate({'rules':['segwit']}) + assert(tmpl['sigoplimit'] == 20000) + assert(tmpl['transactions'][0]['hash'] == txid) + assert(tmpl['transactions'][0]['sigops'] == 2) + self.nodes[0].generate(1) #block 162 + + balance_presetup = self.nodes[0].getbalance() self.pubkey = [] p2sh_ids = [] # p2sh_ids[NODE][VER] is an array of txids that spend to a witness version VER pkscript to an address for NODE embedded in p2sh wit_ids = [] # wit_ids[NODE][VER] is an array of txids that spend to a witness version VER pkscript to an address for NODE via bare witness @@ -137,18 +155,18 @@ def run_test(self): for i in range(5): for n in range(3): for v in range(2): - wit_ids[n][v].append(send_to_witness(v, self.nodes[0], self.nodes[0].listunspent()[0], self.pubkey[n], False, Decimal("49.999"))) - p2sh_ids[n][v].append(send_to_witness(v, self.nodes[0], self.nodes[0].listunspent()[0], self.pubkey[n], True, Decimal("49.999"))) + wit_ids[n][v].append(send_to_witness(v, self.nodes[0], find_unspent(self.nodes[0], 50), self.pubkey[n], False, Decimal("49.999"))) + p2sh_ids[n][v].append(send_to_witness(v, self.nodes[0], find_unspent(self.nodes[0], 50), self.pubkey[n], True, Decimal("49.999"))) - self.nodes[0].generate(1) #block 161 + self.nodes[0].generate(1) #block 163 sync_blocks(self.nodes) # Make sure all nodes recognize the transactions as theirs - assert_equal(self.nodes[0].getbalance(), 60*50 - 60*50 + 20*Decimal("49.999") + 50) + assert_equal(self.nodes[0].getbalance(), balance_presetup - 60*50 + 20*Decimal("49.999") + 50) assert_equal(self.nodes[1].getbalance(), 20*Decimal("49.999")) assert_equal(self.nodes[2].getbalance(), 20*Decimal("49.999")) - self.nodes[0].generate(262) #block 423 + self.nodes[0].generate(260) #block 423 sync_blocks(self.nodes) print("Verify default node can't accept any witness format txs before fork") @@ -205,5 +223,25 @@ def run_test(self): self.success_mine(self.nodes[0], p2sh_ids[NODE_0][WIT_V0][0], True) #block 434 self.success_mine(self.nodes[0], p2sh_ids[NODE_0][WIT_V1][0], True) #block 435 + print("Verify sigops are counted in GBT with BIP141 rules after the fork") + txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1) + tmpl = self.nodes[0].getblocktemplate({'rules':['segwit']}) + assert(tmpl['sigoplimit'] == 80000) + assert(tmpl['transactions'][0]['txid'] == txid) + assert(tmpl['transactions'][0]['sigops'] == 8) + + print("Verify non-segwit miners get a valid GBT response after the fork") + send_to_witness(1, self.nodes[0], find_unspent(self.nodes[0], 50), self.pubkey[0], False, Decimal("49.998")) + try: + tmpl = self.nodes[0].getblocktemplate({}) + assert(len(tmpl['transactions']) == 1) # Doesn't include witness tx + assert(tmpl['sigoplimit'] == 20000) + assert(tmpl['transactions'][0]['hash'] == txid) + assert(tmpl['transactions'][0]['sigops'] == 2) + assert(('!segwit' in tmpl['rules']) or ('segwit' not in tmpl['rules'])) + except JSONRPCException: + # This is an acceptable outcome + pass + if __name__ == '__main__': SegWitTest().main() From 947913fc54325bea88dd52ea219ea2c69e334c97 Mon Sep 17 00:00:00 2001 From: whythat Date: Mon, 18 Jul 2016 12:23:42 +0300 Subject: [PATCH 0705/1802] use std::map::erase(const_iterator, const_iterator) to get non-constant iterator --- src/limitedmap.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/limitedmap.h b/src/limitedmap.h index 4d9bb4fa21d5d..7841d7f4a4abe 100644 --- a/src/limitedmap.h +++ b/src/limitedmap.h @@ -66,8 +66,11 @@ class limitedmap } void update(const_iterator itIn, const mapped_type& v) { - // TODO: When we switch to C++11, use map.erase(itIn, itIn) to get the non-const iterator. - iterator itTarget = map.find(itIn->first); + // Using map::erase() with empty range instead of map::find() to get a non-const iterator, + // since it is a constant time operation in C++11. For more details, see + // https://stackoverflow.com/questions/765148/how-to-remove-constness-of-const-iterator + iterator itTarget = map.erase(itIn, itIn); + if (itTarget == map.end()) return; std::pair itPair = rmap.equal_range(itTarget->second); From 5e187e70012c247b96783f7fa9bcbd0289504ad5 Mon Sep 17 00:00:00 2001 From: whythat Date: Mon, 18 Jul 2016 12:26:21 +0300 Subject: [PATCH 0706/1802] use c++11 std::unique_ptr instead of boost::shared_ptr --- src/rpc/server.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 23149baa6d945..4b594f5fa6674 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -25,6 +25,8 @@ #include #include // for to_upper() +#include // for unique_ptr + using namespace RPCServer; using namespace std; @@ -34,9 +36,8 @@ static std::string rpcWarmupStatus("RPC server started"); static CCriticalSection cs_rpcWarmup; /* Timer-creating functions */ static RPCTimerInterface* timerInterface = NULL; -/* Map of name to timer. - * @note Can be changed to std::unique_ptr when C++11 */ -static std::map > deadlineTimers; +/* Map of name to timer. */ +static std::map > deadlineTimers; static struct CRPCSignals { @@ -490,7 +491,7 @@ void RPCRunLater(const std::string& name, boost::function func, int6 throw JSONRPCError(RPC_INTERNAL_ERROR, "No timer handler registered for RPC"); deadlineTimers.erase(name); LogPrint("rpc", "queue run of timer %s in %i seconds (using %s)\n", name, nSeconds, timerInterface->Name()); - deadlineTimers.insert(std::make_pair(name, boost::shared_ptr(timerInterface->NewTimer(func, nSeconds*1000)))); + deadlineTimers.insert(std::make_pair(name, std::unique_ptr(timerInterface->NewTimer(func, nSeconds*1000)))); } CRPCTable tableRPC; From c78408607536bf030947f69f6dc6e09e07873c84 Mon Sep 17 00:00:00 2001 From: whythat Date: Tue, 19 Jul 2016 02:15:59 +0300 Subject: [PATCH 0707/1802] use std::map::emplace() instead of std::map::insert() --- src/rpc/server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 4b594f5fa6674..5fb97f7496217 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -491,7 +491,7 @@ void RPCRunLater(const std::string& name, boost::function func, int6 throw JSONRPCError(RPC_INTERNAL_ERROR, "No timer handler registered for RPC"); deadlineTimers.erase(name); LogPrint("rpc", "queue run of timer %s in %i seconds (using %s)\n", name, nSeconds, timerInterface->Name()); - deadlineTimers.insert(std::make_pair(name, std::unique_ptr(timerInterface->NewTimer(func, nSeconds*1000)))); + deadlineTimers.emplace(name, std::unique_ptr(timerInterface->NewTimer(func, nSeconds*1000))); } CRPCTable tableRPC; From 216d796ce006df36427c03f0c209c48472d65bef Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Tue, 9 Aug 2016 05:07:28 +0000 Subject: [PATCH 0708/1802] configure: Allow building bench_bitcoin by itself --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 011af6bd1bd8e..cc96511f97c7d 100644 --- a/configure.ac +++ b/configure.ac @@ -1003,8 +1003,8 @@ else AC_MSG_RESULT([no]) fi -if test x$build_bitcoin_utils$build_bitcoin_libs$build_bitcoind$bitcoin_enable_qt$use_tests = xnonononono; then - AC_MSG_ERROR([No targets! Please specify at least one of: --with-utils --with-libs --with-daemon --with-gui or --enable-tests]) +if test x$build_bitcoin_utils$build_bitcoin_libs$build_bitcoind$bitcoin_enable_qt$use_bench$use_tests = xnononononono; then + AC_MSG_ERROR([No targets! Please specify at least one of: --with-utils --with-libs --with-daemon --with-gui --enable-bench or --enable-tests]) fi AM_CONDITIONAL([TARGET_DARWIN], [test x$TARGET_OS = xdarwin]) From 8a270b25fc90495ce4b98b6d6e954fce92135dc1 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 30 Jun 2016 01:51:09 +0000 Subject: [PATCH 0709/1802] Bugfix: Allow building libbitcoinconsensus without any univalue --- configure.ac | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 24f9f090f9a00..cc2624ccb23a0 100644 --- a/configure.ac +++ b/configure.ac @@ -750,6 +750,12 @@ fi dnl univalue check +need_bundled_univalue=yes + +if test x$build_bitcoin_utils$build_bitcoind$bitcoin_enable_qt$use_tests$use_bench = xnonononono; then + need_bundled_univalue=no +else + if test x$system_univalue != xno ; then found_univalue=no if test x$use_pkgconfig = xyes; then @@ -771,6 +777,7 @@ if test x$system_univalue != xno ; then if test x$found_univalue = xyes ; then system_univalue=yes + need_bundled_univalue=no elif test x$system_univalue = xyes ; then AC_MSG_ERROR([univalue not found]) else @@ -778,11 +785,14 @@ if test x$system_univalue != xno ; then fi fi -if test x$system_univalue = xno ; then +if test x$need_bundled_univalue = xyes ; then UNIVALUE_CFLAGS='-I$(srcdir)/univalue/include' UNIVALUE_LIBS='univalue/libunivalue.la' fi -AM_CONDITIONAL([EMBEDDED_UNIVALUE],[test x$system_univalue = xno]) + +fi + +AM_CONDITIONAL([EMBEDDED_UNIVALUE],[test x$need_bundled_univalue = xyes]) AC_SUBST(UNIVALUE_CFLAGS) AC_SUBST(UNIVALUE_LIBS) @@ -1002,7 +1012,7 @@ PKGCONFIG_LIBDIR_TEMP="$PKG_CONFIG_LIBDIR" unset PKG_CONFIG_LIBDIR PKG_CONFIG_LIBDIR="$PKGCONFIG_LIBDIR_TEMP" -if test x$system_univalue = xno; then +if test x$need_bundled_univalue = xyes; then AC_CONFIG_SUBDIRS([src/univalue]) fi From fa5d276c906214ef959529fd6cde0b78bd67ed8e Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 10 Aug 2016 08:39:46 +0200 Subject: [PATCH 0710/1802] [init] ParameterInteraction() iff wallet enabled --- src/init.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/init.cpp b/src/init.cpp index 4d9de6cfc8c9f..44204d93b2f0c 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -966,7 +966,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) nBytesPerSigOp = GetArg("-bytespersigop", nBytesPerSigOp); #ifdef ENABLE_WALLET - if (!CWallet::ParameterInteraction()) + if (!fDisableWallet && !CWallet::ParameterInteraction()) return false; #endif // ENABLE_WALLET From 3897668f5eea679383881af48c3f3ed63bd15a74 Mon Sep 17 00:00:00 2001 From: CryptoVote Date: Sun, 15 May 2016 14:30:05 -0500 Subject: [PATCH 0711/1802] Adds issue template. [skip ci] --- .github/ISSUE_TEMPLATE.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE.md diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000000000..a16cedd7fda0c --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,23 @@ + +### Describe the issue + +### Is the issue reproducible? +#### List steps to reproduce below: +1. +2. +3. + +### Expected behavior +Tell us what should happen + +### Actual behavior +Tell us what happens instead + +### Any information in the debug.log file related to this issue? + +### Screenshots (if available) + +### What binary version was used (official or self compiled) + +### Machine specs: CPU, RAM, Disk space & OS (Windows, OS X, Linux) + From 15df3c196b2359505980a2b0217133e0bb550565 Mon Sep 17 00:00:00 2001 From: Andrew Chow Date: Mon, 8 Aug 2016 14:17:23 -0400 Subject: [PATCH 0712/1802] Persist the datadir after option reset After a reset is performed, the datadir setting is saved and readded to the settings so that it is persisted across option resets. --- src/qt/optionsmodel.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 684db71a8ce03..7987d8e7ea470 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -16,6 +16,7 @@ #include "main.h" // For DEFAULT_SCRIPTCHECK_THREADS #include "net.h" #include "txdb.h" // for -dbcache defaults +#include "intro.h" #ifdef ENABLE_WALLET #include "wallet/wallet.h" @@ -98,6 +99,9 @@ void OptionsModel::Init(bool resetSettings) if (!SoftSetArg("-par", settings.value("nThreadsScriptVerif").toString().toStdString())) addOverriddenOption("-par"); + if (!settings.contains("strDataDir")) + settings.setValue("strDataDir", Intro::getDefaultDataDirectory()); + // Wallet #ifdef ENABLE_WALLET if (!settings.contains("bSpendZeroConfChange")) @@ -150,9 +154,16 @@ void OptionsModel::Reset() { QSettings settings; + // Save the strDataDir setting + QString dataDir = Intro::getDefaultDataDirectory(); + dataDir = settings.value("strDataDir", dataDir).toString(); + // Remove all entries from our QSettings object settings.clear(); + // Set strDataDir + settings.setValue("strDataDir", dataDir); + // default setting for OptionsModel::StartAtStartup - disabled if (GUIUtil::GetStartOnSystemStartup()) GUIUtil::SetStartOnSystemStartup(false); From b3b3c2a5623d5c942d2b3565cc2d833c65105555 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 26 Apr 2016 13:55:13 +0200 Subject: [PATCH 0713/1802] Reduce cs_main locks during ConnectTip/SyncWithWallets --- src/main.cpp | 40 +++++++++++++++----------- src/validationinterface.cpp | 4 +-- src/validationinterface.h | 6 ++-- src/wallet/wallet.cpp | 43 +++++++++++----------------- src/wallet/wallet.h | 6 ++-- src/zmq/zmqnotificationinterface.cpp | 2 +- src/zmq/zmqnotificationinterface.h | 2 +- 7 files changed, 49 insertions(+), 54 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 3a07190a6210f..db457f6f53d57 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1541,7 +1541,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C } } - SyncWithWallets(tx, NULL, NULL); + SyncWithWallets(tx, NULL); return true; } @@ -2770,7 +2770,7 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara // Let wallets know transactions went from 1-confirmed to // 0-confirmed or conflicted: BOOST_FOREACH(const CTransaction &tx, block.vtx) { - SyncWithWallets(tx, pindexDelete->pprev, NULL); + SyncWithWallets(tx, pindexDelete->pprev); } return true; } @@ -2785,7 +2785,7 @@ static int64_t nTimePostConnect = 0; * Connect a new block to chainActive. pblock is either NULL or a pointer to a CBlock * corresponding to pindexNew, to bypass loading it again from disk. */ -bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const CBlock* pblock) +bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const CBlock* pblock, std::list &txConflicted, std::vector > &txChanged) { assert(pindexNew->pprev == chainActive.Tip()); // Read block from disk. @@ -2821,20 +2821,13 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, return false; int64_t nTime5 = GetTimeMicros(); nTimeChainState += nTime5 - nTime4; LogPrint("bench", " - Writing chainstate: %.2fms [%.2fs]\n", (nTime5 - nTime4) * 0.001, nTimeChainState * 0.000001); - // Remove conflicting transactions from the mempool. - list txConflicted; + // Remove conflicting transactions from the mempool.; mempool.removeForBlock(pblock->vtx, pindexNew->nHeight, txConflicted, !IsInitialBlockDownload()); // Update chainActive & related variables. UpdateTip(pindexNew, chainparams); - // Tell wallet about transactions that went from mempool - // to conflicted: - BOOST_FOREACH(const CTransaction &tx, txConflicted) { - SyncWithWallets(tx, pindexNew, NULL); - } - // ... and about transactions that got confirmed: - BOOST_FOREACH(const CTransaction &tx, pblock->vtx) { - SyncWithWallets(tx, pindexNew, pblock); - } + + for(unsigned int i=0; i < pblock->vtx.size(); i++) + txChanged.push_back(std::make_tuple(pblock->vtx[i], pindexNew, i)); int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1; LogPrint("bench", " - Connect postprocess: %.2fms [%.2fs]\n", (nTime6 - nTime5) * 0.001, nTimePostConnect * 0.000001); @@ -2916,7 +2909,7 @@ static void PruneBlockIndexCandidates() { * Try to make some progress towards making pindexMostWork the active block. * pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork. */ -static bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const CBlock* pblock, bool& fInvalidFound) +static bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const CBlock* pblock, bool& fInvalidFound, std::list& txConflicted, std::vector >& txChanged) { AssertLockHeld(cs_main); const CBlockIndex *pindexOldTip = chainActive.Tip(); @@ -2949,7 +2942,7 @@ static bool ActivateBestChainStep(CValidationState& state, const CChainParams& c // Connect new blocks. BOOST_REVERSE_FOREACH(CBlockIndex *pindexConnect, vpindexToConnect) { - if (!ConnectTip(state, chainparams, pindexConnect, pindexConnect == pindexMostWork ? pblock : NULL)) { + if (!ConnectTip(state, chainparams, pindexConnect, pindexConnect == pindexMostWork ? pblock : NULL, txConflicted, txChanged)) { if (state.IsInvalid()) { // The block violates a consensus rule. if (!state.CorruptionPossible()) @@ -3024,6 +3017,8 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, break; const CBlockIndex *pindexFork; + std::list txConflicted; + std::vector > txChanged; bool fInitialDownload; int nNewHeight; { @@ -3038,7 +3033,7 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, return true; bool fInvalidFound = false; - if (!ActivateBestChainStep(state, chainparams, pindexMostWork, pblock && pblock->GetHash() == pindexMostWork->GetBlockHash() ? pblock : NULL, fInvalidFound)) + if (!ActivateBestChainStep(state, chainparams, pindexMostWork, pblock && pblock->GetHash() == pindexMostWork->GetBlockHash() ? pblock : NULL, fInvalidFound, txConflicted, txChanged)) return false; if (fInvalidFound) { @@ -3053,6 +3048,17 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, // When we reach this point, we switched to a new tip (stored in pindexNewTip). // Notifications/callbacks that can run without cs_main + + // throw all transactions though the signal-interface + // while _not_ holding the cs_main lock + BOOST_FOREACH(const CTransaction &tx, txConflicted) + { + SyncWithWallets(tx, pindexNewTip); + } + // ... and about transactions that got confirmed: + for(unsigned int i = 0; i < txChanged.size(); i++) + SyncWithWallets(std::get<0>(txChanged[i]), std::get<1>(txChanged[i]), std::get<2>(txChanged[i])); + // Always notify the UI if a new block tip was connected if (pindexFork != pindexNewTip) { uiInterface.NotifyBlockTip(fInitialDownload, pindexNewTip); diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index 8da0c72858d85..cf1d6ca08699a 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -48,6 +48,6 @@ void UnregisterAllValidationInterfaces() { g_signals.UpdatedBlockTip.disconnect_all_slots(); } -void SyncWithWallets(const CTransaction &tx, const CBlockIndex *pindex, const CBlock *pblock) { - g_signals.SyncTransaction(tx, pindex, pblock); +void SyncWithWallets(const CTransaction &tx, const CBlockIndex *pindex, int posInBlock) { + g_signals.SyncTransaction(tx, pindex, posInBlock); } diff --git a/src/validationinterface.h b/src/validationinterface.h index 01b8e47650dc4..094b1cfe26672 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -28,12 +28,12 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn); /** Unregister all wallets from core */ void UnregisterAllValidationInterfaces(); /** Push an updated transaction to all registered wallets */ -void SyncWithWallets(const CTransaction& tx, const CBlockIndex *pindex, const CBlock* pblock = NULL); +void SyncWithWallets(const CTransaction& tx, const CBlockIndex *pindex, int posInBlock = -1); class CValidationInterface { protected: virtual void UpdatedBlockTip(const CBlockIndex *pindex) {} - virtual void SyncTransaction(const CTransaction &tx, const CBlockIndex *pindex, const CBlock *pblock) {} + virtual void SyncTransaction(const CTransaction &tx, const CBlockIndex *pindex, int posInBlock) {} virtual void SetBestChain(const CBlockLocator &locator) {} virtual void UpdatedTransaction(const uint256 &hash) {} virtual void Inventory(const uint256 &hash) {} @@ -50,7 +50,7 @@ struct CMainSignals { /** Notifies listeners of updated block chain tip */ boost::signals2::signal UpdatedBlockTip; /** Notifies listeners of updated transaction data (transaction, and optionally the block it is found in. */ - boost::signals2::signal SyncTransaction; + boost::signals2::signal SyncTransaction; /** Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible). */ boost::signals2::signal UpdatedTransaction; /** Notifies listeners of a new active block chain. */ diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index ee9254050ce78..888aa029a3dcd 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -886,18 +886,18 @@ bool CWallet::LoadToWallet(const CWalletTx& wtxIn) * pblock is optional, but should be provided if the transaction is known to be in a block. * If fUpdate is true, existing transactions will be updated. */ -bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate) +bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate) { { AssertLockHeld(cs_wallet); - if (pblock) { + if (posInBlock != -1) { BOOST_FOREACH(const CTxIn& txin, tx.vin) { std::pair range = mapTxSpends.equal_range(txin.prevout); while (range.first != range.second) { if (range.first->second != tx.GetHash()) { - LogPrintf("Transaction %s (in block %s) conflicts with wallet transaction %s (both spend %s:%i)\n", tx.GetHash().ToString(), pblock->GetHash().ToString(), range.first->second.ToString(), range.first->first.hash.ToString(), range.first->first.n); - MarkConflicted(pblock->GetHash(), range.first->second); + LogPrintf("Transaction %s (in block %s) conflicts with wallet transaction %s (both spend %s:%i)\n", tx.GetHash().ToString(), pIndex->GetBlockHash().ToString(), range.first->second.ToString(), range.first->first.hash.ToString(), range.first->first.n); + MarkConflicted(pIndex->GetBlockHash(), range.first->second); } range.first++; } @@ -911,8 +911,8 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl CWalletTx wtx(this,tx); // Get merkle branch if transaction was found in a block - if (pblock) - wtx.SetMerkleBranch(*pblock); + if (posInBlock != -1) + wtx.SetMerkleBranch(pIndex, posInBlock); return AddToWallet(wtx, false); } @@ -1037,11 +1037,11 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx) } } -void CWallet::SyncTransaction(const CTransaction& tx, const CBlockIndex *pindex, const CBlock* pblock) +void CWallet::SyncTransaction(const CTransaction& tx, const CBlockIndex *pindex, int posInBlock) { LOCK2(cs_main, cs_wallet); - if (!AddToWalletIfInvolvingMe(tx, pblock, true)) + if (!AddToWalletIfInvolvingMe(tx, pindex, posInBlock, true)) return; // Not one of ours // If a transaction changes 'conflicted' state, that changes the balance @@ -1399,9 +1399,10 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) CBlock block; ReadBlockFromDisk(block, pindex, Params().GetConsensus()); - BOOST_FOREACH(CTransaction& tx, block.vtx) + int posInBlock; + for (posInBlock = 0; posInBlock < (int)block.vtx.size(); posInBlock++) { - if (AddToWalletIfInvolvingMe(tx, &block, fUpdate)) + if (AddToWalletIfInvolvingMe(block.vtx[posInBlock], pindex, posInBlock, fUpdate)) ret++; } pindex = chainActive.Next(pindex); @@ -3526,31 +3527,19 @@ CWalletKey::CWalletKey(int64_t nExpires) nTimeExpires = nExpires; } -int CMerkleTx::SetMerkleBranch(const CBlock& block) +int CMerkleTx::SetMerkleBranch(const CBlockIndex* pindex, int posInBlock) { AssertLockHeld(cs_main); CBlock blockTmp; // Update the tx's hashBlock - hashBlock = block.GetHash(); + hashBlock = pindex->GetBlockHash(); - // Locate the transaction - for (nIndex = 0; nIndex < (int)block.vtx.size(); nIndex++) - if (block.vtx[nIndex] == *(CTransaction*)this) - break; - if (nIndex == (int)block.vtx.size()) - { - nIndex = -1; - LogPrintf("ERROR: SetMerkleBranch(): couldn't find tx in block\n"); - return 0; - } + // set the position of the transaction in the block + nIndex = posInBlock; // Is the tx in a block that's in the main chain - BlockMap::iterator mi = mapBlockIndex.find(hashBlock); - if (mi == mapBlockIndex.end()) - return 0; - const CBlockIndex* pindex = (*mi).second; - if (!pindex || !chainActive.Contains(pindex)) + if (!chainActive.Contains(pindex)) return 0; return chainActive.Height() - pindex->nHeight + 1; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 50c94ccfbcd95..952acd1535abf 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -200,7 +200,7 @@ class CMerkleTx : public CTransaction READWRITE(nIndex); } - int SetMerkleBranch(const CBlock& block); + int SetMerkleBranch(const CBlockIndex* pIndex, int posInBlock); /** * Return depth of transaction in blockchain: @@ -731,8 +731,8 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface void MarkDirty(); bool AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose=true); bool LoadToWallet(const CWalletTx& wtxIn); - void SyncTransaction(const CTransaction& tx, const CBlockIndex *pindex, const CBlock* pblock); - bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate); + void SyncTransaction(const CTransaction& tx, const CBlockIndex *pindex, int posInBlock); + bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate); int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false); void ReacceptWalletTransactions(); void ResendWalletTransactions(int64_t nBestBlockTime); diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp index 8705532429fe8..376e7dec590b5 100644 --- a/src/zmq/zmqnotificationinterface.cpp +++ b/src/zmq/zmqnotificationinterface.cpp @@ -141,7 +141,7 @@ void CZMQNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindex) } } -void CZMQNotificationInterface::SyncTransaction(const CTransaction& tx, const CBlockIndex* pindex, const CBlock* pblock) +void CZMQNotificationInterface::SyncTransaction(const CTransaction& tx, const CBlockIndex* pindex, int posInBlock) { for (std::list::iterator i = notifiers.begin(); i!=notifiers.end(); ) { diff --git a/src/zmq/zmqnotificationinterface.h b/src/zmq/zmqnotificationinterface.h index 7b52e7775bc53..a853447267f31 100644 --- a/src/zmq/zmqnotificationinterface.h +++ b/src/zmq/zmqnotificationinterface.h @@ -24,7 +24,7 @@ class CZMQNotificationInterface : public CValidationInterface void Shutdown(); // CValidationInterface - void SyncTransaction(const CTransaction& tx, const CBlockIndex *pindex, const CBlock* pblock); + void SyncTransaction(const CTransaction& tx, const CBlockIndex *pindex, int posInBlock); void UpdatedBlockTip(const CBlockIndex *pindex); private: From 9e9d644f5178da8b5743ea3ddc3b779a2c8d1cd4 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 12 Aug 2016 14:21:50 -0400 Subject: [PATCH 0714/1802] net: fixup nits --- src/Makefile.am | 2 +- src/httpserver.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 0a35a052c24ab..03fac5bf979ac 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -105,8 +105,8 @@ BITCOIN_CORE_H = \ merkleblock.h \ miner.h \ net.h \ - netbase.h \ netaddress.h \ + netbase.h \ noui.h \ policy/fees.h \ policy/policy.h \ diff --git a/src/httpserver.cpp b/src/httpserver.cpp index 2bb4be564ea94..f921305fcc36b 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -201,7 +201,7 @@ static bool InitHTTPAllowList() CNetAddr localv6; LookupHost("127.0.0.1", localv4, false); LookupHost("::1", localv6, false); - rpc_allow_subnets.push_back(CSubNet(localv4, 8)); // always allow IPv4 local subnet + rpc_allow_subnets.push_back(CSubNet(localv4, 8)); // always allow IPv4 local subnet rpc_allow_subnets.push_back(CSubNet(localv6)); // always allow IPv6 localhost if (mapMultiArgs.count("-rpcallowip")) { const std::vector& vAllow = mapMultiArgs["-rpcallowip"]; From e11f9a2f0244f1d6e34b50293b2ecca61a356bed Mon Sep 17 00:00:00 2001 From: Justin Camarena Date: Fri, 12 Aug 2016 15:30:11 -0700 Subject: [PATCH 0715/1802] [doc] typos, READMEs, comments Just a quick run through some docs and fixing some text errors. --- doc/README_osx.md | 2 +- doc/release-notes.md | 2 +- doc/translation_process.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/README_osx.md b/doc/README_osx.md index aed3cd97e1ecd..6a5c672277cf7 100644 --- a/doc/README_osx.md +++ b/doc/README_osx.md @@ -22,7 +22,7 @@ These tools inject timestamps by default, which produce non-deterministic binaries. The ZERO_AR_DATE environment variable is used to disable that. This version of cctools has been patched to use the current version of clang's -headers and and its libLTO.so rather than those from llvmgcc, as it was +headers and its libLTO.so rather than those from llvmgcc, as it was originally done in toolchain4. To complicate things further, all builds must target an Apple SDK. These SDKs diff --git a/doc/release-notes.md b/doc/release-notes.md index 343bd0846ecc0..b99192ae97c9b 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -31,7 +31,7 @@ libraries such as Qt are no longer being tested on XP. We do not have time nor resources to provide support for an OS that is end-of-life. From 0.13.0 on, Windows XP is no longer supported. Users are -suggested to upgrade to a newer verion of Windows, or install an alternative OS +suggested to upgrade to a newer version of Windows, or install an alternative OS that is supported. No attempt is made to prevent installing or running the software on Windows XP, diff --git a/doc/translation_process.md b/doc/translation_process.md index 310d560b364fa..d8a85292e8ed8 100644 --- a/doc/translation_process.md +++ b/doc/translation_process.md @@ -94,7 +94,7 @@ When new plurals are added to the source file, it's important to do the followin 7. Save the source file ### Translating a new language -To create a new language template, you will need to edit the languages manifest file `src/qt/bitcoin.qrc` and add a new entry. Below is an example of the english language entry. +To create a new language template, you will need to edit the languages manifest file `src/qt/bitcoin.qrc` and add a new entry. Below is an example of the English language entry. ```xml From 3c5251daeb29902b051502dd20030ce25aeccdf2 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sat, 13 Aug 2016 16:03:44 +0200 Subject: [PATCH 0716/1802] test: Remove java comparison tool --- Makefile.am | 24 +++-------------- configure.ac | 32 ----------------------- depends/config.site.in | 3 --- depends/packages/native_comparisontool.mk | 21 --------------- depends/packages/packages.mk | 2 +- 5 files changed, 5 insertions(+), 77 deletions(-) delete mode 100644 depends/packages/native_comparisontool.mk diff --git a/Makefile.am b/Makefile.am index b10d0850664c8..37c1e98eca6bc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -47,9 +47,9 @@ OSX_PACKAGING = $(OSX_DEPLOY_SCRIPT) $(OSX_FANCY_PLIST) $(OSX_INSTALLER_ICONS) \ $(top_srcdir)/contrib/macdeploy/detached-sig-apply.sh \ $(top_srcdir)/contrib/macdeploy/detached-sig-create.sh -COVERAGE_INFO = baseline_filtered_combined.info baseline.info block_test.info \ +COVERAGE_INFO = baseline_filtered_combined.info baseline.info \ leveldb_baseline.info test_bitcoin_filtered.info total_coverage.info \ - baseline_filtered.info block_test_filtered.info rpc_test.info rpc_test_filtered.info \ + baseline_filtered.info rpc_test.info rpc_test_filtered.info \ leveldb_baseline_filtered.info test_bitcoin_coverage.info test_bitcoin.info dist-hook: @@ -175,16 +175,6 @@ test_bitcoin.info: baseline_filtered_combined.info test_bitcoin_filtered.info: test_bitcoin.info $(LCOV) -r $< "/usr/include/*" -o $@ -block_test.info: test_bitcoin_filtered.info - $(MKDIR_P) qa/tmp - -@TIMEOUT=15 qa/pull-tester/run-bitcoind-for-test.sh $(JAVA) -jar $(JAVA_COMPARISON_TOOL) qa/tmp/compTool $(COMPARISON_TOOL_REORG_TESTS) - $(LCOV) -c -d $(abs_builddir)/src --t BitcoinJBlockTest -o $@ - $(LCOV) -z -d $(abs_builddir)/src - $(LCOV) -z -d $(abs_builddir)/src/leveldb - -block_test_filtered.info: block_test.info - $(LCOV) -r $< "/usr/include/*" -o $@ - rpc_test.info: test_bitcoin_filtered.info -@TIMEOUT=15 python qa/pull-tester/rpc-tests.py $(EXTENDED_RPC_TESTS) $(LCOV) -c -d $(abs_builddir)/src --t rpc-tests -o $@ @@ -197,8 +187,8 @@ rpc_test_filtered.info: rpc_test.info test_bitcoin_coverage.info: baseline_filtered_combined.info test_bitcoin_filtered.info $(LCOV) -a baseline_filtered.info -a leveldb_baseline_filtered.info -a test_bitcoin_filtered.info -o $@ -total_coverage.info: baseline_filtered_combined.info test_bitcoin_filtered.info block_test_filtered.info rpc_test_filtered.info - $(LCOV) -a baseline_filtered.info -a leveldb_baseline_filtered.info -a test_bitcoin_filtered.info -a block_test_filtered.info -a rpc_test_filtered.info -o $@ | $(GREP) "\%" | $(AWK) '{ print substr($$3,2,50) "/" $$5 }' > coverage_percent.txt +total_coverage.info: baseline_filtered_combined.info test_bitcoin_filtered.info rpc_test_filtered.info + $(LCOV) -a baseline_filtered.info -a leveldb_baseline_filtered.info -a test_bitcoin_filtered.info -a rpc_test_filtered.info -o $@ | $(GREP) "\%" | $(AWK) '{ print substr($$3,2,50) "/" $$5 }' > coverage_percent.txt test_bitcoin.coverage/.dirstamp: test_bitcoin_coverage.info $(GENHTML) -s $< -o $(@D) @@ -212,12 +202,6 @@ cov: test_bitcoin.coverage/.dirstamp total.coverage/.dirstamp endif -if USE_COMPARISON_TOOL -check-local: - $(MKDIR_P) qa/tmp - @qa/pull-tester/run-bitcoind-for-test.sh $(JAVA) -jar $(JAVA_COMPARISON_TOOL) qa/tmp/compTool $(COMPARISON_TOOL_REORG_TESTS) 2>&1 -endif - dist_noinst_SCRIPTS = autogen.sh EXTRA_DIST = $(top_srcdir)/share/genbuild.sh qa/pull-tester/rpc-tests.py qa/rpc-tests $(DIST_DOCS) $(WINDOWS_PACKAGING) $(OSX_PACKAGING) $(BIN_CHECKS) diff --git a/configure.ac b/configure.ac index c4b60398be2a1..508c3b8a4dc48 100644 --- a/configure.ac +++ b/configure.ac @@ -66,7 +66,6 @@ AC_PATH_TOOL(RANLIB, ranlib) AC_PATH_TOOL(STRIP, strip) AC_PATH_TOOL(GCOV, gcov) AC_PATH_PROG(LCOV, lcov) -AC_PATH_PROG(JAVA, java) AC_PATH_PROGS([PYTHON], [python3 python2.7 python2 python]) AC_PATH_PROG(GENHTML, genhtml) AC_PATH_PROG([GIT], [git]) @@ -113,16 +112,6 @@ AC_ARG_ENABLE(bench, [use_bench=$enableval], [use_bench=yes]) -AC_ARG_WITH([comparison-tool], - AS_HELP_STRING([--with-comparison-tool],[path to java comparison tool (requires --enable-tests)]), - [use_comparison_tool=$withval], - [use_comparison_tool=no]) - -AC_ARG_ENABLE([comparison-tool-reorg-tests], - AS_HELP_STRING([--enable-comparison-tool-reorg-tests],[enable expensive reorg tests in the comparison tool (default no)]), - [use_comparison_tool_reorg_tests=$enableval], - [use_comparison_tool_reorg_tests=no]) - AC_ARG_ENABLE([extended-rpc-tests], AS_HELP_STRING([--enable-extended-rpc-tests],[enable expensive RPC tests when using lcov (default no)]), [use_extended_rpc_tests=$enableval], @@ -382,19 +371,6 @@ if test x$use_pkgconfig = xyes; then ]) fi -if test x$use_comparison_tool != xno; then - AC_SUBST(JAVA_COMPARISON_TOOL, $use_comparison_tool) -fi - -if test x$use_comparison_tool_reorg_tests != xno; then - if test x$use_comparison_tool = x; then - AC_MSG_ERROR("comparison tool reorg tests but comparison tool was not specified") - fi - AC_SUBST(COMPARISON_TOOL_REORG_TESTS, 1) -else - AC_SUBST(COMPARISON_TOOL_REORG_TESTS, 0) -fi - if test x$use_extended_rpc_tests != xno; then AC_SUBST(EXTENDED_RPC_TESTS, -extended) fi @@ -406,18 +382,12 @@ if test x$use_lcov = xyes; then if test x$GCOV = x; then AC_MSG_ERROR("lcov testing requested but gcov not found") fi - if test x$JAVA = x; then - AC_MSG_ERROR("lcov testing requested but java not found") - fi if test x$PYTHON = x; then AC_MSG_ERROR("lcov testing requested but python not found") fi if test x$GENHTML = x; then AC_MSG_ERROR("lcov testing requested but genhtml not found") fi - if test x$use_comparison_tool = x; then - AC_MSG_ERROR("lcov testing requested but comparison tool was not specified") - fi LCOV="$LCOV --gcov-tool=$GCOV" AX_CHECK_COMPILE_FLAG([--coverage],[CXXFLAGS="$CXXFLAGS --coverage"], [AC_MSG_ERROR("lcov testing requested but --coverage flag does not work")]) @@ -1036,8 +1006,6 @@ AM_CONDITIONAL([ENABLE_QT_TESTS],[test x$BUILD_TEST_QT = xyes]) AM_CONDITIONAL([ENABLE_BENCH],[test x$use_bench = xyes]) AM_CONDITIONAL([USE_QRCODE], [test x$use_qr = xyes]) AM_CONDITIONAL([USE_LCOV],[test x$use_lcov = xyes]) -AM_CONDITIONAL([USE_COMPARISON_TOOL],[test x$use_comparison_tool != xno]) -AM_CONDITIONAL([USE_COMPARISON_TOOL_REORG_TESTS],[test x$use_comparison_tool_reorg_test != xno]) AM_CONDITIONAL([GLIBC_BACK_COMPAT],[test x$use_glibc_compat = xyes]) AM_CONDITIONAL([HARDEN],[test x$use_hardening = xyes]) diff --git a/depends/config.site.in b/depends/config.site.in index e731537bf76bd..27e3aedd8ed4f 100644 --- a/depends/config.site.in +++ b/depends/config.site.in @@ -19,9 +19,6 @@ fi if test -z $with_protoc_bindir; then with_protoc_bindir=$depends_prefix/native/bin fi -if test -z $with_comparison_tool; then - with_comparison_tool=$depends_prefix/native/share/BitcoindComparisonTool_jar/BitcoindComparisonTool.jar -fi if test -z $enable_wallet && test -n "@no_wallet@"; then diff --git a/depends/packages/native_comparisontool.mk b/depends/packages/native_comparisontool.mk deleted file mode 100644 index e0ae0cec700e9..0000000000000 --- a/depends/packages/native_comparisontool.mk +++ /dev/null @@ -1,21 +0,0 @@ -package=native_comparisontool -$(package)_version=8c6666f -$(package)_download_path=https://github.com/theuni/bitcoind-comparisontool/raw/master -$(package)_file_name=pull-tests-$($(package)_version).jar -$(package)_sha256_hash=a865332b3827abcde684ab79f5f43c083b0b6a4c97ff5508c79f29fee24f11cd -$(package)_install_dirname=BitcoindComparisonTool_jar -$(package)_install_filename=BitcoindComparisonTool.jar - -define $(package)_extract_cmds -endef - -define $(package)_configure_cmds -endef - -define $(package)_build_cmds -endef - -define $(package)_stage_cmds - mkdir -p $($(package)_staging_prefix_dir)/share/$($(package)_install_dirname) && \ - cp $($(package)_source) $($(package)_staging_prefix_dir)/share/$($(package)_install_dirname)/$($(package)_install_filename) -endef diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk index ba2a05248c04e..4cf44385b88dc 100644 --- a/depends/packages/packages.mk +++ b/depends/packages/packages.mk @@ -1,5 +1,5 @@ packages:=boost openssl libevent zeromq -native_packages := native_ccache native_comparisontool +native_packages := native_ccache qt_native_packages = native_protobuf qt_packages = qrencode protobuf From 6ffd996b8ee5f36ed4490410385f9b072da5889b Mon Sep 17 00:00:00 2001 From: Sev Date: Sun, 14 Aug 2016 15:35:27 +0300 Subject: [PATCH 0717/1802] Corrected JSON typo on setban of net.cpp --- src/rpc/net.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index b85c7b2e1aaa5..89035aaa848c0 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -484,7 +484,7 @@ UniValue setban(const UniValue& params, bool fHelp) "\nExamples:\n" + HelpExampleCli("setban", "\"192.168.0.6\" \"add\" 86400") + HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"") - + HelpExampleRpc("setban", "\"192.168.0.6\", \"add\" 86400") + + HelpExampleRpc("setban", "\"192.168.0.6\", \"add\", 86400") ); CSubNet subNet; From 1aacfc2da521a8e0d718e9ac561d9b2d7916eb0b Mon Sep 17 00:00:00 2001 From: leijurv Date: Sat, 13 Aug 2016 11:21:13 -0600 Subject: [PATCH 0718/1802] various typos --- src/blockencodings.cpp | 2 +- src/init.cpp | 2 +- src/main.cpp | 6 +++--- src/main.h | 2 +- src/net.cpp | 2 +- src/rpc/mining.cpp | 2 +- src/wallet/wallet.cpp | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/blockencodings.cpp b/src/blockencodings.cpp index 5c4c3bd27487c..df237f8f26f58 100644 --- a/src/blockencodings.cpp +++ b/src/blockencodings.cpp @@ -75,7 +75,7 @@ ReadStatus PartiallyDownloadedBlock::InitData(const CBlockHeaderAndShortTxIDs& c } prefilled_count = cmpctblock.prefilledtxn.size(); - // Calculate map of txids -> positions and check mempool to see what we have (or dont) + // Calculate map of txids -> positions and check mempool to see what we have (or don't) // Because well-formed cmpctblock messages will have a (relatively) uniform distribution // of short IDs, any highly-uneven distribution of elements can be safely treated as a // READ_STATUS_FAILED. diff --git a/src/init.cpp b/src/init.cpp index 4d9de6cfc8c9f..6af9d30cdfc40 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1267,7 +1267,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // cache size calculations int64_t nTotalCache = (GetArg("-dbcache", nDefaultDbCache) << 20); nTotalCache = std::max(nTotalCache, nMinDbCache << 20); // total cache cannot be less than nMinDbCache - nTotalCache = std::min(nTotalCache, nMaxDbCache << 20); // total cache cannot be greated than nMaxDbcache + nTotalCache = std::min(nTotalCache, nMaxDbCache << 20); // total cache cannot be greater than nMaxDbcache int64_t nBlockTreeDBCache = nTotalCache / 8; nBlockTreeDBCache = std::min(nBlockTreeDBCache, (GetBoolArg("-txindex", DEFAULT_TXINDEX) ? nMaxBlockDBAndTxIndexCache : nMaxBlockDBCache) << 20); nTotalCache -= nBlockTreeDBCache; diff --git a/src/main.cpp b/src/main.cpp index 3a07190a6210f..64c67ff0f601a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1174,7 +1174,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C // nSequence >= maxint-1 on all inputs. // // maxint-1 is picked to still allow use of nLockTime by - // non-replacable transactions. All inputs rather than just one + // non-replaceable transactions. All inputs rather than just one // is for the sake of multi-party protocols, where we don't // want a single party to be able to disable replacement. // @@ -1988,7 +1988,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi // is safe because block merkle hashes are still computed and checked, // and any change will be caught at the next checkpoint. Of course, if // the checkpoint is for a chain that's invalid due to false scriptSigs - // this optimisation would allow an invalid chain to be accepted. + // this optimization would allow an invalid chain to be accepted. if (fScriptChecks) { for (unsigned int i = 0; i < tx.vin.size(); i++) { const COutPoint &prevout = tx.vin[i].prevout; @@ -4795,7 +4795,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam { // If a peer is asking for old blocks, we're almost guaranteed // they wont have a useful mempool to match against a compact block, - // and we dont feel like constructing the object for them, so + // and we don't feel like constructing the object for them, so // instead we respond with the full, non-compact block. if (mi->second->nHeight >= chainActive.Height() - 10) { CBlockHeaderAndShortTxIDs cmpctblock(block); diff --git a/src/main.h b/src/main.h index d4d70c018027d..e9106fccf7927 100644 --- a/src/main.h +++ b/src/main.h @@ -214,7 +214,7 @@ void UnregisterNodeSignals(CNodeSignals& nodeSignals); * block is made active. Note that it does not, however, guarantee that the * specific block passed to it has been checked for validity! * - * @param[out] state This may be set to an Error state if any error occurred processing it, including during validation/connection/etc of otherwise unrelated blocks during reorganisation; or it may be set to an Invalid state if pblock is itself invalid (but this is not guaranteed even when the block is checked). If you want to *possibly* get feedback on whether pblock is valid, you must also install a CValidationInterface (see validationinterface.h) - this will have its BlockChecked method called whenever *any* block completes validation. + * @param[out] state This may be set to an Error state if any error occurred processing it, including during validation/connection/etc of otherwise unrelated blocks during reorganization; or it may be set to an Invalid state if pblock is itself invalid (but this is not guaranteed even when the block is checked). If you want to *possibly* get feedback on whether pblock is valid, you must also install a CValidationInterface (see validationinterface.h) - this will have its BlockChecked method called whenever *any* block completes validation. * @param[in] pfrom The node which we are receiving the block from; it is added to mapBlockSource and may be penalised if the block is invalid. * @param[in] pblock The block we want to process. * @param[in] fForceProcessing Process this block even if unrequested; used for non-network block sources and whitelisted peers. diff --git a/src/net.cpp b/src/net.cpp index 4bbe5059df188..4f669f3382641 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1676,7 +1676,7 @@ void ThreadOpenConnections() if (nANow - addr.nLastTry < 600 && nTries < 30) continue; - // only consider nodes missing relevant services after 40 failed attemps + // only consider nodes missing relevant services after 40 failed attempts if ((addr.nServices & nRelevantServices) != nRelevantServices && nTries < 40) continue; diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 2479e5d5953d2..6d88d4bec8147 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -650,7 +650,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) if (nMaxVersionPreVB >= 2) { // If VB is supported by the client, nMaxVersionPreVB is -1, so we won't get here - // Because BIP 34 changed how the generation transaction is serialised, we can only use version/force back to v2 blocks + // Because BIP 34 changed how the generation transaction is serialized, we can only use version/force back to v2 blocks // This is safe to do [otherwise-]unconditionally only because we are throwing an exception above if a non-force deployment gets activated // Note that this can probably also be removed entirely after the first BIP9 non-force deployment (ie, probably segwit) gets activated aMutable.push_back("version/force"); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index ee9254050ce78..8a3bebcc6701b 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3132,7 +3132,7 @@ void CWallet::GetKeyBirthTimes(std::map &mapKeyBirth) const { mapKeyBirth[it->first] = it->second.nCreateTime; // map in which we'll infer heights of other keys - CBlockIndex *pindexMax = chainActive[std::max(0, chainActive.Height() - 144)]; // the tip can be reorganised; use a 144-block safety margin + CBlockIndex *pindexMax = chainActive[std::max(0, chainActive.Height() - 144)]; // the tip can be reorganized; use a 144-block safety margin std::map mapKeyFirstBlock; std::set setKeys; GetKeys(setKeys); From 8194a6e525514d5cda85ac08273a6ffb6d5b6cac Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Sun, 14 Aug 2016 20:45:46 -0400 Subject: [PATCH 0719/1802] Fix a type error that would not compile on Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn) --- src/httpserver.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/httpserver.h b/src/httpserver.h index 0e30e666a6b42..49d67f4b88427 100644 --- a/src/httpserver.h +++ b/src/httpserver.h @@ -33,7 +33,7 @@ void InterruptHTTPServer(); void StopHTTPServer(); /** Handler for requests to a certain HTTP path */ -typedef std::function HTTPRequestHandler; +typedef std::function HTTPRequestHandler; /** Register handler for prefix. * If multiple handlers match a prefix, the first-registered one will * be invoked. From b7c349d5e7c207bb7a2e7469c3e5522c9909c17f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Mon, 15 Aug 2016 14:10:07 +0200 Subject: [PATCH 0720/1802] Do not shadow variables in networking code --- src/net.cpp | 2 +- src/net.h | 12 ++++++------ src/netaddress.cpp | 4 ++-- src/netbase.cpp | 6 +++--- src/netbase.h | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index a0773b2e07cb8..8fbd8fd192b89 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -66,7 +66,7 @@ namespace { SOCKET socket; bool whitelisted; - ListenSocket(SOCKET socket, bool whitelisted) : socket(socket), whitelisted(whitelisted) {} + ListenSocket(SOCKET _socket, bool _whitelisted) : socket(_socket), whitelisted(_whitelisted) {} }; } diff --git a/src/net.h b/src/net.h index ea03defc408cf..b5ebe66ce0363 100644 --- a/src/net.h +++ b/src/net.h @@ -509,21 +509,21 @@ class CNode - void AddAddressKnown(const CAddress& addr) + void AddAddressKnown(const CAddress& _addr) { - addrKnown.insert(addr.GetKey()); + addrKnown.insert(_addr.GetKey()); } - void PushAddress(const CAddress& addr) + void PushAddress(const CAddress& _addr) { // Known checking here is only to save space from duplicates. // SendMessages will filter it again for knowns that were added // after addresses were pushed. - if (addr.IsValid() && !addrKnown.contains(addr.GetKey())) { + if (_addr.IsValid() && !addrKnown.contains(_addr.GetKey())) { if (vAddrToSend.size() >= MAX_ADDR_TO_SEND) { - vAddrToSend[insecure_rand() % vAddrToSend.size()] = addr; + vAddrToSend[insecure_rand() % vAddrToSend.size()] = _addr; } else { - vAddrToSend.push_back(addr); + vAddrToSend.push_back(_addr); } } } diff --git a/src/netaddress.cpp b/src/netaddress.cpp index 7000ce3f0acce..db5cc3bc20a0e 100644 --- a/src/netaddress.cpp +++ b/src/netaddress.cpp @@ -197,8 +197,8 @@ bool CNetAddr::IsValid() const return false; // unspecified IPv6 address (::/128) - unsigned char ipNone[16] = {}; - if (memcmp(ip, ipNone, 16) == 0) + unsigned char ipNone6[16] = {}; + if (memcmp(ip, ipNone6, 16) == 0) return false; // documentation IPv6 address diff --git a/src/netbase.cpp b/src/netbase.cpp index 4f243ec6f5397..7d7f1b6788984 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -631,8 +631,8 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest SplitHostPort(std::string(pszDest), port, strDest); - proxyType nameProxy; - GetNameProxy(nameProxy); + proxyType proxy; + GetNameProxy(proxy); std::vector addrResolved; if (Lookup(strDest.c_str(), addrResolved, port, fNameLookup && !HaveNameProxy(), 256)) { @@ -646,7 +646,7 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest if (!HaveNameProxy()) return false; - return ConnectThroughProxy(nameProxy, strDest, port, hSocketRet, nTimeout, outProxyConnectionFailed); + return ConnectThroughProxy(proxy, strDest, port, hSocketRet, nTimeout, outProxyConnectionFailed); } bool LookupSubNet(const char* pszName, CSubNet& ret) diff --git a/src/netbase.h b/src/netbase.h index bb12019a8216b..eb39d16578ed4 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -29,7 +29,7 @@ class proxyType { public: proxyType(): randomize_credentials(false) {} - proxyType(const CService &proxy, bool randomize_credentials=false): proxy(proxy), randomize_credentials(randomize_credentials) {} + proxyType(const CService &_proxy, bool _randomize_credentials=false): proxy(_proxy), randomize_credentials(_randomize_credentials) {} bool IsValid() const { return proxy.IsValid(); } From edb6cf1432568bc54cd3d6a6cc260f3f265403f6 Mon Sep 17 00:00:00 2001 From: instagibbs Date: Mon, 15 Aug 2016 10:28:53 -0400 Subject: [PATCH 0721/1802] remove no-longer-used InitError logic --- src/init.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 72095da4a22d8..5ef8af8b3fd31 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1067,7 +1067,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) LogPrintf("Using data directory %s\n", strDataDir); LogPrintf("Using config file %s\n", GetConfigFile().string()); LogPrintf("Using at most %i connections (%i file descriptors available)\n", nMaxConnections, nFD); - std::ostringstream strErrors; LogPrintf("Using %u threads for script verification\n", nScriptCheckThreads); if (nScriptCheckThreads) { @@ -1492,9 +1491,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // ********************************************************* Step 11: start node - if (!strErrors.str().empty()) - return InitError(strErrors.str()); - //// debug print LogPrintf("mapBlockIndex.size() = %u\n", mapBlockIndex.size()); LogPrintf("nBestHeight = %d\n", chainActive.Height()); From 936c1448ed2e247e99fd3570fd8677870721c8b7 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 16 Aug 2016 11:16:21 +0200 Subject: [PATCH 0722/1802] build: Remove check for `openssl/ec.h` We don't use any elliptic curves from OpenSSL anymore, nor include this header anywhere but optionally in the tests of secp256k1 (which has its own autoconf setup). Reported by sinetek on IRC. --- configure.ac | 8 -------- 1 file changed, 8 deletions(-) diff --git a/configure.ac b/configure.ac index c4b60398be2a1..b1492deba4768 100644 --- a/configure.ac +++ b/configure.ac @@ -880,14 +880,6 @@ AM_CONDITIONAL([EMBEDDED_UNIVALUE],[test x$need_bundled_univalue = xyes]) AC_SUBST(UNIVALUE_CFLAGS) AC_SUBST(UNIVALUE_LIBS) -CXXFLAGS_TEMP="$CXXFLAGS" -LIBS_TEMP="$LIBS" -CXXFLAGS="$CXXFLAGS $SSL_CFLAGS $CRYPTO_CFLAGS" -LIBS="$LIBS $SSL_LIBS $CRYPTO_LIBS" -AC_CHECK_HEADER([openssl/ec.h],, AC_MSG_ERROR(OpenSSL ec header missing),) -CXXFLAGS="$CXXFLAGS_TEMP" -LIBS="$LIBS_TEMP" - BITCOIN_QT_PATH_PROGS([PROTOC], [protoc],$protoc_bin_path) AC_MSG_CHECKING([whether to build bitcoind]) From b2135359b3ad37cf2ac09b008079ddb237eff2c9 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 16 Aug 2016 11:34:11 +0200 Subject: [PATCH 0723/1802] Squashed 'src/secp256k1/' changes from 6c527ec..7a49cac 7a49cac Merge #410: Add string.h include to ecmult_impl 0bbd5d4 Add string.h include to ecmult_impl c5b32e1 Merge #405: Make secp256k1_fe_sqrt constant time 926836a Make secp256k1_fe_sqrt constant time e2a8e92 Merge #404: Replace 3M + 4S doubling formula with 2M + 5S one 8ec49d8 Add note about 2M + 5S doubling formula 5a91bd7 Merge #400: A couple minor cleanups ac01378 build: add -DSECP256K1_BUILD to benchmark_internal build flags a6c6f99 Remove a bunch of unused stdlib #includes 65285a6 Merge #403: configure: add flag to disable OpenSSL tests a9b2a5d configure: add flag to disable OpenSSL tests b340123 Merge #402: Add support for testing quadratic residues e6e9805 Add function for testing quadratic residue field/group elements. efd953a Add Jacobi symbol test via GMP fa36a0d Merge #401: ecmult_const: unify endomorphism and non-endomorphism skew cases c6191fd ecmult_const: unify endomorphism and non-endomorphism skew cases 0b3e618 Merge #378: .gitignore build-aux cleanup 6042217 Merge #384: JNI: align shared files copyright/comments to bitcoinj's 24ad20f Merge #399: build: verify that the native compiler works for static precomp b3be852 Merge #398: Test whether ECDH and Schnorr are enabled for JNI aa0b1fd build: verify that the native compiler works for static precomp eee808d Test whether ECDH and Schnorr are enabled for JNI 7b0fb18 Merge #366: ARM assembly implementation of field_10x26 inner (rebase of #173) 001f176 ARM assembly implementation of field_10x26 inner 0172be9 Merge #397: Small fixes for sha256 3f8b78e Fix undefs in hash_impl.h 2ab4695 Fix state size in sha256 struct 6875b01 Merge #386: Add some missing `VERIFY_CHECK(ctx != NULL)` 2c52b5d Merge #389: Cast pointers through uintptr_t under JNI 43097a4 Merge #390: Update bitcoin-core GitHub links 31c9c12 Merge #391: JNI: Only call ecdsa_verify if its inputs parsed correctly 1cb2302 Merge #392: Add testcase which hits additional branch in secp256k1_scalar_sqr d2ee340 Merge #388: bench_ecdh: fix call to secp256k1_context_create 093a497 Add testcase which hits additional branch in secp256k1_scalar_sqr a40c701 JNI: Only call ecdsa_verify if its inputs parsed correctly faa2a11 Update bitcoin-core GitHub links 47b9e78 Cast pointers through uintptr_t under JNI f36f9c6 bench_ecdh: fix call to secp256k1_context_create bcc4881 Add some missing `VERIFY_CHECK(ctx != NULL)` for functions that use `ARG_CHECK` 6ceea2c align shared files copyright/comments to bitcoinj's 70141a8 Update .gitignore 7b549b1 Merge #373: build: fix x86_64 asm detection for some compilers bc7c93c Merge #374: Add note about y=0 being possible on one of the sextic twists e457018 Merge #364: JNI rebased 86e2d07 JNI library: cleanup, removed unimplemented code 3093576a JNI library bd2895f Merge pull request #371 e72e93a Add note about y=0 being possible on one of the sextic twists 3f8fdfb build: fix x86_64 asm detection for some compilers e5a9047 [Trivial] Remove double semicolons c18b869 Merge pull request #360 3026daa Merge pull request #302 03d4611 Add sage verification script for the group laws a965937 Merge pull request #361 83221ec Add experimental features to configure 5d4c5a3 Prevent damage_array in the signature test from going out of bounds. 419bf7f Merge pull request #356 03d84a4 Benchmark against OpenSSL verification git-subtree-dir: src/secp256k1 git-subtree-split: 7a49cacd3937311fcb1cb36b6ba3336fca811991 --- .gitignore | 19 +- .travis.yml | 19 +- Makefile.am | 72 +- README.md | 2 +- build-aux/m4/ax_jni_include_dir.m4 | 140 +++ build-aux/m4/bitcoin_secp.m4 | 4 +- configure.ac | 146 ++- libsecp256k1.pc.in | 2 +- sage/group_prover.sage | 322 ++++++ sage/secp256k1.sage | 306 ++++++ sage/weierstrass_prover.sage | 264 +++++ src/asm/field_10x26_arm.s | 919 ++++++++++++++++++ src/bench_ecdh.c | 3 +- src/bench_internal.c | 34 +- src/bench_verify.c | 44 + src/ecmult_const_impl.h | 67 +- src/ecmult_impl.h | 2 + src/field.h | 8 +- src/field_10x26_impl.h | 12 +- src/field_5x52_impl.h | 1 - src/field_5x52_int128_impl.h | 4 +- src/field_impl.h | 36 +- src/group.h | 5 +- src/group_impl.h | 36 +- src/hash.h | 2 +- src/hash_impl.h | 10 +- src/java/org/bitcoin/NativeSecp256k1.java | 472 ++++++++- src/java/org/bitcoin/NativeSecp256k1Test.java | 247 +++++ src/java/org/bitcoin/NativeSecp256k1Util.java | 45 + src/java/org/bitcoin/Secp256k1Context.java | 51 + src/java/org_bitcoin_NativeSecp256k1.c | 412 +++++++- src/java/org_bitcoin_NativeSecp256k1.h | 112 ++- src/java/org_bitcoin_Secp256k1Context.c | 15 + src/java/org_bitcoin_Secp256k1Context.h | 22 + src/modules/ecdh/Makefile.am.include | 2 +- src/modules/recovery/Makefile.am.include | 2 +- src/modules/schnorr/Makefile.am.include | 2 +- src/num.h | 6 + src/num_gmp_impl.h | 26 + src/scalar_impl.h | 2 - src/secp256k1.c | 15 +- src/tests.c | 190 +++- 42 files changed, 3905 insertions(+), 195 deletions(-) create mode 100644 build-aux/m4/ax_jni_include_dir.m4 create mode 100644 sage/group_prover.sage create mode 100644 sage/secp256k1.sage create mode 100644 sage/weierstrass_prover.sage create mode 100644 src/asm/field_10x26_arm.s create mode 100644 src/java/org/bitcoin/NativeSecp256k1Test.java create mode 100644 src/java/org/bitcoin/NativeSecp256k1Util.java create mode 100644 src/java/org/bitcoin/Secp256k1Context.java create mode 100644 src/java/org_bitcoin_Secp256k1Context.c create mode 100644 src/java/org_bitcoin_Secp256k1Context.h diff --git a/.gitignore b/.gitignore index e0b7b7a48a31f..efb277d347065 100644 --- a/.gitignore +++ b/.gitignore @@ -25,17 +25,24 @@ config.status libtool .deps/ .dirstamp -build-aux/ *.lo *.o *~ src/libsecp256k1-config.h src/libsecp256k1-config.h.in src/ecmult_static_context.h -m4/libtool.m4 -m4/ltoptions.m4 -m4/ltsugar.m4 -m4/ltversion.m4 -m4/lt~obsolete.m4 +build-aux/config.guess +build-aux/config.sub +build-aux/depcomp +build-aux/install-sh +build-aux/ltmain.sh +build-aux/m4/libtool.m4 +build-aux/m4/lt~obsolete.m4 +build-aux/m4/ltoptions.m4 +build-aux/m4/ltsugar.m4 +build-aux/m4/ltversion.m4 +build-aux/missing +build-aux/compile +build-aux/test-driver src/stamp-h1 libsecp256k1.pc diff --git a/.travis.yml b/.travis.yml index 4e1e73c39f57b..2c5c63adadcb1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,26 +6,31 @@ addons: compiler: - clang - gcc +cache: + directories: + - src/java/guava/ env: global: - - FIELD=auto BIGNUM=auto SCALAR=auto ENDOMORPHISM=no STATICPRECOMPUTATION=yes ASM=no BUILD=check EXTRAFLAGS= HOST= ECDH=no schnorr=no RECOVERY=no + - FIELD=auto BIGNUM=auto SCALAR=auto ENDOMORPHISM=no STATICPRECOMPUTATION=yes ASM=no BUILD=check EXTRAFLAGS= HOST= ECDH=no schnorr=no RECOVERY=no EXPERIMENTAL=no + - GUAVA_URL=https://search.maven.org/remotecontent?filepath=com/google/guava/guava/18.0/guava-18.0.jar GUAVA_JAR=src/java/guava/guava-18.0.jar matrix: - SCALAR=32bit RECOVERY=yes - - SCALAR=32bit FIELD=32bit ECDH=yes + - SCALAR=32bit FIELD=32bit ECDH=yes EXPERIMENTAL=yes - SCALAR=64bit - FIELD=64bit RECOVERY=yes - FIELD=64bit ENDOMORPHISM=yes - - FIELD=64bit ENDOMORPHISM=yes ECDH=yes + - FIELD=64bit ENDOMORPHISM=yes ECDH=yes EXPERIMENTAL=yes - FIELD=64bit ASM=x86_64 - FIELD=64bit ENDOMORPHISM=yes ASM=x86_64 - - FIELD=32bit SCHNORR=yes + - FIELD=32bit SCHNORR=yes EXPERIMENTAL=yes - FIELD=32bit ENDOMORPHISM=yes - BIGNUM=no - - BIGNUM=no ENDOMORPHISM=yes SCHNORR=yes RECOVERY=yes + - BIGNUM=no ENDOMORPHISM=yes SCHNORR=yes RECOVERY=yes EXPERIMENTAL=yes - BIGNUM=no STATICPRECOMPUTATION=no - BUILD=distcheck - EXTRAFLAGS=CPPFLAGS=-DDETERMINISTIC - EXTRAFLAGS=CFLAGS=-O0 + - BUILD=check-java ECDH=yes SCHNORR=yes EXPERIMENTAL=yes matrix: fast_finish: true include: @@ -55,9 +60,11 @@ matrix: packages: - gcc-multilib - libgmp-dev:i386 +before_install: mkdir -p `dirname $GUAVA_JAR` +install: if [ ! -f $GUAVA_JAR ]; then wget $GUAVA_URL -O $GUAVA_JAR; fi before_script: ./autogen.sh script: - if [ -n "$HOST" ]; then export USE_HOST="--host=$HOST"; fi - if [ "x$HOST" = "xi686-linux-gnu" ]; then export CC="$CC -m32"; fi - - ./configure --enable-endomorphism=$ENDOMORPHISM --with-field=$FIELD --with-bignum=$BIGNUM --with-scalar=$SCALAR --enable-ecmult-static-precomputation=$STATICPRECOMPUTATION --enable-module-ecdh=$ECDH --enable-module-schnorr=$SCHNORR --enable-module-recovery=$RECOVERY $EXTRAFLAGS $USE_HOST && make -j2 $BUILD + - ./configure --enable-experimental=$EXPERIMENTAL --enable-endomorphism=$ENDOMORPHISM --with-field=$FIELD --with-bignum=$BIGNUM --with-scalar=$SCALAR --enable-ecmult-static-precomputation=$STATICPRECOMPUTATION --enable-module-ecdh=$ECDH --enable-module-schnorr=$SCHNORR --enable-module-recovery=$RECOVERY $EXTRAFLAGS $USE_HOST && make -j2 $BUILD os: linux diff --git a/Makefile.am b/Makefile.am index 7772a4e9d282c..3d130bdcbd717 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,12 @@ ACLOCAL_AMFLAGS = -I build-aux/m4 lib_LTLIBRARIES = libsecp256k1.la +if USE_JNI +JNI_LIB = libsecp256k1_jni.la +noinst_LTLIBRARIES = $(JNI_LIB) +else +JNI_LIB = +endif include_HEADERS = include/secp256k1.h noinst_HEADERS = noinst_HEADERS += src/scalar.h @@ -32,6 +38,7 @@ noinst_HEADERS += src/field_5x52_impl.h noinst_HEADERS += src/field_5x52_int128_impl.h noinst_HEADERS += src/field_5x52_asm_impl.h noinst_HEADERS += src/java/org_bitcoin_NativeSecp256k1.h +noinst_HEADERS += src/java/org_bitcoin_Secp256k1Context.h noinst_HEADERS += src/util.h noinst_HEADERS += src/testrand.h noinst_HEADERS += src/testrand_impl.h @@ -45,35 +52,80 @@ noinst_HEADERS += contrib/lax_der_parsing.c noinst_HEADERS += contrib/lax_der_privatekey_parsing.h noinst_HEADERS += contrib/lax_der_privatekey_parsing.c +if USE_EXTERNAL_ASM +COMMON_LIB = libsecp256k1_common.la +noinst_LTLIBRARIES = $(COMMON_LIB) +else +COMMON_LIB = +endif + pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libsecp256k1.pc +if USE_EXTERNAL_ASM +if USE_ASM_ARM +libsecp256k1_common_la_SOURCES = src/asm/field_10x26_arm.s +endif +endif + libsecp256k1_la_SOURCES = src/secp256k1.c -libsecp256k1_la_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/src $(SECP_INCLUDES) -libsecp256k1_la_LIBADD = $(SECP_LIBS) +libsecp256k1_la_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/include -I$(top_srcdir)/src $(SECP_INCLUDES) +libsecp256k1_la_LIBADD = $(JNI_LIB) $(SECP_LIBS) $(COMMON_LIB) +libsecp256k1_jni_la_SOURCES = src/java/org_bitcoin_NativeSecp256k1.c src/java/org_bitcoin_Secp256k1Context.c +libsecp256k1_jni_la_CPPFLAGS = -DSECP256K1_BUILD $(JNI_INCLUDES) noinst_PROGRAMS = if USE_BENCHMARK noinst_PROGRAMS += bench_verify bench_sign bench_internal bench_verify_SOURCES = src/bench_verify.c -bench_verify_LDADD = libsecp256k1.la $(SECP_LIBS) +bench_verify_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) bench_sign_SOURCES = src/bench_sign.c -bench_sign_LDADD = libsecp256k1.la $(SECP_LIBS) +bench_sign_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) bench_internal_SOURCES = src/bench_internal.c -bench_internal_LDADD = $(SECP_LIBS) -bench_internal_CPPFLAGS = $(SECP_INCLUDES) +bench_internal_LDADD = $(SECP_LIBS) $(COMMON_LIB) +bench_internal_CPPFLAGS = -DSECP256K1_BUILD $(SECP_INCLUDES) endif if USE_TESTS noinst_PROGRAMS += tests tests_SOURCES = src/tests.c -tests_CPPFLAGS = -DVERIFY -I$(top_srcdir)/src -I$(top_srcdir)/include $(SECP_INCLUDES) $(SECP_TEST_INCLUDES) -tests_LDADD = $(SECP_LIBS) $(SECP_TEST_LIBS) +tests_CPPFLAGS = -DSECP256K1_BUILD -DVERIFY -I$(top_srcdir)/src -I$(top_srcdir)/include $(SECP_INCLUDES) $(SECP_TEST_INCLUDES) +tests_LDADD = $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) tests_LDFLAGS = -static TESTS = tests endif +JAVAROOT=src/java +JAVAORG=org/bitcoin +JAVA_GUAVA=$(srcdir)/$(JAVAROOT)/guava/guava-18.0.jar +CLASSPATH_ENV=CLASSPATH=$(JAVA_GUAVA) +JAVA_FILES= \ + $(JAVAROOT)/$(JAVAORG)/NativeSecp256k1.java \ + $(JAVAROOT)/$(JAVAORG)/NativeSecp256k1Test.java \ + $(JAVAROOT)/$(JAVAORG)/NativeSecp256k1Util.java \ + $(JAVAROOT)/$(JAVAORG)/Secp256k1Context.java + +if USE_JNI + +$(JAVA_GUAVA): + @echo Guava is missing. Fetch it via: \ + wget https://search.maven.org/remotecontent?filepath=com/google/guava/guava/18.0/guava-18.0.jar -O $(@) + @false + +.stamp-java: $(JAVA_FILES) + @echo Compiling $^ + $(AM_V_at)$(CLASSPATH_ENV) javac $^ + @touch $@ + +if USE_TESTS + +check-java: libsecp256k1.la $(JAVA_GUAVA) .stamp-java + $(AM_V_at)java -Djava.library.path="./:./src:./src/.libs:.libs/" -cp "$(JAVA_GUAVA):$(JAVAROOT)" $(JAVAORG)/NativeSecp256k1Test + +endif +endif + if USE_ECMULT_STATIC_PRECOMPUTATION CPPFLAGS_FOR_BUILD +=-I$(top_srcdir) CFLAGS_FOR_BUILD += -Wall -Wextra -Wno-unused-function @@ -93,10 +145,10 @@ $(bench_internal_OBJECTS): src/ecmult_static_context.h src/ecmult_static_context.h: $(gen_context_BIN) ./$(gen_context_BIN) -CLEANFILES = $(gen_context_BIN) src/ecmult_static_context.h +CLEANFILES = $(gen_context_BIN) src/ecmult_static_context.h $(JAVAROOT)/$(JAVAORG)/*.class .stamp-java endif -EXTRA_DIST = autogen.sh src/gen_context.c src/basic-config.h +EXTRA_DIST = autogen.sh src/gen_context.c src/basic-config.h $(JAVA_FILES) if ENABLE_MODULE_ECDH include src/modules/ecdh/Makefile.am.include diff --git a/README.md b/README.md index 6095db42205be..8cd344ea81232 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ libsecp256k1 ============ -[![Build Status](https://travis-ci.org/bitcoin/secp256k1.svg?branch=master)](https://travis-ci.org/bitcoin/secp256k1) +[![Build Status](https://travis-ci.org/bitcoin-core/secp256k1.svg?branch=master)](https://travis-ci.org/bitcoin-core/secp256k1) Optimized C library for EC operations on curve secp256k1. diff --git a/build-aux/m4/ax_jni_include_dir.m4 b/build-aux/m4/ax_jni_include_dir.m4 new file mode 100644 index 0000000000000..1fc36276144a2 --- /dev/null +++ b/build-aux/m4/ax_jni_include_dir.m4 @@ -0,0 +1,140 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_jni_include_dir.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_JNI_INCLUDE_DIR +# +# DESCRIPTION +# +# AX_JNI_INCLUDE_DIR finds include directories needed for compiling +# programs using the JNI interface. +# +# JNI include directories are usually in the Java distribution. This is +# deduced from the value of $JAVA_HOME, $JAVAC, or the path to "javac", in +# that order. When this macro completes, a list of directories is left in +# the variable JNI_INCLUDE_DIRS. +# +# Example usage follows: +# +# AX_JNI_INCLUDE_DIR +# +# for JNI_INCLUDE_DIR in $JNI_INCLUDE_DIRS +# do +# CPPFLAGS="$CPPFLAGS -I$JNI_INCLUDE_DIR" +# done +# +# If you want to force a specific compiler: +# +# - at the configure.in level, set JAVAC=yourcompiler before calling +# AX_JNI_INCLUDE_DIR +# +# - at the configure level, setenv JAVAC +# +# Note: This macro can work with the autoconf M4 macros for Java programs. +# This particular macro is not part of the original set of macros. +# +# LICENSE +# +# Copyright (c) 2008 Don Anderson +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 10 + +AU_ALIAS([AC_JNI_INCLUDE_DIR], [AX_JNI_INCLUDE_DIR]) +AC_DEFUN([AX_JNI_INCLUDE_DIR],[ + +JNI_INCLUDE_DIRS="" + +if test "x$JAVA_HOME" != x; then + _JTOPDIR="$JAVA_HOME" +else + if test "x$JAVAC" = x; then + JAVAC=javac + fi + AC_PATH_PROG([_ACJNI_JAVAC], [$JAVAC], [no]) + if test "x$_ACJNI_JAVAC" = xno; then + AC_MSG_WARN([cannot find JDK; try setting \$JAVAC or \$JAVA_HOME]) + fi + _ACJNI_FOLLOW_SYMLINKS("$_ACJNI_JAVAC") + _JTOPDIR=`echo "$_ACJNI_FOLLOWED" | sed -e 's://*:/:g' -e 's:/[[^/]]*$::'` +fi + +case "$host_os" in + darwin*) _JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[[^/]]*$::'` + _JINC="$_JTOPDIR/Headers";; + *) _JINC="$_JTOPDIR/include";; +esac +_AS_ECHO_LOG([_JTOPDIR=$_JTOPDIR]) +_AS_ECHO_LOG([_JINC=$_JINC]) + +# On Mac OS X 10.6.4, jni.h is a symlink: +# /System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers/jni.h +# -> ../../CurrentJDK/Headers/jni.h. + +AC_CACHE_CHECK(jni headers, ac_cv_jni_header_path, +[ +if test -f "$_JINC/jni.h"; then + ac_cv_jni_header_path="$_JINC" + JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $ac_cv_jni_header_path" +else + _JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[[^/]]*$::'` + if test -f "$_JTOPDIR/include/jni.h"; then + ac_cv_jni_header_path="$_JTOPDIR/include" + JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $ac_cv_jni_header_path" + else + ac_cv_jni_header_path=none + fi +fi +]) + + + +# get the likely subdirectories for system specific java includes +case "$host_os" in +bsdi*) _JNI_INC_SUBDIRS="bsdos";; +darwin*) _JNI_INC_SUBDIRS="darwin";; +freebsd*) _JNI_INC_SUBDIRS="freebsd";; +linux*) _JNI_INC_SUBDIRS="linux genunix";; +osf*) _JNI_INC_SUBDIRS="alpha";; +solaris*) _JNI_INC_SUBDIRS="solaris";; +mingw*) _JNI_INC_SUBDIRS="win32";; +cygwin*) _JNI_INC_SUBDIRS="win32";; +*) _JNI_INC_SUBDIRS="genunix";; +esac + +if test "x$ac_cv_jni_header_path" != "xnone"; then + # add any subdirectories that are present + for JINCSUBDIR in $_JNI_INC_SUBDIRS + do + if test -d "$_JTOPDIR/include/$JINCSUBDIR"; then + JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $_JTOPDIR/include/$JINCSUBDIR" + fi + done +fi +]) + +# _ACJNI_FOLLOW_SYMLINKS +# Follows symbolic links on , +# finally setting variable _ACJNI_FOLLOWED +# ---------------------------------------- +AC_DEFUN([_ACJNI_FOLLOW_SYMLINKS],[ +# find the include directory relative to the javac executable +_cur="$1" +while ls -ld "$_cur" 2>/dev/null | grep " -> " >/dev/null; do + AC_MSG_CHECKING([symlink for $_cur]) + _slink=`ls -ld "$_cur" | sed 's/.* -> //'` + case "$_slink" in + /*) _cur="$_slink";; + # 'X' avoids triggering unwanted echo options. + *) _cur=`echo "X$_cur" | sed -e 's/^X//' -e 's:[[^/]]*$::'`"$_slink";; + esac + AC_MSG_RESULT([$_cur]) +done +_ACJNI_FOLLOWED="$_cur" +])# _ACJNI diff --git a/build-aux/m4/bitcoin_secp.m4 b/build-aux/m4/bitcoin_secp.m4 index d41bbb648708b..b25d8adb92c7f 100644 --- a/build-aux/m4/bitcoin_secp.m4 +++ b/build-aux/m4/bitcoin_secp.m4 @@ -3,13 +3,13 @@ AC_DEFUN([SECP_INT128_CHECK],[ has_int128=$ac_cv_type___int128 ]) -dnl +dnl escape "$0x" below using the m4 quadrigaph @S|@, and escape it again with a \ for the shell. AC_DEFUN([SECP_64BIT_ASM_CHECK],[ AC_MSG_CHECKING(for x86_64 assembly availability) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]],[[ uint64_t a = 11, tmp; - __asm__ __volatile__("movq $0x100000000,%1; mulq %%rsi" : "+a"(a) : "S"(tmp) : "cc", "%rdx"); + __asm__ __volatile__("movq \@S|@0x100000000,%1; mulq %%rsi" : "+a"(a) : "S"(tmp) : "cc", "%rdx"); ]])],[has_64bit_asm=yes],[has_64bit_asm=no]) AC_MSG_RESULT([$has_64bit_asm]) ]) diff --git a/configure.ac b/configure.ac index 786d8dcfb99ec..0743c36690c7a 100644 --- a/configure.ac +++ b/configure.ac @@ -29,6 +29,7 @@ AC_PROG_CC_C89 if test x"$ac_cv_prog_cc_c89" = x"no"; then AC_MSG_ERROR([c89 compiler support required]) fi +AM_PROG_AS case $host_os in *darwin*) @@ -93,23 +94,33 @@ AC_ARG_ENABLE(tests, [use_tests=$enableval], [use_tests=yes]) +AC_ARG_ENABLE(openssl_tests, + AS_HELP_STRING([--enable-openssl-tests],[enable OpenSSL tests, if OpenSSL is available (default is auto)]), + [enable_openssl_tests=$enableval], + [enable_openssl_tests=auto]) + +AC_ARG_ENABLE(experimental, + AS_HELP_STRING([--enable-experimental],[allow experimental configure options (default is no)]), + [use_experimental=$enableval], + [use_experimental=no]) + AC_ARG_ENABLE(endomorphism, AS_HELP_STRING([--enable-endomorphism],[enable endomorphism (default is no)]), [use_endomorphism=$enableval], [use_endomorphism=no]) - + AC_ARG_ENABLE(ecmult_static_precomputation, AS_HELP_STRING([--enable-ecmult-static-precomputation],[enable precomputed ecmult table for signing (default is yes)]), [use_ecmult_static_precomputation=$enableval], - [use_ecmult_static_precomputation=yes]) + [use_ecmult_static_precomputation=auto]) AC_ARG_ENABLE(module_ecdh, - AS_HELP_STRING([--enable-module-ecdh],[enable ECDH shared secret computation (default is no)]), + AS_HELP_STRING([--enable-module-ecdh],[enable ECDH shared secret computation (experimental)]), [enable_module_ecdh=$enableval], [enable_module_ecdh=no]) AC_ARG_ENABLE(module_schnorr, - AS_HELP_STRING([--enable-module-schnorr],[enable Schnorr signature module (default is no)]), + AS_HELP_STRING([--enable-module-schnorr],[enable Schnorr signature module (experimental)]), [enable_module_schnorr=$enableval], [enable_module_schnorr=no]) @@ -118,6 +129,11 @@ AC_ARG_ENABLE(module_recovery, [enable_module_recovery=$enableval], [enable_module_recovery=no]) +AC_ARG_ENABLE(jni, + AS_HELP_STRING([--enable-jni],[enable libsecp256k1_jni (default is auto)]), + [use_jni=$enableval], + [use_jni=auto]) + AC_ARG_WITH([field], [AS_HELP_STRING([--with-field=64bit|32bit|auto], [Specify Field Implementation. Default is auto])],[req_field=$withval], [req_field=auto]) @@ -127,8 +143,8 @@ AC_ARG_WITH([bignum], [AS_HELP_STRING([--with-bignum=gmp|no|auto], AC_ARG_WITH([scalar], [AS_HELP_STRING([--with-scalar=64bit|32bit|auto], [Specify scalar implementation. Default is auto])],[req_scalar=$withval], [req_scalar=auto]) -AC_ARG_WITH([asm], [AS_HELP_STRING([--with-asm=x86_64|no|auto] -[Specify assembly optimizations to use. Default is auto])],[req_asm=$withval], [req_asm=auto]) +AC_ARG_WITH([asm], [AS_HELP_STRING([--with-asm=x86_64|arm|no|auto] +[Specify assembly optimizations to use. Default is auto (experimental: arm)])],[req_asm=$withval], [req_asm=auto]) AC_CHECK_TYPES([__int128]) @@ -138,6 +154,34 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[void myfunc() {__builtin_expect(0,0);}]])], [ AC_MSG_RESULT([no]) ]) +if test x"$use_ecmult_static_precomputation" != x"no"; then + save_cross_compiling=$cross_compiling + cross_compiling=no + TEMP_CC="$CC" + CC="$CC_FOR_BUILD" + AC_MSG_CHECKING([native compiler: ${CC_FOR_BUILD}]) + AC_RUN_IFELSE( + [AC_LANG_PROGRAM([], [return 0])], + [working_native_cc=yes], + [working_native_cc=no],[dnl]) + CC="$TEMP_CC" + cross_compiling=$save_cross_compiling + + if test x"$working_native_cc" = x"no"; then + set_precomp=no + if test x"$use_ecmult_static_precomputation" = x"yes"; then + AC_MSG_ERROR([${CC_FOR_BUILD} does not produce working binaries. Please set CC_FOR_BUILD]) + else + AC_MSG_RESULT([${CC_FOR_BUILD} does not produce working binaries. Please set CC_FOR_BUILD]) + fi + else + AC_MSG_RESULT([ok]) + set_precomp=yes + fi +else + set_precomp=no +fi + if test x"$req_asm" = x"auto"; then SECP_64BIT_ASM_CHECK if test x"$has_64bit_asm" = x"yes"; then @@ -155,6 +199,8 @@ else AC_MSG_ERROR([x86_64 assembly optimization requested but not available]) fi ;; + arm) + ;; no) ;; *) @@ -247,10 +293,15 @@ else fi # select assembly optimization +use_external_asm=no + case $set_asm in x86_64) AC_DEFINE(USE_ASM_X86_64, 1, [Define this symbol to enable x86_64 assembly optimizations]) ;; +arm) + use_external_asm=yes + ;; no) ;; *) @@ -305,16 +356,51 @@ esac if test x"$use_tests" = x"yes"; then SECP_OPENSSL_CHECK if test x"$has_openssl_ec" = x"yes"; then - AC_DEFINE(ENABLE_OPENSSL_TESTS, 1, [Define this symbol if OpenSSL EC functions are available]) - SECP_TEST_INCLUDES="$SSL_CFLAGS $CRYPTO_CFLAGS" - SECP_TEST_LIBS="$CRYPTO_LIBS" - - case $host in - *mingw*) - SECP_TEST_LIBS="$SECP_TEST_LIBS -lgdi32" - ;; - esac + if test x"$enable_openssl_tests" != x"no"; then + AC_DEFINE(ENABLE_OPENSSL_TESTS, 1, [Define this symbol if OpenSSL EC functions are available]) + SECP_TEST_INCLUDES="$SSL_CFLAGS $CRYPTO_CFLAGS" + SECP_TEST_LIBS="$CRYPTO_LIBS" + + case $host in + *mingw*) + SECP_TEST_LIBS="$SECP_TEST_LIBS -lgdi32" + ;; + esac + fi + else + if test x"$enable_openssl_tests" = x"yes"; then + AC_MSG_ERROR([OpenSSL tests requested but OpenSSL with EC support is not available]) + fi + fi +else + if test x"$enable_openssl_tests" = x"yes"; then + AC_MSG_ERROR([OpenSSL tests requested but tests are not enabled]) + fi +fi +if test x"$use_jni" != x"no"; then + AX_JNI_INCLUDE_DIR + have_jni_dependencies=yes + if test x"$enable_module_schnorr" = x"no"; then + have_jni_dependencies=no + fi + if test x"$enable_module_ecdh" = x"no"; then + have_jni_dependencies=no + fi + if test "x$JNI_INCLUDE_DIRS" = "x"; then + have_jni_dependencies=no + fi + if test "x$have_jni_dependencies" = "xno"; then + if test x"$use_jni" = x"yes"; then + AC_MSG_ERROR([jni support explicitly requested but headers/dependencies were not found. Enable ECDH and Schnorr and try again.]) + fi + AC_MSG_WARN([jni headers/dependencies not found. jni support disabled]) + use_jni=no + else + use_jni=yes + for JNI_INCLUDE_DIR in $JNI_INCLUDE_DIRS; do + JNI_INCLUDES="$JNI_INCLUDES -I$JNI_INCLUDE_DIR" + done fi fi @@ -345,18 +431,43 @@ fi AC_C_BIGENDIAN() +if test x"$use_external_asm" = x"yes"; then + AC_DEFINE(USE_EXTERNAL_ASM, 1, [Define this symbol if an external (non-inline) assembly implementation is used]) +fi + +AC_MSG_NOTICE([Using static precomputation: $set_precomp]) AC_MSG_NOTICE([Using assembly optimizations: $set_asm]) AC_MSG_NOTICE([Using field implementation: $set_field]) AC_MSG_NOTICE([Using bignum implementation: $set_bignum]) AC_MSG_NOTICE([Using scalar implementation: $set_scalar]) AC_MSG_NOTICE([Using endomorphism optimizations: $use_endomorphism]) AC_MSG_NOTICE([Building ECDH module: $enable_module_ecdh]) - AC_MSG_NOTICE([Building Schnorr signatures module: $enable_module_schnorr]) AC_MSG_NOTICE([Building ECDSA pubkey recovery module: $enable_module_recovery]) +AC_MSG_NOTICE([Using jni: $use_jni]) + +if test x"$enable_experimental" = x"yes"; then + AC_MSG_NOTICE([******]) + AC_MSG_NOTICE([WARNING: experimental build]) + AC_MSG_NOTICE([Experimental features do not have stable APIs or properties, and may not be safe for production use.]) + AC_MSG_NOTICE([Building ECDH module: $enable_module_ecdh]) + AC_MSG_NOTICE([Building Schnorr signatures module: $enable_module_schnorr]) + AC_MSG_NOTICE([******]) +else + if test x"$enable_module_schnorr" = x"yes"; then + AC_MSG_ERROR([Schnorr signature module is experimental. Use --enable-experimental to allow.]) + fi + if test x"$enable_module_ecdh" = x"yes"; then + AC_MSG_ERROR([ECDH module is experimental. Use --enable-experimental to allow.]) + fi + if test x"$set_asm" = x"arm"; then + AC_MSG_ERROR([ARM assembly optimization is experimental. Use --enable-experimental to allow.]) + fi +fi AC_CONFIG_HEADERS([src/libsecp256k1-config.h]) AC_CONFIG_FILES([Makefile libsecp256k1.pc]) +AC_SUBST(JNI_INCLUDES) AC_SUBST(SECP_INCLUDES) AC_SUBST(SECP_LIBS) AC_SUBST(SECP_TEST_LIBS) @@ -367,6 +478,9 @@ AM_CONDITIONAL([USE_ECMULT_STATIC_PRECOMPUTATION], [test x"$use_ecmult_static_pr AM_CONDITIONAL([ENABLE_MODULE_ECDH], [test x"$enable_module_ecdh" = x"yes"]) AM_CONDITIONAL([ENABLE_MODULE_SCHNORR], [test x"$enable_module_schnorr" = x"yes"]) AM_CONDITIONAL([ENABLE_MODULE_RECOVERY], [test x"$enable_module_recovery" = x"yes"]) +AM_CONDITIONAL([USE_JNI], [test x"$use_jni" == x"yes"]) +AM_CONDITIONAL([USE_EXTERNAL_ASM], [test x"$use_external_asm" = x"yes"]) +AM_CONDITIONAL([USE_ASM_ARM], [test x"$set_asm" = x"arm"]) dnl make sure nothing new is exported so that we don't break the cache PKGCONFIG_PATH_TEMP="$PKG_CONFIG_PATH" diff --git a/libsecp256k1.pc.in b/libsecp256k1.pc.in index 1c72dd00037b5..a0d006f1131f4 100644 --- a/libsecp256k1.pc.in +++ b/libsecp256k1.pc.in @@ -5,7 +5,7 @@ includedir=@includedir@ Name: libsecp256k1 Description: Optimized C library for EC operations on curve secp256k1 -URL: https://github.com/bitcoin/secp256k1 +URL: https://github.com/bitcoin-core/secp256k1 Version: @PACKAGE_VERSION@ Cflags: -I${includedir} Libs.private: @SECP_LIBS@ diff --git a/sage/group_prover.sage b/sage/group_prover.sage new file mode 100644 index 0000000000000..ab580c5b23bbf --- /dev/null +++ b/sage/group_prover.sage @@ -0,0 +1,322 @@ +# This code supports verifying group implementations which have branches +# or conditional statements (like cmovs), by allowing each execution path +# to independently set assumptions on input or intermediary variables. +# +# The general approach is: +# * A constraint is a tuple of two sets of of symbolic expressions: +# the first of which are required to evaluate to zero, the second of which +# are required to evaluate to nonzero. +# - A constraint is said to be conflicting if any of its nonzero expressions +# is in the ideal with basis the zero expressions (in other words: when the +# zero expressions imply that one of the nonzero expressions are zero). +# * There is a list of laws that describe the intended behaviour, including +# laws for addition and doubling. Each law is called with the symbolic point +# coordinates as arguments, and returns: +# - A constraint describing the assumptions under which it is applicable, +# called "assumeLaw" +# - A constraint describing the requirements of the law, called "require" +# * Implementations are transliterated into functions that operate as well on +# algebraic input points, and are called once per combination of branches +# exectured. Each execution returns: +# - A constraint describing the assumptions this implementation requires +# (such as Z1=1), called "assumeFormula" +# - A constraint describing the assumptions this specific branch requires, +# but which is by construction guaranteed to cover the entire space by +# merging the results from all branches, called "assumeBranch" +# - The result of the computation +# * All combinations of laws with implementation branches are tried, and: +# - If the combination of assumeLaw, assumeFormula, and assumeBranch results +# in a conflict, it means this law does not apply to this branch, and it is +# skipped. +# - For others, we try to prove the require constraints hold, assuming the +# information in assumeLaw + assumeFormula + assumeBranch, and if this does +# not succeed, we fail. +# + To prove an expression is zero, we check whether it belongs to the +# ideal with the assumed zero expressions as basis. This test is exact. +# + To prove an expression is nonzero, we check whether each of its +# factors is contained in the set of nonzero assumptions' factors. +# This test is not exact, so various combinations of original and +# reduced expressions' factors are tried. +# - If we succeed, we print out the assumptions from assumeFormula that +# weren't implied by assumeLaw already. Those from assumeBranch are skipped, +# as we assume that all constraints in it are complementary with each other. +# +# Based on the sage verification scripts used in the Explicit-Formulas Database +# by Tanja Lange and others, see http://hyperelliptic.org/EFD + +class fastfrac: + """Fractions over rings.""" + + def __init__(self,R,top,bot=1): + """Construct a fractional, given a ring, a numerator, and denominator.""" + self.R = R + if parent(top) == ZZ or parent(top) == R: + self.top = R(top) + self.bot = R(bot) + elif top.__class__ == fastfrac: + self.top = top.top + self.bot = top.bot * bot + else: + self.top = R(numerator(top)) + self.bot = R(denominator(top)) * bot + + def iszero(self,I): + """Return whether this fraction is zero given an ideal.""" + return self.top in I and self.bot not in I + + def reduce(self,assumeZero): + zero = self.R.ideal(map(numerator, assumeZero)) + return fastfrac(self.R, zero.reduce(self.top)) / fastfrac(self.R, zero.reduce(self.bot)) + + def __add__(self,other): + """Add two fractions.""" + if parent(other) == ZZ: + return fastfrac(self.R,self.top + self.bot * other,self.bot) + if other.__class__ == fastfrac: + return fastfrac(self.R,self.top * other.bot + self.bot * other.top,self.bot * other.bot) + return NotImplemented + + def __sub__(self,other): + """Subtract two fractions.""" + if parent(other) == ZZ: + return fastfrac(self.R,self.top - self.bot * other,self.bot) + if other.__class__ == fastfrac: + return fastfrac(self.R,self.top * other.bot - self.bot * other.top,self.bot * other.bot) + return NotImplemented + + def __neg__(self): + """Return the negation of a fraction.""" + return fastfrac(self.R,-self.top,self.bot) + + def __mul__(self,other): + """Multiply two fractions.""" + if parent(other) == ZZ: + return fastfrac(self.R,self.top * other,self.bot) + if other.__class__ == fastfrac: + return fastfrac(self.R,self.top * other.top,self.bot * other.bot) + return NotImplemented + + def __rmul__(self,other): + """Multiply something else with a fraction.""" + return self.__mul__(other) + + def __div__(self,other): + """Divide two fractions.""" + if parent(other) == ZZ: + return fastfrac(self.R,self.top,self.bot * other) + if other.__class__ == fastfrac: + return fastfrac(self.R,self.top * other.bot,self.bot * other.top) + return NotImplemented + + def __pow__(self,other): + """Compute a power of a fraction.""" + if parent(other) == ZZ: + if other < 0: + # Negative powers require flipping top and bottom + return fastfrac(self.R,self.bot ^ (-other),self.top ^ (-other)) + else: + return fastfrac(self.R,self.top ^ other,self.bot ^ other) + return NotImplemented + + def __str__(self): + return "fastfrac((" + str(self.top) + ") / (" + str(self.bot) + "))" + def __repr__(self): + return "%s" % self + + def numerator(self): + return self.top + +class constraints: + """A set of constraints, consisting of zero and nonzero expressions. + + Constraints can either be used to express knowledge or a requirement. + + Both the fields zero and nonzero are maps from expressions to description + strings. The expressions that are the keys in zero are required to be zero, + and the expressions that are the keys in nonzero are required to be nonzero. + + Note that (a != 0) and (b != 0) is the same as (a*b != 0), so all keys in + nonzero could be multiplied into a single key. This is often much less + efficient to work with though, so we keep them separate inside the + constraints. This allows higher-level code to do fast checks on the individual + nonzero elements, or combine them if needed for stronger checks. + + We can't multiply the different zero elements, as it would suffice for one of + the factors to be zero, instead of all of them. Instead, the zero elements are + typically combined into an ideal first. + """ + + def __init__(self, **kwargs): + if 'zero' in kwargs: + self.zero = dict(kwargs['zero']) + else: + self.zero = dict() + if 'nonzero' in kwargs: + self.nonzero = dict(kwargs['nonzero']) + else: + self.nonzero = dict() + + def negate(self): + return constraints(zero=self.nonzero, nonzero=self.zero) + + def __add__(self, other): + zero = self.zero.copy() + zero.update(other.zero) + nonzero = self.nonzero.copy() + nonzero.update(other.nonzero) + return constraints(zero=zero, nonzero=nonzero) + + def __str__(self): + return "constraints(zero=%s,nonzero=%s)" % (self.zero, self.nonzero) + + def __repr__(self): + return "%s" % self + + +def conflicts(R, con): + """Check whether any of the passed non-zero assumptions is implied by the zero assumptions""" + zero = R.ideal(map(numerator, con.zero)) + if 1 in zero: + return True + # First a cheap check whether any of the individual nonzero terms conflict on + # their own. + for nonzero in con.nonzero: + if nonzero.iszero(zero): + return True + # It can be the case that entries in the nonzero set do not individually + # conflict with the zero set, but their combination does. For example, knowing + # that either x or y is zero is equivalent to having x*y in the zero set. + # Having x or y individually in the nonzero set is not a conflict, but both + # simultaneously is, so that is the right thing to check for. + if reduce(lambda a,b: a * b, con.nonzero, fastfrac(R, 1)).iszero(zero): + return True + return False + + +def get_nonzero_set(R, assume): + """Calculate a simple set of nonzero expressions""" + zero = R.ideal(map(numerator, assume.zero)) + nonzero = set() + for nz in map(numerator, assume.nonzero): + for (f,n) in nz.factor(): + nonzero.add(f) + rnz = zero.reduce(nz) + for (f,n) in rnz.factor(): + nonzero.add(f) + return nonzero + + +def prove_nonzero(R, exprs, assume): + """Check whether an expression is provably nonzero, given assumptions""" + zero = R.ideal(map(numerator, assume.zero)) + nonzero = get_nonzero_set(R, assume) + expl = set() + ok = True + for expr in exprs: + if numerator(expr) in zero: + return (False, [exprs[expr]]) + allexprs = reduce(lambda a,b: numerator(a)*numerator(b), exprs, 1) + for (f, n) in allexprs.factor(): + if f not in nonzero: + ok = False + if ok: + return (True, None) + ok = True + for (f, n) in zero.reduce(numerator(allexprs)).factor(): + if f not in nonzero: + ok = False + if ok: + return (True, None) + ok = True + for expr in exprs: + for (f,n) in numerator(expr).factor(): + if f not in nonzero: + ok = False + if ok: + return (True, None) + ok = True + for expr in exprs: + for (f,n) in zero.reduce(numerator(expr)).factor(): + if f not in nonzero: + expl.add(exprs[expr]) + if expl: + return (False, list(expl)) + else: + return (True, None) + + +def prove_zero(R, exprs, assume): + """Check whether all of the passed expressions are provably zero, given assumptions""" + r, e = prove_nonzero(R, dict(map(lambda x: (fastfrac(R, x.bot, 1), exprs[x]), exprs)), assume) + if not r: + return (False, map(lambda x: "Possibly zero denominator: %s" % x, e)) + zero = R.ideal(map(numerator, assume.zero)) + nonzero = prod(x for x in assume.nonzero) + expl = [] + for expr in exprs: + if not expr.iszero(zero): + expl.append(exprs[expr]) + if not expl: + return (True, None) + return (False, expl) + + +def describe_extra(R, assume, assumeExtra): + """Describe what assumptions are added, given existing assumptions""" + zerox = assume.zero.copy() + zerox.update(assumeExtra.zero) + zero = R.ideal(map(numerator, assume.zero)) + zeroextra = R.ideal(map(numerator, zerox)) + nonzero = get_nonzero_set(R, assume) + ret = set() + # Iterate over the extra zero expressions + for base in assumeExtra.zero: + if base not in zero: + add = [] + for (f, n) in numerator(base).factor(): + if f not in nonzero: + add += ["%s" % f] + if add: + ret.add((" * ".join(add)) + " = 0 [%s]" % assumeExtra.zero[base]) + # Iterate over the extra nonzero expressions + for nz in assumeExtra.nonzero: + nzr = zeroextra.reduce(numerator(nz)) + if nzr not in zeroextra: + for (f,n) in nzr.factor(): + if zeroextra.reduce(f) not in nonzero: + ret.add("%s != 0" % zeroextra.reduce(f)) + return ", ".join(x for x in ret) + + +def check_symbolic(R, assumeLaw, assumeAssert, assumeBranch, require): + """Check a set of zero and nonzero requirements, given a set of zero and nonzero assumptions""" + assume = assumeLaw + assumeAssert + assumeBranch + + if conflicts(R, assume): + # This formula does not apply + return None + + describe = describe_extra(R, assumeLaw + assumeBranch, assumeAssert) + + ok, msg = prove_zero(R, require.zero, assume) + if not ok: + return "FAIL, %s fails (assuming %s)" % (str(msg), describe) + + res, expl = prove_nonzero(R, require.nonzero, assume) + if not res: + return "FAIL, %s fails (assuming %s)" % (str(expl), describe) + + if describe != "": + return "OK (assuming %s)" % describe + else: + return "OK" + + +def concrete_verify(c): + for k in c.zero: + if k != 0: + return (False, c.zero[k]) + for k in c.nonzero: + if k == 0: + return (False, c.nonzero[k]) + return (True, None) diff --git a/sage/secp256k1.sage b/sage/secp256k1.sage new file mode 100644 index 0000000000000..a97e732f7fa3a --- /dev/null +++ b/sage/secp256k1.sage @@ -0,0 +1,306 @@ +# Test libsecp256k1' group operation implementations using prover.sage + +import sys + +load("group_prover.sage") +load("weierstrass_prover.sage") + +def formula_secp256k1_gej_double_var(a): + """libsecp256k1's secp256k1_gej_double_var, used by various addition functions""" + rz = a.Z * a.Y + rz = rz * 2 + t1 = a.X^2 + t1 = t1 * 3 + t2 = t1^2 + t3 = a.Y^2 + t3 = t3 * 2 + t4 = t3^2 + t4 = t4 * 2 + t3 = t3 * a.X + rx = t3 + rx = rx * 4 + rx = -rx + rx = rx + t2 + t2 = -t2 + t3 = t3 * 6 + t3 = t3 + t2 + ry = t1 * t3 + t2 = -t4 + ry = ry + t2 + return jacobianpoint(rx, ry, rz) + +def formula_secp256k1_gej_add_var(branch, a, b): + """libsecp256k1's secp256k1_gej_add_var""" + if branch == 0: + return (constraints(), constraints(nonzero={a.Infinity : 'a_infinite'}), b) + if branch == 1: + return (constraints(), constraints(zero={a.Infinity : 'a_finite'}, nonzero={b.Infinity : 'b_infinite'}), a) + z22 = b.Z^2 + z12 = a.Z^2 + u1 = a.X * z22 + u2 = b.X * z12 + s1 = a.Y * z22 + s1 = s1 * b.Z + s2 = b.Y * z12 + s2 = s2 * a.Z + h = -u1 + h = h + u2 + i = -s1 + i = i + s2 + if branch == 2: + r = formula_secp256k1_gej_double_var(a) + return (constraints(), constraints(zero={h : 'h=0', i : 'i=0', a.Infinity : 'a_finite', b.Infinity : 'b_finite'}), r) + if branch == 3: + return (constraints(), constraints(zero={h : 'h=0', a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={i : 'i!=0'}), point_at_infinity()) + i2 = i^2 + h2 = h^2 + h3 = h2 * h + h = h * b.Z + rz = a.Z * h + t = u1 * h2 + rx = t + rx = rx * 2 + rx = rx + h3 + rx = -rx + rx = rx + i2 + ry = -rx + ry = ry + t + ry = ry * i + h3 = h3 * s1 + h3 = -h3 + ry = ry + h3 + return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={h : 'h!=0'}), jacobianpoint(rx, ry, rz)) + +def formula_secp256k1_gej_add_ge_var(branch, a, b): + """libsecp256k1's secp256k1_gej_add_ge_var, which assume bz==1""" + if branch == 0: + return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(nonzero={a.Infinity : 'a_infinite'}), b) + if branch == 1: + return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite'}, nonzero={b.Infinity : 'b_infinite'}), a) + z12 = a.Z^2 + u1 = a.X + u2 = b.X * z12 + s1 = a.Y + s2 = b.Y * z12 + s2 = s2 * a.Z + h = -u1 + h = h + u2 + i = -s1 + i = i + s2 + if (branch == 2): + r = formula_secp256k1_gej_double_var(a) + return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0', i : 'i=0'}), r) + if (branch == 3): + return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0'}, nonzero={i : 'i!=0'}), point_at_infinity()) + i2 = i^2 + h2 = h^2 + h3 = h * h2 + rz = a.Z * h + t = u1 * h2 + rx = t + rx = rx * 2 + rx = rx + h3 + rx = -rx + rx = rx + i2 + ry = -rx + ry = ry + t + ry = ry * i + h3 = h3 * s1 + h3 = -h3 + ry = ry + h3 + return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={h : 'h!=0'}), jacobianpoint(rx, ry, rz)) + +def formula_secp256k1_gej_add_zinv_var(branch, a, b): + """libsecp256k1's secp256k1_gej_add_zinv_var""" + bzinv = b.Z^(-1) + if branch == 0: + return (constraints(), constraints(nonzero={b.Infinity : 'b_infinite'}), a) + if branch == 1: + bzinv2 = bzinv^2 + bzinv3 = bzinv2 * bzinv + rx = b.X * bzinv2 + ry = b.Y * bzinv3 + rz = 1 + return (constraints(), constraints(zero={b.Infinity : 'b_finite'}, nonzero={a.Infinity : 'a_infinite'}), jacobianpoint(rx, ry, rz)) + azz = a.Z * bzinv + z12 = azz^2 + u1 = a.X + u2 = b.X * z12 + s1 = a.Y + s2 = b.Y * z12 + s2 = s2 * azz + h = -u1 + h = h + u2 + i = -s1 + i = i + s2 + if branch == 2: + r = formula_secp256k1_gej_double_var(a) + return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0', i : 'i=0'}), r) + if branch == 3: + return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0'}, nonzero={i : 'i!=0'}), point_at_infinity()) + i2 = i^2 + h2 = h^2 + h3 = h * h2 + rz = a.Z + rz = rz * h + t = u1 * h2 + rx = t + rx = rx * 2 + rx = rx + h3 + rx = -rx + rx = rx + i2 + ry = -rx + ry = ry + t + ry = ry * i + h3 = h3 * s1 + h3 = -h3 + ry = ry + h3 + return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={h : 'h!=0'}), jacobianpoint(rx, ry, rz)) + +def formula_secp256k1_gej_add_ge(branch, a, b): + """libsecp256k1's secp256k1_gej_add_ge""" + zeroes = {} + nonzeroes = {} + a_infinity = False + if (branch & 4) != 0: + nonzeroes.update({a.Infinity : 'a_infinite'}) + a_infinity = True + else: + zeroes.update({a.Infinity : 'a_finite'}) + zz = a.Z^2 + u1 = a.X + u2 = b.X * zz + s1 = a.Y + s2 = b.Y * zz + s2 = s2 * a.Z + t = u1 + t = t + u2 + m = s1 + m = m + s2 + rr = t^2 + m_alt = -u2 + tt = u1 * m_alt + rr = rr + tt + degenerate = (branch & 3) == 3 + if (branch & 1) != 0: + zeroes.update({m : 'm_zero'}) + else: + nonzeroes.update({m : 'm_nonzero'}) + if (branch & 2) != 0: + zeroes.update({rr : 'rr_zero'}) + else: + nonzeroes.update({rr : 'rr_nonzero'}) + rr_alt = s1 + rr_alt = rr_alt * 2 + m_alt = m_alt + u1 + if not degenerate: + rr_alt = rr + m_alt = m + n = m_alt^2 + q = n * t + n = n^2 + if degenerate: + n = m + t = rr_alt^2 + rz = a.Z * m_alt + infinity = False + if (branch & 8) != 0: + if not a_infinity: + infinity = True + zeroes.update({rz : 'r.z=0'}) + else: + nonzeroes.update({rz : 'r.z!=0'}) + rz = rz * 2 + q = -q + t = t + q + rx = t + t = t * 2 + t = t + q + t = t * rr_alt + t = t + n + ry = -t + rx = rx * 4 + ry = ry * 4 + if a_infinity: + rx = b.X + ry = b.Y + rz = 1 + if infinity: + return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zeroes, nonzero=nonzeroes), point_at_infinity()) + return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zeroes, nonzero=nonzeroes), jacobianpoint(rx, ry, rz)) + +def formula_secp256k1_gej_add_ge_old(branch, a, b): + """libsecp256k1's old secp256k1_gej_add_ge, which fails when ay+by=0 but ax!=bx""" + a_infinity = (branch & 1) != 0 + zero = {} + nonzero = {} + if a_infinity: + nonzero.update({a.Infinity : 'a_infinite'}) + else: + zero.update({a.Infinity : 'a_finite'}) + zz = a.Z^2 + u1 = a.X + u2 = b.X * zz + s1 = a.Y + s2 = b.Y * zz + s2 = s2 * a.Z + z = a.Z + t = u1 + t = t + u2 + m = s1 + m = m + s2 + n = m^2 + q = n * t + n = n^2 + rr = t^2 + t = u1 * u2 + t = -t + rr = rr + t + t = rr^2 + rz = m * z + infinity = False + if (branch & 2) != 0: + if not a_infinity: + infinity = True + else: + return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(nonzero={z : 'conflict_a'}, zero={z : 'conflict_b'}), point_at_infinity()) + zero.update({rz : 'r.z=0'}) + else: + nonzero.update({rz : 'r.z!=0'}) + rz = rz * (0 if a_infinity else 2) + rx = t + q = -q + rx = rx + q + q = q * 3 + t = t * 2 + t = t + q + t = t * rr + t = t + n + ry = -t + rx = rx * (0 if a_infinity else 4) + ry = ry * (0 if a_infinity else 4) + t = b.X + t = t * (1 if a_infinity else 0) + rx = rx + t + t = b.Y + t = t * (1 if a_infinity else 0) + ry = ry + t + t = (1 if a_infinity else 0) + rz = rz + t + if infinity: + return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zero, nonzero=nonzero), point_at_infinity()) + return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zero, nonzero=nonzero), jacobianpoint(rx, ry, rz)) + +if __name__ == "__main__": + check_symbolic_jacobian_weierstrass("secp256k1_gej_add_var", 0, 7, 5, formula_secp256k1_gej_add_var) + check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge_var", 0, 7, 5, formula_secp256k1_gej_add_ge_var) + check_symbolic_jacobian_weierstrass("secp256k1_gej_add_zinv_var", 0, 7, 5, formula_secp256k1_gej_add_zinv_var) + check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge", 0, 7, 16, formula_secp256k1_gej_add_ge) + check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge_old [should fail]", 0, 7, 4, formula_secp256k1_gej_add_ge_old) + + if len(sys.argv) >= 2 and sys.argv[1] == "--exhaustive": + check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_var", 0, 7, 5, formula_secp256k1_gej_add_var, 43) + check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge_var", 0, 7, 5, formula_secp256k1_gej_add_ge_var, 43) + check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_zinv_var", 0, 7, 5, formula_secp256k1_gej_add_zinv_var, 43) + check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge", 0, 7, 16, formula_secp256k1_gej_add_ge, 43) + check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge_old [should fail]", 0, 7, 4, formula_secp256k1_gej_add_ge_old, 43) diff --git a/sage/weierstrass_prover.sage b/sage/weierstrass_prover.sage new file mode 100644 index 0000000000000..03ef2ec901ea9 --- /dev/null +++ b/sage/weierstrass_prover.sage @@ -0,0 +1,264 @@ +# Prover implementation for Weierstrass curves of the form +# y^2 = x^3 + A * x + B, specifically with a = 0 and b = 7, with group laws +# operating on affine and Jacobian coordinates, including the point at infinity +# represented by a 4th variable in coordinates. + +load("group_prover.sage") + + +class affinepoint: + def __init__(self, x, y, infinity=0): + self.x = x + self.y = y + self.infinity = infinity + def __str__(self): + return "affinepoint(x=%s,y=%s,inf=%s)" % (self.x, self.y, self.infinity) + + +class jacobianpoint: + def __init__(self, x, y, z, infinity=0): + self.X = x + self.Y = y + self.Z = z + self.Infinity = infinity + def __str__(self): + return "jacobianpoint(X=%s,Y=%s,Z=%s,inf=%s)" % (self.X, self.Y, self.Z, self.Infinity) + + +def point_at_infinity(): + return jacobianpoint(1, 1, 1, 1) + + +def negate(p): + if p.__class__ == affinepoint: + return affinepoint(p.x, -p.y) + if p.__class__ == jacobianpoint: + return jacobianpoint(p.X, -p.Y, p.Z) + assert(False) + + +def on_weierstrass_curve(A, B, p): + """Return a set of zero-expressions for an affine point to be on the curve""" + return constraints(zero={p.x^3 + A*p.x + B - p.y^2: 'on_curve'}) + + +def tangential_to_weierstrass_curve(A, B, p12, p3): + """Return a set of zero-expressions for ((x12,y12),(x3,y3)) to be a line that is tangential to the curve at (x12,y12)""" + return constraints(zero={ + (p12.y - p3.y) * (p12.y * 2) - (p12.x^2 * 3 + A) * (p12.x - p3.x): 'tangential_to_curve' + }) + + +def colinear(p1, p2, p3): + """Return a set of zero-expressions for ((x1,y1),(x2,y2),(x3,y3)) to be collinear""" + return constraints(zero={ + (p1.y - p2.y) * (p1.x - p3.x) - (p1.y - p3.y) * (p1.x - p2.x): 'colinear_1', + (p2.y - p3.y) * (p2.x - p1.x) - (p2.y - p1.y) * (p2.x - p3.x): 'colinear_2', + (p3.y - p1.y) * (p3.x - p2.x) - (p3.y - p2.y) * (p3.x - p1.x): 'colinear_3' + }) + + +def good_affine_point(p): + return constraints(nonzero={p.x : 'nonzero_x', p.y : 'nonzero_y'}) + + +def good_jacobian_point(p): + return constraints(nonzero={p.X : 'nonzero_X', p.Y : 'nonzero_Y', p.Z^6 : 'nonzero_Z'}) + + +def good_point(p): + return constraints(nonzero={p.Z^6 : 'nonzero_X'}) + + +def finite(p, *affine_fns): + con = good_point(p) + constraints(zero={p.Infinity : 'finite_point'}) + if p.Z != 0: + return con + reduce(lambda a, b: a + b, (f(affinepoint(p.X / p.Z^2, p.Y / p.Z^3)) for f in affine_fns), con) + else: + return con + +def infinite(p): + return constraints(nonzero={p.Infinity : 'infinite_point'}) + + +def law_jacobian_weierstrass_add(A, B, pa, pb, pA, pB, pC): + """Check whether the passed set of coordinates is a valid Jacobian add, given assumptions""" + assumeLaw = (good_affine_point(pa) + + good_affine_point(pb) + + good_jacobian_point(pA) + + good_jacobian_point(pB) + + on_weierstrass_curve(A, B, pa) + + on_weierstrass_curve(A, B, pb) + + finite(pA) + + finite(pB) + + constraints(nonzero={pa.x - pb.x : 'different_x'})) + require = (finite(pC, lambda pc: on_weierstrass_curve(A, B, pc) + + colinear(pa, pb, negate(pc)))) + return (assumeLaw, require) + + +def law_jacobian_weierstrass_double(A, B, pa, pb, pA, pB, pC): + """Check whether the passed set of coordinates is a valid Jacobian doubling, given assumptions""" + assumeLaw = (good_affine_point(pa) + + good_affine_point(pb) + + good_jacobian_point(pA) + + good_jacobian_point(pB) + + on_weierstrass_curve(A, B, pa) + + on_weierstrass_curve(A, B, pb) + + finite(pA) + + finite(pB) + + constraints(zero={pa.x - pb.x : 'equal_x', pa.y - pb.y : 'equal_y'})) + require = (finite(pC, lambda pc: on_weierstrass_curve(A, B, pc) + + tangential_to_weierstrass_curve(A, B, pa, negate(pc)))) + return (assumeLaw, require) + + +def law_jacobian_weierstrass_add_opposites(A, B, pa, pb, pA, pB, pC): + assumeLaw = (good_affine_point(pa) + + good_affine_point(pb) + + good_jacobian_point(pA) + + good_jacobian_point(pB) + + on_weierstrass_curve(A, B, pa) + + on_weierstrass_curve(A, B, pb) + + finite(pA) + + finite(pB) + + constraints(zero={pa.x - pb.x : 'equal_x', pa.y + pb.y : 'opposite_y'})) + require = infinite(pC) + return (assumeLaw, require) + + +def law_jacobian_weierstrass_add_infinite_a(A, B, pa, pb, pA, pB, pC): + assumeLaw = (good_affine_point(pa) + + good_affine_point(pb) + + good_jacobian_point(pA) + + good_jacobian_point(pB) + + on_weierstrass_curve(A, B, pb) + + infinite(pA) + + finite(pB)) + require = finite(pC, lambda pc: constraints(zero={pc.x - pb.x : 'c.x=b.x', pc.y - pb.y : 'c.y=b.y'})) + return (assumeLaw, require) + + +def law_jacobian_weierstrass_add_infinite_b(A, B, pa, pb, pA, pB, pC): + assumeLaw = (good_affine_point(pa) + + good_affine_point(pb) + + good_jacobian_point(pA) + + good_jacobian_point(pB) + + on_weierstrass_curve(A, B, pa) + + infinite(pB) + + finite(pA)) + require = finite(pC, lambda pc: constraints(zero={pc.x - pa.x : 'c.x=a.x', pc.y - pa.y : 'c.y=a.y'})) + return (assumeLaw, require) + + +def law_jacobian_weierstrass_add_infinite_ab(A, B, pa, pb, pA, pB, pC): + assumeLaw = (good_affine_point(pa) + + good_affine_point(pb) + + good_jacobian_point(pA) + + good_jacobian_point(pB) + + infinite(pA) + + infinite(pB)) + require = infinite(pC) + return (assumeLaw, require) + + +laws_jacobian_weierstrass = { + 'add': law_jacobian_weierstrass_add, + 'double': law_jacobian_weierstrass_double, + 'add_opposite': law_jacobian_weierstrass_add_opposites, + 'add_infinite_a': law_jacobian_weierstrass_add_infinite_a, + 'add_infinite_b': law_jacobian_weierstrass_add_infinite_b, + 'add_infinite_ab': law_jacobian_weierstrass_add_infinite_ab +} + + +def check_exhaustive_jacobian_weierstrass(name, A, B, branches, formula, p): + """Verify an implementation of addition of Jacobian points on a Weierstrass curve, by executing and validating the result for every possible addition in a prime field""" + F = Integers(p) + print "Formula %s on Z%i:" % (name, p) + points = [] + for x in xrange(0, p): + for y in xrange(0, p): + point = affinepoint(F(x), F(y)) + r, e = concrete_verify(on_weierstrass_curve(A, B, point)) + if r: + points.append(point) + + for za in xrange(1, p): + for zb in xrange(1, p): + for pa in points: + for pb in points: + for ia in xrange(2): + for ib in xrange(2): + pA = jacobianpoint(pa.x * F(za)^2, pa.y * F(za)^3, F(za), ia) + pB = jacobianpoint(pb.x * F(zb)^2, pb.y * F(zb)^3, F(zb), ib) + for branch in xrange(0, branches): + assumeAssert, assumeBranch, pC = formula(branch, pA, pB) + pC.X = F(pC.X) + pC.Y = F(pC.Y) + pC.Z = F(pC.Z) + pC.Infinity = F(pC.Infinity) + r, e = concrete_verify(assumeAssert + assumeBranch) + if r: + match = False + for key in laws_jacobian_weierstrass: + assumeLaw, require = laws_jacobian_weierstrass[key](A, B, pa, pb, pA, pB, pC) + r, e = concrete_verify(assumeLaw) + if r: + if match: + print " multiple branches for (%s,%s,%s,%s) + (%s,%s,%s,%s)" % (pA.X, pA.Y, pA.Z, pA.Infinity, pB.X, pB.Y, pB.Z, pB.Infinity) + else: + match = True + r, e = concrete_verify(require) + if not r: + print " failure in branch %i for (%s,%s,%s,%s) + (%s,%s,%s,%s) = (%s,%s,%s,%s): %s" % (branch, pA.X, pA.Y, pA.Z, pA.Infinity, pB.X, pB.Y, pB.Z, pB.Infinity, pC.X, pC.Y, pC.Z, pC.Infinity, e) + print + + +def check_symbolic_function(R, assumeAssert, assumeBranch, f, A, B, pa, pb, pA, pB, pC): + assumeLaw, require = f(A, B, pa, pb, pA, pB, pC) + return check_symbolic(R, assumeLaw, assumeAssert, assumeBranch, require) + +def check_symbolic_jacobian_weierstrass(name, A, B, branches, formula): + """Verify an implementation of addition of Jacobian points on a Weierstrass curve symbolically""" + R. = PolynomialRing(QQ,8,order='invlex') + lift = lambda x: fastfrac(R,x) + ax = lift(ax) + ay = lift(ay) + Az = lift(Az) + bx = lift(bx) + by = lift(by) + Bz = lift(Bz) + Ai = lift(Ai) + Bi = lift(Bi) + + pa = affinepoint(ax, ay, Ai) + pb = affinepoint(bx, by, Bi) + pA = jacobianpoint(ax * Az^2, ay * Az^3, Az, Ai) + pB = jacobianpoint(bx * Bz^2, by * Bz^3, Bz, Bi) + + res = {} + + for key in laws_jacobian_weierstrass: + res[key] = [] + + print ("Formula " + name + ":") + count = 0 + for branch in xrange(branches): + assumeFormula, assumeBranch, pC = formula(branch, pA, pB) + pC.X = lift(pC.X) + pC.Y = lift(pC.Y) + pC.Z = lift(pC.Z) + pC.Infinity = lift(pC.Infinity) + + for key in laws_jacobian_weierstrass: + res[key].append((check_symbolic_function(R, assumeFormula, assumeBranch, laws_jacobian_weierstrass[key], A, B, pa, pb, pA, pB, pC), branch)) + + for key in res: + print " %s:" % key + val = res[key] + for x in val: + if x[0] is not None: + print " branch %i: %s" % (x[1], x[0]) + + print diff --git a/src/asm/field_10x26_arm.s b/src/asm/field_10x26_arm.s new file mode 100644 index 0000000000000..5df561f2fc939 --- /dev/null +++ b/src/asm/field_10x26_arm.s @@ -0,0 +1,919 @@ +@ vim: set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab syntax=armasm: +/********************************************************************** + * Copyright (c) 2014 Wladimir J. van der Laan * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ +/* +ARM implementation of field_10x26 inner loops. + +Note: + +- To avoid unnecessary loads and make use of available registers, two + 'passes' have every time been interleaved, with the odd passes accumulating c' and d' + which will be added to c and d respectively in the the even passes + +*/ + + .syntax unified + .arch armv7-a + @ eabi attributes - see readelf -A + .eabi_attribute 8, 1 @ Tag_ARM_ISA_use = yes + .eabi_attribute 9, 0 @ Tag_Thumb_ISA_use = no + .eabi_attribute 10, 0 @ Tag_FP_arch = none + .eabi_attribute 24, 1 @ Tag_ABI_align_needed = 8-byte + .eabi_attribute 25, 1 @ Tag_ABI_align_preserved = 8-byte, except leaf SP + .eabi_attribute 30, 2 @ Tag_ABI_optimization_goals = Agressive Speed + .eabi_attribute 34, 1 @ Tag_CPU_unaligned_access = v6 + .text + + @ Field constants + .set field_R0, 0x3d10 + .set field_R1, 0x400 + .set field_not_M, 0xfc000000 @ ~M = ~0x3ffffff + + .align 2 + .global secp256k1_fe_mul_inner + .type secp256k1_fe_mul_inner, %function + @ Arguments: + @ r0 r Restrict: can overlap with a, not with b + @ r1 a + @ r2 b + @ Stack (total 4+10*4 = 44) + @ sp + #0 saved 'r' pointer + @ sp + #4 + 4*X t0,t1,t2,t3,t4,t5,t6,t7,u8,t9 +secp256k1_fe_mul_inner: + stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r14} + sub sp, sp, #48 @ frame=44 + alignment + str r0, [sp, #0] @ save result address, we need it only at the end + + /****************************************** + * Main computation code. + ****************************************** + + Allocation: + r0,r14,r7,r8 scratch + r1 a (pointer) + r2 b (pointer) + r3:r4 c + r5:r6 d + r11:r12 c' + r9:r10 d' + + Note: do not write to r[] here, it may overlap with a[] + */ + + /* A - interleaved with B */ + ldr r7, [r1, #0*4] @ a[0] + ldr r8, [r2, #9*4] @ b[9] + ldr r0, [r1, #1*4] @ a[1] + umull r5, r6, r7, r8 @ d = a[0] * b[9] + ldr r14, [r2, #8*4] @ b[8] + umull r9, r10, r0, r8 @ d' = a[1] * b[9] + ldr r7, [r1, #2*4] @ a[2] + umlal r5, r6, r0, r14 @ d += a[1] * b[8] + ldr r8, [r2, #7*4] @ b[7] + umlal r9, r10, r7, r14 @ d' += a[2] * b[8] + ldr r0, [r1, #3*4] @ a[3] + umlal r5, r6, r7, r8 @ d += a[2] * b[7] + ldr r14, [r2, #6*4] @ b[6] + umlal r9, r10, r0, r8 @ d' += a[3] * b[7] + ldr r7, [r1, #4*4] @ a[4] + umlal r5, r6, r0, r14 @ d += a[3] * b[6] + ldr r8, [r2, #5*4] @ b[5] + umlal r9, r10, r7, r14 @ d' += a[4] * b[6] + ldr r0, [r1, #5*4] @ a[5] + umlal r5, r6, r7, r8 @ d += a[4] * b[5] + ldr r14, [r2, #4*4] @ b[4] + umlal r9, r10, r0, r8 @ d' += a[5] * b[5] + ldr r7, [r1, #6*4] @ a[6] + umlal r5, r6, r0, r14 @ d += a[5] * b[4] + ldr r8, [r2, #3*4] @ b[3] + umlal r9, r10, r7, r14 @ d' += a[6] * b[4] + ldr r0, [r1, #7*4] @ a[7] + umlal r5, r6, r7, r8 @ d += a[6] * b[3] + ldr r14, [r2, #2*4] @ b[2] + umlal r9, r10, r0, r8 @ d' += a[7] * b[3] + ldr r7, [r1, #8*4] @ a[8] + umlal r5, r6, r0, r14 @ d += a[7] * b[2] + ldr r8, [r2, #1*4] @ b[1] + umlal r9, r10, r7, r14 @ d' += a[8] * b[2] + ldr r0, [r1, #9*4] @ a[9] + umlal r5, r6, r7, r8 @ d += a[8] * b[1] + ldr r14, [r2, #0*4] @ b[0] + umlal r9, r10, r0, r8 @ d' += a[9] * b[1] + ldr r7, [r1, #0*4] @ a[0] + umlal r5, r6, r0, r14 @ d += a[9] * b[0] + @ r7,r14 used in B + + bic r0, r5, field_not_M @ t9 = d & M + str r0, [sp, #4 + 4*9] + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + + /* B */ + umull r3, r4, r7, r14 @ c = a[0] * b[0] + adds r5, r5, r9 @ d += d' + adc r6, r6, r10 + + bic r0, r5, field_not_M @ u0 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u0 * R0 + umlal r3, r4, r0, r14 + + bic r14, r3, field_not_M @ t0 = c & M + str r14, [sp, #4 + 0*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u0 * R1 + umlal r3, r4, r0, r14 + + /* C - interleaved with D */ + ldr r7, [r1, #0*4] @ a[0] + ldr r8, [r2, #2*4] @ b[2] + ldr r14, [r2, #1*4] @ b[1] + umull r11, r12, r7, r8 @ c' = a[0] * b[2] + ldr r0, [r1, #1*4] @ a[1] + umlal r3, r4, r7, r14 @ c += a[0] * b[1] + ldr r8, [r2, #0*4] @ b[0] + umlal r11, r12, r0, r14 @ c' += a[1] * b[1] + ldr r7, [r1, #2*4] @ a[2] + umlal r3, r4, r0, r8 @ c += a[1] * b[0] + ldr r14, [r2, #9*4] @ b[9] + umlal r11, r12, r7, r8 @ c' += a[2] * b[0] + ldr r0, [r1, #3*4] @ a[3] + umlal r5, r6, r7, r14 @ d += a[2] * b[9] + ldr r8, [r2, #8*4] @ b[8] + umull r9, r10, r0, r14 @ d' = a[3] * b[9] + ldr r7, [r1, #4*4] @ a[4] + umlal r5, r6, r0, r8 @ d += a[3] * b[8] + ldr r14, [r2, #7*4] @ b[7] + umlal r9, r10, r7, r8 @ d' += a[4] * b[8] + ldr r0, [r1, #5*4] @ a[5] + umlal r5, r6, r7, r14 @ d += a[4] * b[7] + ldr r8, [r2, #6*4] @ b[6] + umlal r9, r10, r0, r14 @ d' += a[5] * b[7] + ldr r7, [r1, #6*4] @ a[6] + umlal r5, r6, r0, r8 @ d += a[5] * b[6] + ldr r14, [r2, #5*4] @ b[5] + umlal r9, r10, r7, r8 @ d' += a[6] * b[6] + ldr r0, [r1, #7*4] @ a[7] + umlal r5, r6, r7, r14 @ d += a[6] * b[5] + ldr r8, [r2, #4*4] @ b[4] + umlal r9, r10, r0, r14 @ d' += a[7] * b[5] + ldr r7, [r1, #8*4] @ a[8] + umlal r5, r6, r0, r8 @ d += a[7] * b[4] + ldr r14, [r2, #3*4] @ b[3] + umlal r9, r10, r7, r8 @ d' += a[8] * b[4] + ldr r0, [r1, #9*4] @ a[9] + umlal r5, r6, r7, r14 @ d += a[8] * b[3] + ldr r8, [r2, #2*4] @ b[2] + umlal r9, r10, r0, r14 @ d' += a[9] * b[3] + umlal r5, r6, r0, r8 @ d += a[9] * b[2] + + bic r0, r5, field_not_M @ u1 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u1 * R0 + umlal r3, r4, r0, r14 + + bic r14, r3, field_not_M @ t1 = c & M + str r14, [sp, #4 + 1*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u1 * R1 + umlal r3, r4, r0, r14 + + /* D */ + adds r3, r3, r11 @ c += c' + adc r4, r4, r12 + adds r5, r5, r9 @ d += d' + adc r6, r6, r10 + + bic r0, r5, field_not_M @ u2 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u2 * R0 + umlal r3, r4, r0, r14 + + bic r14, r3, field_not_M @ t2 = c & M + str r14, [sp, #4 + 2*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u2 * R1 + umlal r3, r4, r0, r14 + + /* E - interleaved with F */ + ldr r7, [r1, #0*4] @ a[0] + ldr r8, [r2, #4*4] @ b[4] + umull r11, r12, r7, r8 @ c' = a[0] * b[4] + ldr r8, [r2, #3*4] @ b[3] + umlal r3, r4, r7, r8 @ c += a[0] * b[3] + ldr r7, [r1, #1*4] @ a[1] + umlal r11, r12, r7, r8 @ c' += a[1] * b[3] + ldr r8, [r2, #2*4] @ b[2] + umlal r3, r4, r7, r8 @ c += a[1] * b[2] + ldr r7, [r1, #2*4] @ a[2] + umlal r11, r12, r7, r8 @ c' += a[2] * b[2] + ldr r8, [r2, #1*4] @ b[1] + umlal r3, r4, r7, r8 @ c += a[2] * b[1] + ldr r7, [r1, #3*4] @ a[3] + umlal r11, r12, r7, r8 @ c' += a[3] * b[1] + ldr r8, [r2, #0*4] @ b[0] + umlal r3, r4, r7, r8 @ c += a[3] * b[0] + ldr r7, [r1, #4*4] @ a[4] + umlal r11, r12, r7, r8 @ c' += a[4] * b[0] + ldr r8, [r2, #9*4] @ b[9] + umlal r5, r6, r7, r8 @ d += a[4] * b[9] + ldr r7, [r1, #5*4] @ a[5] + umull r9, r10, r7, r8 @ d' = a[5] * b[9] + ldr r8, [r2, #8*4] @ b[8] + umlal r5, r6, r7, r8 @ d += a[5] * b[8] + ldr r7, [r1, #6*4] @ a[6] + umlal r9, r10, r7, r8 @ d' += a[6] * b[8] + ldr r8, [r2, #7*4] @ b[7] + umlal r5, r6, r7, r8 @ d += a[6] * b[7] + ldr r7, [r1, #7*4] @ a[7] + umlal r9, r10, r7, r8 @ d' += a[7] * b[7] + ldr r8, [r2, #6*4] @ b[6] + umlal r5, r6, r7, r8 @ d += a[7] * b[6] + ldr r7, [r1, #8*4] @ a[8] + umlal r9, r10, r7, r8 @ d' += a[8] * b[6] + ldr r8, [r2, #5*4] @ b[5] + umlal r5, r6, r7, r8 @ d += a[8] * b[5] + ldr r7, [r1, #9*4] @ a[9] + umlal r9, r10, r7, r8 @ d' += a[9] * b[5] + ldr r8, [r2, #4*4] @ b[4] + umlal r5, r6, r7, r8 @ d += a[9] * b[4] + + bic r0, r5, field_not_M @ u3 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u3 * R0 + umlal r3, r4, r0, r14 + + bic r14, r3, field_not_M @ t3 = c & M + str r14, [sp, #4 + 3*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u3 * R1 + umlal r3, r4, r0, r14 + + /* F */ + adds r3, r3, r11 @ c += c' + adc r4, r4, r12 + adds r5, r5, r9 @ d += d' + adc r6, r6, r10 + + bic r0, r5, field_not_M @ u4 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u4 * R0 + umlal r3, r4, r0, r14 + + bic r14, r3, field_not_M @ t4 = c & M + str r14, [sp, #4 + 4*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u4 * R1 + umlal r3, r4, r0, r14 + + /* G - interleaved with H */ + ldr r7, [r1, #0*4] @ a[0] + ldr r8, [r2, #6*4] @ b[6] + ldr r14, [r2, #5*4] @ b[5] + umull r11, r12, r7, r8 @ c' = a[0] * b[6] + ldr r0, [r1, #1*4] @ a[1] + umlal r3, r4, r7, r14 @ c += a[0] * b[5] + ldr r8, [r2, #4*4] @ b[4] + umlal r11, r12, r0, r14 @ c' += a[1] * b[5] + ldr r7, [r1, #2*4] @ a[2] + umlal r3, r4, r0, r8 @ c += a[1] * b[4] + ldr r14, [r2, #3*4] @ b[3] + umlal r11, r12, r7, r8 @ c' += a[2] * b[4] + ldr r0, [r1, #3*4] @ a[3] + umlal r3, r4, r7, r14 @ c += a[2] * b[3] + ldr r8, [r2, #2*4] @ b[2] + umlal r11, r12, r0, r14 @ c' += a[3] * b[3] + ldr r7, [r1, #4*4] @ a[4] + umlal r3, r4, r0, r8 @ c += a[3] * b[2] + ldr r14, [r2, #1*4] @ b[1] + umlal r11, r12, r7, r8 @ c' += a[4] * b[2] + ldr r0, [r1, #5*4] @ a[5] + umlal r3, r4, r7, r14 @ c += a[4] * b[1] + ldr r8, [r2, #0*4] @ b[0] + umlal r11, r12, r0, r14 @ c' += a[5] * b[1] + ldr r7, [r1, #6*4] @ a[6] + umlal r3, r4, r0, r8 @ c += a[5] * b[0] + ldr r14, [r2, #9*4] @ b[9] + umlal r11, r12, r7, r8 @ c' += a[6] * b[0] + ldr r0, [r1, #7*4] @ a[7] + umlal r5, r6, r7, r14 @ d += a[6] * b[9] + ldr r8, [r2, #8*4] @ b[8] + umull r9, r10, r0, r14 @ d' = a[7] * b[9] + ldr r7, [r1, #8*4] @ a[8] + umlal r5, r6, r0, r8 @ d += a[7] * b[8] + ldr r14, [r2, #7*4] @ b[7] + umlal r9, r10, r7, r8 @ d' += a[8] * b[8] + ldr r0, [r1, #9*4] @ a[9] + umlal r5, r6, r7, r14 @ d += a[8] * b[7] + ldr r8, [r2, #6*4] @ b[6] + umlal r9, r10, r0, r14 @ d' += a[9] * b[7] + umlal r5, r6, r0, r8 @ d += a[9] * b[6] + + bic r0, r5, field_not_M @ u5 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u5 * R0 + umlal r3, r4, r0, r14 + + bic r14, r3, field_not_M @ t5 = c & M + str r14, [sp, #4 + 5*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u5 * R1 + umlal r3, r4, r0, r14 + + /* H */ + adds r3, r3, r11 @ c += c' + adc r4, r4, r12 + adds r5, r5, r9 @ d += d' + adc r6, r6, r10 + + bic r0, r5, field_not_M @ u6 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u6 * R0 + umlal r3, r4, r0, r14 + + bic r14, r3, field_not_M @ t6 = c & M + str r14, [sp, #4 + 6*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u6 * R1 + umlal r3, r4, r0, r14 + + /* I - interleaved with J */ + ldr r8, [r2, #8*4] @ b[8] + ldr r7, [r1, #0*4] @ a[0] + ldr r14, [r2, #7*4] @ b[7] + umull r11, r12, r7, r8 @ c' = a[0] * b[8] + ldr r0, [r1, #1*4] @ a[1] + umlal r3, r4, r7, r14 @ c += a[0] * b[7] + ldr r8, [r2, #6*4] @ b[6] + umlal r11, r12, r0, r14 @ c' += a[1] * b[7] + ldr r7, [r1, #2*4] @ a[2] + umlal r3, r4, r0, r8 @ c += a[1] * b[6] + ldr r14, [r2, #5*4] @ b[5] + umlal r11, r12, r7, r8 @ c' += a[2] * b[6] + ldr r0, [r1, #3*4] @ a[3] + umlal r3, r4, r7, r14 @ c += a[2] * b[5] + ldr r8, [r2, #4*4] @ b[4] + umlal r11, r12, r0, r14 @ c' += a[3] * b[5] + ldr r7, [r1, #4*4] @ a[4] + umlal r3, r4, r0, r8 @ c += a[3] * b[4] + ldr r14, [r2, #3*4] @ b[3] + umlal r11, r12, r7, r8 @ c' += a[4] * b[4] + ldr r0, [r1, #5*4] @ a[5] + umlal r3, r4, r7, r14 @ c += a[4] * b[3] + ldr r8, [r2, #2*4] @ b[2] + umlal r11, r12, r0, r14 @ c' += a[5] * b[3] + ldr r7, [r1, #6*4] @ a[6] + umlal r3, r4, r0, r8 @ c += a[5] * b[2] + ldr r14, [r2, #1*4] @ b[1] + umlal r11, r12, r7, r8 @ c' += a[6] * b[2] + ldr r0, [r1, #7*4] @ a[7] + umlal r3, r4, r7, r14 @ c += a[6] * b[1] + ldr r8, [r2, #0*4] @ b[0] + umlal r11, r12, r0, r14 @ c' += a[7] * b[1] + ldr r7, [r1, #8*4] @ a[8] + umlal r3, r4, r0, r8 @ c += a[7] * b[0] + ldr r14, [r2, #9*4] @ b[9] + umlal r11, r12, r7, r8 @ c' += a[8] * b[0] + ldr r0, [r1, #9*4] @ a[9] + umlal r5, r6, r7, r14 @ d += a[8] * b[9] + ldr r8, [r2, #8*4] @ b[8] + umull r9, r10, r0, r14 @ d' = a[9] * b[9] + umlal r5, r6, r0, r8 @ d += a[9] * b[8] + + bic r0, r5, field_not_M @ u7 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u7 * R0 + umlal r3, r4, r0, r14 + + bic r14, r3, field_not_M @ t7 = c & M + str r14, [sp, #4 + 7*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u7 * R1 + umlal r3, r4, r0, r14 + + /* J */ + adds r3, r3, r11 @ c += c' + adc r4, r4, r12 + adds r5, r5, r9 @ d += d' + adc r6, r6, r10 + + bic r0, r5, field_not_M @ u8 = d & M + str r0, [sp, #4 + 8*4] + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u8 * R0 + umlal r3, r4, r0, r14 + + /****************************************** + * compute and write back result + ****************************************** + Allocation: + r0 r + r3:r4 c + r5:r6 d + r7 t0 + r8 t1 + r9 t2 + r11 u8 + r12 t9 + r1,r2,r10,r14 scratch + + Note: do not read from a[] after here, it may overlap with r[] + */ + ldr r0, [sp, #0] + add r1, sp, #4 + 3*4 @ r[3..7] = t3..7, r11=u8, r12=t9 + ldmia r1, {r2,r7,r8,r9,r10,r11,r12} + add r1, r0, #3*4 + stmia r1, {r2,r7,r8,r9,r10} + + bic r2, r3, field_not_M @ r[8] = c & M + str r2, [r0, #8*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u8 * R1 + umlal r3, r4, r11, r14 + movw r14, field_R0 @ c += d * R0 + umlal r3, r4, r5, r14 + adds r3, r3, r12 @ c += t9 + adc r4, r4, #0 + + add r1, sp, #4 + 0*4 @ r7,r8,r9 = t0,t1,t2 + ldmia r1, {r7,r8,r9} + + ubfx r2, r3, #0, #22 @ r[9] = c & (M >> 4) + str r2, [r0, #9*4] + mov r3, r3, lsr #22 @ c >>= 22 + orr r3, r3, r4, asl #10 + mov r4, r4, lsr #22 + movw r14, field_R1 << 4 @ c += d * (R1 << 4) + umlal r3, r4, r5, r14 + + movw r14, field_R0 >> 4 @ d = c * (R0 >> 4) + t0 (64x64 multiply+add) + umull r5, r6, r3, r14 @ d = c.lo * (R0 >> 4) + adds r5, r5, r7 @ d.lo += t0 + mla r6, r14, r4, r6 @ d.hi += c.hi * (R0 >> 4) + adc r6, r6, 0 @ d.hi += carry + + bic r2, r5, field_not_M @ r[0] = d & M + str r2, [r0, #0*4] + + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + + movw r14, field_R1 >> 4 @ d += c * (R1 >> 4) + t1 (64x64 multiply+add) + umull r1, r2, r3, r14 @ tmp = c.lo * (R1 >> 4) + adds r5, r5, r8 @ d.lo += t1 + adc r6, r6, #0 @ d.hi += carry + adds r5, r5, r1 @ d.lo += tmp.lo + mla r2, r14, r4, r2 @ tmp.hi += c.hi * (R1 >> 4) + adc r6, r6, r2 @ d.hi += carry + tmp.hi + + bic r2, r5, field_not_M @ r[1] = d & M + str r2, [r0, #1*4] + mov r5, r5, lsr #26 @ d >>= 26 (ignore hi) + orr r5, r5, r6, asl #6 + + add r5, r5, r9 @ d += t2 + str r5, [r0, #2*4] @ r[2] = d + + add sp, sp, #48 + ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc} + .size secp256k1_fe_mul_inner, .-secp256k1_fe_mul_inner + + .align 2 + .global secp256k1_fe_sqr_inner + .type secp256k1_fe_sqr_inner, %function + @ Arguments: + @ r0 r Can overlap with a + @ r1 a + @ Stack (total 4+10*4 = 44) + @ sp + #0 saved 'r' pointer + @ sp + #4 + 4*X t0,t1,t2,t3,t4,t5,t6,t7,u8,t9 +secp256k1_fe_sqr_inner: + stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r14} + sub sp, sp, #48 @ frame=44 + alignment + str r0, [sp, #0] @ save result address, we need it only at the end + /****************************************** + * Main computation code. + ****************************************** + + Allocation: + r0,r14,r2,r7,r8 scratch + r1 a (pointer) + r3:r4 c + r5:r6 d + r11:r12 c' + r9:r10 d' + + Note: do not write to r[] here, it may overlap with a[] + */ + /* A interleaved with B */ + ldr r0, [r1, #1*4] @ a[1]*2 + ldr r7, [r1, #0*4] @ a[0] + mov r0, r0, asl #1 + ldr r14, [r1, #9*4] @ a[9] + umull r3, r4, r7, r7 @ c = a[0] * a[0] + ldr r8, [r1, #8*4] @ a[8] + mov r7, r7, asl #1 + umull r5, r6, r7, r14 @ d = a[0]*2 * a[9] + ldr r7, [r1, #2*4] @ a[2]*2 + umull r9, r10, r0, r14 @ d' = a[1]*2 * a[9] + ldr r14, [r1, #7*4] @ a[7] + umlal r5, r6, r0, r8 @ d += a[1]*2 * a[8] + mov r7, r7, asl #1 + ldr r0, [r1, #3*4] @ a[3]*2 + umlal r9, r10, r7, r8 @ d' += a[2]*2 * a[8] + ldr r8, [r1, #6*4] @ a[6] + umlal r5, r6, r7, r14 @ d += a[2]*2 * a[7] + mov r0, r0, asl #1 + ldr r7, [r1, #4*4] @ a[4]*2 + umlal r9, r10, r0, r14 @ d' += a[3]*2 * a[7] + ldr r14, [r1, #5*4] @ a[5] + mov r7, r7, asl #1 + umlal r5, r6, r0, r8 @ d += a[3]*2 * a[6] + umlal r9, r10, r7, r8 @ d' += a[4]*2 * a[6] + umlal r5, r6, r7, r14 @ d += a[4]*2 * a[5] + umlal r9, r10, r14, r14 @ d' += a[5] * a[5] + + bic r0, r5, field_not_M @ t9 = d & M + str r0, [sp, #4 + 9*4] + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + + /* B */ + adds r5, r5, r9 @ d += d' + adc r6, r6, r10 + + bic r0, r5, field_not_M @ u0 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u0 * R0 + umlal r3, r4, r0, r14 + bic r14, r3, field_not_M @ t0 = c & M + str r14, [sp, #4 + 0*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u0 * R1 + umlal r3, r4, r0, r14 + + /* C interleaved with D */ + ldr r0, [r1, #0*4] @ a[0]*2 + ldr r14, [r1, #1*4] @ a[1] + mov r0, r0, asl #1 + ldr r8, [r1, #2*4] @ a[2] + umlal r3, r4, r0, r14 @ c += a[0]*2 * a[1] + mov r7, r8, asl #1 @ a[2]*2 + umull r11, r12, r14, r14 @ c' = a[1] * a[1] + ldr r14, [r1, #9*4] @ a[9] + umlal r11, r12, r0, r8 @ c' += a[0]*2 * a[2] + ldr r0, [r1, #3*4] @ a[3]*2 + ldr r8, [r1, #8*4] @ a[8] + umlal r5, r6, r7, r14 @ d += a[2]*2 * a[9] + mov r0, r0, asl #1 + ldr r7, [r1, #4*4] @ a[4]*2 + umull r9, r10, r0, r14 @ d' = a[3]*2 * a[9] + ldr r14, [r1, #7*4] @ a[7] + umlal r5, r6, r0, r8 @ d += a[3]*2 * a[8] + mov r7, r7, asl #1 + ldr r0, [r1, #5*4] @ a[5]*2 + umlal r9, r10, r7, r8 @ d' += a[4]*2 * a[8] + ldr r8, [r1, #6*4] @ a[6] + mov r0, r0, asl #1 + umlal r5, r6, r7, r14 @ d += a[4]*2 * a[7] + umlal r9, r10, r0, r14 @ d' += a[5]*2 * a[7] + umlal r5, r6, r0, r8 @ d += a[5]*2 * a[6] + umlal r9, r10, r8, r8 @ d' += a[6] * a[6] + + bic r0, r5, field_not_M @ u1 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u1 * R0 + umlal r3, r4, r0, r14 + bic r14, r3, field_not_M @ t1 = c & M + str r14, [sp, #4 + 1*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u1 * R1 + umlal r3, r4, r0, r14 + + /* D */ + adds r3, r3, r11 @ c += c' + adc r4, r4, r12 + adds r5, r5, r9 @ d += d' + adc r6, r6, r10 + + bic r0, r5, field_not_M @ u2 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u2 * R0 + umlal r3, r4, r0, r14 + bic r14, r3, field_not_M @ t2 = c & M + str r14, [sp, #4 + 2*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u2 * R1 + umlal r3, r4, r0, r14 + + /* E interleaved with F */ + ldr r7, [r1, #0*4] @ a[0]*2 + ldr r0, [r1, #1*4] @ a[1]*2 + ldr r14, [r1, #2*4] @ a[2] + mov r7, r7, asl #1 + ldr r8, [r1, #3*4] @ a[3] + ldr r2, [r1, #4*4] + umlal r3, r4, r7, r8 @ c += a[0]*2 * a[3] + mov r0, r0, asl #1 + umull r11, r12, r7, r2 @ c' = a[0]*2 * a[4] + mov r2, r2, asl #1 @ a[4]*2 + umlal r11, r12, r0, r8 @ c' += a[1]*2 * a[3] + ldr r8, [r1, #9*4] @ a[9] + umlal r3, r4, r0, r14 @ c += a[1]*2 * a[2] + ldr r0, [r1, #5*4] @ a[5]*2 + umlal r11, r12, r14, r14 @ c' += a[2] * a[2] + ldr r14, [r1, #8*4] @ a[8] + mov r0, r0, asl #1 + umlal r5, r6, r2, r8 @ d += a[4]*2 * a[9] + ldr r7, [r1, #6*4] @ a[6]*2 + umull r9, r10, r0, r8 @ d' = a[5]*2 * a[9] + mov r7, r7, asl #1 + ldr r8, [r1, #7*4] @ a[7] + umlal r5, r6, r0, r14 @ d += a[5]*2 * a[8] + umlal r9, r10, r7, r14 @ d' += a[6]*2 * a[8] + umlal r5, r6, r7, r8 @ d += a[6]*2 * a[7] + umlal r9, r10, r8, r8 @ d' += a[7] * a[7] + + bic r0, r5, field_not_M @ u3 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u3 * R0 + umlal r3, r4, r0, r14 + bic r14, r3, field_not_M @ t3 = c & M + str r14, [sp, #4 + 3*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u3 * R1 + umlal r3, r4, r0, r14 + + /* F */ + adds r3, r3, r11 @ c += c' + adc r4, r4, r12 + adds r5, r5, r9 @ d += d' + adc r6, r6, r10 + + bic r0, r5, field_not_M @ u4 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u4 * R0 + umlal r3, r4, r0, r14 + bic r14, r3, field_not_M @ t4 = c & M + str r14, [sp, #4 + 4*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u4 * R1 + umlal r3, r4, r0, r14 + + /* G interleaved with H */ + ldr r7, [r1, #0*4] @ a[0]*2 + ldr r0, [r1, #1*4] @ a[1]*2 + mov r7, r7, asl #1 + ldr r8, [r1, #5*4] @ a[5] + ldr r2, [r1, #6*4] @ a[6] + umlal r3, r4, r7, r8 @ c += a[0]*2 * a[5] + ldr r14, [r1, #4*4] @ a[4] + mov r0, r0, asl #1 + umull r11, r12, r7, r2 @ c' = a[0]*2 * a[6] + ldr r7, [r1, #2*4] @ a[2]*2 + umlal r11, r12, r0, r8 @ c' += a[1]*2 * a[5] + mov r7, r7, asl #1 + ldr r8, [r1, #3*4] @ a[3] + umlal r3, r4, r0, r14 @ c += a[1]*2 * a[4] + mov r0, r2, asl #1 @ a[6]*2 + umlal r11, r12, r7, r14 @ c' += a[2]*2 * a[4] + ldr r14, [r1, #9*4] @ a[9] + umlal r3, r4, r7, r8 @ c += a[2]*2 * a[3] + ldr r7, [r1, #7*4] @ a[7]*2 + umlal r11, r12, r8, r8 @ c' += a[3] * a[3] + mov r7, r7, asl #1 + ldr r8, [r1, #8*4] @ a[8] + umlal r5, r6, r0, r14 @ d += a[6]*2 * a[9] + umull r9, r10, r7, r14 @ d' = a[7]*2 * a[9] + umlal r5, r6, r7, r8 @ d += a[7]*2 * a[8] + umlal r9, r10, r8, r8 @ d' += a[8] * a[8] + + bic r0, r5, field_not_M @ u5 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u5 * R0 + umlal r3, r4, r0, r14 + bic r14, r3, field_not_M @ t5 = c & M + str r14, [sp, #4 + 5*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u5 * R1 + umlal r3, r4, r0, r14 + + /* H */ + adds r3, r3, r11 @ c += c' + adc r4, r4, r12 + adds r5, r5, r9 @ d += d' + adc r6, r6, r10 + + bic r0, r5, field_not_M @ u6 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u6 * R0 + umlal r3, r4, r0, r14 + bic r14, r3, field_not_M @ t6 = c & M + str r14, [sp, #4 + 6*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u6 * R1 + umlal r3, r4, r0, r14 + + /* I interleaved with J */ + ldr r7, [r1, #0*4] @ a[0]*2 + ldr r0, [r1, #1*4] @ a[1]*2 + mov r7, r7, asl #1 + ldr r8, [r1, #7*4] @ a[7] + ldr r2, [r1, #8*4] @ a[8] + umlal r3, r4, r7, r8 @ c += a[0]*2 * a[7] + ldr r14, [r1, #6*4] @ a[6] + mov r0, r0, asl #1 + umull r11, r12, r7, r2 @ c' = a[0]*2 * a[8] + ldr r7, [r1, #2*4] @ a[2]*2 + umlal r11, r12, r0, r8 @ c' += a[1]*2 * a[7] + ldr r8, [r1, #5*4] @ a[5] + umlal r3, r4, r0, r14 @ c += a[1]*2 * a[6] + ldr r0, [r1, #3*4] @ a[3]*2 + mov r7, r7, asl #1 + umlal r11, r12, r7, r14 @ c' += a[2]*2 * a[6] + ldr r14, [r1, #4*4] @ a[4] + mov r0, r0, asl #1 + umlal r3, r4, r7, r8 @ c += a[2]*2 * a[5] + mov r2, r2, asl #1 @ a[8]*2 + umlal r11, r12, r0, r8 @ c' += a[3]*2 * a[5] + umlal r3, r4, r0, r14 @ c += a[3]*2 * a[4] + umlal r11, r12, r14, r14 @ c' += a[4] * a[4] + ldr r8, [r1, #9*4] @ a[9] + umlal r5, r6, r2, r8 @ d += a[8]*2 * a[9] + @ r8 will be used in J + + bic r0, r5, field_not_M @ u7 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u7 * R0 + umlal r3, r4, r0, r14 + bic r14, r3, field_not_M @ t7 = c & M + str r14, [sp, #4 + 7*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u7 * R1 + umlal r3, r4, r0, r14 + + /* J */ + adds r3, r3, r11 @ c += c' + adc r4, r4, r12 + umlal r5, r6, r8, r8 @ d += a[9] * a[9] + + bic r0, r5, field_not_M @ u8 = d & M + str r0, [sp, #4 + 8*4] + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u8 * R0 + umlal r3, r4, r0, r14 + + /****************************************** + * compute and write back result + ****************************************** + Allocation: + r0 r + r3:r4 c + r5:r6 d + r7 t0 + r8 t1 + r9 t2 + r11 u8 + r12 t9 + r1,r2,r10,r14 scratch + + Note: do not read from a[] after here, it may overlap with r[] + */ + ldr r0, [sp, #0] + add r1, sp, #4 + 3*4 @ r[3..7] = t3..7, r11=u8, r12=t9 + ldmia r1, {r2,r7,r8,r9,r10,r11,r12} + add r1, r0, #3*4 + stmia r1, {r2,r7,r8,r9,r10} + + bic r2, r3, field_not_M @ r[8] = c & M + str r2, [r0, #8*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u8 * R1 + umlal r3, r4, r11, r14 + movw r14, field_R0 @ c += d * R0 + umlal r3, r4, r5, r14 + adds r3, r3, r12 @ c += t9 + adc r4, r4, #0 + + add r1, sp, #4 + 0*4 @ r7,r8,r9 = t0,t1,t2 + ldmia r1, {r7,r8,r9} + + ubfx r2, r3, #0, #22 @ r[9] = c & (M >> 4) + str r2, [r0, #9*4] + mov r3, r3, lsr #22 @ c >>= 22 + orr r3, r3, r4, asl #10 + mov r4, r4, lsr #22 + movw r14, field_R1 << 4 @ c += d * (R1 << 4) + umlal r3, r4, r5, r14 + + movw r14, field_R0 >> 4 @ d = c * (R0 >> 4) + t0 (64x64 multiply+add) + umull r5, r6, r3, r14 @ d = c.lo * (R0 >> 4) + adds r5, r5, r7 @ d.lo += t0 + mla r6, r14, r4, r6 @ d.hi += c.hi * (R0 >> 4) + adc r6, r6, 0 @ d.hi += carry + + bic r2, r5, field_not_M @ r[0] = d & M + str r2, [r0, #0*4] + + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + + movw r14, field_R1 >> 4 @ d += c * (R1 >> 4) + t1 (64x64 multiply+add) + umull r1, r2, r3, r14 @ tmp = c.lo * (R1 >> 4) + adds r5, r5, r8 @ d.lo += t1 + adc r6, r6, #0 @ d.hi += carry + adds r5, r5, r1 @ d.lo += tmp.lo + mla r2, r14, r4, r2 @ tmp.hi += c.hi * (R1 >> 4) + adc r6, r6, r2 @ d.hi += carry + tmp.hi + + bic r2, r5, field_not_M @ r[1] = d & M + str r2, [r0, #1*4] + mov r5, r5, lsr #26 @ d >>= 26 (ignore hi) + orr r5, r5, r6, asl #6 + + add r5, r5, r9 @ d += t2 + str r5, [r0, #2*4] @ r[2] = d + + add sp, sp, #48 + ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc} + .size secp256k1_fe_sqr_inner, .-secp256k1_fe_sqr_inner + diff --git a/src/bench_ecdh.c b/src/bench_ecdh.c index 5a7c6376e08a1..cde5e2dbb4e4e 100644 --- a/src/bench_ecdh.c +++ b/src/bench_ecdh.c @@ -28,7 +28,8 @@ static void bench_ecdh_setup(void* arg) { 0xa2, 0xba, 0xd1, 0x84, 0xf8, 0x83, 0xc6, 0x9f }; - data->ctx = secp256k1_context_create(0); + /* create a context with no capabilities */ + data->ctx = secp256k1_context_create(SECP256K1_FLAGS_TYPE_CONTEXT); for (i = 0; i < 32; i++) { data->scalar[i] = i + 1; } diff --git a/src/bench_internal.c b/src/bench_internal.c index 7809f5f8cfeb4..0809f77bda108 100644 --- a/src/bench_internal.c +++ b/src/bench_internal.c @@ -181,12 +181,12 @@ void bench_field_inverse_var(void* arg) { } } -void bench_field_sqrt_var(void* arg) { +void bench_field_sqrt(void* arg) { int i; bench_inv_t *data = (bench_inv_t*)arg; for (i = 0; i < 20000; i++) { - secp256k1_fe_sqrt_var(&data->fe_x, &data->fe_x); + secp256k1_fe_sqrt(&data->fe_x, &data->fe_x); secp256k1_fe_add(&data->fe_x, &data->fe_y); } } @@ -227,6 +227,15 @@ void bench_group_add_affine_var(void* arg) { } } +void bench_group_jacobi_var(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 20000; i++) { + secp256k1_gej_has_quad_y_var(&data->gej_x); + } +} + void bench_ecmult_wnaf(void* arg) { int i; bench_inv_t *data = (bench_inv_t*)arg; @@ -299,6 +308,21 @@ void bench_context_sign(void* arg) { } } +#ifndef USE_NUM_NONE +void bench_num_jacobi(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + secp256k1_num nx, norder; + + secp256k1_scalar_get_num(&nx, &data->scalar_x); + secp256k1_scalar_order_get_num(&norder); + secp256k1_scalar_get_num(&norder, &data->scalar_y); + + for (i = 0; i < 200000; i++) { + secp256k1_num_jacobi(&nx, &norder); + } +} +#endif int have_flag(int argc, char** argv, char *flag) { char** argm = argv + argc; @@ -333,12 +357,13 @@ int main(int argc, char **argv) { if (have_flag(argc, argv, "field") || have_flag(argc, argv, "mul")) run_benchmark("field_mul", bench_field_mul, bench_setup, NULL, &data, 10, 200000); if (have_flag(argc, argv, "field") || have_flag(argc, argv, "inverse")) run_benchmark("field_inverse", bench_field_inverse, bench_setup, NULL, &data, 10, 20000); if (have_flag(argc, argv, "field") || have_flag(argc, argv, "inverse")) run_benchmark("field_inverse_var", bench_field_inverse_var, bench_setup, NULL, &data, 10, 20000); - if (have_flag(argc, argv, "field") || have_flag(argc, argv, "sqrt")) run_benchmark("field_sqrt_var", bench_field_sqrt_var, bench_setup, NULL, &data, 10, 20000); + if (have_flag(argc, argv, "field") || have_flag(argc, argv, "sqrt")) run_benchmark("field_sqrt", bench_field_sqrt, bench_setup, NULL, &data, 10, 20000); if (have_flag(argc, argv, "group") || have_flag(argc, argv, "double")) run_benchmark("group_double_var", bench_group_double_var, bench_setup, NULL, &data, 10, 200000); if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_var", bench_group_add_var, bench_setup, NULL, &data, 10, 200000); if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine", bench_group_add_affine, bench_setup, NULL, &data, 10, 200000); if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine_var", bench_group_add_affine_var, bench_setup, NULL, &data, 10, 200000); + if (have_flag(argc, argv, "group") || have_flag(argc, argv, "jacobi")) run_benchmark("group_jacobi_var", bench_group_jacobi_var, bench_setup, NULL, &data, 10, 20000); if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("wnaf_const", bench_wnaf_const, bench_setup, NULL, &data, 10, 20000); if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("ecmult_wnaf", bench_ecmult_wnaf, bench_setup, NULL, &data, 10, 20000); @@ -350,5 +375,8 @@ int main(int argc, char **argv) { if (have_flag(argc, argv, "context") || have_flag(argc, argv, "verify")) run_benchmark("context_verify", bench_context_verify, bench_setup, NULL, &data, 10, 20); if (have_flag(argc, argv, "context") || have_flag(argc, argv, "sign")) run_benchmark("context_sign", bench_context_sign, bench_setup, NULL, &data, 10, 200); +#ifndef USE_NUM_NONE + if (have_flag(argc, argv, "num") || have_flag(argc, argv, "jacobi")) run_benchmark("num_jacobi", bench_num_jacobi, bench_setup, NULL, &data, 10, 200000); +#endif return 0; } diff --git a/src/bench_verify.c b/src/bench_verify.c index 5718320cda298..418defa0aa22a 100644 --- a/src/bench_verify.c +++ b/src/bench_verify.c @@ -11,6 +11,12 @@ #include "util.h" #include "bench.h" +#ifdef ENABLE_OPENSSL_TESTS +#include +#include +#include +#endif + typedef struct { secp256k1_context *ctx; unsigned char msg[32]; @@ -19,6 +25,9 @@ typedef struct { size_t siglen; unsigned char pubkey[33]; size_t pubkeylen; +#ifdef ENABLE_OPENSSL_TESTS + EC_GROUP* ec_group; +#endif } benchmark_verify_t; static void benchmark_verify(void* arg) { @@ -40,6 +49,36 @@ static void benchmark_verify(void* arg) { } } +#ifdef ENABLE_OPENSSL_TESTS +static void benchmark_verify_openssl(void* arg) { + int i; + benchmark_verify_t* data = (benchmark_verify_t*)arg; + + for (i = 0; i < 20000; i++) { + data->sig[data->siglen - 1] ^= (i & 0xFF); + data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF); + data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF); + { + EC_KEY *pkey = EC_KEY_new(); + const unsigned char *pubkey = &data->pubkey[0]; + int result; + + CHECK(pkey != NULL); + result = EC_KEY_set_group(pkey, data->ec_group); + CHECK(result); + result = (o2i_ECPublicKey(&pkey, &pubkey, data->pubkeylen)) != NULL; + CHECK(result); + result = ECDSA_verify(0, &data->msg[0], sizeof(data->msg), &data->sig[0], data->siglen, pkey) == (i == 0); + CHECK(result); + EC_KEY_free(pkey); + } + data->sig[data->siglen - 1] ^= (i & 0xFF); + data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF); + data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF); + } +} +#endif + int main(void) { int i; secp256k1_pubkey pubkey; @@ -62,6 +101,11 @@ int main(void) { CHECK(secp256k1_ec_pubkey_serialize(data.ctx, data.pubkey, &data.pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED) == 1); run_benchmark("ecdsa_verify", benchmark_verify, NULL, NULL, &data, 10, 20000); +#ifdef ENABLE_OPENSSL_TESTS + data.ec_group = EC_GROUP_new_by_curve_name(NID_secp256k1); + run_benchmark("ecdsa_verify_openssl", benchmark_verify_openssl, NULL, NULL, &data, 10, 20000); + EC_GROUP_free(data.ec_group); +#endif secp256k1_context_destroy(data.ctx); return 0; diff --git a/src/ecmult_const_impl.h b/src/ecmult_const_impl.h index 90ac94770ea13..7a6a25318c4cf 100644 --- a/src/ecmult_const_impl.h +++ b/src/ecmult_const_impl.h @@ -58,22 +58,24 @@ static int secp256k1_wnaf_const(int *wnaf, secp256k1_scalar s, int w) { int global_sign; int skew = 0; int word = 0; + /* 1 2 3 */ int u_last; int u; -#ifdef USE_ENDOMORPHISM int flip; int bit; secp256k1_scalar neg_s; int not_neg_one; - /* If we are using the endomorphism, we cannot handle even numbers by negating - * them, since we are working with 128-bit numbers whose negations would be 256 - * bits, eliminating the performance advantage. Instead we use a technique from + /* Note that we cannot handle even numbers by negating them to be odd, as is + * done in other implementations, since if our scalars were specified to have + * width < 256 for performance reasons, their negations would have width 256 + * and we'd lose any performance benefit. Instead, we use a technique from * Section 4.2 of the Okeya/Tagaki paper, which is to add either 1 (for even) - * or 2 (for odd) to the number we are encoding, then compensating after the - * multiplication. */ - /* Negative 128-bit numbers will be negated, since otherwise they are 256-bit */ + * or 2 (for odd) to the number we are encoding, returning a skew value indicating + * this, and having the caller compensate after doing the multiplication. */ + + /* Negative numbers will be negated to keep their bit representation below the maximum width */ flip = secp256k1_scalar_is_high(&s); /* We add 1 to even numbers, 2 to odd ones, noting that negation flips parity */ bit = flip ^ (s.d[0] & 1); @@ -89,11 +91,6 @@ static int secp256k1_wnaf_const(int *wnaf, secp256k1_scalar s, int w) { global_sign = secp256k1_scalar_cond_negate(&s, flip); global_sign *= not_neg_one * 2 - 1; skew = 1 << bit; -#else - /* Otherwise, we just negate to force oddness */ - int is_even = secp256k1_scalar_is_even(&s); - global_sign = secp256k1_scalar_cond_negate(&s, is_even); -#endif /* 4 */ u_last = secp256k1_scalar_shr_int(&s, w); @@ -127,15 +124,13 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons secp256k1_ge tmpa; secp256k1_fe Z; + int skew_1; + int wnaf_1[1 + WNAF_SIZE(WINDOW_A - 1)]; #ifdef USE_ENDOMORPHISM secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; - int wnaf_1[1 + WNAF_SIZE(WINDOW_A - 1)]; int wnaf_lam[1 + WNAF_SIZE(WINDOW_A - 1)]; - int skew_1; int skew_lam; secp256k1_scalar q_1, q_lam; -#else - int wnaf[1 + WNAF_SIZE(WINDOW_A - 1)]; #endif int i; @@ -145,18 +140,10 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons #ifdef USE_ENDOMORPHISM /* split q into q_1 and q_lam (where q = q_1 + q_lam*lambda, and q_1 and q_lam are ~128 bit) */ secp256k1_scalar_split_lambda(&q_1, &q_lam, &sc); - /* no need for zero correction when using endomorphism since even - * numbers have one added to them anyway */ skew_1 = secp256k1_wnaf_const(wnaf_1, q_1, WINDOW_A - 1); skew_lam = secp256k1_wnaf_const(wnaf_lam, q_lam, WINDOW_A - 1); #else - int is_zero = secp256k1_scalar_is_zero(scalar); - /* the wNAF ladder cannot handle zero, so bump this to one .. we will - * correct the result after the fact */ - sc.d[0] += is_zero; - VERIFY_CHECK(!secp256k1_scalar_is_zero(&sc)); - - secp256k1_wnaf_const(wnaf, sc, WINDOW_A - 1); + skew_1 = secp256k1_wnaf_const(wnaf_1, sc, WINDOW_A - 1); #endif /* Calculate odd multiples of a. @@ -179,21 +166,15 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons /* first loop iteration (separated out so we can directly set r, rather * than having it start at infinity, get doubled several times, then have * its new value added to it) */ -#ifdef USE_ENDOMORPHISM i = wnaf_1[WNAF_SIZE(WINDOW_A - 1)]; VERIFY_CHECK(i != 0); ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, i, WINDOW_A); secp256k1_gej_set_ge(r, &tmpa); - +#ifdef USE_ENDOMORPHISM i = wnaf_lam[WNAF_SIZE(WINDOW_A - 1)]; VERIFY_CHECK(i != 0); ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, i, WINDOW_A); secp256k1_gej_add_ge(r, r, &tmpa); -#else - i = wnaf[WNAF_SIZE(WINDOW_A - 1)]; - VERIFY_CHECK(i != 0); - ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, i, WINDOW_A); - secp256k1_gej_set_ge(r, &tmpa); #endif /* remaining loop iterations */ for (i = WNAF_SIZE(WINDOW_A - 1) - 1; i >= 0; i--) { @@ -202,59 +183,57 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons for (j = 0; j < WINDOW_A - 1; ++j) { secp256k1_gej_double_nonzero(r, r, NULL); } -#ifdef USE_ENDOMORPHISM + n = wnaf_1[i]; ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); VERIFY_CHECK(n != 0); secp256k1_gej_add_ge(r, r, &tmpa); - +#ifdef USE_ENDOMORPHISM n = wnaf_lam[i]; ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A); VERIFY_CHECK(n != 0); secp256k1_gej_add_ge(r, r, &tmpa); -#else - n = wnaf[i]; - VERIFY_CHECK(n != 0); - ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); - secp256k1_gej_add_ge(r, r, &tmpa); #endif } secp256k1_fe_mul(&r->z, &r->z, &Z); -#ifdef USE_ENDOMORPHISM { /* Correct for wNAF skew */ secp256k1_ge correction = *a; secp256k1_ge_storage correction_1_stor; +#ifdef USE_ENDOMORPHISM secp256k1_ge_storage correction_lam_stor; +#endif secp256k1_ge_storage a2_stor; secp256k1_gej tmpj; secp256k1_gej_set_ge(&tmpj, &correction); secp256k1_gej_double_var(&tmpj, &tmpj, NULL); secp256k1_ge_set_gej(&correction, &tmpj); secp256k1_ge_to_storage(&correction_1_stor, a); +#ifdef USE_ENDOMORPHISM secp256k1_ge_to_storage(&correction_lam_stor, a); +#endif secp256k1_ge_to_storage(&a2_stor, &correction); /* For odd numbers this is 2a (so replace it), for even ones a (so no-op) */ secp256k1_ge_storage_cmov(&correction_1_stor, &a2_stor, skew_1 == 2); +#ifdef USE_ENDOMORPHISM secp256k1_ge_storage_cmov(&correction_lam_stor, &a2_stor, skew_lam == 2); +#endif /* Apply the correction */ secp256k1_ge_from_storage(&correction, &correction_1_stor); secp256k1_ge_neg(&correction, &correction); secp256k1_gej_add_ge(r, r, &correction); +#ifdef USE_ENDOMORPHISM secp256k1_ge_from_storage(&correction, &correction_lam_stor); secp256k1_ge_neg(&correction, &correction); secp256k1_ge_mul_lambda(&correction, &correction); secp256k1_gej_add_ge(r, r, &correction); - } -#else - /* correct for zero */ - r->infinity |= is_zero; #endif + } } #endif diff --git a/src/ecmult_impl.h b/src/ecmult_impl.h index e6e5f47188071..81ae08e100b6b 100644 --- a/src/ecmult_impl.h +++ b/src/ecmult_impl.h @@ -11,6 +11,8 @@ #include "scalar.h" #include "ecmult.h" +#include + /* optimal for 128-bit and 256-bit exponents. */ #define WINDOW_A 5 diff --git a/src/field.h b/src/field.h index 2d52af5e366c2..c5ba074244e6a 100644 --- a/src/field.h +++ b/src/field.h @@ -57,6 +57,9 @@ static int secp256k1_fe_is_zero(const secp256k1_fe *a); static int secp256k1_fe_is_odd(const secp256k1_fe *a); /** Compare two field elements. Requires magnitude-1 inputs. */ +static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b); + +/** Same as secp256k1_fe_equal, but may be variable time. */ static int secp256k1_fe_equal_var(const secp256k1_fe *a, const secp256k1_fe *b); /** Compare two field elements. Requires both inputs to be normalized */ @@ -92,7 +95,10 @@ static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a); * The input's magnitude can be at most 8. The output magnitude is 1 (but not * guaranteed to be normalized). The result in r will always be a square * itself. */ -static int secp256k1_fe_sqrt_var(secp256k1_fe *r, const secp256k1_fe *a); +static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a); + +/** Checks whether a field element is a quadratic residue. */ +static int secp256k1_fe_is_quad_var(const secp256k1_fe *a); /** Sets a field element to be the (modular) inverse of another. Requires the input's magnitude to be * at most 8. The output magnitude is 1 (but not guaranteed to be normalized). */ diff --git a/src/field_10x26_impl.h b/src/field_10x26_impl.h index 212cc5396af82..7b8c07960847e 100644 --- a/src/field_10x26_impl.h +++ b/src/field_10x26_impl.h @@ -7,8 +7,6 @@ #ifndef _SECP256K1_FIELD_REPR_IMPL_H_ #define _SECP256K1_FIELD_REPR_IMPL_H_ -#include -#include #include "util.h" #include "num.h" #include "field.h" @@ -429,6 +427,14 @@ SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_f #endif } +#if defined(USE_EXTERNAL_ASM) + +/* External assembler implementation */ +void secp256k1_fe_mul_inner(uint32_t *r, const uint32_t *a, const uint32_t * SECP256K1_RESTRICT b); +void secp256k1_fe_sqr_inner(uint32_t *r, const uint32_t *a); + +#else + #ifdef VERIFY #define VERIFY_BITS(x, n) VERIFY_CHECK(((x) >> (n)) == 0) #else @@ -1037,7 +1043,7 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint32_t *r, const uint32_t VERIFY_BITS(r[2], 27); /* [r9 r8 r7 r6 r5 r4 r3 r2 r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ } - +#endif static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) { #ifdef VERIFY diff --git a/src/field_5x52_impl.h b/src/field_5x52_impl.h index b31e24ab811b0..7a99eb21eccc6 100644 --- a/src/field_5x52_impl.h +++ b/src/field_5x52_impl.h @@ -11,7 +11,6 @@ #include "libsecp256k1-config.h" #endif -#include #include "util.h" #include "num.h" #include "field.h" diff --git a/src/field_5x52_int128_impl.h b/src/field_5x52_int128_impl.h index 9280bb5ea2216..0bf22bdd3ec88 100644 --- a/src/field_5x52_int128_impl.h +++ b/src/field_5x52_int128_impl.h @@ -137,7 +137,7 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t VERIFY_BITS(r[2], 52); VERIFY_BITS(c, 63); /* [d 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - c += d * R + t3;; + c += d * R + t3; VERIFY_BITS(c, 100); /* [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ r[3] = c & M; c >>= 52; @@ -259,7 +259,7 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t VERIFY_BITS(c, 63); /* [d 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - c += d * R + t3;; + c += d * R + t3; VERIFY_BITS(c, 100); /* [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ r[3] = c & M; c >>= 52; diff --git a/src/field_impl.h b/src/field_impl.h index 77f4aae2f9724..52cd902eb3873 100644 --- a/src/field_impl.h +++ b/src/field_impl.h @@ -21,6 +21,13 @@ #error "Please select field implementation" #endif +SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b) { + secp256k1_fe na; + secp256k1_fe_negate(&na, a, 1); + secp256k1_fe_add(&na, b); + return secp256k1_fe_normalizes_to_zero(&na); +} + SECP256K1_INLINE static int secp256k1_fe_equal_var(const secp256k1_fe *a, const secp256k1_fe *b) { secp256k1_fe na; secp256k1_fe_negate(&na, a, 1); @@ -28,7 +35,7 @@ SECP256K1_INLINE static int secp256k1_fe_equal_var(const secp256k1_fe *a, const return secp256k1_fe_normalizes_to_zero_var(&na); } -static int secp256k1_fe_sqrt_var(secp256k1_fe *r, const secp256k1_fe *a) { +static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a) { /** Given that p is congruent to 3 mod 4, we can compute the square root of * a mod p as the (p+1)/4'th power of a. * @@ -123,7 +130,7 @@ static int secp256k1_fe_sqrt_var(secp256k1_fe *r, const secp256k1_fe *a) { /* Check that a square root was actually calculated */ secp256k1_fe_sqr(&t1, r); - return secp256k1_fe_equal_var(&t1, a); + return secp256k1_fe_equal(&t1, a); } static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *a) { @@ -280,4 +287,29 @@ static void secp256k1_fe_inv_all_var(size_t len, secp256k1_fe *r, const secp256k r[0] = u; } +static int secp256k1_fe_is_quad_var(const secp256k1_fe *a) { +#ifndef USE_NUM_NONE + unsigned char b[32]; + secp256k1_num n; + secp256k1_num m; + /* secp256k1 field prime, value p defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */ + static const unsigned char prime[32] = { + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F + }; + + secp256k1_fe c = *a; + secp256k1_fe_normalize_var(&c); + secp256k1_fe_get_b32(b, &c); + secp256k1_num_set_bin(&n, b, 32); + secp256k1_num_set_bin(&m, prime, 32); + return secp256k1_num_jacobi(&n, &m) >= 0; +#else + secp256k1_fe r; + return secp256k1_fe_sqrt(&r, a); +#endif +} + #endif diff --git a/src/group.h b/src/group.h index ebfe1ca70cc15..d5157167447a7 100644 --- a/src/group.h +++ b/src/group.h @@ -47,7 +47,7 @@ static void secp256k1_ge_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const se * and a Y coordinate that is a quadratic residue modulo p. The return value * is true iff a coordinate with the given X coordinate exists. */ -static int secp256k1_ge_set_xquad_var(secp256k1_ge *r, const secp256k1_fe *x); +static int secp256k1_ge_set_xquad(secp256k1_ge *r, const secp256k1_fe *x); /** Set a group element (affine) equal to the point with the given X coordinate, and given oddness * for Y. Return value indicates whether the result is valid. */ @@ -94,6 +94,9 @@ static void secp256k1_gej_neg(secp256k1_gej *r, const secp256k1_gej *a); /** Check whether a group element is the point at infinity. */ static int secp256k1_gej_is_infinity(const secp256k1_gej *a); +/** Check whether a group element's y coordinate is a quadratic residue. */ +static int secp256k1_gej_has_quad_y_var(const secp256k1_gej *a); + /** Set r equal to the double of a. If rzr is not-NULL, r->z = a->z * *rzr (where infinity means an implicit z = 0). * a may not be zero. Constant time. */ static void secp256k1_gej_double_nonzero(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr); diff --git a/src/group_impl.h b/src/group_impl.h index 42e2f6e6ebf6c..3e9c4c410d413 100644 --- a/src/group_impl.h +++ b/src/group_impl.h @@ -7,8 +7,6 @@ #ifndef _SECP256K1_GROUP_IMPL_H_ #define _SECP256K1_GROUP_IMPL_H_ -#include - #include "num.h" #include "field.h" #include "group.h" @@ -165,7 +163,7 @@ static void secp256k1_ge_clear(secp256k1_ge *r) { secp256k1_fe_clear(&r->y); } -static int secp256k1_ge_set_xquad_var(secp256k1_ge *r, const secp256k1_fe *x) { +static int secp256k1_ge_set_xquad(secp256k1_ge *r, const secp256k1_fe *x) { secp256k1_fe x2, x3, c; r->x = *x; secp256k1_fe_sqr(&x2, x); @@ -173,11 +171,11 @@ static int secp256k1_ge_set_xquad_var(secp256k1_ge *r, const secp256k1_fe *x) { r->infinity = 0; secp256k1_fe_set_int(&c, 7); secp256k1_fe_add(&c, &x3); - return secp256k1_fe_sqrt_var(&r->y, &c); + return secp256k1_fe_sqrt(&r->y, &c); } static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd) { - if (!secp256k1_ge_set_xquad_var(r, x)) { + if (!secp256k1_ge_set_xquad(r, x)) { return 0; } secp256k1_fe_normalize_var(&r->y); @@ -251,11 +249,23 @@ static int secp256k1_ge_is_valid_var(const secp256k1_ge *a) { } static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr) { - /* Operations: 3 mul, 4 sqr, 0 normalize, 12 mul_int/add/negate */ + /* Operations: 3 mul, 4 sqr, 0 normalize, 12 mul_int/add/negate. + * + * Note that there is an implementation described at + * https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l + * which trades a multiply for a square, but in practice this is actually slower, + * mainly because it requires more normalizations. + */ secp256k1_fe t1,t2,t3,t4; /** For secp256k1, 2Q is infinity if and only if Q is infinity. This is because if 2Q = infinity, * Q must equal -Q, or that Q.y == -(Q.y), or Q.y is 0. For a point on y^2 = x^3 + 7 to have * y=0, x^3 must be -7 mod p. However, -7 has no cube root mod p. + * + * Having said this, if this function receives a point on a sextic twist, e.g. by + * a fault attack, it is possible for y to be 0. This happens for y^2 = x^3 + 6, + * since -6 does have a cube root mod p. For this point, this function will not set + * the infinity flag even though the point doubles to infinity, and the result + * point will be gibberish (z = 0 but infinity = 0). */ r->infinity = a->infinity; if (r->infinity) { @@ -623,4 +633,18 @@ static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a) { } #endif +static int secp256k1_gej_has_quad_y_var(const secp256k1_gej *a) { + secp256k1_fe yz; + + if (a->infinity) { + return 0; + } + + /* We rely on the fact that the Jacobi symbol of 1 / a->z^3 is the same as + * that of a->z. Thus a->y / a->z^3 is a quadratic residue iff a->y * a->z + is */ + secp256k1_fe_mul(&yz, &a->y, &a->z); + return secp256k1_fe_is_quad_var(&yz); +} + #endif diff --git a/src/hash.h b/src/hash.h index 0ff01e63fa737..fca98cab9f831 100644 --- a/src/hash.h +++ b/src/hash.h @@ -11,7 +11,7 @@ #include typedef struct { - uint32_t s[32]; + uint32_t s[8]; uint32_t buf[16]; /* In big endian */ size_t bytes; } secp256k1_sha256_t; diff --git a/src/hash_impl.h b/src/hash_impl.h index ae55df6d8a29a..b47e65f830a90 100644 --- a/src/hash_impl.h +++ b/src/hash_impl.h @@ -269,15 +269,13 @@ static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256 rng->retry = 0; } - +#undef BE32 #undef Round -#undef sigma0 #undef sigma1 -#undef Sigma0 +#undef sigma0 #undef Sigma1 -#undef Ch +#undef Sigma0 #undef Maj -#undef ReadBE32 -#undef WriteBE32 +#undef Ch #endif diff --git a/src/java/org/bitcoin/NativeSecp256k1.java b/src/java/org/bitcoin/NativeSecp256k1.java index 90a498eaa2c40..be67048fbed69 100644 --- a/src/java/org/bitcoin/NativeSecp256k1.java +++ b/src/java/org/bitcoin/NativeSecp256k1.java @@ -1,60 +1,478 @@ +/* + * Copyright 2013 Google Inc. + * Copyright 2014-2016 the libsecp256k1 contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.bitcoin; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.math.BigInteger; import com.google.common.base.Preconditions; - +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import static org.bitcoin.NativeSecp256k1Util.*; /** - * This class holds native methods to handle ECDSA verification. - * You can find an example library that can be used for this at - * https://github.com/sipa/secp256k1 + *

This class holds native methods to handle ECDSA verification.

+ * + *

You can find an example library that can be used for this at https://github.com/bitcoin/secp256k1

+ * + *

To build secp256k1 for use with bitcoinj, run + * `./configure --enable-jni --enable-experimental --enable-module-schnorr --enable-module-ecdh` + * and `make` then copy `.libs/libsecp256k1.so` to your system library path + * or point the JVM to the folder containing it with -Djava.library.path + *

*/ public class NativeSecp256k1 { - public static final boolean enabled; - static { - boolean isEnabled = true; - try { - System.loadLibrary("javasecp256k1"); - } catch (UnsatisfiedLinkError e) { - isEnabled = false; - } - enabled = isEnabled; - } - + + private static final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); + private static final Lock r = rwl.readLock(); + private static final Lock w = rwl.writeLock(); private static ThreadLocal nativeECDSABuffer = new ThreadLocal(); /** * Verifies the given secp256k1 signature in native code. * Calling when enabled == false is undefined (probably library not loaded) - * + * * @param data The data which was signed, must be exactly 32 bytes * @param signature The signature * @param pub The public key which did the signing */ - public static boolean verify(byte[] data, byte[] signature, byte[] pub) { + public static boolean verify(byte[] data, byte[] signature, byte[] pub) throws AssertFailException{ Preconditions.checkArgument(data.length == 32 && signature.length <= 520 && pub.length <= 520); ByteBuffer byteBuff = nativeECDSABuffer.get(); - if (byteBuff == null) { - byteBuff = ByteBuffer.allocateDirect(32 + 8 + 520 + 520); + if (byteBuff == null || byteBuff.capacity() < 520) { + byteBuff = ByteBuffer.allocateDirect(520); byteBuff.order(ByteOrder.nativeOrder()); nativeECDSABuffer.set(byteBuff); } byteBuff.rewind(); byteBuff.put(data); - byteBuff.putInt(signature.length); - byteBuff.putInt(pub.length); byteBuff.put(signature); byteBuff.put(pub); - return secp256k1_ecdsa_verify(byteBuff) == 1; + + byte[][] retByteArray; + + r.lock(); + try { + return secp256k1_ecdsa_verify(byteBuff, Secp256k1Context.getContext(), signature.length, pub.length) == 1; + } finally { + r.unlock(); + } + } + + /** + * libsecp256k1 Create an ECDSA signature. + * + * @param data Message hash, 32 bytes + * @param key Secret key, 32 bytes + * + * Return values + * @param sig byte array of signature + */ + public static byte[] sign(byte[] data, byte[] sec) throws AssertFailException{ + Preconditions.checkArgument(data.length == 32 && sec.length <= 32); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < 32 + 32) { + byteBuff = ByteBuffer.allocateDirect(32 + 32); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(data); + byteBuff.put(sec); + + byte[][] retByteArray; + + r.lock(); + try { + retByteArray = secp256k1_ecdsa_sign(byteBuff, Secp256k1Context.getContext()); + } finally { + r.unlock(); + } + + byte[] sigArr = retByteArray[0]; + int sigLen = new BigInteger(new byte[] { retByteArray[1][0] }).intValue(); + int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); + + assertEquals(sigArr.length, sigLen, "Got bad signature length."); + + return retVal == 0 ? new byte[0] : sigArr; + } + + /** + * libsecp256k1 Seckey Verify - returns 1 if valid, 0 if invalid + * + * @param seckey ECDSA Secret key, 32 bytes + */ + public static boolean secKeyVerify(byte[] seckey) { + Preconditions.checkArgument(seckey.length == 32); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < seckey.length) { + byteBuff = ByteBuffer.allocateDirect(seckey.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(seckey); + + r.lock(); + try { + return secp256k1_ec_seckey_verify(byteBuff,Secp256k1Context.getContext()) == 1; + } finally { + r.unlock(); + } + } + + + /** + * libsecp256k1 Compute Pubkey - computes public key from secret key + * + * @param seckey ECDSA Secret key, 32 bytes + * + * Return values + * @param pubkey ECDSA Public key, 33 or 65 bytes + */ + //TODO add a 'compressed' arg + public static byte[] computePubkey(byte[] seckey) throws AssertFailException{ + Preconditions.checkArgument(seckey.length == 32); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < seckey.length) { + byteBuff = ByteBuffer.allocateDirect(seckey.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(seckey); + + byte[][] retByteArray; + + r.lock(); + try { + retByteArray = secp256k1_ec_pubkey_create(byteBuff, Secp256k1Context.getContext()); + } finally { + r.unlock(); + } + + byte[] pubArr = retByteArray[0]; + int pubLen = new BigInteger(new byte[] { retByteArray[1][0] }).intValue(); + int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); + + assertEquals(pubArr.length, pubLen, "Got bad pubkey length."); + + return retVal == 0 ? new byte[0]: pubArr; + } + + /** + * libsecp256k1 Cleanup - This destroys the secp256k1 context object + * This should be called at the end of the program for proper cleanup of the context. + */ + public static synchronized void cleanup() { + w.lock(); + try { + secp256k1_destroy_context(Secp256k1Context.getContext()); + } finally { + w.unlock(); + } + } + + public static long cloneContext() { + r.lock(); + try { + return secp256k1_ctx_clone(Secp256k1Context.getContext()); + } finally { r.unlock(); } + } + + /** + * libsecp256k1 PrivKey Tweak-Mul - Tweak privkey by multiplying to it + * + * @param tweak some bytes to tweak with + * @param seckey 32-byte seckey + */ + public static byte[] privKeyTweakMul(byte[] privkey, byte[] tweak) throws AssertFailException{ + Preconditions.checkArgument(privkey.length == 32); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < privkey.length + tweak.length) { + byteBuff = ByteBuffer.allocateDirect(privkey.length + tweak.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(privkey); + byteBuff.put(tweak); + + byte[][] retByteArray; + r.lock(); + try { + retByteArray = secp256k1_privkey_tweak_mul(byteBuff,Secp256k1Context.getContext()); + } finally { + r.unlock(); + } + + byte[] privArr = retByteArray[0]; + + int privLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF; + int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); + + assertEquals(privArr.length, privLen, "Got bad pubkey length."); + + assertEquals(retVal, 1, "Failed return value check."); + + return privArr; } /** - * @param byteBuff signature format is byte[32] data, - * native-endian int signatureLength, native-endian int pubkeyLength, - * byte[signatureLength] signature, byte[pubkeyLength] pub - * @returns 1 for valid signature, anything else for invalid + * libsecp256k1 PrivKey Tweak-Add - Tweak privkey by adding to it + * + * @param tweak some bytes to tweak with + * @param seckey 32-byte seckey */ - private static native int secp256k1_ecdsa_verify(ByteBuffer byteBuff); + public static byte[] privKeyTweakAdd(byte[] privkey, byte[] tweak) throws AssertFailException{ + Preconditions.checkArgument(privkey.length == 32); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < privkey.length + tweak.length) { + byteBuff = ByteBuffer.allocateDirect(privkey.length + tweak.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(privkey); + byteBuff.put(tweak); + + byte[][] retByteArray; + r.lock(); + try { + retByteArray = secp256k1_privkey_tweak_add(byteBuff,Secp256k1Context.getContext()); + } finally { + r.unlock(); + } + + byte[] privArr = retByteArray[0]; + + int privLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF; + int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); + + assertEquals(privArr.length, privLen, "Got bad pubkey length."); + + assertEquals(retVal, 1, "Failed return value check."); + + return privArr; + } + + /** + * libsecp256k1 PubKey Tweak-Add - Tweak pubkey by adding to it + * + * @param tweak some bytes to tweak with + * @param pubkey 32-byte seckey + */ + public static byte[] pubKeyTweakAdd(byte[] pubkey, byte[] tweak) throws AssertFailException{ + Preconditions.checkArgument(pubkey.length == 33 || pubkey.length == 65); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < pubkey.length + tweak.length) { + byteBuff = ByteBuffer.allocateDirect(pubkey.length + tweak.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(pubkey); + byteBuff.put(tweak); + + byte[][] retByteArray; + r.lock(); + try { + retByteArray = secp256k1_pubkey_tweak_add(byteBuff,Secp256k1Context.getContext(), pubkey.length); + } finally { + r.unlock(); + } + + byte[] pubArr = retByteArray[0]; + + int pubLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF; + int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); + + assertEquals(pubArr.length, pubLen, "Got bad pubkey length."); + + assertEquals(retVal, 1, "Failed return value check."); + + return pubArr; + } + + /** + * libsecp256k1 PubKey Tweak-Mul - Tweak pubkey by multiplying to it + * + * @param tweak some bytes to tweak with + * @param pubkey 32-byte seckey + */ + public static byte[] pubKeyTweakMul(byte[] pubkey, byte[] tweak) throws AssertFailException{ + Preconditions.checkArgument(pubkey.length == 33 || pubkey.length == 65); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < pubkey.length + tweak.length) { + byteBuff = ByteBuffer.allocateDirect(pubkey.length + tweak.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(pubkey); + byteBuff.put(tweak); + + byte[][] retByteArray; + r.lock(); + try { + retByteArray = secp256k1_pubkey_tweak_mul(byteBuff,Secp256k1Context.getContext(), pubkey.length); + } finally { + r.unlock(); + } + + byte[] pubArr = retByteArray[0]; + + int pubLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF; + int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); + + assertEquals(pubArr.length, pubLen, "Got bad pubkey length."); + + assertEquals(retVal, 1, "Failed return value check."); + + return pubArr; + } + + /** + * libsecp256k1 create ECDH secret - constant time ECDH calculation + * + * @param seckey byte array of secret key used in exponentiaion + * @param pubkey byte array of public key used in exponentiaion + */ + public static byte[] createECDHSecret(byte[] seckey, byte[] pubkey) throws AssertFailException{ + Preconditions.checkArgument(seckey.length <= 32 && pubkey.length <= 65); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < 32 + pubkey.length) { + byteBuff = ByteBuffer.allocateDirect(32 + pubkey.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(seckey); + byteBuff.put(pubkey); + + byte[][] retByteArray; + r.lock(); + try { + retByteArray = secp256k1_ecdh(byteBuff, Secp256k1Context.getContext(), pubkey.length); + } finally { + r.unlock(); + } + + byte[] resArr = retByteArray[0]; + int retVal = new BigInteger(new byte[] { retByteArray[1][0] }).intValue(); + + assertEquals(resArr.length, 32, "Got bad result length."); + assertEquals(retVal, 1, "Failed return value check."); + + return resArr; + } + + /** + * libsecp256k1 randomize - updates the context randomization + * + * @param seed 32-byte random seed + */ + public static synchronized boolean randomize(byte[] seed) throws AssertFailException{ + Preconditions.checkArgument(seed.length == 32 || seed == null); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < seed.length) { + byteBuff = ByteBuffer.allocateDirect(seed.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(seed); + + w.lock(); + try { + return secp256k1_context_randomize(byteBuff, Secp256k1Context.getContext()) == 1; + } finally { + w.unlock(); + } + } + + public static byte[] schnorrSign(byte[] data, byte[] sec) throws AssertFailException { + Preconditions.checkArgument(data.length == 32 && sec.length <= 32); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null) { + byteBuff = ByteBuffer.allocateDirect(32 + 32); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(data); + byteBuff.put(sec); + + byte[][] retByteArray; + + r.lock(); + try { + retByteArray = secp256k1_schnorr_sign(byteBuff, Secp256k1Context.getContext()); + } finally { + r.unlock(); + } + + byte[] sigArr = retByteArray[0]; + int retVal = new BigInteger(new byte[] { retByteArray[1][0] }).intValue(); + + assertEquals(sigArr.length, 64, "Got bad signature length."); + + return retVal == 0 ? new byte[0] : sigArr; + } + + private static native long secp256k1_ctx_clone(long context); + + private static native int secp256k1_context_randomize(ByteBuffer byteBuff, long context); + + private static native byte[][] secp256k1_privkey_tweak_add(ByteBuffer byteBuff, long context); + + private static native byte[][] secp256k1_privkey_tweak_mul(ByteBuffer byteBuff, long context); + + private static native byte[][] secp256k1_pubkey_tweak_add(ByteBuffer byteBuff, long context, int pubLen); + + private static native byte[][] secp256k1_pubkey_tweak_mul(ByteBuffer byteBuff, long context, int pubLen); + + private static native void secp256k1_destroy_context(long context); + + private static native int secp256k1_ecdsa_verify(ByteBuffer byteBuff, long context, int sigLen, int pubLen); + + private static native byte[][] secp256k1_ecdsa_sign(ByteBuffer byteBuff, long context); + + private static native int secp256k1_ec_seckey_verify(ByteBuffer byteBuff, long context); + + private static native byte[][] secp256k1_ec_pubkey_create(ByteBuffer byteBuff, long context); + + private static native byte[][] secp256k1_ec_pubkey_parse(ByteBuffer byteBuff, long context, int inputLen); + + private static native byte[][] secp256k1_schnorr_sign(ByteBuffer byteBuff, long context); + + private static native byte[][] secp256k1_ecdh(ByteBuffer byteBuff, long context, int inputLen); + } diff --git a/src/java/org/bitcoin/NativeSecp256k1Test.java b/src/java/org/bitcoin/NativeSecp256k1Test.java new file mode 100644 index 0000000000000..f18ce95810d13 --- /dev/null +++ b/src/java/org/bitcoin/NativeSecp256k1Test.java @@ -0,0 +1,247 @@ +package org.bitcoin; + +import com.google.common.io.BaseEncoding; +import java.util.Arrays; +import java.math.BigInteger; +import javax.xml.bind.DatatypeConverter; +import static org.bitcoin.NativeSecp256k1Util.*; + +/** + * This class holds test cases defined for testing this library. + */ +public class NativeSecp256k1Test { + + //TODO improve comments/add more tests + /** + * This tests verify() for a valid signature + */ + public static void testVerifyPos() throws AssertFailException{ + boolean result = false; + byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()); //sha256hash of "testing" + byte[] sig = BaseEncoding.base16().lowerCase().decode("3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589".toLowerCase()); + byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); + + result = NativeSecp256k1.verify( data, sig, pub); + assertEquals( result, true , "testVerifyPos"); + } + + /** + * This tests verify() for a non-valid signature + */ + public static void testVerifyNeg() throws AssertFailException{ + boolean result = false; + byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A91".toLowerCase()); //sha256hash of "testing" + byte[] sig = BaseEncoding.base16().lowerCase().decode("3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589".toLowerCase()); + byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); + + result = NativeSecp256k1.verify( data, sig, pub); + //System.out.println(" TEST " + new BigInteger(1, resultbytes).toString(16)); + assertEquals( result, false , "testVerifyNeg"); + } + + /** + * This tests secret key verify() for a valid secretkey + */ + public static void testSecKeyVerifyPos() throws AssertFailException{ + boolean result = false; + byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); + + result = NativeSecp256k1.secKeyVerify( sec ); + //System.out.println(" TEST " + new BigInteger(1, resultbytes).toString(16)); + assertEquals( result, true , "testSecKeyVerifyPos"); + } + + /** + * This tests secret key verify() for a invalid secretkey + */ + public static void testSecKeyVerifyNeg() throws AssertFailException{ + boolean result = false; + byte[] sec = BaseEncoding.base16().lowerCase().decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".toLowerCase()); + + result = NativeSecp256k1.secKeyVerify( sec ); + //System.out.println(" TEST " + new BigInteger(1, resultbytes).toString(16)); + assertEquals( result, false , "testSecKeyVerifyNeg"); + } + + /** + * This tests public key create() for a valid secretkey + */ + public static void testPubKeyCreatePos() throws AssertFailException{ + byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); + + byte[] resultArr = NativeSecp256k1.computePubkey( sec); + String pubkeyString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( pubkeyString , "04C591A8FF19AC9C4E4E5793673B83123437E975285E7B442F4EE2654DFFCA5E2D2103ED494718C697AC9AEBCFD19612E224DB46661011863ED2FC54E71861E2A6" , "testPubKeyCreatePos"); + } + + /** + * This tests public key create() for a invalid secretkey + */ + public static void testPubKeyCreateNeg() throws AssertFailException{ + byte[] sec = BaseEncoding.base16().lowerCase().decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".toLowerCase()); + + byte[] resultArr = NativeSecp256k1.computePubkey( sec); + String pubkeyString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( pubkeyString, "" , "testPubKeyCreateNeg"); + } + + /** + * This tests sign() for a valid secretkey + */ + public static void testSignPos() throws AssertFailException{ + + byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()); //sha256hash of "testing" + byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); + + byte[] resultArr = NativeSecp256k1.sign(data, sec); + String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( sigString, "30440220182A108E1448DC8F1FB467D06A0F3BB8EA0533584CB954EF8DA112F1D60E39A202201C66F36DA211C087F3AF88B50EDF4F9BDAA6CF5FD6817E74DCA34DB12390C6E9" , "testSignPos"); + } + + /** + * This tests sign() for a invalid secretkey + */ + public static void testSignNeg() throws AssertFailException{ + byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()); //sha256hash of "testing" + byte[] sec = BaseEncoding.base16().lowerCase().decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".toLowerCase()); + + byte[] resultArr = NativeSecp256k1.sign(data, sec); + String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( sigString, "" , "testSignNeg"); + } + + /** + * This tests private key tweak-add + */ + public static void testPrivKeyTweakAdd_1() throws AssertFailException { + byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); + byte[] data = BaseEncoding.base16().lowerCase().decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3".toLowerCase()); //sha256hash of "tweak" + + byte[] resultArr = NativeSecp256k1.privKeyTweakAdd( sec , data ); + String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( sigString , "A168571E189E6F9A7E2D657A4B53AE99B909F7E712D1C23CED28093CD57C88F3" , "testPrivKeyAdd_1"); + } + + /** + * This tests private key tweak-mul + */ + public static void testPrivKeyTweakMul_1() throws AssertFailException { + byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); + byte[] data = BaseEncoding.base16().lowerCase().decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3".toLowerCase()); //sha256hash of "tweak" + + byte[] resultArr = NativeSecp256k1.privKeyTweakMul( sec , data ); + String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( sigString , "97F8184235F101550F3C71C927507651BD3F1CDB4A5A33B8986ACF0DEE20FFFC" , "testPrivKeyMul_1"); + } + + /** + * This tests private key tweak-add uncompressed + */ + public static void testPrivKeyTweakAdd_2() throws AssertFailException { + byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); + byte[] data = BaseEncoding.base16().lowerCase().decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3".toLowerCase()); //sha256hash of "tweak" + + byte[] resultArr = NativeSecp256k1.pubKeyTweakAdd( pub , data ); + String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( sigString , "0411C6790F4B663CCE607BAAE08C43557EDC1A4D11D88DFCB3D841D0C6A941AF525A268E2A863C148555C48FB5FBA368E88718A46E205FABC3DBA2CCFFAB0796EF" , "testPrivKeyAdd_2"); + } + + /** + * This tests private key tweak-mul uncompressed + */ + public static void testPrivKeyTweakMul_2() throws AssertFailException { + byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); + byte[] data = BaseEncoding.base16().lowerCase().decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3".toLowerCase()); //sha256hash of "tweak" + + byte[] resultArr = NativeSecp256k1.pubKeyTweakMul( pub , data ); + String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( sigString , "04E0FE6FE55EBCA626B98A807F6CAF654139E14E5E3698F01A9A658E21DC1D2791EC060D4F412A794D5370F672BC94B722640B5F76914151CFCA6E712CA48CC589" , "testPrivKeyMul_2"); + } + + /** + * This tests seed randomization + */ + public static void testRandomize() throws AssertFailException { + byte[] seed = BaseEncoding.base16().lowerCase().decode("A441B15FE9A3CF56661190A0B93B9DEC7D04127288CC87250967CF3B52894D11".toLowerCase()); //sha256hash of "random" + boolean result = NativeSecp256k1.randomize(seed); + assertEquals( result, true, "testRandomize"); + } + + /** + * This tests signSchnorr() for a valid secretkey + */ + public static void testSchnorrSign() throws AssertFailException{ + + byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()); //sha256hash of "testing" + byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); + + byte[] resultArr = NativeSecp256k1.schnorrSign(data, sec); + String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( sigString, "C5E929AA058B982048760422D3B563749B7D0E50C5EBD8CD2FFC23214BD6A2F1B072C13880997EBA847CF20F2F90FCE07C1CA33A890A4127095A351127F8D95F" , "testSchnorrSign"); + } + + /** + * This tests signSchnorr() for a valid secretkey + */ + public static void testCreateECDHSecret() throws AssertFailException{ + + byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); + byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); + + byte[] resultArr = NativeSecp256k1.createECDHSecret(sec, pub); + String ecdhString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( ecdhString, "2A2A67007A926E6594AF3EB564FC74005B37A9C8AEF2033C4552051B5C87F043" , "testCreateECDHSecret"); + } + + public static void main(String[] args) throws AssertFailException{ + + + System.out.println("\n libsecp256k1 enabled: " + Secp256k1Context.isEnabled() + "\n"); + + assertEquals( Secp256k1Context.isEnabled(), true, "isEnabled" ); + + //Test verify() success/fail + testVerifyPos(); + testVerifyNeg(); + + //Test secKeyVerify() success/fail + testSecKeyVerifyPos(); + testSecKeyVerifyNeg(); + + //Test computePubkey() success/fail + testPubKeyCreatePos(); + testPubKeyCreateNeg(); + + //Test sign() success/fail + testSignPos(); + testSignNeg(); + + //Test Schnorr (partial support) //TODO + testSchnorrSign(); + //testSchnorrVerify + //testSchnorrRecovery + + //Test privKeyTweakAdd() 1 + testPrivKeyTweakAdd_1(); + + //Test privKeyTweakMul() 2 + testPrivKeyTweakMul_1(); + + //Test privKeyTweakAdd() 3 + testPrivKeyTweakAdd_2(); + + //Test privKeyTweakMul() 4 + testPrivKeyTweakMul_2(); + + //Test randomize() + testRandomize(); + + //Test ECDH + testCreateECDHSecret(); + + NativeSecp256k1.cleanup(); + + System.out.println(" All tests passed." ); + + } +} diff --git a/src/java/org/bitcoin/NativeSecp256k1Util.java b/src/java/org/bitcoin/NativeSecp256k1Util.java new file mode 100644 index 0000000000000..04732ba044363 --- /dev/null +++ b/src/java/org/bitcoin/NativeSecp256k1Util.java @@ -0,0 +1,45 @@ +/* + * Copyright 2014-2016 the libsecp256k1 contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.bitcoin; + +public class NativeSecp256k1Util{ + + public static void assertEquals( int val, int val2, String message ) throws AssertFailException{ + if( val != val2 ) + throw new AssertFailException("FAIL: " + message); + } + + public static void assertEquals( boolean val, boolean val2, String message ) throws AssertFailException{ + if( val != val2 ) + throw new AssertFailException("FAIL: " + message); + else + System.out.println("PASS: " + message); + } + + public static void assertEquals( String val, String val2, String message ) throws AssertFailException{ + if( !val.equals(val2) ) + throw new AssertFailException("FAIL: " + message); + else + System.out.println("PASS: " + message); + } + + public static class AssertFailException extends Exception { + public AssertFailException(String message) { + super( message ); + } + } +} diff --git a/src/java/org/bitcoin/Secp256k1Context.java b/src/java/org/bitcoin/Secp256k1Context.java new file mode 100644 index 0000000000000..216c986a8b564 --- /dev/null +++ b/src/java/org/bitcoin/Secp256k1Context.java @@ -0,0 +1,51 @@ +/* + * Copyright 2014-2016 the libsecp256k1 contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.bitcoin; + +/** + * This class holds the context reference used in native methods + * to handle ECDSA operations. + */ +public class Secp256k1Context { + private static final boolean enabled; //true if the library is loaded + private static final long context; //ref to pointer to context obj + + static { //static initializer + boolean isEnabled = true; + long contextRef = -1; + try { + System.loadLibrary("secp256k1"); + contextRef = secp256k1_init_context(); + } catch (UnsatisfiedLinkError e) { + System.out.println("UnsatisfiedLinkError: " + e.toString()); + isEnabled = false; + } + enabled = isEnabled; + context = contextRef; + } + + public static boolean isEnabled() { + return enabled; + } + + public static long getContext() { + if(!enabled) return -1; //sanity check + return context; + } + + private static native long secp256k1_init_context(); +} diff --git a/src/java/org_bitcoin_NativeSecp256k1.c b/src/java/org_bitcoin_NativeSecp256k1.c index bb4cd707280a6..dba9524dd4cc2 100644 --- a/src/java/org_bitcoin_NativeSecp256k1.c +++ b/src/java/org_bitcoin_NativeSecp256k1.c @@ -1,23 +1,411 @@ +#include +#include +#include #include "org_bitcoin_NativeSecp256k1.h" #include "include/secp256k1.h" +#include "include/secp256k1_ecdh.h" +#include "include/secp256k1_recovery.h" +#include "include/secp256k1_schnorr.h" -JNIEXPORT jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1verify - (JNIEnv* env, jclass classObject, jobject byteBufferObject) + +SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ctx_1clone + (JNIEnv* env, jclass classObject, jlong ctx_l) +{ + const secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + + jlong ctx_clone_l = (uintptr_t) secp256k1_context_clone(ctx); + + (void)classObject;(void)env; + + return ctx_clone_l; + +} + +SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1context_1randomize + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + + const unsigned char* seed = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + + (void)classObject; + + return secp256k1_context_randomize(ctx, seed); + +} + +SECP256K1_API void JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1destroy_1context + (JNIEnv* env, jclass classObject, jlong ctx_l) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + + secp256k1_context_destroy(ctx); + + (void)classObject;(void)env; +} + +SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1verify + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint siglen, jint publen) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + + unsigned char* data = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + const unsigned char* sigdata = { (unsigned char*) (data + 32) }; + const unsigned char* pubdata = { (unsigned char*) (data + siglen + 32) }; + + secp256k1_ecdsa_signature sig; + secp256k1_pubkey pubkey; + + int ret = secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigdata, siglen); + + if( ret ) { + ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pubdata, publen); + + if( ret ) { + ret = secp256k1_ecdsa_verify(ctx, &sig, data, &pubkey); + } + } + + (void)classObject; + + return ret; +} + +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1sign + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + unsigned char* data = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + unsigned char* secKey = (unsigned char*) (data + 32); + + jobjectArray retArray; + jbyteArray sigArray, intsByteArray; + unsigned char intsarray[2]; + + secp256k1_ecdsa_signature sig[72]; + + int ret = secp256k1_ecdsa_sign(ctx, sig, data, secKey, NULL, NULL ); + + unsigned char outputSer[72]; + size_t outputLen = 72; + + if( ret ) { + int ret2 = secp256k1_ecdsa_signature_serialize_der(ctx,outputSer, &outputLen, sig ); (void)ret2; + } + + intsarray[0] = outputLen; + intsarray[1] = ret; + + retArray = (*env)->NewObjectArray(env, 2, + (*env)->FindClass(env, "[B"), + (*env)->NewByteArray(env, 1)); + + sigArray = (*env)->NewByteArray(env, outputLen); + (*env)->SetByteArrayRegion(env, sigArray, 0, outputLen, (jbyte*)outputSer); + (*env)->SetObjectArrayElement(env, retArray, 0, sigArray); + + intsByteArray = (*env)->NewByteArray(env, 2); + (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); + (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); + + (void)classObject; + + return retArray; +} + +SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1seckey_1verify + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + unsigned char* secKey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + + (void)classObject; + + return secp256k1_ec_seckey_verify(ctx, secKey); +} + +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1pubkey_1create + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + const unsigned char* secKey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + + secp256k1_pubkey pubkey; + + jobjectArray retArray; + jbyteArray pubkeyArray, intsByteArray; + unsigned char intsarray[2]; + + int ret = secp256k1_ec_pubkey_create(ctx, &pubkey, secKey); + + unsigned char outputSer[65]; + size_t outputLen = 65; + + if( ret ) { + int ret2 = secp256k1_ec_pubkey_serialize(ctx,outputSer, &outputLen, &pubkey,SECP256K1_EC_UNCOMPRESSED );(void)ret2; + } + + intsarray[0] = outputLen; + intsarray[1] = ret; + + retArray = (*env)->NewObjectArray(env, 2, + (*env)->FindClass(env, "[B"), + (*env)->NewByteArray(env, 1)); + + pubkeyArray = (*env)->NewByteArray(env, outputLen); + (*env)->SetByteArrayRegion(env, pubkeyArray, 0, outputLen, (jbyte*)outputSer); + (*env)->SetObjectArrayElement(env, retArray, 0, pubkeyArray); + + intsByteArray = (*env)->NewByteArray(env, 2); + (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); + (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); + + (void)classObject; + + return retArray; + +} + +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1privkey_1tweak_1add + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + unsigned char* privkey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + const unsigned char* tweak = (unsigned char*) (privkey + 32); + + jobjectArray retArray; + jbyteArray privArray, intsByteArray; + unsigned char intsarray[2]; + + int privkeylen = 32; + + int ret = secp256k1_ec_privkey_tweak_add(ctx, privkey, tweak); + + intsarray[0] = privkeylen; + intsarray[1] = ret; + + retArray = (*env)->NewObjectArray(env, 2, + (*env)->FindClass(env, "[B"), + (*env)->NewByteArray(env, 1)); + + privArray = (*env)->NewByteArray(env, privkeylen); + (*env)->SetByteArrayRegion(env, privArray, 0, privkeylen, (jbyte*)privkey); + (*env)->SetObjectArrayElement(env, retArray, 0, privArray); + + intsByteArray = (*env)->NewByteArray(env, 2); + (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); + (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); + + (void)classObject; + + return retArray; +} + +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1privkey_1tweak_1mul + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + unsigned char* privkey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + const unsigned char* tweak = (unsigned char*) (privkey + 32); + + jobjectArray retArray; + jbyteArray privArray, intsByteArray; + unsigned char intsarray[2]; + + int privkeylen = 32; + + int ret = secp256k1_ec_privkey_tweak_mul(ctx, privkey, tweak); + + intsarray[0] = privkeylen; + intsarray[1] = ret; + + retArray = (*env)->NewObjectArray(env, 2, + (*env)->FindClass(env, "[B"), + (*env)->NewByteArray(env, 1)); + + privArray = (*env)->NewByteArray(env, privkeylen); + (*env)->SetByteArrayRegion(env, privArray, 0, privkeylen, (jbyte*)privkey); + (*env)->SetObjectArrayElement(env, retArray, 0, privArray); + + intsByteArray = (*env)->NewByteArray(env, 2); + (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); + (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); + + (void)classObject; + + return retArray; +} + +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1pubkey_1tweak_1add + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; +/* secp256k1_pubkey* pubkey = (secp256k1_pubkey*) (*env)->GetDirectBufferAddress(env, byteBufferObject);*/ + unsigned char* pkey = (*env)->GetDirectBufferAddress(env, byteBufferObject); + const unsigned char* tweak = (unsigned char*) (pkey + publen); + + jobjectArray retArray; + jbyteArray pubArray, intsByteArray; + unsigned char intsarray[2]; + unsigned char outputSer[65]; + size_t outputLen = 65; + + secp256k1_pubkey pubkey; + int ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pkey, publen); + + if( ret ) { + ret = secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, tweak); + } + + if( ret ) { + int ret2 = secp256k1_ec_pubkey_serialize(ctx,outputSer, &outputLen, &pubkey,SECP256K1_EC_UNCOMPRESSED );(void)ret2; + } + + intsarray[0] = outputLen; + intsarray[1] = ret; + + retArray = (*env)->NewObjectArray(env, 2, + (*env)->FindClass(env, "[B"), + (*env)->NewByteArray(env, 1)); + + pubArray = (*env)->NewByteArray(env, outputLen); + (*env)->SetByteArrayRegion(env, pubArray, 0, outputLen, (jbyte*)outputSer); + (*env)->SetObjectArrayElement(env, retArray, 0, pubArray); + + intsByteArray = (*env)->NewByteArray(env, 2); + (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); + (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); + + (void)classObject; + + return retArray; +} + +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1pubkey_1tweak_1mul + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen) { - unsigned char* data = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); - int sigLen = *((int*)(data + 32)); - int pubLen = *((int*)(data + 32 + 4)); + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + unsigned char* pkey = (*env)->GetDirectBufferAddress(env, byteBufferObject); + const unsigned char* tweak = (unsigned char*) (pkey + publen); + + jobjectArray retArray; + jbyteArray pubArray, intsByteArray; + unsigned char intsarray[2]; + unsigned char outputSer[65]; + size_t outputLen = 65; + + secp256k1_pubkey pubkey; + int ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pkey, publen); + + if ( ret ) { + ret = secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, tweak); + } + + if( ret ) { + int ret2 = secp256k1_ec_pubkey_serialize(ctx,outputSer, &outputLen, &pubkey,SECP256K1_EC_UNCOMPRESSED );(void)ret2; + } + + intsarray[0] = outputLen; + intsarray[1] = ret; + + retArray = (*env)->NewObjectArray(env, 2, + (*env)->FindClass(env, "[B"), + (*env)->NewByteArray(env, 1)); + + pubArray = (*env)->NewByteArray(env, outputLen); + (*env)->SetByteArrayRegion(env, pubArray, 0, outputLen, (jbyte*)outputSer); + (*env)->SetObjectArrayElement(env, retArray, 0, pubArray); - return secp256k1_ecdsa_verify(data, 32, data+32+8, sigLen, data+32+8+sigLen, pubLen); + intsByteArray = (*env)->NewByteArray(env, 2); + (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); + (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); + + (void)classObject; + + return retArray; } -static void __javasecp256k1_attach(void) __attribute__((constructor)); -static void __javasecp256k1_detach(void) __attribute__((destructor)); +SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1pubkey_1combine + (JNIEnv * env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint numkeys) +{ + (void)classObject;(void)env;(void)byteBufferObject;(void)ctx_l;(void)numkeys; -static void __javasecp256k1_attach(void) { - secp256k1_start(SECP256K1_START_VERIFY); + return 0; } -static void __javasecp256k1_detach(void) { - secp256k1_stop(); +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1schnorr_1sign + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + unsigned char* data = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + unsigned char* secKey = (unsigned char*) (data + 32); + + jobjectArray retArray; + jbyteArray sigArray, intsByteArray; + unsigned char intsarray[1]; + unsigned char sig[64]; + + int ret = secp256k1_schnorr_sign(ctx, sig, data, secKey, NULL, NULL); + + intsarray[0] = ret; + + retArray = (*env)->NewObjectArray(env, 2, + (*env)->FindClass(env, "[B"), + (*env)->NewByteArray(env, 1)); + + sigArray = (*env)->NewByteArray(env, 64); + (*env)->SetByteArrayRegion(env, sigArray, 0, 64, (jbyte*)sig); + (*env)->SetObjectArrayElement(env, retArray, 0, sigArray); + + intsByteArray = (*env)->NewByteArray(env, 1); + (*env)->SetByteArrayRegion(env, intsByteArray, 0, 1, (jbyte*)intsarray); + (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); + + (void)classObject; + + return retArray; +} + +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdh + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + const unsigned char* secdata = (*env)->GetDirectBufferAddress(env, byteBufferObject); + const unsigned char* pubdata = (const unsigned char*) (secdata + 32); + + jobjectArray retArray; + jbyteArray outArray, intsByteArray; + unsigned char intsarray[1]; + secp256k1_pubkey pubkey; + unsigned char nonce_res[32]; + size_t outputLen = 32; + + int ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pubdata, publen); + + if (ret) { + ret = secp256k1_ecdh( + ctx, + nonce_res, + &pubkey, + secdata + ); + } + + intsarray[0] = ret; + + retArray = (*env)->NewObjectArray(env, 2, + (*env)->FindClass(env, "[B"), + (*env)->NewByteArray(env, 1)); + + outArray = (*env)->NewByteArray(env, outputLen); + (*env)->SetByteArrayRegion(env, outArray, 0, 32, (jbyte*)nonce_res); + (*env)->SetObjectArrayElement(env, retArray, 0, outArray); + + intsByteArray = (*env)->NewByteArray(env, 1); + (*env)->SetByteArrayRegion(env, intsByteArray, 0, 1, (jbyte*)intsarray); + (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); + + (void)classObject; + + return retArray; } diff --git a/src/java/org_bitcoin_NativeSecp256k1.h b/src/java/org_bitcoin_NativeSecp256k1.h index d7fb004fa841e..4125a1f5233be 100644 --- a/src/java/org_bitcoin_NativeSecp256k1.h +++ b/src/java/org_bitcoin_NativeSecp256k1.h @@ -1,5 +1,6 @@ /* DO NOT EDIT THIS FILE - it is machine generated */ #include +#include "include/secp256k1.h" /* Header for class org_bitcoin_NativeSecp256k1 */ #ifndef _Included_org_bitcoin_NativeSecp256k1 @@ -7,13 +8,118 @@ #ifdef __cplusplus extern "C" { #endif +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_ctx_clone + * Signature: (J)J + */ +SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ctx_1clone + (JNIEnv *, jclass, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_context_randomize + * Signature: (Ljava/nio/ByteBuffer;J)I + */ +SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1context_1randomize + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_privkey_tweak_add + * Signature: (Ljava/nio/ByteBuffer;J)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1privkey_1tweak_1add + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_privkey_tweak_mul + * Signature: (Ljava/nio/ByteBuffer;J)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1privkey_1tweak_1mul + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_pubkey_tweak_add + * Signature: (Ljava/nio/ByteBuffer;JI)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1pubkey_1tweak_1add + (JNIEnv *, jclass, jobject, jlong, jint); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_pubkey_tweak_mul + * Signature: (Ljava/nio/ByteBuffer;JI)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1pubkey_1tweak_1mul + (JNIEnv *, jclass, jobject, jlong, jint); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_destroy_context + * Signature: (J)V + */ +SECP256K1_API void JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1destroy_1context + (JNIEnv *, jclass, jlong); + /* * Class: org_bitcoin_NativeSecp256k1 * Method: secp256k1_ecdsa_verify - * Signature: (Ljava/nio/ByteBuffer;)I + * Signature: (Ljava/nio/ByteBuffer;JII)I + */ +SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1verify + (JNIEnv *, jclass, jobject, jlong, jint, jint); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_ecdsa_sign + * Signature: (Ljava/nio/ByteBuffer;J)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1sign + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_ec_seckey_verify + * Signature: (Ljava/nio/ByteBuffer;J)I + */ +SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1seckey_1verify + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_ec_pubkey_create + * Signature: (Ljava/nio/ByteBuffer;J)[[B */ -JNIEXPORT jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1verify - (JNIEnv *, jclass, jobject); +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1pubkey_1create + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_ec_pubkey_parse + * Signature: (Ljava/nio/ByteBuffer;JI)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1pubkey_1parse + (JNIEnv *, jclass, jobject, jlong, jint); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_schnorr_sign + * Signature: (Ljava/nio/ByteBuffer;JI)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1schnorr_1sign + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_ecdh + * Signature: (Ljava/nio/ByteBuffer;JI)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdh + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen); + #ifdef __cplusplus } diff --git a/src/java/org_bitcoin_Secp256k1Context.c b/src/java/org_bitcoin_Secp256k1Context.c new file mode 100644 index 0000000000000..a52939e7e7dac --- /dev/null +++ b/src/java/org_bitcoin_Secp256k1Context.c @@ -0,0 +1,15 @@ +#include +#include +#include "org_bitcoin_Secp256k1Context.h" +#include "include/secp256k1.h" + +SECP256K1_API jlong JNICALL Java_org_bitcoin_Secp256k1Context_secp256k1_1init_1context + (JNIEnv* env, jclass classObject) +{ + secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + + (void)classObject;(void)env; + + return (uintptr_t)ctx; +} + diff --git a/src/java/org_bitcoin_Secp256k1Context.h b/src/java/org_bitcoin_Secp256k1Context.h new file mode 100644 index 0000000000000..0d2bc84b7f3fd --- /dev/null +++ b/src/java/org_bitcoin_Secp256k1Context.h @@ -0,0 +1,22 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +#include "include/secp256k1.h" +/* Header for class org_bitcoin_Secp256k1Context */ + +#ifndef _Included_org_bitcoin_Secp256k1Context +#define _Included_org_bitcoin_Secp256k1Context +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_bitcoin_Secp256k1Context + * Method: secp256k1_init_context + * Signature: ()J + */ +SECP256K1_API jlong JNICALL Java_org_bitcoin_Secp256k1Context_secp256k1_1init_1context + (JNIEnv *, jclass); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/modules/ecdh/Makefile.am.include b/src/modules/ecdh/Makefile.am.include index 670b9c1152e75..e3088b469790b 100644 --- a/src/modules/ecdh/Makefile.am.include +++ b/src/modules/ecdh/Makefile.am.include @@ -4,5 +4,5 @@ noinst_HEADERS += src/modules/ecdh/tests_impl.h if USE_BENCHMARK noinst_PROGRAMS += bench_ecdh bench_ecdh_SOURCES = src/bench_ecdh.c -bench_ecdh_LDADD = libsecp256k1.la $(SECP_LIBS) +bench_ecdh_LDADD = libsecp256k1.la $(SECP_LIBS) $(COMMON_LIB) endif diff --git a/src/modules/recovery/Makefile.am.include b/src/modules/recovery/Makefile.am.include index 5de3ea33ea5e1..bf23c26e71c5d 100644 --- a/src/modules/recovery/Makefile.am.include +++ b/src/modules/recovery/Makefile.am.include @@ -4,5 +4,5 @@ noinst_HEADERS += src/modules/recovery/tests_impl.h if USE_BENCHMARK noinst_PROGRAMS += bench_recover bench_recover_SOURCES = src/bench_recover.c -bench_recover_LDADD = libsecp256k1.la $(SECP_LIBS) +bench_recover_LDADD = libsecp256k1.la $(SECP_LIBS) $(COMMON_LIB) endif diff --git a/src/modules/schnorr/Makefile.am.include b/src/modules/schnorr/Makefile.am.include index b3bfa7d5cc49e..f1af8e83255fd 100644 --- a/src/modules/schnorr/Makefile.am.include +++ b/src/modules/schnorr/Makefile.am.include @@ -6,5 +6,5 @@ noinst_HEADERS += src/modules/schnorr/tests_impl.h if USE_BENCHMARK noinst_PROGRAMS += bench_schnorr_verify bench_schnorr_verify_SOURCES = src/bench_schnorr_verify.c -bench_schnorr_verify_LDADD = libsecp256k1.la $(SECP_LIBS) +bench_schnorr_verify_LDADD = libsecp256k1.la $(SECP_LIBS) $(COMMON_LIB) endif diff --git a/src/num.h b/src/num.h index ebfa71eb44bda..7bb9c5be8cf5a 100644 --- a/src/num.h +++ b/src/num.h @@ -32,6 +32,9 @@ static void secp256k1_num_set_bin(secp256k1_num *r, const unsigned char *a, unsi /** Compute a modular inverse. The input must be less than the modulus. */ static void secp256k1_num_mod_inverse(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *m); +/** Compute the jacobi symbol (a|b). b must be positive and odd. */ +static int secp256k1_num_jacobi(const secp256k1_num *a, const secp256k1_num *b); + /** Compare the absolute value of two numbers. */ static int secp256k1_num_cmp(const secp256k1_num *a, const secp256k1_num *b); @@ -57,6 +60,9 @@ static void secp256k1_num_shift(secp256k1_num *r, int bits); /** Check whether a number is zero. */ static int secp256k1_num_is_zero(const secp256k1_num *a); +/** Check whether a number is one. */ +static int secp256k1_num_is_one(const secp256k1_num *a); + /** Check whether a number is strictly negative. */ static int secp256k1_num_is_neg(const secp256k1_num *a); diff --git a/src/num_gmp_impl.h b/src/num_gmp_impl.h index 7b6a89719ab14..3a46495eeac7d 100644 --- a/src/num_gmp_impl.h +++ b/src/num_gmp_impl.h @@ -144,6 +144,32 @@ static void secp256k1_num_mod_inverse(secp256k1_num *r, const secp256k1_num *a, memset(v, 0, sizeof(v)); } +static int secp256k1_num_jacobi(const secp256k1_num *a, const secp256k1_num *b) { + int ret; + mpz_t ga, gb; + secp256k1_num_sanity(a); + secp256k1_num_sanity(b); + VERIFY_CHECK(!b->neg && (b->limbs > 0) && (b->data[0] & 1)); + + mpz_inits(ga, gb, NULL); + + mpz_import(gb, b->limbs, -1, sizeof(mp_limb_t), 0, 0, b->data); + mpz_import(ga, a->limbs, -1, sizeof(mp_limb_t), 0, 0, a->data); + if (a->neg) { + mpz_neg(ga, ga); + } + + ret = mpz_jacobi(ga, gb); + + mpz_clears(ga, gb, NULL); + + return ret; +} + +static int secp256k1_num_is_one(const secp256k1_num *a) { + return (a->limbs == 1 && a->data[0] == 1); +} + static int secp256k1_num_is_zero(const secp256k1_num *a) { return (a->limbs == 1 && a->data[0] == 0); } diff --git a/src/scalar_impl.h b/src/scalar_impl.h index 88ea97de863e9..c5baf4df413e0 100644 --- a/src/scalar_impl.h +++ b/src/scalar_impl.h @@ -7,8 +7,6 @@ #ifndef _SECP256K1_SCALAR_IMPL_H_ #define _SECP256K1_SCALAR_IMPL_H_ -#include - #include "group.h" #include "scalar.h" diff --git a/src/secp256k1.c b/src/secp256k1.c index 62d192baeb388..7973d60c36a81 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -4,8 +4,6 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#define SECP256K1_BUILD (1) - #include "include/secp256k1.h" #include "util.h" @@ -152,7 +150,6 @@ static void secp256k1_pubkey_save(secp256k1_pubkey* pubkey, secp256k1_ge* ge) { int secp256k1_ec_pubkey_parse(const secp256k1_context* ctx, secp256k1_pubkey* pubkey, const unsigned char *input, size_t inputlen) { secp256k1_ge Q; - (void)ctx; VERIFY_CHECK(ctx != NULL); ARG_CHECK(pubkey != NULL); memset(pubkey, 0, sizeof(*pubkey)); @@ -170,7 +167,6 @@ int secp256k1_ec_pubkey_serialize(const secp256k1_context* ctx, unsigned char *o size_t len; int ret = 0; - (void)ctx; VERIFY_CHECK(ctx != NULL); ARG_CHECK(outputlen != NULL); ARG_CHECK(*outputlen >= ((flags & SECP256K1_FLAGS_BIT_COMPRESSION) ? 33 : 65)); @@ -216,7 +212,7 @@ static void secp256k1_ecdsa_signature_save(secp256k1_ecdsa_signature* sig, const int secp256k1_ecdsa_signature_parse_der(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) { secp256k1_scalar r, s; - (void)ctx; + VERIFY_CHECK(ctx != NULL); ARG_CHECK(sig != NULL); ARG_CHECK(input != NULL); @@ -234,7 +230,7 @@ int secp256k1_ecdsa_signature_parse_compact(const secp256k1_context* ctx, secp25 int ret = 1; int overflow = 0; - (void)ctx; + VERIFY_CHECK(ctx != NULL); ARG_CHECK(sig != NULL); ARG_CHECK(input64 != NULL); @@ -253,7 +249,7 @@ int secp256k1_ecdsa_signature_parse_compact(const secp256k1_context* ctx, secp25 int secp256k1_ecdsa_signature_serialize_der(const secp256k1_context* ctx, unsigned char *output, size_t *outputlen, const secp256k1_ecdsa_signature* sig) { secp256k1_scalar r, s; - (void)ctx; + VERIFY_CHECK(ctx != NULL); ARG_CHECK(output != NULL); ARG_CHECK(outputlen != NULL); ARG_CHECK(sig != NULL); @@ -265,7 +261,7 @@ int secp256k1_ecdsa_signature_serialize_der(const secp256k1_context* ctx, unsign int secp256k1_ecdsa_signature_serialize_compact(const secp256k1_context* ctx, unsigned char *output64, const secp256k1_ecdsa_signature* sig) { secp256k1_scalar r, s; - (void)ctx; + VERIFY_CHECK(ctx != NULL); ARG_CHECK(output64 != NULL); ARG_CHECK(sig != NULL); @@ -398,7 +394,6 @@ int secp256k1_ec_seckey_verify(const secp256k1_context* ctx, const unsigned char int overflow; VERIFY_CHECK(ctx != NULL); ARG_CHECK(seckey != NULL); - (void)ctx; secp256k1_scalar_set_b32(&sec, seckey, &overflow); ret = !overflow && !secp256k1_scalar_is_zero(&sec); @@ -437,7 +432,6 @@ int secp256k1_ec_privkey_tweak_add(const secp256k1_context* ctx, unsigned char * VERIFY_CHECK(ctx != NULL); ARG_CHECK(seckey != NULL); ARG_CHECK(tweak != NULL); - (void)ctx; secp256k1_scalar_set_b32(&term, tweak, &overflow); secp256k1_scalar_set_b32(&sec, seckey, NULL); @@ -485,7 +479,6 @@ int secp256k1_ec_privkey_tweak_mul(const secp256k1_context* ctx, unsigned char * VERIFY_CHECK(ctx != NULL); ARG_CHECK(seckey != NULL); ARG_CHECK(tweak != NULL); - (void)ctx; secp256k1_scalar_set_b32(&factor, tweak, &overflow); secp256k1_scalar_set_b32(&sec, seckey, NULL); diff --git a/src/tests.c b/src/tests.c index 687a5f2fdd801..b32cb90813718 100644 --- a/src/tests.c +++ b/src/tests.c @@ -473,6 +473,8 @@ void test_num_negate(void) { } void test_num_add_sub(void) { + int i; + secp256k1_scalar s; secp256k1_num n1; secp256k1_num n2; secp256k1_num n1p2, n2p1, n1m2, n2m1; @@ -498,6 +500,110 @@ void test_num_add_sub(void) { CHECK(!secp256k1_num_eq(&n2p1, &n1)); secp256k1_num_sub(&n2p1, &n2p1, &n2); /* n2p1 = R2 + R1 - R2 = R1 */ CHECK(secp256k1_num_eq(&n2p1, &n1)); + + /* check is_one */ + secp256k1_scalar_set_int(&s, 1); + secp256k1_scalar_get_num(&n1, &s); + CHECK(secp256k1_num_is_one(&n1)); + /* check that 2^n + 1 is never 1 */ + secp256k1_scalar_get_num(&n2, &s); + for (i = 0; i < 250; ++i) { + secp256k1_num_add(&n1, &n1, &n1); /* n1 *= 2 */ + secp256k1_num_add(&n1p2, &n1, &n2); /* n1p2 = n1 + 1 */ + CHECK(!secp256k1_num_is_one(&n1p2)); + } +} + +void test_num_mod(void) { + int i; + secp256k1_scalar s; + secp256k1_num order, n; + + /* check that 0 mod anything is 0 */ + random_scalar_order_test(&s); + secp256k1_scalar_get_num(&order, &s); + secp256k1_scalar_set_int(&s, 0); + secp256k1_scalar_get_num(&n, &s); + secp256k1_num_mod(&n, &order); + CHECK(secp256k1_num_is_zero(&n)); + + /* check that anything mod 1 is 0 */ + secp256k1_scalar_set_int(&s, 1); + secp256k1_scalar_get_num(&order, &s); + secp256k1_scalar_get_num(&n, &s); + secp256k1_num_mod(&n, &order); + CHECK(secp256k1_num_is_zero(&n)); + + /* check that increasing the number past 2^256 does not break this */ + random_scalar_order_test(&s); + secp256k1_scalar_get_num(&n, &s); + /* multiply by 2^8, which'll test this case with high probability */ + for (i = 0; i < 8; ++i) { + secp256k1_num_add(&n, &n, &n); + } + secp256k1_num_mod(&n, &order); + CHECK(secp256k1_num_is_zero(&n)); +} + +void test_num_jacobi(void) { + secp256k1_scalar sqr; + secp256k1_scalar small; + secp256k1_scalar five; /* five is not a quadratic residue */ + secp256k1_num order, n; + int i; + /* squares mod 5 are 1, 4 */ + const int jacobi5[10] = { 0, 1, -1, -1, 1, 0, 1, -1, -1, 1 }; + + /* check some small values with 5 as the order */ + secp256k1_scalar_set_int(&five, 5); + secp256k1_scalar_get_num(&order, &five); + for (i = 0; i < 10; ++i) { + secp256k1_scalar_set_int(&small, i); + secp256k1_scalar_get_num(&n, &small); + CHECK(secp256k1_num_jacobi(&n, &order) == jacobi5[i]); + } + + /** test large values with 5 as group order */ + secp256k1_scalar_get_num(&order, &five); + /* we first need a scalar which is not a multiple of 5 */ + do { + secp256k1_num fiven; + random_scalar_order_test(&sqr); + secp256k1_scalar_get_num(&fiven, &five); + secp256k1_scalar_get_num(&n, &sqr); + secp256k1_num_mod(&n, &fiven); + } while (secp256k1_num_is_zero(&n)); + /* next force it to be a residue. 2 is a nonresidue mod 5 so we can + * just multiply by two, i.e. add the number to itself */ + if (secp256k1_num_jacobi(&n, &order) == -1) { + secp256k1_num_add(&n, &n, &n); + } + + /* test residue */ + CHECK(secp256k1_num_jacobi(&n, &order) == 1); + /* test nonresidue */ + secp256k1_num_add(&n, &n, &n); + CHECK(secp256k1_num_jacobi(&n, &order) == -1); + + /** test with secp group order as order */ + secp256k1_scalar_order_get_num(&order); + random_scalar_order_test(&sqr); + secp256k1_scalar_sqr(&sqr, &sqr); + /* test residue */ + secp256k1_scalar_get_num(&n, &sqr); + CHECK(secp256k1_num_jacobi(&n, &order) == 1); + /* test nonresidue */ + secp256k1_scalar_mul(&sqr, &sqr, &five); + secp256k1_scalar_get_num(&n, &sqr); + CHECK(secp256k1_num_jacobi(&n, &order) == -1); + /* test multiple of the order*/ + CHECK(secp256k1_num_jacobi(&order, &order) == 0); + + /* check one less than the order */ + secp256k1_scalar_set_int(&small, 1); + secp256k1_scalar_get_num(&n, &small); + secp256k1_num_sub(&n, &order, &n); + CHECK(secp256k1_num_jacobi(&n, &order) == 1); /* sage confirms this is 1 */ } void run_num_smalltests(void) { @@ -505,6 +611,8 @@ void run_num_smalltests(void) { for (i = 0; i < 100*count; i++) { test_num_negate(); test_num_add_sub(); + test_num_mod(); + test_num_jacobi(); } } #endif @@ -689,6 +797,10 @@ void scalar_test(void) { secp256k1_scalar_inverse(&inv, &inv); /* Inverting one must result in one. */ CHECK(secp256k1_scalar_is_one(&inv)); +#ifndef USE_NUM_NONE + secp256k1_scalar_get_num(&invnum, &inv); + CHECK(secp256k1_num_is_one(&invnum)); +#endif } } @@ -855,7 +967,7 @@ void run_scalar_tests(void) { secp256k1_scalar zzv; #endif int overflow; - unsigned char chal[32][2][32] = { + unsigned char chal[33][2][32] = { {{0xff, 0xff, 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, @@ -1111,9 +1223,17 @@ void run_scalar_tests(void) { {0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xc7, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff}} + 0xff, 0xc7, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff}}, + {{0x82, 0xc9, 0xfa, 0xb0, 0x68, 0x04, 0xa0, 0x00, + 0x82, 0xc9, 0xfa, 0xb0, 0x68, 0x04, 0xa0, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x03, 0xfb, + 0xfa, 0x8a, 0x7d, 0xdf, 0x13, 0x86, 0xe2, 0x03}, + {0x82, 0xc9, 0xfa, 0xb0, 0x68, 0x04, 0xa0, 0x00, + 0x82, 0xc9, 0xfa, 0xb0, 0x68, 0x04, 0xa0, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x03, 0xfb, + 0xfa, 0x8a, 0x7d, 0xdf, 0x13, 0x86, 0xe2, 0x03}} }; - unsigned char res[32][2][32] = { + unsigned char res[33][2][32] = { {{0x0c, 0x3b, 0x0a, 0xca, 0x8d, 0x1a, 0x2f, 0xb9, 0x8a, 0x7b, 0x53, 0x5a, 0x1f, 0xc5, 0x22, 0xa1, 0x07, 0x2a, 0x48, 0xea, 0x02, 0xeb, 0xb3, 0xd6, @@ -1369,10 +1489,18 @@ void run_scalar_tests(void) { {0xe4, 0xf1, 0x23, 0x84, 0xe1, 0xb5, 0x9d, 0xf2, 0xb8, 0x73, 0x8b, 0x45, 0x2b, 0x35, 0x46, 0x38, 0x10, 0x2b, 0x50, 0xf8, 0x8b, 0x35, 0xcd, 0x34, - 0xc8, 0x0e, 0xf6, 0xdb, 0x09, 0x35, 0xf0, 0xda}} + 0xc8, 0x0e, 0xf6, 0xdb, 0x09, 0x35, 0xf0, 0xda}}, + {{0xdb, 0x21, 0x5c, 0x8d, 0x83, 0x1d, 0xb3, 0x34, + 0xc7, 0x0e, 0x43, 0xa1, 0x58, 0x79, 0x67, 0x13, + 0x1e, 0x86, 0x5d, 0x89, 0x63, 0xe6, 0x0a, 0x46, + 0x5c, 0x02, 0x97, 0x1b, 0x62, 0x43, 0x86, 0xf5}, + {0xdb, 0x21, 0x5c, 0x8d, 0x83, 0x1d, 0xb3, 0x34, + 0xc7, 0x0e, 0x43, 0xa1, 0x58, 0x79, 0x67, 0x13, + 0x1e, 0x86, 0x5d, 0x89, 0x63, 0xe6, 0x0a, 0x46, + 0x5c, 0x02, 0x97, 0x1b, 0x62, 0x43, 0x86, 0xf5}} }; secp256k1_scalar_set_int(&one, 1); - for (i = 0; i < 32; i++) { + for (i = 0; i < 33; i++) { secp256k1_scalar_set_b32(&x, chal[i][0], &overflow); CHECK(!overflow); secp256k1_scalar_set_b32(&y, chal[i][1], &overflow); @@ -1446,7 +1574,7 @@ void random_fe_non_zero(secp256k1_fe *nz) { void random_fe_non_square(secp256k1_fe *ns) { secp256k1_fe r; random_fe_non_zero(ns); - if (secp256k1_fe_sqrt_var(&r, ns)) { + if (secp256k1_fe_sqrt(&r, ns)) { secp256k1_fe_negate(ns, ns, 1); } } @@ -1641,7 +1769,7 @@ void run_sqr(void) { void test_sqrt(const secp256k1_fe *a, const secp256k1_fe *k) { secp256k1_fe r1, r2; - int v = secp256k1_fe_sqrt_var(&r1, a); + int v = secp256k1_fe_sqrt(&r1, a); CHECK((v == 0) == (k == NULL)); if (k != NULL) { @@ -1951,8 +2079,8 @@ void test_add_neg_y_diff_x(void) { * of the sum to be wrong (since infinity has no xy coordinates). * HOWEVER, if the x-coordinates are different, infinity is the * wrong answer, and such degeneracies are exposed. This is the - * root of https://github.com/bitcoin/secp256k1/issues/257 which - * this test is a regression test for. + * root of https://github.com/bitcoin-core/secp256k1/issues/257 + * which this test is a regression test for. * * These points were generated in sage as * # secp256k1 params @@ -2051,15 +2179,16 @@ void run_ec_combine(void) { void test_group_decompress(const secp256k1_fe* x) { /* The input itself, normalized. */ secp256k1_fe fex = *x; - secp256k1_fe tmp; + secp256k1_fe fez; /* Results of set_xquad_var, set_xo_var(..., 0), set_xo_var(..., 1). */ secp256k1_ge ge_quad, ge_even, ge_odd; + secp256k1_gej gej_quad; /* Return values of the above calls. */ int res_quad, res_even, res_odd; secp256k1_fe_normalize_var(&fex); - res_quad = secp256k1_ge_set_xquad_var(&ge_quad, &fex); + res_quad = secp256k1_ge_set_xquad(&ge_quad, &fex); res_even = secp256k1_ge_set_xo_var(&ge_even, &fex, 0); res_odd = secp256k1_ge_set_xo_var(&ge_odd, &fex, 1); @@ -2085,13 +2214,29 @@ void test_group_decompress(const secp256k1_fe* x) { CHECK(secp256k1_fe_equal_var(&ge_odd.x, x)); /* Check that the Y coordinate result in ge_quad is a square. */ - CHECK(secp256k1_fe_sqrt_var(&tmp, &ge_quad.y)); - secp256k1_fe_sqr(&tmp, &tmp); - CHECK(secp256k1_fe_equal_var(&tmp, &ge_quad.y)); + CHECK(secp256k1_fe_is_quad_var(&ge_quad.y)); /* Check odd/even Y in ge_odd, ge_even. */ CHECK(secp256k1_fe_is_odd(&ge_odd.y)); CHECK(!secp256k1_fe_is_odd(&ge_even.y)); + + /* Check secp256k1_gej_has_quad_y_var. */ + secp256k1_gej_set_ge(&gej_quad, &ge_quad); + CHECK(secp256k1_gej_has_quad_y_var(&gej_quad)); + do { + random_fe_test(&fez); + } while (secp256k1_fe_is_zero(&fez)); + secp256k1_gej_rescale(&gej_quad, &fez); + CHECK(secp256k1_gej_has_quad_y_var(&gej_quad)); + secp256k1_gej_neg(&gej_quad, &gej_quad); + CHECK(!secp256k1_gej_has_quad_y_var(&gej_quad)); + do { + random_fe_test(&fez); + } while (secp256k1_fe_is_zero(&fez)); + secp256k1_gej_rescale(&gej_quad, &fez); + CHECK(!secp256k1_gej_has_quad_y_var(&gej_quad)); + secp256k1_gej_neg(&gej_quad, &gej_quad); + CHECK(secp256k1_gej_has_quad_y_var(&gej_quad)); } } @@ -2383,9 +2528,7 @@ void test_constant_wnaf(const secp256k1_scalar *number, int w) { secp256k1_scalar x, shift; int wnaf[256] = {0}; int i; -#ifdef USE_ENDOMORPHISM int skew; -#endif secp256k1_scalar num = *number; secp256k1_scalar_set_int(&x, 0); @@ -2395,10 +2538,8 @@ void test_constant_wnaf(const secp256k1_scalar *number, int w) { for (i = 0; i < 16; ++i) { secp256k1_scalar_shr_int(&num, 8); } - skew = secp256k1_wnaf_const(wnaf, num, w); -#else - secp256k1_wnaf_const(wnaf, num, w); #endif + skew = secp256k1_wnaf_const(wnaf, num, w); for (i = WNAF_SIZE(w); i >= 0; --i) { secp256k1_scalar t; @@ -2417,10 +2558,8 @@ void test_constant_wnaf(const secp256k1_scalar *number, int w) { } secp256k1_scalar_add(&x, &x, &t); } -#ifdef USE_ENDOMORPHISM - /* Skew num because when encoding 128-bit numbers as odd we use an offset */ + /* Skew num because when encoding numbers as odd we use an offset */ secp256k1_scalar_cadd_bit(&num, skew == 2, 1); -#endif CHECK(secp256k1_scalar_eq(&x, &num)); } @@ -3484,12 +3623,14 @@ void run_ecdsa_end_to_end(void) { int test_ecdsa_der_parse(const unsigned char *sig, size_t siglen, int certainly_der, int certainly_not_der) { static const unsigned char zeroes[32] = {0}; +#ifdef ENABLE_OPENSSL_TESTS static const unsigned char max_scalar[32] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x40 }; +#endif int ret = 0; @@ -3607,13 +3748,13 @@ static void assign_big_endian(unsigned char *ptr, size_t ptrlen, uint32_t val) { static void damage_array(unsigned char *sig, size_t *len) { int pos; int action = secp256k1_rand_bits(3); - if (action < 1) { + if (action < 1 && *len > 3) { /* Delete a byte. */ pos = secp256k1_rand_int(*len); memmove(sig + pos, sig + pos + 1, *len - pos - 1); (*len)--; return; - } else if (action < 2) { + } else if (action < 2 && *len < 2048) { /* Insert a byte. */ pos = secp256k1_rand_int(1 + *len); memmove(sig + pos + 1, sig + pos, *len - pos); @@ -3785,6 +3926,7 @@ void run_ecdsa_der_parse(void) { int certainly_der = 0; int certainly_not_der = 0; random_ber_signature(buffer, &buflen, &certainly_der, &certainly_not_der); + CHECK(buflen <= 2048); for (j = 0; j < 16; j++) { int ret = 0; if (j > 0) { From c1582d5d8595ce8814a86dffdb0fa647e4100862 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 16 Aug 2016 11:48:54 +0200 Subject: [PATCH 0724/1802] qa: Remove duplicate `hash160` implementation `hash160` is defined in `test_framework.script`, so there is no need to define it here again. --- qa/rpc-tests/p2p-fullblocktest.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/qa/rpc-tests/p2p-fullblocktest.py b/qa/rpc-tests/p2p-fullblocktest.py index 17fd40ef1dffd..9aee81164f088 100755 --- a/qa/rpc-tests/p2p-fullblocktest.py +++ b/qa/rpc-tests/p2p-fullblocktest.py @@ -25,9 +25,6 @@ def __init__(self, tx = CTransaction(), n = -1): each test. ''' -def hash160(s): - return hashlib.new('ripemd160', sha256(s)).digest() - # Use this class for tests that require behavior other than normal "mininode" behavior. # For now, it is used to serialize a bloated varint (b64). class CBrokenBlock(CBlock): From d2c5d044d00ec805957ab246a7863d83ca075805 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 16 Aug 2016 15:35:45 +0200 Subject: [PATCH 0725/1802] Precompute sighashes Original version by Nicolas Dorier. Precomputing version by Pieter Wuille. --- src/main.cpp | 22 ++++++++------ src/main.h | 9 ++++-- src/script/bitcoinconsensus.cpp | 4 +-- src/script/interpreter.cpp | 54 ++++++++++++++++++++++----------- src/script/interpreter.h | 13 ++++++-- src/script/sigcache.h | 2 +- src/test/script_P2SH_tests.cpp | 6 ++-- src/test/transaction_tests.cpp | 6 ++-- 8 files changed, 78 insertions(+), 38 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index db457f6f53d57..7f48ccbae1de4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1492,12 +1492,13 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C // Check against previous transactions // This is done last to help prevent CPU exhaustion denial-of-service attacks. - if (!CheckInputs(tx, state, view, true, scriptVerifyFlags, true)) { + CachedHashes cachedHashes(tx); + if (!CheckInputs(tx, state, view, true, scriptVerifyFlags, true, cachedHashes)) { // SCRIPT_VERIFY_CLEANSTACK requires SCRIPT_VERIFY_WITNESS, so we // need to turn both off, and compare against just turning off CLEANSTACK // to see if the failure is specifically due to witness validation. - if (CheckInputs(tx, state, view, true, scriptVerifyFlags & ~(SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_CLEANSTACK), true) && - !CheckInputs(tx, state, view, true, scriptVerifyFlags & ~SCRIPT_VERIFY_CLEANSTACK, true)) { + if (CheckInputs(tx, state, view, true, scriptVerifyFlags & ~(SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_CLEANSTACK), true, cachedHashes) && + !CheckInputs(tx, state, view, true, scriptVerifyFlags & ~SCRIPT_VERIFY_CLEANSTACK, true, cachedHashes)) { // Only the witness is wrong, so the transaction itself may be fine. state.SetCorruptionPossible(); } @@ -1513,7 +1514,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C // There is a similar check in CreateNewBlock() to prevent creating // invalid blocks, however allowing such transactions into the mempool // can be exploited as a DoS attack. - if (!CheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true)) + if (!CheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, cachedHashes)) { return error("%s: BUG! PLEASE REPORT THIS! ConnectInputs failed against MANDATORY but not STANDARD flags %s, %s", __func__, hash.ToString(), FormatStateMessage(state)); @@ -1910,7 +1911,7 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight) bool CScriptCheck::operator()() { const CScript &scriptSig = ptxTo->vin[nIn].scriptSig; const CScriptWitness *witness = (nIn < ptxTo->wit.vtxinwit.size()) ? &ptxTo->wit.vtxinwit[nIn].scriptWitness : NULL; - if (!VerifyScript(scriptSig, scriptPubKey, witness, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, amount, cacheStore), &error)) { + if (!VerifyScript(scriptSig, scriptPubKey, witness, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, amount, cacheStore, *cachedHashes), &error)) { return false; } return true; @@ -1969,7 +1970,7 @@ bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoins } }// namespace Consensus -bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, std::vector *pvChecks) +bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, CachedHashes& cachedHashes, std::vector *pvChecks) { if (!tx.IsCoinBase()) { @@ -1996,7 +1997,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi assert(coins); // Verify signature - CScriptCheck check(*coins, tx, i, flags, cacheStore); + CScriptCheck check(*coins, tx, i, flags, cacheStore, &cachedHashes); if (pvChecks) { pvChecks->push_back(CScriptCheck()); check.swap(pvChecks->back()); @@ -2009,7 +2010,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi // avoid splitting the network between upgraded and // non-upgraded nodes. CScriptCheck check2(*coins, tx, i, - flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore); + flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore, &cachedHashes); if (check2()) return state.Invalid(false, REJECT_NONSTANDARD, strprintf("non-mandatory-script-verify-flag (%s)", ScriptErrorString(check.GetScriptError()))); } @@ -2405,6 +2406,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin std::vector > vPos; vPos.reserve(block.vtx.size()); blockundo.vtxundo.reserve(block.vtx.size() - 1); + std::vector cachedHashes; + cachedHashes.reserve(block.vtx.size()); // Required so that pointers to individual CachedHashes don't get invalidated for (unsigned int i = 0; i < block.vtx.size(); i++) { const CTransaction &tx = block.vtx[i]; @@ -2451,13 +2454,14 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return state.DoS(100, error("ConnectBlock(): too many sigops"), REJECT_INVALID, "bad-blk-sigops"); + cachedHashes.emplace_back(tx); if (!tx.IsCoinBase()) { nFees += view.GetValueIn(tx)-tx.GetValueOut(); std::vector vChecks; bool fCacheResults = fJustCheck; /* Don't cache results if we're actually connecting blocks (still consult the cache, though) */ - if (!CheckInputs(tx, state, view, fScriptChecks, flags, fCacheResults, nScriptCheckThreads ? &vChecks : NULL)) + if (!CheckInputs(tx, state, view, fScriptChecks, flags, fCacheResults, cachedHashes[i], nScriptCheckThreads ? &vChecks : NULL)) return error("ConnectBlock(): CheckInputs on %s failed with %s", tx.GetHash().ToString(), FormatStateMessage(state)); control.Add(vChecks); diff --git a/src/main.h b/src/main.h index d4d70c018027d..fbf66c0481166 100644 --- a/src/main.h +++ b/src/main.h @@ -38,6 +38,7 @@ class CScriptCheck; class CTxMemPool; class CValidationInterface; class CValidationState; +class CachedHashes; struct CNodeStateStats; struct LockPoints; @@ -347,7 +348,7 @@ int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& i * instead of being performed inline. */ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &view, bool fScriptChecks, - unsigned int flags, bool cacheStore, std::vector *pvChecks = NULL); + unsigned int flags, bool cacheStore, CachedHashes& cachedHashes, std::vector *pvChecks = NULL); /** Apply the effects of this transaction on the UTXO set represented by view */ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight); @@ -421,12 +422,13 @@ class CScriptCheck unsigned int nFlags; bool cacheStore; ScriptError error; + CachedHashes *cachedHashes; public: CScriptCheck(): amount(0), ptxTo(0), nIn(0), nFlags(0), cacheStore(false), error(SCRIPT_ERR_UNKNOWN_ERROR) {} - CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn) : + CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn, CachedHashes* cachedHashesIn) : scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey), amount(txFromIn.vout[txToIn.vin[nInIn].prevout.n].nValue), - ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR) { } + ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR), cachedHashes(cachedHashesIn) { } bool operator()(); @@ -438,6 +440,7 @@ class CScriptCheck std::swap(nFlags, check.nFlags); std::swap(cacheStore, check.cacheStore); std::swap(error, check.error); + std::swap(cachedHashes, check.cachedHashes); } ScriptError GetScriptError() const { return error; } diff --git a/src/script/bitcoinconsensus.cpp b/src/script/bitcoinconsensus.cpp index 62fd9031f853a..01a8babb679eb 100644 --- a/src/script/bitcoinconsensus.cpp +++ b/src/script/bitcoinconsensus.cpp @@ -84,8 +84,8 @@ static int verify_script(const unsigned char *scriptPubKey, unsigned int scriptP // Regardless of the verification result, the tx did not error. set_error(err, bitcoinconsensus_ERR_OK); - - return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), nIn < tx.wit.vtxinwit.size() ? &tx.wit.vtxinwit[nIn].scriptWitness : NULL, flags, TransactionSignatureChecker(&tx, nIn, amount), NULL); + CachedHashes cachedHashes(tx); + return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), nIn < tx.wit.vtxinwit.size() ? &tx.wit.vtxinwit[nIn].scriptWitness : NULL, flags, TransactionSignatureChecker(&tx, nIn, amount, cachedHashes), NULL); } catch (const std::exception&) { return set_error(err, bitcoinconsensus_ERR_TX_DESERIALIZE); // Error deserializing } diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index bc027e9f0c113..459feaa0f4826 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1108,9 +1108,40 @@ class CTransactionSignatureSerializer { } }; +uint256 GetPrevoutHash(const CTransaction& txTo) { + CHashWriter ss(SER_GETHASH, 0); + for (unsigned int n = 0; n < txTo.vin.size(); n++) { + ss << txTo.vin[n].prevout; + } + return ss.GetHash(); +} + +uint256 GetSequenceHash(const CTransaction& txTo) { + CHashWriter ss(SER_GETHASH, 0); + for (unsigned int n = 0; n < txTo.vin.size(); n++) { + ss << txTo.vin[n].nSequence; + } + return ss.GetHash(); +} + +uint256 GetOutputsHash(const CTransaction& txTo) { + CHashWriter ss(SER_GETHASH, 0); + for (unsigned int n = 0; n < txTo.vout.size(); n++) { + ss << txTo.vout[n]; + } + return ss.GetHash(); +} + } // anon namespace -uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion) +CachedHashes::CachedHashes(const CTransaction& txTo) +{ + hashPrevouts = GetPrevoutHash(txTo); + hashSequence = GetSequenceHash(txTo); + hashOutputs = GetOutputsHash(txTo); +} + +uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const CachedHashes* cache) { if (sigversion == SIGVERSION_WITNESS_V0) { uint256 hashPrevouts; @@ -1118,27 +1149,16 @@ uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsig uint256 hashOutputs; if (!(nHashType & SIGHASH_ANYONECANPAY)) { - CHashWriter ss(SER_GETHASH, 0); - for (unsigned int n = 0; n < txTo.vin.size(); n++) { - ss << txTo.vin[n].prevout; - } - hashPrevouts = ss.GetHash(); // TODO: cache this value for all signatures in a transaction + hashPrevouts = cache ? cache->hashPrevouts : GetPrevoutHash(txTo); } if (!(nHashType & SIGHASH_ANYONECANPAY) && (nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) { - CHashWriter ss(SER_GETHASH, 0); - for (unsigned int n = 0; n < txTo.vin.size(); n++) { - ss << txTo.vin[n].nSequence; - } - hashSequence = ss.GetHash(); // TODO: cache this value for all signatures in a transaction + hashSequence = cache ? cache->hashSequence : GetSequenceHash(txTo); } + if ((nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) { - CHashWriter ss(SER_GETHASH, 0); - for (unsigned int n = 0; n < txTo.vout.size(); n++) { - ss << txTo.vout[n]; - } - hashOutputs = ss.GetHash(); // TODO: cache this value for all signatures in a transaction + hashOutputs = cache ? cache->hashOutputs : GetOutputsHash(txTo); } else if ((nHashType & 0x1f) == SIGHASH_SINGLE && nIn < txTo.vout.size()) { CHashWriter ss(SER_GETHASH, 0); ss << txTo.vout[nIn]; @@ -1209,7 +1229,7 @@ bool TransactionSignatureChecker::CheckSig(const vector& vchSigIn int nHashType = vchSig.back(); vchSig.pop_back(); - uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion); + uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion, this->cachedHashes); if (!VerifySignature(vchSig, pubkey, sighash)) return false; diff --git a/src/script/interpreter.h b/src/script/interpreter.h index bd2f21166368a..b4da113eec939 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -98,13 +98,20 @@ enum bool CheckSignatureEncoding(const std::vector &vchSig, unsigned int flags, ScriptError* serror); +struct CachedHashes +{ + uint256 hashPrevouts, hashSequence, hashOutputs; + + CachedHashes(const CTransaction& tx); +}; + enum SigVersion { SIGVERSION_BASE = 0, SIGVERSION_WITNESS_V0 = 1, }; -uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion); +uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const CachedHashes* cache = NULL); class BaseSignatureChecker { @@ -133,12 +140,14 @@ class TransactionSignatureChecker : public BaseSignatureChecker const CTransaction* txTo; unsigned int nIn; const CAmount amount; + const CachedHashes* cachedHashes; protected: virtual bool VerifySignature(const std::vector& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const; public: - TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn) : txTo(txToIn), nIn(nInIn), amount(amountIn) {} + TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), cachedHashes(NULL) {} + TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, const CachedHashes& cachedHashesIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), cachedHashes(&cachedHashesIn) {} bool CheckSig(const std::vector& scriptSig, const std::vector& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const; bool CheckLockTime(const CScriptNum& nLockTime) const; bool CheckSequence(const CScriptNum& nSequence) const; diff --git a/src/script/sigcache.h b/src/script/sigcache.h index 050bf8cc42290..551f8b2253e76 100644 --- a/src/script/sigcache.h +++ b/src/script/sigcache.h @@ -22,7 +22,7 @@ class CachingTransactionSignatureChecker : public TransactionSignatureChecker bool store; public: - CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amount, bool storeIn) : TransactionSignatureChecker(txToIn, nInIn, amount), store(storeIn) {} + CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amount, bool storeIn, CachedHashes& cachedHashesIn) : TransactionSignatureChecker(txToIn, nInIn, amount, cachedHashesIn), store(storeIn) {} bool VerifySignature(const std::vector& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const; }; diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp index 5224b57ca4479..5cd7c93622977 100644 --- a/src/test/script_P2SH_tests.cpp +++ b/src/test/script_P2SH_tests.cpp @@ -107,18 +107,20 @@ BOOST_AUTO_TEST_CASE(sign) } // All of the above should be OK, and the txTos have valid signatures // Check to make sure signature verification fails if we use the wrong ScriptSig: - for (int i = 0; i < 8; i++) + for (int i = 0; i < 8; i++) { + CachedHashes cachedHashes(txTo[i]); for (int j = 0; j < 8; j++) { CScript sigSave = txTo[i].vin[0].scriptSig; txTo[i].vin[0].scriptSig = txTo[j].vin[0].scriptSig; - bool sigOK = CScriptCheck(CCoins(txFrom, 0), txTo[i], 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, false)(); + bool sigOK = CScriptCheck(CCoins(txFrom, 0), txTo[i], 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, false, &cachedHashes)(); if (i == j) BOOST_CHECK_MESSAGE(sigOK, strprintf("VerifySignature %d %d", i, j)); else BOOST_CHECK_MESSAGE(!sigOK, strprintf("VerifySignature %d %d", i, j)); txTo[i].vin[0].scriptSig = sigSave; } + } } BOOST_AUTO_TEST_CASE(norecurse) diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index fd4f174b40c80..c06515f7302b6 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -153,6 +153,7 @@ BOOST_AUTO_TEST_CASE(tx_valid) BOOST_CHECK_MESSAGE(CheckTransaction(tx, state), strTest); BOOST_CHECK(state.IsValid()); + CachedHashes cachedHashes(tx); for (unsigned int i = 0; i < tx.vin.size(); i++) { if (!mapprevOutScriptPubKeys.count(tx.vin[i].prevout)) @@ -168,7 +169,7 @@ BOOST_AUTO_TEST_CASE(tx_valid) unsigned int verify_flags = ParseScriptFlags(test[2].get_str()); const CScriptWitness *witness = (i < tx.wit.vtxinwit.size()) ? &tx.wit.vtxinwit[i].scriptWitness : NULL; BOOST_CHECK_MESSAGE(VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], - witness, verify_flags, TransactionSignatureChecker(&tx, i, amount), &err), + witness, verify_flags, TransactionSignatureChecker(&tx, i, amount, cachedHashes), &err), strTest); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); } @@ -237,6 +238,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid) CValidationState state; fValid = CheckTransaction(tx, state) && state.IsValid(); + CachedHashes cachedHashes(tx); for (unsigned int i = 0; i < tx.vin.size() && fValid; i++) { if (!mapprevOutScriptPubKeys.count(tx.vin[i].prevout)) @@ -252,7 +254,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid) } const CScriptWitness *witness = (i < tx.wit.vtxinwit.size()) ? &tx.wit.vtxinwit[i].scriptWitness : NULL; fValid = VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], - witness, verify_flags, TransactionSignatureChecker(&tx, i, amount), &err); + witness, verify_flags, TransactionSignatureChecker(&tx, i, amount, cachedHashes), &err); } BOOST_CHECK_MESSAGE(!fValid, strTest); BOOST_CHECK_MESSAGE(err != SCRIPT_ERR_OK, ScriptErrorString(err)); From ab48c5e72156b34300db4a6521cb3c9969be3937 Mon Sep 17 00:00:00 2001 From: Nicolas DORIER Date: Tue, 16 Aug 2016 15:37:56 +0200 Subject: [PATCH 0726/1802] Unit test for sighash caching --- src/test/transaction_tests.cpp | 81 ++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index c06515f7302b6..8f8666c76d1dc 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -7,6 +7,7 @@ #include "test/test_bitcoin.h" #include "clientversion.h" +#include "checkqueue.h" #include "consensus/validation.h" #include "core_io.h" #include "key.h" @@ -421,6 +422,86 @@ void ReplaceRedeemScript(CScript& script, const CScript& redeemScript) script = PushAll(stack); } +BOOST_AUTO_TEST_CASE(test_big_witness_transaction) { + CMutableTransaction mtx; + mtx.nVersion = 1; + + CKey key; + key.MakeNewKey(false); + CBasicKeyStore keystore; + keystore.AddKeyPubKey(key, key.GetPubKey()); + CKeyID hash = key.GetPubKey().GetID(); + CScript scriptPubKey = CScript() << OP_0 << std::vector(hash.begin(), hash.end()); + + vector sigHashes; + sigHashes.push_back(SIGHASH_NONE | SIGHASH_ANYONECANPAY); + sigHashes.push_back(SIGHASH_SINGLE | SIGHASH_ANYONECANPAY); + sigHashes.push_back(SIGHASH_ALL | SIGHASH_ANYONECANPAY); + sigHashes.push_back(SIGHASH_NONE); + sigHashes.push_back(SIGHASH_SINGLE); + sigHashes.push_back(SIGHASH_ALL); + + // create a big transaction of 4500 inputs signed by the same key + for(uint32_t ij = 0; ij < 4500; ij++) { + uint32_t i = mtx.vin.size(); + uint256 prevId; + prevId.SetHex("0000000000000000000000000000000000000000000000000000000000000100"); + COutPoint outpoint(prevId, i); + + mtx.vin.resize(mtx.vin.size() + 1); + mtx.vin[i].prevout = outpoint; + mtx.vin[i].scriptSig = CScript(); + + mtx.vout.resize(mtx.vout.size() + 1); + mtx.vout[i].nValue = 1000; + mtx.vout[i].scriptPubKey = CScript() << OP_1; + } + + // sign all inputs + for(uint32_t i = 0; i < mtx.vin.size(); i++) { + bool hashSigned = SignSignature(keystore, scriptPubKey, mtx, i, 1000, sigHashes.at(i % sigHashes.size())); + assert(hashSigned); + } + + CTransaction tx; + CDataStream ssout(SER_NETWORK, PROTOCOL_VERSION); + WithOrVersion(&ssout, 0) << mtx; + WithOrVersion(&ssout, 0) >> tx; + + // check all inputs concurrently, with the cache + CachedHashes cachedHashes(tx); + boost::thread_group threadGroup; + CCheckQueue scriptcheckqueue(128); + CCheckQueueControl control(&scriptcheckqueue); + + for (int i=0; i<20; i++) + threadGroup.create_thread(boost::bind(&CCheckQueue::Thread, boost::ref(scriptcheckqueue))); + + CCoins coins; + coins.nVersion = 1; + coins.fCoinBase = false; + for(uint32_t i = 0; i < mtx.vin.size(); i++) { + CTxOut txout; + txout.nValue = 1000; + txout.scriptPubKey = scriptPubKey; + coins.vout.push_back(txout); + } + + for(uint32_t i = 0; i < mtx.vin.size(); i++) { + std::vector vChecks; + CScriptCheck check(coins, tx, i, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false, &cachedHashes); + vChecks.push_back(CScriptCheck()); + check.swap(vChecks.back()); + control.Add(vChecks); + } + + bool controlCheck = control.Wait(); + assert(controlCheck); + + threadGroup.interrupt_all(); + threadGroup.join_all(); +} + BOOST_AUTO_TEST_CASE(test_witness) { CBasicKeyStore keystore, keystore2; From bc1d1f266046ec79e87c7bf90aaf279f43266cf5 Mon Sep 17 00:00:00 2001 From: instagibbs Date: Tue, 16 Aug 2016 14:11:10 -0400 Subject: [PATCH 0727/1802] Update p2p-segwit.py to reflect correct AskFor behavior --- qa/rpc-tests/p2p-segwit.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/qa/rpc-tests/p2p-segwit.py b/qa/rpc-tests/p2p-segwit.py index cd02692b1e88c..3813743e5b912 100755 --- a/qa/rpc-tests/p2p-segwit.py +++ b/qa/rpc-tests/p2p-segwit.py @@ -946,8 +946,7 @@ def test_tx_relay_after_segwit_activation(self): self.test_node.test_transaction_acceptance(tx, with_witness=True, accepted=False) # Verify that removing the witness succeeds. - # Re-announcing won't result in a getdata for ~2.5 minutes, so just - # deliver the modified transaction. + self.test_node.announce_tx_and_wait_for_getdata(tx) self.test_node.test_transaction_acceptance(tx, with_witness=False, accepted=True) # Now try to add extra witness data to a valid witness tx. From eb0c52ec1d3ffd4e2d78b2044c1c3d62de7711d3 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 17 Aug 2016 12:03:33 +0200 Subject: [PATCH 0728/1802] travis: Remove hostname hack This was required for java, and we no longer use java for the tests. --- .travis.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index a6c51753b6727..e1600cf26932a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,5 @@ sudo: required dist: trusty - -#workaround for https://github.com/travis-ci/travis-ci/issues/5227 -addons: - hostname: bitcoin-tester - os: linux language: generic cache: From fa64306520156af1d1fe90e92f6cc22ffa097c02 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 17 Aug 2016 13:28:09 +0200 Subject: [PATCH 0729/1802] [qa] abandonconflict: Use assert_equal --- qa/rpc-tests/abandonconflict.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/qa/rpc-tests/abandonconflict.py b/qa/rpc-tests/abandonconflict.py index c50c3cc562e5f..874df487777cf 100755 --- a/qa/rpc-tests/abandonconflict.py +++ b/qa/rpc-tests/abandonconflict.py @@ -68,7 +68,7 @@ def run_test(self): # In mempool txs from self should increase balance from change newbalance = self.nodes[0].getbalance() - assert(newbalance == balance - Decimal("30") + Decimal("24.9996")) + assert_equal(newbalance, balance - Decimal("30") + Decimal("24.9996")) balance = newbalance # Restart the node with a higher min relay fee so the parent tx is no longer in mempool @@ -78,16 +78,16 @@ def run_test(self): self.nodes[0]=start_node(0, self.options.tmpdir, ["-debug","-logtimemicros","-minrelaytxfee=0.0001"]) # Verify txs no longer in mempool - assert(len(self.nodes[0].getrawmempool()) == 0) + assert_equal(len(self.nodes[0].getrawmempool()), 0) # Not in mempool txs from self should only reduce balance # inputs are still spent, but change not received newbalance = self.nodes[0].getbalance() - assert(newbalance == balance - Decimal("24.9996")) + assert_equal(newbalance, balance - Decimal("24.9996")) # Unconfirmed received funds that are not in mempool, also shouldn't show # up in unconfirmed balance unconfbalance = self.nodes[0].getunconfirmedbalance() + self.nodes[0].getbalance() - assert(unconfbalance == newbalance) + assert_equal(unconfbalance, newbalance) # Also shouldn't show up in listunspent assert(not txABC2 in [utxo["txid"] for utxo in self.nodes[0].listunspent(0)]) balance = newbalance @@ -96,35 +96,35 @@ def run_test(self): # including that the child tx was also abandoned self.nodes[0].abandontransaction(txAB1) newbalance = self.nodes[0].getbalance() - assert(newbalance == balance + Decimal("30")) + assert_equal(newbalance, balance + Decimal("30")) balance = newbalance # Verify that even with a low min relay fee, the tx is not reaccepted from wallet on startup once abandoned stop_node(self.nodes[0],0) self.nodes[0]=start_node(0, self.options.tmpdir, ["-debug","-logtimemicros","-minrelaytxfee=0.00001"]) - assert(len(self.nodes[0].getrawmempool()) == 0) - assert(self.nodes[0].getbalance() == balance) + assert_equal(len(self.nodes[0].getrawmempool()), 0) + assert_equal(self.nodes[0].getbalance(), balance) # But if its received again then it is unabandoned # And since now in mempool, the change is available # But its child tx remains abandoned self.nodes[0].sendrawtransaction(signed["hex"]) newbalance = self.nodes[0].getbalance() - assert(newbalance == balance - Decimal("20") + Decimal("14.99998")) + assert_equal(newbalance, balance - Decimal("20") + Decimal("14.99998")) balance = newbalance # Send child tx again so its unabandoned self.nodes[0].sendrawtransaction(signed2["hex"]) newbalance = self.nodes[0].getbalance() - assert(newbalance == balance - Decimal("10") - Decimal("14.99998") + Decimal("24.9996")) + assert_equal(newbalance, balance - Decimal("10") - Decimal("14.99998") + Decimal("24.9996")) balance = newbalance # Remove using high relay fee again stop_node(self.nodes[0],0) self.nodes[0]=start_node(0, self.options.tmpdir, ["-debug","-logtimemicros","-minrelaytxfee=0.0001"]) - assert(len(self.nodes[0].getrawmempool()) == 0) + assert_equal(len(self.nodes[0].getrawmempool()), 0) newbalance = self.nodes[0].getbalance() - assert(newbalance == balance - Decimal("24.9996")) + assert_equal(newbalance, balance - Decimal("24.9996")) balance = newbalance # Create a double spend of AB1 by spending again from only A's 10 output @@ -143,7 +143,7 @@ def run_test(self): # Verify that B and C's 10 BTC outputs are available for spending again because AB1 is now conflicted newbalance = self.nodes[0].getbalance() - assert(newbalance == balance + Decimal("20")) + assert_equal(newbalance, balance + Decimal("20")) balance = newbalance # There is currently a minor bug around this and so this test doesn't work. See Issue #7315 @@ -151,7 +151,7 @@ def run_test(self): # Don't think C's should either self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash()) newbalance = self.nodes[0].getbalance() - #assert(newbalance == balance - Decimal("10")) + #assert_equal(newbalance, balance - Decimal("10")) print("If balance has not declined after invalidateblock then out of mempool wallet tx which is no longer") print("conflicted has not resumed causing its inputs to be seen as spent. See Issue #7315") print(str(balance) + " -> " + str(newbalance) + " ?") From fa0afdee16ddca121076784d58d79e1833381058 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 17 Aug 2016 21:40:20 +0200 Subject: [PATCH 0730/1802] [travis] Drop java --- .travis.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index e1600cf26932a..0b38fd45fe46e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,15 +24,15 @@ env: # ARM - HOST=arm-linux-gnueabihf PACKAGES="g++-arm-linux-gnueabihf" DEP_OPTS="NO_QT=1" CHECK_DOC=1 GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" # Win32 - - HOST=i686-w64-mingw32 DPKG_ADD_ARCH="i386" DEP_OPTS="NO_QT=1" PACKAGES="python3 nsis g++-mingw-w64-i686 wine1.6 bc openjdk-7-jre-headless" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-reduce-exports" + - HOST=i686-w64-mingw32 DPKG_ADD_ARCH="i386" DEP_OPTS="NO_QT=1" PACKAGES="python3 nsis g++-mingw-w64-i686 wine1.6 bc" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-reduce-exports" # 32-bit + dash - - HOST=i686-pc-linux-gnu PACKAGES="g++-multilib bc python3-zmq openjdk-7-jre-headless" DEP_OPTS="NO_QT=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++" USE_SHELL="/bin/dash" + - HOST=i686-pc-linux-gnu PACKAGES="g++-multilib bc python3-zmq" DEP_OPTS="NO_QT=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++" USE_SHELL="/bin/dash" # Win64 - - HOST=x86_64-w64-mingw32 DPKG_ADD_ARCH="i386" DEP_OPTS="NO_QT=1" PACKAGES="python3 nsis g++-mingw-w64-x86-64 wine1.6 bc openjdk-7-jre-headless" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-reduce-exports" + - HOST=x86_64-w64-mingw32 DPKG_ADD_ARCH="i386" DEP_OPTS="NO_QT=1" PACKAGES="python3 nsis g++-mingw-w64-x86-64 wine1.6 bc" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-reduce-exports" # bitcoind - - HOST=x86_64-unknown-linux-gnu PACKAGES="bc python3-zmq openjdk-7-jre-headless" DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports CPPFLAGS=-DDEBUG_LOCKORDER" + - HOST=x86_64-unknown-linux-gnu PACKAGES="bc python3-zmq" DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports CPPFLAGS=-DDEBUG_LOCKORDER" # No wallet - - HOST=x86_64-unknown-linux-gnu PACKAGES=" openjdk-7-jre-headless python3" DEP_OPTS="NO_WALLET=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" + - HOST=x86_64-unknown-linux-gnu PACKAGES="python3" DEP_OPTS="NO_WALLET=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" # Cross-Mac - HOST=x86_64-apple-darwin11 PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev" BITCOIN_CONFIG="--enable-reduce-exports" OSX_SDK=10.11 GOAL="deploy" From e86eb71604e73ad35b8b1f59d73af22e353a156e Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Mon, 1 Aug 2016 17:14:40 -0700 Subject: [PATCH 0731/1802] Move CWallet::setKeyPool to private section of CWallet --- src/init.cpp | 9 ++++++--- src/wallet/wallet.h | 15 ++++++++++++++- src/wallet/walletdb.cpp | 10 ++-------- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 8d4a2cafbfbb1..a15fe2e13b94f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1439,9 +1439,12 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) LogPrintf("mapBlockIndex.size() = %u\n", mapBlockIndex.size()); LogPrintf("nBestHeight = %d\n", chainActive.Height()); #ifdef ENABLE_WALLET - LogPrintf("setKeyPool.size() = %u\n", pwalletMain ? pwalletMain->setKeyPool.size() : 0); - LogPrintf("mapWallet.size() = %u\n", pwalletMain ? pwalletMain->mapWallet.size() : 0); - LogPrintf("mapAddressBook.size() = %u\n", pwalletMain ? pwalletMain->mapAddressBook.size() : 0); + if (pwalletMain) { + LOCK(pwalletMain->cs_wallet); + LogPrintf("setKeyPool.size() = %u\n", pwalletMain->GetKeyPoolSize()); + LogPrintf("mapWallet.size() = %u\n", pwalletMain->mapWallet.size()); + LogPrintf("mapAddressBook.size() = %u\n", pwalletMain->mapAddressBook.size()); + } #endif if (GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION)) diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 50c94ccfbcd95..d2e3e2c6e3ee9 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -582,6 +582,8 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface CHDChain hdChain; bool fFileBacked; + + std::set setKeyPool; public: /* * Main wallet lock. @@ -594,7 +596,18 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface std::string strWalletFile; - std::set setKeyPool; + void LoadKeyPool(int nIndex, const CKeyPool &keypool) + { + setKeyPool.insert(nIndex); + + // If no metadata exists yet, create a default with the pool key's + // creation time. Note that this may be overwritten by actually + // stored metadata for that key later, which is fine. + CKeyID keyid = keypool.vchPubKey.GetID(); + if (mapKeyMetadata.count(keyid) == 0) + mapKeyMetadata[keyid] = CKeyMetadata(keypool.nTime); + } + std::map mapKeyMetadata; typedef std::map MasterKeyMap; diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 543522ca6485c..025d3606d9d20 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -556,14 +556,8 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, ssKey >> nIndex; CKeyPool keypool; ssValue >> keypool; - pwallet->setKeyPool.insert(nIndex); - - // If no metadata exists yet, create a default with the pool key's - // creation time. Note that this may be overwritten by actually - // stored metadata for that key later, which is fine. - CKeyID keyid = keypool.vchPubKey.GetID(); - if (pwallet->mapKeyMetadata.count(keyid) == 0) - pwallet->mapKeyMetadata[keyid] = CKeyMetadata(keypool.nTime); + + pwallet->LoadKeyPool(nIndex, keypool); } else if (strType == "version") { From 35f64e45c207960078eef58ccc50d91e4abc2c55 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 18 Aug 2016 09:22:57 +0200 Subject: [PATCH 0732/1802] Revert "[qa] Adjust timeouts for micro-optimization of run time" This reverts commit fa2d68f79c459b505652728c3d8da60679f98ae3. Temporary revert - see discussion in #8532. --- qa/rpc-tests/test_framework/util.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index 586e2a07ba925..190fa7f661a6d 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -121,7 +121,7 @@ def hex_str_to_bytes(hex_str): def str_to_b64str(string): return b64encode(string.encode('utf-8')).decode('ascii') -def sync_blocks(rpc_connections, wait=0.125, timeout=60): +def sync_blocks(rpc_connections, wait=1, timeout=60): """ Wait until everybody has the same tip """ @@ -133,7 +133,7 @@ def sync_blocks(rpc_connections, wait=0.125, timeout=60): timeout -= wait raise AssertionError("Block sync failed") -def sync_mempools(rpc_connections, wait=0.5, timeout=60): +def sync_mempools(rpc_connections, wait=1, timeout=60): """ Wait until everybody has the same transactions in their memory pools From fab2e26d2033ca3c7a24f6a0ad6529fceda52ebc Mon Sep 17 00:00:00 2001 From: crowning- Date: Thu, 18 Aug 2016 16:52:38 +0200 Subject: [PATCH 0733/1802] CDB: fix debug output It doesn't really help to clear a variable before printing it to the debug log. --- src/wallet/db.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index c906785e9e2eb..cfd007ca1c807 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -284,7 +284,7 @@ CDB::CDB(const std::string& strFilename, const char* pszMode, bool fFlushOnClose pdb = NULL; --bitdb.mapFileUseCount[strFile]; strFile = ""; - throw runtime_error(strprintf("CDB: Error %d, can't open database %s", ret, strFile)); + throw runtime_error(strprintf("CDB: Error %d, can't open database %s", ret, strFilename)); } if (fCreate && !Exists(string("version"))) { From b4a9aa511c95a1bd0da8ae363b3b9c0b3b7afe4e Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 18 Aug 2016 16:58:04 +0200 Subject: [PATCH 0734/1802] qt: Fix random segfault when closing "Choose data directory" dialog The `pickDataDirectory()` function was calling `exit(0)` to quit the application when the user closes the dialog without choosing a data directory. This is a bad idea because a background thread is created (to check free space on the drive of the currently selected datadir). The thread is not stopped and unwound properly, resulting in a potential race condition somewhere deep in Qt. So replace the `exit()` by a boolean return value, and let the stack unwind normally. --- src/qt/bitcoin.cpp | 3 ++- src/qt/intro.cpp | 7 ++++--- src/qt/intro.h | 5 ++++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 64b5c83d72a00..430e6dd0e8df8 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -578,7 +578,8 @@ int main(int argc, char *argv[]) /// 5. Now that settings and translations are available, ask user for data directory // User language is set up: pick a data directory - Intro::pickDataDirectory(); + if (!Intro::pickDataDirectory()) + return 0; /// 6. Determine availability of data directory and parse bitcoin.conf /// - Do not call GetDataDir(true) before this step finishes diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index 6d6af54290fd5..6a5740e21d3cb 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -165,14 +165,14 @@ QString Intro::getDefaultDataDirectory() return GUIUtil::boostPathToQString(GetDefaultDataDir()); } -void Intro::pickDataDirectory() +bool Intro::pickDataDirectory() { namespace fs = boost::filesystem; QSettings settings; /* If data directory provided on command line, no need to look at settings or show a picking dialog */ if(!GetArg("-datadir", "").empty()) - return; + return true; /* 1) Default data directory for operating system */ QString dataDir = getDefaultDataDirectory(); /* 2) Allow QSettings to override default dir */ @@ -190,7 +190,7 @@ void Intro::pickDataDirectory() if(!intro.exec()) { /* Cancel clicked */ - exit(0); + return false; } dataDir = intro.getDataDirectory(); try { @@ -211,6 +211,7 @@ void Intro::pickDataDirectory() */ if(dataDir != getDefaultDataDirectory()) SoftSetArg("-datadir", GUIUtil::qstringToBoostPath(dataDir).string()); // use OS locale for path setting + return true; } void Intro::setStatus(int status, const QString &message, quint64 bytesAvailable) diff --git a/src/qt/intro.h b/src/qt/intro.h index 9e2e96dc9eca7..ee768a7ad8d1d 100644 --- a/src/qt/intro.h +++ b/src/qt/intro.h @@ -35,10 +35,13 @@ class Intro : public QDialog /** * Determine data directory. Let the user choose if the current one doesn't exist. * + * @returns true if a data directory was selected, false if the user cancelled the selection + * dialog. + * * @note do NOT call global GetDataDir() before calling this function, this * will cause the wrong path to be cached. */ - static void pickDataDirectory(); + static bool pickDataDirectory(); /** * Determine default data directory for operating system. From 5547aeb0159027912069b4773184963f54c672af Mon Sep 17 00:00:00 2001 From: instagibbs Date: Tue, 16 Aug 2016 15:45:42 -0400 Subject: [PATCH 0735/1802] p2psegwit.py transaction is rejected due to premature witness not size --- qa/rpc-tests/p2p-segwit.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/qa/rpc-tests/p2p-segwit.py b/qa/rpc-tests/p2p-segwit.py index 3813743e5b912..68d8b9a006fad 100755 --- a/qa/rpc-tests/p2p-segwit.py +++ b/qa/rpc-tests/p2p-segwit.py @@ -302,13 +302,18 @@ def test_unnecessary_witness_before_segwit_activation(self): sync_blocks(self.nodes) # We'll add an unnecessary witness to this transaction that would cause - # it to be too large according to IsStandard. + # it to be non-standard, to test that violating policy with a witness before + # segwit activation doesn't blind a node to a transaction. Transactions + # rejected for having a witness before segwit activation shouldn't be added + # to the rejection cache. tx3 = CTransaction() tx3.vin.append(CTxIn(COutPoint(tx2.sha256, 0), CScript([p2sh_program]))) tx3.vout.append(CTxOut(tx2.vout[0].nValue-1000, scriptPubKey)) tx3.wit.vtxinwit.append(CTxInWitness()) tx3.wit.vtxinwit[0].scriptWitness.stack = [b'a'*400000] tx3.rehash() + # Note that this should be rejected for the premature witness reason, + # rather than a policy check, since segwit hasn't activated yet. self.std_node.test_transaction_acceptance(tx3, True, False, b'no-witness-yet') # If we send without witness, it should be accepted. From 914154f0ccf2a18a273c7fdb3e80016732149303 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Wed, 17 Aug 2016 14:09:47 +0200 Subject: [PATCH 0736/1802] [Qt] add HD enabled/disabled icon to the status bar --- contrib/debian/copyright | 4 ++++ src/Makefile.qt.include | 6 ++++-- src/qt/bitcoin.qrc | 2 ++ src/qt/bitcoingui.cpp | 32 +++++++++++++++++++++---------- src/qt/bitcoingui.h | 9 ++++++++- src/qt/res/icons/hd_disabled.png | Bin 0 -> 4328 bytes src/qt/res/icons/hd_enabled.png | Bin 0 -> 1889 bytes src/qt/res/src/hd_disabled.svg | 26 +++++++++++++++++++++++++ src/qt/res/src/hd_enabled.svg | 13 +++++++++++++ src/qt/walletmodel.cpp | 5 +++++ src/qt/walletmodel.h | 2 ++ src/qt/walletview.cpp | 6 ++++++ src/qt/walletview.h | 2 ++ src/wallet/wallet.cpp | 15 ++++++++++----- src/wallet/wallet.h | 3 +++ 15 files changed, 107 insertions(+), 18 deletions(-) create mode 100644 src/qt/res/icons/hd_disabled.png create mode 100644 src/qt/res/icons/hd_enabled.png create mode 100644 src/qt/res/src/hd_disabled.svg create mode 100644 src/qt/res/src/hd_enabled.svg diff --git a/contrib/debian/copyright b/contrib/debian/copyright index c039a7bae5861..cc4606ca88ad9 100644 --- a/contrib/debian/copyright +++ b/contrib/debian/copyright @@ -59,6 +59,10 @@ Files: src/qt/res/icons/tx_mined.png src/qt/res/src/mine.svg src/qt/res/icons/fontbigger.png src/qt/res/icons/fontsmaller.png + src/qt/res/icons/hd_disabled.png + src/qt/res/src/hd_disabled.svg + src/qt/res/icons/hd_enabled.png + src/qt/res/src/hd_enabled.svg Copyright: Jonas Schnelli License: Expat Comment: diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 7730aba375c44..8947aeaca0b14 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -257,6 +257,8 @@ RES_ICONS = \ qt/res/icons/filesave.png \ qt/res/icons/fontbigger.png \ qt/res/icons/fontsmaller.png \ + qt/res/icons/hd_disabled.png \ + qt/res/icons/hd_enabled.png \ qt/res/icons/history.png \ qt/res/icons/info.png \ qt/res/icons/key.png \ @@ -271,14 +273,14 @@ RES_ICONS = \ qt/res/icons/synced.png \ qt/res/icons/transaction0.png \ qt/res/icons/transaction2.png \ + qt/res/icons/transaction_abandoned.png \ qt/res/icons/transaction_conflicted.png \ qt/res/icons/tx_inout.png \ qt/res/icons/tx_input.png \ qt/res/icons/tx_output.png \ qt/res/icons/tx_mined.png \ qt/res/icons/warning.png \ - qt/res/icons/verify.png \ - qt/res/icons/transaction_abandoned.png + qt/res/icons/verify.png BITCOIN_QT_CPP = \ qt/bantablemodel.cpp \ diff --git a/src/qt/bitcoin.qrc b/src/qt/bitcoin.qrc index 24b0bae3ec144..ca5b1fa67321c 100644 --- a/src/qt/bitcoin.qrc +++ b/src/qt/bitcoin.qrc @@ -50,6 +50,8 @@ res/icons/fontsmaller.png res/icons/chevron.png res/icons/transaction_abandoned.png + res/icons/hd_enabled.png + res/icons/hd_disabled.png res/movies/spinner-000.png diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 2afefb733edcf..272df3fdae42c 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -80,7 +80,8 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *platformStyle, const NetworkStyle *n clientModel(0), walletFrame(0), unitDisplayControl(0), - labelEncryptionIcon(0), + labelWalletEncryptionIcon(0), + labelWalletHDStatusIcon(0), labelConnectionsIcon(0), labelBlocksIcon(0), progressBarLabel(0), @@ -194,7 +195,8 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *platformStyle, const NetworkStyle *n frameBlocksLayout->setContentsMargins(3,0,3,0); frameBlocksLayout->setSpacing(3); unitDisplayControl = new UnitDisplayStatusBarControl(platformStyle); - labelEncryptionIcon = new QLabel(); + labelWalletEncryptionIcon = new QLabel(); + labelWalletHDStatusIcon = new QLabel(); labelConnectionsIcon = new QLabel(); labelBlocksIcon = new QLabel(); if(enableWallet) @@ -202,7 +204,8 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *platformStyle, const NetworkStyle *n frameBlocksLayout->addStretch(); frameBlocksLayout->addWidget(unitDisplayControl); frameBlocksLayout->addStretch(); - frameBlocksLayout->addWidget(labelEncryptionIcon); + frameBlocksLayout->addWidget(labelWalletEncryptionIcon); + frameBlocksLayout->addWidget(labelWalletHDStatusIcon); } frameBlocksLayout->addStretch(); frameBlocksLayout->addWidget(labelConnectionsIcon); @@ -988,28 +991,37 @@ bool BitcoinGUI::handlePaymentRequest(const SendCoinsRecipient& recipient) return false; } +void BitcoinGUI::setHDStatus(int hdEnabled) +{ + labelWalletHDStatusIcon->setPixmap(platformStyle->SingleColorIcon(hdEnabled ? ":/icons/hd_enabled" : ":/icons/hd_disabled").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE)); + labelWalletHDStatusIcon->setToolTip(hdEnabled ? tr("HD key generation is enabled") : tr("HD key generation is disabled")); + + // eventually disable the QLabel to set its opacity to 50% + labelWalletHDStatusIcon->setEnabled(hdEnabled); +} + void BitcoinGUI::setEncryptionStatus(int status) { switch(status) { case WalletModel::Unencrypted: - labelEncryptionIcon->hide(); + labelWalletEncryptionIcon->hide(); encryptWalletAction->setChecked(false); changePassphraseAction->setEnabled(false); encryptWalletAction->setEnabled(true); break; case WalletModel::Unlocked: - labelEncryptionIcon->show(); - labelEncryptionIcon->setPixmap(platformStyle->SingleColorIcon(":/icons/lock_open").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE)); - labelEncryptionIcon->setToolTip(tr("Wallet is encrypted and currently unlocked")); + labelWalletEncryptionIcon->show(); + labelWalletEncryptionIcon->setPixmap(platformStyle->SingleColorIcon(":/icons/lock_open").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE)); + labelWalletEncryptionIcon->setToolTip(tr("Wallet is encrypted and currently unlocked")); encryptWalletAction->setChecked(true); changePassphraseAction->setEnabled(true); encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported break; case WalletModel::Locked: - labelEncryptionIcon->show(); - labelEncryptionIcon->setPixmap(platformStyle->SingleColorIcon(":/icons/lock_closed").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE)); - labelEncryptionIcon->setToolTip(tr("Wallet is encrypted and currently locked")); + labelWalletEncryptionIcon->show(); + labelWalletEncryptionIcon->setPixmap(platformStyle->SingleColorIcon(":/icons/lock_closed").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE)); + labelWalletEncryptionIcon->setToolTip(tr("Wallet is encrypted and currently locked")); encryptWalletAction->setChecked(true); changePassphraseAction->setEnabled(true); encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 12e7702ed82d6..41770929b4706 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -82,7 +82,8 @@ class BitcoinGUI : public QMainWindow WalletFrame *walletFrame; UnitDisplayStatusBarControl *unitDisplayControl; - QLabel *labelEncryptionIcon; + QLabel *labelWalletEncryptionIcon; + QLabel *labelWalletHDStatusIcon; QLabel *labelConnectionsIcon; QLabel *labelBlocksIcon; QLabel *progressBarLabel; @@ -169,6 +170,12 @@ public Q_SLOTS: */ void setEncryptionStatus(int status); + /** Set the hd-enabled status as shown in the UI. + @param[in] status current hd enabled status + @see WalletModel::EncryptionStatus + */ + void setHDStatus(int hdEnabled); + bool handlePaymentRequest(const SendCoinsRecipient& recipient); /** Show incoming transaction notification for new transactions. */ diff --git a/src/qt/res/icons/hd_disabled.png b/src/qt/res/icons/hd_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..687b6d2e38e9e3f8955072574ce644735a249982 GIT binary patch literal 4328 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 HpS|$k8tbb^ literal 0 HcmV?d00001 diff --git a/src/qt/res/icons/hd_enabled.png b/src/qt/res/icons/hd_enabled.png new file mode 100644 index 0000000000000000000000000000000000000000..568dde1cd1c1dba2dc1d575365ecd89aa7e55f68 GIT binary patch literal 1889 zcmb_dYfuwc6kZ@AP*Lea@Frmh+xa8 zbwEae`r;v0d=zN4ty6q}jt?jxR%DP@E!N3cD+mQgu~6&=0sEu$PrG+_&pmg}_nmX^ z`F3`XI40cD!Nmap0LRD(frPX{bo+V<4bbKUL9bv?fIAe@dY22!0tEeGs!5{;NB+wv)0yJpSv^d8QOr7H8kaNp2 zLc!g;B8u%^-rQWTmgSpwZ3JYVqk~A`c8QD0C1^XIQp06DSh>d#FY; z8;uhZvgB8w+wP-=3BQpySOuY?J2{BXyPVJeap1T(QoP5(*)!elR z=EOo|F_5LRf9v$j5-A_cbXK>dGpl?=OUfN1b$#9b#5no6bVLexQbW%`X~OP>u|VVP zbM%^){RXf`PIYRpl1GL1Q1b%XF9d-;nI4e4*Ne*MJgqr*zI*ld58Ackp--;b)TL4P z4B$Z%X(Ts}|V%ezc*YdeN&_ z>+5RelBeD~4%{y^4eXV|lJ1H=>1OZVqK%ZM6>&v(qdq_9W;N2{XFiWbJAVqiyy5@u z&}z@cU_)!X`^w`^q!srRaVSkte)CIADhT0b8H*CLX>sLOjQ3XEYTiIOMei-fy(T-) zKRn4h^d(Jlxaca}nH^epBCG%HLX)vrukdW!ru@p@6~9=#&*_O zot|`6M+9|X|8a>d4={-r4ACY7OA_*d z$ze%dzbrYdsMkn|fNBa_7O{8%u(cs{SNou>>Q07N@vrvP`;6JYeGPB;;M^0jve|E^nljXT~{qHBbl`Jm+Chr_j zne7TqCXid7?hJSA1zs+x=--&>#o0NKv}?Y7$C|i92W_n6_pQc?gjSo6s4nar6rWjg zTVJ2Op#zy{80{C+tsW;|csTNtUH{VBbuY?1a}sH|y#6h#iL3SVE?qwxy~29zny@k9 zO3H_ZZ8<<$-}q2E4TqXPTMU+V>22iYgNZyKM0RRGPg90F=|S%EL&xR5PnQ!lvGKcs z$BNPsv9nqB)YV#br29eaj&8yBhN0bies4NxPyHn>C91rx#a*Y2X3VcBbveH>XfWKI zj|H~f^yFs6ms_7}i8TxRq85Wky6in)6d$Kjn%tk8cAQ9er56BYNhkLw zo|&M<=h+oH4(M$b9!^rNKX&vzd?~3Uz0H6dcQ8`g<_uo$dax-$#2EW7_;j((HezXm zXjlWRNl8i=(^rDrjIZyd_vVgvQc$4x?xjC-Iu2m|!%?}nZ<^gGT!6g)j}hVVin0uN XRMO0!1b*IZ`RPT5#RzIclXm_E9we}T literal 0 HcmV?d00001 diff --git a/src/qt/res/src/hd_disabled.svg b/src/qt/res/src/hd_disabled.svg new file mode 100644 index 0000000000000..035f4431c7a92 --- /dev/null +++ b/src/qt/res/src/hd_disabled.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/qt/res/src/hd_enabled.svg b/src/qt/res/src/hd_enabled.svg new file mode 100644 index 0000000000000..cbaa16f8f0be3 --- /dev/null +++ b/src/qt/res/src/hd_enabled.svg @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 3867310cd6857..ae7efc7a0d40b 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -683,3 +683,8 @@ bool WalletModel::abandonTransaction(uint256 hash) const LOCK2(cs_main, wallet->cs_wallet); return wallet->AbandonTransaction(hash); } + +bool WalletModel::hdEnabled() const +{ + return wallet->IsHDEnabled(); +} diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index e5470bf618eea..a15ecf899b87a 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -203,6 +203,8 @@ class WalletModel : public QObject bool transactionCanBeAbandoned(uint256 hash) const; bool abandonTransaction(uint256 hash) const; + bool hdEnabled() const; + private: CWallet *wallet; bool fHaveWatchOnly; diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index 6ce98ef160a5c..495ebfd834bfc 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -98,6 +98,9 @@ void WalletView::setBitcoinGUI(BitcoinGUI *gui) // Pass through transaction notifications connect(this, SIGNAL(incomingTransaction(QString,int,CAmount,QString,QString,QString)), gui, SLOT(incomingTransaction(QString,int,CAmount,QString,QString,QString))); + + // Connect HD enabled state signal + connect(this, SIGNAL(hdEnabledStatusChanged(int)), gui, SLOT(setHDStatus(int))); } } @@ -130,6 +133,9 @@ void WalletView::setWalletModel(WalletModel *walletModel) connect(walletModel, SIGNAL(encryptionStatusChanged(int)), this, SIGNAL(encryptionStatusChanged(int))); updateEncryptionStatus(); + // update HD status + Q_EMIT hdEnabledStatusChanged(walletModel->hdEnabled()); + // Balloon pop-up for new transaction connect(walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(processNewTransaction(QModelIndex,int,int))); diff --git a/src/qt/walletview.h b/src/qt/walletview.h index dbb289f425466..2045605954d23 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -117,6 +117,8 @@ public Q_SLOTS: void message(const QString &title, const QString &message, unsigned int style); /** Encryption status of wallet changed */ void encryptionStatusChanged(int status); + /** HD-Enabled status of wallet changed (only possible during startup) */ + void hdEnabledStatusChanged(int hdEnabled); /** Notify that a new transaction appeared */ void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label); }; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 888aa029a3dcd..22a6f9087cb24 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -98,7 +98,7 @@ CPubKey CWallet::GenerateNewKey() CKeyMetadata metadata(nCreationTime); // use HD key derivation if HD was enabled during wallet creation - if (!hdChain.masterKeyID.IsNull()) { + if (IsHDEnabled()) { // for now we use a fixed keypath scheme of m/0'/0'/k CKey key; //master key seed (256bit) CExtKey masterKey; //hd master key @@ -628,7 +628,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) Unlock(strWalletPassphrase); // if we are using HD, replace the HD master key (seed) with a new one - if (!hdChain.masterKeyID.IsNull()) { + if (IsHDEnabled()) { CKey key; CPubKey masterPubKey = GenerateNewHDMasterKey(); if (!SetHDMasterKey(masterPubKey)) @@ -1233,6 +1233,11 @@ bool CWallet::SetHDChain(const CHDChain& chain, bool memonly) return true; } +bool CWallet::IsHDEnabled() +{ + return !hdChain.masterKeyID.IsNull(); +} + int64_t CWalletTx::GetTxTime() const { int64_t n = nTimeSmart; @@ -3322,7 +3327,7 @@ bool CWallet::InitLoadWallet() if (fFirstRun) { // Create new keyUser and set as default key - if (GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET) && walletInstance->hdChain.masterKeyID.IsNull()) { + if (GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET) && !walletInstance->IsHDEnabled()) { // generate a new master key CKey key; CPubKey masterPubKey = walletInstance->GenerateNewHDMasterKey(); @@ -3340,9 +3345,9 @@ bool CWallet::InitLoadWallet() } else if (mapArgs.count("-usehd")) { bool useHD = GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET); - if (!walletInstance->hdChain.masterKeyID.IsNull() && !useHD) + if (walletInstance->IsHDEnabled() && !useHD) return InitError(strprintf(_("Error loading %s: You can't disable HD on a already existing HD wallet"), walletFile)); - if (walletInstance->hdChain.masterKeyID.IsNull() && useHD) + if (!walletInstance->IsHDEnabled() && useHD) return InitError(strprintf(_("Error loading %s: You can't enable HD on a already existing non-HD wallet"), walletFile)); } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 952acd1535abf..30f092e9a812d 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -902,6 +902,9 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface bool SetHDChain(const CHDChain& chain, bool memonly); const CHDChain& GetHDChain() { return hdChain; } + /* Returns true if HD is enabled */ + bool IsHDEnabled(); + /* Generates a new HD master key (will not be activated) */ CPubKey GenerateNewHDMasterKey(); From fa3d9740099c8513f9942983f135f58890e62cb5 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 13 Jun 2016 12:10:46 +0200 Subject: [PATCH 0737/1802] [doc] Update git-subtree-check.sh README --- contrib/devtools/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contrib/devtools/README.md b/contrib/devtools/README.md index bb8b9246b8781..af5c000b0305e 100644 --- a/contrib/devtools/README.md +++ b/contrib/devtools/README.md @@ -51,8 +51,9 @@ maintained: * for `src/secp256k1`: https://github.com/bitcoin-core/secp256k1.git (branch master) * for `src/leveldb`: https://github.com/bitcoin-core/leveldb.git (branch bitcoin-fork) * for `src/univalue`: https://github.com/bitcoin-core/univalue.git (branch master) +* for `src/crypto/ctaes`: https://github.com/bitcoin-core/ctaes.git (branch master) -Usage: `git-subtree-check.sh DIR COMMIT` +Usage: `git-subtree-check.sh DIR (COMMIT)` `COMMIT` may be omitted, in which case `HEAD` is used. From 7e5d94df1fb09ed7ee7ed50032f876972ef39489 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Mon, 1 Aug 2016 15:18:15 +0200 Subject: [PATCH 0738/1802] [Wallet] Trivial cleanup of HD wallet changes --- src/wallet/wallet.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index ee9254050ce78..e2dea521214b9 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1200,7 +1200,7 @@ CPubKey CWallet::GenerateNewHDMasterKey() // write the key&metadata to the database if (!AddKeyPubKey(key, pubkey)) - throw std::runtime_error("CWallet::GenerateNewKey(): AddKey failed"); + throw std::runtime_error(std::string(__func__)+": AddKeyPubKey failed"); } return pubkey; @@ -3323,7 +3323,6 @@ bool CWallet::InitLoadWallet() // Create new keyUser and set as default key if (GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET) && walletInstance->hdChain.masterKeyID.IsNull()) { // generate a new master key - CKey key; CPubKey masterPubKey = walletInstance->GenerateNewHDMasterKey(); if (!walletInstance->SetHDMasterKey(masterPubKey)) throw std::runtime_error("CWallet::GenerateNewKey(): Storing master key failed"); From fa785d121152c652d0704ac32ce8611262e609d2 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Fri, 19 Aug 2016 18:31:35 +0200 Subject: [PATCH 0739/1802] Use __func__ to get function name for output printing --- src/main.cpp | 2 +- src/primitives/transaction.cpp | 2 +- src/wallet/wallet.cpp | 34 +++++++++++++++++----------------- src/wallet/walletdb.cpp | 4 ++-- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 46118fff81eb0..a6bf96f3e450a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3954,7 +3954,7 @@ CBlockIndex * InsertBlockIndex(uint256 hash) // Create new CBlockIndex* pindexNew = new CBlockIndex(); if (!pindexNew) - throw runtime_error("LoadBlockIndex(): new CBlockIndex failed"); + throw runtime_error(std::string(__func__) + ": new CBlockIndex failed"); mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first; pindexNew->phashBlock = &((*mi).first); diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index 8d6380564365e..2fdc59ea07767 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -100,7 +100,7 @@ CAmount CTransaction::GetValueOut() const { nValueOut += it->nValue; if (!MoneyRange(it->nValue) || !MoneyRange(nValueOut)) - throw std::runtime_error("CTransaction::GetValueOut(): value out of range"); + throw std::runtime_error(std::string(__func__) + ": value out of range"); } return nValueOut; } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index e2dea521214b9..cb414cec1d505 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -108,7 +108,7 @@ CPubKey CWallet::GenerateNewKey() // try to get the master key if (!GetKey(hdChain.masterKeyID, key)) - throw std::runtime_error("CWallet::GenerateNewKey(): Master key not found"); + throw std::runtime_error(std::string(__func__) + ": Master key not found"); masterKey.SetMaster(key.begin(), key.size()); @@ -135,7 +135,7 @@ CPubKey CWallet::GenerateNewKey() // update the chain model in the database if (!CWalletDB(strWalletFile).WriteHDChain(hdChain)) - throw std::runtime_error("CWallet::GenerateNewKey(): Writing HD chain model failed"); + throw std::runtime_error(std::string(__func__) + ": Writing HD chain model failed"); } else { secret.MakeNewKey(fCompressed); } @@ -152,7 +152,7 @@ CPubKey CWallet::GenerateNewKey() nTimeFirstKey = nCreationTime; if (!AddKeyPubKey(secret, pubkey)) - throw std::runtime_error("CWallet::GenerateNewKey(): AddKey failed"); + throw std::runtime_error(std::string(__func__) + ": AddKey failed"); return pubkey; } @@ -1094,7 +1094,7 @@ isminetype CWallet::IsMine(const CTxOut& txout) const CAmount CWallet::GetCredit(const CTxOut& txout, const isminefilter& filter) const { if (!MoneyRange(txout.nValue)) - throw std::runtime_error("CWallet::GetCredit(): value out of range"); + throw std::runtime_error(std::string(__func__) + ": value out of range"); return ((IsMine(txout) & filter) ? txout.nValue : 0); } @@ -1123,7 +1123,7 @@ bool CWallet::IsChange(const CTxOut& txout) const CAmount CWallet::GetChange(const CTxOut& txout) const { if (!MoneyRange(txout.nValue)) - throw std::runtime_error("CWallet::GetChange(): value out of range"); + throw std::runtime_error(std::string(__func__) + ": value out of range"); return (IsChange(txout) ? txout.nValue : 0); } @@ -1147,7 +1147,7 @@ CAmount CWallet::GetDebit(const CTransaction& tx, const isminefilter& filter) co { nDebit += GetDebit(txin, filter); if (!MoneyRange(nDebit)) - throw std::runtime_error("CWallet::GetDebit(): value out of range"); + throw std::runtime_error(std::string(__func__) + ": value out of range"); } return nDebit; } @@ -1159,7 +1159,7 @@ CAmount CWallet::GetCredit(const CTransaction& tx, const isminefilter& filter) c { nCredit += GetCredit(txout, filter); if (!MoneyRange(nCredit)) - throw std::runtime_error("CWallet::GetCredit(): value out of range"); + throw std::runtime_error(std::string(__func__) + ": value out of range"); } return nCredit; } @@ -1171,7 +1171,7 @@ CAmount CWallet::GetChange(const CTransaction& tx) const { nChange += GetChange(txout); if (!MoneyRange(nChange)) - throw std::runtime_error("CWallet::GetChange(): value out of range"); + throw std::runtime_error(std::string(__func__) + ": value out of range"); } return nChange; } @@ -1200,7 +1200,7 @@ CPubKey CWallet::GenerateNewHDMasterKey() // write the key&metadata to the database if (!AddKeyPubKey(key, pubkey)) - throw std::runtime_error(std::string(__func__)+": AddKeyPubKey failed"); + throw std::runtime_error(std::string(__func__) + ": AddKeyPubKey failed"); } return pubkey; @@ -1227,7 +1227,7 @@ bool CWallet::SetHDChain(const CHDChain& chain, bool memonly) { LOCK(cs_wallet); if (!memonly && !CWalletDB(strWalletFile).WriteHDChain(chain)) - throw runtime_error("AddHDChain(): writing chain failed"); + throw runtime_error(std::string(__func__) + ": writing chain failed"); hdChain = chain; return true; @@ -2706,7 +2706,7 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize) if (!setKeyPool.empty()) nEnd = *(--setKeyPool.end()) + 1; if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey()))) - throw runtime_error("TopUpKeyPool(): writing generated key failed"); + throw runtime_error(std::string(__func__) + ": writing generated key failed"); setKeyPool.insert(nEnd); LogPrintf("keypool added key %d, size=%u\n", nEnd, setKeyPool.size()); } @@ -2733,9 +2733,9 @@ void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool) nIndex = *(setKeyPool.begin()); setKeyPool.erase(setKeyPool.begin()); if (!walletdb.ReadPool(nIndex, keypool)) - throw runtime_error("ReserveKeyFromKeyPool(): read failed"); + throw runtime_error(std::string(__func__) + ": read failed"); if (!HaveKey(keypool.vchPubKey.GetID())) - throw runtime_error("ReserveKeyFromKeyPool(): unknown key in key pool"); + throw runtime_error(std::string(__func__) + ": unknown key in key pool"); assert(keypool.vchPubKey.IsValid()); LogPrintf("keypool reserve %d\n", nIndex); } @@ -2794,7 +2794,7 @@ int64_t CWallet::GetOldestKeyPoolTime() CWalletDB walletdb(strWalletFile); int64_t nIndex = *(setKeyPool.begin()); if (!walletdb.ReadPool(nIndex, keypool)) - throw runtime_error("GetOldestKeyPoolTime(): read oldest key in keypool failed"); + throw runtime_error(std::string(__func__) + ": read oldest key in keypool failed"); assert(keypool.vchPubKey.IsValid()); return keypool.nTime; } @@ -3021,11 +3021,11 @@ void CWallet::GetAllReserveKeys(set& setAddress) const { CKeyPool keypool; if (!walletdb.ReadPool(id, keypool)) - throw runtime_error("GetAllReserveKeyHashes(): read failed"); + throw runtime_error(std::string(__func__) + ": read failed"); assert(keypool.vchPubKey.IsValid()); CKeyID keyID = keypool.vchPubKey.GetID(); if (!HaveKey(keyID)) - throw runtime_error("GetAllReserveKeyHashes(): unknown key in key pool"); + throw runtime_error(std::string(__func__) + ": unknown key in key pool"); setAddress.insert(keyID); } } @@ -3325,7 +3325,7 @@ bool CWallet::InitLoadWallet() // generate a new master key CPubKey masterPubKey = walletInstance->GenerateNewHDMasterKey(); if (!walletInstance->SetHDMasterKey(masterPubKey)) - throw std::runtime_error("CWallet::GenerateNewKey(): Storing master key failed"); + throw std::runtime_error(std::string(__func__) + ": Storing master key failed"); } CPubKey newDefaultKey; if (walletInstance->GetKeyFromPool(newDefaultKey)) { diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 543522ca6485c..f824492cb6fd4 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -215,7 +215,7 @@ void CWalletDB::ListAccountCreditDebit(const string& strAccount, listclose(); - throw runtime_error("CWalletDB::ListAccountCreditDebit(): error scanning DB"); + throw runtime_error(std::string(__func__) + ": error scanning DB"); } // Unserialize From faaec1377c6975a7c427bac958b67a0aba9e1694 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Fri, 19 Aug 2016 22:41:09 +0200 Subject: [PATCH 0740/1802] [qa] Remove unused code --- qa/pull-tester/rpc-tests.py | 2 -- qa/rpc-tests/importprunedfunds.py | 2 +- qa/rpc-tests/rpcbind_test.py | 6 ++---- qa/rpc-tests/segwit.py | 2 -- 4 files changed, 3 insertions(+), 9 deletions(-) diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index a0951f31a0ecb..daaa7782f9356 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -77,8 +77,6 @@ #Set env vars if "BITCOIND" not in os.environ: os.environ["BITCOIND"] = BUILDDIR + '/src/bitcoind' + EXEEXT -if "BITCOINCLI" not in os.environ: - os.environ["BITCOINCLI"] = BUILDDIR + '/src/bitcoin-cli' + EXEEXT if EXEEXT == ".exe" and "-win" not in opts: # https://github.com/bitcoin/bitcoin/commit/d52802551752140cf41f0d9a225a43e84404d3e9 diff --git a/qa/rpc-tests/importprunedfunds.py b/qa/rpc-tests/importprunedfunds.py index d86f51b7f3aaf..eb3c11b4d85db 100755 --- a/qa/rpc-tests/importprunedfunds.py +++ b/qa/rpc-tests/importprunedfunds.py @@ -5,7 +5,7 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * -import decimal + class ImportPrunedFundsTest(BitcoinTestFramework): diff --git a/qa/rpc-tests/rpcbind_test.py b/qa/rpc-tests/rpcbind_test.py index bf1cc8712611a..3ac32140ba898 100755 --- a/qa/rpc-tests/rpcbind_test.py +++ b/qa/rpc-tests/rpcbind_test.py @@ -5,13 +5,11 @@ # Test for -rpcbind, as well as -rpcallowip and -rpcconnect -import tempfile -import traceback - from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * from test_framework.netutil import * + class RPCBindTest(BitcoinTestFramework): def __init__(self): @@ -109,4 +107,4 @@ def run_test(self): pass if __name__ == '__main__': - RPCBindTest ().main () + RPCBindTest().main() diff --git a/qa/rpc-tests/segwit.py b/qa/rpc-tests/segwit.py index da82b09901611..745a1d47508cb 100755 --- a/qa/rpc-tests/segwit.py +++ b/qa/rpc-tests/segwit.py @@ -10,8 +10,6 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * from test_framework.mininode import sha256, ripemd160 -import os -import shutil NODE_0 = 0 NODE_1 = 1 From 4207630f5aef4e1937052eb96be7209e51d1371d Mon Sep 17 00:00:00 2001 From: Daniel Kraft Date: Sat, 20 Aug 2016 10:28:06 +0200 Subject: [PATCH 0741/1802] trivial: remove unused variable Remove the unused variable "blockTmp" in CMerkleTx::SetMerkleBranch. It was previously used to read the block from disk if not provided as argument, but is no longer needed. --- src/wallet/wallet.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index e19c40dbd1e16..bad82771703c4 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3534,7 +3534,6 @@ CWalletKey::CWalletKey(int64_t nExpires) int CMerkleTx::SetMerkleBranch(const CBlockIndex* pindex, int posInBlock) { AssertLockHeld(cs_main); - CBlock blockTmp; // Update the tx's hashBlock hashBlock = pindex->GetBlockHash(); From 8680d3aa800aa4fab8c321b92cc7f3fa97a8a0a3 Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Fri, 19 Aug 2016 15:50:48 -0700 Subject: [PATCH 0742/1802] Move wallet initialization logic from AppInit2 to CWallet::InitLoadWallet --- src/init.cpp | 12 ------------ src/wallet/wallet.cpp | 10 ++++++++++ 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index a15fe2e13b94f..1547afe6cfd95 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1438,15 +1438,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) //// debug print LogPrintf("mapBlockIndex.size() = %u\n", mapBlockIndex.size()); LogPrintf("nBestHeight = %d\n", chainActive.Height()); -#ifdef ENABLE_WALLET - if (pwalletMain) { - LOCK(pwalletMain->cs_wallet); - LogPrintf("setKeyPool.size() = %u\n", pwalletMain->GetKeyPoolSize()); - LogPrintf("mapWallet.size() = %u\n", pwalletMain->mapWallet.size()); - LogPrintf("mapAddressBook.size() = %u\n", pwalletMain->mapAddressBook.size()); - } -#endif - if (GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION)) StartTorControl(threadGroup, scheduler); @@ -1459,9 +1450,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) #ifdef ENABLE_WALLET if (pwalletMain) { - // Add wallet transactions that aren't already in a block to mapTransactions - pwalletMain->ReacceptWalletTransactions(); - // Run a thread to flush wallet periodically threadGroup.create_thread(boost::bind(&ThreadFlushWalletDB, boost::ref(pwalletMain->strWalletFile))); } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index ee9254050ce78..04f08e38c3e69 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3411,7 +3411,17 @@ bool CWallet::InitLoadWallet() } walletInstance->SetBroadcastTransactions(GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST)); + { + LOCK(walletInstance->cs_wallet); + LogPrintf("setKeyPool.size() = %u\n", walletInstance->GetKeyPoolSize()); + LogPrintf("mapWallet.size() = %u\n", walletInstance->mapWallet.size()); + LogPrintf("mapAddressBook.size() = %u\n", walletInstance->mapAddressBook.size()); + } + // Add wallet transactions that aren't already in a block to mapTransactions + walletInstance->ReacceptWalletTransactions(); + pwalletMain = walletInstance; + return true; } From fab1f9272c4999cd505f1e56eb348b5eb4bb38cb Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 21 Aug 2016 21:29:18 +0200 Subject: [PATCH 0743/1802] [contrib] verifybinaries: Adjust parsing to new rc path --- contrib/verifybinaries/README.md | 1 + contrib/verifybinaries/verify.sh | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/contrib/verifybinaries/README.md b/contrib/verifybinaries/README.md index 8970f3daa406a..d43a60ca0f5b0 100644 --- a/contrib/verifybinaries/README.md +++ b/contrib/verifybinaries/README.md @@ -10,4 +10,5 @@ Usage: ```sh ./verify.sh bitcoin-core-0.11.2 ./verify.sh bitcoin-core-0.12.0 +./verify.sh bitcoin-core-0.13.0-rc3 ``` diff --git a/contrib/verifybinaries/verify.sh b/contrib/verifybinaries/verify.sh index 657c3bd33c2e2..40759c36bc6cf 100755 --- a/contrib/verifybinaries/verify.sh +++ b/contrib/verifybinaries/verify.sh @@ -14,11 +14,11 @@ function clean_up { done } -WORKINGDIR="/tmp/bitcoin" +WORKINGDIR="/tmp/bitcoin_verify_binaries" TMPFILE="hashes.tmp" SIGNATUREFILENAME="SHA256SUMS.asc" -RCSUBDIR="test/" +RCSUBDIR="test" BASEDIR="https://bitcoin.org/bin/" VERSIONPREFIX="bitcoin-core-" RCVERSIONSTRING="rc" @@ -43,7 +43,7 @@ if [ -n "$1" ]; then # and simultaneously add RCSUBDIR to BASEDIR, where we will look for SIGNATUREFILENAME if [[ $VERSION == *"$RCVERSIONSTRING"* ]]; then BASEDIR="$BASEDIR${VERSION/%-$RCVERSIONSTRING*}/" - BASEDIR="$BASEDIR$RCSUBDIR" + BASEDIR="$BASEDIR$RCSUBDIR.$RCVERSIONSTRING${VERSION: -1}/" else BASEDIR="$BASEDIR$VERSION/" fi @@ -93,7 +93,7 @@ fi FILES=$(awk '{print $2}' "$TMPFILE") #and download these one by one -for file in in $FILES +for file in $FILES do wget --quiet -N "$BASEDIR$file" done From fa917f662346868486cdffce92a1fbe34980a72b Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 21 Aug 2016 21:37:21 +0200 Subject: [PATCH 0744/1802] [contrib] verifybinaries: Keep downloads by default --- contrib/verifybinaries/README.md | 6 ++++++ contrib/verifybinaries/verify.sh | 11 ++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/contrib/verifybinaries/README.md b/contrib/verifybinaries/README.md index d43a60ca0f5b0..516af8575f068 100644 --- a/contrib/verifybinaries/README.md +++ b/contrib/verifybinaries/README.md @@ -12,3 +12,9 @@ Usage: ./verify.sh bitcoin-core-0.12.0 ./verify.sh bitcoin-core-0.13.0-rc3 ``` + +If you do not want to keep the downloaded binaries, specify anything as the second parameter. + +```sh +./verify.sh bitcoin-core-0.13.0 delete +``` diff --git a/contrib/verifybinaries/verify.sh b/contrib/verifybinaries/verify.sh index 40759c36bc6cf..e22b911743b8f 100755 --- a/contrib/verifybinaries/verify.sh +++ b/contrib/verifybinaries/verify.sh @@ -108,11 +108,16 @@ if [ $? -eq 1 ]; then exit 1 elif [ $? -gt 1 ]; then echo "Error executing 'diff'" - exit 2 + exit 2 fi -#everything matches! clean up the mess -clean_up $FILES $SIGNATUREFILENAME $TMPFILE +if [ -n "$2" ]; then + echo "Clean up the binaries" + clean_up $FILES $SIGNATUREFILENAME $TMPFILE +else + echo "Keep the binaries in $WORKINGDIR" + clean_up $TMPFILE +fi echo -e "Verified hashes of \n$FILES" From faaed8874f83373e54a1878c5c7381ce47557bb8 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 21 Aug 2016 21:58:29 +0200 Subject: [PATCH 0745/1802] [contrib] verifybinaries: Mention mandatory preparation step --- contrib/verifybinaries/README.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/contrib/verifybinaries/README.md b/contrib/verifybinaries/README.md index 516af8575f068..ed3e14fb6c110 100644 --- a/contrib/verifybinaries/README.md +++ b/contrib/verifybinaries/README.md @@ -1,11 +1,24 @@ ### Verify Binaries + +#### Preparation: + +Make sure you obtain the proper release signing key and verify the fingerprint with several independent sources. + +```sh +$ gpg --fingerprint "Bitcoin Core binary release signing key" +pub 4096R/36C2E964 2015-06-24 [expires: 2017-02-13] + Key fingerprint = 01EA 5486 DE18 A882 D4C2 6845 90C8 019E 36C2 E964 +uid Wladimir J. van der Laan (Bitcoin Core binary release signing key) +``` + +#### Usage: + This script attempts to download the signature file `SHA256SUMS.asc` from https://bitcoin.org. It first checks if the signature passes, and then downloads the files specified in the file, and checks if the hashes of these files match those that are specified in the signature file. The script returns 0 if everything passes the checks. It returns 1 if either the signature check or the hash check doesn't pass. If an error occurs the return value is 2. -Usage: ```sh ./verify.sh bitcoin-core-0.11.2 From 653bb3d64057f11c5c9a8f539ba57be549097cee Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 22 Aug 2016 09:24:50 +0200 Subject: [PATCH 0746/1802] Add copyright header to wallet_text_fixture.cpp I created the file but forgot to add this header. --- src/wallet/test/wallet_test_fixture.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/wallet/test/wallet_test_fixture.cpp b/src/wallet/test/wallet_test_fixture.cpp index 9036ee26d83e0..a76db376179da 100644 --- a/src/wallet/test/wallet_test_fixture.cpp +++ b/src/wallet/test/wallet_test_fixture.cpp @@ -1,3 +1,7 @@ +// Copyright (c) 2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + #include "wallet/test/wallet_test_fixture.h" #include "rpc/server.h" From 67a55025a1ea5d0461139cd6764686a77524feed Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 3 May 2016 18:02:46 +0200 Subject: [PATCH 0747/1802] init: Fix typo in help message for -whitelistforcerelay Reported by pryds on Transifex in the Danish translation. --- src/init.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/init.cpp b/src/init.cpp index 5d29f14eb8821..d9b6f1eb1523b 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -379,7 +379,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-whitelist=", _("Whitelist peers connecting from the given netmask or IP address. 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")); strUsage += HelpMessageOpt("-whitelistrelay", strprintf(_("Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)"), DEFAULT_WHITELISTRELAY)); - strUsage += HelpMessageOpt("-whitelistforcerelay", strprintf(_("Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d)"), DEFAULT_WHITELISTFORCERELAY)); + strUsage += HelpMessageOpt("-whitelistforcerelay", strprintf(_("Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)"), DEFAULT_WHITELISTFORCERELAY)); strUsage += HelpMessageOpt("-maxuploadtarget=", strprintf(_("Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)"), DEFAULT_MAX_UPLOAD_TARGET)); #ifdef ENABLE_WALLET From fabfd5dae28cbe26e71d50dbfb6feab03673f27a Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 29 Jun 2016 11:53:07 +0200 Subject: [PATCH 0748/1802] [qa] pull-tester: Don't mute zmq ImportError --- qa/pull-tester/rpc-tests.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index 37979a933fc29..ff6c0d918fe77 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -94,12 +94,12 @@ if ENABLE_ZMQ: try: import zmq - except ImportError as e: - print("WARNING: \"import zmq\" failed. Set ENABLE_ZMQ=0 or " \ - "to run zmq tests, see dependency info in /qa/README.md.") - ENABLE_ZMQ=0 + except ImportError: + print("ERROR: \"import zmq\" failed. Set ENABLE_ZMQ=0 or " + "to run zmq tests, see dependency info in /qa/README.md.") + # ENABLE_ZMQ=0 + raise -#Tests testScripts = [ # longest test should go first, to favor running tests in parallel 'p2p-fullblocktest.py', From fa27c0a2c4545a579bf339e816c3fa785252b7dc Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 29 Jun 2016 11:48:51 +0200 Subject: [PATCH 0749/1802] [doc] Fix typos in comments, doxygen: Fix comment syntax --- src/chain.h | 10 +++---- src/consensus/validation.h | 6 ++-- src/rpc/protocol.h | 54 ++++++++++++++++++------------------ src/script/sign.h | 2 +- src/zmq/zmqpublishnotifier.h | 2 +- 5 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/chain.h b/src/chain.h index 76a774c1238f1..6588e8f57d2c2 100644 --- a/src/chain.h +++ b/src/chain.h @@ -137,15 +137,15 @@ enum BlockStatus: uint32_t { BLOCK_VALID_MASK = BLOCK_VALID_HEADER | BLOCK_VALID_TREE | BLOCK_VALID_TRANSACTIONS | BLOCK_VALID_CHAIN | BLOCK_VALID_SCRIPTS, - BLOCK_HAVE_DATA = 8, //! full block available in blk*.dat - BLOCK_HAVE_UNDO = 16, //! undo data available in rev*.dat + BLOCK_HAVE_DATA = 8, //!< full block available in blk*.dat + BLOCK_HAVE_UNDO = 16, //!< undo data available in rev*.dat BLOCK_HAVE_MASK = BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO, - BLOCK_FAILED_VALID = 32, //! stage after last reached validness failed - BLOCK_FAILED_CHILD = 64, //! descends from failed block + BLOCK_FAILED_VALID = 32, //!< stage after last reached validness failed + BLOCK_FAILED_CHILD = 64, //!< descends from failed block BLOCK_FAILED_MASK = BLOCK_FAILED_VALID | BLOCK_FAILED_CHILD, - BLOCK_OPT_WITNESS = 128, //! block data in blk*.data was received with a witness-enforcing client + BLOCK_OPT_WITNESS = 128, //!< block data in blk*.data was received with a witness-enforcing client }; /** The block chain is a tree shaped structure starting with the diff --git a/src/consensus/validation.h b/src/consensus/validation.h index 000b197270271..3e24294a64208 100644 --- a/src/consensus/validation.h +++ b/src/consensus/validation.h @@ -22,9 +22,9 @@ static const unsigned char REJECT_CHECKPOINT = 0x43; class CValidationState { private: enum mode_state { - MODE_VALID, //! everything ok - MODE_INVALID, //! network rule violation (DoS value may be set) - MODE_ERROR, //! run-time error + MODE_VALID, //!< everything ok + MODE_INVALID, //!< network rule violation (DoS value may be set) + MODE_ERROR, //!< run-time error } mode; int nDoS; std::string strRejectReason; diff --git a/src/rpc/protocol.h b/src/rpc/protocol.h index 55d0aac68b785..988e0fc5facb9 100644 --- a/src/rpc/protocol.h +++ b/src/rpc/protocol.h @@ -38,18 +38,18 @@ enum RPCErrorCode RPC_PARSE_ERROR = -32700, //! General application defined errors - RPC_MISC_ERROR = -1, //! std::exception thrown in command handling - RPC_FORBIDDEN_BY_SAFE_MODE = -2, //! Server is in safe mode, and command is not allowed in safe mode - RPC_TYPE_ERROR = -3, //! Unexpected type was passed as parameter - RPC_INVALID_ADDRESS_OR_KEY = -5, //! Invalid address or key - RPC_OUT_OF_MEMORY = -7, //! Ran out of memory during operation - RPC_INVALID_PARAMETER = -8, //! Invalid, missing or duplicate parameter - RPC_DATABASE_ERROR = -20, //! Database error - RPC_DESERIALIZATION_ERROR = -22, //! Error parsing or validating structure in raw format - RPC_VERIFY_ERROR = -25, //! General error during transaction or block submission - RPC_VERIFY_REJECTED = -26, //! Transaction or block was rejected by network rules - RPC_VERIFY_ALREADY_IN_CHAIN = -27, //! Transaction already in chain - RPC_IN_WARMUP = -28, //! Client still warming up + RPC_MISC_ERROR = -1, //!< std::exception thrown in command handling + RPC_FORBIDDEN_BY_SAFE_MODE = -2, //!< Server is in safe mode, and command is not allowed in safe mode + RPC_TYPE_ERROR = -3, //!< Unexpected type was passed as parameter + RPC_INVALID_ADDRESS_OR_KEY = -5, //!< Invalid address or key + RPC_OUT_OF_MEMORY = -7, //!< Ran out of memory during operation + RPC_INVALID_PARAMETER = -8, //!< Invalid, missing or duplicate parameter + RPC_DATABASE_ERROR = -20, //!< Database error + RPC_DESERIALIZATION_ERROR = -22, //!< Error parsing or validating structure in raw format + RPC_VERIFY_ERROR = -25, //!< General error during transaction or block submission + RPC_VERIFY_REJECTED = -26, //!< Transaction or block was rejected by network rules + RPC_VERIFY_ALREADY_IN_CHAIN = -27, //!< Transaction already in chain + RPC_IN_WARMUP = -28, //!< Client still warming up //! Aliases for backward compatibility RPC_TRANSACTION_ERROR = RPC_VERIFY_ERROR, @@ -57,23 +57,23 @@ enum RPCErrorCode RPC_TRANSACTION_ALREADY_IN_CHAIN= RPC_VERIFY_ALREADY_IN_CHAIN, //! P2P client errors - RPC_CLIENT_NOT_CONNECTED = -9, //! Bitcoin is not connected - RPC_CLIENT_IN_INITIAL_DOWNLOAD = -10, //! Still downloading initial blocks - RPC_CLIENT_NODE_ALREADY_ADDED = -23, //! Node is already added - RPC_CLIENT_NODE_NOT_ADDED = -24, //! Node has not been added before - RPC_CLIENT_NODE_NOT_CONNECTED = -29, //! Node to disconnect not found in connected nodes - RPC_CLIENT_INVALID_IP_OR_SUBNET = -30, //! Invalid IP/Subnet + RPC_CLIENT_NOT_CONNECTED = -9, //!< Bitcoin is not connected + RPC_CLIENT_IN_INITIAL_DOWNLOAD = -10, //!< Still downloading initial blocks + RPC_CLIENT_NODE_ALREADY_ADDED = -23, //!< Node is already added + RPC_CLIENT_NODE_NOT_ADDED = -24, //!< Node has not been added before + RPC_CLIENT_NODE_NOT_CONNECTED = -29, //!< Node to disconnect not found in connected nodes + RPC_CLIENT_INVALID_IP_OR_SUBNET = -30, //!< Invalid IP/Subnet //! Wallet errors - RPC_WALLET_ERROR = -4, //! Unspecified problem with wallet (key not found etc.) - RPC_WALLET_INSUFFICIENT_FUNDS = -6, //! Not enough funds in wallet or account - RPC_WALLET_INVALID_ACCOUNT_NAME = -11, //! Invalid account name - RPC_WALLET_KEYPOOL_RAN_OUT = -12, //! Keypool ran out, call keypoolrefill first - RPC_WALLET_UNLOCK_NEEDED = -13, //! Enter the wallet passphrase with walletpassphrase first - RPC_WALLET_PASSPHRASE_INCORRECT = -14, //! The wallet passphrase entered was incorrect - RPC_WALLET_WRONG_ENC_STATE = -15, //! Command given in wrong wallet encryption state (encrypting an encrypted wallet etc.) - RPC_WALLET_ENCRYPTION_FAILED = -16, //! Failed to encrypt the wallet - RPC_WALLET_ALREADY_UNLOCKED = -17, //! Wallet is already unlocked + RPC_WALLET_ERROR = -4, //!< Unspecified problem with wallet (key not found etc.) + RPC_WALLET_INSUFFICIENT_FUNDS = -6, //!< Not enough funds in wallet or account + RPC_WALLET_INVALID_ACCOUNT_NAME = -11, //!< Invalid account name + RPC_WALLET_KEYPOOL_RAN_OUT = -12, //!< Keypool ran out, call keypoolrefill first + RPC_WALLET_UNLOCK_NEEDED = -13, //!< Enter the wallet passphrase with walletpassphrase first + RPC_WALLET_PASSPHRASE_INCORRECT = -14, //!< The wallet passphrase entered was incorrect + RPC_WALLET_WRONG_ENC_STATE = -15, //!< Command given in wrong wallet encryption state (encrypting an encrypted wallet etc.) + RPC_WALLET_ENCRYPTION_FAILED = -16, //!< Failed to encrypt the wallet + RPC_WALLET_ALREADY_UNLOCKED = -17, //!< Wallet is already unlocked }; std::string JSONRPCRequest(const std::string& strMethod, const UniValue& params, const UniValue& id); diff --git a/src/script/sign.h b/src/script/sign.h index 6404b4523ecaa..f9aa6fca27119 100644 --- a/src/script/sign.h +++ b/src/script/sign.h @@ -51,7 +51,7 @@ class MutableTransactionSignatureCreator : public TransactionSignatureCreator { MutableTransactionSignatureCreator(const CKeyStore* keystoreIn, const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amount, int nHashTypeIn) : TransactionSignatureCreator(keystoreIn, &tx, nInIn, amount, nHashTypeIn), tx(*txToIn) {} }; -/** A signature creator that just produces 72-byte empty signatyres. */ +/** A signature creator that just produces 72-byte empty signatures. */ class DummySignatureCreator : public BaseSignatureCreator { public: DummySignatureCreator(const CKeyStore* keystoreIn) : BaseSignatureCreator(keystoreIn) {} diff --git a/src/zmq/zmqpublishnotifier.h b/src/zmq/zmqpublishnotifier.h index 22f02a3d0dbb8..751ded39572d7 100644 --- a/src/zmq/zmqpublishnotifier.h +++ b/src/zmq/zmqpublishnotifier.h @@ -12,7 +12,7 @@ class CBlockIndex; class CZMQAbstractPublishNotifier : public CZMQAbstractNotifier { private: - uint32_t nSequence; //! upcounting per message sequence number + uint32_t nSequence; //!< upcounting per message sequence number public: From fafe7b3432d5117e3f207eafe2fca1f9637b24f6 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Fri, 1 Jul 2016 12:39:04 +0200 Subject: [PATCH 0750/1802] contrib: Make fix-copyright-headers.py more portable --- contrib/devtools/fix-copyright-headers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/devtools/fix-copyright-headers.py b/contrib/devtools/fix-copyright-headers.py index b6414a551f870..31a81ae4fadb5 100755 --- a/contrib/devtools/fix-copyright-headers.py +++ b/contrib/devtools/fix-copyright-headers.py @@ -16,7 +16,7 @@ import re year = time.gmtime()[0] -CMD_GIT_DATE = 'git log --format=@%%at -1 %s | date +"%%Y" -u -f -' +CMD_GIT_DATE = 'git log --format=%%ad --date=short -1 %s | cut -d"-" -f 1' CMD_REGEX= "perl -pi -e 's/(20\d\d)(?:-20\d\d)? The Bitcoin/$1-%s The Bitcoin/' %s" REGEX_CURRENT= re.compile("%s The Bitcoin" % year) CMD_LIST_FILES= "find %s | grep %s" From 7bd5ff46237b06b3cf223176c1c71ef66383fa92 Mon Sep 17 00:00:00 2001 From: Christian Barcenas Date: Mon, 22 Aug 2016 20:49:36 -0400 Subject: [PATCH 0751/1802] Trivial: Fix two VarInt examples in serialize.h --- src/serialize.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/serialize.h b/src/serialize.h index 378ed39074ea3..04ab9aa2e7762 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -322,8 +322,8 @@ uint64_t ReadCompactSize(Stream& is) * 0: [0x00] 256: [0x81 0x00] * 1: [0x01] 16383: [0xFE 0x7F] * 127: [0x7F] 16384: [0xFF 0x00] - * 128: [0x80 0x00] 16511: [0x80 0xFF 0x7F] - * 255: [0x80 0x7F] 65535: [0x82 0xFD 0x7F] + * 128: [0x80 0x00] 16511: [0xFF 0x7F] + * 255: [0x80 0x7F] 65535: [0x82 0xFE 0x7F] * 2^32: [0x8E 0xFE 0xFE 0xFF 0x00] */ From 259ee09f88dbf0ce1a580d3aa93b4d82acadf8f0 Mon Sep 17 00:00:00 2001 From: R E Broadley Date: Tue, 23 Aug 2016 13:09:27 +0700 Subject: [PATCH 0752/1802] Show "end" instead of many zeros when getheaders request received with a hashStop of Null. --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 27ab677eb1510..7d1686c2fa91f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5387,7 +5387,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // we must use CBlocks, as CBlockHeaders won't include the 0x00 nTx count at the end vector vHeaders; int nLimit = MAX_HEADERS_RESULTS; - LogPrint("net", "getheaders %d to %s from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString(), pfrom->id); + LogPrint("net", "getheaders %d to %s from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ? "end" : hashStop.ToString(), pfrom->id); for (; pindex; pindex = chainActive.Next(pindex)) { vHeaders.push_back(pindex->GetBlockHeader()); From 878faacd7b3daac437cc689b13422f6432fb5cd0 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Tue, 23 Aug 2016 16:55:15 +1000 Subject: [PATCH 0753/1802] Add configure check for -latomic --- build-aux/m4/l_atomic.m4 | 40 ++++++++++++++++++++++++++++++++++++++++ configure.ac | 3 +++ 2 files changed, 43 insertions(+) create mode 100644 build-aux/m4/l_atomic.m4 diff --git a/build-aux/m4/l_atomic.m4 b/build-aux/m4/l_atomic.m4 new file mode 100644 index 0000000000000..906724b6405d8 --- /dev/null +++ b/build-aux/m4/l_atomic.m4 @@ -0,0 +1,40 @@ +# Some versions of gcc/libstdc++ require linking with -latomic if +# using the C++ atomic library. +# +# Sourced from http://bugs.debian.org/797228 + +m4_define([_CHECK_ATOMIC_testbody], [[ + #include + #include + + int main() { + std::atomic a{}; + + int64_t v = 5; + int64_t r = a.fetch_add(v); + return static_cast(r); + } +]]) + +AC_DEFUN([CHECK_ATOMIC], [ + + AC_LANG_PUSH(C++) + + AC_MSG_CHECKING([whether std::atomic can be used without link library]) + + AC_LINK_IFELSE([AC_LANG_SOURCE([_CHECK_ATOMIC_testbody])],[ + AC_MSG_RESULT([yes]) + ],[ + AC_MSG_RESULT([no]) + LIBS="$LIBS -latomic" + AC_MSG_CHECKING([whether std::atomic needs -latomic]) + AC_LINK_IFELSE([AC_LANG_SOURCE([_CHECK_ATOMIC_testbody])],[ + AC_MSG_RESULT([yes]) + ],[ + AC_MSG_RESULT([no]) + AC_MSG_FAILURE([cannot figure our how to use std::atomic]) + ]) + ]) + + AC_LANG_POP +]) diff --git a/configure.ac b/configure.ac index d332f4face3ee..335609f5e5a48 100644 --- a/configure.ac +++ b/configure.ac @@ -57,6 +57,9 @@ case $host in esac dnl Require C++11 compiler (no GNU extensions) AX_CXX_COMPILE_STDCXX([11], [noext], [mandatory]) +dnl Check if -latomic is required for +CHECK_ATOMIC + dnl Libtool init checks. LT_INIT([pic-only]) From 15860448d38ba7a436cf7c08fa5c0132fe10f8d3 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Sat, 20 Aug 2016 11:19:35 +0200 Subject: [PATCH 0754/1802] [Qt] RPC-Console: support nested commands and simple value queries Commands can be executed with bracket syntax, example: `getwalletinfo()`. Commands can be nested, example: `sendtoaddress(getnewaddress(), 10)`. Simple queries are possible: `listunspent()[0][txid]` Object values are accessed with a non-quoted string, example: [txid]. Fully backward compatible. `generate 101` is identical to `generate(101)` Result value queries indicated with `[]` require the new brackets syntax. Comma as argument separator is now also possible: `sendtoaddress,
,` Space as argument separator works also with the bracket syntax, example: `sendtoaddress(getnewaddress() 10) No dept limitation, complex commands are possible: `decoderawtransaction(getrawtransaction(getblock(getbestblockhash())[tx][0]))[vout][0][value]` --- src/Makefile.qttest.include | 6 +- src/qt/rpcconsole.cpp | 229 +++++++++++++++++++++++---------- src/qt/rpcconsole.h | 2 + src/qt/test/rpcnestedtests.cpp | 93 +++++++++++++ src/qt/test/rpcnestedtests.h | 25 ++++ src/qt/test/test_main.cpp | 16 ++- 6 files changed, 300 insertions(+), 71 deletions(-) create mode 100644 src/qt/test/rpcnestedtests.cpp create mode 100644 src/qt/test/rpcnestedtests.h diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include index 813a343ffa395..0a7efb5d5b2e5 100644 --- a/src/Makefile.qttest.include +++ b/src/Makefile.qttest.include @@ -1,13 +1,16 @@ bin_PROGRAMS += qt/test/test_bitcoin-qt TESTS += qt/test/test_bitcoin-qt -TEST_QT_MOC_CPP = qt/test/moc_uritests.cpp +TEST_QT_MOC_CPP = \ + qt/test/moc_rpcnestedtests.cpp \ + qt/test/moc_uritests.cpp if ENABLE_WALLET TEST_QT_MOC_CPP += qt/test/moc_paymentservertests.cpp endif TEST_QT_H = \ + qt/test/rpcnestedtests.h \ qt/test/uritests.h \ qt/test/paymentrequestdata.h \ qt/test/paymentservertests.h @@ -16,6 +19,7 @@ qt_test_test_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_ $(QT_INCLUDES) $(QT_TEST_INCLUDES) $(PROTOBUF_CFLAGS) qt_test_test_bitcoin_qt_SOURCES = \ + qt/test/rpcnestedtests.cpp \ qt/test/test_main.cpp \ qt/test/uritests.cpp \ $(TEST_QT_H) diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index bcaa9164c91ba..0456b89da2a16 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -113,9 +113,11 @@ class QtRPCTimerInterface: public RPCTimerInterface #include "rpcconsole.moc" /** - * Split shell command line into a list of arguments. Aims to emulate \c bash and friends. + * Split shell command line into a list of arguments and execute the command(s). + * Aims to emulate \c bash and friends. * - * - Arguments are delimited with whitespace + * - Command nesting is possible with brackets [example: validateaddress(getnewaddress())] + * - Arguments are delimited with whitespace or comma * - Extra whitespace at the beginning and end and between arguments will be ignored * - Text can be "double" or 'single' quoted * - The backslash \c \ is used as escape character @@ -123,11 +125,15 @@ class QtRPCTimerInterface: public RPCTimerInterface * - Within double quotes, only escape \c " and backslashes before a \c " or another backslash * - Within single quotes, no escaping is possible and no special interpretation takes place * - * @param[out] args Parsed arguments will be appended to this list + * @param[out] result stringified Result from the executed command(chain) * @param[in] strCommand Command line to split */ -bool parseCommandLine(std::vector &args, const std::string &strCommand) + +bool RPCConsole::RPCExecuteCommandLine(std::string &strResult, const std::string &strCommand) { + std::vector< std::vector > stack; + stack.push_back(std::vector()); + enum CmdParseState { STATE_EATING_SPACES, @@ -135,95 +141,180 @@ bool parseCommandLine(std::vector &args, const std::string &strComm STATE_SINGLEQUOTED, STATE_DOUBLEQUOTED, STATE_ESCAPE_OUTER, - STATE_ESCAPE_DOUBLEQUOTED + STATE_ESCAPE_DOUBLEQUOTED, + STATE_COMMAND_EXECUTED, + STATE_COMMAND_EXECUTED_INNER } state = STATE_EATING_SPACES; std::string curarg; - Q_FOREACH(char ch, strCommand) + UniValue lastResult; + + std::string strCommandTerminated = strCommand; + if (strCommandTerminated.back() != '\n') + strCommandTerminated += "\n"; + for(char ch: strCommandTerminated) { switch(state) { - case STATE_ARGUMENT: // In or after argument - case STATE_EATING_SPACES: // Handle runs of whitespace - switch(ch) + case STATE_COMMAND_EXECUTED_INNER: + case STATE_COMMAND_EXECUTED: { - case '"': state = STATE_DOUBLEQUOTED; break; - case '\'': state = STATE_SINGLEQUOTED; break; - case '\\': state = STATE_ESCAPE_OUTER; break; - case ' ': case '\n': case '\t': - if(state == STATE_ARGUMENT) // Space ends argument + bool breakParsing = true; + switch(ch) { - args.push_back(curarg); - curarg.clear(); + case '[': curarg.clear(); state = STATE_COMMAND_EXECUTED_INNER; break; + default: + if (state == STATE_COMMAND_EXECUTED_INNER) + { + if (ch != ']') + { + // append char to the current argument (which is also used for the query command) + curarg += ch; + break; + } + if (curarg.size()) + { + // if we have a value query, query arrays with index and objects with a string key + UniValue subelement; + if (lastResult.isArray()) + { + for(char argch: curarg) + if (!std::isdigit(argch)) + throw std::runtime_error("Invalid result query"); + subelement = lastResult[atoi(curarg.c_str())]; + } + else if (lastResult.isObject()) + subelement = find_value(lastResult, curarg); + else + throw std::runtime_error("Invalid result query"); //no array or object: abort + lastResult = subelement; + } + + state = STATE_COMMAND_EXECUTED; + break; + } + // don't break parsing when the char is required for the next argument + breakParsing = false; + + // pop the stack and return the result to the current command arguments + stack.pop_back(); + + // don't stringify the json in case of a string to avoid doublequotes + if (lastResult.isStr()) + curarg = lastResult.get_str(); + else + curarg = lastResult.write(2); + + // if we have a non empty result, use it as stack argument otherwise as general result + if (curarg.size()) + { + if (stack.size()) + stack.back().push_back(curarg); + else + strResult = curarg; + } + curarg.clear(); + // assume eating space state + state = STATE_EATING_SPACES; } - state = STATE_EATING_SPACES; - break; - default: curarg += ch; state = STATE_ARGUMENT; + if (breakParsing) + break; } - break; - case STATE_SINGLEQUOTED: // Single-quoted string - switch(ch) + case STATE_ARGUMENT: // In or after argument + case STATE_EATING_SPACES: // Handle runs of whitespace + switch(ch) { - case '\'': state = STATE_ARGUMENT; break; - default: curarg += ch; + case '"': state = STATE_DOUBLEQUOTED; break; + case '\'': state = STATE_SINGLEQUOTED; break; + case '\\': state = STATE_ESCAPE_OUTER; break; + case '(': case ')': case '\n': + if (state == STATE_ARGUMENT) + { + if (ch == '(' && stack.size() && stack.back().size() > 0) + stack.push_back(std::vector()); + if (curarg.size()) + { + // don't allow commands after executed commands on baselevel + if (!stack.size()) + throw std::runtime_error("Invalid Syntax"); + stack.back().push_back(curarg); + } + curarg.clear(); + state = STATE_EATING_SPACES; + } + if ((ch == ')' || ch == '\n') && stack.size() > 0) + { + std::string strPrint; + // Convert argument list to JSON objects in method-dependent way, + // and pass it along with the method name to the dispatcher. + lastResult = tableRPC.execute(stack.back()[0], RPCConvertValues(stack.back()[0], std::vector(stack.back().begin() + 1, stack.back().end()))); + + state = STATE_COMMAND_EXECUTED; + curarg.clear(); + } + break; + case ' ': case ',': case '\t': + if(state == STATE_ARGUMENT) // Space ends argument + { + if (curarg.size()) + stack.back().push_back(curarg); + curarg.clear(); + } + state = STATE_EATING_SPACES; + break; + default: curarg += ch; state = STATE_ARGUMENT; } - break; - case STATE_DOUBLEQUOTED: // Double-quoted string - switch(ch) + break; + case STATE_SINGLEQUOTED: // Single-quoted string + switch(ch) { - case '"': state = STATE_ARGUMENT; break; - case '\\': state = STATE_ESCAPE_DOUBLEQUOTED; break; - default: curarg += ch; + case '\'': state = STATE_ARGUMENT; break; + default: curarg += ch; } - break; - case STATE_ESCAPE_OUTER: // '\' outside quotes - curarg += ch; state = STATE_ARGUMENT; - break; - case STATE_ESCAPE_DOUBLEQUOTED: // '\' in double-quoted text - if(ch != '"' && ch != '\\') curarg += '\\'; // keep '\' for everything but the quote and '\' itself - curarg += ch; state = STATE_DOUBLEQUOTED; - break; + break; + case STATE_DOUBLEQUOTED: // Double-quoted string + switch(ch) + { + case '"': state = STATE_ARGUMENT; break; + case '\\': state = STATE_ESCAPE_DOUBLEQUOTED; break; + default: curarg += ch; + } + break; + case STATE_ESCAPE_OUTER: // '\' outside quotes + curarg += ch; state = STATE_ARGUMENT; + break; + case STATE_ESCAPE_DOUBLEQUOTED: // '\' in double-quoted text + if(ch != '"' && ch != '\\') curarg += '\\'; // keep '\' for everything but the quote and '\' itself + curarg += ch; state = STATE_DOUBLEQUOTED; + break; } } switch(state) // final state { - case STATE_EATING_SPACES: - return true; - case STATE_ARGUMENT: - args.push_back(curarg); - return true; - default: // ERROR to end in one of the other states - return false; + case STATE_COMMAND_EXECUTED: + if (lastResult.isStr()) + strResult = lastResult.get_str(); + else + strResult = lastResult.write(2); + case STATE_ARGUMENT: + case STATE_EATING_SPACES: + return true; + default: // ERROR to end in one of the other states + return false; } } void RPCExecutor::request(const QString &command) { - std::vector args; - if(!parseCommandLine(args, command.toStdString())) - { - Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \"")); - return; - } - if(args.empty()) - return; // Nothing to do try { - std::string strPrint; - // Convert argument list to JSON objects in method-dependent way, - // and pass it along with the method name to the dispatcher. - UniValue result = tableRPC.execute( - args[0], - RPCConvertValues(args[0], std::vector(args.begin() + 1, args.end()))); - - // Format result reply - if (result.isNull()) - strPrint = ""; - else if (result.isStr()) - strPrint = result.get_str(); - else - strPrint = result.write(2); - - Q_EMIT reply(RPCConsole::CMD_REPLY, QString::fromStdString(strPrint)); + std::string result; + std::string executableCommand = command.toStdString() + "\n"; + if(!RPCConsole::RPCExecuteCommandLine(result, executableCommand)) + { + Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \"")); + return; + } + Q_EMIT reply(RPCConsole::CMD_REPLY, QString::fromStdString(result)); } catch (UniValue& objError) { diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 28affa954dca2..50224a1cc0bf1 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -35,6 +35,8 @@ class RPCConsole: public QWidget explicit RPCConsole(const PlatformStyle *platformStyle, QWidget *parent); ~RPCConsole(); + static bool RPCExecuteCommandLine(std::string &strResult, const std::string &strCommand); + void setClientModel(ClientModel *model); enum MessageClass { diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp new file mode 100644 index 0000000000000..3dae33bafbbbf --- /dev/null +++ b/src/qt/test/rpcnestedtests.cpp @@ -0,0 +1,93 @@ +// Copyright (c) 2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "rpcnestedtests.h" + +#include "chainparams.h" +#include "consensus/validation.h" +#include "main.h" +#include "rpc/register.h" +#include "rpc/server.h" +#include "rpcconsole.h" +#include "test/testutil.h" +#include "univalue.h" +#include "util.h" + +#include + +#include + +void RPCNestedTests::rpcNestedTests() +{ + UniValue jsonRPCError; + + // do some test setup + // could be moved to a more generic place when we add more tests on QT level + const CChainParams& chainparams = Params(); + RegisterAllCoreRPCCommands(tableRPC); + ClearDatadirCache(); + std::string path = QDir::tempPath().toStdString() + "/" + strprintf("test_bitcoin_qt_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000))); + QDir dir(QString::fromStdString(path)); + dir.mkpath("."); + mapArgs["-datadir"] = path; + //mempool.setSanityCheck(1.0); + pblocktree = new CBlockTreeDB(1 << 20, true); + pcoinsdbview = new CCoinsViewDB(1 << 23, true); + pcoinsTip = new CCoinsViewCache(pcoinsdbview); + InitBlockIndex(chainparams); + { + CValidationState state; + bool ok = ActivateBestChain(state, chainparams); + QVERIFY(ok); + } + + SetRPCWarmupFinished(); + + std::string result; + std::string result2; + RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo()[chain]"); //simple result filtering with path + QVERIFY(result=="main"); + + RPCConsole::RPCExecuteCommandLine(result, "getblock(getbestblockhash())"); //simple 2 level nesting + RPCConsole::RPCExecuteCommandLine(result, "getblock(getblock(getbestblockhash())[hash], true)"); + + RPCConsole::RPCExecuteCommandLine(result, "getblock( getblock( getblock(getbestblockhash())[hash] )[hash], true)"); //4 level nesting with whitespace, filtering path and boolean parameter + + RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo"); + QVERIFY(result.substr(0,1) == "{"); + + RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo()"); + QVERIFY(result.substr(0,1) == "{"); + + RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo "); //whitespace at the end will be tolerated + QVERIFY(result.substr(0,1) == "{"); + +#if QT_VERSION >= 0x050300 + // do the QVERIFY_EXCEPTION_THROWN checks only with Qt5.3 and higher (QVERIFY_EXCEPTION_THROWN was introduced in Qt5.3) + QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo() .\n"), std::runtime_error); //invalid syntax + QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo() getblockchaininfo()"), std::runtime_error); //invalid syntax + (RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo(")); //tolerate non closing brackets if we have no arguments + (RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo()()()")); //tolerate non command brackts + QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo(True)"), UniValue); //invalid argument + QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "a(getblockchaininfo(True))"), UniValue); //method not found +#endif + + (RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo()[\"chain\"]")); //Quote path identifier are allowed, but look after a child contaning the quotes in the key + QVERIFY(result == "null"); + + (RPCConsole::RPCExecuteCommandLine(result, "createrawtransaction [] {} 0")); //parameter not in brackets are allowed + (RPCConsole::RPCExecuteCommandLine(result2, "createrawtransaction([],{},0)")); //parameter in brackets are allowed + QVERIFY(result == result2); + (RPCConsole::RPCExecuteCommandLine(result2, "createrawtransaction( [], {} , 0 )")); //whitespace between parametres is allowed + QVERIFY(result == result2); + + RPCConsole::RPCExecuteCommandLine(result, "getblock(getbestblockhash())[tx][0]"); + QVERIFY(result == "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); + + delete pcoinsTip; + delete pcoinsdbview; + delete pblocktree; + + boost::filesystem::remove_all(boost::filesystem::path(path)); +} diff --git a/src/qt/test/rpcnestedtests.h b/src/qt/test/rpcnestedtests.h new file mode 100644 index 0000000000000..9ad409019f281 --- /dev/null +++ b/src/qt/test/rpcnestedtests.h @@ -0,0 +1,25 @@ +// Copyright (c) 2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_QT_TEST_RPC_NESTED_TESTS_H +#define BITCOIN_QT_TEST_RPC_NESTED_TESTS_H + +#include +#include + +#include "txdb.h" +#include "txmempool.h" + +class RPCNestedTests : public QObject +{ + Q_OBJECT + + private Q_SLOTS: + void rpcNestedTests(); + +private: + CCoinsViewDB *pcoinsdbview; +}; + +#endif // BITCOIN_QT_TEST_RPC_NESTED_TESTS_H diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp index db193420bfb6e..dbaab54fb65b4 100644 --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2015 The Bitcoin Core developers +// Copyright (c) 2009-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -6,6 +6,9 @@ #include "config/bitcoin-config.h" #endif +#include "chainparams.h" +#include "key.h" +#include "rpcnestedtests.h" #include "util.h" #include "uritests.h" @@ -27,10 +30,17 @@ Q_IMPORT_PLUGIN(qtwcodecs) Q_IMPORT_PLUGIN(qkrcodecs) #endif +extern void noui_connect(); + // This is all you need to run all the tests int main(int argc, char *argv[]) { + ECC_Start(); SetupEnvironment(); + SetupNetworking(); + SelectParams(CBaseChainParams::MAIN); + noui_connect(); + bool fInvalid = false; // Don't remove this, it's needed to access @@ -48,6 +58,10 @@ int main(int argc, char *argv[]) if (QTest::qExec(&test2) != 0) fInvalid = true; #endif + RPCNestedTests test3; + if (QTest::qExec(&test3) != 0) + fInvalid = true; + ECC_Stop(); return fInvalid; } From beef966e365e16a9b041321e404f7cd21a4e999e Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 23 Aug 2016 15:36:23 +0200 Subject: [PATCH 0755/1802] [Wallet] remove unused code/conditions in ReadAtCursor --- src/wallet/db.cpp | 2 +- src/wallet/db.h | 10 ++++------ src/wallet/walletdb.cpp | 8 ++++---- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index cfd007ca1c807..652bbebded844 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -387,7 +387,7 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip) while (fSuccess) { CDataStream ssKey(SER_DISK, CLIENT_VERSION); CDataStream ssValue(SER_DISK, CLIENT_VERSION); - int ret = db.ReadAtCursor(pcursor, ssKey, ssValue, DB_NEXT); + int ret = db.ReadAtCursor(pcursor, ssKey, ssValue); if (ret == DB_NOTFOUND) { pcursor->close(); break; diff --git a/src/wallet/db.h b/src/wallet/db.h index 01b8c71a04bbb..a0f673ecfc46f 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -228,19 +228,17 @@ class CDB return pcursor; } - int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, unsigned int fFlags = DB_NEXT) + int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, bool setRange = false) { // Read at cursor Dbt datKey; - if (fFlags == DB_SET || fFlags == DB_SET_RANGE || fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE) { + unsigned int fFlags = DB_NEXT; + if (setRange) { datKey.set_data(&ssKey[0]); datKey.set_size(ssKey.size()); + fFlags = DB_SET_RANGE; } Dbt datValue; - if (fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE) { - datValue.set_data(&ssValue[0]); - datValue.set_size(ssValue.size()); - } datKey.set_flags(DB_DBT_MALLOC); datValue.set_flags(DB_DBT_MALLOC); int ret = pcursor->get(&datKey, &datValue, fFlags); diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index f824492cb6fd4..a8072f1d28339 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -216,16 +216,16 @@ void CWalletDB::ListAccountCreditDebit(const string& strAccount, list Date: Tue, 23 Aug 2016 17:46:54 +0200 Subject: [PATCH 0756/1802] doc: Add historical release notes for 0.12.1 0.13.0 --- doc/release-notes/release-notes-0.12.1.md | 198 +++++ doc/release-notes/release-notes-0.13.0.md | 863 ++++++++++++++++++++++ 2 files changed, 1061 insertions(+) create mode 100644 doc/release-notes/release-notes-0.12.1.md create mode 100644 doc/release-notes/release-notes-0.13.0.md diff --git a/doc/release-notes/release-notes-0.12.1.md b/doc/release-notes/release-notes-0.12.1.md new file mode 100644 index 0000000000000..610cd481de485 --- /dev/null +++ b/doc/release-notes/release-notes-0.12.1.md @@ -0,0 +1,198 @@ +Bitcoin Core version 0.12.1 is now available from: + + + +This is a new minor version release, including the BIP9, BIP68 and BIP112 +softfork, various bugfixes and updated translations. + +Please report bugs using the issue tracker at github: + + + +Upgrading and downgrading +========================= + +How to Upgrade +-------------- + +If you are running an older version, shut it down. Wait until it has completely +shut down (which might take a few minutes for older versions), then run the +installer (on Windows) or just copy over /Applications/Bitcoin-Qt (on Mac) or +bitcoind/bitcoin-qt (on Linux). + +Downgrade warning +----------------- + +### Downgrade to a version < 0.12.0 + +Because release 0.12.0 and later will obfuscate the chainstate on every +fresh sync or reindex, the chainstate is not backwards-compatible with +pre-0.12 versions of Bitcoin Core or other software. + +If you want to downgrade after you have done a reindex with 0.12.0 or later, +you will need to reindex when you first start Bitcoin Core version 0.11 or +earlier. + +Notable changes +=============== + +First version bits BIP9 softfork deployment +------------------------------------------- + +This release includes a soft fork deployment to enforce [BIP68][], +[BIP112][] and [BIP113][] using the [BIP9][] deployment mechanism. + +The deployment sets the block version number to 0x20000001 between +midnight 1st May 2016 and midnight 1st May 2017 to signal readiness for +deployment. The version number consists of 0x20000000 to indicate version +bits together with setting bit 0 to indicate support for this combined +deployment, shown as "csv" in the `getblockchaininfo` RPC call. + +For more information about the soft forking change, please see + + +This specific backport pull-request can be viewed at + + +[BIP9]: https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki +[BIP68]: https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki +[BIP112]: https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki +[BIP113]: https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki + +BIP68 soft fork to enforce sequence locks for relative locktime +--------------------------------------------------------------- + +[BIP68][] introduces relative lock-time consensus-enforced semantics of +the sequence number field to enable a signed transaction input to remain +invalid for a defined period of time after confirmation of its corresponding +outpoint. + +For more information about the implementation, see + + +BIP112 soft fork to enforce OP_CHECKSEQUENCEVERIFY +-------------------------------------------------- + +[BIP112][] redefines the existing OP_NOP3 as OP_CHECKSEQUENCEVERIFY (CSV) +for a new opcode in the Bitcoin scripting system that in combination with +[BIP68][] allows execution pathways of a script to be restricted based +on the age of the output being spent. + +For more information about the implementation, see + + +BIP113 locktime enforcement soft fork +------------------------------------- + +Bitcoin Core 0.11.2 previously introduced mempool-only locktime +enforcement using GetMedianTimePast(). This release seeks to +consensus enforce the rule. + +Bitcoin transactions currently may specify a locktime indicating when +they may be added to a valid block. Current consensus rules require +that blocks have a block header time greater than the locktime specified +in any transaction in that block. + +Miners get to choose what time they use for their header time, with the +consensus rule being that no node will accept a block whose time is more +than two hours in the future. This creates a incentive for miners to +set their header times to future values in order to include locktimed +transactions which weren't supposed to be included for up to two more +hours. + +The consensus rules also specify that valid blocks may have a header +time greater than that of the median of the 11 previous blocks. This +GetMedianTimePast() time has a key feature we generally associate with +time: it can't go backwards. + +[BIP113][] specifies a soft fork enforced in this release that +weakens this perverse incentive for individual miners to use a future +time by requiring that valid blocks have a computed GetMedianTimePast() +greater than the locktime specified in any transaction in that block. + +Mempool inclusion rules currently require transactions to be valid for +immediate inclusion in a block in order to be accepted into the mempool. +This release begins applying the BIP113 rule to received transactions, +so transaction whose time is greater than the GetMedianTimePast() will +no longer be accepted into the mempool. + +**Implication for miners:** you will begin rejecting transactions that +would not be valid under BIP113, which will prevent you from producing +invalid blocks when BIP113 is enforced on the network. Any +transactions which are valid under the current rules but not yet valid +under the BIP113 rules will either be mined by other miners or delayed +until they are valid under BIP113. Note, however, that time-based +locktime transactions are more or less unseen on the network currently. + +**Implication for users:** GetMedianTimePast() always trails behind the +current time, so a transaction locktime set to the present time will be +rejected by nodes running this release until the median time moves +forward. To compensate, subtract one hour (3,600 seconds) from your +locktimes to allow those transactions to be included in mempools at +approximately the expected time. + +For more information about the implementation, see + + +Miscellaneous +------------- + +The p2p alert system is off by default. To turn on, use `-alert` with +startup configuration. + +0.12.1 Change log +================= + +Detailed release notes follow. This overview includes changes that affect +behavior, not code moves, refactors and string updates. For convenience in locating +the code changes and accompanying discussion, both the pull request and +git merge commit are mentioned. + +### RPC and other APIs +- #7739 `7ffc2bd` Add abandoned status to listtransactions (jonasschnelli) + +### Block and transaction handling +- #7543 `834aaef` Backport BIP9, BIP68 and BIP112 with softfork (btcdrak) + +### P2P protocol and network code +- #7804 `90f1d24` Track block download times per individual block (sipa) +- #7832 `4c3a00d` Reduce block timeout to 10 minutes (laanwj) + +### Validation +- #7821 `4226aac` init: allow shutdown during 'Activating best chain...' (laanwj) +- #7835 `46898e7` Version 2 transactions remain non-standard until CSV activates (sdaftuar) + +### Build system +- #7487 `00d57b4` Workaround Travis-side CI issues (luke-jr) +- #7606 `a10da9a` No need to set -L and --location for curl (MarcoFalke) +- #7614 `ca8f160` Add curl to packages (now needed for depends) (luke-jr) +- #7776 `a784675` Remove unnecessary executables from gitian release (laanwj) + +### Wallet +- #7715 `19866c1` Fix calculation of balances and available coins. (morcos) + +### Miscellaneous +- #7617 `f04f4fd` Fix markdown syntax and line terminate LogPrint (MarcoFalke) +- #7747 `4d035bc` added depends cross compile info (accraze) +- #7741 `a0cea89` Mark p2p alert system as deprecated (btcdrak) +- #7780 `c5f94f6` Disable bad-chain alert (btcdrak) + +Credits +======= + +Thanks to everyone who directly contributed to this release: + +- accraze +- Alex Morcos +- BtcDrak +- Jonas Schnelli +- Luke Dashjr +- MarcoFalke +- Mark Friedenbach +- NicolasDorier +- Pieter Wuille +- Suhas Daftuar +- Wladimir J. van der Laan + +As well as everyone that helped translating on [Transifex](https://www.transifex.com/projects/p/bitcoin/). + diff --git a/doc/release-notes/release-notes-0.13.0.md b/doc/release-notes/release-notes-0.13.0.md new file mode 100644 index 0000000000000..5dd3f5a651ea2 --- /dev/null +++ b/doc/release-notes/release-notes-0.13.0.md @@ -0,0 +1,863 @@ +Bitcoin Core version 0.13.0 is now available from: + + + +This is a new major version release, including new features, various bugfixes +and performance improvements, as well as updated translations. + +Please report bugs using the issue tracker at github: + + + +To receive security and update notifications, please subscribe to: + + + +Compatibility +============== + +Microsoft ended support for Windows XP on [April 8th, 2014](https://www.microsoft.com/en-us/WindowsForBusiness/end-of-xp-support), +an OS initially released in 2001. This means that not even critical security +updates will be released anymore. Without security updates, using a bitcoin +wallet on a XP machine is irresponsible at least. + +In addition to that, with 0.12.x there have been varied reports of Bitcoin Core +randomly crashing on Windows XP. It is [not clear](https://github.com/bitcoin/bitcoin/issues/7681#issuecomment-217439891) +what the source of these crashes is, but it is likely that upstream +libraries such as Qt are no longer being tested on XP. + +We do not have time nor resources to provide support for an OS that is +end-of-life. From 0.13.0 on, Windows XP is no longer supported. Users are +suggested to upgrade to a newer verion of Windows, or install an alternative OS +that is supported. + +No attempt is made to prevent installing or running the software on Windows XP, +you can still do so at your own risk, but do not expect it to work: do not +report issues about Windows XP to the issue tracker. + +Notable changes +=============== + +Database cache memory increased +-------------------------------- + +As a result of growth of the UTXO set, performance with the prior default +database cache of 100 MiB has suffered. +For this reason the default was changed to 300 MiB in this release. + +For nodes on low-memory systems, the database cache can be changed back to +100 MiB (or to another value) by either: + +- Adding `dbcache=100` in bitcoin.conf +- Changing it in the GUI under `Options → Size of database cache` + +Note that the database cache setting has the most performance impact +during initial sync of a node, and when catching up after downtime. + + +bitcoin-cli: arguments privacy +------------------------------ + +The RPC command line client gained a new argument, `-stdin` +to read extra arguments from standard input, one per line until EOF/Ctrl-D. +For example: + + $ src/bitcoin-cli -stdin walletpassphrase + mysecretcode + 120 + ..... press Ctrl-D here to end input + $ + +It is recommended to use this for sensitive information such as wallet +passphrases, as command-line arguments can usually be read from the process +table by any user on the system. + + +C++11 and Python 3 +------------------ + +Various code modernizations have been done. The Bitcoin Core code base has +started using C++11. This means that a C++11-capable compiler is now needed for +building. Effectively this means GCC 4.7 or higher, or Clang 3.3 or higher. + +When cross-compiling for a target that doesn't have C++11 libraries, configure with +`./configure --enable-glibc-back-compat ... LDFLAGS=-static-libstdc++`. + +For running the functional tests in `qa/rpc-tests`, Python3.4 or higher is now +required. + + +Linux ARM builds +---------------- + +Due to popular request, Linux ARM builds have been added to the uploaded +executables. + +The following extra files can be found in the download directory or torrent: + +- `bitcoin-${VERSION}-arm-linux-gnueabihf.tar.gz`: Linux binaries for the most + common 32-bit ARM architecture. +- `bitcoin-${VERSION}-aarch64-linux-gnu.tar.gz`: Linux binaries for the most + common 64-bit ARM architecture. + +ARM builds are still experimental. If you have problems on a certain device or +Linux distribution combination please report them on the bug tracker, it may be +possible to resolve them. + +Note that Android is not considered ARM Linux in this context. The executables +are not expected to work out of the box on Android. + + +Compact Block support (BIP 152) +------------------------------- + +Support for block relay using the Compact Blocks protocol has been implemented +in PR 8068. + +The primary goal is reducing the bandwidth spikes at relay time, though in many +cases it also reduces propagation delay. It is automatically enabled between +compatible peers. +[BIP 152](https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki) + +As a side-effect, ordinary non-mining nodes will download and upload blocks +faster if those blocks were produced by miners using similar transaction +filtering policies. This means that a miner who produces a block with many +transactions discouraged by your node will be relayed slower than one with +only transactions already in your memory pool. The overall effect of such +relay differences on the network may result in blocks which include widely- +discouraged transactions losing a stale block race, and therefore miners may +wish to configure their node to take common relay policies into consideration. + + +Hierarchical Deterministic Key Generation +----------------------------------------- +Newly created wallets will use hierarchical deterministic key generation +according to BIP32 (keypath m/0'/0'/k'). +Existing wallets will still use traditional key generation. + +Backups of HD wallets, regardless of when they have been created, can +therefore be used to re-generate all possible private keys, even the +ones which haven't already been generated during the time of the backup. +**Attention:** Encrypting the wallet will create a new seed which requires +a new backup! + +Wallet dumps (created using the `dumpwallet` RPC) will contain the deterministic +seed. This is expected to allow future versions to import the seed and all +associated funds, but this is not yet implemented. + +HD key generation for new wallets can be disabled by `-usehd=0`. Keep in +mind that this flag only has affect on newly created wallets. +You can't disable HD key generation once you have created a HD wallet. + +There is no distinction between internal (change) and external keys. + +HD wallets are incompatible with older versions of Bitcoin Core. + +[Pull request](https://github.com/bitcoin/bitcoin/pull/8035/files), [BIP 32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) + + +Segregated Witness +------------------ + +The code preparations for Segregated Witness ("segwit"), as described in [BIP +141](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki), [BIP +143](https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki), [BIP +144](https://github.com/bitcoin/bips/blob/master/bip-0144.mediawiki), and [BIP +145](https://github.com/bitcoin/bips/blob/master/bip-0145.mediawiki) are +finished and included in this release. However, BIP 141 does not yet specify +activation parameters on mainnet, and so this release does not support segwit +use on mainnet. Testnet use is supported, and after BIP 141 is updated with +proposed parameters, a future release of Bitcoin Core is expected that +implements those parameters for mainnet. + +Furthermore, because segwit activation is not yet specified for mainnet, +version 0.13.0 will behave similarly as other pre-segwit releases even after a +future activation of BIP 141 on the network. Upgrading from 0.13.0 will be +required in order to utilize segwit-related features on mainnet (such as signal +BIP 141 activation, mine segwit blocks, fully validate segwit blocks, relay +segwit blocks to other segwit nodes, and use segwit transactions in the +wallet, etc). + + +Mining transaction selection ("Child Pays For Parent") +------------------------------------------------------ + +The mining transaction selection algorithm has been replaced with an algorithm +that selects transactions based on their feerate inclusive of unconfirmed +ancestor transactions. This means that a low-fee transaction can become more +likely to be selected if a high-fee transaction that spends its outputs is +relayed. + +With this change, the `-blockminsize` command line option has been removed. + +The command line option `-blockmaxsize` remains an option to specify the +maximum number of serialized bytes in a generated block. In addition, the new +command line option `-blockmaxweight` has been added, which specifies the +maximum "block weight" of a generated block, as defined by [BIP 141 (Segregated +Witness)] (https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki). + +In preparation for Segregated Witness, the mining algorithm has been modified +to optimize transaction selection for a given block weight, rather than a given +number of serialized bytes in a block. In this release, transaction selection +is unaffected by this distinction (as BIP 141 activation is not supported on +mainnet in this release, see above), but in future releases and after BIP 141 +activation, these calculations would be expected to differ. + +For optimal runtime performance, miners using this release should specify +`-blockmaxweight` on the command line, and not specify `-blockmaxsize`. +Additionally (or only) specifying `-blockmaxsize`, or relying on default +settings for both, may result in performance degradation, as the logic to +support `-blockmaxsize` performs additional computation to ensure that +constraint is met. (Note that for mainnet, in this release, the equivalent +parameter for `-blockmaxweight` would be four times the desired +`-blockmaxsize`. See [BIP 141] +(https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki) for additional +details.) + +In the future, the `-blockmaxsize` option may be removed, as block creation is +no longer optimized for this metric. Feedback is requested on whether to +deprecate or keep this command line option in future releases. + + +Reindexing changes +------------------ + +In earlier versions, reindexing did validation while reading through the block +files on disk. These two have now been split up, so that all blocks are known +before validation starts. This was necessary to make certain optimizations that +are available during normal synchronizations also available during reindexing. + +The two phases are distinct in the Bitcoin-Qt GUI. During the first one, +"Reindexing blocks on disk" is shown. During the second (slower) one, +"Processing blocks on disk" is shown. + +It is possible to only redo validation now, without rebuilding the block index, +using the command line option `-reindex-chainstate` (in addition to +`-reindex` which does both). This new option is useful when the blocks on disk +are assumed to be fine, but the chainstate is still corrupted. It is also +useful for benchmarks. + + +Removal of internal miner +-------------------------- + +As CPU mining has been useless for a long time, the internal miner has been +removed in this release, and replaced with a simpler implementation for the +test framework. + +The overall result of this is that `setgenerate` RPC call has been removed, as +well as the `-gen` and `-genproclimit` command-line options. + +For testing, the `generate` call can still be used to mine a block, and a new +RPC call `generatetoaddress` has been added to mine to a specific address. This +works with wallet disabled. + + +New bytespersigop implementation +-------------------------------- + +The former implementation of the bytespersigop filter accidentally broke bare +multisig (which is meant to be controlled by the `permitbaremultisig` option), +since the consensus protocol always counts these older transaction forms as 20 +sigops for backwards compatibility. Simply fixing this bug by counting more +accurately would have reintroduced a vulnerability. It has therefore been +replaced with a new implementation that rather than filter such transactions, +instead treats them (for fee purposes only) as if they were in fact the size +of a transaction actually using all 20 sigops. + + +Low-level P2P changes +---------------------- + +- The optional new p2p message "feefilter" is implemented and the protocol + version is bumped to 70013. Upon receiving a feefilter message from a peer, + a node will not send invs for any transactions which do not meet the filter + feerate. [BIP 133](https://github.com/bitcoin/bips/blob/master/bip-0133.mediawiki) + +- The P2P alert system has been removed in PR #7692 and the `alert` P2P message + is no longer supported. + +- The transaction relay mechanism used to relay one quarter of all transactions + instantly, while queueing up the rest and sending them out in batch. As + this resulted in chains of dependent transactions being reordered, it + systematically hurt transaction relay. The relay code was redesigned in PRs + \#7840 and #8082, and now always batches transactions announcements while also + sorting them according to dependency order. This significantly reduces orphan + transactions. To compensate for the removal of instant relay, the frequency of + batch sending was doubled for outgoing peers. + +- Since PR #7840 the BIP35 `mempool` command is also subject to batch processing. + Also the `mempool` message is no longer handled for non-whitelisted peers when + `NODE_BLOOM` is disabled through `-peerbloomfilters=0`. + +- The maximum size of orphan transactions that are kept in memory until their + ancestors arrive has been raised in PR #8179 from 5000 to 99999 bytes. They + are now also removed from memory when they are included in a block, conflict + with a block, and time out after 20 minutes. + +- We respond at most once to a getaddr request during the lifetime of a + connection since PR #7856. + +- Connections to peers who have recently been the first one to give us a valid + new block or transaction are protected from disconnections since PR #8084. + + +Low-level RPC changes +---------------------- + +- RPC calls have been added to output detailed statistics for individual mempool + entries, as well as to calculate the in-mempool ancestors or descendants of a + transaction: see `getmempoolentry`, `getmempoolancestors`, `getmempooldescendants`. + +- `gettxoutsetinfo` UTXO hash (`hash_serialized`) has changed. There was a divergence between + 32-bit and 64-bit platforms, and the txids were missing in the hashed data. This has been + fixed, but this means that the output will be different than from previous versions. + +- Full UTF-8 support in the RPC API. Non-ASCII characters in, for example, + wallet labels have always been malformed because they weren't taken into account + properly in JSON RPC processing. This is no longer the case. This also affects + the GUI debug console. + +- Asm script outputs replacements for OP_NOP2 and OP_NOP3 + + - OP_NOP2 has been renamed to OP_CHECKLOCKTIMEVERIFY by [BIP +65](https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki) + + - OP_NOP3 has been renamed to OP_CHECKSEQUENCEVERIFY by [BIP +112](https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki) + + - The following outputs are affected by this change: + + - RPC `getrawtransaction` (in verbose mode) + - RPC `decoderawtransaction` + - RPC `decodescript` + - REST `/rest/tx/` (JSON format) + - REST `/rest/block/` (JSON format when including extended tx details) + - `bitcoin-tx -json` + +- The sorting of the output of the `getrawmempool` output has changed. + +- New RPC commands: `generatetoaddress`, `importprunedfunds`, `removeprunedfunds`, `signmessagewithprivkey`, + `getmempoolancestors`, `getmempooldescendants`, `getmempoolentry`, + `createwitnessaddress`, `addwitnessaddress`. + +- Removed RPC commands: `setgenerate`, `getgenerate`. + +- New options were added to `fundrawtransaction`: `includeWatching`, `changeAddress`, `changePosition` and `feeRate`. + + +Low-level ZMQ changes +---------------------- + +- Each ZMQ notification now contains an up-counting sequence number that allows + listeners to detect lost notifications. + The sequence number is always the last element in a multi-part ZMQ notification and + therefore backward compatible. Each message type has its own counter. + PR [#7762](https://github.com/bitcoin/bitcoin/pull/7762). + + +0.13.0 Change log +================= + +Detailed release notes follow. This overview includes changes that affect +behavior, not code moves, refactors and string updates. For convenience in locating +the code changes and accompanying discussion, both the pull request and +git merge commit are mentioned. + +### RPC and other APIs + +- #7156 `9ee02cf` Remove cs_main lock from `createrawtransaction` (laanwj) +- #7326 `2cd004b` Fix typo, wrong information in gettxout help text (paveljanik) +- #7222 `82429d0` Indicate which transactions are signaling opt-in RBF (sdaftuar) +- #7480 `b49a623` Changed getnetworkhps value to double to avoid overflow (instagibbs) +- #7550 `8b958ab` Input-from-stdin mode for bitcoin-cli (laanwj) +- #7670 `c9a1265` Use cached block hash in blockToJSON() (rat4) +- #7726 `9af69fa` Correct importaddress help reference to importpubkey (CypherGrue) +- #7766 `16555b6` Register calls where they are defined (laanwj) +- #7797 `e662a76` Fix generatetoaddress failing to parse address (mruddy) +- #7774 `916b15a` Add versionHex in getblock and getblockheader JSON results (mruddy) +- #7863 `72c54e3` Getblockchaininfo: make bip9_softforks an object, not an array (rustyrussell) +- #7842 `d97101e` Do not print minping time in getpeerinfo when no ping received yet (paveljanik) +- #7518 `be14ca5` Add multiple options to fundrawtransaction (promag) +- #7756 `9e47fce` Add cursor to iterate over utxo set, use this in `gettxoutsetinfo` (laanwj) +- #7848 `88616d2` Divergence between 32- and 64-bit when hashing >4GB affects `gettxoutsetinfo` (laanwj) +- #7827 `4205ad7` Speed up `getchaintips` (mrbandrews) +- #7762 `a1eb344` Append a message sequence number to every ZMQ notification (jonasschnelli) +- #7688 `46880ed` List solvability in listunspent output and improve help (sipa) +- #7926 `5725807` Push back `getaddednodeinfo` dead value (instagibbs) +- #7953 `0630353` Create `signmessagewithprivkey` rpc (achow101) +- #8049 `c028c7b` Expose information on whether transaction relay is enabled in `getnetworkinfo` (laanwj) +- #7967 `8c1e49b` Add feerate option to `fundrawtransaction` (jonasschnelli) +- #8118 `9b6a48c` Reduce unnecessary hashing in `signrawtransaction` (jonasnick) +- #7957 `79004d4` Add support for transaction sequence number (jonasschnelli) +- #8153 `75ec320` `fundrawtransaction` feeRate: Use BTC/kB (MarcoFalke) +- #7292 `7ce9ac5` Expose ancestor/descendant information over RPC (sdaftuar) +- #8171 `62fcf27` Fix createrawtx sequence number unsigned int parsing (jonasschnelli) +- #7892 `9c3d0fa` Add full UTF-8 support to RPC (laanwj) +- #8317 `304eff3` Don't use floating point in rpcwallet (MarcoFalke) +- #8258 `5a06ebb` Hide softfork in `getblockchaininfo` if timeout is 0 (jl2012) +- #8244 `1922e5a` Remove unnecessary LOCK(cs_main) in getrawmempool (dcousens) + +### Block and transaction handling + +- #7056 `6a07208` Save last db read (morcos) +- #6842 `0192806` Limitfreerelay edge case bugfix (ptschip) +- #7084 `11d74f6` Replace maxFeeRate of 10000*minRelayTxFee with maxTxFee in mempool (MarcoFalke) +- #7539 `9f33dba` Add tags to mempool's mapTx indices (sdaftuar) +- #7592 `26a2a72` Re-remove ERROR logging for mempool rejects (laanwj) +- #7187 `14d6324` Keep reorgs fast for SequenceLocks checks (morcos) +- #7594 `01f4267` Mempool: Add tracking of ancestor packages (sdaftuar) +- #7904 `fc9e334` Txdb: Fix assert crash in new UTXO set cursor (laanwj) +- #7927 `f9c2ac7` Minor changes to dbwrapper to simplify support for other databases (laanwj) +- #7933 `e26b620` Fix OOM when deserializing UTXO entries with invalid length (sipa) +- #8020 `5e374f7` Use SipHash-2-4 for various non-cryptographic hashes (sipa) +- #8076 `d720980` VerifyDB: don't check blocks that have been pruned (sdaftuar) +- #8080 `862fd24` Do not use mempool for GETDATA for tx accepted after the last mempool req (gmaxwell) +- #7997 `a82f033` Replace mapNextTx with slimmer setSpends (kazcw) +- #8220 `1f86d64` Stop trimming when mapTx is empty (sipa) +- #8273 `396f9d6` Bump `-dbcache` default to 300MiB (laanwj) +- #7225 `eb33179` Eliminate unnecessary call to CheckBlock (sdaftuar) +- #7907 `006cdf6` Optimize and Cleanup CScript::FindAndDelete (pstratem) +- #7917 `239d419` Optimize reindex (sipa) +- #7763 `3081fb9` Put hex-encoded version in UpdateTip (sipa) +- #8149 `d612837` Testnet-only segregated witness (sipa) +- #8305 `3730393` Improve handling of unconnecting headers (sdaftuar) +- #8363 `fca1a41` Rename "block cost" to "block weight" (sdaftuar) +- #8381 `f84ee3d` Make witness v0 outputs non-standard (jl2012) +- #8364 `3f65ba2` Treat high-sigop transactions as larger rather than rejecting them (sipa) + +### P2P protocol and network code + +- #6589 `dc0305d` Log bytes recv/sent per command (jonasschnelli) +- #7164 `3b43cad` Do not download transactions during initial blockchain sync (ptschip) +- #7458 `898fedf` peers.dat, banlist.dat recreated when missing (kirkalx) +- #7637 `3da5d1b` Fix memleak in TorController (laanwj, jonasschnelli) +- #7553 `9f14e5a` Remove vfReachable and modify IsReachable to only use vfLimited (pstratem) +- #7708 `9426632` De-neuter NODE_BLOOM (pstratem) +- #7692 `29b2be6` Remove P2P alert system (btcdrak) +- #7542 `c946a15` Implement "feefilter" P2P message (morcos) +- #7573 `352fd57` Add `-maxtimeadjustment` command line option (mruddy) +- #7570 `232592a` Add IPv6 Link-Local Address Support (mruddy) +- #7874 `e6a4d48` Improve AlreadyHave (morcos) +- #7856 `64e71b3` Only send one GetAddr response per connection (gmaxwell) +- #7868 `7daa3ad` Split DNS resolving functionality out of net structures (theuni) +- #7919 `7617682` Fix headers announcements edge case (sdaftuar) +- #7514 `d9594bf` Fix IsInitialBlockDownload for testnet (jmacwhyte) +- #7959 `03cf6e8` fix race that could fail to persist a ban (kazcw) +- #7840 `3b9a0bf` Several performance and privacy improvements to inv/mempool handling (sipa) +- #8011 `65aecda` Don't run ThreadMessageHandler at lowered priority (kazcw) +- #7696 `5c3f8dd` Fix de-serialization bug where AddrMan is left corrupted (EthanHeilman) +- #7932 `ed749bd` CAddrMan::Deserialize handle corrupt serializations better (pstratem) +- #7906 `83121cc` Prerequisites for p2p encapsulation changes (theuni) +- #8033 `18436d8` Fix Socks5() connect failures to be less noisy and less unnecessarily scary (wtogami) +- #8082 `01d8359` Defer inserting into maprelay until just before relaying (gmaxwell) +- #7960 `6a22373` Only use AddInventoryKnown for transactions (sdaftuar) +- #8078 `2156fa2` Disable the mempool P2P command when bloom filters disabled (petertodd) +- #8065 `67c91f8` Addrman offline attempts (gmaxwell) +- #7703 `761cddb` Tor: Change auth order to only use password auth if -torpassword (laanwj) +- #8083 `cd0c513` Add support for dnsseeds with option to filter by servicebits (jonasschnelli) +- #8173 `4286f43` Use SipHash for node eviction (sipa) +- #8154 `1445835` Drop vAddrToSend after sending big addr message (kazcw) +- #7749 `be9711e` Enforce expected outbound services (sipa) +- #8208 `0a64777` Do not set extra flags for unfiltered DNS seed results (sipa) +- #8084 `e4bb4a8` Add recently accepted blocks and txn to AttemptToEvictConnection (gmaxwell) +- #8113 `3f89a53` Rework addnode behaviour (sipa) +- #8179 `94ab58b` Evict orphans which are included or precluded by accepted blocks (gmaxwell) +- #8068 `e9d76a1` Compact Blocks (TheBlueMatt) +- #8204 `0833894` Update petertodd's testnet seed (petertodd) +- #8247 `5cd35d3` Mark my dnsseed as supporting filtering (sipa) +- #8275 `042c323` Remove bad chain alert partition check (btcdrak) +- #8271 `1bc9c80` Do not send witnesses in cmpctblock (sipa) +- #8312 `ca40ef6` Fix mempool DoS vulnerability from malleated transactions (sdaftuar) +- #7180 `16ccb74` Account for `sendheaders` `verack` messages (laanwj) +- #8102 `425278d` Bugfix: use global ::fRelayTxes instead of CNode in version send (sipa) +- #8408 `b7e2011` Prevent fingerprinting, disk-DoS with compact blocks (sdaftuar) + +### Build system + +- #7302 `41f1a3e` C++11 build/runtime fixes (theuni) +- #7322 `fd9356b` c++11: add scoped enum fallbacks to CPPFLAGS rather than defining them locally (theuni) +- #7441 `a6771fc` Use Debian 8.3 in gitian build guide (fanquake) +- #7349 `152a821` Build against system UniValue when available (luke-jr) +- #7520 `621940e` LibreSSL doesn't define OPENSSL_VERSION, use LIBRESSL_VERSION_TEXT instead (paveljanik) +- #7528 `9b9bfce` autogen.sh: warn about needing autoconf if autoreconf is not found (knocte) +- #7504 `19324cf` Crystal clean make clean (paveljanik) +- #7619 `18b3f1b` Add missing sudo entry in gitian VM setup (btcdrak) +- #7616 `639ec58` [depends] Delete unused patches (MarcoFalke) +- #7658 `c15eb28` Add curl to Gitian setup instructions (btcdrak) +- #7710 `909b72b` [Depends] Bump miniupnpc and config.guess+sub (fanquake) +- #7723 `5131005` build: python 3 compatibility (laanwj) +- #7477 `28ad4d9` Fix quoting of copyright holders in configure.ac (domob1812) +- #7711 `a67bc5e` [build-aux] Update Boost & check macros to latest serials (fanquake) +- #7788 `4dc1b3a` Use relative paths instead of absolute paths in protoc calls (paveljanik) +- #7809 `bbd210d` depends: some base fixes/changes (theuni) +- #7603 `73fc922` Build System: Use PACKAGE_TARNAME in NSIS script (JeremyRand) +- #7905 `187186b` test: move accounting_tests and rpc_wallet_tests to wallet/test (laanwj) +- #7911 `351abf9` leveldb: integrate leveldb into our buildsystem (theuni) +- #7944 `a407807` Re-instate TARGET_OS=linux in configure.ac. Removed by 351abf9e035 (randy-waterhouse) +- #7920 `c3e3cfb` Switch Travis to Trusty (theuni) +- #7954 `08b37c5` build: quiet annoying warnings without adding new ones (theuni) +- #7165 `06162f1` build: Enable C++11 in build, require C++11 compiler (laanwj) +- #7982 `559fbae` build: No need to check for leveldb atomics (theuni) +- #8002 `f9b4582` [depends] Add -stdlib=libc++ to darwin CXX flags (fanquake) +- #7993 `6a034ed` [depends] Bump Freetype, ccache, ZeroMQ, miniupnpc, expat (fanquake) +- #8167 `19ea173` Ship debug tarballs/zips with debug symbols (theuni) +- #8175 `f0299d8` Add --disable-bench to config flags for windows (laanwj) +- #7283 `fd9881a` [gitian] Default reference_datetime to commit author date (MarcoFalke) +- #8181 `9201ce8` Get rid of `CLIENT_DATE` (laanwj) +- #8133 `fde0ac4` Finish up out-of-tree changes (theuni) +- #8188 `65a9d7d` Add armhf/aarch64 gitian builds (theuni) +- #8194 `cca1c8c` [gitian] set correct PATH for wrappers (MarcoFalke) +- #8198 `5201614` Sync ax_pthread with upstream draft4 (fanquake) +- #8210 `12a541e` [Qt] Bump to Qt5.6.1 (jonasschnelli) +- #8285 `da50997` windows: Add testnet link to installer (laanwj) +- #8304 `0cca2fe` [travis] Update SDK_URL (MarcoFalke) +- #8310 `6ae20df` Require boost for bench (theuni) +- #8315 `2e51590` Don't require sudo for Linux (theuni) +- #8314 `67caef6` Fix pkg-config issues for 0.13 (theuni) +- #8373 `1fe7f40` Fix OSX non-deterministic dmg (theuni) +- #8358 `cfd1280` Gbuild: Set memory explicitly (default is too low) (MarcoFalke) + +### GUI + +- #7154 `00b4b8d` Add InMempool() info to transaction details (jonasschnelli) +- #7068 `5f3c670` [RPC-Tests] add simple way to run rpc test over QT clients (jonasschnelli) +- #7218 `a1c185b` Fix misleading translation (MarcoFalke) +- #7214 `be9a9a3` qt5: Use the fixed font the system recommends (MarcoFalke) +- #7256 `08ab906` Add note to coin control dialog QT5 workaround (fanquake) +- #7255 `e289807` Replace some instances of formatWithUnit with formatHtmlWithUnit (fanquake) +- #7317 `3b57e9c` Fix RPCTimerInterface ordering issue (jonasschnelli) +- #7327 `c079d79` Transaction View: LastMonth calculation fixed (crowning-) +- #7334 `e1060c5` coincontrol workaround is still needed in qt5.4 (fixed in qt5.5) (MarcoFalke) +- #7383 `ae2db67` Rename "amount" to "requested amount" in receive coins table (jonasschnelli) +- #7396 `cdcbc59` Add option to increase/decrease font size in the console window (jonasschnelli) +- #7437 `9645218` Disable tab navigation for peers tables (Kefkius) +- #7604 `354b03d` build: Remove spurious dollar sign. Fixes #7189 (dooglus) +- #7605 `7f001bd` Remove openssl info from init/log and from Qt debug window (jonasschnelli) +- #7628 `87d6562` Add 'copy full transaction details' option (ericshawlinux) +- #7613 `3798e5d` Add autocomplete to bitcoin-qt's console window (GamerSg) +- #7668 `b24266c` Fix history deletion bug after font size change (achow101) +- #7680 `41d2dfa` Remove reflection from `about` icon (laanwj) +- #7686 `f034bce` Remove 0-fee from send dialog (MarcoFalke) +- #7506 `b88e0b0` Use CCoinControl selection in CWallet::FundTransaction (promag) +- #7732 `0b98dd7` Debug window: replace "Build date" with "Datadir" (jonasschnelli) +- #7761 `60db51d` remove trailing output-index from transaction-id (jonasschnelli) +- #7772 `6383268` Clear the input line after activating autocomplete (paveljanik) +- #7925 `f604bf6` Fix out-of-tree GUI builds (laanwj) +- #7939 `574ddc6` Make it possible to show details for multiple transactions (laanwj) +- #8012 `b33824b` Delay user confirmation of send (Tyler-Hardin) +- #8006 `7c8558d` Add option to disable the system tray icon (Tyler-Hardin) +- #8046 `169d379` Fix Cmd-Q / Menu Quit shutdown on OSX (jonasschnelli) +- #8042 `6929711` Don't allow to open the debug window during splashscreen & verification state (jonasschnelli) +- #8014 `77b49ac` Sort transactions by date (Tyler-Hardin) +- #8073 `eb2f6f7` askpassphrasedialog: Clear pass fields on accept (rat4) +- #8129 `ee1533e` Fix RPC console auto completer (UdjinM6) +- #7636 `fb0ac48` Add bitcoin address label to request payment QR code (makevoid) +- #8231 `760a6c7` Fix a bug where the SplashScreen will not be hidden during startup (jonasschnelli) +- #8256 `af2421c` BUG: bitcoin-qt crash (fsb4000) +- #8257 `ff03c50` Do not ask a UI question from bitcoind (sipa) +- #8288 `91abb77` Network-specific example address (laanwj) +- #7707 `a914968` UI support for abandoned transactions (jonasschnelli) +- #8207 `f7a403b` Add a link to the Bitcoin-Core repository and website to the About Dialog (MarcoFalke) +- #8281 `6a87eb0` Remove client name from debug window (laanwj) +- #8407 `45eba4b` Add dbcache migration path (jonasschnelli) + +### Wallet + +- #7262 `fc08994` Reduce inefficiency of GetAccountAddress() (dooglus) +- #7537 `78e81b0` Warn on unexpected EOF while salvaging wallet (laanwj) +- #7521 `3368895` Don't resend wallet txs that aren't in our own mempool (morcos) +- #7576 `86a1ec5` Move wallet help string creation to CWallet (jonasschnelli) +- #7577 `5b3b5a7` Move "load wallet phase" to CWallet (jonasschnelli) +- #7608 `0735c0c` Move hardcoded file name out of log messages (MarcoFalke) +- #7649 `4900641` Prevent multiple calls to CWallet::AvailableCoins (promag) +- #7646 `e5c3511` Fix lockunspent help message (promag) +- #7558 `b35a591` Add import/removeprunedfunds rpc call (instagibbs) +- #6215 `48c5adf` add bip32 pub key serialization (jonasschnelli) +- #7913 `bafd075` Fix for incorrect locking in GetPubKey() (keystore.cpp) (yurizhykin) +- #8036 `41138f9` init: Move berkeleydb version reporting to wallet (laanwj) +- #8028 `373b50d` Fix insanity of CWalletDB::WriteTx and CWalletTx::WriteToDisk (pstratem) +- #8061 `f6b7df3` Improve Wallet encapsulation (pstratem) +- #7891 `950be19` Always require OS randomness when generating secret keys (sipa) +- #7689 `b89ef13` Replace OpenSSL AES with ctaes-based version (sipa) +- #7825 `f972b04` Prevent multiple calls to ExtractDestination (pedrobranco) +- #8137 `243ac0c` Improve CWallet API with new AccountMove function (pstratem) +- #8142 `52c3f34` Improve CWallet API with new GetAccountPubkey function (pstratem) +- #8035 `b67a472` Add simplest BIP32/deterministic key generation implementation (jonasschnelli) +- #7687 `a6ddb19` Stop treating importaddress'ed scripts as change (sipa) +- #8298 `aef3811` wallet: Revert input selection post-pruning (laanwj) +- #8324 `bc94b87` Keep HD seed during salvagewallet (jonasschnelli) +- #8323 `238300b` Add HD keypath to CKeyMetadata, report metadata in validateaddress (jonasschnelli) +- #8367 `3b38a6a` Ensure <0.13 clients can't open HD wallets (jonasschnelli) +- #8378 `ebea651` Move SetMinVersion for FEATURE_HD to SetHDMasterKey (pstratem) +- #8390 `73adfe3` Correct hdmasterkeyid/masterkeyid name confusion (jonasschnelli) +- #8206 `18b8ee1` Add HD xpriv to dumpwallet (jonasschnelli) +- #8389 `c3c82c4` Create a new HD seed after encrypting the wallet (jonasschnelli) + +### Tests and QA + +- #7320 `d3dfc6d` Test walletpassphrase timeout (MarcoFalke) +- #7208 `47c5ed1` Make max tip age an option instead of chainparam (laanwj) +- #7372 `21376af` Trivial: [qa] wallet: Print maintenance (MarcoFalke) +- #7280 `668906f` [travis] Fail when documentation is outdated (MarcoFalke) +- #7177 `93b0576` [qa] Change default block priority size to 0 (MarcoFalke) +- #7236 `02676c5` Use createrawtx locktime parm in txn_clone (dgenr8) +- #7212 `326ffed` Adds unittests for CAddrMan and CAddrinfo, removes source of non-determinism (EthanHeilman) +- #7490 `d007511` tests: Remove May15 test (laanwj) +- #7531 `18cb2d5` Add bip68-sequence.py to extended rpc tests (btcdrak) +- #7536 `ce5fc02` test: test leading spaces for ParseHex (laanwj) +- #7620 `1b68de3` [travis] Only run check-doc.py once (MarcoFalke) +- #7455 `7f96671` [travis] Exit early when check-doc.py fails (MarcoFalke) +- #7667 `56d2c4e` Move GetTempPath() to testutil (musalbas) +- #7517 `f1ca891` test: script_error checking in script_invalid tests (laanwj) +- #7684 `3d0dfdb` Extend tests (MarcoFalke) +- #7697 `622fe6c` Tests: make prioritise_transaction.py more robust (sdaftuar) +- #7709 `efde86b` Tests: fix missing import in mempool_packages (sdaftuar) +- #7702 `29e1131` Add tests verifychain, lockunspent, getbalance, listsinceblock (MarcoFalke) +- #7720 `3b4324b` rpc-test: Normalize assert() (MarcoFalke) +- #7757 `26794d4` wallet: Wait for reindex to catch up (MarcoFalke) +- #7764 `a65b36c` Don't run pruning.py twice (MarcoFalke) +- #7773 `7c80e72` Fix comments in tests (btcdrak) +- #7489 `e9723cb` tests: Make proxy_test work on travis servers without IPv6 (laanwj) +- #7801 `70ac71b` Remove misleading "errorString syntax" (MarcoFalke) +- #7803 `401c65c` maxblocksinflight: Actually enable test (MarcoFalke) +- #7802 `3bc71e1` httpbasics: Actually test second connection (MarcoFalke) +- #7849 `ab8586e` tests: add varints_bitpatterns test (laanwj) +- #7846 `491171f` Clean up lockorder data of destroyed mutexes (sipa) +- #7853 `6ef5e00` py2: Unfiddle strings into bytes explicitly (MarcoFalke) +- #7878 `53adc83` [test] bctest.py: Revert faa41ee (MarcoFalke) +- #7798 `cabba24` [travis] Print the commit which was evaluated (MarcoFalke) +- #7833 `b1bf511` tests: Check Content-Type header returned from RPC server (laanwj) +- #7851 `fa9d86f` pull-tester: Don't mute zmq ImportError (MarcoFalke) +- #7822 `0e6fd5e` Add listunspent() test for spendable/unspendable UTXO (jpdffonseca) +- #7912 `59ad568` Tests: Fix deserialization of reject messages (sdaftuar) +- #7941 `0ea3941` Fixing comment in script_test.json test case (Christewart) +- #7807 `0ad1041` Fixed miner test values, gave constants for less error-prone values (instagibbs) +- #7980 `88b77c7` Smartfees: Properly use ordered dict (MarcoFalke) +- #7814 `77b637f` Switch to py3 (MarcoFalke) +- #8030 `409a8a1` Revert fatal-ness of missing python-zmq (laanwj) +- #8018 `3e90fe6` Autofind rpc tests --srcdir (jonasschnelli) +- #8016 `5767e80` Fix multithread CScheduler and reenable test (paveljanik) +- #7972 `423ca30` pull-tester: Run rpc test in parallel (MarcoFalke) +- #8039 `69b3a6d` Bench: Add crypto hash benchmarks (laanwj) +- #8041 `5b736dd` Fix bip9-softforks blockstore issue (MarcoFalke) +- #7994 `1f01443` Add op csv tests to script_tests.json (Christewart) +- #8038 `e2bf830` Various minor fixes (MarcoFalke) +- #8072 `1b87e5b` Travis: 'make check' in parallel and verbose (MarcoFalke) +- #8056 `8844ef1` Remove hardcoded "4 nodes" from test_framework (MarcoFalke) +- #8047 `37f9a1f` Test_framework: Set wait-timeout for bitcoind procs (MarcoFalke) +- #8095 `6700cc9` Test framework: only cleanup on successful test runs (sdaftuar) +- #8098 `06bd4f6` Test_framework: Append portseed to tmpdir (MarcoFalke) +- #8104 `6ff2c8d` Add timeout to sync_blocks() and sync_mempools() (sdaftuar) +- #8111 `61b8684` Benchmark SipHash (sipa) +- #8107 `52b803e` Bench: Added base58 encoding/decoding benchmarks (yurizhykin) +- #8115 `0026e0e` Avoid integer division in the benchmark inner-most loop (gmaxwell) +- #8090 `a2df115` Adding P2SH(p2pkh) script test case (Christewart) +- #7992 `ec45cc5` Extend #7956 with one more test (TheBlueMatt) +- #8139 `ae5575b` Fix interrupted HTTP RPC connection workaround for Python 3.5+ (sipa) +- #8164 `0f24eaf` [Bitcoin-Tx] fix missing test fixtures, fix 32bit atoi issue (jonasschnelli) +- #8166 `0b5279f` Src/test: Do not shadow local variables (paveljanik) +- #8141 `44c1b1c` Continuing port of java comparison tool (mrbandrews) +- #8201 `36b7400` fundrawtransaction: Fix race, assert amounts (MarcoFalke) +- #8214 `ed2cd59` Mininode: fail on send_message instead of silent return (MarcoFalke) +- #8215 `a072d1a` Don't use floating point in wallet tests (MarcoFalke) +- #8066 `65c2058` Test_framework: Use different rpc_auth_pair for each node (MarcoFalke) +- #8216 `0d41d70` Assert 'changePosition out of bounds' (MarcoFalke) +- #8222 `961893f` Enable mempool consistency checks in unit tests (sipa) +- #7751 `84370d5` test_framework: python3.4 authproxy compat (laanwj) +- #7744 `d8e862a` test_framework: detect failure of bitcoind startup (laanwj) +- #8280 `115735d` Increase sync_blocks() timeouts in pruning.py (MarcoFalke) +- #8340 `af9b7a9` Solve trivial merge conflict in p2p-segwit.py (MarcoFalke) +- #8067 `3e4cf8f` Travis: use slim generic image, and some fixups (theuni) +- #7951 `5c7df70` Test_framework: Properly print exception (MarcoFalke) +- #8070 `7771aa5` Remove non-determinism which is breaking net_tests #8069 (EthanHeilman) +- #8309 `bb2646a` Add wallet-hd test (MarcoFalke) +- #8444 `cd0910b` Fix p2p-feefilter.py for changed tx relay behavior (sdaftuar) + +### Mining + +- #7507 `11c7699` Remove internal miner (Leviathn) +- #7663 `c87f51e` Make the generate RPC call function for non-regtest (sipa) +- #7671 `e2ebd25` Add generatetoaddress RPC to mine to an address (achow101) +- #7935 `66ed450` Versionbits: GBT support (luke-jr) +- #7600 `66db2d6` Select transactions using feerate-with-ancestors (sdaftuar) +- #8295 `f5660d3` Mining-related fixups for 0.13.0 (sdaftuar) +- #7796 `536b75e` Add support for negative fee rates, fixes `prioritizetransaction` (MarcoFalke) +- #8362 `86edc20` Scale legacy sigop count in CreateNewBlock (sdaftuar) +- #8489 `8b0eee6` Bugfix: Use pre-BIP141 sigops until segwit activates (GBT) (luke-jr) + +### Documentation and miscellaneous + +- #7423 `69e2a40` Add example for building with constrained resources (jarret) +- #8254 `c2c69ed` Add OSX ZMQ requirement to QA readme (fanquake) +- #8203 `377d131` Clarify documentation for running a tor node (nathaniel-mahieu) +- #7428 `4b12266` Add example for listing ./configure flags (nathaniel-mahieu) +- #7847 `3eae681` Add arch linux build example (mruddy) +- #7968 `ff69aaf` Fedora build requirements (wtogami) +- #8013 `fbedc09` Fedora build requirements, add gcc-c++ and fix typo (wtogami) +- #8009 `fbd8478` Fixed invalid example paths in gitian-building.md (JeremyRand) +- #8240 `63fbdbc` Mention Windows XP end of support in release notes (laanwj) +- #8303 `5077d2c` Update bips.md for CSV softfork (fanquake) +- #7789 `e0b3e19` Add note about using the Qt official binary installer (paveljanik) +- #7791 `e30a5b0` Change Precise to Trusty in gitian-building.md (JeremyRand) +- #7838 `8bb5d3d` Update gitian build guide to debian 8.4.0 (fanquake) +- #7855 `b778e59` Replace precise with trusty (MarcoFalke) +- #7975 `fc23fee` Update bitcoin-core GitHub links (MarcoFalke) +- #8034 `e3a8207` Add basic git squash workflow (fanquake) +- #7813 `214ec0b` Update port in tor.md (MarcoFalke) +- #8193 `37c9830` Use Debian 8.5 in the gitian-build guide (fanquake) +- #8261 `3685e0c` Clarify help for `getblockchaininfo` (paveljanik) +- #7185 `ea0f5a2` Note that reviewers should mention the id of the commits they reviewed (pstratem) +- #7290 `c851d8d` [init] Add missing help for args (MarcoFalke) +- #7281 `f9fd4c2` Improve CheckInputs() comment about sig verification (petertodd) +- #7417 `1e06bab` Minor improvements to the release process (PRabahy) +- #7444 `4cdbd42` Improve block validity/ConnectBlock() comments (petertodd) +- #7527 `db2e1c0` Fix and cleanup listreceivedbyX documentation (instagibbs) +- #7541 `b6e00af` Clarify description of blockindex (pinheadmz) +- #7590 `f06af57` Improving wording related to Boost library requirements [updated] (jonathancross) +- #7635 `0fa88ef` Add dependency info to test docs (elliotolds) +- #7609 `3ba07bd` RPM spec file project (AliceWonderMiscreations) +- #7850 `229a17c` Removed call to `TryCreateDirectory` from `GetDefaultDataDir` in `src/util.cpp` (alexreg) +- #7888 `ec870e1` Prevector: fix 2 bugs in currently unreached code paths (kazcw) +- #7922 `90653bc` CBase58Data::SetString: cleanse the full vector (kazcw) +- #7881 `c4e8390` Update release process (laanwj) +- #7952 `a9c8b74` Log invalid block hash to make debugging easier (paveljanik) +- #7974 `8206835` More comments on the design of AttemptToEvictConnection (gmaxwell) +- #7795 `47a7cfb` UpdateTip: log only one line at most per block (laanwj) +- #8110 `e7e25ea` Add benchmarking notes (fanquake) +- #8121 `58f0c92` Update implemented BIPs list (fanquake) +- #8029 `58725ba` Simplify OS X build notes (fanquake) +- #8143 `d46b8b5` comment nit: miners don't vote (instagibbs) +- #8136 `22e0b35` Log/report in 10% steps during VerifyDB (jonasschnelli) +- #8168 `d366185` util: Add ParseUInt32 and ParseUInt64 (laanwj) +- #8178 `f7b1bfc` Add git and github tips and tricks to developer notes (sipa) +- #8177 `67db011` developer notes: updates for C++11 (kazcw) +- #8229 `8ccdac1` [Doc] Update OS X build notes for 10.11 SDK (fanquake) +- #8233 `9f1807a` Mention Linux ARM executables in release process and notes (laanwj) +- #7540 `ff46dd4` Rename OP_NOP3 to OP_CHECKSEQUENCEVERIFY (btcdrak) +- #8289 `26316ff` bash-completion: Adapt for 0.12 and 0.13 (roques) +- #7453 `3dc3149` Missing patches from 0.12 (MarcoFalke) +- #7113 `54a550b` Switch to a more efficient rolling Bloom filter (sipa) +- #7257 `de9e5ea` Combine common error strings for different options so translations can be shared and reused (luke-jr) +- #7304 `b8f485c` [contrib] Add clang-format-diff.py (MarcoFalke) +- #7378 `e6f97ef` devtools: replace github-merge with python version (laanwj) +- #7395 `0893705` devtools: show pull and commit information in github-merge (laanwj) +- #7402 `6a5932b` devtools: github-merge get toplevel dir without extra whitespace (achow101) +- #7425 `20a408c` devtools: Fix utf-8 support in messages for github-merge (laanwj) +- #7632 `409f843` Delete outdated test-patches reference (Lewuathe) +- #7662 `386f438` remove unused NOBLKS_VERSION_{START,END} constants (rat4) +- #7737 `aa0d2b2` devtools: make github-merge.py use py3 (laanwj) +- #7781 `55db5f0` devtools: Auto-set branch to merge to in github-merge (laanwj) +- #7934 `f17032f` Improve rolling bloom filter performance and benchmark (sipa) +- #8004 `2efe38b` signal handling: fReopenDebugLog and fRequestShutdown should be type sig_atomic_t (catilac) +- #7713 `f6598df` Fixes for verify-commits script (petertodd) +- #8412 `8360d5b` libconsensus: Expose a flag for BIP112 (jtimon) + +Credits +======= + +Thanks to everyone who directly contributed to this release: + +- 21E14 +- accraze +- Adam Brown +- Alexander Regueiro +- Alex Morcos +- Alfie John +- Alice Wonder +- AlSzacrel +- Andrew Chow +- Andrés G. Aragoneses +- Bob McElrath +- BtcDrak +- calebogden +- Cédric Félizard +- Chirag Davé +- Chris Moore +- Chris Stewart +- Christian von Roques +- Chris Wheeler +- Cory Fields +- crowning- +- Daniel Cousens +- Daniel Kraft +- Denis Lukianov +- Elias Rohrer +- Elliot Olds +- Eric Shaw +- error10 +- Ethan Heilman +- face +- fanquake +- Francesco 'makevoid' Canessa +- fsb4000 +- Gavin Andresen +- gladoscc +- Gregory Maxwell +- Gregory Sanders +- instagibbs +- James O'Beirne +- Jannes Faber +- Jarret Dyrbye +- Jeremy Rand +- jloughry +- jmacwhyte +- Joao Fonseca +- Johnson Lau +- Jonas Nick +- Jonas Schnelli +- Jonathan Cross +- João Barbosa +- Jorge Timón +- Kaz Wesley +- Kefkius +- kirkalx +- Krzysztof Jurewicz +- Leviathn +- lewuathe +- Luke Dashjr +- Luv Khemani +- Marcel Krüger +- Marco Falke +- Mark Friedenbach +- Matt +- Matt Bogosian +- Matt Corallo +- Matthew English +- Matthew Zipkin +- mb300sd +- Mitchell Cash +- mrbandrews +- mruddy +- Murch +- Mustafa +- Nathaniel Mahieu +- Nicolas Dorier +- Patrick Strateman +- Paul Rabahy +- paveljanik +- Pavel Janík +- Pavel Vasin +- Pedro Branco +- Peter Todd +- Philip Kaufmann +- Pieter Wuille +- Prayag Verma +- ptschip +- Puru +- randy-waterhouse +- R E Broadley +- Rusty Russell +- Suhas Daftuar +- Suriyaa Kudo +- TheLazieR Yip +- Thomas Kerin +- Tom Harding +- Tyler Hardin +- UdjinM6 +- Warren Togami +- Will Binns +- Wladimir J. van der Laan +- Yuri Zhykin + +As well as everyone that helped translating on [Transifex](https://www.transifex.com/projects/p/bitcoin/). From dbb1f640e67da25f0a41b9d2e696b789d2fd4e0d Mon Sep 17 00:00:00 2001 From: Ethan Heilman Date: Fri, 17 Jun 2016 00:10:07 -0400 Subject: [PATCH 0757/1802] Added feeler connections increasing good addrs in the tried table. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tests if addresses are online or offline by briefly connecting to them. These short lived connections are referred to as feeler connections. Feeler connections are designed to increase the number of fresh online addresses in tried by selecting and connecting to addresses in new. One feeler connection is attempted on average once every two minutes. This change was suggested as Countermeasure 4 in Eclipse Attacks on Bitcoin’s Peer-to-Peer Network, Ethan Heilman, Alison Kendler, Aviv Zohar, Sharon Goldberg. ePrint Archive Report 2015/263. March 2015. --- src/main.cpp | 6 +++++ src/net.cpp | 59 ++++++++++++++++++++++++++++++++++++------ src/net.h | 5 +++- src/test/net_tests.cpp | 22 ++++++++++++++++ 4 files changed, 83 insertions(+), 9 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 75f991d31a723..758a6dcce1924 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4903,6 +4903,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, if (strCommand == NetMsgType::VERSION) { + // Feeler connections exist only to verify if address is online. + if (pfrom->fFeeler) { + assert(pfrom->fInbound == false); + pfrom->fDisconnect = true; + } + // Each connection can only send one version message if (pfrom->nVersion != 0) { diff --git a/src/net.cpp b/src/net.cpp index 39c8d12e2081f..33dc10cbcbe2a 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -43,6 +43,9 @@ // Dump addresses to peers.dat and banlist.dat every 15 minutes (900s) #define DUMP_ADDRESSES_INTERVAL 900 +// We add a random period time (0 to 1 seconds) to feeler connections to prevent synchronization. +#define FEELER_SLEEP_WINDOW 1 + #if !defined(HAVE_MSG_NOSIGNAL) && !defined(MSG_NOSIGNAL) #define MSG_NOSIGNAL 0 #endif @@ -61,6 +64,7 @@ namespace { const int MAX_OUTBOUND_CONNECTIONS = 8; + const int MAX_FEELER_CONNECTIONS = 1; struct ListenSocket { SOCKET socket; @@ -1017,7 +1021,8 @@ static void AcceptConnection(const ListenSocket& hListenSocket) { SOCKET hSocket = accept(hListenSocket.socket, (struct sockaddr*)&sockaddr, &len); CAddress addr; int nInbound = 0; - int nMaxInbound = nMaxConnections - MAX_OUTBOUND_CONNECTIONS; + int nMaxInbound = nMaxConnections - (MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS); + assert(nMaxInbound > 0); if (hSocket != INVALID_SOCKET) if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr)) @@ -1613,6 +1618,9 @@ void ThreadOpenConnections() // Initiate network connections int64_t nStart = GetTime(); + + // Minimum time before next feeler connection (in microseconds). + int64_t nNextFeeler = PoissonNextSend(nStart*1000*1000, FEELER_INTERVAL); while (true) { ProcessOneShot(); @@ -1652,13 +1660,36 @@ void ThreadOpenConnections() } } } + assert(nOutbound <= (MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS)); - int64_t nANow = GetAdjustedTime(); + // Feeler Connections + // + // Design goals: + // * Increase the number of connectable addresses in the tried table. + // + // Method: + // * Choose a random address from new and attempt to connect to it if we can connect + // successfully it is added to tried. + // * Start attempting feeler connections only after node finishes making outbound + // connections. + // * Only make a feeler connection once every few minutes. + // + bool fFeeler = false; + if (nOutbound >= MAX_OUTBOUND_CONNECTIONS) { + int64_t nTime = GetTimeMicros(); // The current time right now (in microseconds). + if (nTime > nNextFeeler) { + nNextFeeler = PoissonNextSend(nTime, FEELER_INTERVAL); + fFeeler = true; + } else { + continue; + } + } + int64_t nANow = GetAdjustedTime(); int nTries = 0; while (true) { - CAddrInfo addr = addrman.Select(); + CAddrInfo addr = addrman.Select(fFeeler); // if we selected an invalid address, restart if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr)) @@ -1694,8 +1725,17 @@ void ThreadOpenConnections() break; } - if (addrConnect.IsValid()) - OpenNetworkConnection(addrConnect, (int)setConnected.size() >= std::min(nMaxConnections - 1, 2), &grant); + if (addrConnect.IsValid()) { + + if (fFeeler) { + // Add small amount of random noise before connection to avoid synchronization. + int randsleep = GetRandInt(FEELER_SLEEP_WINDOW * 1000); + MilliSleep(randsleep); + LogPrint("net", "Making feeler connection to %s\n", addrConnect.ToString()); + } + + OpenNetworkConnection(addrConnect, (int)setConnected.size() >= std::min(nMaxConnections - 1, 2), &grant, NULL, false, fFeeler); + } } } @@ -1777,7 +1817,7 @@ void ThreadOpenAddedConnections() } // if successful, this moves the passed grant to the constructed node -bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound, const char *pszDest, bool fOneShot) +bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound, const char *pszDest, bool fOneShot, bool fFeeler) { // // Initiate outbound network connection @@ -1801,6 +1841,8 @@ bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSem pnode->fNetworkNode = true; if (fOneShot) pnode->fOneShot = true; + if (fFeeler) + pnode->fFeeler = true; return true; } @@ -2062,7 +2104,7 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler) if (semOutbound == NULL) { // initialize semaphore - int nMaxOutbound = std::min(MAX_OUTBOUND_CONNECTIONS, nMaxConnections); + int nMaxOutbound = std::min((MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS), nMaxConnections); semOutbound = new CSemaphore(nMaxOutbound); } @@ -2107,7 +2149,7 @@ bool StopNode() LogPrintf("StopNode()\n"); MapPort(false); if (semOutbound) - for (int i=0; ipost(); if (fAddressesInitialized) @@ -2448,6 +2490,7 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa fWhitelisted = false; fOneShot = false; fClient = false; // set by version message + fFeeler = false; fInbound = fInboundIn; fNetworkNode = false; fSuccessfullyConnected = false; diff --git a/src/net.h b/src/net.h index ea03defc408cf..1ba2d47da7d8c 100644 --- a/src/net.h +++ b/src/net.h @@ -41,6 +41,8 @@ namespace boost { static const int PING_INTERVAL = 2 * 60; /** Time after which to disconnect, after waiting for a ping response (or inactivity). */ static const int TIMEOUT_INTERVAL = 20 * 60; +/** Run the feeler connection loop once every 2 minutes or 120 seconds. **/ +static const int FEELER_INTERVAL = 120; /** The maximum number of entries in an 'inv' protocol message */ static const unsigned int MAX_INV_SZ = 50000; /** The maximum number of new addresses to accumulate before announcing. */ @@ -89,7 +91,7 @@ CNode* FindNode(const CSubNet& subNet); CNode* FindNode(const std::string& addrName); CNode* FindNode(const CService& ip); CNode* FindNode(const NodeId id); //TODO: Remove this -bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false); +bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false, bool fFeeler = false); void MapPort(bool fUseUPnP); unsigned short GetListenPort(); bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); @@ -350,6 +352,7 @@ class CNode // the network or wire types and the cleaned string used when displayed or logged. std::string strSubVer, cleanSubVer; bool fWhitelisted; // This peer can bypass DoS banning. + bool fFeeler; // If true this node is being used as a short lived feeler. bool fOneShot; bool fClient; bool fInbound; diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index 6511e6ffa24f1..267d1b55e13e8 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -150,4 +150,26 @@ BOOST_AUTO_TEST_CASE(caddrdb_read_corrupted) BOOST_CHECK(addrman2.size() == 0); } +BOOST_AUTO_TEST_CASE(cnode_simple_test) +{ + SOCKET hSocket = INVALID_SOCKET; + + in_addr ipv4Addr; + ipv4Addr.s_addr = 0xa0b0c001; + + CAddress addr = CAddress(CService(ipv4Addr, 7777), NODE_NETWORK); + std::string pszDest = ""; + bool fInboundIn = false; + + // Test that fFeeler is false by default. + CNode* pnode1 = new CNode(hSocket, addr, pszDest, fInboundIn); + BOOST_CHECK(pnode1->fInbound == false); + BOOST_CHECK(pnode1->fFeeler == false); + + fInboundIn = true; + CNode* pnode2 = new CNode(hSocket, addr, pszDest, fInboundIn); + BOOST_CHECK(pnode2->fInbound == true); + BOOST_CHECK(pnode2->fFeeler == false); +} + BOOST_AUTO_TEST_SUITE_END() From c91103573b7a928eebf9f564658537111d458a4f Mon Sep 17 00:00:00 2001 From: djpnewton Date: Wed, 24 Aug 2016 08:41:42 +1200 Subject: [PATCH 0758/1802] Add default port numbers to REST doc --- doc/REST-interface.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/REST-interface.md b/doc/REST-interface.md index bf669235e38a2..7fbb174030271 100644 --- a/doc/REST-interface.md +++ b/doc/REST-interface.md @@ -3,6 +3,8 @@ Unauthenticated REST Interface The REST API can be enabled with the `-rest` option. +The interface runs on the same port as the JSON-RPC interface, by default port 8332 for mainnet and port 18332 for testnet. + Supported API ------------- From 40a95cfd8f21bedbf35016b920f26c19bfb25c69 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Wed, 24 Aug 2016 09:06:56 +0200 Subject: [PATCH 0759/1802] Set jonasschnellis dns-seeder filter flag --- src/chainparams.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index ea6e3aada24ad..e6be1b5d5b716 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -118,7 +118,7 @@ class CMainParams : public CChainParams { vSeeds.push_back(CDNSSeedData("dashjr.org", "dnsseed.bitcoin.dashjr.org")); // Luke Dashjr vSeeds.push_back(CDNSSeedData("bitcoinstats.com", "seed.bitcoinstats.com")); // Christian Decker vSeeds.push_back(CDNSSeedData("xf2.org", "bitseed.xf2.org")); // Jeff Garzik - vSeeds.push_back(CDNSSeedData("bitcoin.jonasschnelli.ch", "seed.bitcoin.jonasschnelli.ch")); // Jonas Schnelli + vSeeds.push_back(CDNSSeedData("bitcoin.jonasschnelli.ch", "seed.bitcoin.jonasschnelli.ch", true)); // Jonas Schnelli base58Prefixes[PUBKEY_ADDRESS] = std::vector(1,0); base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,5); From fa8dd785a2d82e190ada724aa1c46dbd66fb3067 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Fri, 5 Aug 2016 17:09:16 +0200 Subject: [PATCH 0760/1802] [qt] Remove Priority from coincontrol dialog --- src/qt/coincontroldialog.cpp | 90 ++++--------------------------- src/qt/coincontroldialog.h | 8 --- src/qt/forms/coincontroldialog.ui | 61 ++++----------------- src/qt/forms/sendcoinsdialog.ui | 39 ++------------ src/qt/sendcoinsdialog.cpp | 9 ---- src/qt/sendcoinsdialog.h | 1 - 6 files changed, 27 insertions(+), 181 deletions(-) diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index 837f8ba6c18f5..f53242100cac7 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -76,7 +76,6 @@ CoinControlDialog::CoinControlDialog(const PlatformStyle *platformStyle, QWidget QAction *clipboardFeeAction = new QAction(tr("Copy fee"), this); QAction *clipboardAfterFeeAction = new QAction(tr("Copy after fee"), this); QAction *clipboardBytesAction = new QAction(tr("Copy bytes"), this); - QAction *clipboardPriorityAction = new QAction(tr("Copy priority"), this); QAction *clipboardLowOutputAction = new QAction(tr("Copy dust"), this); QAction *clipboardChangeAction = new QAction(tr("Copy change"), this); @@ -85,7 +84,6 @@ CoinControlDialog::CoinControlDialog(const PlatformStyle *platformStyle, QWidget connect(clipboardFeeAction, SIGNAL(triggered()), this, SLOT(clipboardFee())); connect(clipboardAfterFeeAction, SIGNAL(triggered()), this, SLOT(clipboardAfterFee())); connect(clipboardBytesAction, SIGNAL(triggered()), this, SLOT(clipboardBytes())); - connect(clipboardPriorityAction, SIGNAL(triggered()), this, SLOT(clipboardPriority())); connect(clipboardLowOutputAction, SIGNAL(triggered()), this, SLOT(clipboardLowOutput())); connect(clipboardChangeAction, SIGNAL(triggered()), this, SLOT(clipboardChange())); @@ -94,7 +92,6 @@ CoinControlDialog::CoinControlDialog(const PlatformStyle *platformStyle, QWidget ui->labelCoinControlFee->addAction(clipboardFeeAction); ui->labelCoinControlAfterFee->addAction(clipboardAfterFeeAction); ui->labelCoinControlBytes->addAction(clipboardBytesAction); - ui->labelCoinControlPriority->addAction(clipboardPriorityAction); ui->labelCoinControlLowOutput->addAction(clipboardLowOutputAction); ui->labelCoinControlChange->addAction(clipboardChangeAction); @@ -124,16 +121,14 @@ CoinControlDialog::CoinControlDialog(const PlatformStyle *platformStyle, QWidget ui->treeWidget->headerItem()->setText(COLUMN_CHECKBOX, QString()); ui->treeWidget->setColumnWidth(COLUMN_CHECKBOX, 84); - ui->treeWidget->setColumnWidth(COLUMN_AMOUNT, 100); - ui->treeWidget->setColumnWidth(COLUMN_LABEL, 170); - ui->treeWidget->setColumnWidth(COLUMN_ADDRESS, 290); - ui->treeWidget->setColumnWidth(COLUMN_DATE, 110); - ui->treeWidget->setColumnWidth(COLUMN_CONFIRMATIONS, 100); - ui->treeWidget->setColumnWidth(COLUMN_PRIORITY, 100); + ui->treeWidget->setColumnWidth(COLUMN_AMOUNT, 110); + ui->treeWidget->setColumnWidth(COLUMN_LABEL, 190); + ui->treeWidget->setColumnWidth(COLUMN_ADDRESS, 320); + ui->treeWidget->setColumnWidth(COLUMN_DATE, 130); + ui->treeWidget->setColumnWidth(COLUMN_CONFIRMATIONS, 110); ui->treeWidget->setColumnHidden(COLUMN_TXHASH, true); // store transaction hash in this column, but don't show it ui->treeWidget->setColumnHidden(COLUMN_VOUT_INDEX, true); // store vout index in this column, but don't show it ui->treeWidget->setColumnHidden(COLUMN_AMOUNT_INT64, true); // store amount int64 in this column, but don't show it - ui->treeWidget->setColumnHidden(COLUMN_PRIORITY_INT64, true); // store priority int64 in this column, but don't show it ui->treeWidget->setColumnHidden(COLUMN_DATE_INT64, true); // store date int64 in this column, but don't show it // default view is sorted by amount desc @@ -325,12 +320,6 @@ void CoinControlDialog::clipboardBytes() GUIUtil::setClipboard(ui->labelCoinControlBytes->text().replace(ASYMP_UTF8, "")); } -// copy label "Priority" to clipboard -void CoinControlDialog::clipboardPriority() -{ - GUIUtil::setClipboard(ui->labelCoinControlPriority->text()); -} - // copy label "Dust" to clipboard void CoinControlDialog::clipboardLowOutput() { @@ -419,25 +408,6 @@ void CoinControlDialog::viewItemChanged(QTreeWidgetItem* item, int column) #endif } -// return human readable label for priority number -QString CoinControlDialog::getPriorityLabel(double dPriority, double mempoolEstimatePriority) -{ - double dPriorityMedium = mempoolEstimatePriority; - - if (dPriorityMedium <= 0) - dPriorityMedium = AllowFreeThreshold(); // not enough data, back to hard-coded - - if (dPriority / 1000000 > dPriorityMedium) return tr("highest"); - else if (dPriority / 100000 > dPriorityMedium) return tr("higher"); - else if (dPriority / 10000 > dPriorityMedium) return tr("high"); - else if (dPriority / 1000 > dPriorityMedium) return tr("medium-high"); - else if (dPriority > dPriorityMedium) return tr("medium"); - else if (dPriority * 10 > dPriorityMedium) return tr("low-medium"); - else if (dPriority * 100 > dPriorityMedium) return tr("low"); - else if (dPriority * 1000 > dPriorityMedium) return tr("lower"); - else return tr("lowest"); -} - // shows count of locked unspent outputs void CoinControlDialog::updateLabelLocked() { @@ -473,7 +443,6 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) } } - QString sPriorityLabel = tr("none"); CAmount nAmount = 0; CAmount nPayFee = 0; CAmount nAfterFee = 0; @@ -551,11 +520,6 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) nBytes += nQuantity; // account for the witness byte that holds the number of stack items for each input. } - // Priority - double mempoolEstimatePriority = mempool.estimateSmartPriority(nTxConfirmTarget); - dPriority = dPriorityInputs / (nBytes - nBytesInputs + (nQuantityUncompressed * 29)); // 29 = 180 - 151 (uncompressed public keys are over the limit. max 151 bytes of the input are ignored for priority) - sPriorityLabel = CoinControlDialog::getPriorityLabel(dPriority, mempoolEstimatePriority); - // in the subtract fee from amount case, we can tell if zero change already and subtract the bytes, so that fee calculation afterwards is accurate if (CoinControlDialog::fSubtractFeeFromAmount) if (nAmount - nPayAmount == 0) @@ -568,6 +532,8 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) // Allow free? (require at least hard-coded threshold and default to that if no estimate) + double mempoolEstimatePriority = mempool.estimateSmartPriority(nTxConfirmTarget); + dPriority = dPriorityInputs / (nBytes - nBytesInputs + (nQuantityUncompressed * 29)); // 29 = 180 - 151 (uncompressed public keys are over the limit. max 151 bytes of the input are ignored for priority) double dPriorityNeeded = std::max(mempoolEstimatePriority, AllowFreeThreshold()); fAllowFree = (dPriority >= dPriorityNeeded); @@ -617,7 +583,6 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) QLabel *l3 = dialog->findChild("labelCoinControlFee"); QLabel *l4 = dialog->findChild("labelCoinControlAfterFee"); QLabel *l5 = dialog->findChild("labelCoinControlBytes"); - QLabel *l6 = dialog->findChild("labelCoinControlPriority"); QLabel *l7 = dialog->findChild("labelCoinControlLowOutput"); QLabel *l8 = dialog->findChild("labelCoinControlChange"); @@ -633,7 +598,6 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) l3->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nPayFee)); // Fee l4->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nAfterFee)); // After Fee l5->setText(((nBytes > 0) ? ASYMP_UTF8 : "") + QString::number(nBytes)); // Bytes - l6->setText(sPriorityLabel); // Priority l7->setText(fDust ? tr("yes") : tr("no")); // Dust l8->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nChange)); // Change if (nPayFee > 0 && (coinControl->nMinimumTotalFee < nPayFee)) @@ -644,21 +608,11 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) l8->setText(ASYMP_UTF8 + l8->text()); } - // turn labels "red" - l5->setStyleSheet((nBytes >= MAX_FREE_TRANSACTION_CREATE_SIZE) ? "color:red;" : "");// Bytes >= 1000 - l6->setStyleSheet((dPriority > 0 && !fAllowFree) ? "color:red;" : ""); // Priority < "medium" - l7->setStyleSheet((fDust) ? "color:red;" : ""); // Dust = "yes" + // turn label red when dust + l7->setStyleSheet((fDust) ? "color:red;" : ""); // tool tips - QString toolTip1 = tr("This label turns red if the transaction size is greater than 1000 bytes.") + "

"; - toolTip1 += tr("This means a fee of at least %1 per kB is required.").arg(BitcoinUnits::formatHtmlWithUnit(nDisplayUnit, CWallet::GetRequiredFee(1000))) + "

"; - toolTip1 += tr("Can vary +/- 1 byte per input."); - - QString toolTip2 = tr("Transactions with higher priority are more likely to get included into a block.") + "

"; - toolTip2 += tr("This label turns red if the priority is smaller than \"medium\".") + "

"; - toolTip2 += tr("This means a fee of at least %1 per kB is required.").arg(BitcoinUnits::formatHtmlWithUnit(nDisplayUnit, CWallet::GetRequiredFee(1000))); - - QString toolTip3 = tr("This label turns red if any recipient receives an amount smaller than the current dust threshold."); + QString toolTipDust = tr("This label turns red if any recipient receives an amount smaller than the current dust threshold."); // how many satoshis the estimated fee can vary per byte we guess wrong double dFeeVary; @@ -671,14 +625,11 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) l3->setToolTip(toolTip4); l4->setToolTip(toolTip4); - l5->setToolTip(toolTip1); - l6->setToolTip(toolTip2); - l7->setToolTip(toolTip3); + l7->setToolTip(toolTipDust); l8->setToolTip(toolTip4); dialog->findChild("labelCoinControlFeeText") ->setToolTip(l3->toolTip()); dialog->findChild("labelCoinControlAfterFeeText") ->setToolTip(l4->toolTip()); dialog->findChild("labelCoinControlBytesText") ->setToolTip(l5->toolTip()); - dialog->findChild("labelCoinControlPriorityText") ->setToolTip(l6->toolTip()); dialog->findChild("labelCoinControlLowOutputText")->setToolTip(l7->toolTip()); dialog->findChild("labelCoinControlChangeText") ->setToolTip(l8->toolTip()); @@ -702,7 +653,6 @@ void CoinControlDialog::updateView() QFlags flgTristate = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsTristate; int nDisplayUnit = model->getOptionsModel()->getDisplayUnit(); - double mempoolEstimatePriority = mempool.estimateSmartPriority(nTxConfirmTarget); std::map > mapCoins; model->listCoins(mapCoins); @@ -731,11 +681,8 @@ void CoinControlDialog::updateView() } CAmount nSum = 0; - double dPrioritySum = 0; int nChildren = 0; - int nInputSum = 0; BOOST_FOREACH(const COutput& out, coins.second) { - int nInputSize = 0; nSum += out.tx->vout[out.i].nValue; nChildren++; @@ -755,11 +702,6 @@ void CoinControlDialog::updateView() // if listMode or change => show bitcoin address. In tree mode, address is not shown again for direct wallet address outputs if (!treeMode || (!(sAddress == sWalletAddress))) itemOutput->setText(COLUMN_ADDRESS, sAddress); - - CPubKey pubkey; - CKeyID *keyid = boost::get(&outputAddress); - if (keyid && model->getPubKey(*keyid, pubkey) && !pubkey.IsCompressed()) - nInputSize = 29; // 29 = 180 - 151 (public key is 180 bytes, priority free area is 151 bytes) } // label @@ -788,13 +730,6 @@ void CoinControlDialog::updateView() // confirmations itemOutput->setText(COLUMN_CONFIRMATIONS, strPad(QString::number(out.nDepth), 8, " ")); - // priority - double dPriority = ((double)out.tx->vout[out.i].nValue / (nInputSize + 78)) * (out.nDepth+1); // 78 = 2 * 34 + 10 - itemOutput->setText(COLUMN_PRIORITY, CoinControlDialog::getPriorityLabel(dPriority, mempoolEstimatePriority)); - itemOutput->setText(COLUMN_PRIORITY_INT64, strPad(QString::number((int64_t)dPriority), 20, " ")); - dPrioritySum += (double)out.tx->vout[out.i].nValue * (out.nDepth+1); - nInputSum += nInputSize; - // transaction hash uint256 txhash = out.tx->GetHash(); itemOutput->setText(COLUMN_TXHASH, QString::fromStdString(txhash.GetHex())); @@ -819,12 +754,9 @@ void CoinControlDialog::updateView() // amount if (treeMode) { - dPrioritySum = dPrioritySum / (nInputSum + 78); itemWalletAddress->setText(COLUMN_CHECKBOX, "(" + QString::number(nChildren) + ")"); itemWalletAddress->setText(COLUMN_AMOUNT, BitcoinUnits::format(nDisplayUnit, nSum)); itemWalletAddress->setText(COLUMN_AMOUNT_INT64, strPad(QString::number(nSum), 15, " ")); - itemWalletAddress->setText(COLUMN_PRIORITY, CoinControlDialog::getPriorityLabel(dPrioritySum, mempoolEstimatePriority)); - itemWalletAddress->setText(COLUMN_PRIORITY_INT64, strPad(QString::number((int64_t)dPrioritySum), 20, " ")); } } diff --git a/src/qt/coincontroldialog.h b/src/qt/coincontroldialog.h index 1a467eb2ffba2..7d73421e3a72b 100644 --- a/src/qt/coincontroldialog.h +++ b/src/qt/coincontroldialog.h @@ -40,7 +40,6 @@ class CoinControlDialog : public QDialog // static because also called from sendcoinsdialog static void updateLabels(WalletModel*, QDialog*); - static QString getPriorityLabel(double dPriority, double mempoolEstimatePriority); static QList payAmounts; static CCoinControl *coinControl; @@ -72,11 +71,9 @@ class CoinControlDialog : public QDialog COLUMN_ADDRESS, COLUMN_DATE, COLUMN_CONFIRMATIONS, - COLUMN_PRIORITY, COLUMN_TXHASH, COLUMN_VOUT_INDEX, COLUMN_AMOUNT_INT64, - COLUMN_PRIORITY_INT64, COLUMN_DATE_INT64 }; @@ -87,8 +84,6 @@ class CoinControlDialog : public QDialog { if (column == COLUMN_AMOUNT_INT64) return COLUMN_AMOUNT; - else if (column == COLUMN_PRIORITY_INT64) - return COLUMN_PRIORITY; else if (column == COLUMN_DATE_INT64) return COLUMN_DATE; } @@ -96,8 +91,6 @@ class CoinControlDialog : public QDialog { if (column == COLUMN_AMOUNT) return COLUMN_AMOUNT_INT64; - else if (column == COLUMN_PRIORITY) - return COLUMN_PRIORITY_INT64; else if (column == COLUMN_DATE) return COLUMN_DATE_INT64; } @@ -118,7 +111,6 @@ private Q_SLOTS: void clipboardFee(); void clipboardAfterFee(); void clipboardBytes(); - void clipboardPriority(); void clipboardLowOutput(); void clipboardChange(); void radioTreeMode(bool); diff --git a/src/qt/forms/coincontroldialog.ui b/src/qt/forms/coincontroldialog.ui index c1fef6b9b171a..1ea00eb5c3337 100644 --- a/src/qt/forms/coincontroldialog.ui +++ b/src/qt/forms/coincontroldialog.ui @@ -140,7 +140,10 @@ - + + + false + 75 @@ -148,12 +151,15 @@ - Priority: + Dust: - + + + false + IBeamCursor @@ -161,7 +167,7 @@ Qt::ActionsContextMenu - medium + no Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse @@ -213,41 +219,6 @@ - - - - false - - - - 75 - true - - - - Dust: - - - - - - - false - - - IBeamCursor - - - Qt::ActionsContextMenu - - - no - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - @@ -431,7 +402,7 @@ false - 12 + 10 true @@ -472,16 +443,6 @@ Confirmed - - - Priority - - - - - - - diff --git a/src/qt/forms/sendcoinsdialog.ui b/src/qt/forms/sendcoinsdialog.ui index 12d6a62c081b3..06e09074d1453 100644 --- a/src/qt/forms/sendcoinsdialog.ui +++ b/src/qt/forms/sendcoinsdialog.ui @@ -332,7 +332,7 @@ - + 75 @@ -340,12 +340,12 @@ - Priority: + Dust: - + IBeamCursor @@ -353,7 +353,7 @@ Qt::ActionsContextMenu - medium + no Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse @@ -411,36 +411,7 @@ - - - - - 75 - true - - - - Dust: - - - - - - - IBeamCursor - - - Qt::ActionsContextMenu - - - no - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - + diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 6d50be56ecba7..3e96bb18c3ebd 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -69,7 +69,6 @@ SendCoinsDialog::SendCoinsDialog(const PlatformStyle *platformStyle, QWidget *pa QAction *clipboardFeeAction = new QAction(tr("Copy fee"), this); QAction *clipboardAfterFeeAction = new QAction(tr("Copy after fee"), this); QAction *clipboardBytesAction = new QAction(tr("Copy bytes"), this); - QAction *clipboardPriorityAction = new QAction(tr("Copy priority"), this); QAction *clipboardLowOutputAction = new QAction(tr("Copy dust"), this); QAction *clipboardChangeAction = new QAction(tr("Copy change"), this); connect(clipboardQuantityAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardQuantity())); @@ -77,7 +76,6 @@ SendCoinsDialog::SendCoinsDialog(const PlatformStyle *platformStyle, QWidget *pa connect(clipboardFeeAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardFee())); connect(clipboardAfterFeeAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardAfterFee())); connect(clipboardBytesAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardBytes())); - connect(clipboardPriorityAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardPriority())); connect(clipboardLowOutputAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardLowOutput())); connect(clipboardChangeAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardChange())); ui->labelCoinControlQuantity->addAction(clipboardQuantityAction); @@ -85,7 +83,6 @@ SendCoinsDialog::SendCoinsDialog(const PlatformStyle *platformStyle, QWidget *pa ui->labelCoinControlFee->addAction(clipboardFeeAction); ui->labelCoinControlAfterFee->addAction(clipboardAfterFeeAction); ui->labelCoinControlBytes->addAction(clipboardBytesAction); - ui->labelCoinControlPriority->addAction(clipboardPriorityAction); ui->labelCoinControlLowOutput->addAction(clipboardLowOutputAction); ui->labelCoinControlChange->addAction(clipboardChangeAction); @@ -681,12 +678,6 @@ void SendCoinsDialog::coinControlClipboardBytes() GUIUtil::setClipboard(ui->labelCoinControlBytes->text().replace(ASYMP_UTF8, "")); } -// Coin Control: copy label "Priority" to clipboard -void SendCoinsDialog::coinControlClipboardPriority() -{ - GUIUtil::setClipboard(ui->labelCoinControlPriority->text()); -} - // Coin Control: copy label "Dust" to clipboard void SendCoinsDialog::coinControlClipboardLowOutput() { diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h index be4f2ee44ba03..83dac0bd114b9 100644 --- a/src/qt/sendcoinsdialog.h +++ b/src/qt/sendcoinsdialog.h @@ -88,7 +88,6 @@ private Q_SLOTS: void coinControlClipboardFee(); void coinControlClipboardAfterFee(); void coinControlClipboardBytes(); - void coinControlClipboardPriority(); void coinControlClipboardLowOutput(); void coinControlClipboardChange(); void setMinimumFee(); From 57acb82e7014f3214229349485fa3f57842b10ae Mon Sep 17 00:00:00 2001 From: Andrew Chow Date: Wed, 10 Aug 2016 15:35:22 -0400 Subject: [PATCH 0761/1802] Load choose datadir dialog after options reset --- src/qt/intro.cpp | 3 ++- src/qt/optionsmodel.cpp | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index 6d6af54290fd5..390bcd22fbe78 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -178,7 +178,7 @@ void Intro::pickDataDirectory() /* 2) Allow QSettings to override default dir */ dataDir = settings.value("strDataDir", dataDir).toString(); - if(!fs::exists(GUIUtil::qstringToBoostPath(dataDir)) || GetBoolArg("-choosedatadir", DEFAULT_CHOOSE_DATADIR)) + if(!fs::exists(GUIUtil::qstringToBoostPath(dataDir)) || GetBoolArg("-choosedatadir", DEFAULT_CHOOSE_DATADIR) || settings.value("fReset", false).toBool() || GetBoolArg("-resetguisettings", false)) { /* If current default data directory does not exist, let the user choose one */ Intro intro; @@ -204,6 +204,7 @@ void Intro::pickDataDirectory() } settings.setValue("strDataDir", dataDir); + settings.setValue("fReset", false); } /* Only override -datadir if different from the default, to make it possible to * override -datadir in the bitcoin.conf file in the default data directory diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 7987d8e7ea470..5538a28413ddd 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -164,6 +164,9 @@ void OptionsModel::Reset() // Set strDataDir settings.setValue("strDataDir", dataDir); + // Set that this was reset + settings.setValue("fReset", true); + // default setting for OptionsModel::StartAtStartup - disabled if (GUIUtil::GetStartOnSystemStartup()) GUIUtil::SetStartOnSystemStartup(false); From fab5ecb7719063aa72751df1258dfa4cf4a9a4a9 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 24 Aug 2016 19:21:27 +0200 Subject: [PATCH 0762/1802] [wallet] rpc: Drop misleading option --- doc/release-notes.md | 8 +++++++ qa/rpc-tests/importprunedfunds.py | 35 ++++++++++++------------------- src/wallet/rpcdump.cpp | 7 +------ 3 files changed, 22 insertions(+), 28 deletions(-) diff --git a/doc/release-notes.md b/doc/release-notes.md index b99192ae97c9b..0be192233d5ea 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -41,6 +41,14 @@ report issues about Windows XP to the issue tracker. Notable changes =============== +Low-level RPC changes +---------------------- + +- `importprunedfunds` only accepts two required arguments. Some versions accept + an optional third arg, which was always ignored. Make sure to never pass more + than two arguments. + + 0.14.0 Change log ================= diff --git a/qa/rpc-tests/importprunedfunds.py b/qa/rpc-tests/importprunedfunds.py index eb3c11b4d85db..0dee8ad4ec922 100755 --- a/qa/rpc-tests/importprunedfunds.py +++ b/qa/rpc-tests/importprunedfunds.py @@ -20,14 +20,10 @@ def setup_network(self, split=False): self.is_network_split=False self.sync_all() - def run_test (self): - import time - begintime = int(time.time()) - + def run_test(self): print("Mining blocks...") self.nodes[0].generate(101) - # sync self.sync_all() # address @@ -72,7 +68,6 @@ def run_test (self): rawtxn2 = self.nodes[0].gettransaction(txnid2)['hex'] proof2 = self.nodes[0].gettxoutproof([txnid2]) - txnid3 = self.nodes[0].sendtoaddress(address3, 0.025) self.nodes[0].generate(1) rawtxn3 = self.nodes[0].gettransaction(txnid3)['hex'] @@ -82,28 +77,27 @@ def run_test (self): #Import with no affiliated address try: - result1 = self.nodes[1].importprunedfunds(rawtxn1, proof1, "") + self.nodes[1].importprunedfunds(rawtxn1, proof1) except JSONRPCException as e: assert('No addresses' in e.error['message']) else: assert(False) - balance1 = self.nodes[1].getbalance("", 0, True) assert_equal(balance1, Decimal(0)) #Import with affiliated address with no rescan - self.nodes[1].importaddress(address2, "", False) - result2 = self.nodes[1].importprunedfunds(rawtxn2, proof2, "") - balance2 = Decimal(self.nodes[1].getbalance("", 0, True)) + self.nodes[1].importaddress(address2, "add2", False) + result2 = self.nodes[1].importprunedfunds(rawtxn2, proof2) + balance2 = self.nodes[1].getbalance("add2", 0, True) assert_equal(balance2, Decimal('0.05')) #Import with private key with no rescan - self.nodes[1].importprivkey(address3_privkey, "", False) - result3 = self.nodes[1].importprunedfunds(rawtxn3, proof3, "") - balance3 = Decimal(self.nodes[1].getbalance("", 0, False)) + self.nodes[1].importprivkey(address3_privkey, "add3", False) + result3 = self.nodes[1].importprunedfunds(rawtxn3, proof3) + balance3 = self.nodes[1].getbalance("add3", 0, False) assert_equal(balance3, Decimal('0.025')) - balance3 = Decimal(self.nodes[1].getbalance("", 0, True)) + balance3 = self.nodes[1].getbalance("*", 0, True) assert_equal(balance3, Decimal('0.075')) #Addresses Test - after import @@ -118,7 +112,6 @@ def run_test (self): assert_equal(address_info['ismine'], True) #Remove transactions - try: self.nodes[1].removeprunedfunds(txnid1) except JSONRPCException as e: @@ -126,18 +119,16 @@ def run_test (self): else: assert(False) - - balance1 = Decimal(self.nodes[1].getbalance("", 0, True)) + balance1 = self.nodes[1].getbalance("*", 0, True) assert_equal(balance1, Decimal('0.075')) - self.nodes[1].removeprunedfunds(txnid2) - balance2 = Decimal(self.nodes[1].getbalance("", 0, True)) + balance2 = self.nodes[1].getbalance("*", 0, True) assert_equal(balance2, Decimal('0.025')) self.nodes[1].removeprunedfunds(txnid3) - balance3 = Decimal(self.nodes[1].getbalance("", 0, True)) + balance3 = self.nodes[1].getbalance("*", 0, True) assert_equal(balance3, Decimal('0.0')) if __name__ == '__main__': - ImportPrunedFundsTest ().main () + ImportPrunedFundsTest().main() diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index fe8b53ceb0c1a..42ebdb9b9b861 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -257,14 +257,13 @@ UniValue importprunedfunds(const UniValue& params, bool fHelp) if (!EnsureWalletIsAvailable(fHelp)) return NullUniValue; - if (fHelp || params.size() < 2 || params.size() > 3) + if (fHelp || params.size() != 2) throw runtime_error( "importprunedfunds\n" "\nImports funds without rescan. Corresponding address or script must previously be included in wallet. Aimed towards pruned wallets. The end-user is responsible to import additional transactions that subsequently spend the imported outputs or rescan after the point in the blockchain the transaction is included.\n" "\nArguments:\n" "1. \"rawtransaction\" (string, required) A raw transaction in hex funding an already-existing address in wallet\n" "2. \"txoutproof\" (string, required) The hex output from gettxoutproof that contains the transaction\n" - "3. \"label\" (string, optional) An optional label\n" ); CTransaction tx; @@ -277,10 +276,6 @@ UniValue importprunedfunds(const UniValue& params, bool fHelp) CMerkleBlock merkleBlock; ssMB >> merkleBlock; - string strLabel = ""; - if (params.size() == 3) - strLabel = params[2].get_str(); - //Search partial merkle tree in proof for our transaction and index in valid block vector vMatch; vector vIndex; From fa1cf9e7b83c7d1ac6130589c24c055406ba407a Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 24 Aug 2016 17:05:12 +0200 Subject: [PATCH 0763/1802] [test] Remove unused code --- src/test/base58_tests.cpp | 3 --- src/test/pmt_tests.cpp | 1 - src/test/rpc_tests.cpp | 12 ------------ src/test/util_tests.cpp | 9 ++------- 4 files changed, 2 insertions(+), 23 deletions(-) diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index 01eb2aee9ed02..ac3ab4c83f99e 100644 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -121,7 +121,6 @@ class TestPayloadVisitor : public boost::static_visitor BOOST_AUTO_TEST_CASE(base58_keys_valid_parse) { UniValue tests = read_json(std::string(json_tests::base58_keys_valid, json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid))); - std::vector result; CBitcoinSecret secret; CBitcoinAddress addr; SelectParams(CBaseChainParams::MAIN); @@ -179,7 +178,6 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse) BOOST_AUTO_TEST_CASE(base58_keys_valid_gen) { UniValue tests = read_json(std::string(json_tests::base58_keys_valid, json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid))); - std::vector result; for (unsigned int idx = 0; idx < tests.size(); idx++) { UniValue test = tests[idx]; @@ -247,7 +245,6 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen) BOOST_AUTO_TEST_CASE(base58_keys_invalid) { UniValue tests = read_json(std::string(json_tests::base58_keys_invalid, json_tests::base58_keys_invalid + sizeof(json_tests::base58_keys_invalid))); // Negative testcases - std::vector result; CBitcoinSecret secret; CBitcoinAddress addr; diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index 74ffe0cc74045..e9c8691745cc5 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -122,7 +122,6 @@ BOOST_AUTO_TEST_CASE(pmt_malleability) std::vector vMatch = boost::assign::list_of(false)(false)(false)(false)(false)(false)(false)(false)(false)(true)(true)(false); CPartialMerkleTree tree(vTxid, vMatch); - std::vector vTxid2; std::vector vIndex; BOOST_CHECK(tree.ExtractMatches(vTxid, vIndex).IsNull()); } diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index bbda6a48f4d5a..a15915aad2f10 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -18,18 +18,6 @@ using namespace std; -UniValue -createArgs(int nRequired, const char* address1=NULL, const char* address2=NULL) -{ - UniValue result(UniValue::VARR); - result.push_back(nRequired); - UniValue addresses(UniValue::VARR); - if (address1) addresses.push_back(address1); - if (address2) addresses.push_back(address2); - result.push_back(addresses); - return result; -} - UniValue CallRPC(string args) { vector vArgs; diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index e467a4171d984..efd44987473c2 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -243,11 +243,7 @@ BOOST_AUTO_TEST_CASE(util_IsHex) BOOST_AUTO_TEST_CASE(util_seed_insecure_rand) { - int i; - int count=0; - seed_insecure_rand(true); - for (int mod=2;mod<11;mod++) { int mask = 1; @@ -256,10 +252,9 @@ BOOST_AUTO_TEST_CASE(util_seed_insecure_rand) //mask is 2^ceil(log2(mod))-1 while(mask Date: Thu, 25 Aug 2016 09:21:58 +0700 Subject: [PATCH 0764/1802] Show XTHIN in GUI --- src/protocol.h | 3 +++ src/qt/guiutil.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/protocol.h b/src/protocol.h index 015215b2a668b..9b474ec79c8dd 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -267,6 +267,9 @@ enum ServiceFlags : uint64_t { // Indicates that a node can be asked for blocks and transactions including // witness data. NODE_WITNESS = (1 << 3), + // NODE_XTHIN means the node supports Xtreme Thinblocks + // If this is turned off then the node will not service nor make xthin requests + NODE_XTHIN = (1 << 4), // Bits 24-31 are reserved for temporary experiments. Just pick a bit that // isn't getting used, or one not being used much, and notify the diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 947a4c6821d84..c00f5e8591f3a 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -930,6 +930,9 @@ QString formatServicesStr(quint64 mask) case NODE_WITNESS: strList.append("WITNESS"); break; + case NODE_XTHIN: + strList.append("XTHIN"); + break; default: strList.append(QString("%1[%2]").arg("UNKNOWN").arg(check)); } From fa6dc9f0e5eac8ec473b63adfd43635005778f46 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 25 Aug 2016 12:48:23 +0200 Subject: [PATCH 0765/1802] Remove unused variables --- src/bitcoin-tx.cpp | 4 +--- src/init.cpp | 2 +- src/txmempool.cpp | 1 - src/wallet/wallet.cpp | 1 - 4 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 8e8ac47455cbe..5cf9b043ea94b 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -395,10 +395,8 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) if (!registers.count("privatekeys")) throw runtime_error("privatekeys register variable must be set."); - bool fGivenKeys = false; CBasicKeyStore tempKeystore; UniValue keysObj = registers["privatekeys"]; - fGivenKeys = true; for (unsigned int kidx = 0; kidx < keysObj.size(); kidx++) { if (!keysObj[kidx].isStr()) @@ -454,7 +452,7 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) // if redeemScript given and private keys given, // add redeemScript to the tempKeystore so it can be signed: - if (fGivenKeys && (scriptPubKey.IsPayToScriptHash() || scriptPubKey.IsPayToWitnessScriptHash()) && + if ((scriptPubKey.IsPayToScriptHash() || scriptPubKey.IsPayToWitnessScriptHash()) && prevOut.exists("redeemScript")) { UniValue v = prevOut["redeemScript"]; vector rsData(ParseHexUV(v, "redeemScript")); diff --git a/src/init.cpp b/src/init.cpp index 13c68e512a345..65ae4dbd9d1b0 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1183,8 +1183,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) fNameLookup = GetBoolArg("-dns", DEFAULT_NAME_LOOKUP); fRelayTxes = !GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY); - bool fBound = false; if (fListen) { + bool fBound = false; if (mapArgs.count("-bind") || mapArgs.count("-whitebind")) { BOOST_FOREACH(const std::string& strBind, mapMultiArgs["-bind"]) { CService addrBind; diff --git a/src/txmempool.cpp b/src/txmempool.cpp index b631c48484891..0a00d757a225a 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -576,7 +576,6 @@ void CTxMemPool::removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMem void CTxMemPool::removeConflicts(const CTransaction &tx, std::list& removed) { // Remove transactions which depend on inputs of tx, recursively - list result; LOCK(cs); BOOST_FOREACH(const CTxIn &txin, tx.vin) { auto it = mapNextTx.find(txin.prevout); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 769322969d207..10aca2e499f60 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2461,7 +2461,6 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) AddToWallet(wtxNew); // Notify that old coins are spent - set setCoins; BOOST_FOREACH(const CTxIn& txin, wtxNew.vin) { CWalletTx &coin = mapWallet[txin.prevout.hash]; From de1bbe3b7876e311ebba5445b7b251782c0a7e0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Tue, 7 Jun 2016 18:42:42 +0200 Subject: [PATCH 0766/1802] Do not shadow global RPC table variable (tableRPC) --- src/rpc/blockchain.cpp | 4 ++-- src/rpc/mining.cpp | 4 ++-- src/rpc/misc.cpp | 4 ++-- src/rpc/net.cpp | 4 ++-- src/rpc/rawtransaction.cpp | 4 ++-- src/rpc/register.h | 12 ++++++------ src/wallet/rpcwallet.cpp | 4 ++-- src/wallet/rpcwallet.h | 2 +- 8 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index e3c32d905af74..7f391da097fa3 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1205,8 +1205,8 @@ static const CRPCCommand commands[] = { "hidden", "reconsiderblock", &reconsiderblock, true }, }; -void RegisterBlockchainRPCCommands(CRPCTable &tableRPC) +void RegisterBlockchainRPCCommands(CRPCTable &t) { for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) - tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); + t.appendCommand(commands[vcidx].name, &commands[vcidx]); } diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 2479e5d5953d2..bc3e6c4ef7d8f 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -918,8 +918,8 @@ static const CRPCCommand commands[] = { "util", "estimatesmartpriority", &estimatesmartpriority, true }, }; -void RegisterMiningRPCCommands(CRPCTable &tableRPC) +void RegisterMiningRPCCommands(CRPCTable &t) { for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) - tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); + t.appendCommand(commands[vcidx].name, &commands[vcidx]); } diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index a8c5bcd177fbc..e96feaa864939 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -498,8 +498,8 @@ static const CRPCCommand commands[] = { "hidden", "setmocktime", &setmocktime, true }, }; -void RegisterMiscRPCCommands(CRPCTable &tableRPC) +void RegisterMiscRPCCommands(CRPCTable &t) { for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) - tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); + t.appendCommand(commands[vcidx].name, &commands[vcidx]); } diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 58cf4a56e05ec..74c32c1cc14f2 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -590,8 +590,8 @@ static const CRPCCommand commands[] = { "network", "clearbanned", &clearbanned, true }, }; -void RegisterNetRPCCommands(CRPCTable &tableRPC) +void RegisterNetRPCCommands(CRPCTable &t) { for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) - tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); + t.appendCommand(commands[vcidx].name, &commands[vcidx]); } diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 3270cd384f4b6..9461a7280ccac 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -910,8 +910,8 @@ static const CRPCCommand commands[] = { "blockchain", "verifytxoutproof", &verifytxoutproof, true }, }; -void RegisterRawTransactionRPCCommands(CRPCTable &tableRPC) +void RegisterRawTransactionRPCCommands(CRPCTable &t) { for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) - tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); + t.appendCommand(commands[vcidx].name, &commands[vcidx]); } diff --git a/src/rpc/register.h b/src/rpc/register.h index 01aa58a25d850..49aee2365f049 100644 --- a/src/rpc/register.h +++ b/src/rpc/register.h @@ -20,13 +20,13 @@ void RegisterMiningRPCCommands(CRPCTable &tableRPC); /** Register raw transaction RPC commands */ void RegisterRawTransactionRPCCommands(CRPCTable &tableRPC); -static inline void RegisterAllCoreRPCCommands(CRPCTable &tableRPC) +static inline void RegisterAllCoreRPCCommands(CRPCTable &t) { - RegisterBlockchainRPCCommands(tableRPC); - RegisterNetRPCCommands(tableRPC); - RegisterMiscRPCCommands(tableRPC); - RegisterMiningRPCCommands(tableRPC); - RegisterRawTransactionRPCCommands(tableRPC); + RegisterBlockchainRPCCommands(t); + RegisterNetRPCCommands(t); + RegisterMiscRPCCommands(t); + RegisterMiningRPCCommands(t); + RegisterRawTransactionRPCCommands(t); } #endif diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index aa0a9374c1991..9629ec1db6f59 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2617,8 +2617,8 @@ static const CRPCCommand commands[] = { "wallet", "removeprunedfunds", &removeprunedfunds, true }, }; -void RegisterWalletRPCCommands(CRPCTable &tableRPC) +void RegisterWalletRPCCommands(CRPCTable &t) { for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) - tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); + t.appendCommand(commands[vcidx].name, &commands[vcidx]); } diff --git a/src/wallet/rpcwallet.h b/src/wallet/rpcwallet.h index a5de7e2de1456..3a68ccf1b2556 100644 --- a/src/wallet/rpcwallet.h +++ b/src/wallet/rpcwallet.h @@ -7,6 +7,6 @@ class CRPCTable; -void RegisterWalletRPCCommands(CRPCTable &tableRPC); +void RegisterWalletRPCCommands(CRPCTable &t); #endif //BITCOIN_WALLET_RPCWALLET_H From fa28bfa341b0f1ca53ae2fc8d3d08afbf8d69a61 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 25 Aug 2016 15:28:11 +0200 Subject: [PATCH 0767/1802] [wallet] Set fLimitFree = true --- src/wallet/wallet.cpp | 9 ++++----- src/wallet/wallet.h | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 87b85eeb72301..3275ac2ef26ae 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1405,7 +1405,7 @@ void CWallet::ReacceptWalletTransactions() CWalletTx& wtx = *(item.second); LOCK(mempool.cs); - wtx.AcceptToMemoryPool(false, maxTxFee); + wtx.AcceptToMemoryPool(maxTxFee); } } @@ -2450,8 +2450,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) if (fBroadcastTransactions) { // Broadcast - if (!wtxNew.AcceptToMemoryPool(false, maxTxFee)) - { + if (!wtxNew.AcceptToMemoryPool(maxTxFee)) { // This must not fail. The transaction has already been signed and recorded. LogPrintf("CommitTransaction(): Error: Transaction not valid\n"); return false; @@ -3563,8 +3562,8 @@ int CMerkleTx::GetBlocksToMaturity() const } -bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, CAmount nAbsurdFee) +bool CMerkleTx::AcceptToMemoryPool(const CAmount& nAbsurdFee) { CValidationState state; - return ::AcceptToMemoryPool(mempool, state, *this, fLimitFree, NULL, false, nAbsurdFee); + return ::AcceptToMemoryPool(mempool, state, *this, true, NULL, false, nAbsurdFee); } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 7fc6ce5de5af1..db9e9d1a157cb 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -212,7 +212,7 @@ class CMerkleTx : public CTransaction bool IsInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet) > 0; } int GetBlocksToMaturity() const; /** Pass this transaction to the mempool. Fails if absolute fee exceeds absurd fee. */ - bool AcceptToMemoryPool(bool fLimitFree, const CAmount nAbsurdFee); + bool AcceptToMemoryPool(const CAmount& nAbsurdFee); bool hashUnset() const { return (hashBlock.IsNull() || hashBlock == ABANDON_HASH); } bool isAbandoned() const { return (hashBlock == ABANDON_HASH); } void setAbandoned() { hashBlock = ABANDON_HASH; } From fa8b02d36d5c75266d3c8ffb91ece761ce90e774 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 25 Aug 2016 15:29:32 +0200 Subject: [PATCH 0768/1802] [rpc] rawtx: Prepare fLimitFree to make it an option --- src/rpc/rawtransaction.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 3270cd384f4b6..b1eaa248d4b81 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -866,6 +866,7 @@ UniValue sendrawtransaction(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); uint256 hashTx = tx.GetHash(); + bool fLimitFree = false; CAmount nMaxRawTxFee = maxTxFee; if (params.size() > 1 && params[1].get_bool()) nMaxRawTxFee = 0; @@ -878,7 +879,7 @@ UniValue sendrawtransaction(const UniValue& params, bool fHelp) // push to local node and sync with wallets CValidationState state; bool fMissingInputs; - if (!AcceptToMemoryPool(mempool, state, tx, false, &fMissingInputs, false, nMaxRawTxFee)) { + if (!AcceptToMemoryPool(mempool, state, tx, fLimitFree, &fMissingInputs, false, nMaxRawTxFee)) { if (state.IsInvalid()) { throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason())); } else { From eb3596f7c220685fe6203178d5535c6775a789df Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Thu, 25 Aug 2016 23:42:40 +0000 Subject: [PATCH 0769/1802] Do not add random inbound peers to addrman. We should learn about new peers via address messages. An inbound peer connecting to us tells us nothing about its ability to accept incoming connections from us, so we shouldn't assume that we can connect to it based on this. The vast majority of nodes on the network do not accept incoming connections, adding them will only slow down the process of making a successful connection in the future. Nodes which have configured themselves to not announce would prefer we not violate their privacy by announcing them in GETADDR responses. --- src/main.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 5160e60750d08..ddd05411013e7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5029,12 +5029,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, pfrom->fGetAddr = true; } addrman.Good(pfrom->addr); - } else { - if (((CNetAddr)pfrom->addr) == (CNetAddr)addrFrom) - { - addrman.Add(addrFrom, addrFrom); - addrman.Good(addrFrom); - } } pfrom->fSuccessfullyConnected = true; From 0904c3cda4d1f40d41154bd9b2739660bdf12852 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 19 Jul 2016 15:22:01 +0200 Subject: [PATCH 0770/1802] [Refactor] refactor function that forms human readable text out of a timeoffset --- src/qt/bitcoingui.cpp | 25 +------------------------ src/qt/guiutil.cpp | 36 ++++++++++++++++++++++++++++++++++++ src/qt/guiutil.h | 2 ++ 3 files changed, 39 insertions(+), 24 deletions(-) diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 272df3fdae42c..b3cd7cfbcad93 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -762,30 +762,7 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer } else { - // Represent time from last generated block in human readable text - QString timeBehindText; - const int HOUR_IN_SECONDS = 60*60; - const int DAY_IN_SECONDS = 24*60*60; - const int WEEK_IN_SECONDS = 7*24*60*60; - const int YEAR_IN_SECONDS = 31556952; // Average length of year in Gregorian calendar - if(secs < 2*DAY_IN_SECONDS) - { - timeBehindText = tr("%n hour(s)","",secs/HOUR_IN_SECONDS); - } - else if(secs < 2*WEEK_IN_SECONDS) - { - timeBehindText = tr("%n day(s)","",secs/DAY_IN_SECONDS); - } - else if(secs < YEAR_IN_SECONDS) - { - timeBehindText = tr("%n week(s)","",secs/WEEK_IN_SECONDS); - } - else - { - qint64 years = secs / YEAR_IN_SECONDS; - qint64 remainder = secs % YEAR_IN_SECONDS; - timeBehindText = tr("%1 and %2").arg(tr("%n year(s)", "", years)).arg(tr("%n week(s)","", remainder/WEEK_IN_SECONDS)); - } + QString timeBehindText = GUIUtil::formateNiceTimeOffset(secs); progressBarLabel->setVisible(true); progressBar->setFormat(tr("%1 behind").arg(timeBehindText)); diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 947a4c6821d84..fe9de1c7a1bfd 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -952,4 +952,40 @@ QString formatTimeOffset(int64_t nTimeOffset) return QString(QObject::tr("%1 s")).arg(QString::number((int)nTimeOffset, 10)); } +QString formateNiceTimeOffset(qint64 secs) +{ + // Represent time from last generated block in human readable text + QString timeBehindText; + const int HOUR_IN_SECONDS = 60*60; + const int DAY_IN_SECONDS = 24*60*60; + const int WEEK_IN_SECONDS = 7*24*60*60; + const int YEAR_IN_SECONDS = 31556952; // Average length of year in Gregorian calendar + if(secs < 60) + { + timeBehindText = QObject::tr("%n seconds(s)","",secs); + } + else if(secs < 2*HOUR_IN_SECONDS) + { + timeBehindText = QObject::tr("%n minutes(s)","",secs/60); + } + else if(secs < 2*DAY_IN_SECONDS) + { + timeBehindText = QObject::tr("%n hour(s)","",secs/HOUR_IN_SECONDS); + } + else if(secs < 2*WEEK_IN_SECONDS) + { + timeBehindText = QObject::tr("%n day(s)","",secs/DAY_IN_SECONDS); + } + else if(secs < YEAR_IN_SECONDS) + { + timeBehindText = QObject::tr("%n week(s)","",secs/WEEK_IN_SECONDS); + } + else + { + qint64 years = secs / YEAR_IN_SECONDS; + qint64 remainder = secs % YEAR_IN_SECONDS; + timeBehindText = QObject::tr("%1 and %2").arg(QObject::tr("%n year(s)", "", years)).arg(QObject::tr("%n week(s)","", remainder/WEEK_IN_SECONDS)); + } + return timeBehindText; +} } // namespace GUIUtil diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h index 9267e0a6c9db0..7697e53ae9f3d 100644 --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -200,6 +200,8 @@ namespace GUIUtil /* Format a CNodeCombinedStats.nTimeOffset into a user-readable string. */ QString formatTimeOffset(int64_t nTimeOffset); + QString formateNiceTimeOffset(qint64 secs); + #if defined(Q_OS_MAC) && QT_VERSION >= 0x050000 // workaround for Qt OSX Bug: // https://bugreports.qt-project.org/browse/QTBUG-15631 From bd44a04dc3fe94d2764fadd9f9a7deb81ff49f45 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 19 Jul 2016 15:27:14 +0200 Subject: [PATCH 0771/1802] [Qt] make Out-Of-Sync warning icon clickable --- src/qt/forms/overviewpage.ui | 4 ++-- src/qt/overviewpage.cpp | 7 +++++++ src/qt/overviewpage.h | 2 ++ src/qt/walletframe.cpp | 6 ++++++ src/qt/walletframe.h | 6 ++++++ src/qt/walletview.cpp | 6 ++++++ src/qt/walletview.h | 5 +++++ 7 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/qt/forms/overviewpage.ui b/src/qt/forms/overviewpage.ui index 6d792d1475fed..923ed68996101 100644 --- a/src/qt/forms/overviewpage.ui +++ b/src/qt/forms/overviewpage.ui @@ -61,7 +61,7 @@ - false + true @@ -447,7 +447,7 @@ - false + true diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 6a0404cbf702f..e415a6c4dd2df 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -140,6 +140,8 @@ OverviewPage::OverviewPage(const PlatformStyle *platformStyle, QWidget *parent) // start with displaying the "out of sync" warnings showOutOfSyncWarning(true); + connect(ui->labelWalletStatus, SIGNAL(clicked()), this, SLOT(handleOutOfSyncWarningClicks())); + connect(ui->labelTransactionsStatus, SIGNAL(clicked()), this, SLOT(handleOutOfSyncWarningClicks())); } void OverviewPage::handleTransactionClicked(const QModelIndex &index) @@ -148,6 +150,11 @@ void OverviewPage::handleTransactionClicked(const QModelIndex &index) Q_EMIT transactionClicked(filter->mapToSource(index)); } +void OverviewPage::handleOutOfSyncWarningClicks() +{ + Q_EMIT outOfSyncWarningClicked(); +} + OverviewPage::~OverviewPage() { delete ui; diff --git a/src/qt/overviewpage.h b/src/qt/overviewpage.h index 911443c76af19..65cd3341b6b42 100644 --- a/src/qt/overviewpage.h +++ b/src/qt/overviewpage.h @@ -42,6 +42,7 @@ public Q_SLOTS: Q_SIGNALS: void transactionClicked(const QModelIndex &index); + void outOfSyncWarningClicked(); private: Ui::OverviewPage *ui; @@ -62,6 +63,7 @@ private Q_SLOTS: void handleTransactionClicked(const QModelIndex &index); void updateAlerts(const QString &warnings); void updateWatchOnlyLabels(bool showWatchOnly); + void handleOutOfSyncWarningClicks(); }; #endif // BITCOIN_QT_OVERVIEWPAGE_H diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp index e4ca5e1831d15..9d68e54e3a27b 100644 --- a/src/qt/walletframe.cpp +++ b/src/qt/walletframe.cpp @@ -57,6 +57,8 @@ bool WalletFrame::addWallet(const QString& name, WalletModel *walletModel) // Ensure a walletView is able to show the main window connect(walletView, SIGNAL(showNormalIfMinimized()), gui, SLOT(showNormalIfMinimized())); + connect(walletView, SIGNAL(outOfSyncWarningClicked()), this, SLOT(outOfSyncWarningClicked())); + return true; } @@ -195,3 +197,7 @@ WalletView *WalletFrame::currentWalletView() return qobject_cast(walletStack->currentWidget()); } +void WalletFrame::outOfSyncWarningClicked() +{ + Q_EMIT requestedOfSyncWarningInfo(); +} \ No newline at end of file diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h index 9a5bc273c2eae..7e3a5690eb00a 100644 --- a/src/qt/walletframe.h +++ b/src/qt/walletframe.h @@ -38,6 +38,10 @@ class WalletFrame : public QFrame void showOutOfSyncWarning(bool fShow); +Q_SIGNALS: + /** Notify that the user has requested more information about the out-of-sync warning */ + void requestedOfSyncWarningInfo(); + private: QStackedWidget *walletStack; BitcoinGUI *gui; @@ -78,6 +82,8 @@ public Q_SLOTS: void usedSendingAddresses(); /** Show used receiving addresses */ void usedReceivingAddresses(); + /** Pass on signal over requested out-of-sync-warning information */ + void outOfSyncWarningClicked(); }; #endif // BITCOIN_QT_WALLETFRAME_H diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index 495ebfd834bfc..656b21586f838 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -66,6 +66,7 @@ WalletView::WalletView(const PlatformStyle *platformStyle, QWidget *parent): // Clicking on a transaction on the overview pre-selects the transaction on the transaction history page connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), transactionView, SLOT(focusTransaction(QModelIndex))); + connect(overviewPage, SIGNAL(outOfSyncWarningClicked()), this, SLOT(requestedOfSyncWarningInfo())); // Double-clicking on a transaction on the transaction history page shows details connect(transactionView, SIGNAL(doubleClicked(QModelIndex)), transactionView, SLOT(showDetails())); @@ -322,3 +323,8 @@ void WalletView::showProgress(const QString &title, int nProgress) else if (progressDialog) progressDialog->setValue(nProgress); } + +void WalletView::requestedOfSyncWarningInfo() +{ + Q_EMIT outOfSyncWarningClicked(); +} diff --git a/src/qt/walletview.h b/src/qt/walletview.h index 2045605954d23..c0a27ab98970d 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -110,6 +110,9 @@ public Q_SLOTS: /** Show progress dialog e.g. for rescan */ void showProgress(const QString &title, int nProgress); + /** User has requested more information about the out of sync state */ + void requestedOfSyncWarningInfo(); + Q_SIGNALS: /** Signal that we want to show the main window */ void showNormalIfMinimized(); @@ -121,6 +124,8 @@ public Q_SLOTS: void hdEnabledStatusChanged(int hdEnabled); /** Notify that a new transaction appeared */ void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label); + /** Notify that the out of sync warning icon has been pressed */ + void outOfSyncWarningClicked(); }; #endif // BITCOIN_QT_WALLETVIEW_H From a001f1880283089d3eb0aa83e889d9707d79fd5f Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 19 Jul 2016 15:49:50 +0200 Subject: [PATCH 0772/1802] [Qt] Always pass the numBlocksChanged signal for headers tip changed --- src/qt/clientmodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 14661b857a5a5..30f412dd232f8 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -234,7 +234,7 @@ static void BlockTipChanged(ClientModel *clientmodel, bool initialSync, const CB int64_t& nLastUpdateNotification = fHeader ? nLastHeaderTipUpdateNotification : nLastBlockTipUpdateNotification; // if we are in-sync, update the UI regardless of last update time - if (!initialSync || now - nLastUpdateNotification > MODEL_UPDATE_DELAY) { + if (fHeader || !initialSync || now - nLastUpdateNotification > MODEL_UPDATE_DELAY) { //pass a async signal to the UI thread QMetaObject::invokeMethod(clientmodel, "numBlocksChanged", Qt::QueuedConnection, Q_ARG(int, pIndex->nHeight), From e47052f6b5ea901ecdc1cb8245dd98a98b06618a Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 19 Jul 2016 15:50:50 +0200 Subject: [PATCH 0773/1802] [Qt] ClientModel add method to get the height of the header chain --- src/qt/clientmodel.cpp | 8 ++++++++ src/qt/clientmodel.h | 1 + 2 files changed, 9 insertions(+) diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 30f412dd232f8..e3240b95a25f8 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -68,6 +68,14 @@ int ClientModel::getNumBlocks() const return chainActive.Height(); } +int ClientModel::getHeaderHeight() const +{ + LOCK(cs_main); + if (!pindexBestHeader) + return 0; + return pindexBestHeader->nHeight; +} + quint64 ClientModel::getTotalBytesRecv() const { return CNode::GetTotalBytesRecv(); diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 99fd574b9e14d..f0c9a7988a62e 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -51,6 +51,7 @@ class ClientModel : public QObject //! Return number of connections, default is in- and outbound (total) int getNumConnections(unsigned int flags = CONNECTIONS_ALL) const; int getNumBlocks() const; + int getHeaderHeight() const; //! Return number of transactions in the mempool long getMempoolSize() const; From e3245b43d5c6fc984e8c60495f6db54f85d64368 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 19 Jul 2016 15:51:24 +0200 Subject: [PATCH 0774/1802] [Qt] add out-of-sync modal info layer --- src/Makefile.qt.include | 4 + src/qt/bitcoingui.cpp | 31 ++- src/qt/bitcoingui.h | 4 + src/qt/forms/modaloverlay.ui | 370 +++++++++++++++++++++++++++++++++++ src/qt/modaloverlay.cpp | 150 ++++++++++++++ src/qt/modaloverlay.h | 44 +++++ 6 files changed, 602 insertions(+), 1 deletion(-) create mode 100644 src/qt/forms/modaloverlay.ui create mode 100644 src/qt/modaloverlay.cpp create mode 100644 src/qt/modaloverlay.h diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 8947aeaca0b14..ea9be82717e91 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -96,6 +96,7 @@ QT_FORMS_UI = \ qt/forms/editaddressdialog.ui \ qt/forms/helpmessagedialog.ui \ qt/forms/intro.ui \ + qt/forms/modaloverlay.ui \ qt/forms/openuridialog.ui \ qt/forms/optionsdialog.ui \ qt/forms/overviewpage.ui \ @@ -125,6 +126,7 @@ QT_MOC_CPP = \ qt/moc_intro.cpp \ qt/moc_macdockiconhandler.cpp \ qt/moc_macnotificationhandler.cpp \ + qt/moc_modaloverlay.cpp \ qt/moc_notificator.cpp \ qt/moc_openuridialog.cpp \ qt/moc_optionsdialog.cpp \ @@ -192,6 +194,7 @@ BITCOIN_QT_H = \ qt/intro.h \ qt/macdockiconhandler.h \ qt/macnotificationhandler.h \ + qt/modaloverlay.h \ qt/networkstyle.h \ qt/notificator.h \ qt/openuridialog.h \ @@ -292,6 +295,7 @@ BITCOIN_QT_CPP = \ qt/csvmodelwriter.cpp \ qt/guiutil.cpp \ qt/intro.cpp \ + qt/modaloverlay.cpp \ qt/networkstyle.cpp \ qt/notificator.cpp \ qt/optionsdialog.cpp \ diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index b3cd7cfbcad93..628d35b5ea8b5 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -12,6 +12,7 @@ #include "clientmodel.h" #include "guiconstants.h" #include "guiutil.h" +#include "modaloverlay.h" #include "networkstyle.h" #include "notificator.h" #include "openuridialog.h" @@ -114,6 +115,7 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *platformStyle, const NetworkStyle *n notificator(0), rpcConsole(0), helpMessageDialog(0), + modalOverlay(0), prevBlocks(0), spinnerFrame(0), platformStyle(platformStyle) @@ -241,6 +243,12 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *platformStyle, const NetworkStyle *n // Subscribe to notifications from core subscribeToCoreSignals(); + + modalOverlay = new ModalOverlay(this->centralWidget()); +#ifdef ENABLE_WALLET + if(enableWallet) + connect(walletFrame, SIGNAL(requestedOfSyncWarningInfo()), this, SLOT(showModalOverlay())); +#endif } BitcoinGUI::~BitcoinGUI() @@ -491,6 +499,8 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel) // initialize the disable state of the tray icon with the current value in the model. setTrayIconVisible(optionsModel->getHideTrayIcon()); } + + modalOverlay->setKnownBestHeight(clientModel->getHeaderHeight()); } else { // Disable possibility to show main window via action toggleHideAction->setEnabled(false); @@ -705,7 +715,14 @@ void BitcoinGUI::setNumConnections(int count) void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool header) { - if(!clientModel) + if (modalOverlay) + { + if (header) + modalOverlay->setKnownBestHeight(count); + else + modalOverlay->tipUpdate(count, blockDate, nVerificationProgress); + } + if (!clientModel) return; // Prevent orphan statusbar messages (e.g. hover Quit in main menu, wait until chain-sync starts -> garbelled text) @@ -754,7 +771,10 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer #ifdef ENABLE_WALLET if(walletFrame) + { walletFrame->showOutOfSyncWarning(false); + modalOverlay->showHide(true, true); + } #endif // ENABLE_WALLET progressBarLabel->setVisible(false); @@ -782,7 +802,10 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer #ifdef ENABLE_WALLET if(walletFrame) + { walletFrame->showOutOfSyncWarning(true); + modalOverlay->showHide(); + } #endif // ENABLE_WALLET tooltip += QString("
"); @@ -1078,6 +1101,12 @@ void BitcoinGUI::setTrayIconVisible(bool fHideTrayIcon) } } +void BitcoinGUI::showModalOverlay() +{ + if (modalOverlay) + modalOverlay->showHide(false, true); +} + static bool ThreadSafeMessageBox(BitcoinGUI *gui, const std::string& message, const std::string& caption, unsigned int style) { bool modal = (style & CClientUIInterface::MODAL); diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 41770929b4706..0eaa44b263ac5 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -29,6 +29,7 @@ class UnitDisplayStatusBarControl; class WalletFrame; class WalletModel; class HelpMessageDialog; +class ModalOverlay; class CWallet; @@ -118,6 +119,7 @@ class BitcoinGUI : public QMainWindow Notificator *notificator; RPCConsole *rpcConsole; HelpMessageDialog *helpMessageDialog; + ModalOverlay *modalOverlay; /** Keep track of previous number of blocks, to detect progress */ int prevBlocks; @@ -229,6 +231,8 @@ private Q_SLOTS: /** When hideTrayIcon setting is changed in OptionsModel hide or show the icon accordingly. */ void setTrayIconVisible(bool); + + void showModalOverlay(); }; class UnitDisplayStatusBarControl : public QLabel diff --git a/src/qt/forms/modaloverlay.ui b/src/qt/forms/modaloverlay.ui new file mode 100644 index 0000000000000..f1967a7c05721 --- /dev/null +++ b/src/qt/forms/modaloverlay.ui @@ -0,0 +1,370 @@ + + + ModalOverlay + + + + 0 + 0 + 640 + 385 + + + + Form + + + + QLayout::SetDefaultConstraint + + + 0 + + + 0 + + + 0 + + + 0 + + + + + #bgWidget { background: rgba(0,0,0,220); } + + + + 60 + + + 60 + + + 60 + + + 60 + + + + + #contentWidget { background: rgba(255,255,255,240); border-radius: 6px; } + +QLabel { color: rgb(40,40,40); } + + + + 0 + + + 10 + + + 10 + + + 10 + + + 10 + + + + + 20 + + + + + 0 + + + + + + + + + :/icons/warning + :/icons/warning:/icons/warning + + + + 48 + 48 + + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + 0 + + + 0 + + + + + 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. + + + Qt::RichText + + + true + + + + + + + + 75 + true + + + + This means that recent transactions will not be visible, and the balance will not be up-to-date until this process has completed. Spending bitcoins is not possible during that phase! + + + Qt::RichText + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + QFormLayout::FieldsStayAtSizeHint + + + 6 + + + 6 + + + 10 + + + + + + 75 + true + + + + Amount of blocks left + + + + + + + unknown... + + + + + + + + 75 + true + + + + Last block time + + + + + + + + 0 + 0 + + + + unknown... + + + + + + + + 75 + true + + + + Progress + + + + + + + + + ~ + + + + + + + 24 + + + + + + + + + + 75 + true + + + + Progress increase per Hour + + + + + + + calculating... + + + + + + + + 75 + true + + + + Estimated time left until synced + + + + + + + calculating... + + + + + + + + + 10 + + + 10 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Hide + + + + + + + + + + + + + + + + ModalOverlay + QWidget +
modaloverlay.h
+ 1 +
+
+ + +
diff --git a/src/qt/modaloverlay.cpp b/src/qt/modaloverlay.cpp new file mode 100644 index 0000000000000..1cd5b199661b7 --- /dev/null +++ b/src/qt/modaloverlay.cpp @@ -0,0 +1,150 @@ +// Copyright (c) 2017 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 "modaloverlay.h" +#include "ui_modaloverlay.h" + +#include "guiutil.h" + +#include +#include + +ModalOverlay::ModalOverlay(QWidget *parent) : +QWidget(parent), +ui(new Ui::ModalOverlay), +bestBlockHeight(0), +layerIsVisible(false), +userClosed(false) +{ + ui->setupUi(this); + connect(ui->closeButton, SIGNAL(clicked()), this, SLOT(closeClicked())); + if (parent) { + parent->installEventFilter(this); + raise(); + } + + blockProcessTime.clear(); + setVisible(false); +} + +ModalOverlay::~ModalOverlay() +{ + delete ui; +} + +bool ModalOverlay::eventFilter(QObject * obj, QEvent * ev) { + if (obj == parent()) { + if (ev->type() == QEvent::Resize) { + QResizeEvent * rev = static_cast(ev); + resize(rev->size()); + if (!layerIsVisible) + setGeometry(0, height(), width(), height()); + + } + else if (ev->type() == QEvent::ChildAdded) { + raise(); + } + } + return QWidget::eventFilter(obj, ev); +} + +//! Tracks parent widget changes +bool ModalOverlay::event(QEvent* ev) { + if (ev->type() == QEvent::ParentAboutToChange) { + if (parent()) parent()->removeEventFilter(this); + } + else if (ev->type() == QEvent::ParentChange) { + if (parent()) { + parent()->installEventFilter(this); + raise(); + } + } + return QWidget::event(ev); +} + +void ModalOverlay::setKnownBestHeight(int count) +{ + if (count > bestBlockHeight) + bestBlockHeight = count; +} + +void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVerificationProgress) +{ + QDateTime currentDate = QDateTime::currentDateTime(); + + // keep a vector of samples of verification progress at height + blockProcessTime.push_front(qMakePair(currentDate.currentMSecsSinceEpoch(), nVerificationProgress)); + + // show progress speed if we have more then one sample + if (blockProcessTime.size() >= 2) + { + // try to get the window from the last 500 seconds or at least 10 samples + double progressStart = blockProcessTime[0].second; + double progressDelta = 0; + double progressPerHour = 0; + qint64 timeDelta = 0; + qint64 remainingMSecs = 0; + double remainingProgress = 1.0 - nVerificationProgress; + for (int i = 1; i < blockProcessTime.size(); i++) + { + QPair sample = blockProcessTime[i]; + + // take first sample after 500 seconds or last available one + if (sample.first < (currentDate.currentMSecsSinceEpoch() - 500*1000) || i == blockProcessTime.size()-1) + { + progressDelta = progressStart-sample.second; + timeDelta = blockProcessTime[0].first - sample.first; + progressPerHour = progressDelta/(double)timeDelta*1000*3600; + remainingMSecs = remainingProgress / progressDelta * timeDelta; + break; + } + } + // show progress increase per hour + ui->progressIncreasePerH->setText(QString::number(progressPerHour*100, 'f', 2)+"%"); + + // show expected remaining time + ui->expectedTimeLeft->setText(GUIUtil::formateNiceTimeOffset(remainingMSecs/1000.0)); + + // keep maximal 5000 samples + static int maxSamples = 5000; + if (blockProcessTime.count() > maxSamples) + blockProcessTime.remove(maxSamples, blockProcessTime.count()-maxSamples); + } + + // show the last block date + ui->newestBlockDate->setText(blockDate.toString()); + + // show the percentage done according to nVerificationProgress + ui->percentageProgress->setText(QString::number(nVerificationProgress*100, 'f', 2)+"%"); + ui->progressBar->setValue(nVerificationProgress*100); + + // show remaining amount of blocks + if (bestBlockHeight > 0) + ui->amountOfBlocksLeft->setText(QString::number(bestBlockHeight-count)); +} + +void ModalOverlay::showHide(bool hide, bool userRequested) +{ + if ( (layerIsVisible && !hide) || (!layerIsVisible && hide) || (!hide && userClosed && !userRequested)) + return; + + if (!isVisible() && !hide) + setVisible(true); + + setGeometry(0, hide ? 0 : height(), width(), height()); + + QPropertyAnimation* animation = new QPropertyAnimation(this, "pos"); + animation->setDuration(300); + animation->setStartValue(QPoint(0, hide ? 0 : this->height())); + animation->setEndValue(QPoint(0, hide ? this->height() : 0)); + animation->setEasingCurve(QEasingCurve::OutQuad); + animation->start(QAbstractAnimation::DeleteWhenStopped); + layerIsVisible = !hide; +} + +void ModalOverlay::closeClicked() +{ + showHide(true); + userClosed = true; +} diff --git a/src/qt/modaloverlay.h b/src/qt/modaloverlay.h new file mode 100644 index 0000000000000..5bf913a3f3d6f --- /dev/null +++ b/src/qt/modaloverlay.h @@ -0,0 +1,44 @@ +// Copyright (c) 2017 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_QT_MODALOVERLAY_H +#define BITCOIN_QT_MODALOVERLAY_H + +#include +#include + +namespace Ui { + class ModalOverlay; +} + +/** Modal overlay to display information about the chain-sync state */ +class ModalOverlay : public QWidget +{ + Q_OBJECT + +public: + explicit ModalOverlay(QWidget *parent); + ~ModalOverlay(); + +public Q_SLOTS: + void tipUpdate(int count, const QDateTime& blockDate, double nVerificationProgress); + void setKnownBestHeight(int count); + + // will show or hide the modal layer + void showHide(bool hide = false, bool userRequested = false); + void closeClicked(); + +protected: + bool eventFilter(QObject * obj, QEvent * ev); + bool event(QEvent* ev); + +private: + Ui::ModalOverlay *ui; + int bestBlockHeight; //best known height (based on the headers) + QVector > blockProcessTime; + bool layerIsVisible; + bool userClosed; +}; + +#endif // BITCOIN_QT_MODALOVERLAY_H From 152f45ba58b1548bba0788ca557fd66197063aa3 Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Mon, 30 Nov 2015 13:11:18 +0800 Subject: [PATCH 0775/1802] Add option to opt into full-RBF when sending funds --- src/wallet/wallet.cpp | 9 ++++++--- src/wallet/wallet.h | 3 +++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 769322969d207..c804d79c28ba8 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -40,6 +40,7 @@ CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE); unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET; bool bSpendZeroConfChange = DEFAULT_SPEND_ZEROCONF_CHANGE; bool fSendFreeTransactions = DEFAULT_SEND_FREE_TRANSACTIONS; +bool fOptIntoFullRbf = DEFAULT_OPT_INTO_FULL_RBF; const char * DEFAULT_WALLET_DAT = "wallet.dat"; const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000; @@ -2355,11 +2356,11 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt // Fill vin // - // Note how the sequence number is set to max()-1 so that the - // nLockTime set above actually works. + // Note how the sequence number is set to non-maxint so that + // the nLockTime set above actually works. BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins) txNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second,CScript(), - std::numeric_limits::max()-1)); + std::numeric_limits::max() - (fOptIntoFullRbf ? 2 : 1))); // Sign int nIn = 0; @@ -3240,6 +3241,7 @@ std::string CWallet::GetWalletHelpString(bool showDebug) strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), DEFAULT_SPEND_ZEROCONF_CHANGE)); strUsage += HelpMessageOpt("-txconfirmtarget=", strprintf(_("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)"), DEFAULT_TX_CONFIRM_TARGET)); strUsage += HelpMessageOpt("-usehd", _("Use hierarchical deterministic key generation (HD) after BIP32. Only has effect during wallet creation/first start") + " " + strprintf(_("(default: %u)"), DEFAULT_USE_HD_WALLET)); + strUsage += HelpMessageOpt("-optintofullrbf", strprintf(_("Send transactions with full-RBF opt-in enabled (default: %u)"), DEFAULT_OPT_INTO_FULL_RBF)); strUsage += HelpMessageOpt("-upgradewallet", _("Upgrade wallet to latest format on startup")); strUsage += HelpMessageOpt("-wallet=", _("Specify wallet file (within data directory)") + " " + strprintf(_("(default: %s)"), DEFAULT_WALLET_DAT)); strUsage += HelpMessageOpt("-walletbroadcast", _("Make the wallet broadcast transactions") + " " + strprintf(_("(default: %u)"), DEFAULT_WALLETBROADCAST)); @@ -3480,6 +3482,7 @@ bool CWallet::ParameterInteraction() nTxConfirmTarget = GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET); bSpendZeroConfChange = GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE); fSendFreeTransactions = GetBoolArg("-sendfreetransactions", DEFAULT_SEND_FREE_TRANSACTIONS); + fOptIntoFullRbf = GetBoolArg("-optintofullrbf", DEFAULT_OPT_INTO_FULL_RBF); return true; } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index c06513650c74a..5d93d2c4d96d8 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -37,6 +37,7 @@ extern CFeeRate payTxFee; extern unsigned int nTxConfirmTarget; extern bool bSpendZeroConfChange; extern bool fSendFreeTransactions; +extern bool fOptIntoFullRbf; static const unsigned int DEFAULT_KEYPOOL_SIZE = 100; //! -paytxfee default @@ -53,6 +54,8 @@ static const bool DEFAULT_SPEND_ZEROCONF_CHANGE = true; static const bool DEFAULT_SEND_FREE_TRANSACTIONS = false; //! -txconfirmtarget default static const unsigned int DEFAULT_TX_CONFIRM_TARGET = 2; +//! -optintofullrbf default +static const bool DEFAULT_OPT_INTO_FULL_RBF = false; //! Largest (in bytes) free transaction we're willing to create static const unsigned int MAX_FREE_TRANSACTION_CREATE_SIZE = 1000; static const bool DEFAULT_WALLETBROADCAST = true; From 05fa823bf60d21049caebc64dd5c5add8ba4ee10 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 26 Aug 2016 12:13:48 +0200 Subject: [PATCH 0776/1802] wallet: Add BIP125 comment for MAXINT-1/-2 behavior --- src/wallet/wallet.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index c804d79c28ba8..5542a536e1d39 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2358,6 +2358,12 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt // // Note how the sequence number is set to non-maxint so that // the nLockTime set above actually works. + // + // BIP125 defines opt-in RBF as any nSequence < maxint-1, so + // we use the highest possible value in that range (maxint-2) + // to avoid conflicting with other possible uses of nSequence, + // and in the spirit of "smallest posible change from prior + // behavior." BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins) txNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second,CScript(), std::numeric_limits::max() - (fOptIntoFullRbf ? 2 : 1))); From ab53207b9cdb6422cbb515ca6acf1bf945651895 Mon Sep 17 00:00:00 2001 From: fanquake Date: Fri, 26 Aug 2016 19:40:24 +0800 Subject: [PATCH 0777/1802] [trivial][doc] Mention ++i as preferred to i++ in dev notes --- doc/developer-notes.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/developer-notes.md b/doc/developer-notes.md index 95c46b05fe203..70c0690ba3c21 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -14,6 +14,7 @@ gradually. - No indentation for public/protected/private or for namespaces. - No extra spaces inside parenthesis; don't do ( this ) - No space after function names; one space after if, for and while. + - `++i` is preferred over `i++`. Block style example: ```c++ @@ -24,7 +25,7 @@ class Class bool Function(char* psz, int n) { // Comment summarising what this section of code does - for (int i = 0; i < n; i++) { + for (int i = 0; i < n; ++i) { // When something fails, return early if (!Something()) return false; @@ -231,9 +232,9 @@ General Bitcoin Core - *Rationale*: Makes sure that they pass thorough testing, and that the tester will keep passing on the master branch. Otherwise all new pull requests will start failing the tests, resulting in confusion and mayhem - + - *Explanation*: If the test suite is to be updated for a change, this has to - be done first + be done first Wallet ------- From c25083bcef68188bc69ec8e64e3105d262d67ab8 Mon Sep 17 00:00:00 2001 From: fanquake Date: Fri, 26 Aug 2016 20:08:30 +0800 Subject: [PATCH 0778/1802] [trivial][doc] Mention gpg --refresh-keys in release-process.md --- doc/release-process.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/release-process.md b/doc/release-process.md index 41c1ac8556b1a..394b159b31ae5 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -137,9 +137,10 @@ Build output expected: ### Verify other gitian builders signatures to your own. (Optional) -Add other gitian builders keys to your gpg keyring +Add other gitian builders keys to your gpg keyring, and/or refresh keys. gpg --import bitcoin/contrib/gitian-keys/*.pgp + gpg --refresh-keys Verify the signatures From 35fe0393f216aa6020fc929272118eade5628636 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 26 Aug 2016 18:38:20 +0200 Subject: [PATCH 0779/1802] Rename to PrecomputedTransactionData --- src/main.cpp | 26 +++++++++++++------------- src/main.h | 12 ++++++------ src/script/bitcoinconsensus.cpp | 4 ++-- src/script/interpreter.cpp | 6 +++--- src/script/interpreter.h | 12 ++++++------ src/script/sigcache.h | 2 +- src/test/script_P2SH_tests.cpp | 4 ++-- src/test/transaction_tests.cpp | 12 ++++++------ 8 files changed, 39 insertions(+), 39 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 7f48ccbae1de4..3cb476f9577ba 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1492,13 +1492,13 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C // Check against previous transactions // This is done last to help prevent CPU exhaustion denial-of-service attacks. - CachedHashes cachedHashes(tx); - if (!CheckInputs(tx, state, view, true, scriptVerifyFlags, true, cachedHashes)) { + PrecomputedTransactionData txdata(tx); + if (!CheckInputs(tx, state, view, true, scriptVerifyFlags, true, txdata)) { // SCRIPT_VERIFY_CLEANSTACK requires SCRIPT_VERIFY_WITNESS, so we // need to turn both off, and compare against just turning off CLEANSTACK // to see if the failure is specifically due to witness validation. - if (CheckInputs(tx, state, view, true, scriptVerifyFlags & ~(SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_CLEANSTACK), true, cachedHashes) && - !CheckInputs(tx, state, view, true, scriptVerifyFlags & ~SCRIPT_VERIFY_CLEANSTACK, true, cachedHashes)) { + if (CheckInputs(tx, state, view, true, scriptVerifyFlags & ~(SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_CLEANSTACK), true, txdata) && + !CheckInputs(tx, state, view, true, scriptVerifyFlags & ~SCRIPT_VERIFY_CLEANSTACK, true, txdata)) { // Only the witness is wrong, so the transaction itself may be fine. state.SetCorruptionPossible(); } @@ -1514,7 +1514,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C // There is a similar check in CreateNewBlock() to prevent creating // invalid blocks, however allowing such transactions into the mempool // can be exploited as a DoS attack. - if (!CheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, cachedHashes)) + if (!CheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata)) { return error("%s: BUG! PLEASE REPORT THIS! ConnectInputs failed against MANDATORY but not STANDARD flags %s, %s", __func__, hash.ToString(), FormatStateMessage(state)); @@ -1911,7 +1911,7 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight) bool CScriptCheck::operator()() { const CScript &scriptSig = ptxTo->vin[nIn].scriptSig; const CScriptWitness *witness = (nIn < ptxTo->wit.vtxinwit.size()) ? &ptxTo->wit.vtxinwit[nIn].scriptWitness : NULL; - if (!VerifyScript(scriptSig, scriptPubKey, witness, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, amount, cacheStore, *cachedHashes), &error)) { + if (!VerifyScript(scriptSig, scriptPubKey, witness, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, amount, cacheStore, *txdata), &error)) { return false; } return true; @@ -1970,7 +1970,7 @@ bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoins } }// namespace Consensus -bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, CachedHashes& cachedHashes, std::vector *pvChecks) +bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, PrecomputedTransactionData& txdata, std::vector *pvChecks) { if (!tx.IsCoinBase()) { @@ -1997,7 +1997,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi assert(coins); // Verify signature - CScriptCheck check(*coins, tx, i, flags, cacheStore, &cachedHashes); + CScriptCheck check(*coins, tx, i, flags, cacheStore, &txdata); if (pvChecks) { pvChecks->push_back(CScriptCheck()); check.swap(pvChecks->back()); @@ -2010,7 +2010,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi // avoid splitting the network between upgraded and // non-upgraded nodes. CScriptCheck check2(*coins, tx, i, - flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore, &cachedHashes); + flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore, &txdata); if (check2()) return state.Invalid(false, REJECT_NONSTANDARD, strprintf("non-mandatory-script-verify-flag (%s)", ScriptErrorString(check.GetScriptError()))); } @@ -2406,8 +2406,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin std::vector > vPos; vPos.reserve(block.vtx.size()); blockundo.vtxundo.reserve(block.vtx.size() - 1); - std::vector cachedHashes; - cachedHashes.reserve(block.vtx.size()); // Required so that pointers to individual CachedHashes don't get invalidated + std::vector txdata; + txdata.reserve(block.vtx.size()); // Required so that pointers to individual PrecomputedTransactionData don't get invalidated for (unsigned int i = 0; i < block.vtx.size(); i++) { const CTransaction &tx = block.vtx[i]; @@ -2454,14 +2454,14 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return state.DoS(100, error("ConnectBlock(): too many sigops"), REJECT_INVALID, "bad-blk-sigops"); - cachedHashes.emplace_back(tx); + txdata.emplace_back(tx); if (!tx.IsCoinBase()) { nFees += view.GetValueIn(tx)-tx.GetValueOut(); std::vector vChecks; bool fCacheResults = fJustCheck; /* Don't cache results if we're actually connecting blocks (still consult the cache, though) */ - if (!CheckInputs(tx, state, view, fScriptChecks, flags, fCacheResults, cachedHashes[i], nScriptCheckThreads ? &vChecks : NULL)) + if (!CheckInputs(tx, state, view, fScriptChecks, flags, fCacheResults, txdata[i], nScriptCheckThreads ? &vChecks : NULL)) return error("ConnectBlock(): CheckInputs on %s failed with %s", tx.GetHash().ToString(), FormatStateMessage(state)); control.Add(vChecks); diff --git a/src/main.h b/src/main.h index fbf66c0481166..1c374c8a03ae3 100644 --- a/src/main.h +++ b/src/main.h @@ -38,7 +38,7 @@ class CScriptCheck; class CTxMemPool; class CValidationInterface; class CValidationState; -class CachedHashes; +class PrecomputedTransactionData; struct CNodeStateStats; struct LockPoints; @@ -348,7 +348,7 @@ int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& i * instead of being performed inline. */ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &view, bool fScriptChecks, - unsigned int flags, bool cacheStore, CachedHashes& cachedHashes, std::vector *pvChecks = NULL); + unsigned int flags, bool cacheStore, PrecomputedTransactionData& txdata, std::vector *pvChecks = NULL); /** Apply the effects of this transaction on the UTXO set represented by view */ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight); @@ -422,13 +422,13 @@ class CScriptCheck unsigned int nFlags; bool cacheStore; ScriptError error; - CachedHashes *cachedHashes; + PrecomputedTransactionData *txdata; public: CScriptCheck(): amount(0), ptxTo(0), nIn(0), nFlags(0), cacheStore(false), error(SCRIPT_ERR_UNKNOWN_ERROR) {} - CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn, CachedHashes* cachedHashesIn) : + CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn, PrecomputedTransactionData* txdataIn) : scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey), amount(txFromIn.vout[txToIn.vin[nInIn].prevout.n].nValue), - ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR), cachedHashes(cachedHashesIn) { } + ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR), txdata(txdataIn) { } bool operator()(); @@ -440,7 +440,7 @@ class CScriptCheck std::swap(nFlags, check.nFlags); std::swap(cacheStore, check.cacheStore); std::swap(error, check.error); - std::swap(cachedHashes, check.cachedHashes); + std::swap(txdata, check.txdata); } ScriptError GetScriptError() const { return error; } diff --git a/src/script/bitcoinconsensus.cpp b/src/script/bitcoinconsensus.cpp index 01a8babb679eb..b629f4278ba20 100644 --- a/src/script/bitcoinconsensus.cpp +++ b/src/script/bitcoinconsensus.cpp @@ -84,8 +84,8 @@ static int verify_script(const unsigned char *scriptPubKey, unsigned int scriptP // Regardless of the verification result, the tx did not error. set_error(err, bitcoinconsensus_ERR_OK); - CachedHashes cachedHashes(tx); - return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), nIn < tx.wit.vtxinwit.size() ? &tx.wit.vtxinwit[nIn].scriptWitness : NULL, flags, TransactionSignatureChecker(&tx, nIn, amount, cachedHashes), NULL); + PrecomputedTransactionData txdata(tx); + return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), nIn < tx.wit.vtxinwit.size() ? &tx.wit.vtxinwit[nIn].scriptWitness : NULL, flags, TransactionSignatureChecker(&tx, nIn, amount, txdata), NULL); } catch (const std::exception&) { return set_error(err, bitcoinconsensus_ERR_TX_DESERIALIZE); // Error deserializing } diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 459feaa0f4826..47ea261e31040 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1134,14 +1134,14 @@ uint256 GetOutputsHash(const CTransaction& txTo) { } // anon namespace -CachedHashes::CachedHashes(const CTransaction& txTo) +PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo) { hashPrevouts = GetPrevoutHash(txTo); hashSequence = GetSequenceHash(txTo); hashOutputs = GetOutputsHash(txTo); } -uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const CachedHashes* cache) +uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache) { if (sigversion == SIGVERSION_WITNESS_V0) { uint256 hashPrevouts; @@ -1229,7 +1229,7 @@ bool TransactionSignatureChecker::CheckSig(const vector& vchSigIn int nHashType = vchSig.back(); vchSig.pop_back(); - uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion, this->cachedHashes); + uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion, this->txdata); if (!VerifySignature(vchSig, pubkey, sighash)) return false; diff --git a/src/script/interpreter.h b/src/script/interpreter.h index b4da113eec939..e5d7865cd3de6 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -98,11 +98,11 @@ enum bool CheckSignatureEncoding(const std::vector &vchSig, unsigned int flags, ScriptError* serror); -struct CachedHashes +struct PrecomputedTransactionData { uint256 hashPrevouts, hashSequence, hashOutputs; - CachedHashes(const CTransaction& tx); + PrecomputedTransactionData(const CTransaction& tx); }; enum SigVersion @@ -111,7 +111,7 @@ enum SigVersion SIGVERSION_WITNESS_V0 = 1, }; -uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const CachedHashes* cache = NULL); +uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache = NULL); class BaseSignatureChecker { @@ -140,14 +140,14 @@ class TransactionSignatureChecker : public BaseSignatureChecker const CTransaction* txTo; unsigned int nIn; const CAmount amount; - const CachedHashes* cachedHashes; + const PrecomputedTransactionData* txdata; protected: virtual bool VerifySignature(const std::vector& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const; public: - TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), cachedHashes(NULL) {} - TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, const CachedHashes& cachedHashesIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), cachedHashes(&cachedHashesIn) {} + TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(NULL) {} + TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, const PrecomputedTransactionData& txdataIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(&txdataIn) {} bool CheckSig(const std::vector& scriptSig, const std::vector& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const; bool CheckLockTime(const CScriptNum& nLockTime) const; bool CheckSequence(const CScriptNum& nSequence) const; diff --git a/src/script/sigcache.h b/src/script/sigcache.h index 551f8b2253e76..44551ec2bc435 100644 --- a/src/script/sigcache.h +++ b/src/script/sigcache.h @@ -22,7 +22,7 @@ class CachingTransactionSignatureChecker : public TransactionSignatureChecker bool store; public: - CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amount, bool storeIn, CachedHashes& cachedHashesIn) : TransactionSignatureChecker(txToIn, nInIn, amount, cachedHashesIn), store(storeIn) {} + CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amount, bool storeIn, PrecomputedTransactionData& txdataIn) : TransactionSignatureChecker(txToIn, nInIn, amount, txdataIn), store(storeIn) {} bool VerifySignature(const std::vector& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const; }; diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp index 5cd7c93622977..1a01593a8e163 100644 --- a/src/test/script_P2SH_tests.cpp +++ b/src/test/script_P2SH_tests.cpp @@ -108,12 +108,12 @@ BOOST_AUTO_TEST_CASE(sign) // All of the above should be OK, and the txTos have valid signatures // Check to make sure signature verification fails if we use the wrong ScriptSig: for (int i = 0; i < 8; i++) { - CachedHashes cachedHashes(txTo[i]); + PrecomputedTransactionData txdata(txTo[i]); for (int j = 0; j < 8; j++) { CScript sigSave = txTo[i].vin[0].scriptSig; txTo[i].vin[0].scriptSig = txTo[j].vin[0].scriptSig; - bool sigOK = CScriptCheck(CCoins(txFrom, 0), txTo[i], 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, false, &cachedHashes)(); + bool sigOK = CScriptCheck(CCoins(txFrom, 0), txTo[i], 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, false, &txdata)(); if (i == j) BOOST_CHECK_MESSAGE(sigOK, strprintf("VerifySignature %d %d", i, j)); else diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 8f8666c76d1dc..b5af400bc54b5 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -154,7 +154,7 @@ BOOST_AUTO_TEST_CASE(tx_valid) BOOST_CHECK_MESSAGE(CheckTransaction(tx, state), strTest); BOOST_CHECK(state.IsValid()); - CachedHashes cachedHashes(tx); + PrecomputedTransactionData txdata(tx); for (unsigned int i = 0; i < tx.vin.size(); i++) { if (!mapprevOutScriptPubKeys.count(tx.vin[i].prevout)) @@ -170,7 +170,7 @@ BOOST_AUTO_TEST_CASE(tx_valid) unsigned int verify_flags = ParseScriptFlags(test[2].get_str()); const CScriptWitness *witness = (i < tx.wit.vtxinwit.size()) ? &tx.wit.vtxinwit[i].scriptWitness : NULL; BOOST_CHECK_MESSAGE(VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], - witness, verify_flags, TransactionSignatureChecker(&tx, i, amount, cachedHashes), &err), + witness, verify_flags, TransactionSignatureChecker(&tx, i, amount, txdata), &err), strTest); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); } @@ -239,7 +239,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid) CValidationState state; fValid = CheckTransaction(tx, state) && state.IsValid(); - CachedHashes cachedHashes(tx); + PrecomputedTransactionData txdata(tx); for (unsigned int i = 0; i < tx.vin.size() && fValid; i++) { if (!mapprevOutScriptPubKeys.count(tx.vin[i].prevout)) @@ -255,7 +255,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid) } const CScriptWitness *witness = (i < tx.wit.vtxinwit.size()) ? &tx.wit.vtxinwit[i].scriptWitness : NULL; fValid = VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], - witness, verify_flags, TransactionSignatureChecker(&tx, i, amount, cachedHashes), &err); + witness, verify_flags, TransactionSignatureChecker(&tx, i, amount, txdata), &err); } BOOST_CHECK_MESSAGE(!fValid, strTest); BOOST_CHECK_MESSAGE(err != SCRIPT_ERR_OK, ScriptErrorString(err)); @@ -469,7 +469,7 @@ BOOST_AUTO_TEST_CASE(test_big_witness_transaction) { WithOrVersion(&ssout, 0) >> tx; // check all inputs concurrently, with the cache - CachedHashes cachedHashes(tx); + PrecomputedTransactionData txdata(tx); boost::thread_group threadGroup; CCheckQueue scriptcheckqueue(128); CCheckQueueControl control(&scriptcheckqueue); @@ -489,7 +489,7 @@ BOOST_AUTO_TEST_CASE(test_big_witness_transaction) { for(uint32_t i = 0; i < mtx.vin.size(); i++) { std::vector vChecks; - CScriptCheck check(coins, tx, i, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false, &cachedHashes); + CScriptCheck check(coins, tx, i, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false, &txdata); vChecks.push_back(CScriptCheck()); check.swap(vChecks.back()); control.Add(vChecks); From 144ed76ea0b38b7c21b224501964f8a2c65c4bb6 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 26 Aug 2016 21:07:05 +0200 Subject: [PATCH 0780/1802] Fix some locks This makes sure that cs_filter is never held while taking cs_main or CNode::cs_vSend. --- src/main.cpp | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 30edc5dbebaa9..8c4447a6d5d19 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4781,10 +4781,16 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam pfrom->PushMessage(NetMsgType::BLOCK, block); else if (inv.type == MSG_FILTERED_BLOCK) { - LOCK(pfrom->cs_filter); - if (pfrom->pfilter) + bool send = false; + CMerkleBlock merkleBlock; { - CMerkleBlock merkleBlock(block, *pfrom->pfilter); + LOCK(pfrom->cs_filter); + if (pfrom->pfilter) { + send = true; + merkleBlock = CMerkleBlock(block, *pfrom->pfilter); + } + } + if (send) { pfrom->PushMessage(NetMsgType::MERKLEBLOCK, merkleBlock); // CMerkleBlock just contains hashes, so also push any transactions in the block the client did not see // This avoids hurting performance by pointlessly requiring a round-trip @@ -6052,8 +6058,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, CBloomFilter filter; vRecv >> filter; - LOCK(pfrom->cs_filter); - if (!filter.IsWithinSizeConstraints()) { // There is no excuse for sending a too-large filter @@ -6062,11 +6066,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } else { + LOCK(pfrom->cs_filter); delete pfrom->pfilter; pfrom->pfilter = new CBloomFilter(filter); pfrom->pfilter->UpdateEmptyFull(); + pfrom->fRelayTxes = true; } - pfrom->fRelayTxes = true; } @@ -6077,20 +6082,21 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // Nodes must NEVER send a data item > 520 bytes (the max size for a script data object, // and thus, the maximum size any matched object can have) in a filteradd message - if (vData.size() > MAX_SCRIPT_ELEMENT_SIZE) - { - LOCK(cs_main); - Misbehaving(pfrom->GetId(), 100); + bool bad = false; + if (vData.size() > MAX_SCRIPT_ELEMENT_SIZE) { + bad = true; } else { LOCK(pfrom->cs_filter); - if (pfrom->pfilter) + if (pfrom->pfilter) { pfrom->pfilter->insert(vData); - else - { - LOCK(cs_main); - Misbehaving(pfrom->GetId(), 100); + } else { + bad = true; } } + if (bad) { + LOCK(cs_main); + Misbehaving(pfrom->GetId(), 100); + } } From 887919c7b7120ab0ca12703ea1cdfc18a5085aa2 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 26 Aug 2016 21:44:44 +0200 Subject: [PATCH 0781/1802] Check for compatibility with download in FindNextBlocksToDownload --- src/main.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 30edc5dbebaa9..73d8f003afce7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -532,7 +532,7 @@ CBlockIndex* LastCommonAncestor(CBlockIndex* pa, CBlockIndex* pb) { /** Update pindexLastCommonBlock and add not-in-flight missing successors to vBlocks, until it has * at most count entries. */ -void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector& vBlocks, NodeId& nodeStaller) { +void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector& vBlocks, NodeId& nodeStaller, const Consensus::Params& consensusParams) { if (count == 0) return; @@ -589,6 +589,10 @@ void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vectorfHaveWitness && IsWitnessEnabled(pindex->pprev, consensusParams)) { + // We wouldn't download this block or its descendants from this peer. + return; + } if (pindex->nStatus & BLOCK_HAVE_DATA || chainActive.Contains(pindex)) { if (pindex->nChainTx) state->pindexLastCommonBlock = pindex; @@ -6713,15 +6717,13 @@ bool SendMessages(CNode* pto) if (!pto->fDisconnect && !pto->fClient && (fFetch || !IsInitialBlockDownload()) && state.nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) { vector vToDownload; NodeId staller = -1; - FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller); + FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller, consensusParams); BOOST_FOREACH(CBlockIndex *pindex, vToDownload) { - if (State(pto->GetId())->fHaveWitness || !IsWitnessEnabled(pindex->pprev, consensusParams)) { - uint32_t nFetchFlags = GetFetchFlags(pto, pindex->pprev, consensusParams); - vGetData.push_back(CInv(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash())); - MarkBlockAsInFlight(pto->GetId(), pindex->GetBlockHash(), consensusParams, pindex); - LogPrint("net", "Requesting block %s (%d) peer=%d\n", pindex->GetBlockHash().ToString(), - pindex->nHeight, pto->id); - } + uint32_t nFetchFlags = GetFetchFlags(pto, pindex->pprev, consensusParams); + vGetData.push_back(CInv(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash())); + MarkBlockAsInFlight(pto->GetId(), pindex->GetBlockHash(), consensusParams, pindex); + LogPrint("net", "Requesting block %s (%d) peer=%d\n", pindex->GetBlockHash().ToString(), + pindex->nHeight, pto->id); } if (state.nBlocksInFlight == 0 && staller != -1) { if (State(staller)->nStallingSince == 0) { From 5127c4f21ca3f092b3a853833631dfc7f9c9456b Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 26 Aug 2016 23:05:09 +0200 Subject: [PATCH 0782/1802] Add preciousblock RPC Includes a bugfix by Luke-Jr. --- src/chain.h | 2 +- src/main.cpp | 38 ++++++++++++++++++++++++++++++++++++-- src/main.h | 3 +++ src/rpc/blockchain.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 3 deletions(-) diff --git a/src/chain.h b/src/chain.h index 76a774c1238f1..bf801c5cbec12 100644 --- a/src/chain.h +++ b/src/chain.h @@ -200,7 +200,7 @@ class CBlockIndex unsigned int nNonce; //! (memory only) Sequential id assigned to distinguish order in which blocks are received. - uint32_t nSequenceId; + int32_t nSequenceId; void SetNull() { diff --git a/src/main.cpp b/src/main.cpp index 30edc5dbebaa9..8456039c8ffd9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -167,7 +167,11 @@ namespace { */ CCriticalSection cs_nBlockSequenceId; /** Blocks loaded from disk are assigned id 0, so start the counter at 1. */ - uint32_t nBlockSequenceId = 1; + int32_t nBlockSequenceId = 1; + /** Decreasing counter (used by subsequent preciousblock calls). */ + int32_t nBlockReverseSequenceId = -1; + /** chainwork for the last block that preciousblock has been applied to. */ + arith_uint256 nLastPreciousChainwork = 0; /** * Sources of received blocks, saved to be able to send them reject @@ -3107,6 +3111,36 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, return true; } + +bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex *pindex) +{ + { + LOCK(cs_main); + if (pindex->nChainWork < chainActive.Tip()->nChainWork) { + // Nothing to do, this block is not at the tip. + return true; + } + if (chainActive.Tip()->nChainWork > nLastPreciousChainwork) { + // The chain has been extended since the last call, reset the counter. + nBlockReverseSequenceId = -1; + } + nLastPreciousChainwork = chainActive.Tip()->nChainWork; + setBlockIndexCandidates.erase(pindex); + pindex->nSequenceId = nBlockReverseSequenceId; + if (nBlockReverseSequenceId > std::numeric_limits::min()) { + // We can't keep reducing the counter if somebody really wants to + // call preciousblock 2**31-1 times on the same set of tips... + nBlockReverseSequenceId--; + } + if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS) && pindex->nChainTx) { + setBlockIndexCandidates.insert(pindex); + PruneBlockIndexCandidates(); + } + } + + return ActivateBestChain(state, params); +} + bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex) { AssertLockHeld(cs_main); @@ -4501,7 +4535,7 @@ void static CheckBlockIndex(const Consensus::Params& consensusParams) assert(pindex->GetBlockHash() == consensusParams.hashGenesisBlock); // Genesis block's hash must match. assert(pindex == chainActive.Genesis()); // The current active chain's genesis block must be this block. } - if (pindex->nChainTx == 0) assert(pindex->nSequenceId == 0); // nSequenceId can't be set for blocks that aren't linked + if (pindex->nChainTx == 0) assert(pindex->nSequenceId <= 0); // nSequenceId can't be set positive for blocks that aren't linked (negative is used for preciousblock) // VALID_TRANSACTIONS is equivalent to nTx > 0 for all nodes (whether or not pruning has occurred). // HAVE_DATA is only equivalent to nTx > 0 (or VALID_TRANSACTIONS) if no pruning has occurred. if (!fHavePruned) { diff --git a/src/main.h b/src/main.h index e9106fccf7927..f809f89812860 100644 --- a/src/main.h +++ b/src/main.h @@ -499,6 +499,9 @@ class CVerifyDB { /** Find the last common block between the parameter chain and a locator. */ CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator); +/** Mark a block as precious and reorganize. */ +bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex *pindex); + /** Mark a block as invalid. */ bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index e3c32d905af74..75f49e939bac8 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1105,6 +1105,44 @@ UniValue getmempoolinfo(const UniValue& params, bool fHelp) return mempoolInfoToJSON(); } +UniValue preciousblock(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "preciousblock \"hash\"\n" + "\nTreats a block as if it were received before others with the same work.\n" + "\nA later preciousblock call can override the effect of an earlier one.\n" + "\nThe effects of preciousblock are not retained across restarts.\n" + "\nArguments:\n" + "1. hash (string, required) the hash of the block to mark as precious\n" + "\nResult:\n" + "\nExamples:\n" + + HelpExampleCli("preciousblock", "\"blockhash\"") + + HelpExampleRpc("preciousblock", "\"blockhash\"") + ); + + std::string strHash = params[0].get_str(); + uint256 hash(uint256S(strHash)); + CBlockIndex* pblockindex; + + { + LOCK(cs_main); + if (mapBlockIndex.count(hash) == 0) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); + + pblockindex = mapBlockIndex[hash]; + } + + CValidationState state; + PreciousBlock(state, Params(), pblockindex); + + if (!state.IsValid()) { + throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); + } + + return NullUniValue; +} + UniValue invalidateblock(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 1) @@ -1200,6 +1238,8 @@ static const CRPCCommand commands[] = { "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true }, { "blockchain", "verifychain", &verifychain, true }, + { "blockchain", "preciousblock", &preciousblock, true }, + /* Not shown in help */ { "hidden", "invalidateblock", &invalidateblock, true }, { "hidden", "reconsiderblock", &reconsiderblock, true }, From 5805ac836c5847bc54cbef3e71154d022ca18eda Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 26 Aug 2016 23:05:26 +0200 Subject: [PATCH 0783/1802] Add preciousblock tests Rebased, improved and extended by Luke-Jr. --- qa/pull-tester/rpc-tests.py | 1 + qa/rpc-tests/preciousblock.py | 116 ++++++++++++++++++++++++++++ qa/rpc-tests/test_framework/util.py | 10 +++ 3 files changed, 127 insertions(+) create mode 100755 qa/rpc-tests/preciousblock.py diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index 92cce6aadde0b..bd5c5f8e1892e 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -140,6 +140,7 @@ 'invalidtxrequest.py', 'abandonconflict.py', 'p2p-versionbits-warning.py', + 'preciousblock.py', 'importprunedfunds.py', 'signmessages.py', 'p2p-compactblocks.py', diff --git a/qa/rpc-tests/preciousblock.py b/qa/rpc-tests/preciousblock.py new file mode 100755 index 0000000000000..854dcc7251d1d --- /dev/null +++ b/qa/rpc-tests/preciousblock.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 +# Copyright (c) 2015 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# +# Test PreciousBlock code +# + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * + +def unidirectional_node_sync_via_rpc(node_src, node_dest): + blocks_to_copy = [] + blockhash = node_src.getbestblockhash() + while True: + try: + assert(len(node_dest.getblock(blockhash, False)) > 0) + break + except: + blocks_to_copy.append(blockhash) + blockhash = node_src.getblockheader(blockhash, True)['previousblockhash'] + blocks_to_copy.reverse() + for blockhash in blocks_to_copy: + blockdata = node_src.getblock(blockhash, False) + assert(node_dest.submitblock(blockdata) in (None, 'inconclusive')) + +def node_sync_via_rpc(nodes): + for node_src in nodes: + for node_dest in nodes: + if node_src is node_dest: + continue + unidirectional_node_sync_via_rpc(node_src, node_dest) + +class PreciousTest(BitcoinTestFramework): + def setup_chain(self): + print("Initializing test directory "+self.options.tmpdir) + initialize_chain_clean(self.options.tmpdir, 3) + + def setup_network(self): + self.nodes = [] + self.is_network_split = False + self.nodes.append(start_node(0, self.options.tmpdir, ["-debug"])) + self.nodes.append(start_node(1, self.options.tmpdir, ["-debug"])) + self.nodes.append(start_node(2, self.options.tmpdir, ["-debug"])) + + def run_test(self): + print("Ensure submitblock can in principle reorg to a competing chain") + self.nodes[0].generate(1) + assert(self.nodes[0].getblockcount() == 1) + (hashY, hashZ) = self.nodes[1].generate(2) + assert(self.nodes[1].getblockcount() == 2) + node_sync_via_rpc(self.nodes[0:3]) + assert(self.nodes[0].getbestblockhash() == hashZ) + + print("Mine blocks A-B-C on Node 0") + (hashA, hashB, hashC) = self.nodes[0].generate(3) + assert(self.nodes[0].getblockcount() == 5) + print("Mine competing blocks E-F-G on Node 1") + (hashE, hashF, hashG) = self.nodes[1].generate(3) + assert(self.nodes[1].getblockcount() == 5) + assert(hashC != hashG) + print("Connect nodes and check no reorg occurs") + # Submit competing blocks via RPC so any reorg should occur before we proceed (no way to wait on inaction for p2p sync) + node_sync_via_rpc(self.nodes[0:2]) + connect_nodes_bi(self.nodes,0,1) + assert(self.nodes[0].getbestblockhash() == hashC) + assert(self.nodes[1].getbestblockhash() == hashG) + print("Make Node0 prefer block G") + self.nodes[0].preciousblock(hashG) + assert(self.nodes[0].getbestblockhash() == hashG) + print("Make Node0 prefer block C again") + self.nodes[0].preciousblock(hashC) + assert(self.nodes[0].getbestblockhash() == hashC) + print("Make Node1 prefer block C") + self.nodes[1].preciousblock(hashC) + sync_chain(self.nodes[0:2]) # wait because node 1 may not have downloaded hashC + assert(self.nodes[1].getbestblockhash() == hashC) + print("Make Node1 prefer block G again") + self.nodes[1].preciousblock(hashG) + assert(self.nodes[1].getbestblockhash() == hashG) + print("Make Node0 prefer block G again") + self.nodes[0].preciousblock(hashG) + assert(self.nodes[0].getbestblockhash() == hashG) + print("Make Node1 prefer block C again") + self.nodes[1].preciousblock(hashC) + assert(self.nodes[1].getbestblockhash() == hashC) + print("Mine another block (E-F-G-)H on Node 0 and reorg Node 1") + self.nodes[0].generate(1) + assert(self.nodes[0].getblockcount() == 6) + sync_blocks(self.nodes[0:2]) + hashH = self.nodes[0].getbestblockhash() + assert(self.nodes[1].getbestblockhash() == hashH) + print("Node1 should not be able to prefer block C anymore") + self.nodes[1].preciousblock(hashC) + assert(self.nodes[1].getbestblockhash() == hashH) + print("Mine competing blocks I-J-K-L on Node 2") + self.nodes[2].generate(4) + assert(self.nodes[2].getblockcount() == 6) + hashL = self.nodes[2].getbestblockhash() + print("Connect nodes and check no reorg occurs") + node_sync_via_rpc(self.nodes[0:3]) + connect_nodes_bi(self.nodes,1,2) + connect_nodes_bi(self.nodes,0,2) + assert(self.nodes[0].getbestblockhash() == hashH) + assert(self.nodes[1].getbestblockhash() == hashH) + assert(self.nodes[2].getbestblockhash() == hashL) + print("Make Node1 prefer block L") + self.nodes[1].preciousblock(hashL) + assert(self.nodes[1].getbestblockhash() == hashL) + print("Make Node2 prefer block H") + self.nodes[2].preciousblock(hashH) + assert(self.nodes[2].getbestblockhash() == hashH) + +if __name__ == '__main__': + PreciousTest().main() diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index 190fa7f661a6d..bc0b801ff49a4 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -133,6 +133,16 @@ def sync_blocks(rpc_connections, wait=1, timeout=60): timeout -= wait raise AssertionError("Block sync failed") +def sync_chain(rpc_connections, wait=1): + """ + Wait until everybody has the same best block + """ + while True: + counts = [ x.getbestblockhash() for x in rpc_connections ] + if counts == [ counts[0] ]*len(counts): + break + time.sleep(wait) + def sync_mempools(rpc_connections, wait=1, timeout=60): """ Wait until everybody has the same transactions in their memory From d2cd9c033b603cb25dc4516f3511afa52dfb1ce0 Mon Sep 17 00:00:00 2001 From: nomnombtc Date: Sat, 27 Aug 2016 00:59:07 +0200 Subject: [PATCH 0784/1802] add script to generate manpages with help2man --- contrib/devtools/gen-manpages.sh | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100755 contrib/devtools/gen-manpages.sh diff --git a/contrib/devtools/gen-manpages.sh b/contrib/devtools/gen-manpages.sh new file mode 100755 index 0000000000000..7cd7d1b50997a --- /dev/null +++ b/contrib/devtools/gen-manpages.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +# the autodetected version git tag at the end +# can screw up manpage output a little bit +BTCVER=$(bitcoin-cli --version | cut -d"-" -f1 | cut -d"v" -f3) + +# Create a footer file with copyright content. +# This gets autodetected fine for bitcoind if +# --version-string is not set, but has different +# outcomes for bitcoin-qt and bitcoin-cli. +echo "[COPYRIGHT]" > footer.h2m +bitcoind --version | sed -n '1!p' >> footer.h2m + +for cmd in bitcoind bitcoin-qt bitcoin-cli; do + help2man -N --version-string=${BTCVER} --include=footer.h2m -o ../../doc/man/${cmd}.1 ${cmd} +done + +rm -f footer.h2m From 6edf2fdb85047be2d3236a2ced4c89116aa243bc Mon Sep 17 00:00:00 2001 From: nomnombtc Date: Sat, 27 Aug 2016 00:59:45 +0200 Subject: [PATCH 0785/1802] add gen-manpages.sh description to README.md --- contrib/devtools/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/contrib/devtools/README.md b/contrib/devtools/README.md index af5c000b0305e..60fe69e7e39e8 100644 --- a/contrib/devtools/README.md +++ b/contrib/devtools/README.md @@ -40,6 +40,12 @@ would be changed to: ```// Copyright (c) 2009-2015 The Bitcoin Core developers``` +gen-manpages.sh +=============== + +A small script to automatically create manpages in ../../doc/man by running the release binaries with the -help option. +This requires help2man which can be found at: https://www.gnu.org/software/help2man/ + git-subtree-check.sh ==================== From eb5643b7c709a86329666f0671dd899ace1012b3 Mon Sep 17 00:00:00 2001 From: nomnombtc Date: Sat, 27 Aug 2016 01:03:06 +0200 Subject: [PATCH 0786/1802] add autogenerated manpages by help2man --- doc/man/bitcoin-cli.1 | 84 +++++++ doc/man/bitcoin-qt.1 | 513 ++++++++++++++++++++++++++++++++++++++++++ doc/man/bitcoind.1 | 492 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1089 insertions(+) create mode 100644 doc/man/bitcoin-cli.1 create mode 100644 doc/man/bitcoin-qt.1 create mode 100644 doc/man/bitcoind.1 diff --git a/doc/man/bitcoin-cli.1 b/doc/man/bitcoin-cli.1 new file mode 100644 index 0000000000000..f15594080a074 --- /dev/null +++ b/doc/man/bitcoin-cli.1 @@ -0,0 +1,84 @@ +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.5. +.TH BITCOIN-CLI "1" "August 2016" "bitcoin-cli 0.13.0.0" "User Commands" +.SH NAME +bitcoin-cli \- manual page for bitcoin-cli 0.13.0.0 +.SH DESCRIPTION +Bitcoin Core RPC client version v0.13.0.0\-ga402396 +.SS "Usage:" +.TP +bitcoin\-cli [options] [params] +Send command to Bitcoin Core +.TP +bitcoin\-cli [options] help +List commands +.TP +bitcoin\-cli [options] help +Get help for a command +.SH OPTIONS +.HP +\-? +.IP +This help message +.HP +\fB\-conf=\fR +.IP +Specify configuration file (default: bitcoin.conf) +.HP +\fB\-datadir=\fR
+.IP +Specify data directory +.PP +Chain selection options: +.HP +\fB\-testnet\fR +.IP +Use the test chain +.HP +\fB\-regtest\fR +.IP +Enter regression test mode, which uses a special chain in which blocks +can be solved instantly. This is intended for regression testing +tools and app development. +.HP +\fB\-rpcconnect=\fR +.IP +Send commands to node running on (default: 127.0.0.1) +.HP +\fB\-rpcport=\fR +.IP +Connect to JSON\-RPC on (default: 8332 or testnet: 18332) +.HP +\fB\-rpcwait\fR +.IP +Wait for RPC server to start +.HP +\fB\-rpcuser=\fR +.IP +Username for JSON\-RPC connections +.HP +\fB\-rpcpassword=\fR +.IP +Password for JSON\-RPC connections +.HP +\fB\-rpcclienttimeout=\fR +.IP +Timeout during HTTP requests (default: 900) +.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) +.SH COPYRIGHT +Copyright (C) 2009-2016 The Bitcoin Core developers + +Please contribute if you find Bitcoin Core useful. Visit + for further information about the software. +The source code is available from . + +This is experimental software. +Distributed under the MIT software license, see the accompanying file COPYING +or . + +This product includes software developed by the OpenSSL Project for use in the +OpenSSL Toolkit and cryptographic software written +by Eric Young and UPnP software written by Thomas Bernard. diff --git a/doc/man/bitcoin-qt.1 b/doc/man/bitcoin-qt.1 new file mode 100644 index 0000000000000..b57e6819d93b1 --- /dev/null +++ b/doc/man/bitcoin-qt.1 @@ -0,0 +1,513 @@ +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.5. +.TH BITCOIN-QT "1" "August 2016" "bitcoin-qt 0.13.0.0" "User Commands" +.SH NAME +bitcoin-qt \- manual page for bitcoin-qt 0.13.0.0 +.SH DESCRIPTION +Bitcoin Core version v0.13.0.0\-ga402396 (64\-bit) +Usage: +.IP +bitcoin\-qt [command\-line options] +.SH OPTIONS +.HP +\-? +.IP +Print this help message and exit +.HP +\fB\-version\fR +.IP +Print version and exit +.HP +\fB\-alertnotify=\fR +.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\-blocknotify=\fR +.IP +Execute command when the best block changes (%s in cmd is replaced by +block hash) +.HP +\fB\-checkblocks=\fR +.IP +How many blocks to check at startup (default: 288, 0 = all) +.HP +\fB\-checklevel=\fR +.IP +How thorough the block verification of \fB\-checkblocks\fR is (0\-4, default: 3) +.HP +\fB\-conf=\fR +.IP +Specify configuration file (default: bitcoin.conf) +.HP +\fB\-datadir=\fR +.IP +Specify data directory +.HP +\fB\-dbcache=\fR +.IP +Set database cache size in megabytes (4 to 16384, default: 300) +.HP +\fB\-loadblock=\fR +.IP +Imports blocks from external blk000??.dat file on startup +.HP +\fB\-maxorphantx=\fR +.IP +Keep at most unconnectable transactions in memory (default: 100) +.HP +\fB\-maxmempool=\fR +.IP +Keep the transaction memory pool below megabytes (default: 300) +.HP +\fB\-mempoolexpiry=\fR +.IP +Do not keep transactions in the mempool longer than hours (default: +72) +.HP +\fB\-par=\fR +.IP +Set the number of script verification threads (\fB\-4\fR to 16, 0 = auto, <0 = +leave that many cores free, default: 0) +.HP +\fB\-pid=\fR +.IP +Specify pid file (default: bitcoind.pid) +.HP +\fB\-prune=\fR +.IP +Reduce storage requirements by pruning (deleting) old blocks. 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, >550 = target size in MiB +to use for block files) +.HP +\fB\-reindex\-chainstate\fR +.IP +Rebuild chain state from the currently indexed blocks +.HP +\fB\-reindex\fR +.IP +Rebuild chain state and block index from the blk*.dat files on disk +.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) +.PP +Connection options: +.HP +\fB\-addnode=\fR +.IP +Add a node to connect to and attempt to keep the connection open +.HP +\fB\-banscore=\fR +.IP +Threshold for disconnecting misbehaving peers (default: 100) +.HP +\fB\-bantime=\fR +.IP +Number of seconds to keep misbehaving peers from reconnecting (default: +86400) +.HP +\fB\-bind=\fR +.IP +Bind to given address and always listen on it. Use [host]:port notation +for IPv6 +.HP +\fB\-connect=\fR +.IP +Connect only to the specified node(s) +.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) +.HP +\fB\-externalip=\fR +.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 +.IP +Maintain at most connections to peers (default: 125) +.HP +\fB\-maxreceivebuffer=\fR +.IP +Maximum per\-connection receive buffer, *1000 bytes (default: 5000) +.HP +\fB\-maxsendbuffer=\fR +.IP +Maximum per\-connection send buffer, *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\-onion=\fR +.IP +Use separate SOCKS5 proxy to reach peers via Tor hidden services +(default: \fB\-proxy\fR) +.HP +\fB\-onlynet=\fR +.IP +Only connect to nodes in network (ipv4, ipv6 or onion) +.HP +\fB\-permitbaremultisig\fR +.IP +Relay non\-P2SH multisig (default: 1) +.HP +\fB\-peerbloomfilters\fR +.IP +Support filtering of blocks and transaction with bloom filters (default: +1) +.HP +\fB\-port=\fR +.IP +Listen for connections on (default: 8333 or testnet: 18333) +.HP +\fB\-proxy=\fR +.IP +Connect through SOCKS5 proxy +.HP +\fB\-proxyrandomize\fR +.IP +Randomize credentials for every proxy connection. This enables Tor +stream isolation (default: 1) +.HP +\fB\-seednode=\fR +.IP +Connect to a node to retrieve peer addresses, and disconnect +.HP +\fB\-timeout=\fR +.IP +Specify connection timeout in milliseconds (minimum: 1, default: 5000) +.HP +\fB\-torcontrol=\fR: +.IP +Tor control port to use if onion listening enabled (default: +127.0.0.1:9051) +.HP +\fB\-torpassword=\fR +.IP +Tor control port password (default: empty) +.HP +\fB\-whitebind=\fR +.IP +Bind to given address and whitelist peers connecting to it. Use +[host]:port notation for IPv6 +.HP +\fB\-whitelist=\fR +.IP +Whitelist peers connecting from the given netmask or IP address. 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 +.HP +\fB\-whitelistrelay\fR +.IP +Accept relayed transactions received from whitelisted peers even when +not relaying transactions (default: 1) +.HP +\fB\-whitelistforcerelay\fR +.IP +Force relay of transactions from whitelisted peers even they violate +local relay policy (default: 1) +.HP +\fB\-maxuploadtarget=\fR +.IP +Tries to keep outbound traffic under the given target (in MiB per 24h), +0 = no limit (default: 0) +.PP +Wallet options: +.HP +\fB\-disablewallet\fR +.IP +Do not load the wallet and disable wallet RPC calls +.HP +\fB\-keypool=\fR +.IP +Set key pool size to (default: 100) +.HP +\fB\-fallbackfee=\fR +.IP +A fee rate (in BTC/kB) that will be used when fee estimation has +insufficient data (default: 0.0002) +.HP +\fB\-mintxfee=\fR +.IP +Fees (in BTC/kB) smaller than this are considered zero fee for +transaction creation (default: 0.00001) +.HP +\fB\-paytxfee=\fR +.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 +.IP +If paytxfee is not set, include enough fee so transactions begin +confirmation on average within n blocks (default: 2) +.HP +\fB\-usehd\fR +.IP +Use hierarchical deterministic key generation (HD) after BIP32. Only has +effect during wallet creation/first start (default: 1) +.HP +\fB\-upgradewallet\fR +.IP +Upgrade wallet to latest format on startup +.HP +\fB\-wallet=\fR +.IP +Specify wallet file (within data directory) (default: wallet.dat) +.HP +\fB\-walletbroadcast\fR +.IP +Make the wallet broadcast transactions (default: 1) +.HP +\fB\-walletnotify=\fR +.IP +Execute command when a wallet transaction changes (%s in cmd is replaced +by TxID) +.HP +\fB\-zapwallettxes=\fR +.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. +account owner and payment request information, 2 = drop tx meta +data) +.PP +ZeroMQ notification options: +.HP +\fB\-zmqpubhashblock=\fR
+.IP +Enable publish hash block in
+.HP +\fB\-zmqpubhashtx=\fR
+.IP +Enable publish hash transaction in
+.HP +\fB\-zmqpubrawblock=\fR
+.IP +Enable publish raw block in
+.HP +\fB\-zmqpubrawtx=\fR
+.IP +Enable publish raw transaction in
+.PP +Debugging/Testing options: +.HP +\fB\-uacomment=\fR +.IP +Append comment to the user agent string +.HP +\fB\-debug=\fR +.IP +Output debugging information (default: 0, supplying is +optional). If is not supplied or if = 1, +output all debugging information. can be: addrman, +alert, bench, coindb, db, http, libevent, lock, mempool, +mempoolrej, net, proxy, prune, rand, reindex, rpc, selectcoins, +tor, zmq, qt. +.HP +\fB\-help\-debug\fR +.IP +Show all debugging options (usage: \fB\-\-help\fR \fB\-help\-debug\fR) +.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\-minrelaytxfee=\fR +.IP +Fees (in BTC/kB) smaller than this are considered zero fee for relaying, +mining and transaction creation (default: 0.00001) +.HP +\fB\-maxtxfee=\fR +.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 instead of debug.log file +.HP +\fB\-shrinkdebugfile\fR +.IP +Shrink debug.log file on client startup (default: 1 when no \fB\-debug\fR) +.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\-mempoolreplacement\fR +.IP +Enable transaction replacement in the memory pool (default: 1) +.PP +Block creation options: +.HP +\fB\-blockmaxweight=\fR +.IP +Set maximum BIP141 block weight (default: 3000000) +.HP +\fB\-blockmaxsize=\fR +.IP +Set maximum block size in bytes (default: 750000) +.HP +\fB\-blockprioritysize=\fR +.IP +Set maximum size of high\-priority/low\-fee transactions in bytes +(default: 0) +.PP +RPC server options: +.HP +\fB\-server\fR +.IP +Accept command line and JSON\-RPC commands +.HP +\fB\-rest\fR +.IP +Accept public REST requests (default: 0) +.HP +\fB\-rpcbind=\fR +.IP +Bind to given address to listen for JSON\-RPC connections. Use +[host]:port notation for IPv6. This option can be specified +multiple times (default: bind to all interfaces) +.HP +\fB\-rpccookiefile=\fR +.IP +Location of the auth cookie (default: data dir) +.HP +\fB\-rpcuser=\fR +.IP +Username for JSON\-RPC connections +.HP +\fB\-rpcpassword=\fR +.IP +Password for JSON\-RPC connections +.HP +\fB\-rpcauth=\fR +.IP +Username and hashed password for JSON\-RPC connections. The field + comes in the format: :$. A +canonical python script is included in share/rpcuser. This option +can be specified multiple times +.HP +\fB\-rpcport=\fR +.IP +Listen for JSON\-RPC connections on (default: 8332 or testnet: +18332) +.HP +\fB\-rpcallowip=\fR +.IP +Allow JSON\-RPC connections from specified source. Valid for 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\-rpcthreads=\fR +.IP +Set the number of threads to service RPC calls (default: 4) +.PP +UI Options: +.HP +\fB\-choosedatadir\fR +.IP +Choose data directory on startup (default: 0) +.HP +\fB\-lang=\fR +.IP +Set language, for example "de_DE" (default: system locale) +.HP +\fB\-min\fR +.IP +Start minimized +.HP +\fB\-rootcertificates=\fR +.IP +Set SSL root certificates for payment request (default: \fB\-system\-\fR) +.HP +\fB\-splash\fR +.IP +Show splash screen on startup (default: 1) +.HP +\fB\-resetguisettings\fR +.IP +Reset all settings changed in the GUI +.SH COPYRIGHT +Copyright (C) 2009-2016 The Bitcoin Core developers + +Please contribute if you find Bitcoin Core useful. Visit + for further information about the software. +The source code is available from . + +This is experimental software. +Distributed under the MIT software license, see the accompanying file COPYING +or . + +This product includes software developed by the OpenSSL Project for use in the +OpenSSL Toolkit and cryptographic software written +by Eric Young and UPnP software written by Thomas Bernard. diff --git a/doc/man/bitcoind.1 b/doc/man/bitcoind.1 new file mode 100644 index 0000000000000..c3c55add0ce85 --- /dev/null +++ b/doc/man/bitcoind.1 @@ -0,0 +1,492 @@ +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.5. +.TH BITCOIND "1" "August 2016" "bitcoind 0.13.0.0" "User Commands" +.SH NAME +bitcoind \- manual page for bitcoind 0.13.0.0 +.SH DESCRIPTION +Bitcoin Core Daemon version v0.13.0.0\-ga402396 +.SS "Usage:" +.TP +bitcoind [options] +Start Bitcoin Core Daemon +.SH OPTIONS +.HP +\-? +.IP +Print this help message and exit +.HP +\fB\-version\fR +.IP +Print version and exit +.HP +\fB\-alertnotify=\fR +.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\-blocknotify=\fR +.IP +Execute command when the best block changes (%s in cmd is replaced by +block hash) +.HP +\fB\-checkblocks=\fR +.IP +How many blocks to check at startup (default: 288, 0 = all) +.HP +\fB\-checklevel=\fR +.IP +How thorough the block verification of \fB\-checkblocks\fR is (0\-4, default: 3) +.HP +\fB\-conf=\fR +.IP +Specify configuration file (default: bitcoin.conf) +.HP +\fB\-daemon\fR +.IP +Run in the background as a daemon and accept commands +.HP +\fB\-datadir=\fR +.IP +Specify data directory +.HP +\fB\-dbcache=\fR +.IP +Set database cache size in megabytes (4 to 16384, default: 300) +.HP +\fB\-loadblock=\fR +.IP +Imports blocks from external blk000??.dat file on startup +.HP +\fB\-maxorphantx=\fR +.IP +Keep at most unconnectable transactions in memory (default: 100) +.HP +\fB\-maxmempool=\fR +.IP +Keep the transaction memory pool below megabytes (default: 300) +.HP +\fB\-mempoolexpiry=\fR +.IP +Do not keep transactions in the mempool longer than hours (default: +72) +.HP +\fB\-par=\fR +.IP +Set the number of script verification threads (\fB\-4\fR to 16, 0 = auto, <0 = +leave that many cores free, default: 0) +.HP +\fB\-pid=\fR +.IP +Specify pid file (default: bitcoind.pid) +.HP +\fB\-prune=\fR +.IP +Reduce storage requirements by pruning (deleting) old blocks. 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, >550 = target size in MiB +to use for block files) +.HP +\fB\-reindex\-chainstate\fR +.IP +Rebuild chain state from the currently indexed blocks +.HP +\fB\-reindex\fR +.IP +Rebuild chain state and block index from the blk*.dat files on disk +.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) +.PP +Connection options: +.HP +\fB\-addnode=\fR +.IP +Add a node to connect to and attempt to keep the connection open +.HP +\fB\-banscore=\fR +.IP +Threshold for disconnecting misbehaving peers (default: 100) +.HP +\fB\-bantime=\fR +.IP +Number of seconds to keep misbehaving peers from reconnecting (default: +86400) +.HP +\fB\-bind=\fR +.IP +Bind to given address and always listen on it. Use [host]:port notation +for IPv6 +.HP +\fB\-connect=\fR +.IP +Connect only to the specified node(s) +.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) +.HP +\fB\-externalip=\fR +.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 +.IP +Maintain at most connections to peers (default: 125) +.HP +\fB\-maxreceivebuffer=\fR +.IP +Maximum per\-connection receive buffer, *1000 bytes (default: 5000) +.HP +\fB\-maxsendbuffer=\fR +.IP +Maximum per\-connection send buffer, *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\-onion=\fR +.IP +Use separate SOCKS5 proxy to reach peers via Tor hidden services +(default: \fB\-proxy\fR) +.HP +\fB\-onlynet=\fR +.IP +Only connect to nodes in network (ipv4, ipv6 or onion) +.HP +\fB\-permitbaremultisig\fR +.IP +Relay non\-P2SH multisig (default: 1) +.HP +\fB\-peerbloomfilters\fR +.IP +Support filtering of blocks and transaction with bloom filters (default: +1) +.HP +\fB\-port=\fR +.IP +Listen for connections on (default: 8333 or testnet: 18333) +.HP +\fB\-proxy=\fR +.IP +Connect through SOCKS5 proxy +.HP +\fB\-proxyrandomize\fR +.IP +Randomize credentials for every proxy connection. This enables Tor +stream isolation (default: 1) +.HP +\fB\-seednode=\fR +.IP +Connect to a node to retrieve peer addresses, and disconnect +.HP +\fB\-timeout=\fR +.IP +Specify connection timeout in milliseconds (minimum: 1, default: 5000) +.HP +\fB\-torcontrol=\fR: +.IP +Tor control port to use if onion listening enabled (default: +127.0.0.1:9051) +.HP +\fB\-torpassword=\fR +.IP +Tor control port password (default: empty) +.HP +\fB\-whitebind=\fR +.IP +Bind to given address and whitelist peers connecting to it. Use +[host]:port notation for IPv6 +.HP +\fB\-whitelist=\fR +.IP +Whitelist peers connecting from the given netmask or IP address. 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 +.HP +\fB\-whitelistrelay\fR +.IP +Accept relayed transactions received from whitelisted peers even when +not relaying transactions (default: 1) +.HP +\fB\-whitelistforcerelay\fR +.IP +Force relay of transactions from whitelisted peers even they violate +local relay policy (default: 1) +.HP +\fB\-maxuploadtarget=\fR +.IP +Tries to keep outbound traffic under the given target (in MiB per 24h), +0 = no limit (default: 0) +.PP +Wallet options: +.HP +\fB\-disablewallet\fR +.IP +Do not load the wallet and disable wallet RPC calls +.HP +\fB\-keypool=\fR +.IP +Set key pool size to (default: 100) +.HP +\fB\-fallbackfee=\fR +.IP +A fee rate (in BTC/kB) that will be used when fee estimation has +insufficient data (default: 0.0002) +.HP +\fB\-mintxfee=\fR +.IP +Fees (in BTC/kB) smaller than this are considered zero fee for +transaction creation (default: 0.00001) +.HP +\fB\-paytxfee=\fR +.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 +.IP +If paytxfee is not set, include enough fee so transactions begin +confirmation on average within n blocks (default: 2) +.HP +\fB\-usehd\fR +.IP +Use hierarchical deterministic key generation (HD) after BIP32. Only has +effect during wallet creation/first start (default: 1) +.HP +\fB\-upgradewallet\fR +.IP +Upgrade wallet to latest format on startup +.HP +\fB\-wallet=\fR +.IP +Specify wallet file (within data directory) (default: wallet.dat) +.HP +\fB\-walletbroadcast\fR +.IP +Make the wallet broadcast transactions (default: 1) +.HP +\fB\-walletnotify=\fR +.IP +Execute command when a wallet transaction changes (%s in cmd is replaced +by TxID) +.HP +\fB\-zapwallettxes=\fR +.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. +account owner and payment request information, 2 = drop tx meta +data) +.PP +ZeroMQ notification options: +.HP +\fB\-zmqpubhashblock=\fR
+.IP +Enable publish hash block in
+.HP +\fB\-zmqpubhashtx=\fR
+.IP +Enable publish hash transaction in
+.HP +\fB\-zmqpubrawblock=\fR
+.IP +Enable publish raw block in
+.HP +\fB\-zmqpubrawtx=\fR
+.IP +Enable publish raw transaction in
+.PP +Debugging/Testing options: +.HP +\fB\-uacomment=\fR +.IP +Append comment to the user agent string +.HP +\fB\-debug=\fR +.IP +Output debugging information (default: 0, supplying is +optional). If is not supplied or if = 1, +output all debugging information. can be: addrman, +alert, bench, coindb, db, http, libevent, lock, mempool, +mempoolrej, net, proxy, prune, rand, reindex, rpc, selectcoins, +tor, zmq. +.HP +\fB\-help\-debug\fR +.IP +Show all debugging options (usage: \fB\-\-help\fR \fB\-help\-debug\fR) +.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\-minrelaytxfee=\fR +.IP +Fees (in BTC/kB) smaller than this are considered zero fee for relaying, +mining and transaction creation (default: 0.00001) +.HP +\fB\-maxtxfee=\fR +.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 instead of debug.log file +.HP +\fB\-shrinkdebugfile\fR +.IP +Shrink debug.log file on client startup (default: 1 when no \fB\-debug\fR) +.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\-mempoolreplacement\fR +.IP +Enable transaction replacement in the memory pool (default: 1) +.PP +Block creation options: +.HP +\fB\-blockmaxweight=\fR +.IP +Set maximum BIP141 block weight (default: 3000000) +.HP +\fB\-blockmaxsize=\fR +.IP +Set maximum block size in bytes (default: 750000) +.HP +\fB\-blockprioritysize=\fR +.IP +Set maximum size of high\-priority/low\-fee transactions in bytes +(default: 0) +.PP +RPC server options: +.HP +\fB\-server\fR +.IP +Accept command line and JSON\-RPC commands +.HP +\fB\-rest\fR +.IP +Accept public REST requests (default: 0) +.HP +\fB\-rpcbind=\fR +.IP +Bind to given address to listen for JSON\-RPC connections. Use +[host]:port notation for IPv6. This option can be specified +multiple times (default: bind to all interfaces) +.HP +\fB\-rpccookiefile=\fR +.IP +Location of the auth cookie (default: data dir) +.HP +\fB\-rpcuser=\fR +.IP +Username for JSON\-RPC connections +.HP +\fB\-rpcpassword=\fR +.IP +Password for JSON\-RPC connections +.HP +\fB\-rpcauth=\fR +.IP +Username and hashed password for JSON\-RPC connections. The field + comes in the format: :$. A +canonical python script is included in share/rpcuser. This option +can be specified multiple times +.HP +\fB\-rpcport=\fR +.IP +Listen for JSON\-RPC connections on (default: 8332 or testnet: +18332) +.HP +\fB\-rpcallowip=\fR +.IP +Allow JSON\-RPC connections from specified source. Valid for 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\-rpcthreads=\fR +.IP +Set the number of threads to service RPC calls (default: 4) +.SH COPYRIGHT +Copyright (C) 2009-2016 The Bitcoin Core developers + +Please contribute if you find Bitcoin Core useful. Visit + for further information about the software. +The source code is available from . + +This is experimental software. +Distributed under the MIT software license, see the accompanying file COPYING +or . + +This product includes software developed by the OpenSSL Project for use in the +OpenSSL Toolkit and cryptographic software written +by Eric Young and UPnP software written by Thomas Bernard. From 00dba72cc3674f3cf60ac42c78d5792264c78e94 Mon Sep 17 00:00:00 2001 From: nomnombtc Date: Sat, 27 Aug 2016 01:05:28 +0200 Subject: [PATCH 0787/1802] add doc/man/Makefile.am to include manpages --- doc/man/Makefile.am | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/man/Makefile.am diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am new file mode 100644 index 0000000000000..1a31039360b18 --- /dev/null +++ b/doc/man/Makefile.am @@ -0,0 +1 @@ +dist_man1_MANS=bitcoind.1 bitcoin-qt.1 bitcoin-cli.1 From dc84b6f4192828abd1c0c7a0960445870346c5c7 Mon Sep 17 00:00:00 2001 From: nomnombtc Date: Sat, 27 Aug 2016 01:09:22 +0200 Subject: [PATCH 0788/1802] add doc/man to subdir if configure flag --enable-man is set --- Makefile.am | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Makefile.am b/Makefile.am index 37c1e98eca6bc..2e061c3773580 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,8 @@ ACLOCAL_AMFLAGS = -I build-aux/m4 SUBDIRS = src +if ENABLE_MAN +SUBDIRS += doc/man +endif .PHONY: deploy FORCE GZIP_ENV="-9n" @@ -213,6 +216,8 @@ DISTCLEANFILES = qa/pull-tester/tests_config.pyc .INTERMEDIATE: $(COVERAGE_INFO) +DISTCHECK_CONFIGURE_FLAGS = --enable-man + clean-local: rm -rf coverage_percent.txt test_bitcoin.coverage/ total.coverage/ qa/tmp/ cache/ $(OSX_APP) rm -rf qa/pull-tester/__pycache__ From a32c102fb1766301977d093c006f7f6cbf7fbea7 Mon Sep 17 00:00:00 2001 From: nomnombtc Date: Sat, 27 Aug 2016 01:12:41 +0200 Subject: [PATCH 0789/1802] add conditional for --enable-man, default is yes --- configure.ac | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index d332f4face3ee..4eadd58e79c97 100644 --- a/configure.ac +++ b/configure.ac @@ -167,6 +167,13 @@ AC_ARG_ENABLE([zmq], AC_ARG_WITH([protoc-bindir],[AS_HELP_STRING([--with-protoc-bindir=BIN_DIR],[specify protoc bin path])], [protoc_bin_path=$withval], []) +# Enable manpages +AC_ARG_ENABLE(man, + [AS_HELP_STRING([--enable-man], + [install man pages [default=yes]])],, + enable_man=yes) +AM_CONDITIONAL(ENABLE_MAN, test "$enable_man" != no) + # Enable debug AC_ARG_ENABLE([debug], [AS_HELP_STRING([--enable-debug], @@ -1046,7 +1053,7 @@ AC_SUBST(EVENT_PTHREADS_LIBS) AC_SUBST(ZMQ_LIBS) AC_SUBST(PROTOBUF_LIBS) AC_SUBST(QR_LIBS) -AC_CONFIG_FILES([Makefile src/Makefile share/setup.nsi share/qt/Info.plist src/test/buildenv.py]) +AC_CONFIG_FILES([Makefile src/Makefile doc/man/Makefile share/setup.nsi share/qt/Info.plist src/test/buildenv.py]) AC_CONFIG_FILES([qa/pull-tester/run-bitcoind-for-test.sh],[chmod +x qa/pull-tester/run-bitcoind-for-test.sh]) AC_CONFIG_FILES([qa/pull-tester/tests_config.py],[chmod +x qa/pull-tester/tests_config.py]) AC_CONFIG_FILES([contrib/devtools/split-debug.sh],[chmod +x contrib/devtools/split-debug.sh]) From eda4cfb992d140c8471f6cc2bf16c4a106439225 Mon Sep 17 00:00:00 2001 From: Andrew Chow Date: Tue, 23 Aug 2016 16:20:15 -0400 Subject: [PATCH 0790/1802] Create an easy to use gitian building script I've written a script that automates the setup and building of binaries with gitian. All of the commands are pulled from various documentation on gitian building. --- contrib/README.md | 3 + contrib/gitian-build.sh | 362 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 365 insertions(+) create mode 100755 contrib/gitian-build.sh diff --git a/contrib/README.md b/contrib/README.md index a23b197cc6122..3e3c83da5f1e6 100644 --- a/contrib/README.md +++ b/contrib/README.md @@ -45,6 +45,9 @@ Scripts and notes for Mac builds. ### [RPM](/contrib/rpm) ### RPM spec file for building bitcoin-core on RPM based distributions +### [Gitian-build](/contrib/gitian-build.sh) ### +Script for running full gitian builds. + Test and Verify Tools --------------------- diff --git a/contrib/gitian-build.sh b/contrib/gitian-build.sh new file mode 100755 index 0000000000000..b51a91fdc0e39 --- /dev/null +++ b/contrib/gitian-build.sh @@ -0,0 +1,362 @@ +# What to do +sign=false +verify=false +build=false +setupenv=false + +# Systems to build +linux=true +windows=true +osx=true + +# Other Basic variables +SIGNER= +VERSION= +commit=false +url=https://github.com/bitcoin/bitcoin +proc=4 +mem=4000 +lxc=true +osslTarUrl=http://downloads.sourceforge.net/project/osslsigncode/osslsigncode/osslsigncode-1.7.1.tar.gz +osslPatchUrl=https://bitcoincore.org/cfields/osslsigncode-Backports-to-1.7.1.patch +scriptName=$(basename -- "$0") + +# Help Message +read -d '' usage <<- EOF +Usage: $scriptName [-c|u|v|b|s|B|o|h|j|m|] signer version + +Run this script from the directory containing the bitcoin, gitian-builder, gitian.sigs, and bitcoin-detached-sigs. + +Arguments: +signer GPG signer to sign each build assert file +version Version number, commit, or branch to build. If building a commit or branch, the -c option must be specified + +Options: +-c|--commit Indicate that the version argument is for a commit or branch +-u|--url Specify the URL of the repository. Default is https://github.com/bitcoin/bitcoin +-v|--verify Verify the gitian build +-b|--build Do a gitiain build +-s|--sign Make signed binaries for Windows and Mac OSX +-B|--buildsign Build both signed and unsigned binaries +-o|--os Specify which Operating Systems the build is for. Default is lwx. l for linux, w for windows, x for osx +-j Number of processes to use. Default 4 +-m Memory to allocate in MiB. Default 2000 +--kvm Use KVM instead of LXC +--setup Setup the gitian building environment. Uses KVM. If you want to use lxc, use the --lxc option. Only works on Debian-based systems (Ubuntu, Debian) +-h|--help Print this help message +EOF + +# Get options and arguments +while :; do + case $1 in + # Verify + -v|--verify) + verify=true + ;; + # Build + -b|--build) + build=true + ;; + # Sign binaries + -s|--sign) + sign=true + ;; + # Build then Sign + -B|--buildsign) + sign=true + build=true + ;; + # PGP Signer + -S|--signer) + if [ -n "$2" ] + then + SIGNER=$2 + shift + else + echo 'Error: "--signer" requires a non-empty argument.' + exit 1 + fi + ;; + # Operating Systems + -o|--os) + if [ -n "$2" ] + then + linux=false + windows=false + osx=false + if [[ "$2" = *"l"* ]] + then + linux=true + fi + if [[ "$2" = *"w"* ]] + then + windows=true + fi + if [[ "$2" = *"x"* ]] + then + osx=true + fi + shift + else + echo 'Error: "--os" requires an argument containing an l (for linux), w (for windows), or x (for Mac OSX)\n' + exit 1 + fi + ;; + # Help message + -h|--help) + echo "$usage" + exit 0 + ;; + # Commit or branch + -c|--commit) + commit=true + ;; + # Number of Processes + -j) + if [ -n "$2" ] + then + proc=$2 + shift + else + echo 'Error: "-j" requires an argument' + exit 1 + fi + ;; + # Memory to allocate + -m) + if [ -n "$2" ] + then + mem=$2 + shift + else + echo 'Error: "-m" requires an argument' + exit 1 + fi + ;; + # URL + -u) + if [ -n "$2" ] + then + url=$2 + shift + else + echo 'Error: "-u" requires an argument' + exit 1 + fi + ;; + # kvm + --kvm) + lxc=false + ;; + # Setup + --setup) + setup=true + ;; + *) # Default case: If no more options then break out of the loop. + break + esac + shift +done + +# Set up LXC +if [[ $lxc = true ]] +then + export USE_LXC=1 + export LXC_BRIDGE=lxcbr0 + sudo ifconfig lxcbr0 up 10.0.2.2 +fi + +# Get signer +if [[ -n"$1" ]] +then + SIGNER=$1 + shift +fi + +# Get version +if [[ -n "$1" ]] +then + VERSION=$1 + COMMIT=$VERSION + shift +fi + +# Check that a signer is specified +if [[ $SIGNER == "" ]] +then + echo "$scriptName: Missing signer." + echo "Try $scriptName --help for more information" + exit 1 +fi + +# Check that a version is specified +if [[ $VERSION == "" ]] +then + echo "$scriptName: Missing version." + echo "Try $scriptName --help for more information" + exit 1 +fi + +# Add a "v" if no -c +if [[ $commit = false ]] +then + COMMIT="v${VERSION}" +fi +echo ${COMMIT} + +# Setup build environment +if [[ $setup = true ]] +then + pushd ./gitian-builder + sudo apt-get install ruby apache2 git apt-cacher-ng python-vm-builder qemu-kvm qemu-utils + git clone https://github.com/bitcoin-core/gitian.sigs.git + git clone https://github.com/bitcoin-core/bitcoin-detached-sigs.git + git clone https://github.com/devrandom/gitian-builder.git + if [[ -n "$USE_LXC" ]] + then + sudo apt-get install lxc + bin/make-base-vm --suite trusty --arch amd64 --lxc + else + bin/make-base-vm --suite trusty --arch amd64 + fi + popd +fi + +# Set up build +pushd ./bitcoin +git fetch +git checkout ${COMMIT} +popd + +# Build +if [[ $build = true ]] +then + # Make output folder + mkdir -p ./bitcoin-binaries/${VERSION} + + # Build Dependencies + echo "" + echo "Building Dependencies" + echo "" + pushd ./gitian-builder + mkdir -p inputs + wget -N -P inputs $osslPatchUrl + wget -N -P inputs $osslTarUrl + make -C ../bitcoin/depends download SOURCES_PATH=`pwd`/cache/common + + # Linux + if [[ $linux = true ]] + then + echo "" + echo "Compiling ${VERSION} Linux" + echo "" + ./bin/gbuild -j ${proc} -m ${mem} --commit bitcoin=${COMMIT} --url bitcoin=${url} ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml + ./bin/gsign --signer $SIGNER --release ${VERSION}-linux --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml + mv build/out/bitcoin-*.tar.gz build/out/src/bitcoin-*.tar.gz ../bitcoin-binaries/${VERSION} + fi + # Windows + if [[ $windows = true ]] + then + echo "" + echo "Compiling ${VERSION} Windows" + echo "" + ./bin/gbuild -j ${proc} -m ${mem} --commit bitcoin=${COMMIT} --url bitcoin=${url} ../bitcoin/contrib/gitian-descriptors/gitian-win.yml + ./bin/gsign --signer $SIGNER --release ${VERSION}-win-unsigned --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win.yml + mv build/out/bitcoin-*-win-unsigned.tar.gz inputs/bitcoin-win-unsigned.tar.gz + mv build/out/bitcoin-*.zip build/out/bitcoin-*.exe ../bitcoin-binaries/${VERSION} + fi + # Mac OSX + if [[ $osx = true ]] + then + echo "" + echo "Compiling ${VERSION} Mac OSX" + echo "" + ./bin/gbuild -j ${proc} -m ${mem} --commit bitcoin=${COMMIT} --url bitcoin=${url} ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml + ./bin/gsign --signer $SIGNER --release ${VERSION}-osx-unsigned --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml + mv build/out/bitcoin-*-osx-unsigned.tar.gz inputs/bitcoin-osx-unsigned.tar.gz + mv build/out/bitcoin-*.tar.gz build/out/bitcoin-*.dmg ../bitcoin-binaries/${VERSION} + fi + popd + + # Commit to gitian.sigs repo + echo "" + echo "Committing ${VERSION} Unsigned Sigs" + echo "" + pushd gitian.sigs + git add ${VERSION}-linux/${SIGNER} + git add ${VERSION}-win-unsigned/${SIGNER} + git add ${VERSION}-osx-unsigned/${SIGNER} + git commit -a -m "Add ${VERSION} unsigned sigs for ${SIGNER}" + popd +fi + +# Verify the build +if [[ $verify = true ]] +then + # Linux + pushd ./gitian-builder + echo "" + echo "Verifying v${VERSION} Linux" + echo "" + ./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-linux ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml + # Windows + echo "" + echo "Verifying v${VERSION} Windows" + echo "" + ./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-win-unsigned ../bitcoin/contrib/gitian-descriptors/gitian-win.yml + # Mac OSX + echo "" + echo "Verifying v${VERSION} Mac OSX" + echo "" + ./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-osx-unsigned ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml + # Signed Windows + echo "" + echo "Verifying v${VERSION} Signed Windows" + echo "" + ./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-osx-signed ../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml + # Signed Mac OSX + echo "" + echo "Verifying v${VERSION} Signed Mac OSX" + echo "" + ./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-osx-signed ../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml + popd +fi + +# Sign binaries +if [[ $sign = true ]] +then + + pushd ./gitian-builder + # Sign Windows + if [[ $windows = true ]] + then + echo "" + echo "Signing ${VERSION} Windows" + echo "" + ./bin/gbuild -i --commit signature=${COMMIT} ../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml + ./bin/gsign --signer $SIGNER --release ${VERSION}-win-signed --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml + mv build/out/bitcoin-*win64-setup.exe ../bitcoin-binaries/${VERSION} + mv build/out/bitcoin-*win32-setup.exe ../bitcoin-binaries/${VERSION} + fi + # Sign Mac OSX + if [[ $osx = true ]] + then + echo "" + echo "Signing ${VERSION} Mac OSX" + echo "" + ./bin/gbuild -i --commit signature=${COMMIT} ../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml + ./bin/gsign --signer $SIGNER --release ${VERSION}-osx-signed --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml + mv build/out/bitcoin-osx-signed.dmg ../bitcoin-binaries/${VERSION}/bitcoin-${VERSION}-osx.dmg + fi + popd + + # Commit Sigs + pushd gitian.sigs + echo "" + echo "Committing ${VERSION} Signed Sigs" + echo "" + git add ${VERSION}-win-signed/${SIGNER} + git add ${VERSION}-osx-signed/${SIGNER} + git commit -a -m "Add ${VERSION} signed binary sigs for ${SIGNER}" + popd +fi From 498d8dadbf71b96f9b2a82e449c848acf1ed03f5 Mon Sep 17 00:00:00 2001 From: Andrew Chow Date: Thu, 25 Aug 2016 15:42:39 -0400 Subject: [PATCH 0791/1802] Check for OSX SDK --- contrib/gitian-build.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/contrib/gitian-build.sh b/contrib/gitian-build.sh index b51a91fdc0e39..7baaabee6d669 100755 --- a/contrib/gitian-build.sh +++ b/contrib/gitian-build.sh @@ -166,6 +166,13 @@ then sudo ifconfig lxcbr0 up 10.0.2.2 fi +# Check for OSX SDK +if [[ ! -e "gitian-builder/inputs/MacOSX10.11.sdk.tar.gz" && $osx == true ]] +then + echo "Cannot build for OSX, SDK does not exist. Will build for other OSes" + osx=false +fi + # Get signer if [[ -n"$1" ]] then From 6ffd6b4a573e00644b8985c825357a7aa7b8ce88 Mon Sep 17 00:00:00 2001 From: Andrew Chow Date: Thu, 25 Aug 2016 19:34:07 -0400 Subject: [PATCH 0792/1802] Create option to detach sign gitian builds and not commit the files in the script Gitian builds can be done where the assert files are made but no signing is done. The sigs can also optionally not be committed automatically. --- contrib/gitian-build.sh | 69 ++++++++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 25 deletions(-) diff --git a/contrib/gitian-build.sh b/contrib/gitian-build.sh index 7baaabee6d669..e45a0d591f649 100755 --- a/contrib/gitian-build.sh +++ b/contrib/gitian-build.sh @@ -20,6 +20,8 @@ lxc=true osslTarUrl=http://downloads.sourceforge.net/project/osslsigncode/osslsigncode/osslsigncode-1.7.1.tar.gz osslPatchUrl=https://bitcoincore.org/cfields/osslsigncode-Backports-to-1.7.1.patch scriptName=$(basename -- "$0") +signProg="gpg --detach-sign" +commitFiles=true # Help Message read -d '' usage <<- EOF @@ -43,6 +45,8 @@ Options: -m Memory to allocate in MiB. Default 2000 --kvm Use KVM instead of LXC --setup Setup the gitian building environment. Uses KVM. If you want to use lxc, use the --lxc option. Only works on Debian-based systems (Ubuntu, Debian) +--detach-sign Create the assert file for detached signing. Will not commit anything. +--no-commit Do not commit anything to git -h|--help Print this help message EOF @@ -148,6 +152,15 @@ while :; do --kvm) lxc=false ;; + # Detach sign + --detach-sign) + signProg="true" + commitFiles=false + ;; + # Commit files + --no-commit) + commitFiles=false + ;; # Setup --setup) setup=true @@ -214,11 +227,11 @@ echo ${COMMIT} # Setup build environment if [[ $setup = true ]] then - pushd ./gitian-builder sudo apt-get install ruby apache2 git apt-cacher-ng python-vm-builder qemu-kvm qemu-utils git clone https://github.com/bitcoin-core/gitian.sigs.git git clone https://github.com/bitcoin-core/bitcoin-detached-sigs.git git clone https://github.com/devrandom/gitian-builder.git + pushd ./gitian-builder if [[ -n "$USE_LXC" ]] then sudo apt-get install lxc @@ -258,7 +271,7 @@ then echo "Compiling ${VERSION} Linux" echo "" ./bin/gbuild -j ${proc} -m ${mem} --commit bitcoin=${COMMIT} --url bitcoin=${url} ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml - ./bin/gsign --signer $SIGNER --release ${VERSION}-linux --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml + ./bin/gsign -p $signProg --signer $SIGNER --release ${VERSION}-linux --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml mv build/out/bitcoin-*.tar.gz build/out/src/bitcoin-*.tar.gz ../bitcoin-binaries/${VERSION} fi # Windows @@ -268,7 +281,7 @@ then echo "Compiling ${VERSION} Windows" echo "" ./bin/gbuild -j ${proc} -m ${mem} --commit bitcoin=${COMMIT} --url bitcoin=${url} ../bitcoin/contrib/gitian-descriptors/gitian-win.yml - ./bin/gsign --signer $SIGNER --release ${VERSION}-win-unsigned --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win.yml + ./bin/gsign -p $signProg --signer $SIGNER --release ${VERSION}-win-unsigned --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win.yml mv build/out/bitcoin-*-win-unsigned.tar.gz inputs/bitcoin-win-unsigned.tar.gz mv build/out/bitcoin-*.zip build/out/bitcoin-*.exe ../bitcoin-binaries/${VERSION} fi @@ -279,22 +292,25 @@ then echo "Compiling ${VERSION} Mac OSX" echo "" ./bin/gbuild -j ${proc} -m ${mem} --commit bitcoin=${COMMIT} --url bitcoin=${url} ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml - ./bin/gsign --signer $SIGNER --release ${VERSION}-osx-unsigned --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml + ./bin/gsign -p $signProg --signer $SIGNER --release ${VERSION}-osx-unsigned --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml mv build/out/bitcoin-*-osx-unsigned.tar.gz inputs/bitcoin-osx-unsigned.tar.gz mv build/out/bitcoin-*.tar.gz build/out/bitcoin-*.dmg ../bitcoin-binaries/${VERSION} fi popd - # Commit to gitian.sigs repo - echo "" - echo "Committing ${VERSION} Unsigned Sigs" - echo "" - pushd gitian.sigs - git add ${VERSION}-linux/${SIGNER} - git add ${VERSION}-win-unsigned/${SIGNER} - git add ${VERSION}-osx-unsigned/${SIGNER} - git commit -a -m "Add ${VERSION} unsigned sigs for ${SIGNER}" - popd + if [[ $commitFiles = true ]] + then + # Commit to gitian.sigs repo + echo "" + echo "Committing ${VERSION} Unsigned Sigs" + echo "" + pushd gitian.sigs + git add ${VERSION}-linux/${SIGNER} + git add ${VERSION}-win-unsigned/${SIGNER} + git add ${VERSION}-osx-unsigned/${SIGNER} + git commit -a -m "Add ${VERSION} unsigned sigs for ${SIGNER}" + popd + fi fi # Verify the build @@ -341,7 +357,7 @@ then echo "Signing ${VERSION} Windows" echo "" ./bin/gbuild -i --commit signature=${COMMIT} ../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml - ./bin/gsign --signer $SIGNER --release ${VERSION}-win-signed --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml + ./bin/gsign -p $signProg --signer $SIGNER --release ${VERSION}-win-signed --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml mv build/out/bitcoin-*win64-setup.exe ../bitcoin-binaries/${VERSION} mv build/out/bitcoin-*win32-setup.exe ../bitcoin-binaries/${VERSION} fi @@ -352,18 +368,21 @@ then echo "Signing ${VERSION} Mac OSX" echo "" ./bin/gbuild -i --commit signature=${COMMIT} ../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml - ./bin/gsign --signer $SIGNER --release ${VERSION}-osx-signed --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml + ./bin/gsign -p $signProg --signer $SIGNER --release ${VERSION}-osx-signed --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml mv build/out/bitcoin-osx-signed.dmg ../bitcoin-binaries/${VERSION}/bitcoin-${VERSION}-osx.dmg fi popd - # Commit Sigs - pushd gitian.sigs - echo "" - echo "Committing ${VERSION} Signed Sigs" - echo "" - git add ${VERSION}-win-signed/${SIGNER} - git add ${VERSION}-osx-signed/${SIGNER} - git commit -a -m "Add ${VERSION} signed binary sigs for ${SIGNER}" - popd + if [[ $commitFiles = true ]] + then + # Commit Sigs + pushd gitian.sigs + echo "" + echo "Committing ${VERSION} Signed Sigs" + echo "" + git add ${VERSION}-win-signed/${SIGNER} + git add ${VERSION}-osx-signed/${SIGNER} + git commit -a -m "Add ${VERSION} signed binary sigs for ${SIGNER}" + popd + fi fi From 203f2121be0a84e85f7dff9cca9a30387005954f Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 27 Aug 2016 15:28:20 +0200 Subject: [PATCH 0793/1802] Reduce default number of blocks to check at startup --- src/main.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.h b/src/main.h index e9106fccf7927..b22c642404321 100644 --- a/src/main.h +++ b/src/main.h @@ -191,7 +191,7 @@ extern uint64_t nPruneTarget; /** Block files containing a block-height within MIN_BLOCKS_TO_KEEP of chainActive.Tip() will not be pruned. */ static const unsigned int MIN_BLOCKS_TO_KEEP = 288; -static const signed int DEFAULT_CHECKBLOCKS = MIN_BLOCKS_TO_KEEP; +static const signed int DEFAULT_CHECKBLOCKS = 6; static const unsigned int DEFAULT_CHECKLEVEL = 3; // Require that user allocate at least 550MB for block & undo files (blk???.dat and rev???.dat) From ae6e754928b85642b7024995f1771776c064a341 Mon Sep 17 00:00:00 2001 From: nomnombtc Date: Sun, 28 Aug 2016 02:46:36 +0200 Subject: [PATCH 0794/1802] change help string --enable-man to --disable-man --- configure.ac | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 4eadd58e79c97..7ca254aaabead 100644 --- a/configure.ac +++ b/configure.ac @@ -167,10 +167,9 @@ AC_ARG_ENABLE([zmq], AC_ARG_WITH([protoc-bindir],[AS_HELP_STRING([--with-protoc-bindir=BIN_DIR],[specify protoc bin path])], [protoc_bin_path=$withval], []) -# Enable manpages AC_ARG_ENABLE(man, - [AS_HELP_STRING([--enable-man], - [install man pages [default=yes]])],, + [AS_HELP_STRING([--disable-man], + [do not install man pages (default is to install)])],, enable_man=yes) AM_CONDITIONAL(ENABLE_MAN, test "$enable_man" != no) From 3fe0b68fb423da2a49dee31983e865fb22a24248 Mon Sep 17 00:00:00 2001 From: Andrew Chow Date: Sun, 28 Aug 2016 09:41:50 -0400 Subject: [PATCH 0795/1802] Set defaults to gitian defaults Set the default -j and -m to 2 and 2000 respectively, matching gitian's default values. --- contrib/gitian-build.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contrib/gitian-build.sh b/contrib/gitian-build.sh index e45a0d591f649..ee47d138f3798 100755 --- a/contrib/gitian-build.sh +++ b/contrib/gitian-build.sh @@ -14,8 +14,8 @@ SIGNER= VERSION= commit=false url=https://github.com/bitcoin/bitcoin -proc=4 -mem=4000 +proc=2 +mem=2000 lxc=true osslTarUrl=http://downloads.sourceforge.net/project/osslsigncode/osslsigncode/osslsigncode-1.7.1.tar.gz osslPatchUrl=https://bitcoincore.org/cfields/osslsigncode-Backports-to-1.7.1.patch @@ -41,7 +41,7 @@ Options: -s|--sign Make signed binaries for Windows and Mac OSX -B|--buildsign Build both signed and unsigned binaries -o|--os Specify which Operating Systems the build is for. Default is lwx. l for linux, w for windows, x for osx --j Number of processes to use. Default 4 +-j Number of processes to use. Default 2 -m Memory to allocate in MiB. Default 2000 --kvm Use KVM instead of LXC --setup Setup the gitian building environment. Uses KVM. If you want to use lxc, use the --lxc option. Only works on Debian-based systems (Ubuntu, Debian) From 883175f5d361720c75c89efcbc9d199cd6d3b2ab Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 26 Aug 2016 16:26:02 +0200 Subject: [PATCH 0796/1802] build: Updates for OpenBSD - LevelDB platform was not guessed correctly (it ended up defining `-DOS_OPENBSD59` instead of `-DOS_OPENBSD`) - On OpenBSD there is no convenience link from `python3.5` to `python3`: add detection for other python interpreter names. - If it has to guess the LevelDB OS, print a autoconf warning so that the user can check. --- configure.ac | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index d332f4face3ee..add8d217817ca 100644 --- a/configure.ac +++ b/configure.ac @@ -66,7 +66,8 @@ AC_PATH_TOOL(RANLIB, ranlib) AC_PATH_TOOL(STRIP, strip) AC_PATH_TOOL(GCOV, gcov) AC_PATH_PROG(LCOV, lcov) -AC_PATH_PROGS([PYTHON], [python3 python2.7 python2 python]) +dnl Python 3.x is supported from 3.4 on (see https://github.com/bitcoin/bitcoin/issues/7893) +AC_PATH_PROGS([PYTHON], [python3.6 python3.5 python3.4 python3 python2.7 python2 python]) AC_PATH_PROG(GENHTML, genhtml) AC_PATH_PROG([GIT], [git]) AC_PATH_PROG(CCACHE,ccache) @@ -355,8 +356,15 @@ case $host in TARGET_OS=linux LEVELDB_TARGET_FLAGS="-DOS_LINUX" ;; + *freebsd*) + LEVELDB_TARGET_FLAGS="-DOS_FREEBSD" + ;; + *openbsd*) + LEVELDB_TARGET_FLAGS="-DOS_OPENBSD" + ;; *) OTHER_OS=`echo ${host_os} | awk '{print toupper($0)}'` + AC_MSG_WARN([Guessing LevelDB OS as OS_${OTHER_OS}, please check whether this is correct, if not add an entry to configure.ac.]) LEVELDB_TARGET_FLAGS="-DOS_${OTHER_OS}" ;; esac From 6275123ce960172aeecfe087c8c0e303a216736a Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 26 Aug 2016 16:26:09 +0200 Subject: [PATCH 0797/1802] doc: Update build-openbsd for 0.13.0+ and OpenBSD 5.9 - Python 3 now supported. - Bump boost version to 1.61 - one boost patch no longer needed. - All checked with OpenBSD 5.9, except for the clang part, I left this as-is for someone adventurous. - Mention overriding resource limits, OpenBSD's default ulimit does not suffice for building Bitcoin Core with gcc 4.9.3. --- doc/build-openbsd.md | 46 ++++++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/doc/build-openbsd.md b/doc/build-openbsd.md index d923301467a7f..55283d6dcea93 100644 --- a/doc/build-openbsd.md +++ b/doc/build-openbsd.md @@ -1,6 +1,6 @@ OpenBSD build guide ====================== -(updated for OpenBSD 5.7) +(updated for OpenBSD 5.9) This guide describes how to build bitcoind and command-line utilities on OpenBSD. @@ -15,11 +15,10 @@ Run the following as root to install the base dependencies for building: pkg_add gmake libtool libevent pkg_add autoconf # (select highest version, e.g. 2.69) pkg_add automake # (select highest version, e.g. 1.15) -pkg_add python # (select version 2.7.x, not 3.x) -ln -sf /usr/local/bin/python2.7 /usr/local/bin/python2 +pkg_add python # (select highest version, e.g. 3.5) ``` -The default C++ compiler that comes with OpenBSD 5.7 is g++ 4.2. This version is old (from 2007), and is not able to compile the current version of Bitcoin Core. It is possible to patch it up to compile, but with the planned transition to C++11 this is a losing battle. So here we will be installing a newer compiler. +The default C++ compiler that comes with OpenBSD 5.9 is g++ 4.2. This version is old (from 2007), and is not able to compile the current version of Bitcoin Core, primarily as it has no C++11 support, but even before there were issues. So here we will be installing a newer compiler. GCC ------- @@ -27,7 +26,7 @@ GCC You can install a newer version of gcc with: ```bash -pkg_add g++ # (select newest 4.x version, e.g. 4.9.2) +pkg_add g++ # (select newest 4.x version, e.g. 4.9.3) ``` This compiler will not overwrite the system compiler, it will be installed as `egcc` and `eg++` in `/usr/local/bin`. @@ -49,18 +48,15 @@ BOOST_PREFIX="${BITCOIN_ROOT}/boost" mkdir -p $BOOST_PREFIX # Fetch the source and verify that it is not tampered with -wget http://heanet.dl.sourceforge.net/project/boost/boost/1.59.0/boost_1_59_0.tar.bz2 -echo '727a932322d94287b62abb1bd2d41723eec4356a7728909e38adb65ca25241ca boost_1_59_0.tar.bz2' | sha256 -c -# MUST output: (SHA256) boost_1_59_0.tar.bz2: OK -tar -xjf boost_1_59_0.tar.bz2 +curl -o boost_1_61_0.tar.bz2 http://heanet.dl.sourceforge.net/project/boost/boost/1.61.0/boost_1_61_0.tar.bz2 +echo 'a547bd06c2fd9a71ba1d169d9cf0339da7ebf4753849a8f7d6fdb8feee99b640 boost_1_61_0.tar.bz2' | sha256 -c +# MUST output: (SHA256) boost_1_61_0.tar.bz2: OK +tar -xjf boost_1_61_0.tar.bz2 -# Boost 1.59 needs two small patches for OpenBSD -cd boost_1_59_0 +# Boost 1.61 needs one small patch for OpenBSD +cd boost_1_61_0 # Also here: https://gist.githubusercontent.com/laanwj/bf359281dc319b8ff2e1/raw/92250de8404b97bb99d72ab898f4a8cb35ae1ea3/patch-boost_test_impl_execution_monitor_ipp.patch patch -p0 < /usr/ports/devel/boost/patches/patch-boost_test_impl_execution_monitor_ipp -# https://github.com/boostorg/filesystem/commit/90517e459681790a091566dce27ca3acabf9a70c -sed 's/__OPEN_BSD__/__OpenBSD__/g' < libs/filesystem/src/path.cpp > libs/filesystem/src/path.cpp.tmp -mv libs/filesystem/src/path.cpp.tmp libs/filesystem/src/path.cpp # Build w/ minimum configuration necessary for bitcoin echo 'using gcc : : eg++ : "-fvisibility=hidden -fPIC" "" "ar" "strip" "ranlib" "" : ;' > user-config.jam @@ -84,7 +80,7 @@ BDB_PREFIX="${BITCOIN_ROOT}/db4" mkdir -p $BDB_PREFIX # Fetch the source and verify that it is not tampered with -wget 'http://download.oracle.com/berkeley-db/db-4.8.30.NC.tar.gz' +curl -o db-4.8.30.NC.tar.gz 'http://download.oracle.com/berkeley-db/db-4.8.30.NC.tar.gz' echo '12edc0df75bf9abd7f82f821795bcee50f42cb2e5f76a6a281b85732798364ef db-4.8.30.NC.tar.gz' | sha256 -c # MUST output: (SHA256) db-4.8.30.NC.tar.gz: OK tar -xzf db-4.8.30.NC.tar.gz @@ -93,9 +89,25 @@ tar -xzf db-4.8.30.NC.tar.gz cd db-4.8.30.NC/build_unix/ # Note: Do a static build so that it can be embedded into the executable, instead of having to find a .so at runtime ../dist/configure --enable-cxx --disable-shared --with-pic --prefix=$BDB_PREFIX CC=egcc CXX=eg++ CPP=ecpp -make install +make install # do NOT use -jX, this is broken ``` +### Resource limits + +The standard ulimit restrictions in OpenBSD are very strict: + + data(kbytes) 1572864 + +This is, unfortunately, no longer enough to compile some `.cpp` files in the project, +at least with gcc 4.9.3 (see issue https://github.com/bitcoin/bitcoin/issues/6658). +If your user is in the `staff` group the limit can be raised with: + + ulimit -d 3000000 + +The change will only affect the current shell and processes spawned by it. To +make the change system-wide, change `datasize-cur` and `datasize-max` in +`/etc/login.conf`, and reboot. + ### Building Bitcoin Core **Important**: use `gmake`, not `make`. The non-GNU `make` will exit with a horrible error. @@ -123,7 +135,7 @@ To configure without wallet: Build and run the tests: ```bash -gmake +gmake # can use -jX here for parallelism gmake check ``` From fa994a7b8e8f2dbcbfb446e2fe2845866d4cd2cc Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 28 Aug 2016 17:01:52 +0200 Subject: [PATCH 0798/1802] contrib: Don't use shell=True --- contrib/devtools/fix-copyright-headers.py | 77 ++++++++++++++--------- 1 file changed, 49 insertions(+), 28 deletions(-) diff --git a/contrib/devtools/fix-copyright-headers.py b/contrib/devtools/fix-copyright-headers.py index 31a81ae4fadb5..54836bd83f592 100755 --- a/contrib/devtools/fix-copyright-headers.py +++ b/contrib/devtools/fix-copyright-headers.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python -''' +#!/usr/bin/env python3 +""" Run this script to update all the copyright headers of files that were changed this year. @@ -10,37 +10,58 @@ it will change it to // Copyright (c) 2009-2015 The Bitcoin Core developers -''' -import os +""" +import subprocess import time import re -year = time.gmtime()[0] -CMD_GIT_DATE = 'git log --format=%%ad --date=short -1 %s | cut -d"-" -f 1' -CMD_REGEX= "perl -pi -e 's/(20\d\d)(?:-20\d\d)? The Bitcoin/$1-%s The Bitcoin/' %s" -REGEX_CURRENT= re.compile("%s The Bitcoin" % year) -CMD_LIST_FILES= "find %s | grep %s" +CMD_GIT_LIST_FILES = ['git', 'ls-files'] +CMD_GIT_DATE = ['git', 'log', '--format=%ad', '--date=short', '-1'] +CMD_PERL_REGEX = ['perl', '-pi', '-e'] +REGEX_TEMPLATE = 's/(20\\d\\d)(?:-20\\d\\d)? The Bitcoin/$1-%s The Bitcoin/' -FOLDERS = ["./qa", "./src"] +FOLDERS = ["qa/", "src/"] EXTENSIONS = [".cpp",".h", ".py"] + def get_git_date(file_path): - r = os.popen(CMD_GIT_DATE % file_path) - for l in r: - # Result is one line, so just return - return l.replace("\n","") - return "" - -n=1 -for folder in FOLDERS: - for extension in EXTENSIONS: - for file_path in os.popen(CMD_LIST_FILES % (folder, extension)): - file_path = os.getcwd() + file_path[1:-1] - if file_path.endswith(extension): - git_date = get_git_date(file_path) - if str(year) == git_date: - # Only update if current year is not found - if REGEX_CURRENT.search(open(file_path, "r").read()) is None: - print n,"Last git edit", git_date, "-", file_path - os.popen(CMD_REGEX % (year,file_path)) + d = subprocess.run(CMD_GIT_DATE + [file_path], + stdout=subprocess.PIPE, + check=True, + universal_newlines=True).stdout + # yyyy-mm-dd + return d.split('-')[0] + + +def skip_file(file_path): + for ext in EXTENSIONS: + if file_path.endswith(ext): + return False + else: + return True + +if __name__ == "__main__": + year = str(time.gmtime()[0]) + regex_current = re.compile("%s The Bitcoin" % year) + n = 1 + for folder in FOLDERS: + for file_path in subprocess.run( + CMD_GIT_LIST_FILES + [folder], + stdout=subprocess.PIPE, + check=True, + universal_newlines=True + ).stdout.split("\n"): + if skip_file(file_path): + # print(file_path, "(skip)") + continue + git_date = get_git_date(file_path) + if not year == git_date: + # print(file_path, year, "(skip)") + continue + if regex_current.search(open(file_path, "r").read()) is not None: + # already up to date + # print(file_path, year, "(skip)") + continue + print(n, file_path, "(update to %s)" % year) + subprocess.run(CMD_PERL_REGEX + [REGEX_TEMPLATE % year, file_path], check=True) n = n + 1 From b729fcdb84f819e72d6d2bc264c76328d171abd8 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Sat, 27 Aug 2016 20:17:25 +0000 Subject: [PATCH 0799/1802] Include instructions to extract Mac OS X SDK on Linux using 7zip and SleuthKit --- contrib/macdeploy/extract-osx-sdk.sh | 29 ++++++++++++++++++++++++++++ doc/README_osx.md | 17 +++++++++++++++- 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100755 contrib/macdeploy/extract-osx-sdk.sh diff --git a/contrib/macdeploy/extract-osx-sdk.sh b/contrib/macdeploy/extract-osx-sdk.sh new file mode 100755 index 0000000000000..46d2d825d4523 --- /dev/null +++ b/contrib/macdeploy/extract-osx-sdk.sh @@ -0,0 +1,29 @@ +#!/bin/bash +set -e + +INPUTFILE="Xcode_7.3.1.dmg" +HFSFILENAME="5.hfs" +SDKDIR="Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk" + +7z x "${INPUTFILE}" "${HFSFILENAME}" +SDKNAME="$(basename "${SDKDIR}")" +SDKDIRINODE=$(ifind -n "${SDKDIR}" "${HFSFILENAME}") +fls "${HFSFILENAME}" -rpF ${SDKDIRINODE} | + while read type inode filename; do + inode="${inode::-1}" + if [ "${filename:0:14}" = "usr/share/man/" ]; then + continue + fi + filename="${SDKNAME}/$filename" + echo "Extracting $filename ..." + mkdir -p "$(dirname "$filename")" + if [ "$type" = "l/l" ]; then + ln -s "$(icat "${HFSFILENAME}" $inode)" "$filename" + else + icat "${HFSFILENAME}" $inode >"$filename" + fi +done +echo "Building ${SDKNAME}.tar.gz ..." +MTIME="$(istat "${HFSFILENAME}" "${SDKDIRINODE}" | perl -nle 'm/Content Modified:\s+(.*?)\s\(/ && print $1')" +find "${SDKNAME}" | sort | tar --no-recursion --mtime="${MTIME}" --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > "${SDKNAME}.tar.gz" +echo 'All done!' diff --git a/doc/README_osx.md b/doc/README_osx.md index aed3cd97e1ecd..e934b4fc54a04 100644 --- a/doc/README_osx.md +++ b/doc/README_osx.md @@ -36,11 +36,26 @@ Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.1 ``` Unfortunately, the usual linux tools (7zip, hpmount, loopback mount) are incapable of opening this file. -To create a tarball suitable for Gitian input, mount the dmg in OS X, then create it with: +To create a tarball suitable for Gitian input, there are two options: + +Using Mac OS X, you can mount the dmg, and then create it with: ``` + $ hdiutil attach Xcode_7.3.1.dmg $ tar -C /Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ -czf MacOSX10.11.sdk.tar.gz MacOSX10.11.sdk ``` +Alternatively, you can use 7zip and SleuthKit to extract the files one by one. +The script contrib/macdeploy/extract-osx-sdk.sh automates this. First ensure +the dmg file is in the current directory, and then run the script. You may wish +to delete the intermediate 5.hfs file and MacOSX10.11.sdk (the directory) when +you've confirmed the extraction succeeded. + +```bash +apt-get install p7zip-full sleuthkit +contrib/macdeploy/extract-osx-sdk.sh +rm -rf 5.hfs MacOSX10.11.sdk +``` + The Gitian descriptors build 2 sets of files: Linux tools, then Apple binaries which are created using these tools. The build process has been designed to avoid including the SDK's files in Gitian's outputs. All interim tarballs are From fae6bb85cf71056aa2541d9bc5cce26946a56945 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 29 Aug 2016 10:33:36 +0200 Subject: [PATCH 0800/1802] [doc] build: Mention curl --- doc/build-unix.md | 5 +++-- doc/build-windows.md | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/doc/build-unix.md b/doc/build-unix.md index bd89978cc2a74..62e3e793e97f3 100644 --- a/doc/build-unix.md +++ b/doc/build-unix.md @@ -293,9 +293,10 @@ These steps can be performed on, for example, an Ubuntu VM. The depends system will also work on other Linux distributions, however the commands for installing the toolchain will be different. -First install the toolchain: +Make sure you install the build requirements mentioned above. +Then, install the toolchain and curl: - sudo apt-get install g++-arm-linux-gnueabihf + sudo apt-get install g++-arm-linux-gnueabihf curl To build executables for ARM: diff --git a/doc/build-windows.md b/doc/build-windows.md index 2b9233d1e1406..129774491b2ff 100644 --- a/doc/build-windows.md +++ b/doc/build-windows.md @@ -16,9 +16,11 @@ These steps can be performed on, for example, an Ubuntu VM. The depends system will also work on other Linux distributions, however the commands for installing the toolchain will be different. -First install the toolchains: +Make sure you install the build requirements mentioned in +[build-unix.md](/doc/build-unix.md). +Then, install the toolchains and curl: - sudo apt-get install g++-mingw-w64-i686 mingw-w64-i686-dev g++-mingw-w64-x86-64 mingw-w64-x86-64-dev + sudo apt-get install g++-mingw-w64-i686 mingw-w64-i686-dev g++-mingw-w64-x86-64 mingw-w64-x86-64-dev curl To build executables for Windows 32-bit: From 14675610245e951f2b922a0eaad6eb7d011ae87e Mon Sep 17 00:00:00 2001 From: isle2983 Date: Mon, 29 Aug 2016 21:01:38 -0600 Subject: [PATCH 0801/1802] [doc] - clarify statement about parallel jobs in rpc-tests.py --- qa/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qa/README.md b/qa/README.md index 723660c6c857e..225207cc1cebf 100644 --- a/qa/README.md +++ b/qa/README.md @@ -41,8 +41,8 @@ Run all possible tests with qa/pull-tester/rpc-tests.py -extended -By default, tests will be run in parallel if you want to specify how many -tests should be run in parallel, append `-parallel=n` (default n=4). +By default, tests will be run in parallel. To specify how many jobs to run, +append `-parallel=n` (default n=4). If you want to create a basic coverage report for the rpc test suite, append `--coverage`. From 323a5fe06af43d3922a435e696d6c52acc6fade1 Mon Sep 17 00:00:00 2001 From: Alexey Vesnin Date: Tue, 30 Aug 2016 09:00:55 +0300 Subject: [PATCH 0802/1802] Berkeley DB v6 compatibility fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes building error looking like this: CXX wallet/libbitcoin_wallet_a-db.o wallet/db.cpp: In member function ‘void CDBEnv::EnvShutdown()’: wallet/db.cpp:46:16: error: call of overloaded ‘DbEnv(int)’ is ambiguous DbEnv(0).remove(strPath.c_str(), 0); ^ wallet/db.cpp:46:16: note: candidates are: In file included from wallet/db.h:21:0, from wallet/db.cpp:6: /usr/include/db_cxx.h:916:2: note: DbEnv::DbEnv(const DbEnv&) DbEnv(const DbEnv &); ^ /usr/include/db_cxx.h:518:2: note: DbEnv::DbEnv(DB_ENV) DbEnv(DB_ENV *dbenv); ^ /usr/include/db_cxx.h:516:2: note: DbEnv::DbEnv(u_int32_t) DbEnv(u_int32_t flags); ^ Makefile:5780: recipe for target 'wallet/libbitcoin_wallet_a-db.o' failed make[2]: ** [wallet/libbitcoin_wallet_a-db.o] Error 1 --- src/wallet/db.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index 652bbebded844..ab7a4cf2e5f13 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -43,7 +43,7 @@ void CDBEnv::EnvShutdown() if (ret != 0) LogPrintf("CDBEnv::EnvShutdown: Error %d shutting down database environment: %s\n", ret, DbEnv::strerror(ret)); if (!fMockDb) - DbEnv(0).remove(strPath.c_str(), 0); + DbEnv((u_int32_t)0).remove(strPath.c_str(), 0); } void CDBEnv::Reset() From 482f852da65457eb2fbea6b259e7568133fb81c4 Mon Sep 17 00:00:00 2001 From: Johnson Lau Date: Wed, 31 Aug 2016 19:38:23 +0800 Subject: [PATCH 0803/1802] Implement NULLDUMMY softfork --- qa/pull-tester/rpc-tests.py | 1 + qa/rpc-tests/nulldummy.py | 148 ++++++++++++++++++++++++++++++++++++ src/main.cpp | 1 + 3 files changed, 150 insertions(+) create mode 100755 qa/rpc-tests/nulldummy.py diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index 92cce6aadde0b..cf951fe175a2b 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -143,6 +143,7 @@ 'importprunedfunds.py', 'signmessages.py', 'p2p-compactblocks.py', + 'nulldummy.py', ] if ENABLE_ZMQ: testScripts.append('zmq_test.py') diff --git a/qa/rpc-tests/nulldummy.py b/qa/rpc-tests/nulldummy.py new file mode 100755 index 0000000000000..eaed7a8c78970 --- /dev/null +++ b/qa/rpc-tests/nulldummy.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python3 +# Copyright (c) 2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +from test_framework.test_framework import ComparisonTestFramework +from test_framework.util import * +from test_framework.mininode import CTransaction, NetworkThread +from test_framework.blocktools import create_coinbase, create_block, add_witness_commitment +from test_framework.comptool import TestManager +from test_framework.script import CScript +from io import BytesIO +import time + +NULLDUMMY_ERROR = "64: non-mandatory-script-verify-flag (Dummy CHECKMULTISIG argument must be zero)" + +def trueDummy(tx): + scriptSig = CScript(tx.vin[0].scriptSig) + newscript = [] + for i in scriptSig: + if (len(newscript) == 0): + assert(len(i) == 0) + newscript.append(b'\x51') + else: + newscript.append(i) + tx.vin[0].scriptSig = CScript(newscript) + tx.rehash() + +''' +This test is meant to exercise NULLDUMMY softfork. +Connect to a single node. +Generate 2 blocks (save the coinbases for later). +Generate 427 more blocks. +[Policy/Consensus] Check that NULLDUMMY compliant transactions are accepted in the 430th block. +[Policy] Check that non-NULLDUMMY transactions are rejected before activation. +[Consensus] Check that the new NULLDUMMY rules are not enforced on the 431st block. +[Policy/Consensus] Check that the new NULLDUMMY rules are enforced on the 432nd block. +''' + +class NULLDUMMYTest(ComparisonTestFramework): + + def __init__(self): + super().__init__() + self.num_nodes = 1 + + def setup_network(self): + # Must set the blockversion for this test + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, + extra_args=[['-debug', '-whitelist=127.0.0.1', '-walletprematurewitness']]) + + def run_test(self): + self.address = self.nodes[0].getnewaddress() + self.ms_address = self.nodes[0].addmultisigaddress(1,[self.address]) + self.wit_address = self.nodes[0].addwitnessaddress(self.address) + self.wit_ms_address = self.nodes[0].addwitnessaddress(self.ms_address) + + test = TestManager(self, self.options.tmpdir) + test.add_all_connections(self.nodes) + NetworkThread().start() # Start up network handling in another thread + self.coinbase_blocks = self.nodes[0].generate(2) # Block 2 + coinbase_txid = [] + for i in self.coinbase_blocks: + coinbase_txid.append(self.nodes[0].getblock(i)['tx'][0]) + self.nodes[0].generate(427) # Block 429 + self.lastblockhash = self.nodes[0].getbestblockhash() + self.tip = int("0x" + self.lastblockhash, 0) + self.lastblockheight = 429 + self.lastblocktime = int(time.time()) + 429 + + print ("Test 1: NULLDUMMY compliant base transactions should be accepted to mempool and mined before activation [430]") + test1txs = [self.create_transaction(self.nodes[0], coinbase_txid[0], self.ms_address, 49)] + txid1 = self.tx_submit(self.nodes[0], test1txs[0]) + test1txs.append(self.create_transaction(self.nodes[0], txid1, self.ms_address, 48)) + txid2 = self.tx_submit(self.nodes[0], test1txs[1]) + test1txs.append(self.create_transaction(self.nodes[0], coinbase_txid[1], self.wit_ms_address, 49)) + txid3 = self.tx_submit(self.nodes[0], test1txs[2]) + self.block_submit(self.nodes[0], test1txs, False, True) + + print ("Test 2: Non-NULLDUMMY base multisig transaction should not be accepted to mempool before activation") + test2tx = self.create_transaction(self.nodes[0], txid2, self.ms_address, 48) + trueDummy(test2tx) + txid4 = self.tx_submit(self.nodes[0], test2tx, NULLDUMMY_ERROR) + + print ("Test 3: Non-NULLDUMMY base transactions should be accepted in a block before activation [431]") + self.block_submit(self.nodes[0], [test2tx], False, True) + + print ("Test 4: Non-NULLDUMMY base multisig transaction is invalid after activation") + test4tx = self.create_transaction(self.nodes[0], txid4, self.address, 47) + test6txs=[CTransaction(test4tx)] + trueDummy(test4tx) + self.tx_submit(self.nodes[0], test4tx, NULLDUMMY_ERROR) + self.block_submit(self.nodes[0], [test4tx]) + + print ("Test 5: Non-NULLDUMMY P2WSH multisig transaction invalid after activation") + test5tx = self.create_transaction(self.nodes[0], txid3, self.wit_address, 48) + test6txs.append(CTransaction(test5tx)) + test5tx.wit.vtxinwit[0].scriptWitness.stack[0] = b'\x01' + self.tx_submit(self.nodes[0], test5tx, NULLDUMMY_ERROR) + self.block_submit(self.nodes[0], [test5tx], True) + + print ("Test 6: NULLDUMMY compliant base/witness transactions should be accepted to mempool and in block after activation [432]") + for i in test6txs: + self.tx_submit(self.nodes[0], i) + self.block_submit(self.nodes[0], test6txs, True, True) + + + def create_transaction(self, node, txid, to_address, amount): + inputs = [{ "txid" : txid, "vout" : 0}] + outputs = { to_address : amount } + rawtx = node.createrawtransaction(inputs, outputs) + signresult = node.signrawtransaction(rawtx) + tx = CTransaction() + f = BytesIO(hex_str_to_bytes(signresult['hex'])) + tx.deserialize(f) + return tx + + + def tx_submit(self, node, tx, msg = ""): + tx.rehash() + try: + node.sendrawtransaction(bytes_to_hex_str(tx.serialize_with_witness()), True) + except JSONRPCException as exp: + assert_equal(exp.error["message"], msg) + return tx.hash + + + def block_submit(self, node, txs, witness = False, accept = False): + block = create_block(self.tip, create_coinbase(self.lastblockheight + 1), self.lastblocktime + 1) + block.nVersion = 4 + for tx in txs: + tx.rehash() + block.vtx.append(tx) + block.hashMerkleRoot = block.calc_merkle_root() + witness and add_witness_commitment(block) + block.rehash() + block.solve() + node.submitblock(bytes_to_hex_str(block.serialize(True))) + if (accept): + assert_equal(node.getbestblockhash(), block.hash) + self.tip = block.sha256 + self.lastblockhash = block.hash + self.lastblocktime += 1 + self.lastblockheight += 1 + else: + assert_equal(node.getbestblockhash(), self.lastblockhash) + +if __name__ == '__main__': + NULLDUMMYTest().main() \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 5160e60750d08..7eb7194a3f096 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2387,6 +2387,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin // Start enforcing WITNESS rules using versionbits logic. if (IsWitnessEnabled(pindex->pprev, chainparams.GetConsensus())) { flags |= SCRIPT_VERIFY_WITNESS; + flags |= SCRIPT_VERIFY_NULLDUMMY; } int64_t nTime2 = GetTimeMicros(); nTimeForks += nTime2 - nTime1; From b175cb755bd2b62a19dbf27daf07ae5354f9a079 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Sat, 11 Jun 2016 16:35:19 +0200 Subject: [PATCH 0804/1802] Do not shadow variables. --- src/wallet/db.cpp | 6 +++--- src/wallet/rpcwallet.cpp | 12 ++++++------ src/wallet/test/wallet_tests.cpp | 6 +++--- src/wallet/walletdb.cpp | 6 +++--- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index ab7a4cf2e5f13..a809c9ad64015 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -387,11 +387,11 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip) while (fSuccess) { CDataStream ssKey(SER_DISK, CLIENT_VERSION); CDataStream ssValue(SER_DISK, CLIENT_VERSION); - int ret = db.ReadAtCursor(pcursor, ssKey, ssValue); - if (ret == DB_NOTFOUND) { + int ret1 = db.ReadAtCursor(pcursor, ssKey, ssValue); + if (ret1 == DB_NOTFOUND) { pcursor->close(); break; - } else if (ret != 0) { + } else if (ret1 != 0) { pcursor->close(); fSuccess = false; break; diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 9629ec1db6f59..0ba6706baf830 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -1176,10 +1176,10 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts) if (fByAccounts) { - tallyitem& item = mapAccountTally[strAccount]; - item.nAmount += nAmount; - item.nConf = min(item.nConf, nConf); - item.fIsWatchonly = fIsWatchonly; + tallyitem& _item = mapAccountTally[strAccount]; + _item.nAmount += nAmount; + _item.nConf = min(_item.nConf, nConf); + _item.fIsWatchonly = fIsWatchonly; } else { @@ -1195,9 +1195,9 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts) UniValue transactions(UniValue::VARR); if (it != mapTally.end()) { - BOOST_FOREACH(const uint256& item, (*it).second.txids) + BOOST_FOREACH(const uint256& _item, (*it).second.txids) { - transactions.push_back(item.GetHex()); + transactions.push_back(_item.GetHex()); } } obj.push_back(Pair("txids", transactions)); diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index c6c5058984c00..acf980c784561 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -217,7 +217,7 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) // run the 'mtgox' test (see http://blockexplorer.com/tx/29a3efd3ef04f9153d47a990bd7b048a4b2d213daaa5fb8ed670fb85f13bdbcf) // they tried to consolidate 10 50k coins into one 500k coin, and ended up with 50k in change empty_wallet(); - for (int i = 0; i < 20; i++) + for (int j = 0; j < 20; j++) add_coin(50000 * COIN); BOOST_CHECK( wallet.SelectCoinsMinConf(500000 * COIN, 1, 1, vCoins, setCoinsRet, nValueRet)); @@ -296,7 +296,7 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) BOOST_CHECK(!equal_sets(setCoinsRet, setCoinsRet2)); int fails = 0; - for (int i = 0; i < RANDOM_REPEATS; i++) + for (int j = 0; j < RANDOM_REPEATS; j++) { // selecting 1 from 100 identical coins depends on the shuffle; this test will fail 1% of the time // run the test RANDOM_REPEATS times and only complain if all of them fail @@ -317,7 +317,7 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) add_coin(25 * CENT); fails = 0; - for (int i = 0; i < RANDOM_REPEATS; i++) + for (int j = 0; j < RANDOM_REPEATS; j++) { // selecting 1 from 100 identical coins depends on the shuffle; this test will fail 1% of the time // run the test RANDOM_REPEATS times and only complain if all of them fail diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 9de0671ea2164..e9b7addef8752 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -887,8 +887,8 @@ void ThreadFlushWalletDB(const string& strFile) if (nRefCount == 0) { boost::this_thread::interruption_point(); - map::iterator mi = bitdb.mapFileUseCount.find(strFile); - if (mi != bitdb.mapFileUseCount.end()) + map::iterator _mi = bitdb.mapFileUseCount.find(strFile); + if (_mi != bitdb.mapFileUseCount.end()) { LogPrint("db", "Flushing %s\n", strFile); nLastFlushed = nWalletDBUpdated; @@ -898,7 +898,7 @@ void ThreadFlushWalletDB(const string& strFile) bitdb.CloseDb(strFile); bitdb.CheckpointLSN(strFile); - bitdb.mapFileUseCount.erase(mi++); + bitdb.mapFileUseCount.erase(_mi++); LogPrint("db", "Flushed %s %dms\n", strFile, GetTimeMillis() - nStart); } } From 3e7d2a24cf1a4820941dd09a4e18f2683bed2c0c Mon Sep 17 00:00:00 2001 From: Michael Ford Date: Thu, 1 Sep 2016 08:23:33 +0800 Subject: [PATCH 0805/1802] [depends] Remove Qt46 package --- depends/packages/qt46.mk | 66 ---------------------------------------- 1 file changed, 66 deletions(-) delete mode 100644 depends/packages/qt46.mk diff --git a/depends/packages/qt46.mk b/depends/packages/qt46.mk deleted file mode 100644 index 8fb30a5c4471c..0000000000000 --- a/depends/packages/qt46.mk +++ /dev/null @@ -1,66 +0,0 @@ -PACKAGE=qt46 -$(package)_version=4.6.4 -$(package)_download_path=http://download.qt-project.org/archive/qt/4.6/ -$(package)_file_name=qt-everywhere-opensource-src-$($(package)_version).tar.gz -$(package)_sha256_hash=9ad4d46c721b53a429ed5a2eecfd3c239a9ab566562f183f99d3125f1a234250 -$(package)_dependencies=openssl freetype dbus libX11 xproto libXext libICE libSM -$(package)_patches=stlfix.patch - -define $(package)_set_vars -$(package)_config_opts = -prefix $(host_prefix) -headerdir $(host_prefix)/include/qt4 -bindir $(build_prefix)/bin -$(package)_config_opts += -release -no-separate-debug-info -opensource -confirm-license -$(package)_config_opts += -stl -qt-zlib - -$(package)_config_opts += -nomake examples -nomake tests -nomake tools -nomake translations -nomake demos -nomake docs -$(package)_config_opts += -no-audio-backend -no-glib -no-nis -no-cups -no-iconv -no-gif -no-pch -$(package)_config_opts += -no-xkb -no-xrender -no-xrandr -no-xfixes -no-xcursor -no-xinerama -no-xsync -no-xinput -no-mitshm -no-xshape -$(package)_config_opts += -no-libtiff -no-fontconfig -openssl-linked -$(package)_config_opts += -no-sql-db2 -no-sql-ibase -no-sql-oci -no-sql-tds -no-sql-mysql -$(package)_config_opts += -no-sql-odbc -no-sql-psql -no-sql-sqlite -no-sql-sqlite2 -$(package)_config_opts += -no-xmlpatterns -no-multimedia -no-phonon -no-scripttools -no-declarative -$(package)_config_opts += -no-phonon-backend -no-webkit -no-javascript-jit -no-script -$(package)_config_opts += -no-svg -no-libjpeg -no-libtiff -no-libpng -no-libmng -no-qt3support -no-opengl - -$(package)_config_opts_x86_64_linux += -platform linux-g++-64 -$(package)_config_opts_i686_linux = -platform linux-g++-32 -$(package)_build_env = QT_RCC_TEST=1 -endef - -define $(package)_preprocess_cmds - sed -i.old "s|/include /usr/include||" config.tests/unix/freetype/freetype.pri && \ - sed -i.old "s|src_plugins.depends = src_gui src_sql src_svg|src_plugins.depends = src_gui src_sql|" src/src.pro && \ - sed -i.old "s|\.lower(|\.toLower(|g" src/network/ssl/qsslsocket_openssl.cpp && \ - sed -i.old "s|Key_BackSpace|Key_Backspace|" src/gui/itemviews/qabstractitemview.cpp && \ - sed -i.old "s|/usr/X11R6/lib64|$(host_prefix)/lib|" mkspecs/*/*.conf && \ - sed -i.old "s|/usr/X11R6/lib|$(host_prefix)/lib|" mkspecs/*/*.conf && \ - sed -i.old "s|/usr/X11R6/include|$(host_prefix)/include|" mkspecs/*/*.conf && \ - sed -i.old "s|QMAKE_LFLAGS_SHLIB\t+= -shared|QMAKE_LFLAGS_SHLIB\t+= -shared -Wl,--exclude-libs,ALL|" mkspecs/common/g++.conf && \ - sed -i.old "/SSLv2_client_method/d" src/network/ssl/qsslsocket_openssl.cpp src/network/ssl/qsslsocket_openssl_symbols.cpp && \ - sed -i.old "/SSLv2_server_method/d" src/network/ssl/qsslsocket_openssl.cpp src/network/ssl/qsslsocket_openssl_symbols.cpp && \ - patch -p1 < $($(package)_patch_dir)/stlfix.patch -endef - -define $(package)_config_cmds - export PKG_CONFIG_SYSROOT_DIR=/ && \ - export PKG_CONFIG_LIBDIR=$(host_prefix)/lib/pkgconfig && \ - export PKG_CONFIG_PATH=$(host_prefix)/share/pkgconfig && \ - export CPATH=$(host_prefix)/include && \ - OPENSSL_LIBS='-L$(host_prefix)/lib -lssl -lcrypto' ./configure $($(package)_config_opts) && \ - cd tools/linguist/lrelease; ../../../bin/qmake -o Makefile lrelease.pro -endef - -define $(package)_build_cmds - export CPATH=$(host_prefix)/include && \ - $(MAKE) -C src && \ - $(MAKE) -C tools/linguist/lrelease -endef - -define $(package)_stage_cmds - $(MAKE) -C src INSTALL_ROOT=$($(package)_staging_dir) install && \ - $(MAKE) -C tools/linguist/lrelease INSTALL_ROOT=$($(package)_staging_dir) install -endef - -define $(package)_postprocess_cmds - rm -rf mkspecs/ lib/cmake/ lib/*.prl lib/*.la && \ - find native/bin -type f -exec mv {} {}-qt4 \; -endef From f012a857f5e9b3bdd11a64dd0c16b4c805076594 Mon Sep 17 00:00:00 2001 From: djpnewton Date: Thu, 1 Sep 2016 11:52:47 +1200 Subject: [PATCH 0806/1802] rest.cpp: change HTTP_INTERNAL_SERVER_ERROR to HTTP_BAD_REQUEST --- doc/release-notes.md | 4 ++++ qa/rpc-tests/rest.py | 10 +++++----- src/rest.cpp | 14 +++++++------- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/doc/release-notes.md b/doc/release-notes.md index 0be192233d5ea..f2d8ca3a1517b 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -59,6 +59,10 @@ git merge commit are mentioned. ### RPC and REST +UTXO set query (`GET /rest/getutxos//-/-/.../-.`) responses +were changed to return status code HTTP_BAD_REQUEST (400) instead of HTTP_INTERNAL_SERVER_ERROR (500) when requests +contain invalid parameters. + ### Configuration and command-line options ### Block and transaction handling diff --git a/qa/rpc-tests/rest.py b/qa/rpc-tests/rest.py index c9c2eaf7f37b9..b769cd71f2050 100755 --- a/qa/rpc-tests/rest.py +++ b/qa/rpc-tests/rest.py @@ -179,14 +179,14 @@ def run_test(self): #do some invalid requests json_request = '{"checkmempool' response = http_post_call(url.hostname, url.port, '/rest/getutxos'+self.FORMAT_SEPARATOR+'json', json_request, True) - assert_equal(response.status, 500) #must be a 500 because we send a invalid json request + assert_equal(response.status, 400) #must be a 400 because we send a invalid json request json_request = '{"checkmempool' response = http_post_call(url.hostname, url.port, '/rest/getutxos'+self.FORMAT_SEPARATOR+'bin', json_request, True) - assert_equal(response.status, 500) #must be a 500 because we send a invalid bin request + assert_equal(response.status, 400) #must be a 400 because we send a invalid bin request response = http_post_call(url.hostname, url.port, '/rest/getutxos/checkmempool'+self.FORMAT_SEPARATOR+'bin', '', True) - assert_equal(response.status, 500) #must be a 500 because we send a invalid bin request + assert_equal(response.status, 400) #must be a 400 because we send a invalid bin request #test limits json_request = '/checkmempool/' @@ -194,14 +194,14 @@ def run_test(self): json_request += txid+'-'+str(n)+'/' json_request = json_request.rstrip("/") response = http_post_call(url.hostname, url.port, '/rest/getutxos'+json_request+self.FORMAT_SEPARATOR+'json', '', True) - assert_equal(response.status, 500) #must be a 500 because we exceeding the limits + assert_equal(response.status, 400) #must be a 400 because we exceeding the limits json_request = '/checkmempool/' for x in range(0, 15): json_request += txid+'-'+str(n)+'/' json_request = json_request.rstrip("/") response = http_post_call(url.hostname, url.port, '/rest/getutxos'+json_request+self.FORMAT_SEPARATOR+'json', '', True) - assert_equal(response.status, 200) #must be a 500 because we exceeding the limits + assert_equal(response.status, 200) #must be a 200 because we are within the limits self.nodes[0].generate(1) #generate block to not affect upcoming tests self.sync_all() diff --git a/src/rest.cpp b/src/rest.cpp index 2dff8d7daddfc..c81559212419f 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -420,7 +420,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart) // throw exception in case of a empty request std::string strRequestMutable = req->ReadBody(); if (strRequestMutable.length() == 0 && uriParts.size() == 0) - return RESTERR(req, HTTP_INTERNAL_SERVER_ERROR, "Error: empty request"); + return RESTERR(req, HTTP_BAD_REQUEST, "Error: empty request"); bool fInputParsed = false; bool fCheckMemPool = false; @@ -444,7 +444,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart) std::string strOutput = uriParts[i].substr(uriParts[i].find("-")+1); if (!ParseInt32(strOutput, &nOutput) || !IsHex(strTxid)) - return RESTERR(req, HTTP_INTERNAL_SERVER_ERROR, "Parse error"); + return RESTERR(req, HTTP_BAD_REQUEST, "Parse error"); txid.SetHex(strTxid); vOutPoints.push_back(COutPoint(txid, (uint32_t)nOutput)); @@ -453,7 +453,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart) if (vOutPoints.size() > 0) fInputParsed = true; else - return RESTERR(req, HTTP_INTERNAL_SERVER_ERROR, "Error: empty request"); + return RESTERR(req, HTTP_BAD_REQUEST, "Error: empty request"); } switch (rf) { @@ -469,7 +469,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart) if (strRequestMutable.size() > 0) { if (fInputParsed) //don't allow sending input over URI and HTTP RAW DATA - return RESTERR(req, HTTP_INTERNAL_SERVER_ERROR, "Combination of URI scheme inputs and raw post data is not allowed"); + return RESTERR(req, HTTP_BAD_REQUEST, "Combination of URI scheme inputs and raw post data is not allowed"); CDataStream oss(SER_NETWORK, PROTOCOL_VERSION); oss << strRequestMutable; @@ -478,14 +478,14 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart) } } catch (const std::ios_base::failure& e) { // abort in case of unreadable binary data - return RESTERR(req, HTTP_INTERNAL_SERVER_ERROR, "Parse error"); + return RESTERR(req, HTTP_BAD_REQUEST, "Parse error"); } break; } case RF_JSON: { if (!fInputParsed) - return RESTERR(req, HTTP_INTERNAL_SERVER_ERROR, "Error: empty request"); + return RESTERR(req, HTTP_BAD_REQUEST, "Error: empty request"); break; } default: { @@ -495,7 +495,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart) // limit max outpoints if (vOutPoints.size() > MAX_GETUTXOS_OUTPOINTS) - return RESTERR(req, HTTP_INTERNAL_SERVER_ERROR, strprintf("Error: max outpoints exceeded (max: %d, tried: %d)", MAX_GETUTXOS_OUTPOINTS, vOutPoints.size())); + return RESTERR(req, HTTP_BAD_REQUEST, strprintf("Error: max outpoints exceeded (max: %d, tried: %d)", MAX_GETUTXOS_OUTPOINTS, vOutPoints.size())); // check spentness and form a bitmap (as well as a JSON capable human-readable string representation) vector bitmap; From 854f1af22e930cbe37195a5e9ad7dd7b878a9106 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 26 Jun 2016 20:32:37 +0200 Subject: [PATCH 0807/1802] Make the dummy argument to getaddednodeinfo optional --- doc/release-notes.md | 2 ++ src/rpc/client.cpp | 1 - src/rpc/net.cpp | 11 +++++------ 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/release-notes.md b/doc/release-notes.md index f2d8ca3a1517b..58994a6839415 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -63,6 +63,8 @@ UTXO set query (`GET /rest/getutxos//-/-/.../ 2) + if (fHelp || params.size() > 1) throw runtime_error( - "getaddednodeinfo dummy ( \"node\" )\n" + "getaddednodeinfo ( \"node\" )\n" "\nReturns information about the given added node, or all added nodes\n" "(note that onetry addnodes are not listed here)\n" "\nArguments:\n" - "1. dummy (boolean, required) Kept for historical purposes but ignored\n" - "2. \"node\" (string, optional) If provided, return information about this specific node, otherwise all nodes are returned.\n" + "1. \"node\" (string, optional) If provided, return information about this specific node, otherwise all nodes are returned.\n" "\nResult:\n" "[\n" " {\n" @@ -299,10 +298,10 @@ UniValue getaddednodeinfo(const UniValue& params, bool fHelp) std::vector vInfo = GetAddedNodeInfo(); - if (params.size() == 2) { + if (params.size() == 1) { bool found = false; for (const AddedNodeInfo& info : vInfo) { - if (info.strAddedNode == params[1].get_str()) { + if (info.strAddedNode == params[0].get_str()) { vInfo.assign(1, info); found = true; break; From 09546ca0c939d21e9331df24cffeb96b156eaab2 Mon Sep 17 00:00:00 2001 From: nomnombtc Date: Thu, 1 Sep 2016 16:36:38 +0200 Subject: [PATCH 0808/1802] regenerated all manpages with commit tag stripped, also add bitcoin-tx --- doc/man/Makefile.am | 2 +- doc/man/bitcoin-cli.1 | 6 +-- doc/man/bitcoin-qt.1 | 6 +-- doc/man/bitcoin-tx.1 | 107 ++++++++++++++++++++++++++++++++++++++++++ doc/man/bitcoind.1 | 6 +-- 5 files changed, 117 insertions(+), 10 deletions(-) create mode 100644 doc/man/bitcoin-tx.1 diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am index 1a31039360b18..5252ef4a19aa4 100644 --- a/doc/man/Makefile.am +++ b/doc/man/Makefile.am @@ -1 +1 @@ -dist_man1_MANS=bitcoind.1 bitcoin-qt.1 bitcoin-cli.1 +dist_man1_MANS=bitcoind.1 bitcoin-qt.1 bitcoin-cli.1 bitcoin-tx.1 diff --git a/doc/man/bitcoin-cli.1 b/doc/man/bitcoin-cli.1 index f15594080a074..11b690cf856c0 100644 --- a/doc/man/bitcoin-cli.1 +++ b/doc/man/bitcoin-cli.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.5. -.TH BITCOIN-CLI "1" "August 2016" "bitcoin-cli 0.13.0.0" "User Commands" +.TH BITCOIN-CLI "1" "September 2016" "bitcoin-cli v0.13.0.0" "User Commands" .SH NAME -bitcoin-cli \- manual page for bitcoin-cli 0.13.0.0 +bitcoin-cli \- manual page for bitcoin-cli v0.13.0.0 .SH DESCRIPTION -Bitcoin Core RPC client version v0.13.0.0\-ga402396 +Bitcoin Core RPC client version v0.13.0.0 .SS "Usage:" .TP bitcoin\-cli [options] [params] diff --git a/doc/man/bitcoin-qt.1 b/doc/man/bitcoin-qt.1 index b57e6819d93b1..24b529dac1671 100644 --- a/doc/man/bitcoin-qt.1 +++ b/doc/man/bitcoin-qt.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.5. -.TH BITCOIN-QT "1" "August 2016" "bitcoin-qt 0.13.0.0" "User Commands" +.TH BITCOIN-QT "1" "September 2016" "bitcoin-qt v0.13.0.0" "User Commands" .SH NAME -bitcoin-qt \- manual page for bitcoin-qt 0.13.0.0 +bitcoin-qt \- manual page for bitcoin-qt v0.13.0.0 .SH DESCRIPTION -Bitcoin Core version v0.13.0.0\-ga402396 (64\-bit) +Bitcoin Core version v0.13.0.0 (64\-bit) Usage: .IP bitcoin\-qt [command\-line options] diff --git a/doc/man/bitcoin-tx.1 b/doc/man/bitcoin-tx.1 new file mode 100644 index 0000000000000..5c4e31e7f7922 --- /dev/null +++ b/doc/man/bitcoin-tx.1 @@ -0,0 +1,107 @@ +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.5. +.TH BITCOIN-TX "1" "September 2016" "bitcoin-tx v0.13.0.0" "User Commands" +.SH NAME +bitcoin-tx \- manual page for bitcoin-tx v0.13.0.0 +.SH DESCRIPTION +Bitcoin Core bitcoin\-tx utility version v0.13.0.0 +.SS "Usage:" +.TP +bitcoin\-tx [options] [commands] +Update hex\-encoded bitcoin transaction +.TP +bitcoin\-tx [options] \fB\-create\fR [commands] +Create hex\-encoded bitcoin transaction +.SH OPTIONS +.HP +\-? +.IP +This help message +.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 +.HP +\fB\-regtest\fR +.IP +Enter regression test mode, which uses a special chain in which blocks +can be solved instantly. This is intended for regression testing +tools and app development. +.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 +outscript=VALUE:SCRIPT +.IP +Add raw script output to TX +.IP +sign=SIGHASH\-FLAGS +.IP +Add zero or more signatures to transaction. This command requires JSON +registers:prevtxs=JSON object, privatekeys=JSON object. See +signrawtransaction 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-2016 The Bitcoin Core developers + +Please contribute if you find Bitcoin Core useful. Visit + for further information about the software. +The source code is available from . + +This is experimental software. +Distributed under the MIT software license, see the accompanying file COPYING +or . + +This product includes software developed by the OpenSSL Project for use in the +OpenSSL Toolkit and cryptographic software written +by Eric Young and UPnP software written by Thomas Bernard. diff --git a/doc/man/bitcoind.1 b/doc/man/bitcoind.1 index c3c55add0ce85..b99657a5fae3a 100644 --- a/doc/man/bitcoind.1 +++ b/doc/man/bitcoind.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.5. -.TH BITCOIND "1" "August 2016" "bitcoind 0.13.0.0" "User Commands" +.TH BITCOIND "1" "September 2016" "bitcoind v0.13.0.0" "User Commands" .SH NAME -bitcoind \- manual page for bitcoind 0.13.0.0 +bitcoind \- manual page for bitcoind v0.13.0.0 .SH DESCRIPTION -Bitcoin Core Daemon version v0.13.0.0\-ga402396 +Bitcoin Core Daemon version v0.13.0.0 .SS "Usage:" .TP bitcoind [options] From d19583f478f4104ea8ff787a475f9064d2c388ae Mon Sep 17 00:00:00 2001 From: nomnombtc Date: Thu, 1 Sep 2016 16:51:24 +0200 Subject: [PATCH 0809/1802] improved gen-manpages.sh, includes bitcoin-tx and strips commit tag, now also runs binaries from build dir by default, added variables for more control --- contrib/devtools/gen-manpages.sh | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/contrib/devtools/gen-manpages.sh b/contrib/devtools/gen-manpages.sh index 7cd7d1b50997a..967717e1e0d6d 100755 --- a/contrib/devtools/gen-manpages.sh +++ b/contrib/devtools/gen-manpages.sh @@ -1,18 +1,29 @@ #!/bin/sh -# the autodetected version git tag at the end -# can screw up manpage output a little bit -BTCVER=$(bitcoin-cli --version | cut -d"-" -f1 | cut -d"v" -f3) +TOPDIR=${TOPDIR:-$(git rev-parse --show-toplevel)} +SRCDIR=${SRCDIR:-$TOPDIR/src} +MANDIR=${MANDIR:-$TOPDIR/doc/man} + +BITCOIND=${BITCOIND:-$SRCDIR/bitcoind} +BITCOINCLI=${BITCOINCLI:-$SRCDIR/bitcoin-cli} +BITCOINTX=${BITCOINTX:-$SRCDIR/bitcoin-tx} +BITCOINQT=${BITCOINQT:-$SRCDIR/qt/bitcoin-qt} + +[ ! -x $BITCOIND ] && echo "$BITCOIND not found or not executable." && exit 1 + +# The autodetected version git tag can screw up manpage output a little bit +BTCVER=($($BITCOINCLI --version | head -n1 | awk -F'[ -]' '{ print $6, $7 }')) # Create a footer file with copyright content. -# This gets autodetected fine for bitcoind if -# --version-string is not set, but has different -# outcomes for bitcoin-qt and bitcoin-cli. +# This gets autodetected fine for bitcoind if --version-string is not set, +# but has different outcomes for bitcoin-qt and bitcoin-cli. echo "[COPYRIGHT]" > footer.h2m -bitcoind --version | sed -n '1!p' >> footer.h2m +$BITCOIND --version | sed -n '1!p' >> footer.h2m -for cmd in bitcoind bitcoin-qt bitcoin-cli; do - help2man -N --version-string=${BTCVER} --include=footer.h2m -o ../../doc/man/${cmd}.1 ${cmd} +for cmd in $BITCOIND $BITCOINCLI $BITCOINTX $BITCOINQT; do + cmdname="${cmd##*/}" + help2man -N --version-string=${BTCVER[0]} --include=footer.h2m -o ${MANDIR}/${cmdname}.1 ${cmd} + sed -i "s/\\\-${BTCVER[1]}//g" ${MANDIR}/${cmdname}.1 done rm -f footer.h2m From cdd79eb70fe163a92531a6f11c72bce6d228dac6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Tim=C3=B3n?= Date: Tue, 30 Aug 2016 22:41:56 +0200 Subject: [PATCH 0810/1802] C++11: s/boost::scoped_ptr/std::unique_ptr/ --- src/bitcoin-tx.cpp | 2 +- src/dbwrapper.cpp | 2 +- src/init.cpp | 2 +- src/main.cpp | 2 +- src/rpc/blockchain.cpp | 2 +- src/test/dbwrapper_tests.cpp | 6 +++--- src/txdb.cpp | 2 +- src/txdb.h | 2 +- src/wallet/walletdb.cpp | 3 +-- 9 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 5cf9b043ea94b..cb863bda191f8 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -515,7 +515,7 @@ class Secp256k1Init static void MutateTx(CMutableTransaction& tx, const string& command, const string& commandVal) { - boost::scoped_ptr ecc; + std::unique_ptr ecc; if (command == "nversion") MutateTxVersion(tx, commandVal); diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp index 09c68fbe550c8..4fa06135d286f 100644 --- a/src/dbwrapper.cpp +++ b/src/dbwrapper.cpp @@ -117,7 +117,7 @@ std::vector CDBWrapper::CreateObfuscateKey() const bool CDBWrapper::IsEmpty() { - boost::scoped_ptr it(NewIterator()); + std::unique_ptr it(NewIterator()); it->SeekToFirst(); return !(it->Valid()); } diff --git a/src/init.cpp b/src/init.cpp index 9bd820852c778..27843fa882318 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -162,7 +162,7 @@ class CCoinsViewErrorCatcher : public CCoinsViewBacked static CCoinsViewDB *pcoinsdbview = NULL; static CCoinsViewErrorCatcher *pcoinscatcher = NULL; -static boost::scoped_ptr globalVerifyHandle; +static std::unique_ptr globalVerifyHandle; void Interrupt(boost::thread_group& threadGroup) { diff --git a/src/main.cpp b/src/main.cpp index 30edc5dbebaa9..f19fada113b01 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -196,7 +196,7 @@ namespace { * * Memory used: 1.3 MB */ - boost::scoped_ptr recentRejects; + std::unique_ptr recentRejects; uint256 hashRecentRejectsChainTip; /** Blocks that are in flight, and that are in the queue to be downloaded. Protected by cs_main. */ diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index e3c32d905af74..0f3edde145745 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -632,7 +632,7 @@ struct CCoinsStats //! Calculate statistics about the unspent transaction output set static bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats) { - boost::scoped_ptr pcursor(view->Cursor()); + std::unique_ptr pcursor(view->Cursor()); CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); stats.hashBlock = pcursor->GetBestBlock(); diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp index a0bdcf4afbc70..d4d825d199406 100644 --- a/src/test/dbwrapper_tests.cpp +++ b/src/test/dbwrapper_tests.cpp @@ -101,7 +101,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper_iterator) uint256 in2 = GetRandHash(); BOOST_CHECK(dbw.Write(key2, in2)); - boost::scoped_ptr it(const_cast(&dbw)->NewIterator()); + std::unique_ptr it(const_cast(&dbw)->NewIterator()); // Be sure to seek past the obfuscation key (if it exists) it->Seek(key); @@ -214,7 +214,7 @@ BOOST_AUTO_TEST_CASE(iterator_ordering) BOOST_CHECK(dbw.Write(key, value)); } - boost::scoped_ptr it(const_cast(&dbw)->NewIterator()); + std::unique_ptr it(const_cast(&dbw)->NewIterator()); for (int c=0; c<2; ++c) { int seek_start; if (c == 0) @@ -290,7 +290,7 @@ BOOST_AUTO_TEST_CASE(iterator_string_ordering) } } - boost::scoped_ptr it(const_cast(&dbw)->NewIterator()); + std::unique_ptr it(const_cast(&dbw)->NewIterator()); for (int c=0; c<2; ++c) { int seek_start; if (c == 0) diff --git a/src/txdb.cpp b/src/txdb.cpp index 078c29def319b..4f11c7b95172e 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -173,7 +173,7 @@ bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) { bool CBlockTreeDB::LoadBlockIndexGuts(boost::function insertBlockIndex) { - boost::scoped_ptr pcursor(NewIterator()); + std::unique_ptr pcursor(NewIterator()); pcursor->Seek(make_pair(DB_BLOCK_INDEX, uint256())); diff --git a/src/txdb.h b/src/txdb.h index 5b98d2792c50d..adb3f66327223 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -92,7 +92,7 @@ class CCoinsViewDBCursor: public CCoinsViewCursor private: CCoinsViewDBCursor(CDBIterator* pcursorIn, const uint256 &hashBlockIn): CCoinsViewCursor(hashBlockIn), pcursor(pcursorIn) {} - boost::scoped_ptr pcursor; + std::unique_ptr pcursor; std::pair keyTmp; friend class CCoinsViewDB; diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 9de0671ea2164..239b1ac9b548a 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -18,7 +18,6 @@ #include #include #include -#include #include using namespace std; @@ -941,7 +940,7 @@ bool CWalletDB::Recover(CDBEnv& dbenv, const std::string& filename, bool fOnlyKe } LogPrintf("Salvage(aggressive) found %u records\n", salvagedData.size()); - boost::scoped_ptr pdbCopy(new Db(dbenv.dbenv, 0)); + std::unique_ptr pdbCopy(new Db(dbenv.dbenv, 0)); int ret = pdbCopy->open(NULL, // Txn pointer filename.c_str(), // Filename "main", // Logical db name From 38acbf83e1aa652f7af917efc31a035999a98af3 Mon Sep 17 00:00:00 2001 From: Doug Date: Thu, 1 Sep 2016 17:20:44 -0700 Subject: [PATCH 0811/1802] Remove unused Qt 4.6 patch. Core no longer supports Qt 4. Therefore, the STL fix patch isn't needed. --- depends/patches/qt46/stlfix.patch | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 depends/patches/qt46/stlfix.patch diff --git a/depends/patches/qt46/stlfix.patch b/depends/patches/qt46/stlfix.patch deleted file mode 100644 index f8f6fb04b0b70..0000000000000 --- a/depends/patches/qt46/stlfix.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- old/config.tests/unix/stl/stltest.cpp 2011-06-23 03:45:23.000000000 -0400 -+++ new/config.tests/unix/stl/stltest.cpp 2014-08-28 00:54:04.154837604 -0400 -@@ -49,6 +49,7 @@ - #include - #include - #include -+#include - - // something mean to see if the compiler and C++ standard lib are good enough - template From 4424af5190f11996e7970064b4f6553ba7cd1f9e Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 2 Sep 2016 11:43:06 +0200 Subject: [PATCH 0812/1802] Predeclare PrecomputedTransactionData as sturct --- src/main.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.h b/src/main.h index 7a2d432628957..18d674612f97e 100644 --- a/src/main.h +++ b/src/main.h @@ -38,8 +38,8 @@ class CScriptCheck; class CTxMemPool; class CValidationInterface; class CValidationState; -class PrecomputedTransactionData; +struct PrecomputedTransactionData; struct CNodeStateStats; struct LockPoints; From 7c069a70931a6bb27d060927765146d4c6ceced4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Fri, 2 Sep 2016 20:50:59 +0200 Subject: [PATCH 0813/1802] Do not shadow global variable --- src/util.cpp | 12 ++++++------ src/util.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/util.cpp b/src/util.cpp index ee12f2b443427..fe37f5e7532c6 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -601,19 +601,19 @@ bool TryCreateDirectory(const boost::filesystem::path& p) return false; } -void FileCommit(FILE *fileout) +void FileCommit(FILE *file) { - fflush(fileout); // harmless if redundantly called + fflush(file); // harmless if redundantly called #ifdef WIN32 - HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(fileout)); + HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file)); FlushFileBuffers(hFile); #else #if defined(__linux__) || defined(__NetBSD__) - fdatasync(fileno(fileout)); + fdatasync(fileno(file)); #elif defined(__APPLE__) && defined(F_FULLFSYNC) - fcntl(fileno(fileout), F_FULLFSYNC, 0); + fcntl(fileno(file), F_FULLFSYNC, 0); #else - fsync(fileno(fileout)); + fsync(fileno(file)); #endif #endif } diff --git a/src/util.h b/src/util.h index 39328b51ef154..45b365855781a 100644 --- a/src/util.h +++ b/src/util.h @@ -93,7 +93,7 @@ bool error(const char* fmt, const Args&... args) void PrintExceptionContinue(const std::exception *pex, const char* pszThread); void ParseParameters(int argc, const char*const argv[]); -void FileCommit(FILE *fileout); +void FileCommit(FILE *file); bool TruncateFile(FILE *file, unsigned int length); int RaiseFileDescriptorLimit(int nMinFD); void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length); From 46606af200db563ca742b56f291cee2311a27491 Mon Sep 17 00:00:00 2001 From: BtcDrak Date: Fri, 2 Sep 2016 23:05:29 +0100 Subject: [PATCH 0814/1802] Update btcdrak signing key --- contrib/gitian-keys/btcdrak-key.pgp | Bin 8954 -> 4916 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/contrib/gitian-keys/btcdrak-key.pgp b/contrib/gitian-keys/btcdrak-key.pgp index 60d76c0ec7ab86635637ee9f49948e004fadfee4..f00dc729d57a2e7b7848324177c605dac9dc8e45 100644 GIT binary patch literal 4916 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 z%0A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 Date: Sat, 3 Sep 2016 10:24:37 +0000 Subject: [PATCH 0815/1802] Do not set an addr time penalty when a peer advertises itself. Claims a peer makes about itself are inherently more credible. --- src/addrman.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/addrman.cpp b/src/addrman.cpp index cebb1c8e5e708..bfb8e94575de2 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -255,6 +255,11 @@ bool CAddrMan::Add_(const CAddress& addr, const CNetAddr& source, int64_t nTimeP int nId; CAddrInfo* pinfo = Find(addr, &nId); + // Do not set a penality for a source's self-announcement + if (addr == source) { + nTimePenalty = 0; + } + if (pinfo) { // periodically update nTime bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60); From ff2ed7a5bc8f56d2c0cd8d4fa6cf06ecfe17f1b2 Mon Sep 17 00:00:00 2001 From: mruddy Date: Sun, 4 Sep 2016 11:42:07 -0400 Subject: [PATCH 0816/1802] trivial: remove unnecessary variable fDaemon --- src/bitcoind.cpp | 5 +---- src/util.cpp | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 28bc374acc76e..322298d1b38ab 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -40,8 +40,6 @@ * Use the buttons Namespaces, Classes or Files at the top of the page to start navigating the code. */ -static bool fDaemon; - void WaitForShutdown(boost::thread_group* threadGroup) { bool fShutdown = ShutdownRequested(); @@ -130,8 +128,7 @@ bool AppInit(int argc, char* argv[]) exit(1); } #ifndef WIN32 - fDaemon = GetBoolArg("-daemon", false); - if (fDaemon) + if (GetBoolArg("-daemon", false)) { fprintf(stdout, "Bitcoin server starting\n"); diff --git a/src/util.cpp b/src/util.cpp index ee12f2b443427..c7d147a11eebb 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -107,7 +107,6 @@ map > mapMultiArgs; bool fDebug = false; bool fPrintToConsole = false; bool fPrintToDebugLog = true; -bool fDaemon = false; bool fServer = false; string strMiscWarning; bool fLogTimestamps = DEFAULT_LOGTIMESTAMPS; From 438e94dc330a37600ec1d86f2ba8502385b5262d Mon Sep 17 00:00:00 2001 From: whythat Date: Fri, 2 Sep 2016 12:38:04 +0300 Subject: [PATCH 0817/1802] remove root test directory for RPC tests --- qa/rpc-tests/test_framework/test_framework.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/qa/rpc-tests/test_framework/test_framework.py b/qa/rpc-tests/test_framework/test_framework.py index a1383729fad96..186cf866cfda6 100755 --- a/qa/rpc-tests/test_framework/test_framework.py +++ b/qa/rpc-tests/test_framework/test_framework.py @@ -125,7 +125,8 @@ def main(self): self.add_options(parser) (self.options, self.args) = parser.parse_args() - self.options.tmpdir += '/' + str(self.options.port_seed) + # backup dir variable for removal at cleanup + self.options.root, self.options.tmpdir = self.options.tmpdir, self.options.tmpdir + '/' + str(self.options.port_seed) if self.options.trace_rpc: logging.basicConfig(level=logging.DEBUG, stream=sys.stdout) @@ -176,6 +177,8 @@ def main(self): if not self.options.nocleanup and not self.options.noshutdown and success: print("Cleaning up") shutil.rmtree(self.options.tmpdir) + if not os.listdir(self.options.root): + os.rmdir(self.options.root) else: print("Not cleaning up dir %s" % self.options.tmpdir) From c62cc4ec759a8487373f158b3cbb888efcdd753a Mon Sep 17 00:00:00 2001 From: whythat Date: Mon, 5 Sep 2016 02:04:37 +0300 Subject: [PATCH 0818/1802] fix path for bak file --- qa/rpc-tests/wallet-hd.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/qa/rpc-tests/wallet-hd.py b/qa/rpc-tests/wallet-hd.py index c11da1e9a9989..a49d91f6f4f53 100755 --- a/qa/rpc-tests/wallet-hd.py +++ b/qa/rpc-tests/wallet-hd.py @@ -39,8 +39,8 @@ def run_test (self): self.nodes[1].importprivkey(self.nodes[0].dumpprivkey(non_hd_add)) # This should be enough to keep the master key and the non-HD key - self.nodes[1].backupwallet(tmpdir + "hd.bak") - #self.nodes[1].dumpwallet(tmpdir + "hd.dump") + self.nodes[1].backupwallet(tmpdir + "/hd.bak") + #self.nodes[1].dumpwallet(tmpdir + "/hd.dump") # Derive some HD addresses and remember the last # Also send funds to each add @@ -63,7 +63,7 @@ def run_test (self): print("Restore backup ...") self.stop_node(1) os.remove(self.options.tmpdir + "/node1/regtest/wallet.dat") - shutil.copyfile(tmpdir + "hd.bak", tmpdir + "/node1/regtest/wallet.dat") + shutil.copyfile(tmpdir + "/hd.bak", tmpdir + "/node1/regtest/wallet.dat") self.nodes[1] = start_node(1, self.options.tmpdir, self.node_args[1]) #connect_nodes_bi(self.nodes, 0, 1) From c40b034327bf8a30d3af1eeeef84bc4ccd57e685 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Sun, 4 Sep 2016 20:02:40 -0400 Subject: [PATCH 0819/1802] Clear witness with vin/vout in CWallet::CreateTransaction() --- src/wallet/wallet.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 10aca2e499f60..78d62582975f2 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2209,6 +2209,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt nChangePosInOut = nChangePosRequest; txNew.vin.clear(); txNew.vout.clear(); + txNew.wit.SetNull(); wtxNew.fFromMe = true; bool fFirst = true; From 34521e4d7d176109dedf52ec8ef2b5052b9a30f3 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 16 Aug 2016 17:38:57 +0200 Subject: [PATCH 0820/1802] Do not store witness txn in rejection cache --- src/main.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index aed9591f99394..d32a7e9be5c62 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1501,9 +1501,9 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C // SCRIPT_VERIFY_CLEANSTACK requires SCRIPT_VERIFY_WITNESS, so we // need to turn both off, and compare against just turning off CLEANSTACK // to see if the failure is specifically due to witness validation. - if (CheckInputs(tx, state, view, true, scriptVerifyFlags & ~(SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_CLEANSTACK), true, txdata) && + if (tx.wit.IsNull() && CheckInputs(tx, state, view, true, scriptVerifyFlags & ~(SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_CLEANSTACK), true, txdata) && !CheckInputs(tx, state, view, true, scriptVerifyFlags & ~SCRIPT_VERIFY_CLEANSTACK, true, txdata)) { - // Only the witness is wrong, so the transaction itself may be fine. + // Only the witness is missing, so the transaction itself may be fine. state.SetCorruptionPossible(); } return false; @@ -5493,7 +5493,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, else if (!fMissingInputs2) { int nDos = 0; - if (stateDummy.IsInvalid(nDos) && nDos > 0 && (!state.CorruptionPossible() || State(fromPeer)->fHaveWitness)) + if (stateDummy.IsInvalid(nDos) && nDos > 0) { // Punish peer that gave us an invalid orphan tx Misbehaving(fromPeer, nDos); @@ -5504,7 +5504,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // Probably non-standard or insufficient fee/priority LogPrint("mempool", " removed orphan tx %s\n", orphanHash.ToString()); vEraseQueue.push_back(orphanHash); - if (!stateDummy.CorruptionPossible()) { + if (orphanTx.wit.IsNull() && !stateDummy.CorruptionPossible()) { + // Do not use rejection cache for witness transactions or + // witness-stripped transactions, as they can have been malleated. + // See https://github.com/bitcoin/bitcoin/issues/8279 for details. assert(recentRejects); recentRejects->insert(orphanHash); } @@ -5542,7 +5545,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, LogPrint("mempool", "not keeping orphan with rejected parents %s\n",tx.GetHash().ToString()); } } else { - if (!state.CorruptionPossible()) { + if (tx.wit.IsNull() && !state.CorruptionPossible()) { + // Do not use rejection cache for witness transactions or + // witness-stripped transactions, as they can have been malleated. + // See https://github.com/bitcoin/bitcoin/issues/8279 for details. assert(recentRejects); recentRejects->insert(tx.GetHash()); } @@ -5574,9 +5580,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, if (state.GetRejectCode() < REJECT_INTERNAL) // Never send AcceptToMemoryPool's internal codes over P2P pfrom->PushMessage(NetMsgType::REJECT, strCommand, (unsigned char)state.GetRejectCode(), state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash); - if (nDoS > 0 && (!state.CorruptionPossible() || State(pfrom->id)->fHaveWitness)) { - // When a non-witness-supporting peer gives us a transaction that would - // be accepted if witness validation was off, we can't blame them for it. + if (nDoS > 0) { Misbehaving(pfrom->GetId(), nDoS); } } From ca10a03addf70421893791c2c499e82fc494d60b Mon Sep 17 00:00:00 2001 From: instagibbs Date: Thu, 18 Aug 2016 12:04:33 -0400 Subject: [PATCH 0821/1802] Add basic test for IsStandard witness transaction blinding --- qa/rpc-tests/p2p-segwit.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/qa/rpc-tests/p2p-segwit.py b/qa/rpc-tests/p2p-segwit.py index eb857ed983b3c..ca784644d8ee2 100755 --- a/qa/rpc-tests/p2p-segwit.py +++ b/qa/rpc-tests/p2p-segwit.py @@ -964,8 +964,24 @@ def test_tx_relay_after_segwit_activation(self): tx3 = CTransaction() tx3.vin.append(CTxIn(COutPoint(tx2.sha256, 0), b"")) - tx3.vout.append(CTxOut(tx2.vout[0].nValue-1000, CScript([OP_TRUE]))) tx3.wit.vtxinwit.append(CTxInWitness()) + + # Add too-large for IsStandard witness and check that it does not enter reject filter + p2sh_program = CScript([OP_TRUE]) + p2sh_pubkey = hash160(p2sh_program) + witness_program2 = CScript([b'a'*400000]) + tx3.vout.append(CTxOut(tx2.vout[0].nValue-1000, CScript([OP_HASH160, p2sh_pubkey, OP_EQUAL]))) + tx3.wit.vtxinwit[0].scriptWitness.stack = [witness_program2] + tx3.rehash() + + # Node will not be blinded to the transaction + self.std_node.announce_tx_and_wait_for_getdata(tx3) + self.std_node.test_transaction_acceptance(tx3, True, False, b'tx-size') + self.std_node.announce_tx_and_wait_for_getdata(tx3) + self.std_node.test_transaction_acceptance(tx3, True, False, b'tx-size') + + # Remove witness stuffing, instead add extra witness push on stack + tx3.vout[0] = CTxOut(tx2.vout[0].nValue-1000, CScript([OP_TRUE])) tx3.wit.vtxinwit[0].scriptWitness.stack = [CScript([CScriptNum(1)]), witness_program ] tx3.rehash() From 2f2548d5e0ccea6879eb7b0b851d61ad2f544423 Mon Sep 17 00:00:00 2001 From: Johnson Lau Date: Tue, 6 Sep 2016 00:50:23 +0800 Subject: [PATCH 0822/1802] Fix SIGHASH_SINGLE bug in test_framework SignatureHash The value for "other" inputs should be -1 (0xffffffffffffffff) instead of 0 --- qa/rpc-tests/test_framework/script.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qa/rpc-tests/test_framework/script.py b/qa/rpc-tests/test_framework/script.py index b46c643ccb114..83bbf2047964c 100644 --- a/qa/rpc-tests/test_framework/script.py +++ b/qa/rpc-tests/test_framework/script.py @@ -882,7 +882,7 @@ def SignatureHash(script, txTo, inIdx, hashtype): tmp = txtmp.vout[outIdx] txtmp.vout = [] for i in range(outIdx): - txtmp.vout.append(CTxOut()) + txtmp.vout.append(CTxOut(-1)) txtmp.vout.append(tmp) for i in range(len(txtmp.vin)): From f71d4a3786611d564e4c239099501daee989b170 Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Tue, 6 Sep 2016 16:19:25 -0400 Subject: [PATCH 0823/1802] Minimal fix to slow prevector tests as stopgap measure --- src/test/prevector_tests.cpp | 62 +++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 19 deletions(-) diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp index d1407c1da9339..b8c45ca564dc9 100644 --- a/src/test/prevector_tests.cpp +++ b/src/test/prevector_tests.cpp @@ -26,57 +26,70 @@ class prevector_tester { pretype pre_vector_alt; typedef typename pretype::size_type Size; + bool passed = true; + uint32_t insecure_rand_Rz_cache; + uint32_t insecure_rand_Rw_cache; + + template + void local_check_equal(A a, B b) + { + local_check(a == b); + } + void local_check(bool b) + { + passed &= b; + } void test() { const pretype& const_pre_vector = pre_vector; - BOOST_CHECK_EQUAL(real_vector.size(), pre_vector.size()); - BOOST_CHECK_EQUAL(real_vector.empty(), pre_vector.empty()); + local_check_equal(real_vector.size(), pre_vector.size()); + local_check_equal(real_vector.empty(), pre_vector.empty()); for (Size s = 0; s < real_vector.size(); s++) { - BOOST_CHECK(real_vector[s] == pre_vector[s]); - BOOST_CHECK(&(pre_vector[s]) == &(pre_vector.begin()[s])); - BOOST_CHECK(&(pre_vector[s]) == &*(pre_vector.begin() + s)); - BOOST_CHECK(&(pre_vector[s]) == &*((pre_vector.end() + s) - real_vector.size())); + local_check(real_vector[s] == pre_vector[s]); + local_check(&(pre_vector[s]) == &(pre_vector.begin()[s])); + local_check(&(pre_vector[s]) == &*(pre_vector.begin() + s)); + local_check(&(pre_vector[s]) == &*((pre_vector.end() + s) - real_vector.size())); } - // BOOST_CHECK(realtype(pre_vector) == real_vector); - BOOST_CHECK(pretype(real_vector.begin(), real_vector.end()) == pre_vector); - BOOST_CHECK(pretype(pre_vector.begin(), pre_vector.end()) == pre_vector); + // local_check(realtype(pre_vector) == real_vector); + local_check(pretype(real_vector.begin(), real_vector.end()) == pre_vector); + local_check(pretype(pre_vector.begin(), pre_vector.end()) == pre_vector); size_t pos = 0; BOOST_FOREACH(const T& v, pre_vector) { - BOOST_CHECK(v == real_vector[pos++]); + local_check(v == real_vector[pos++]); } BOOST_REVERSE_FOREACH(const T& v, pre_vector) { - BOOST_CHECK(v == real_vector[--pos]); + local_check(v == real_vector[--pos]); } BOOST_FOREACH(const T& v, const_pre_vector) { - BOOST_CHECK(v == real_vector[pos++]); + local_check(v == real_vector[pos++]); } BOOST_REVERSE_FOREACH(const T& v, const_pre_vector) { - BOOST_CHECK(v == real_vector[--pos]); + local_check(v == real_vector[--pos]); } CDataStream ss1(SER_DISK, 0); CDataStream ss2(SER_DISK, 0); ss1 << real_vector; ss2 << pre_vector; - BOOST_CHECK_EQUAL(ss1.size(), ss2.size()); + local_check_equal(ss1.size(), ss2.size()); for (Size s = 0; s < ss1.size(); s++) { - BOOST_CHECK_EQUAL(ss1[s], ss2[s]); + local_check_equal(ss1[s], ss2[s]); } } public: void resize(Size s) { real_vector.resize(s); - BOOST_CHECK_EQUAL(real_vector.size(), s); + local_check_equal(real_vector.size(), s); pre_vector.resize(s); - BOOST_CHECK_EQUAL(pre_vector.size(), s); + local_check_equal(pre_vector.size(), s); test(); } void reserve(Size s) { real_vector.reserve(s); - BOOST_CHECK(real_vector.capacity() >= s); + local_check(real_vector.capacity() >= s); pre_vector.reserve(s); - BOOST_CHECK(pre_vector.capacity() >= s); + local_check(pre_vector.capacity() >= s); test(); } @@ -157,6 +170,17 @@ class prevector_tester { pre_vector.swap(pre_vector_alt); test(); } + ~prevector_tester() { + BOOST_CHECK_MESSAGE(passed, "insecure_rand_Rz: " + << insecure_rand_Rz_cache + << ", insecure_rand_Rw: " + << insecure_rand_Rw_cache); + } + prevector_tester() { + seed_insecure_rand(); + insecure_rand_Rz_cache = insecure_rand_Rz; + insecure_rand_Rw_cache = insecure_rand_Rw; + } }; BOOST_AUTO_TEST_CASE(PrevectorTestInt) From 426e7bce0e365e0947f932ca46bcc48ca3a2f10e Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Tue, 6 Sep 2016 16:22:13 -0400 Subject: [PATCH 0824/1802] Fix obvious assignment/equality error in test --- src/test/arith_uint256_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/arith_uint256_tests.cpp b/src/test/arith_uint256_tests.cpp index 53ab7e95ee0cd..b19d2faea014c 100644 --- a/src/test/arith_uint256_tests.cpp +++ b/src/test/arith_uint256_tests.cpp @@ -112,7 +112,7 @@ BOOST_AUTO_TEST_CASE( basics ) // constructors, equality, inequality BOOST_CHECK( (R1L & arith_uint256("0xffffffffffffffff")) == arith_uint256(R1LLow64)); BOOST_CHECK(ZeroL == arith_uint256(0)); BOOST_CHECK(OneL == arith_uint256(1)); - BOOST_CHECK(arith_uint256("0xffffffffffffffff") = arith_uint256(0xffffffffffffffffULL)); + BOOST_CHECK(arith_uint256("0xffffffffffffffff") == arith_uint256(0xffffffffffffffffULL)); // Assignment (from base_uint) arith_uint256 tmpL = ~ZeroL; BOOST_CHECK(tmpL == ~ZeroL); From fdf82fba3105c3c824e594db8cd7c55c4f692744 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hampus=20Sj=C3=B6berg?= Date: Tue, 6 Sep 2016 22:30:30 +0200 Subject: [PATCH 0825/1802] Adding method GetTotalSize() to CTransaction GetTotalSize() returns the total transaction size (including witness) in bytes. --- src/primitives/transaction.cpp | 5 +++++ src/primitives/transaction.h | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index 2fdc59ea07767..4afbe99fd39a9 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -131,6 +131,11 @@ unsigned int CTransaction::CalculateModifiedSize(unsigned int nTxSize) const return nTxSize; } +unsigned int CTransaction::GetTotalSize() const +{ + return ::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION); +} + std::string CTransaction::ToString() const { std::string str; diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 5689d15bf7eb1..16c2e5c454fe4 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -415,6 +415,13 @@ class CTransaction // Compute modified tx size for priority calculation (optionally given tx size) unsigned int CalculateModifiedSize(unsigned int nTxSize=0) const; + + /** + * Get the total transaction size in bytes, including witness data. + * "Total Size" defined in BIP141 and BIP144. + * @return Total transaction size in bytes + */ + unsigned int GetTotalSize() const; bool IsCoinBase() const { From c015634400f112f8b7f037c82690f1332d7971a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hampus=20Sj=C3=B6berg?= Date: Tue, 6 Sep 2016 22:31:36 +0200 Subject: [PATCH 0826/1802] qt: Adding transaction size to transaction details window --- src/qt/transactiondesc.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index bae0cbd1c8681..32b3955ce57bd 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -241,6 +241,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco strHTML += "
" + tr("Comment") + ":
" + GUIUtil::HtmlEscape(wtx.mapValue["comment"], true) + "
"; strHTML += "" + tr("Transaction ID") + ": " + rec->getTxID() + "
"; + strHTML += "" + tr("Transaction size") + ": " + QString::number(wtx.GetTotalSize()) + " bytes
"; strHTML += "" + tr("Output index") + ": " + QString::number(rec->getOutputIndex()) + "
"; // Message from normal bitcoin:URI (bitcoin:123...?message=example) From 125b946cb4412fdf92bc3a68e6030bf4ddfe752d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Wed, 7 Sep 2016 13:45:13 +0200 Subject: [PATCH 0827/1802] Do not shadow upper local variable 'send', prevent -Wshadow compiler warning. --- src/main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 4b42afb561472..de16b0ca4ac2a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4789,16 +4789,16 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam pfrom->PushMessage(NetMsgType::BLOCK, block); else if (inv.type == MSG_FILTERED_BLOCK) { - bool send = false; + bool sendMerkleBlock = false; CMerkleBlock merkleBlock; { LOCK(pfrom->cs_filter); if (pfrom->pfilter) { - send = true; + sendMerkleBlock = true; merkleBlock = CMerkleBlock(block, *pfrom->pfilter); } } - if (send) { + if (sendMerkleBlock) { pfrom->PushMessage(NetMsgType::MERKLEBLOCK, merkleBlock); // CMerkleBlock just contains hashes, so also push any transactions in the block the client did not see // This avoids hurting performance by pointlessly requiring a round-trip From 04802930d4e1f565b3c36e1a806fbe9cd4809937 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Wed, 7 Sep 2016 16:03:08 +0200 Subject: [PATCH 0828/1802] [Qt][CoinControl] fix UI bug that could result in paying unexpected fee --- src/qt/sendcoinsdialog.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 3e96bb18c3ebd..8433818a64838 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -589,6 +589,9 @@ void SendCoinsDialog::updateGlobalFeeVariables() { nTxConfirmTarget = defaultConfirmTarget - ui->sliderSmartFee->value(); payTxFee = CFeeRate(0); + + // set nMinimumTotalFee to 0 to not accidentally pay a custom fee + CoinControlDialog::coinControl->nMinimumTotalFee = 0; } else { @@ -781,7 +784,7 @@ void SendCoinsDialog::coinControlUpdateLabels() ui->radioCustomAtLeast->setVisible(true); // only enable the feature if inputs are selected - ui->radioCustomAtLeast->setEnabled(CoinControlDialog::coinControl->HasSelected()); + ui->radioCustomAtLeast->setEnabled(ui->radioCustomFee->isChecked() && !ui->checkBoxMinimumFee->isChecked() &&CoinControlDialog::coinControl->HasSelected()); } else { From d6a5dc4a2eaa0d7348804254ca09e75fc3a858ab Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 1 Sep 2016 21:55:21 -0400 Subject: [PATCH 0829/1802] add waitfornewblock/waitforblock/waitforblockheight rpcs and use them for tests waitfornewblock waits until a new block is received, or the timeout expires, then returns the current block height/hash. waitforblock waits for a specific blockhash, or until the timeout expires, then returns the current block height/hash. If the target blockhash is the current tip, it will return immediately. waitforblockheight waits until the tip has reached a certain height or higher, then returns the current height and hash. waitforblockheight is used to avoid polling in the rpc tests. --- qa/rpc-tests/test_framework/util.py | 8 +- src/init.cpp | 8 ++ src/rpc/blockchain.cpp | 147 ++++++++++++++++++++++++++++ src/rpc/client.cpp | 6 ++ src/rpc/server.h | 1 + 5 files changed, 168 insertions(+), 2 deletions(-) diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index 190fa7f661a6d..eee77f1a104cc 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -125,12 +125,16 @@ def sync_blocks(rpc_connections, wait=1, timeout=60): """ Wait until everybody has the same tip """ + maxheight = 0 while timeout > 0: - tips = [ x.getbestblockhash() for x in rpc_connections ] + tips = [ x.waitforblockheight(maxheight, int(wait * 1000)) for x in rpc_connections ] + heights = [ x["height"] for x in tips ] if tips == [ tips[0] ]*len(tips): return True - time.sleep(wait) + if heights == [ heights[0] ]*len(heights): #heights are the same but hashes are not + raise AssertionError("Block sync failed") timeout -= wait + maxheight = max(heights) raise AssertionError("Block sync failed") def sync_mempools(rpc_connections, wait=1, timeout=60): diff --git a/src/init.cpp b/src/init.cpp index 27843fa882318..64e161b9b2907 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -280,9 +280,15 @@ bool static Bind(const CService &addr, unsigned int flags) { } return true; } +void OnRPCStarted() +{ + uiInterface.NotifyBlockTip.connect(&RPCNotifyBlockChange); +} void OnRPCStopped() { + uiInterface.NotifyBlockTip.disconnect(&RPCNotifyBlockChange); + RPCNotifyBlockChange(false, nullptr); cvBlockChange.notify_all(); LogPrint("rpc", "RPC stopped.\n"); } @@ -666,6 +672,7 @@ bool InitSanityCheck(void) bool AppInitServers(boost::thread_group& threadGroup) { + RPCServer::OnStarted(&OnRPCStarted); RPCServer::OnStopped(&OnRPCStopped); RPCServer::OnPreCommand(&OnRPCPreCommand); if (!InitHTTPServer()) @@ -1357,6 +1364,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) { LOCK(cs_main); CBlockIndex* tip = chainActive.Tip(); + RPCNotifyBlockChange(true, tip); if (tip && tip->nTime > GetAdjustedTime() + 2 * 60 * 60) { strLoadError = _("The block database contains a block which appears to be from the future. " "This may be due to your computer's date and time being set incorrectly. " diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index b90410017b692..dc7e4721bbc46 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -26,8 +26,20 @@ #include // boost::thread::interrupt +#include +#include using namespace std; +struct CUpdatedBlock +{ + uint256 hash; + int height; +}; + +static std::mutex cs_blockchange; +static std::condition_variable cond_blockchange; +static CUpdatedBlock latestblock; + extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); @@ -168,6 +180,138 @@ UniValue getbestblockhash(const UniValue& params, bool fHelp) return chainActive.Tip()->GetBlockHash().GetHex(); } +void RPCNotifyBlockChange(bool ibd, const CBlockIndex * pindex) +{ + if(pindex) { + std::lock_guard lock(cs_blockchange); + latestblock.hash = pindex->GetBlockHash(); + latestblock.height = pindex->nHeight; + } + cond_blockchange.notify_all(); +} + +UniValue waitfornewblock(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() > 1) + throw runtime_error( + "waitfornewblock\n" + "\nWaits for a specific new block and returns useful info about it.\n" + "\nReturns the current block on timeout or exit.\n" + "\nArguments:\n" + "1. timeout (milliseconds) (int, optional, default=false)\n" + "\nResult::\n" + "{ (json object)\n" + " \"hash\" : { (string) The blockhash\n" + " \"height\" : { (int) Block height\n" + "}\n" + "\nExamples\n" + + HelpExampleCli("waitfornewblock", "1000") + + HelpExampleRpc("waitfornewblock", "1000") + ); + int timeout = 0; + if (params.size() > 0) + timeout = params[0].get_int(); + + CUpdatedBlock block; + { + std::unique_lock lock(cs_blockchange); + block = latestblock; + if(timeout) + cond_blockchange.wait_for(lock, std::chrono::milliseconds(timeout), [&block]{return latestblock.height != block.height || latestblock.hash != block.hash || !IsRPCRunning(); }); + else + cond_blockchange.wait(lock, [&block]{return latestblock.height != block.height || latestblock.hash != block.hash || !IsRPCRunning(); }); + block = latestblock; + } + UniValue ret(UniValue::VOBJ); + ret.push_back(Pair("hash", block.hash.GetHex())); + ret.push_back(Pair("height", block.height)); + return ret; +} + +UniValue waitforblock(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "waitforblock\n" + "\nWaits for a specific new block and returns useful info about it.\n" + "\nReturns the current block on timeout or exit.\n" + "\nArguments:\n" + "1. blockhash to wait for (string)\n" + "2. timeout (milliseconds) (int, optional, default=false)\n" + "\nResult::\n" + "{ (json object)\n" + " \"hash\" : { (string) The blockhash\n" + " \"height\" : { (int) Block height\n" + "}\n" + "\nExamples\n" + + HelpExampleCli("waitforblock", "\"0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862\", 1000") + + HelpExampleRpc("waitforblock", "\"0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862\", 1000") + ); + int timeout = 0; + + uint256 hash = uint256S(params[0].get_str()); + + if (params.size() > 1) + timeout = params[1].get_int(); + + CUpdatedBlock block; + { + std::unique_lock lock(cs_blockchange); + if(timeout) + cond_blockchange.wait_for(lock, std::chrono::milliseconds(timeout), [&hash]{return latestblock.hash == hash || !IsRPCRunning();}); + else + cond_blockchange.wait(lock, [&hash]{return latestblock.hash == hash || !IsRPCRunning(); }); + block = latestblock; + } + + UniValue ret(UniValue::VOBJ); + ret.push_back(Pair("hash", block.hash.GetHex())); + ret.push_back(Pair("height", block.height)); + return ret; +} + +UniValue waitforblockheight(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "waitforblock\n" + "\nWaits for (at least) block height and returns the height and hash\n" + "\nof the current tip.\n" + "\nReturns the current block on timeout or exit.\n" + "\nArguments:\n" + "1. block height to wait for (int)\n" + "2. timeout (milliseconds) (int, optional, default=false)\n" + "\nResult::\n" + "{ (json object)\n" + " \"hash\" : { (string) The blockhash\n" + " \"height\" : { (int) Block height\n" + "}\n" + "\nExamples\n" + + HelpExampleCli("waitforblockheight", "\"100\", 1000") + + HelpExampleRpc("waitforblockheight", "\"100\", 1000") + ); + int timeout = 0; + + int height = params[0].get_int(); + + if (params.size() > 1) + timeout = params[1].get_int(); + + CUpdatedBlock block; + { + std::unique_lock lock(cs_blockchange); + if(timeout) + cond_blockchange.wait_for(lock, std::chrono::milliseconds(timeout), [&height]{return latestblock.height >= height || !IsRPCRunning();}); + else + cond_blockchange.wait(lock, [&height]{return latestblock.height >= height || !IsRPCRunning(); }); + block = latestblock; + } + UniValue ret(UniValue::VOBJ); + ret.push_back(Pair("hash", block.hash.GetHex())); + ret.push_back(Pair("height", block.height)); + return ret; +} + UniValue getdifficulty(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 0) @@ -1203,6 +1347,9 @@ static const CRPCCommand commands[] = /* Not shown in help */ { "hidden", "invalidateblock", &invalidateblock, true }, { "hidden", "reconsiderblock", &reconsiderblock, true }, + { "hidden", "waitfornewblock", &waitfornewblock, true }, + { "hidden", "waitforblock", &waitforblock, true }, + { "hidden", "waitforblockheight", &waitforblockheight, true }, }; void RegisterBlockchainRPCCommands(CRPCTable &t) diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 3003ea34528ae..c14d9d67474fe 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -46,6 +46,12 @@ static const CRPCConvertParam vRPCConvertParams[] = { "getbalance", 1 }, { "getbalance", 2 }, { "getblockhash", 0 }, + { "waitforblockheight", 0 }, + { "waitforblockheight", 1 }, + { "waitforblock", 1 }, + { "waitforblock", 2 }, + { "waitfornewblock", 0 }, + { "waitfornewblock", 1 }, { "move", 2 }, { "move", 3 }, { "sendfrom", 2 }, diff --git a/src/rpc/server.h b/src/rpc/server.h index b5ccc153d07ef..4e0aa2c6d6f6f 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -194,5 +194,6 @@ bool StartRPC(); void InterruptRPC(); void StopRPC(); std::string JSONRPCExecBatch(const UniValue& vReq); +void RPCNotifyBlockChange(bool ibd, const CBlockIndex *); #endif // BITCOIN_RPCSERVER_H From ec81881b86b9680fcdcc42fd3ba31f04b8d09714 Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Wed, 7 Sep 2016 18:24:40 -0400 Subject: [PATCH 0830/1802] Performance Regression Fix: Pre-Allocate txChanged vector --- src/main.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 4b42afb561472..932e0653bc51d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2793,7 +2793,7 @@ static int64_t nTimePostConnect = 0; * Connect a new block to chainActive. pblock is either NULL or a pointer to a CBlock * corresponding to pindexNew, to bypass loading it again from disk. */ -bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const CBlock* pblock, std::list &txConflicted, std::vector > &txChanged) +bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const CBlock* pblock, std::list &txConflicted, std::vector> &txChanged) { assert(pindexNew->pprev == chainActive.Tip()); // Read block from disk. @@ -2835,7 +2835,7 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, UpdateTip(pindexNew, chainparams); for(unsigned int i=0; i < pblock->vtx.size(); i++) - txChanged.push_back(std::make_tuple(pblock->vtx[i], pindexNew, i)); + txChanged.emplace_back(pblock->vtx[i], pindexNew, i); int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1; LogPrint("bench", " - Connect postprocess: %.2fms [%.2fs]\n", (nTime6 - nTime5) * 0.001, nTimePostConnect * 0.000001); @@ -2917,7 +2917,7 @@ static void PruneBlockIndexCandidates() { * Try to make some progress towards making pindexMostWork the active block. * pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork. */ -static bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const CBlock* pblock, bool& fInvalidFound, std::list& txConflicted, std::vector >& txChanged) +static bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const CBlock* pblock, bool& fInvalidFound, std::list& txConflicted, std::vector>& txChanged) { AssertLockHeld(cs_main); const CBlockIndex *pindexOldTip = chainActive.Tip(); @@ -3019,14 +3019,17 @@ static void NotifyHeaderTip() { bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, const CBlock *pblock) { CBlockIndex *pindexMostWork = NULL; CBlockIndex *pindexNewTip = NULL; + std::vector> txChanged; + if (pblock) + txChanged.reserve(pblock->vtx.size()); do { + txChanged.clear(); boost::this_thread::interruption_point(); if (ShutdownRequested()) break; const CBlockIndex *pindexFork; std::list txConflicted; - std::vector > txChanged; bool fInitialDownload; int nNewHeight; { From df2d2e70cac8d15ecc30bc5c46930fd27c8afac0 Mon Sep 17 00:00:00 2001 From: Gaurav Rana Date: Thu, 8 Sep 2016 17:43:55 +0545 Subject: [PATCH 0831/1802] update name of file bitcoin.qrc --- doc/translation_process.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/translation_process.md b/doc/translation_process.md index d8a85292e8ed8..a443a16fe240e 100644 --- a/doc/translation_process.md +++ b/doc/translation_process.md @@ -94,7 +94,7 @@ When new plurals are added to the source file, it's important to do the followin 7. Save the source file ### Translating a new language -To create a new language template, you will need to edit the languages manifest file `src/qt/bitcoin.qrc` and add a new entry. Below is an example of the English language entry. +To create a new language template, you will need to edit the languages manifest file `src/qt/bitcoin_locale.qrc` and add a new entry. Below is an example of the English language entry. ```xml From 531214fb100c14e62921085cd68cabe2b20ee0eb Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 19 Aug 2016 15:38:04 -0400 Subject: [PATCH 0832/1802] gui: add NodeID to the peer table --- src/qt/guiutil.cpp | 8 ++++---- src/qt/guiutil.h | 2 +- src/qt/peertablemodel.cpp | 6 +++++- src/qt/peertablemodel.h | 7 ++++--- src/qt/rpcconsole.cpp | 6 +++--- 5 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index c00f5e8591f3a..444e35de8af5c 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -291,17 +291,17 @@ void copyEntryData(QAbstractItemView *view, int column, int role) } } -QString getEntryData(QAbstractItemView *view, int column, int role) +QVariant getEntryData(QAbstractItemView *view, int column, int role) { if(!view || !view->selectionModel()) - return QString(); + return QVariant(); QModelIndexList selection = view->selectionModel()->selectedRows(column); if(!selection.isEmpty()) { // Return first item - return (selection.at(0).data(role).toString()); + return (selection.at(0).data(role)); } - return QString(); + return QVariant(); } QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h index 9267e0a6c9db0..d5a658e7c0add 100644 --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -70,7 +70,7 @@ namespace GUIUtil @param[in] role Data role to extract from the model @see TransactionView::copyLabel, TransactionView::copyAmount, TransactionView::copyAddress */ - QString getEntryData(QAbstractItemView *view, int column, int role); + QVariant getEntryData(QAbstractItemView *view, int column, int role); void setClipboard(const QString& str); diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp index 84ad0052fdd90..0eb28f4ae18e8 100644 --- a/src/qt/peertablemodel.cpp +++ b/src/qt/peertablemodel.cpp @@ -24,6 +24,8 @@ bool NodeLessThan::operator()(const CNodeCombinedStats &left, const CNodeCombine switch(column) { + case PeerTableModel::NetNodeId: + return pLeft->nodeid < pRight->nodeid; case PeerTableModel::Address: return pLeft->addrName.compare(pRight->addrName) < 0; case PeerTableModel::Subversion: @@ -114,7 +116,7 @@ PeerTableModel::PeerTableModel(ClientModel *parent) : clientModel(parent), timer(0) { - columns << tr("Node/Service") << tr("User Agent") << tr("Ping Time"); + columns << tr("NodeId") << tr("Node/Service") << tr("User Agent") << tr("Ping Time"); priv = new PeerTablePriv(); // default to unsorted priv->sortColumn = -1; @@ -160,6 +162,8 @@ QVariant PeerTableModel::data(const QModelIndex &index, int role) const if (role == Qt::DisplayRole) { switch(index.column()) { + case NetNodeId: + return rec->nodeStats.nodeid; case Address: return QString::fromStdString(rec->nodeStats.addrName); case Subversion: diff --git a/src/qt/peertablemodel.h b/src/qt/peertablemodel.h index a2aaaa5d24b94..a4f7bbdb3d708 100644 --- a/src/qt/peertablemodel.h +++ b/src/qt/peertablemodel.h @@ -52,9 +52,10 @@ class PeerTableModel : public QAbstractTableModel void stopAutoRefresh(); enum ColumnIndex { - Address = 0, - Subversion = 1, - Ping = 2 + NetNodeId = 0, + Address = 1, + Subversion = 2, + Ping = 3 }; /** @name Methods overridden from QAbstractTableModel diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index bcaa9164c91ba..e5720dd70e0cd 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -877,7 +877,7 @@ void RPCConsole::showBanTableContextMenu(const QPoint& point) void RPCConsole::disconnectSelectedNode() { // Get currently selected peer address - QString strNode = GUIUtil::getEntryData(ui->peerWidget, 0, PeerTableModel::Address); + QString strNode = GUIUtil::getEntryData(ui->peerWidget, 0, PeerTableModel::Address).toString(); // Find the node, disconnect it and clear the selected node if (CNode *bannedNode = FindNode(strNode.toStdString())) { bannedNode->fDisconnect = true; @@ -891,7 +891,7 @@ void RPCConsole::banSelectedNode(int bantime) return; // Get currently selected peer address - QString strNode = GUIUtil::getEntryData(ui->peerWidget, 0, PeerTableModel::Address); + QString strNode = GUIUtil::getEntryData(ui->peerWidget, 0, PeerTableModel::Address).toString(); // Find possible nodes, ban it and clear the selected node if (FindNode(strNode.toStdString())) { std::string nStr = strNode.toStdString(); @@ -915,7 +915,7 @@ void RPCConsole::unbanSelectedNode() return; // Get currently selected ban address - QString strNode = GUIUtil::getEntryData(ui->banlistWidget, 0, BanTableModel::Address); + QString strNode = GUIUtil::getEntryData(ui->banlistWidget, 0, BanTableModel::Address).toString(); CSubNet possibleSubnet; LookupSubNet(strNode.toStdString().c_str(), possibleSubnet); From d93b14dc5ddfb937b0cc18be425b9d048cefb66b Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Sat, 16 Apr 2016 00:13:15 -0400 Subject: [PATCH 0833/1802] net: move CBanDB and CAddrDB out of net.h/cpp This will eventually solve a circular dependency --- src/Makefile.am | 2 + src/addrdb.cpp | 218 ++++++++++++++++++++++++++++++++++++++++++++++++ src/addrdb.h | 102 ++++++++++++++++++++++ src/net.cpp | 209 ---------------------------------------------- src/net.h | 84 +------------------ 5 files changed, 323 insertions(+), 292 deletions(-) create mode 100644 src/addrdb.cpp create mode 100644 src/addrdb.h diff --git a/src/Makefile.am b/src/Makefile.am index 03fac5bf979ac..ebdddc87f54a2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -71,6 +71,7 @@ endif .PHONY: FORCE check-symbols check-security # bitcoin core # BITCOIN_CORE_H = \ + addrdb.h \ addrman.h \ base58.h \ bloom.h \ @@ -164,6 +165,7 @@ libbitcoin_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CP libbitcoin_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_server_a_SOURCES = \ addrman.cpp \ + addrdb.cpp \ bloom.cpp \ blockencodings.cpp \ chain.cpp \ diff --git a/src/addrdb.cpp b/src/addrdb.cpp new file mode 100644 index 0000000000000..ddf41f92de0ea --- /dev/null +++ b/src/addrdb.cpp @@ -0,0 +1,218 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "addrdb.h" + +#include "addrman.h" +#include "chainparams.h" +#include "clientversion.h" +#include "hash.h" +#include "random.h" +#include "streams.h" +#include "tinyformat.h" +#include "util.h" + +#include + +CBanDB::CBanDB() +{ + pathBanlist = GetDataDir() / "banlist.dat"; +} + +bool CBanDB::Write(const banmap_t& banSet) +{ + // Generate random temporary filename + unsigned short randv = 0; + GetRandBytes((unsigned char*)&randv, sizeof(randv)); + std::string tmpfn = strprintf("banlist.dat.%04x", randv); + + // serialize banlist, checksum data up to that point, then append csum + CDataStream ssBanlist(SER_DISK, CLIENT_VERSION); + ssBanlist << FLATDATA(Params().MessageStart()); + ssBanlist << banSet; + uint256 hash = Hash(ssBanlist.begin(), ssBanlist.end()); + ssBanlist << hash; + + // open temp output file, and associate with CAutoFile + boost::filesystem::path pathTmp = GetDataDir() / tmpfn; + FILE *file = fopen(pathTmp.string().c_str(), "wb"); + CAutoFile fileout(file, SER_DISK, CLIENT_VERSION); + if (fileout.IsNull()) + return error("%s: Failed to open file %s", __func__, pathTmp.string()); + + // Write and commit header, data + try { + fileout << ssBanlist; + } + catch (const std::exception& e) { + return error("%s: Serialize or I/O error - %s", __func__, e.what()); + } + FileCommit(fileout.Get()); + fileout.fclose(); + + // replace existing banlist.dat, if any, with new banlist.dat.XXXX + if (!RenameOver(pathTmp, pathBanlist)) + return error("%s: Rename-into-place failed", __func__); + + return true; +} + +bool CBanDB::Read(banmap_t& banSet) +{ + // open input file, and associate with CAutoFile + FILE *file = fopen(pathBanlist.string().c_str(), "rb"); + CAutoFile filein(file, SER_DISK, CLIENT_VERSION); + if (filein.IsNull()) + return error("%s: Failed to open file %s", __func__, pathBanlist.string()); + + // use file size to size memory buffer + uint64_t fileSize = boost::filesystem::file_size(pathBanlist); + uint64_t dataSize = 0; + // Don't try to resize to a negative number if file is small + if (fileSize >= sizeof(uint256)) + dataSize = fileSize - sizeof(uint256); + std::vector vchData; + vchData.resize(dataSize); + uint256 hashIn; + + // read data and checksum from file + try { + filein.read((char *)&vchData[0], dataSize); + filein >> hashIn; + } + catch (const std::exception& e) { + return error("%s: Deserialize or I/O error - %s", __func__, e.what()); + } + filein.fclose(); + + CDataStream ssBanlist(vchData, SER_DISK, CLIENT_VERSION); + + // verify stored checksum matches input data + uint256 hashTmp = Hash(ssBanlist.begin(), ssBanlist.end()); + if (hashIn != hashTmp) + return error("%s: Checksum mismatch, data corrupted", __func__); + + unsigned char pchMsgTmp[4]; + try { + // de-serialize file header (network specific magic number) and .. + ssBanlist >> FLATDATA(pchMsgTmp); + + // ... verify the network matches ours + if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp))) + return error("%s: Invalid network magic number", __func__); + + // de-serialize address data into one CAddrMan object + ssBanlist >> banSet; + } + catch (const std::exception& e) { + return error("%s: Deserialize or I/O error - %s", __func__, e.what()); + } + + return true; +} + +CAddrDB::CAddrDB() +{ + pathAddr = GetDataDir() / "peers.dat"; +} + +bool CAddrDB::Write(const CAddrMan& addr) +{ + // Generate random temporary filename + unsigned short randv = 0; + GetRandBytes((unsigned char*)&randv, sizeof(randv)); + std::string tmpfn = strprintf("peers.dat.%04x", randv); + + // serialize addresses, checksum data up to that point, then append csum + CDataStream ssPeers(SER_DISK, CLIENT_VERSION); + ssPeers << FLATDATA(Params().MessageStart()); + ssPeers << addr; + uint256 hash = Hash(ssPeers.begin(), ssPeers.end()); + ssPeers << hash; + + // open temp output file, and associate with CAutoFile + boost::filesystem::path pathTmp = GetDataDir() / tmpfn; + FILE *file = fopen(pathTmp.string().c_str(), "wb"); + CAutoFile fileout(file, SER_DISK, CLIENT_VERSION); + if (fileout.IsNull()) + return error("%s: Failed to open file %s", __func__, pathTmp.string()); + + // Write and commit header, data + try { + fileout << ssPeers; + } + catch (const std::exception& e) { + return error("%s: Serialize or I/O error - %s", __func__, e.what()); + } + FileCommit(fileout.Get()); + fileout.fclose(); + + // replace existing peers.dat, if any, with new peers.dat.XXXX + if (!RenameOver(pathTmp, pathAddr)) + return error("%s: Rename-into-place failed", __func__); + + return true; +} + +bool CAddrDB::Read(CAddrMan& addr) +{ + // open input file, and associate with CAutoFile + FILE *file = fopen(pathAddr.string().c_str(), "rb"); + CAutoFile filein(file, SER_DISK, CLIENT_VERSION); + if (filein.IsNull()) + return error("%s: Failed to open file %s", __func__, pathAddr.string()); + + // use file size to size memory buffer + uint64_t fileSize = boost::filesystem::file_size(pathAddr); + uint64_t dataSize = 0; + // Don't try to resize to a negative number if file is small + if (fileSize >= sizeof(uint256)) + dataSize = fileSize - sizeof(uint256); + std::vector vchData; + vchData.resize(dataSize); + uint256 hashIn; + + // read data and checksum from file + try { + filein.read((char *)&vchData[0], dataSize); + filein >> hashIn; + } + catch (const std::exception& e) { + return error("%s: Deserialize or I/O error - %s", __func__, e.what()); + } + filein.fclose(); + + CDataStream ssPeers(vchData, SER_DISK, CLIENT_VERSION); + + // verify stored checksum matches input data + uint256 hashTmp = Hash(ssPeers.begin(), ssPeers.end()); + if (hashIn != hashTmp) + return error("%s: Checksum mismatch, data corrupted", __func__); + + return Read(addr, ssPeers); +} + +bool CAddrDB::Read(CAddrMan& addr, CDataStream& ssPeers) +{ + unsigned char pchMsgTmp[4]; + try { + // de-serialize file header (network specific magic number) and .. + ssPeers >> FLATDATA(pchMsgTmp); + + // ... verify the network matches ours + if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp))) + return error("%s: Invalid network magic number", __func__); + + // de-serialize address data into one CAddrMan object + ssPeers >> addr; + } + catch (const std::exception& e) { + // de-serialization has failed, ensure addrman is left in a clean state + addr.Clear(); + return error("%s: Deserialize or I/O error - %s", __func__, e.what()); + } + + return true; +} diff --git a/src/addrdb.h b/src/addrdb.h new file mode 100644 index 0000000000000..3ffcfe3e17468 --- /dev/null +++ b/src/addrdb.h @@ -0,0 +1,102 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_ADDRDB_H +#define BITCOIN_ADDRDB_H + +#include "serialize.h" + +#include +#include +#include + +class CSubNet; +class CAddrMan; + +typedef enum BanReason +{ + BanReasonUnknown = 0, + BanReasonNodeMisbehaving = 1, + BanReasonManuallyAdded = 2 +} BanReason; + +class CBanEntry +{ +public: + static const int CURRENT_VERSION=1; + int nVersion; + int64_t nCreateTime; + int64_t nBanUntil; + uint8_t banReason; + + CBanEntry() + { + SetNull(); + } + + CBanEntry(int64_t nCreateTimeIn) + { + SetNull(); + nCreateTime = nCreateTimeIn; + } + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + READWRITE(this->nVersion); + nVersion = this->nVersion; + READWRITE(nCreateTime); + READWRITE(nBanUntil); + READWRITE(banReason); + } + + void SetNull() + { + nVersion = CBanEntry::CURRENT_VERSION; + nCreateTime = 0; + nBanUntil = 0; + banReason = BanReasonUnknown; + } + + std::string banReasonToString() + { + switch (banReason) { + case BanReasonNodeMisbehaving: + return "node misbehaving"; + case BanReasonManuallyAdded: + return "manually added"; + default: + return "unknown"; + } + } +}; + +typedef std::map banmap_t; + +/** Access to the (IP) address database (peers.dat) */ +class CAddrDB +{ +private: + boost::filesystem::path pathAddr; +public: + CAddrDB(); + bool Write(const CAddrMan& addr); + bool Read(CAddrMan& addr); + bool Read(CAddrMan& addr, CDataStream& ssPeers); +}; + +/** Access to the banlist database (banlist.dat) */ +class CBanDB +{ +private: + boost::filesystem::path pathBanlist; +public: + CBanDB(); + bool Write(const banmap_t& banSet); + bool Read(banmap_t& banSet); +}; + +#endif // BITCOIN_ADDRDB_H diff --git a/src/net.cpp b/src/net.cpp index c5b080f794096..cee149ee7ee06 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2356,114 +2356,6 @@ void CNode::Fuzz(int nChance) Fuzz(2); } -// -// CAddrDB -// - -CAddrDB::CAddrDB() -{ - pathAddr = GetDataDir() / "peers.dat"; -} - -bool CAddrDB::Write(const CAddrMan& addr) -{ - // Generate random temporary filename - unsigned short randv = 0; - GetRandBytes((unsigned char*)&randv, sizeof(randv)); - std::string tmpfn = strprintf("peers.dat.%04x", randv); - - // serialize addresses, checksum data up to that point, then append csum - CDataStream ssPeers(SER_DISK, CLIENT_VERSION); - ssPeers << FLATDATA(Params().MessageStart()); - ssPeers << addr; - uint256 hash = Hash(ssPeers.begin(), ssPeers.end()); - ssPeers << hash; - - // open temp output file, and associate with CAutoFile - boost::filesystem::path pathTmp = GetDataDir() / tmpfn; - FILE *file = fopen(pathTmp.string().c_str(), "wb"); - CAutoFile fileout(file, SER_DISK, CLIENT_VERSION); - if (fileout.IsNull()) - return error("%s: Failed to open file %s", __func__, pathTmp.string()); - - // Write and commit header, data - try { - fileout << ssPeers; - } - catch (const std::exception& e) { - return error("%s: Serialize or I/O error - %s", __func__, e.what()); - } - FileCommit(fileout.Get()); - fileout.fclose(); - - // replace existing peers.dat, if any, with new peers.dat.XXXX - if (!RenameOver(pathTmp, pathAddr)) - return error("%s: Rename-into-place failed", __func__); - - return true; -} - -bool CAddrDB::Read(CAddrMan& addr) -{ - // open input file, and associate with CAutoFile - FILE *file = fopen(pathAddr.string().c_str(), "rb"); - CAutoFile filein(file, SER_DISK, CLIENT_VERSION); - if (filein.IsNull()) - return error("%s: Failed to open file %s", __func__, pathAddr.string()); - - // use file size to size memory buffer - uint64_t fileSize = boost::filesystem::file_size(pathAddr); - uint64_t dataSize = 0; - // Don't try to resize to a negative number if file is small - if (fileSize >= sizeof(uint256)) - dataSize = fileSize - sizeof(uint256); - std::vector vchData; - vchData.resize(dataSize); - uint256 hashIn; - - // read data and checksum from file - try { - filein.read((char *)&vchData[0], dataSize); - filein >> hashIn; - } - catch (const std::exception& e) { - return error("%s: Deserialize or I/O error - %s", __func__, e.what()); - } - filein.fclose(); - - CDataStream ssPeers(vchData, SER_DISK, CLIENT_VERSION); - - // verify stored checksum matches input data - uint256 hashTmp = Hash(ssPeers.begin(), ssPeers.end()); - if (hashIn != hashTmp) - return error("%s: Checksum mismatch, data corrupted", __func__); - - return Read(addr, ssPeers); -} - -bool CAddrDB::Read(CAddrMan& addr, CDataStream& ssPeers) -{ - unsigned char pchMsgTmp[4]; - try { - // de-serialize file header (network specific magic number) and .. - ssPeers >> FLATDATA(pchMsgTmp); - - // ... verify the network matches ours - if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp))) - return error("%s: Invalid network magic number", __func__); - - // de-serialize address data into one CAddrMan object - ssPeers >> addr; - } - catch (const std::exception& e) { - // de-serialization has failed, ensure addrman is left in a clean state - addr.Clear(); - return error("%s: Deserialize or I/O error - %s", __func__, e.what()); - } - - return true; -} - unsigned int ReceiveFloodSize() { return 1000*GetArg("-maxreceivebuffer", DEFAULT_MAXRECEIVEBUFFER); } unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER); } @@ -2649,107 +2541,6 @@ void CNode::EndMessage(const char* pszCommand) UNLOCK_FUNCTION(cs_vSend) LEAVE_CRITICAL_SECTION(cs_vSend); } -// -// CBanDB -// - -CBanDB::CBanDB() -{ - pathBanlist = GetDataDir() / "banlist.dat"; -} - -bool CBanDB::Write(const banmap_t& banSet) -{ - // Generate random temporary filename - unsigned short randv = 0; - GetRandBytes((unsigned char*)&randv, sizeof(randv)); - std::string tmpfn = strprintf("banlist.dat.%04x", randv); - - // serialize banlist, checksum data up to that point, then append csum - CDataStream ssBanlist(SER_DISK, CLIENT_VERSION); - ssBanlist << FLATDATA(Params().MessageStart()); - ssBanlist << banSet; - uint256 hash = Hash(ssBanlist.begin(), ssBanlist.end()); - ssBanlist << hash; - - // open temp output file, and associate with CAutoFile - boost::filesystem::path pathTmp = GetDataDir() / tmpfn; - FILE *file = fopen(pathTmp.string().c_str(), "wb"); - CAutoFile fileout(file, SER_DISK, CLIENT_VERSION); - if (fileout.IsNull()) - return error("%s: Failed to open file %s", __func__, pathTmp.string()); - - // Write and commit header, data - try { - fileout << ssBanlist; - } - catch (const std::exception& e) { - return error("%s: Serialize or I/O error - %s", __func__, e.what()); - } - FileCommit(fileout.Get()); - fileout.fclose(); - - // replace existing banlist.dat, if any, with new banlist.dat.XXXX - if (!RenameOver(pathTmp, pathBanlist)) - return error("%s: Rename-into-place failed", __func__); - - return true; -} - -bool CBanDB::Read(banmap_t& banSet) -{ - // open input file, and associate with CAutoFile - FILE *file = fopen(pathBanlist.string().c_str(), "rb"); - CAutoFile filein(file, SER_DISK, CLIENT_VERSION); - if (filein.IsNull()) - return error("%s: Failed to open file %s", __func__, pathBanlist.string()); - - // use file size to size memory buffer - uint64_t fileSize = boost::filesystem::file_size(pathBanlist); - uint64_t dataSize = 0; - // Don't try to resize to a negative number if file is small - if (fileSize >= sizeof(uint256)) - dataSize = fileSize - sizeof(uint256); - std::vector vchData; - vchData.resize(dataSize); - uint256 hashIn; - - // read data and checksum from file - try { - filein.read((char *)&vchData[0], dataSize); - filein >> hashIn; - } - catch (const std::exception& e) { - return error("%s: Deserialize or I/O error - %s", __func__, e.what()); - } - filein.fclose(); - - CDataStream ssBanlist(vchData, SER_DISK, CLIENT_VERSION); - - // verify stored checksum matches input data - uint256 hashTmp = Hash(ssBanlist.begin(), ssBanlist.end()); - if (hashIn != hashTmp) - return error("%s: Checksum mismatch, data corrupted", __func__); - - unsigned char pchMsgTmp[4]; - try { - // de-serialize file header (network specific magic number) and .. - ssBanlist >> FLATDATA(pchMsgTmp); - - // ... verify the network matches ours - if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp))) - return error("%s: Invalid network magic number", __func__); - - // de-serialize address data into one CAddrMan object - ssBanlist >> banSet; - } - catch (const std::exception& e) { - return error("%s: Deserialize or I/O error - %s", __func__, e.what()); - } - - return true; -} - int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds) { return nNow + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5); } diff --git a/src/net.h b/src/net.h index b9cc81e4e9c50..0d1c62e428fb6 100644 --- a/src/net.h +++ b/src/net.h @@ -6,6 +6,7 @@ #ifndef BITCOIN_NET_H #define BITCOIN_NET_H +#include "addrdb.h" #include "amount.h" #include "bloom.h" #include "compat.h" @@ -256,67 +257,6 @@ class CNetMessage { }; -typedef enum BanReason -{ - BanReasonUnknown = 0, - BanReasonNodeMisbehaving = 1, - BanReasonManuallyAdded = 2 -} BanReason; - -class CBanEntry -{ -public: - static const int CURRENT_VERSION=1; - int nVersion; - int64_t nCreateTime; - int64_t nBanUntil; - uint8_t banReason; - - CBanEntry() - { - SetNull(); - } - - CBanEntry(int64_t nCreateTimeIn) - { - SetNull(); - nCreateTime = nCreateTimeIn; - } - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(this->nVersion); - nVersion = this->nVersion; - READWRITE(nCreateTime); - READWRITE(nBanUntil); - READWRITE(banReason); - } - - void SetNull() - { - nVersion = CBanEntry::CURRENT_VERSION; - nCreateTime = 0; - nBanUntil = 0; - banReason = BanReasonUnknown; - } - - std::string banReasonToString() - { - switch (banReason) { - case BanReasonNodeMisbehaving: - return "node misbehaving"; - case BanReasonManuallyAdded: - return "manually added"; - default: - return "unknown"; - } - } -}; - -typedef std::map banmap_t; - /** Information about a peer */ class CNode { @@ -819,28 +759,6 @@ class CNode class CTransaction; void RelayTransaction(const CTransaction& tx); -/** Access to the (IP) address database (peers.dat) */ -class CAddrDB -{ -private: - boost::filesystem::path pathAddr; -public: - CAddrDB(); - bool Write(const CAddrMan& addr); - bool Read(CAddrMan& addr); - bool Read(CAddrMan& addr, CDataStream& ssPeers); -}; - -/** Access to the banlist database (banlist.dat) */ -class CBanDB -{ -private: - boost::filesystem::path pathBanlist; -public: - CBanDB(); - bool Write(const banmap_t& banSet); - bool Read(banmap_t& banSet); -}; /** Return a timestamp in the future (in microseconds) for exponentially distributed events. */ int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds); From cd16f48028f54327d4afba9c1f91f25d0b072aa5 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Sat, 16 Apr 2016 14:47:18 -0400 Subject: [PATCH 0834/1802] net: Create CConnman to encapsulate p2p connections --- src/addrdb.h | 1 + src/init.cpp | 14 ++++- src/net.cpp | 113 +++++++++++++++++++++----------------- src/net.h | 30 +++++++++- src/test/test_bitcoin.cpp | 6 ++ src/test/test_bitcoin.h | 2 + 6 files changed, 112 insertions(+), 54 deletions(-) diff --git a/src/addrdb.h b/src/addrdb.h index 3ffcfe3e17468..d8c66d872bb18 100644 --- a/src/addrdb.h +++ b/src/addrdb.h @@ -14,6 +14,7 @@ class CSubNet; class CAddrMan; +class CDataStream; typedef enum BanReason { diff --git a/src/init.cpp b/src/init.cpp index 27843fa882318..6aaa7bfc5db00 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -42,6 +42,7 @@ #endif #include #include +#include #ifndef WIN32 #include @@ -70,6 +71,7 @@ static const bool DEFAULT_REST_ENABLE = false; static const bool DEFAULT_DISABLE_SAFEMODE = false; static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false; +std::unique_ptr g_connman; #if ENABLE_ZMQ static CZMQNotificationInterface* pzmqNotificationInterface = NULL; @@ -197,7 +199,9 @@ void Shutdown() if (pwalletMain) pwalletMain->Flush(false); #endif - StopNode(); + StopNode(*g_connman); + g_connman.reset(); + StopTorControl(); UnregisterNodeSignals(GetNodeSignals()); @@ -1101,6 +1105,10 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) #endif // ENABLE_WALLET // ********************************************************* Step 6: network initialization + assert(!g_connman); + g_connman = std::unique_ptr(new CConnman()); + CConnman& connman = *g_connman; + RegisterNodeSignals(GetNodeSignals()); // sanitize comments per BIP-0014, format user agent and check total size @@ -1497,7 +1505,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION)) StartTorControl(threadGroup, scheduler); - StartNode(threadGroup, scheduler); + std::string strNodeError; + if(!StartNode(connman, threadGroup, scheduler, strNodeError)) + return InitError(strNodeError); // ********************************************************* Step 12: finished diff --git a/src/net.cpp b/src/net.cpp index cee149ee7ee06..6177dc04ff4c1 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -65,13 +65,6 @@ namespace { const int MAX_OUTBOUND_CONNECTIONS = 8; const int MAX_FEELER_CONNECTIONS = 1; - - struct ListenSocket { - SOCKET socket; - bool whitelisted; - - ListenSocket(SOCKET _socket, bool _whitelisted) : socket(_socket), whitelisted(_whitelisted) {} - }; } const static std::string NET_MESSAGE_COMMAND_OTHER = "*other*"; @@ -1015,7 +1008,7 @@ static bool AttemptToEvictConnection() { return false; } -static void AcceptConnection(const ListenSocket& hListenSocket) { +void CConnman::AcceptConnection(const ListenSocket& hListenSocket) { struct sockaddr_storage sockaddr; socklen_t len = sizeof(sockaddr); SOCKET hSocket = accept(hListenSocket.socket, (struct sockaddr*)&sockaddr, &len); @@ -1089,7 +1082,7 @@ static void AcceptConnection(const ListenSocket& hListenSocket) { } } -void ThreadSocketHandler() +void CConnman::ThreadSocketHandler() { unsigned int nPrevNodeCount = 0; while (true) @@ -1497,7 +1490,7 @@ static std::string GetDNSHost(const CDNSSeedData& data, ServiceFlags* requiredSe } -void ThreadDNSAddressSeed() +void CConnman::ThreadDNSAddressSeed() { // goal: only query DNS seeds if address need is acute if ((addrman.size() > 0) && @@ -1577,7 +1570,7 @@ void DumpData() DumpBanlist(); } -void static ProcessOneShot() +void CConnman::ProcessOneShot() { std::string strDest; { @@ -1595,7 +1588,7 @@ void static ProcessOneShot() } } -void ThreadOpenConnections() +void CConnman::ThreadOpenConnections() { // Connect to specific addresses if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0) @@ -1791,7 +1784,7 @@ std::vector GetAddedNodeInfo() return ret; } -void ThreadOpenAddedConnections() +void CConnman::ThreadOpenAddedConnections() { { LOCK(cs_vAddedNodes); @@ -1848,7 +1841,7 @@ bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSem } -void ThreadMessageHandler() +void CConnman::ThreadMessageHandler() { boost::mutex condition_mutex; boost::unique_lock lock(condition_mutex); @@ -2064,7 +2057,11 @@ void static Discover(boost::thread_group& threadGroup) #endif } -void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler) +CConnman::CConnman() +{ +} + +bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler& scheduler, std::string& strNodeError) { uiInterface.InitMessage(_("Loading addresses...")); // Load addresses from peers.dat @@ -2102,6 +2099,17 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler) fAddressesInitialized = true; + Discover(threadGroup); + + bool ret = connman.Start(threadGroup, strNodeError); + + // Dump network addresses + scheduler.scheduleEvery(DumpData, DUMP_ADDRESSES_INTERVAL); + return ret; +} + +bool CConnman::Start(boost::thread_group& threadGroup, std::string& strNodeError) +{ if (semOutbound == NULL) { // initialize semaphore int nMaxOutbound = std::min((MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS), nMaxConnections); @@ -2114,8 +2122,6 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler) pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService(local, 0), nLocalServices)); } - Discover(threadGroup); - // // Start threads // @@ -2123,34 +2129,30 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler) if (!GetBoolArg("-dnsseed", true)) LogPrintf("DNS seeding disabled\n"); else - threadGroup.create_thread(boost::bind(&TraceThread, "dnsseed", &ThreadDNSAddressSeed)); + threadGroup.create_thread(boost::bind(&TraceThread >, "dnsseed", boost::function(boost::bind(&CConnman::ThreadDNSAddressSeed, this)))); // Map ports with UPnP MapPort(GetBoolArg("-upnp", DEFAULT_UPNP)); // Send and receive from sockets, accept connections - threadGroup.create_thread(boost::bind(&TraceThread, "net", &ThreadSocketHandler)); + threadGroup.create_thread(boost::bind(&TraceThread >, "net", boost::function(boost::bind(&CConnman::ThreadSocketHandler, this)))); // Initiate outbound connections from -addnode - threadGroup.create_thread(boost::bind(&TraceThread, "addcon", &ThreadOpenAddedConnections)); + threadGroup.create_thread(boost::bind(&TraceThread >, "addcon", boost::function(boost::bind(&CConnman::ThreadOpenAddedConnections, this)))); // Initiate outbound connections - threadGroup.create_thread(boost::bind(&TraceThread, "opencon", &ThreadOpenConnections)); + threadGroup.create_thread(boost::bind(&TraceThread >, "opencon", boost::function(boost::bind(&CConnman::ThreadOpenConnections, this)))); // Process messages - threadGroup.create_thread(boost::bind(&TraceThread, "msghand", &ThreadMessageHandler)); + threadGroup.create_thread(boost::bind(&TraceThread >, "msghand", boost::function(boost::bind(&CConnman::ThreadMessageHandler, this)))); - // Dump network addresses - scheduler.scheduleEvery(&DumpData, DUMP_ADDRESSES_INTERVAL); + return true; } -bool StopNode() +bool StopNode(CConnman& connman) { LogPrintf("StopNode()\n"); MapPort(false); - if (semOutbound) - for (int i=0; i<(MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS); i++) - semOutbound->post(); if (fAddressesInitialized) { @@ -2158,6 +2160,7 @@ bool StopNode() fAddressesInitialized = false; } + connman.Stop(); return true; } @@ -2168,28 +2171,6 @@ class CNetCleanup ~CNetCleanup() { - // Close sockets - BOOST_FOREACH(CNode* pnode, vNodes) - if (pnode->hSocket != INVALID_SOCKET) - CloseSocket(pnode->hSocket); - BOOST_FOREACH(ListenSocket& hListenSocket, vhListenSocket) - if (hListenSocket.socket != INVALID_SOCKET) - if (!CloseSocket(hListenSocket.socket)) - LogPrintf("CloseSocket(hListenSocket) failed with error %s\n", NetworkErrorString(WSAGetLastError())); - - // clean up some globals (to help leak detection) - BOOST_FOREACH(CNode *pnode, vNodes) - delete pnode; - BOOST_FOREACH(CNode *pnode, vNodesDisconnected) - delete pnode; - vNodes.clear(); - vNodesDisconnected.clear(); - vhListenSocket.clear(); - delete semOutbound; - semOutbound = NULL; - delete pnodeLocalHost; - pnodeLocalHost = NULL; - #ifdef WIN32 // Shutdown Windows Sockets WSACleanup(); @@ -2198,6 +2179,38 @@ class CNetCleanup } instance_of_cnetcleanup; +void CConnman::Stop() +{ + if (semOutbound) + for (int i=0; i<(MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS); i++) + semOutbound->post(); + + // Close sockets + BOOST_FOREACH(CNode* pnode, vNodes) + if (pnode->hSocket != INVALID_SOCKET) + CloseSocket(pnode->hSocket); + BOOST_FOREACH(ListenSocket& hListenSocket, vhListenSocket) + if (hListenSocket.socket != INVALID_SOCKET) + if (!CloseSocket(hListenSocket.socket)) + LogPrintf("CloseSocket(hListenSocket) failed with error %s\n", NetworkErrorString(WSAGetLastError())); + + // clean up some globals (to help leak detection) + BOOST_FOREACH(CNode *pnode, vNodes) + delete pnode; + BOOST_FOREACH(CNode *pnode, vNodesDisconnected) + delete pnode; + vNodes.clear(); + vNodesDisconnected.clear(); + vhListenSocket.clear(); + delete semOutbound; + semOutbound = NULL; + delete pnodeLocalHost; + pnodeLocalHost = NULL; +} + +CConnman::~CConnman() +{ +} void RelayTransaction(const CTransaction& tx) { diff --git a/src/net.h b/src/net.h index 0d1c62e428fb6..7f212f233c758 100644 --- a/src/net.h +++ b/src/net.h @@ -21,6 +21,7 @@ #include #include #include +#include #ifndef WIN32 #include @@ -93,11 +94,36 @@ CNode* FindNode(const std::string& addrName); CNode* FindNode(const CService& ip); CNode* FindNode(const NodeId id); //TODO: Remove this bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false, bool fFeeler = false); + +struct ListenSocket { + SOCKET socket; + bool whitelisted; + + ListenSocket(SOCKET socket_, bool whitelisted_) : socket(socket_), whitelisted(whitelisted_) {} +}; + +class CConnman +{ +public: + CConnman(); + ~CConnman(); + bool Start(boost::thread_group& threadGroup, std::string& strNodeError); + void Stop(); +private: + void ThreadOpenAddedConnections(); + void ProcessOneShot(); + void ThreadOpenConnections(); + void ThreadMessageHandler(); + void AcceptConnection(const ListenSocket& hListenSocket); + void ThreadSocketHandler(); + void ThreadDNSAddressSeed(); +}; +extern std::unique_ptr g_connman; void MapPort(bool fUseUPnP); unsigned short GetListenPort(); bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); -void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler); -bool StopNode(); +bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler& scheduler, std::string& strNodeError); +bool StopNode(CConnman& connman); void SocketSendData(CNode *pnode); struct CombinerAll diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index 056f2982cf1eb..ed74418e3426d 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -26,6 +26,8 @@ #include #include +std::unique_ptr g_connman; + extern bool fPrintToConsole; extern void noui_connect(); @@ -43,6 +45,7 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName) BasicTestingSetup::~BasicTestingSetup() { ECC_Stop(); + g_connman.reset(); } TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(chainName) @@ -50,6 +53,7 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha const CChainParams& chainparams = Params(); // Ideally we'd move all the RPC tests to the functional testing framework // instead of unit tests, but for now we need these here. + RegisterAllCoreRPCCommands(tableRPC); ClearDatadirCache(); pathTemp = GetTempPath() / strprintf("test_bitcoin_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000))); @@ -68,6 +72,8 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha nScriptCheckThreads = 3; for (int i=0; i < nScriptCheckThreads-1; i++) threadGroup.create_thread(&ThreadScriptCheck); + g_connman = std::unique_ptr(new CConnman()); + connman = g_connman.get(); RegisterNodeSignals(GetNodeSignals()); } diff --git a/src/test/test_bitcoin.h b/src/test/test_bitcoin.h index bc0d2fe316aa5..9819a7097dc75 100644 --- a/src/test/test_bitcoin.h +++ b/src/test/test_bitcoin.h @@ -27,10 +27,12 @@ struct BasicTestingSetup { /** Testing setup that configures a complete environment. * Included are data directory, coins database, script check threads setup. */ +class CConnman; struct TestingSetup: public BasicTestingSetup { CCoinsViewDB *pcoinsdbview; boost::filesystem::path pathTemp; boost::thread_group threadGroup; + CConnman* connman; TestingSetup(const std::string& chainName = CBaseChainParams::MAIN); ~TestingSetup(); From d7349ca50d000573d60064d4b295be308357d58e Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 26 May 2016 13:10:55 -0400 Subject: [PATCH 0835/1802] net: Add rpc error for missing/disabled p2p functionality --- src/rpc/protocol.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/rpc/protocol.h b/src/rpc/protocol.h index 988e0fc5facb9..1d2ef0e41e67e 100644 --- a/src/rpc/protocol.h +++ b/src/rpc/protocol.h @@ -63,6 +63,7 @@ enum RPCErrorCode RPC_CLIENT_NODE_NOT_ADDED = -24, //!< Node has not been added before RPC_CLIENT_NODE_NOT_CONNECTED = -29, //!< Node to disconnect not found in connected nodes RPC_CLIENT_INVALID_IP_OR_SUBNET = -30, //!< Invalid IP/Subnet + RPC_CLIENT_P2P_DISABLED = -31, //!< No valid connection manager instance found //! Wallet errors RPC_WALLET_ERROR = -4, //!< Unspecified problem with wallet (key not found etc.) From 8d58c4d81f18e9a51d11ee354434cf55d03a4add Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 26 May 2016 14:26:01 -0400 Subject: [PATCH 0836/1802] net: Pass CConnman around as needed --- src/main.cpp | 22 +++++++++++----------- src/main.h | 10 ++++++---- src/net.cpp | 4 ++-- src/net.h | 4 ++-- src/rpc/blockchain.cpp | 4 ++-- src/rpc/mining.cpp | 4 ++-- src/test/DoS_tests.cpp | 14 +++++++------- src/test/miner_tests.cpp | 2 +- src/test/test_bitcoin.cpp | 2 +- 9 files changed, 34 insertions(+), 32 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 4b42afb561472..32859ebc26388 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3016,7 +3016,7 @@ static void NotifyHeaderTip() { * or an activated best chain. pblock is either NULL or a pointer to a block * that is already loaded (to avoid loading it again from disk). */ -bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, const CBlock *pblock) { +bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, const CBlock *pblock, CConnman* connman) { CBlockIndex *pindexMostWork = NULL; CBlockIndex *pindexNewTip = NULL; do { @@ -3731,7 +3731,7 @@ static bool AcceptBlock(const CBlock& block, CValidationState& state, const CCha return true; } -bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp) +bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp, CConnman* connman) { { LOCK(cs_main); @@ -3753,7 +3753,7 @@ bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, C NotifyHeaderTip(); - if (!ActivateBestChain(state, chainparams, pblock)) + if (!ActivateBestChain(state, chainparams, pblock, connman)) return error("%s: ActivateBestChain failed", __func__); return true; @@ -4891,7 +4891,7 @@ uint32_t GetFetchFlags(CNode* pfrom, CBlockIndex* pprev, const Consensus::Params return nFetchFlags; } -bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams) +bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CConnman& connman) { LogPrint("net", "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->id); if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0) @@ -5680,7 +5680,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, txn.blockhash = cmpctblock.header.GetHash(); CDataStream blockTxnMsg(SER_NETWORK, PROTOCOL_VERSION); blockTxnMsg << txn; - return ProcessMessage(pfrom, NetMsgType::BLOCKTXN, blockTxnMsg, nTimeReceived, chainparams); + return ProcessMessage(pfrom, NetMsgType::BLOCKTXN, blockTxnMsg, nTimeReceived, chainparams, connman); } else { req.blockhash = pindex->GetBlockHash(); pfrom->PushMessage(NetMsgType::GETBLOCKTXN, req); @@ -5701,7 +5701,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, headers.push_back(cmpctblock.header); CDataStream vHeadersMsg(SER_NETWORK, PROTOCOL_VERSION); vHeadersMsg << headers; - return ProcessMessage(pfrom, NetMsgType::HEADERS, vHeadersMsg, nTimeReceived, chainparams); + return ProcessMessage(pfrom, NetMsgType::HEADERS, vHeadersMsg, nTimeReceived, chainparams, connman); } } @@ -5737,7 +5737,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, pfrom->PushMessage(NetMsgType::GETDATA, invs); } else { CValidationState state; - ProcessNewBlock(state, chainparams, pfrom, &block, false, NULL); + ProcessNewBlock(state, chainparams, pfrom, &block, false, NULL, &connman); int nDoS; if (state.IsInvalid(nDoS)) { assert (state.GetRejectCode() < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes @@ -5913,7 +5913,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // Such an unrequested block may still be processed, subject to the // conditions in AcceptBlock(). bool forceProcessing = pfrom->fWhitelisted && !IsInitialBlockDownload(); - ProcessNewBlock(state, chainparams, pfrom, &block, forceProcessing, NULL); + ProcessNewBlock(state, chainparams, pfrom, &block, forceProcessing, NULL, &connman); int nDoS; if (state.IsInvalid(nDoS)) { assert (state.GetRejectCode() < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes @@ -6163,7 +6163,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } // requires LOCK(cs_vRecvMsg) -bool ProcessMessages(CNode* pfrom) +bool ProcessMessages(CNode* pfrom, CConnman& connman) { const CChainParams& chainparams = Params(); //if (fDebug) @@ -6240,7 +6240,7 @@ bool ProcessMessages(CNode* pfrom) bool fRet = false; try { - fRet = ProcessMessage(pfrom, strCommand, vRecv, msg.nTime, chainparams); + fRet = ProcessMessage(pfrom, strCommand, vRecv, msg.nTime, chainparams, connman); boost::this_thread::interruption_point(); } catch (const std::ios_base::failure& e) @@ -6305,7 +6305,7 @@ class CompareInvMempoolOrder } }; -bool SendMessages(CNode* pto) +bool SendMessages(CNode* pto, CConnman& connman) { const Consensus::Params& consensusParams = Params().GetConsensus(); { diff --git a/src/main.h b/src/main.h index 18d674612f97e..2646d8f86b0a3 100644 --- a/src/main.h +++ b/src/main.h @@ -34,6 +34,7 @@ class CBlockTreeDB; class CBloomFilter; class CChainParams; class CInv; +class CConnman; class CScriptCheck; class CTxMemPool; class CValidationInterface; @@ -222,7 +223,7 @@ void UnregisterNodeSignals(CNodeSignals& nodeSignals); * @param[out] dbp The already known disk position of pblock, or NULL if not yet stored. * @return True if state.IsValid() */ -bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp); +bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp, CConnman* connman); /** Check whether enough disk space is available for an incoming block */ bool CheckDiskSpace(uint64_t nAdditionalBytes = 0); /** Open a block file (blk?????.dat) */ @@ -240,13 +241,14 @@ bool LoadBlockIndex(); /** Unload database information */ void UnloadBlockIndex(); /** Process protocol messages received from a given node */ -bool ProcessMessages(CNode* pfrom); +bool ProcessMessages(CNode* pfrom, CConnman& connman); /** * Send queued protocol messages to be sent to a give node. * * @param[in] pto The node which we are sending messages to. + * @param[in] connman The connection manager for that node. */ -bool SendMessages(CNode* pto); +bool SendMessages(CNode* pto, CConnman& connman); /** Run an instance of the script checking thread */ void ThreadScriptCheck(); /** Check whether we are doing an initial block download (synchronizing from disk or network) */ @@ -262,7 +264,7 @@ std::string GetWarnings(const std::string& strFor); /** Retrieve a transaction (from memory pool, or from disk, if possible) */ bool GetTransaction(const uint256 &hash, CTransaction &tx, const Consensus::Params& params, uint256 &hashBlock, bool fAllowSlow = false); /** Find the best known block, and make it the tip of the block chain */ -bool ActivateBestChain(CValidationState& state, const CChainParams& chainparams, const CBlock* pblock = NULL); +bool ActivateBestChain(CValidationState& state, const CChainParams& chainparams, const CBlock* pblock = NULL, CConnman* connman = NULL); CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams); /** diff --git a/src/net.cpp b/src/net.cpp index 6177dc04ff4c1..b99989b289eb3 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1869,7 +1869,7 @@ void CConnman::ThreadMessageHandler() TRY_LOCK(pnode->cs_vRecvMsg, lockRecv); if (lockRecv) { - if (!GetNodeSignals().ProcessMessages(pnode)) + if (!GetNodeSignals().ProcessMessages(pnode, *this)) pnode->CloseSocketDisconnect(); if (pnode->nSendSize < SendBufferSize()) @@ -1887,7 +1887,7 @@ void CConnman::ThreadMessageHandler() { TRY_LOCK(pnode->cs_vSend, lockSend); if (lockSend) - GetNodeSignals().SendMessages(pnode); + GetNodeSignals().SendMessages(pnode, *this); } boost::this_thread::interruption_point(); } diff --git a/src/net.h b/src/net.h index 7f212f233c758..d2a38e7dc4ff9 100644 --- a/src/net.h +++ b/src/net.h @@ -145,8 +145,8 @@ struct CombinerAll struct CNodeSignals { boost::signals2::signal GetHeight; - boost::signals2::signal ProcessMessages; - boost::signals2::signal SendMessages; + boost::signals2::signal ProcessMessages; + boost::signals2::signal SendMessages; boost::signals2::signal InitializeNode; boost::signals2::signal FinalizeNode; }; diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index b90410017b692..d600383c4bc18 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1133,7 +1133,7 @@ UniValue invalidateblock(const UniValue& params, bool fHelp) } if (state.IsValid()) { - ActivateBestChain(state, Params()); + ActivateBestChain(state, Params(), NULL, g_connman.get()); } if (!state.IsValid()) { @@ -1171,7 +1171,7 @@ UniValue reconsiderblock(const UniValue& params, bool fHelp) } CValidationState state; - ActivateBestChain(state, Params()); + ActivateBestChain(state, Params(), NULL, g_connman.get()); if (!state.IsValid()) { throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 14183c8e826f5..63ecf49ecd697 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -131,7 +131,7 @@ UniValue generateBlocks(boost::shared_ptr coinbaseScript, int nG continue; } CValidationState state; - if (!ProcessNewBlock(state, Params(), NULL, pblock, true, NULL)) + if (!ProcessNewBlock(state, Params(), NULL, pblock, true, NULL, g_connman.get())) throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted"); ++nHeight; blockHashes.push_back(pblock->GetHash().GetHex()); @@ -754,7 +754,7 @@ UniValue submitblock(const UniValue& params, bool fHelp) CValidationState state; submitblock_StateCatcher sc(block.GetHash()); RegisterValidationInterface(&sc); - bool fAccepted = ProcessNewBlock(state, Params(), NULL, &block, true, NULL); + bool fAccepted = ProcessNewBlock(state, Params(), NULL, &block, true, NULL, g_connman.get()); UnregisterValidationInterface(&sc); if (fBlockPresent) { diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index a8c5f95ace4af..10529cda9e6bc 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -49,7 +49,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning) CNode dummyNode1(INVALID_SOCKET, addr1, "", true); dummyNode1.nVersion = 1; Misbehaving(dummyNode1.GetId(), 100); // Should get banned - SendMessages(&dummyNode1); + SendMessages(&dummyNode1, *connman); BOOST_CHECK(CNode::IsBanned(addr1)); BOOST_CHECK(!CNode::IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned @@ -57,11 +57,11 @@ BOOST_AUTO_TEST_CASE(DoS_banning) CNode dummyNode2(INVALID_SOCKET, addr2, "", true); dummyNode2.nVersion = 1; Misbehaving(dummyNode2.GetId(), 50); - SendMessages(&dummyNode2); + SendMessages(&dummyNode2, *connman); BOOST_CHECK(!CNode::IsBanned(addr2)); // 2 not banned yet... BOOST_CHECK(CNode::IsBanned(addr1)); // ... but 1 still should be Misbehaving(dummyNode2.GetId(), 50); - SendMessages(&dummyNode2); + SendMessages(&dummyNode2, *connman); BOOST_CHECK(CNode::IsBanned(addr2)); } @@ -73,13 +73,13 @@ BOOST_AUTO_TEST_CASE(DoS_banscore) CNode dummyNode1(INVALID_SOCKET, addr1, "", true); dummyNode1.nVersion = 1; Misbehaving(dummyNode1.GetId(), 100); - SendMessages(&dummyNode1); + SendMessages(&dummyNode1, *connman); BOOST_CHECK(!CNode::IsBanned(addr1)); Misbehaving(dummyNode1.GetId(), 10); - SendMessages(&dummyNode1); + SendMessages(&dummyNode1, *connman); BOOST_CHECK(!CNode::IsBanned(addr1)); Misbehaving(dummyNode1.GetId(), 1); - SendMessages(&dummyNode1); + SendMessages(&dummyNode1, *connman); BOOST_CHECK(CNode::IsBanned(addr1)); mapArgs.erase("-banscore"); } @@ -95,7 +95,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) dummyNode.nVersion = 1; Misbehaving(dummyNode.GetId(), 100); - SendMessages(&dummyNode); + SendMessages(&dummyNode, *connman); BOOST_CHECK(CNode::IsBanned(addr)); SetMockTime(nStartTime+60*60); diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 15fceb963a59f..d3aa2364d1f7b 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -222,7 +222,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) pblock->hashMerkleRoot = BlockMerkleRoot(*pblock); pblock->nNonce = blockinfo[i].nonce; CValidationState state; - BOOST_CHECK(ProcessNewBlock(state, chainparams, NULL, pblock, true, NULL)); + BOOST_CHECK(ProcessNewBlock(state, chainparams, NULL, pblock, true, NULL, connman)); BOOST_CHECK(state.IsValid()); pblock->hashPrevBlock = pblock->GetHash(); } diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index ed74418e3426d..b1ceef4f64d07 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -124,7 +124,7 @@ TestChain100Setup::CreateAndProcessBlock(const std::vector& while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce; CValidationState state; - ProcessNewBlock(state, chainparams, NULL, &block, true, NULL); + ProcessNewBlock(state, chainparams, NULL, &block, true, NULL, connman); CBlock result = block; delete pblocktemplate; From 5b446dd5b11d4f403554bc2dd5a7a94c7d20422a Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 24 May 2016 20:56:17 -0400 Subject: [PATCH 0837/1802] net: Pass CConnection to wallet rather than using the global --- src/main.cpp | 2 +- src/qt/walletmodel.cpp | 2 +- src/validationinterface.cpp | 4 ++-- src/validationinterface.h | 5 +++-- src/wallet/rpcwallet.cpp | 15 ++++++++++++--- src/wallet/wallet.cpp | 14 +++++++------- src/wallet/wallet.h | 8 ++++---- 7 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 32859ebc26388..4dc9d71eea011 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6431,7 +6431,7 @@ bool SendMessages(CNode* pto, CConnman& connman) // transactions become unconfirmed and spams other nodes. if (!fReindex && !fImporting && !IsInitialBlockDownload()) { - GetMainSignals().Broadcast(nTimeBestReceived); + GetMainSignals().Broadcast(nTimeBestReceived, &connman); } // diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index ae7efc7a0d40b..73851e97fc1f1 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -328,7 +328,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran } CReserveKey *keyChange = transaction.getPossibleKeyChange(); - if(!wallet->CommitTransaction(*newTx, *keyChange)) + if(!wallet->CommitTransaction(*newTx, *keyChange, g_connman.get())) return TransactionCommitFailed; CTransaction* t = (CTransaction*)newTx; diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index cf1d6ca08699a..6ddf37658d854 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -18,7 +18,7 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) { g_signals.UpdatedTransaction.connect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1)); g_signals.SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1)); g_signals.Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1)); - g_signals.Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1)); + g_signals.Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2)); g_signals.BlockChecked.connect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2)); g_signals.ScriptForMining.connect(boost::bind(&CValidationInterface::GetScriptForMining, pwalletIn, _1)); g_signals.BlockFound.connect(boost::bind(&CValidationInterface::ResetRequestCount, pwalletIn, _1)); @@ -28,7 +28,7 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn) { g_signals.BlockFound.disconnect(boost::bind(&CValidationInterface::ResetRequestCount, pwalletIn, _1)); g_signals.ScriptForMining.disconnect(boost::bind(&CValidationInterface::GetScriptForMining, pwalletIn, _1)); g_signals.BlockChecked.disconnect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2)); - g_signals.Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1)); + g_signals.Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2)); g_signals.Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1)); g_signals.SetBestChain.disconnect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1)); g_signals.UpdatedTransaction.disconnect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1)); diff --git a/src/validationinterface.h b/src/validationinterface.h index 094b1cfe26672..0c91ec8308eed 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -13,6 +13,7 @@ class CBlock; class CBlockIndex; struct CBlockLocator; class CBlockIndex; +class CConnman; class CReserveScript; class CTransaction; class CValidationInterface; @@ -37,7 +38,7 @@ class CValidationInterface { virtual void SetBestChain(const CBlockLocator &locator) {} virtual void UpdatedTransaction(const uint256 &hash) {} virtual void Inventory(const uint256 &hash) {} - virtual void ResendWalletTransactions(int64_t nBestBlockTime) {} + virtual void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) {} virtual void BlockChecked(const CBlock&, const CValidationState&) {} virtual void GetScriptForMining(boost::shared_ptr&) {}; virtual void ResetRequestCount(const uint256 &hash) {}; @@ -58,7 +59,7 @@ struct CMainSignals { /** Notifies listeners about an inventory item being seen on the network. */ boost::signals2::signal Inventory; /** Tells listeners to broadcast their data. */ - boost::signals2::signal Broadcast; + boost::signals2::signal Broadcast; /** Notifies listeners of a block validation result */ boost::signals2::signal BlockChecked; /** Notifies listeners that a key for mining is required (coinbase) */ diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 0ba6706baf830..a399f8ad9f3b9 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -346,6 +346,9 @@ static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtr if (nValue > curBalance) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds"); + if (pwalletMain->GetBroadcastTransactions() && !g_connman) + throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); + // Parse Bitcoin address CScript scriptPubKey = GetScriptForDestination(address); @@ -362,7 +365,7 @@ static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtr strError = strprintf("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!", FormatMoney(nFeeRequired)); throw JSONRPCError(RPC_WALLET_ERROR, strError); } - if (!pwalletMain->CommitTransaction(wtxNew, reservekey)) + if (!pwalletMain->CommitTransaction(wtxNew, reservekey, g_connman.get())) throw JSONRPCError(RPC_WALLET_ERROR, "Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of the wallet and coins were spent in the copy but not marked as spent here."); } @@ -891,6 +894,9 @@ UniValue sendmany(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); + if (pwalletMain->GetBroadcastTransactions() && !g_connman) + throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); + string strAccount = AccountFromValue(params[0]); UniValue sendTo = params[1].get_obj(); int nMinDepth = 1; @@ -953,7 +959,7 @@ UniValue sendmany(const UniValue& params, bool fHelp) bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, nChangePosRet, strFailReason); if (!fCreated) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason); - if (!pwalletMain->CommitTransaction(wtx, keyChange)) + if (!pwalletMain->CommitTransaction(wtx, keyChange, g_connman.get())) throw JSONRPCError(RPC_WALLET_ERROR, "Transaction commit failed"); return wtx.GetHash().GetHex(); @@ -2308,9 +2314,12 @@ UniValue resendwallettransactions(const UniValue& params, bool fHelp) "Returns array of transaction ids that were re-broadcast.\n" ); + if (!g_connman) + throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); + LOCK2(cs_main, pwalletMain->cs_wallet); - std::vector txids = pwalletMain->ResendWalletTransactionsBefore(GetTime()); + std::vector txids = pwalletMain->ResendWalletTransactionsBefore(GetTime(), g_connman.get()); UniValue result(UniValue::VARR); BOOST_FOREACH(const uint256& txid, txids) { diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 10aca2e499f60..4396c2a2b0125 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1453,7 +1453,7 @@ void CWallet::ReacceptWalletTransactions() } } -bool CWalletTx::RelayWalletTransaction() +bool CWalletTx::RelayWalletTransaction(CConnman* connman) { assert(pwallet->GetBroadcastTransactions()); if (!IsCoinBase()) @@ -1688,7 +1688,7 @@ bool CWalletTx::IsEquivalentTo(const CWalletTx& tx) const return CTransaction(tx1) == CTransaction(tx2); } -std::vector CWallet::ResendWalletTransactionsBefore(int64_t nTime) +std::vector CWallet::ResendWalletTransactionsBefore(int64_t nTime, CConnman* connman) { std::vector result; @@ -1706,13 +1706,13 @@ std::vector CWallet::ResendWalletTransactionsBefore(int64_t nTime) BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted) { CWalletTx& wtx = *item.second; - if (wtx.RelayWalletTransaction()) + if (wtx.RelayWalletTransaction(connman)) result.push_back(wtx.GetHash()); } return result; } -void CWallet::ResendWalletTransactions(int64_t nBestBlockTime) +void CWallet::ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) { // Do this infrequently and randomly to avoid giving away // that these are our transactions. @@ -1730,7 +1730,7 @@ void CWallet::ResendWalletTransactions(int64_t nBestBlockTime) // Rebroadcast unconfirmed txes older than 5 minutes before the last // block was found: - std::vector relayed = ResendWalletTransactionsBefore(nBestBlockTime-5*60); + std::vector relayed = ResendWalletTransactionsBefore(nBestBlockTime-5*60, connman); if (!relayed.empty()) LogPrintf("%s: rebroadcast %u unconfirmed transactions\n", __func__, relayed.size()); } @@ -2447,7 +2447,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt /** * Call after CreateTransaction unless you want to abort */ -bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) +bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CConnman* connman) { { LOCK2(cs_main, cs_wallet); @@ -2481,7 +2481,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) LogPrintf("CommitTransaction(): Error: Transaction not valid\n"); return false; } - wtxNew.RelayWalletTransaction(); + wtxNew.RelayWalletTransaction(connman); } } return true; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index c06513650c74a..7a771350cba43 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -401,7 +401,7 @@ class CWalletTx : public CMerkleTx int64_t GetTxTime() const; int GetRequestCount() const; - bool RelayWalletTransaction(); + bool RelayWalletTransaction(CConnman* connman); std::set GetConflicts() const; }; @@ -748,8 +748,8 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate); int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false); void ReacceptWalletTransactions(); - void ResendWalletTransactions(int64_t nBestBlockTime); - std::vector ResendWalletTransactionsBefore(int64_t nTime); + void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman); + std::vector ResendWalletTransactionsBefore(int64_t nTime, CConnman* connman); CAmount GetBalance() const; CAmount GetUnconfirmedBalance() const; CAmount GetImmatureBalance() const; @@ -770,7 +770,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface */ bool CreateTransaction(const std::vector& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, const CCoinControl *coinControl = NULL, bool sign = true); - bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey); + bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CConnman* connman); bool AddAccountingEntry(const CAccountingEntry&, CWalletDB & pwalletdb); From 02137f11e2ea5d153f433493639730587836a1e3 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Sat, 16 Apr 2016 15:46:00 -0400 Subject: [PATCH 0838/1802] net: Move socket binding into CConnman --- src/init.cpp | 12 ++++++------ src/net.cpp | 3 +-- src/net.h | 18 +++++++++++------- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 6aaa7bfc5db00..b0ffb7a40e35f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -273,11 +273,11 @@ void HandleSIGHUP(int) fReopenDebugLog = true; } -bool static Bind(const CService &addr, unsigned int flags) { +bool static Bind(CConnman& connman, const CService &addr, unsigned int flags) { if (!(flags & BF_EXPLICIT) && IsLimited(addr)) return false; std::string strError; - if (!BindListenPort(addr, strError, (flags & BF_WHITELIST) != 0)) { + if (!connman.BindListenPort(addr, strError, (flags & BF_WHITELIST) != 0)) { if (flags & BF_REPORT_ERROR) return InitError(strError); return false; @@ -1198,7 +1198,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) CService addrBind; if (!Lookup(strBind.c_str(), addrBind, GetListenPort(), false)) return InitError(ResolveErrMsg("bind", strBind)); - fBound |= Bind(addrBind, (BF_EXPLICIT | BF_REPORT_ERROR)); + fBound |= Bind(connman, addrBind, (BF_EXPLICIT | BF_REPORT_ERROR)); } BOOST_FOREACH(const std::string& strBind, mapMultiArgs["-whitebind"]) { CService addrBind; @@ -1206,14 +1206,14 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) return InitError(ResolveErrMsg("whitebind", strBind)); if (addrBind.GetPort() == 0) return InitError(strprintf(_("Need to specify a port with -whitebind: '%s'"), strBind)); - fBound |= Bind(addrBind, (BF_EXPLICIT | BF_REPORT_ERROR | BF_WHITELIST)); + fBound |= Bind(connman, addrBind, (BF_EXPLICIT | BF_REPORT_ERROR | BF_WHITELIST)); } } else { struct in_addr inaddr_any; inaddr_any.s_addr = INADDR_ANY; - fBound |= Bind(CService(in6addr_any, GetListenPort()), BF_NONE); - fBound |= Bind(CService(inaddr_any, GetListenPort()), !fBound ? BF_REPORT_ERROR : BF_NONE); + fBound |= Bind(connman, CService(in6addr_any, GetListenPort()), BF_NONE); + fBound |= Bind(connman, CService(inaddr_any, GetListenPort()), !fBound ? BF_REPORT_ERROR : BF_NONE); } if (!fBound) return InitError(_("Failed to listen on any port. Use -listen=0 if you want this.")); diff --git a/src/net.cpp b/src/net.cpp index b99989b289eb3..0069820004c58 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -84,7 +84,6 @@ std::map mapLocalHost; static bool vfLimited[NET_MAX] = {}; static CNode* pnodeLocalHost = NULL; uint64_t nLocalHostNonce = 0; -static std::vector vhListenSocket; CAddrMan addrman; int nMaxConnections = DEFAULT_MAX_PEER_CONNECTIONS; bool fAddressesInitialized = false; @@ -1908,7 +1907,7 @@ void CConnman::ThreadMessageHandler() -bool BindListenPort(const CService &addrBind, std::string& strError, bool fWhitelisted) +bool CConnman::BindListenPort(const CService &addrBind, std::string& strError, bool fWhitelisted) { strError = ""; int nOne = 1; diff --git a/src/net.h b/src/net.h index d2a38e7dc4ff9..4d87408e3237d 100644 --- a/src/net.h +++ b/src/net.h @@ -95,13 +95,6 @@ CNode* FindNode(const CService& ip); CNode* FindNode(const NodeId id); //TODO: Remove this bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false, bool fFeeler = false); -struct ListenSocket { - SOCKET socket; - bool whitelisted; - - ListenSocket(SOCKET socket_, bool whitelisted_) : socket(socket_), whitelisted(whitelisted_) {} -}; - class CConnman { public: @@ -109,7 +102,16 @@ class CConnman ~CConnman(); bool Start(boost::thread_group& threadGroup, std::string& strNodeError); void Stop(); + bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); + private: + struct ListenSocket { + SOCKET socket; + bool whitelisted; + + ListenSocket(SOCKET socket_, bool whitelisted_) : socket(socket_), whitelisted(whitelisted_) {} + }; + void ThreadOpenAddedConnections(); void ProcessOneShot(); void ThreadOpenConnections(); @@ -117,6 +119,8 @@ class CConnman void AcceptConnection(const ListenSocket& hListenSocket); void ThreadSocketHandler(); void ThreadDNSAddressSeed(); + + std::vector vhListenSocket; }; extern std::unique_ptr g_connman; void MapPort(bool fUseUPnP); From b1a5f4320878e34eb998737dce333270dd83e436 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Sat, 16 Apr 2016 15:59:10 -0400 Subject: [PATCH 0839/1802] net: move OpenNetworkConnection into CConnman --- src/net.cpp | 4 ++-- src/net.h | 4 +++- src/rpc/net.cpp | 5 ++++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 0069820004c58..83a96205a35d0 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -375,7 +375,7 @@ CNode* FindNode(const NodeId nodeid) return NULL; } -CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure) +CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure) { if (pszDest == NULL) { if (IsLocal(addrConnect)) @@ -1809,7 +1809,7 @@ void CConnman::ThreadOpenAddedConnections() } // if successful, this moves the passed grant to the constructed node -bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound, const char *pszDest, bool fOneShot, bool fFeeler) +bool CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound, const char *pszDest, bool fOneShot, bool fFeeler) { // // Initiate outbound network connection diff --git a/src/net.h b/src/net.h index 4d87408e3237d..e0c317ae46525 100644 --- a/src/net.h +++ b/src/net.h @@ -93,7 +93,6 @@ CNode* FindNode(const CSubNet& subNet); CNode* FindNode(const std::string& addrName); CNode* FindNode(const CService& ip); CNode* FindNode(const NodeId id); //TODO: Remove this -bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false, bool fFeeler = false); class CConnman { @@ -103,6 +102,7 @@ class CConnman bool Start(boost::thread_group& threadGroup, std::string& strNodeError); void Stop(); bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); + bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false, bool fFeeler = false); private: struct ListenSocket { @@ -120,6 +120,8 @@ class CConnman void ThreadSocketHandler(); void ThreadDNSAddressSeed(); + CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure); + std::vector vhListenSocket; }; extern std::unique_ptr g_connman; diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 840bfd5a2424b..edf33c70be72f 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -214,12 +214,15 @@ UniValue addnode(const UniValue& params, bool fHelp) + HelpExampleRpc("addnode", "\"192.168.0.6:8333\", \"onetry\"") ); + if(!g_connman) + throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); + string strNode = params[0].get_str(); if (strCommand == "onetry") { CAddress addr; - OpenNetworkConnection(addr, false, NULL, strNode.c_str()); + g_connman->OpenNetworkConnection(addr, false, NULL, strNode.c_str()); return NullUniValue; } From aaf018e3b79417ecfd39291a8c100df77969d77a Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 24 May 2016 18:59:16 -0400 Subject: [PATCH 0840/1802] net: handle nodesignals in CConnman --- src/main.cpp | 5 +++-- src/net.cpp | 38 ++++++++++++++++++++++---------------- src/net.h | 3 ++- src/test/DoS_tests.cpp | 4 ++++ 4 files changed, 31 insertions(+), 19 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 4dc9d71eea011..bd85fa8f07060 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -348,7 +348,8 @@ void InitializeNode(NodeId nodeid, const CNode *pnode) { state.address = pnode->addr; } -void FinalizeNode(NodeId nodeid) { +void FinalizeNode(NodeId nodeid, bool& fUpdateConnectionTime) { + fUpdateConnectionTime = false; LOCK(cs_main); CNodeState *state = State(nodeid); @@ -356,7 +357,7 @@ void FinalizeNode(NodeId nodeid) { nSyncStarted--; if (state->nMisbehavior == 0 && state->fCurrentlyConnected) { - AddressCurrentlyConnected(state->address); + fUpdateConnectionTime = true; } BOOST_FOREACH(const QueuedBlock& entry, state->vBlocksInFlight) { diff --git a/src/net.cpp b/src/net.cpp index 83a96205a35d0..26bf477e999cf 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -313,12 +313,6 @@ bool IsReachable(const CNetAddr& addr) return IsReachable(net); } -void AddressCurrentlyConnected(const CService& addr) -{ - addrman.Connected(addr); -} - - uint64_t CNode::nTotalBytesRecv = 0; uint64_t CNode::nTotalBytesSent = 0; CCriticalSection CNode::cs_totalBytesRecv; @@ -431,6 +425,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo // Add node CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false); + GetNodeSignals().InitializeNode(pnode->GetId(), pnode); pnode->AddRef(); { @@ -1070,6 +1065,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) { } CNode* pnode = new CNode(hSocket, addr, "", true); + GetNodeSignals().InitializeNode(pnode->GetId(), pnode); pnode->AddRef(); pnode->fWhitelisted = whitelisted; @@ -1139,7 +1135,7 @@ void CConnman::ThreadSocketHandler() if (fDelete) { vNodesDisconnected.remove(pnode); - delete pnode; + DeleteNode(pnode); } } } @@ -2119,6 +2115,7 @@ bool CConnman::Start(boost::thread_group& threadGroup, std::string& strNodeError CNetAddr local; LookupHost("127.0.0.1", local, false); pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService(local, 0), nLocalServices)); + GetNodeSignals().InitializeNode(pnodeLocalHost->GetId(), pnodeLocalHost); } // @@ -2194,19 +2191,32 @@ void CConnman::Stop() LogPrintf("CloseSocket(hListenSocket) failed with error %s\n", NetworkErrorString(WSAGetLastError())); // clean up some globals (to help leak detection) - BOOST_FOREACH(CNode *pnode, vNodes) - delete pnode; - BOOST_FOREACH(CNode *pnode, vNodesDisconnected) - delete pnode; + BOOST_FOREACH(CNode *pnode, vNodes) { + DeleteNode(pnode); + } + BOOST_FOREACH(CNode *pnode, vNodesDisconnected) { + DeleteNode(pnode); + } vNodes.clear(); vNodesDisconnected.clear(); vhListenSocket.clear(); delete semOutbound; semOutbound = NULL; - delete pnodeLocalHost; + if(pnodeLocalHost) + DeleteNode(pnodeLocalHost); pnodeLocalHost = NULL; } +void CConnman::DeleteNode(CNode* pnode) +{ + assert(pnode); + bool fUpdateConnectionTime = false; + GetNodeSignals().FinalizeNode(pnode->GetId(), fUpdateConnectionTime); + if(fUpdateConnectionTime) + addrman.Connected(pnode->addr); + delete pnode; +} + CConnman::~CConnman() { } @@ -2442,8 +2452,6 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa // Be shy and don't send version until we hear if (hSocket != INVALID_SOCKET && !fInbound) PushVersion(); - - GetNodeSignals().InitializeNode(GetId(), this); } CNode::~CNode() @@ -2452,8 +2460,6 @@ CNode::~CNode() if (pfilter) delete pfilter; - - GetNodeSignals().FinalizeNode(GetId()); } void CNode::AskFor(const CInv& inv) diff --git a/src/net.h b/src/net.h index e0c317ae46525..b9dfaa0f40345 100644 --- a/src/net.h +++ b/src/net.h @@ -121,6 +121,7 @@ class CConnman void ThreadDNSAddressSeed(); CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure); + void DeleteNode(CNode* pnode); std::vector vhListenSocket; }; @@ -154,7 +155,7 @@ struct CNodeSignals boost::signals2::signal ProcessMessages; boost::signals2::signal SendMessages; boost::signals2::signal InitializeNode; - boost::signals2::signal FinalizeNode; + boost::signals2::signal FinalizeNode; }; diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index 10529cda9e6bc..007ea79f9edf0 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -47,6 +47,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning) CNode::ClearBanned(); CAddress addr1(ip(0xa0b0c001), NODE_NONE); CNode dummyNode1(INVALID_SOCKET, addr1, "", true); + GetNodeSignals().InitializeNode(dummyNode1.GetId(), &dummyNode1); dummyNode1.nVersion = 1; Misbehaving(dummyNode1.GetId(), 100); // Should get banned SendMessages(&dummyNode1, *connman); @@ -55,6 +56,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning) CAddress addr2(ip(0xa0b0c002), NODE_NONE); CNode dummyNode2(INVALID_SOCKET, addr2, "", true); + GetNodeSignals().InitializeNode(dummyNode2.GetId(), &dummyNode2); dummyNode2.nVersion = 1; Misbehaving(dummyNode2.GetId(), 50); SendMessages(&dummyNode2, *connman); @@ -71,6 +73,7 @@ BOOST_AUTO_TEST_CASE(DoS_banscore) mapArgs["-banscore"] = "111"; // because 11 is my favorite number CAddress addr1(ip(0xa0b0c001), NODE_NONE); CNode dummyNode1(INVALID_SOCKET, addr1, "", true); + GetNodeSignals().InitializeNode(dummyNode1.GetId(), &dummyNode1); dummyNode1.nVersion = 1; Misbehaving(dummyNode1.GetId(), 100); SendMessages(&dummyNode1, *connman); @@ -92,6 +95,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) CAddress addr(ip(0xa0b0c001), NODE_NONE); CNode dummyNode(INVALID_SOCKET, addr, "", true); + GetNodeSignals().InitializeNode(dummyNode.GetId(), &dummyNode); dummyNode.nVersion = 1; Misbehaving(dummyNode.GetId(), 100); From a0f3d3cdad630103d919a4ec802c413b87fa1f1a Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Sat, 16 Apr 2016 17:43:11 -0400 Subject: [PATCH 0841/1802] net: move ban and addrman functions into CConnman --- src/main.cpp | 14 ++--- src/net.cpp | 126 ++++++++++++++++++++++++--------------- src/net.h | 89 ++++++++++++++------------- src/qt/bantablemodel.cpp | 3 +- src/qt/rpcconsole.cpp | 29 ++++----- src/rpc/net.cpp | 17 ++++-- src/test/DoS_tests.cpp | 28 ++++----- 7 files changed, 174 insertions(+), 132 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index bd85fa8f07060..f3babb71d219d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4944,7 +4944,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, pfrom->nServices = ServiceFlags(nServiceInt); if (!pfrom->fInbound) { - addrman.SetServices(pfrom->addr, pfrom->nServices); + connman.SetServices(pfrom->addr, pfrom->nServices); } if (pfrom->nServicesExpected & ~pfrom->nServices) { @@ -5038,12 +5038,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } // Get recent addresses - if (pfrom->fOneShot || pfrom->nVersion >= CADDR_TIME_VERSION || addrman.size() < 1000) + if (pfrom->fOneShot || pfrom->nVersion >= CADDR_TIME_VERSION || connman.GetAddressCount() < 1000) { pfrom->PushMessage(NetMsgType::GETADDR); pfrom->fGetAddr = true; } - addrman.Good(pfrom->addr); + connman.MarkAddressGood(pfrom->addr); } pfrom->fSuccessfullyConnected = true; @@ -5108,7 +5108,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, vRecv >> vAddr; // Don't want addr from older versions unless seeding - if (pfrom->nVersion < CADDR_TIME_VERSION && addrman.size() > 1000) + if (pfrom->nVersion < CADDR_TIME_VERSION && connman.GetAddressCount() > 1000) return true; if (vAddr.size() > 1000) { @@ -5160,7 +5160,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, if (fReachable) vAddrOk.push_back(addr); } - addrman.Add(vAddrOk, pfrom->addr, 2 * 60 * 60); + connman.AddNewAddresses(vAddrOk, pfrom->addr, 2 * 60 * 60); if (vAddr.size() < 1000) pfrom->fGetAddr = false; if (pfrom->fOneShot) @@ -5950,7 +5950,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, pfrom->fSentAddr = true; pfrom->vAddrToSend.clear(); - vector vAddr = addrman.GetAddr(); + vector vAddr = connman.GetAddresses(); BOOST_FOREACH(const CAddress &addr, vAddr) pfrom->PushAddress(addr); } @@ -6393,7 +6393,7 @@ bool SendMessages(CNode* pto, CConnman& connman) LogPrintf("Warning: not banning local peer %s!\n", pto->addr.ToString()); else { - CNode::Ban(pto->addr, BanReasonNodeMisbehaving); + connman.Ban(pto->addr, BanReasonNodeMisbehaving); } } state.fShouldBan = false; diff --git a/src/net.cpp b/src/net.cpp index 26bf477e999cf..eeb84fca7a20b 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -84,9 +84,7 @@ std::map mapLocalHost; static bool vfLimited[NET_MAX] = {}; static CNode* pnodeLocalHost = NULL; uint64_t nLocalHostNonce = 0; -CAddrMan addrman; int nMaxConnections = DEFAULT_MAX_PEER_CONNECTIONS; -bool fAddressesInitialized = false; std::string strSubVersion; std::vector vNodes; @@ -446,21 +444,21 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo return NULL; } -static void DumpBanlist() +void CConnman::DumpBanlist() { - CNode::SweepBanned(); // clean unused entries (if bantime has expired) + SweepBanned(); // clean unused entries (if bantime has expired) - if (!CNode::BannedSetIsDirty()) + if (!BannedSetIsDirty()) return; int64_t nStart = GetTimeMillis(); CBanDB bandb; banmap_t banmap; - CNode::SetBannedSetDirty(false); - CNode::GetBanned(banmap); + SetBannedSetDirty(false); + GetBanned(banmap); if (!bandb.Write(banmap)) - CNode::SetBannedSetDirty(true); + SetBannedSetDirty(true); LogPrint("net", "Flushed %d banned node ips/subnets to banlist.dat %dms\n", banmap.size(), GetTimeMillis() - nStart); @@ -501,11 +499,7 @@ void CNode::PushVersion() -banmap_t CNode::setBanned; -CCriticalSection CNode::cs_setBanned; -bool CNode::setBannedIsDirty; - -void CNode::ClearBanned() +void CConnman::ClearBanned() { { LOCK(cs_setBanned); @@ -516,7 +510,7 @@ void CNode::ClearBanned() uiInterface.BannedListChanged(); } -bool CNode::IsBanned(CNetAddr ip) +bool CConnman::IsBanned(CNetAddr ip) { bool fResult = false; { @@ -533,7 +527,7 @@ bool CNode::IsBanned(CNetAddr ip) return fResult; } -bool CNode::IsBanned(CSubNet subnet) +bool CConnman::IsBanned(CSubNet subnet) { bool fResult = false; { @@ -549,12 +543,12 @@ bool CNode::IsBanned(CSubNet subnet) return fResult; } -void CNode::Ban(const CNetAddr& addr, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch) { +void CConnman::Ban(const CNetAddr& addr, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch) { CSubNet subNet(addr); Ban(subNet, banReason, bantimeoffset, sinceUnixEpoch); } -void CNode::Ban(const CSubNet& subNet, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch) { +void CConnman::Ban(const CSubNet& subNet, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch) { CBanEntry banEntry(GetTime()); banEntry.banReason = banReason; if (bantimeoffset <= 0) @@ -585,12 +579,12 @@ void CNode::Ban(const CSubNet& subNet, const BanReason &banReason, int64_t banti DumpBanlist(); //store banlist to disk immediately if user requested ban } -bool CNode::Unban(const CNetAddr &addr) { +bool CConnman::Unban(const CNetAddr &addr) { CSubNet subNet(addr); return Unban(subNet); } -bool CNode::Unban(const CSubNet &subNet) { +bool CConnman::Unban(const CSubNet &subNet) { { LOCK(cs_setBanned); if (!setBanned.erase(subNet)) @@ -602,20 +596,20 @@ bool CNode::Unban(const CSubNet &subNet) { return true; } -void CNode::GetBanned(banmap_t &banMap) +void CConnman::GetBanned(banmap_t &banMap) { LOCK(cs_setBanned); banMap = setBanned; //create a thread safe copy } -void CNode::SetBanned(const banmap_t &banMap) +void CConnman::SetBanned(const banmap_t &banMap) { LOCK(cs_setBanned); setBanned = banMap; setBannedIsDirty = true; } -void CNode::SweepBanned() +void CConnman::SweepBanned() { int64_t now = GetTime(); @@ -636,13 +630,13 @@ void CNode::SweepBanned() } } -bool CNode::BannedSetIsDirty() +bool CConnman::BannedSetIsDirty() { LOCK(cs_setBanned); return setBannedIsDirty; } -void CNode::SetBannedSetDirty(bool dirty) +void CConnman::SetBannedSetDirty(bool dirty) { LOCK(cs_setBanned); //reuse setBanned lock for the isDirty flag setBannedIsDirty = dirty; @@ -1047,7 +1041,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) { setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (void*)&set, sizeof(int)); #endif - if (CNode::IsBanned(addr) && !whitelisted) + if (IsBanned(addr) && !whitelisted) { LogPrintf("connection from %s dropped (banned)\n", addr.ToString()); CloseSocket(hSocket); @@ -1548,7 +1542,7 @@ void CConnman::ThreadDNSAddressSeed() -void DumpAddresses() +void CConnman::DumpAddresses() { int64_t nStart = GetTimeMillis(); @@ -1559,7 +1553,7 @@ void DumpAddresses() addrman.size(), GetTimeMillis() - nStart); } -void DumpData() +void CConnman::DumpData() { DumpAddresses(); DumpBanlist(); @@ -1813,7 +1807,7 @@ bool CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFai boost::this_thread::interruption_point(); if (!pszDest) { if (IsLocal(addrConnect) || - FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) || + FindNode((CNetAddr)addrConnect) || IsBanned(addrConnect) || FindNode(addrConnect.ToStringIPPort())) return false; } else if (FindNode(std::string(pszDest))) @@ -2054,10 +2048,22 @@ void static Discover(boost::thread_group& threadGroup) CConnman::CConnman() { + setBannedIsDirty = false; + fAddressesInitialized = false; } bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler& scheduler, std::string& strNodeError) { + Discover(threadGroup); + + bool ret = connman.Start(threadGroup, scheduler, strNodeError); + + return ret; +} + +bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, std::string& strNodeError) +{ + uiInterface.InitMessage(_("Loading addresses...")); // Load addresses from peers.dat int64_t nStart = GetTimeMillis(); @@ -2078,15 +2084,15 @@ bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler& CBanDB bandb; banmap_t banmap; if (bandb.Read(banmap)) { - CNode::SetBanned(banmap); // thread save setter - CNode::SetBannedSetDirty(false); // no need to write down, just read data - CNode::SweepBanned(); // sweep out unused entries + SetBanned(banmap); // thread save setter + SetBannedSetDirty(false); // no need to write down, just read data + SweepBanned(); // sweep out unused entries LogPrint("net", "Loaded %d banned node ips/subnets from banlist.dat %dms\n", banmap.size(), GetTimeMillis() - nStart); } else { LogPrintf("Invalid or missing banlist.dat; recreating\n"); - CNode::SetBannedSetDirty(true); // force write + SetBannedSetDirty(true); // force write DumpBanlist(); } @@ -2094,17 +2100,6 @@ bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler& fAddressesInitialized = true; - Discover(threadGroup); - - bool ret = connman.Start(threadGroup, strNodeError); - - // Dump network addresses - scheduler.scheduleEvery(DumpData, DUMP_ADDRESSES_INTERVAL); - return ret; -} - -bool CConnman::Start(boost::thread_group& threadGroup, std::string& strNodeError) -{ if (semOutbound == NULL) { // initialize semaphore int nMaxOutbound = std::min((MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS), nMaxConnections); @@ -2142,6 +2137,9 @@ bool CConnman::Start(boost::thread_group& threadGroup, std::string& strNodeError // Process messages threadGroup.create_thread(boost::bind(&TraceThread >, "msghand", boost::function(boost::bind(&CConnman::ThreadMessageHandler, this)))); + // Dump network addresses + scheduler.scheduleEvery(boost::bind(&CConnman::DumpData, this), DUMP_ADDRESSES_INTERVAL); + return true; } @@ -2150,12 +2148,6 @@ bool StopNode(CConnman& connman) LogPrintf("StopNode()\n"); MapPort(false); - if (fAddressesInitialized) - { - DumpData(); - fAddressesInitialized = false; - } - connman.Stop(); return true; } @@ -2181,6 +2173,12 @@ void CConnman::Stop() for (int i=0; i<(MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS); i++) semOutbound->post(); + if (fAddressesInitialized) + { + DumpData(); + fAddressesInitialized = false; + } + // Close sockets BOOST_FOREACH(CNode* pnode, vNodes) if (pnode->hSocket != INVALID_SOCKET) @@ -2221,6 +2219,36 @@ CConnman::~CConnman() { } +size_t CConnman::GetAddressCount() const +{ + return addrman.size(); +} + +void CConnman::SetServices(const CService &addr, ServiceFlags nServices) +{ + addrman.SetServices(addr, nServices); +} + +void CConnman::MarkAddressGood(const CAddress& addr) +{ + addrman.Good(addr); +} + +void CConnman::AddNewAddress(const CAddress& addr, const CAddress& addrFrom, int64_t nTimePenalty) +{ + addrman.Add(addr, addrFrom, nTimePenalty); +} + +void CConnman::AddNewAddresses(const std::vector& vAddr, const CAddress& addrFrom, int64_t nTimePenalty) +{ + addrman.Add(vAddr, addrFrom, nTimePenalty); +} + +std::vector CConnman::GetAddresses() +{ + return addrman.GetAddr(); +} + void RelayTransaction(const CTransaction& tx) { CInv inv(MSG_TX, tx.GetHash()); diff --git a/src/net.h b/src/net.h index b9dfaa0f40345..65dafb4fd926c 100644 --- a/src/net.h +++ b/src/net.h @@ -7,6 +7,7 @@ #define BITCOIN_NET_H #include "addrdb.h" +#include "addrman.h" #include "amount.h" #include "bloom.h" #include "compat.h" @@ -87,7 +88,6 @@ unsigned int SendBufferSize(); typedef int NodeId; void AddOneShot(const std::string& strDest); -void AddressCurrentlyConnected(const CService& addr); CNode* FindNode(const CNetAddr& ip); CNode* FindNode(const CSubNet& subNet); CNode* FindNode(const std::string& addrName); @@ -99,11 +99,44 @@ class CConnman public: CConnman(); ~CConnman(); - bool Start(boost::thread_group& threadGroup, std::string& strNodeError); + bool Start(boost::thread_group& threadGroup, CScheduler& scheduler, std::string& strNodeError); void Stop(); bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false, bool fFeeler = false); + // Addrman functions + size_t GetAddressCount() const; + void SetServices(const CService &addr, ServiceFlags nServices); + void MarkAddressGood(const CAddress& addr); + void AddNewAddress(const CAddress& addr, const CAddress& addrFrom, int64_t nTimePenalty = 0); + void AddNewAddresses(const std::vector& vAddr, const CAddress& addrFrom, int64_t nTimePenalty = 0); + std::vector GetAddresses(); + void AddressCurrentlyConnected(const CService& addr); + + // Denial-of-service detection/prevention + // The idea is to detect peers that are behaving + // badly and disconnect/ban them, but do it in a + // one-coding-mistake-won't-shatter-the-entire-network + // way. + // IMPORTANT: There should be nothing I can give a + // node that it will forward on that will make that + // node's peers drop it. If there is, an attacker + // can isolate a node and/or try to split the network. + // Dropping a node for sending stuff that is invalid + // now but might be valid in a later version is also + // dangerous, because it can cause a network split + // between nodes running old code and nodes running + // new code. + void Ban(const CNetAddr& netAddr, const BanReason& reason, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false); + void Ban(const CSubNet& subNet, const BanReason& reason, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false); + void ClearBanned(); // needed for unit testing + bool IsBanned(CNetAddr ip); + bool IsBanned(CSubNet subnet); + bool Unban(const CNetAddr &ip); + bool Unban(const CSubNet &ip); + void GetBanned(banmap_t &banmap); + void SetBanned(const banmap_t &banmap); + private: struct ListenSocket { SOCKET socket; @@ -122,8 +155,22 @@ class CConnman CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure); void DeleteNode(CNode* pnode); + //!check is the banlist has unwritten changes + bool BannedSetIsDirty(); + //!set the "dirty" flag for the banlist + void SetBannedSetDirty(bool dirty=true); + //!clean unused entries (if bantime has expired) + void SweepBanned(); + void DumpAddresses(); + void DumpData(); + void DumpBanlist(); std::vector vhListenSocket; + banmap_t setBanned; + CCriticalSection cs_setBanned; + bool setBannedIsDirty; + bool fAddressesInitialized; + CAddrMan addrman; }; extern std::unique_ptr g_connman; void MapPort(bool fUseUPnP); @@ -195,7 +242,6 @@ extern ServiceFlags nLocalServices; extern ServiceFlags nRelevantServices; extern bool fRelayTxes; extern uint64_t nLocalHostNonce; -extern CAddrMan addrman; /** Maximum number of connections to simultaneously allow (aka connection slots) */ extern int nMaxConnections; @@ -347,12 +393,6 @@ class CNode const uint64_t nKeyedNetGroup; protected: - // Denial-of-service detection/prevention - // Key is IP address, value is banned-until-time - static banmap_t setBanned; - static CCriticalSection cs_setBanned; - static bool setBannedIsDirty; - // Whitelisted ranges. Any node connecting from these is automatically // whitelisted (as well as those connecting to whitelisted binds). static std::vector vWhitelistedRange; @@ -722,37 +762,6 @@ class CNode void CloseSocketDisconnect(); - // Denial-of-service detection/prevention - // The idea is to detect peers that are behaving - // badly and disconnect/ban them, but do it in a - // one-coding-mistake-won't-shatter-the-entire-network - // way. - // IMPORTANT: There should be nothing I can give a - // node that it will forward on that will make that - // node's peers drop it. If there is, an attacker - // can isolate a node and/or try to split the network. - // Dropping a node for sending stuff that is invalid - // now but might be valid in a later version is also - // dangerous, because it can cause a network split - // between nodes running old code and nodes running - // new code. - static void ClearBanned(); // needed for unit testing - static bool IsBanned(CNetAddr ip); - static bool IsBanned(CSubNet subnet); - static void Ban(const CNetAddr &ip, const BanReason &banReason, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false); - static void Ban(const CSubNet &subNet, const BanReason &banReason, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false); - static bool Unban(const CNetAddr &ip); - static bool Unban(const CSubNet &ip); - static void GetBanned(banmap_t &banmap); - static void SetBanned(const banmap_t &banmap); - - //!check is the banlist has unwritten changes - static bool BannedSetIsDirty(); - //!set the "dirty" flag for the banlist - static void SetBannedSetDirty(bool dirty=true); - //!clean unused entries (if bantime has expired) - static void SweepBanned(); - void copyStats(CNodeStats &stats); static bool IsWhitelistedRange(const CNetAddr &ip); diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp index d95106b5ac87a..6e11e23904733 100644 --- a/src/qt/bantablemodel.cpp +++ b/src/qt/bantablemodel.cpp @@ -48,7 +48,8 @@ class BanTablePriv void refreshBanlist() { banmap_t banMap; - CNode::GetBanned(banMap); + if(g_connman) + g_connman->GetBanned(banMap); cachedBanlist.clear(); #if QT_VERSION >= 0x040700 diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index e5720dd70e0cd..708be6b646e8a 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -887,26 +887,23 @@ void RPCConsole::disconnectSelectedNode() void RPCConsole::banSelectedNode(int bantime) { - if (!clientModel) + if (!clientModel || !g_connman) return; // Get currently selected peer address QString strNode = GUIUtil::getEntryData(ui->peerWidget, 0, PeerTableModel::Address).toString(); // Find possible nodes, ban it and clear the selected node - if (FindNode(strNode.toStdString())) { - std::string nStr = strNode.toStdString(); - std::string addr; - int port = 0; - SplitHostPort(nStr, port, addr); - - CNetAddr resolved; - if(!LookupHost(addr.c_str(), resolved, false)) - return; - CNode::Ban(resolved, BanReasonManuallyAdded, bantime); + std::string nStr = strNode.toStdString(); + std::string addr; + int port = 0; + SplitHostPort(nStr, port, addr); - clearSelectedNode(); - clientModel->getBanTableModel()->refresh(); - } + CNetAddr resolved; + if(!LookupHost(addr.c_str(), resolved, false)) + return; + g_connman->Ban(resolved, BanReasonManuallyAdded, bantime); + clearSelectedNode(); + clientModel->getBanTableModel()->refresh(); } void RPCConsole::unbanSelectedNode() @@ -919,9 +916,9 @@ void RPCConsole::unbanSelectedNode() CSubNet possibleSubnet; LookupSubNet(strNode.toStdString().c_str(), possibleSubnet); - if (possibleSubnet.IsValid()) + if (possibleSubnet.IsValid() && g_connman) { - CNode::Unban(possibleSubnet); + g_connman->Unban(possibleSubnet); clientModel->getBanTableModel()->refresh(); } } diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index edf33c70be72f..0244da9fea746 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -488,6 +488,8 @@ UniValue setban(const UniValue& params, bool fHelp) + HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"") + HelpExampleRpc("setban", "\"192.168.0.6\", \"add\", 86400") ); + if(!g_connman) + throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); CSubNet subNet; CNetAddr netAddr; @@ -509,7 +511,7 @@ UniValue setban(const UniValue& params, bool fHelp) if (strCommand == "add") { - if (isSubnet ? CNode::IsBanned(subNet) : CNode::IsBanned(netAddr)) + if (isSubnet ? g_connman->IsBanned(subNet) : g_connman->IsBanned(netAddr)) throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned"); int64_t banTime = 0; //use standard bantime if not specified @@ -520,11 +522,11 @@ UniValue setban(const UniValue& params, bool fHelp) if (params.size() == 4 && params[3].isTrue()) absolute = true; - isSubnet ? CNode::Ban(subNet, BanReasonManuallyAdded, banTime, absolute) : CNode::Ban(netAddr, BanReasonManuallyAdded, banTime, absolute); + isSubnet ? g_connman->Ban(subNet, BanReasonManuallyAdded, banTime, absolute) : g_connman->Ban(netAddr, BanReasonManuallyAdded, banTime, absolute); } else if(strCommand == "remove") { - if (!( isSubnet ? CNode::Unban(subNet) : CNode::Unban(netAddr) )) + if (!( isSubnet ? g_connman->Unban(subNet) : g_connman->Unban(netAddr) )) throw JSONRPCError(RPC_MISC_ERROR, "Error: Unban failed"); } return NullUniValue; @@ -541,8 +543,11 @@ UniValue listbanned(const UniValue& params, bool fHelp) + HelpExampleRpc("listbanned", "") ); + if(!g_connman) + throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); + banmap_t banMap; - CNode::GetBanned(banMap); + g_connman->GetBanned(banMap); UniValue bannedAddresses(UniValue::VARR); for (banmap_t::iterator it = banMap.begin(); it != banMap.end(); it++) @@ -570,8 +575,10 @@ UniValue clearbanned(const UniValue& params, bool fHelp) + HelpExampleCli("clearbanned", "") + HelpExampleRpc("clearbanned", "") ); + if(!g_connman) + throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); - CNode::ClearBanned(); + g_connman->ClearBanned(); return NullUniValue; } diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index 007ea79f9edf0..412f94f40d9dd 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -44,15 +44,15 @@ BOOST_FIXTURE_TEST_SUITE(DoS_tests, TestingSetup) BOOST_AUTO_TEST_CASE(DoS_banning) { - CNode::ClearBanned(); + connman->ClearBanned(); CAddress addr1(ip(0xa0b0c001), NODE_NONE); CNode dummyNode1(INVALID_SOCKET, addr1, "", true); GetNodeSignals().InitializeNode(dummyNode1.GetId(), &dummyNode1); dummyNode1.nVersion = 1; Misbehaving(dummyNode1.GetId(), 100); // Should get banned SendMessages(&dummyNode1, *connman); - BOOST_CHECK(CNode::IsBanned(addr1)); - BOOST_CHECK(!CNode::IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned + BOOST_CHECK(connman->IsBanned(addr1)); + BOOST_CHECK(!connman->IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned CAddress addr2(ip(0xa0b0c002), NODE_NONE); CNode dummyNode2(INVALID_SOCKET, addr2, "", true); @@ -60,16 +60,16 @@ BOOST_AUTO_TEST_CASE(DoS_banning) dummyNode2.nVersion = 1; Misbehaving(dummyNode2.GetId(), 50); SendMessages(&dummyNode2, *connman); - BOOST_CHECK(!CNode::IsBanned(addr2)); // 2 not banned yet... - BOOST_CHECK(CNode::IsBanned(addr1)); // ... but 1 still should be + BOOST_CHECK(!connman->IsBanned(addr2)); // 2 not banned yet... + BOOST_CHECK(connman->IsBanned(addr1)); // ... but 1 still should be Misbehaving(dummyNode2.GetId(), 50); SendMessages(&dummyNode2, *connman); - BOOST_CHECK(CNode::IsBanned(addr2)); + BOOST_CHECK(connman->IsBanned(addr2)); } BOOST_AUTO_TEST_CASE(DoS_banscore) { - CNode::ClearBanned(); + connman->ClearBanned(); mapArgs["-banscore"] = "111"; // because 11 is my favorite number CAddress addr1(ip(0xa0b0c001), NODE_NONE); CNode dummyNode1(INVALID_SOCKET, addr1, "", true); @@ -77,19 +77,19 @@ BOOST_AUTO_TEST_CASE(DoS_banscore) dummyNode1.nVersion = 1; Misbehaving(dummyNode1.GetId(), 100); SendMessages(&dummyNode1, *connman); - BOOST_CHECK(!CNode::IsBanned(addr1)); + BOOST_CHECK(!connman->IsBanned(addr1)); Misbehaving(dummyNode1.GetId(), 10); SendMessages(&dummyNode1, *connman); - BOOST_CHECK(!CNode::IsBanned(addr1)); + BOOST_CHECK(!connman->IsBanned(addr1)); Misbehaving(dummyNode1.GetId(), 1); SendMessages(&dummyNode1, *connman); - BOOST_CHECK(CNode::IsBanned(addr1)); + BOOST_CHECK(connman->IsBanned(addr1)); mapArgs.erase("-banscore"); } BOOST_AUTO_TEST_CASE(DoS_bantime) { - CNode::ClearBanned(); + connman->ClearBanned(); int64_t nStartTime = GetTime(); SetMockTime(nStartTime); // Overrides future calls to GetTime() @@ -100,13 +100,13 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) Misbehaving(dummyNode.GetId(), 100); SendMessages(&dummyNode, *connman); - BOOST_CHECK(CNode::IsBanned(addr)); + BOOST_CHECK(connman->IsBanned(addr)); SetMockTime(nStartTime+60*60); - BOOST_CHECK(CNode::IsBanned(addr)); + BOOST_CHECK(connman->IsBanned(addr)); SetMockTime(nStartTime+60*60*24+1); - BOOST_CHECK(!CNode::IsBanned(addr)); + BOOST_CHECK(!connman->IsBanned(addr)); } CTransaction RandomOrphan() From 502dd3a8a0bc0d12744e75f84a22cc12074c5683 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Sat, 16 Apr 2016 17:51:01 -0400 Subject: [PATCH 0842/1802] net: Add oneshot functions to CConnman --- src/init.cpp | 2 +- src/net.cpp | 5 +---- src/net.h | 4 +++- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index b0ffb7a40e35f..719b648c04cfd 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1230,7 +1230,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) } BOOST_FOREACH(const std::string& strDest, mapMultiArgs["-seednode"]) - AddOneShot(strDest); + connman.AddOneShot(strDest); #if ENABLE_ZMQ pzmqNotificationInterface = CZMQNotificationInterface::CreateWithArguments(mapArgs); diff --git a/src/net.cpp b/src/net.cpp index eeb84fca7a20b..045939c2ea19f 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -91,9 +91,6 @@ std::vector vNodes; CCriticalSection cs_vNodes; limitedmap mapAlreadyAskedFor(MAX_INV_SZ); -static std::deque vOneShots; -CCriticalSection cs_vOneShots; - std::vector vAddedNodes; CCriticalSection cs_vAddedNodes; @@ -107,7 +104,7 @@ boost::condition_variable messageHandlerCondition; static CNodeSignals g_signals; CNodeSignals& GetNodeSignals() { return g_signals; } -void AddOneShot(const std::string& strDest) +void CConnman::AddOneShot(const std::string& strDest) { LOCK(cs_vOneShots); vOneShots.push_back(strDest); diff --git a/src/net.h b/src/net.h index 65dafb4fd926c..81de7f5a98f06 100644 --- a/src/net.h +++ b/src/net.h @@ -87,7 +87,6 @@ unsigned int SendBufferSize(); typedef int NodeId; -void AddOneShot(const std::string& strDest); CNode* FindNode(const CNetAddr& ip); CNode* FindNode(const CSubNet& subNet); CNode* FindNode(const std::string& addrName); @@ -137,6 +136,7 @@ class CConnman void GetBanned(banmap_t &banmap); void SetBanned(const banmap_t &banmap); + void AddOneShot(const std::string& strDest); private: struct ListenSocket { SOCKET socket; @@ -171,6 +171,8 @@ class CConnman bool setBannedIsDirty; bool fAddressesInitialized; CAddrMan addrman; + std::deque vOneShots; + CCriticalSection cs_vOneShots; }; extern std::unique_ptr g_connman; void MapPort(bool fUseUPnP); From 8ae2dac1c65349e4620422a43b7fa9d49af52c11 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Sat, 16 Apr 2016 18:12:58 -0400 Subject: [PATCH 0843/1802] net: move added node functions to CConnman --- src/net.cpp | 29 +++++++++++++++++++++++++---- src/net.h | 28 +++++++++++++++------------- src/rpc/net.cpp | 17 ++++++----------- 3 files changed, 46 insertions(+), 28 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 045939c2ea19f..8ca6df0f9ba09 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -91,9 +91,6 @@ std::vector vNodes; CCriticalSection cs_vNodes; limitedmap mapAlreadyAskedFor(MAX_INV_SZ); -std::vector vAddedNodes; -CCriticalSection cs_vAddedNodes; - NodeId nLastNodeId = 0; CCriticalSection cs_nLastNodeId; @@ -1718,7 +1715,7 @@ void CConnman::ThreadOpenConnections() } } -std::vector GetAddedNodeInfo() +std::vector CConnman::GetAddedNodeInfo() { std::vector ret; @@ -2246,6 +2243,30 @@ std::vector CConnman::GetAddresses() return addrman.GetAddr(); } +bool CConnman::AddNode(const std::string& strNode) +{ + LOCK(cs_vAddedNodes); + for(std::vector::const_iterator it = vAddedNodes.begin(); it != vAddedNodes.end(); ++it) { + if (strNode == *it) + return false; + } + + vAddedNodes.push_back(strNode); + return true; +} + +bool CConnman::RemoveAddedNode(const std::string& strNode) +{ + LOCK(cs_vAddedNodes); + for(std::vector::iterator it = vAddedNodes.begin(); it != vAddedNodes.end(); ++it) { + if (strNode == *it) { + vAddedNodes.erase(it); + return true; + } + } + return false; +} + void RelayTransaction(const CTransaction& tx) { CInv inv(MSG_TX, tx.GetHash()); diff --git a/src/net.h b/src/net.h index 81de7f5a98f06..f343646cba78e 100644 --- a/src/net.h +++ b/src/net.h @@ -87,6 +87,14 @@ unsigned int SendBufferSize(); typedef int NodeId; +struct AddedNodeInfo +{ + std::string strAddedNode; + CService resolvedAddress; + bool fConnected; + bool fInbound; +}; + CNode* FindNode(const CNetAddr& ip); CNode* FindNode(const CSubNet& subNet); CNode* FindNode(const std::string& addrName); @@ -137,6 +145,11 @@ class CConnman void SetBanned(const banmap_t &banmap); void AddOneShot(const std::string& strDest); + + bool AddNode(const std::string& node); + bool RemoveAddedNode(const std::string& node); + std::vector GetAddedNodeInfo(); + private: struct ListenSocket { SOCKET socket; @@ -173,6 +186,8 @@ class CConnman CAddrMan addrman; std::deque vOneShots; CCriticalSection cs_vOneShots; + std::vector vAddedNodes; + CCriticalSection cs_vAddedNodes; }; extern std::unique_ptr g_connman; void MapPort(bool fUseUPnP); @@ -252,9 +267,6 @@ extern std::vector vNodes; extern CCriticalSection cs_vNodes; extern limitedmap mapAlreadyAskedFor; -extern std::vector vAddedNodes; -extern CCriticalSection cs_vAddedNodes; - extern NodeId nLastNodeId; extern CCriticalSection cs_nLastNodeId; @@ -807,14 +819,4 @@ void RelayTransaction(const CTransaction& tx); /** Return a timestamp in the future (in microseconds) for exponentially distributed events. */ int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds); -struct AddedNodeInfo -{ - std::string strAddedNode; - CService resolvedAddress; - bool fConnected; - bool fInbound; -}; - -std::vector GetAddedNodeInfo(); - #endif // BITCOIN_NET_H diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 0244da9fea746..ab475f7125ffb 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -226,23 +226,15 @@ UniValue addnode(const UniValue& params, bool fHelp) return NullUniValue; } - LOCK(cs_vAddedNodes); - vector::iterator it = vAddedNodes.begin(); - for(; it != vAddedNodes.end(); it++) - if (strNode == *it) - break; - if (strCommand == "add") { - if (it != vAddedNodes.end()) + if(!g_connman->AddNode(strNode)) throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added"); - vAddedNodes.push_back(strNode); } else if(strCommand == "remove") { - if (it == vAddedNodes.end()) + if(!g_connman->RemoveAddedNode(strNode)) throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added."); - vAddedNodes.erase(it); } return NullUniValue; @@ -299,7 +291,10 @@ UniValue getaddednodeinfo(const UniValue& params, bool fHelp) + HelpExampleRpc("getaddednodeinfo", "true, \"192.168.0.201\"") ); - std::vector vInfo = GetAddedNodeInfo(); + if(!g_connman) + throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); + + std::vector vInfo = g_connman->GetAddedNodeInfo(); if (params.size() == 1) { bool found = false; From c0569c7fa1e25599b3f1d6a16b15ec23052021da Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Sat, 16 Apr 2016 18:30:03 -0400 Subject: [PATCH 0844/1802] net: Add most functions needed for vNodes to CConnman --- src/net.cpp | 66 +++++++++++++++++++++++++++++++++++++++ src/net.h | 16 ++++++++++ src/qt/clientmodel.cpp | 22 +++++++------ src/qt/peertablemodel.cpp | 15 ++++----- src/qt/rpcconsole.cpp | 8 ++--- src/rpc/mining.cpp | 5 ++- src/rpc/misc.cpp | 3 +- src/rpc/net.cpp | 36 ++++++++------------- 8 files changed, 123 insertions(+), 48 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 8ca6df0f9ba09..e1cfc565d6051 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2267,6 +2267,72 @@ bool CConnman::RemoveAddedNode(const std::string& strNode) return false; } +size_t CConnman::GetNodeCount(NumConnections flags) +{ + LOCK(cs_vNodes); + if (flags == CConnman::CONNECTIONS_ALL) // Shortcut if we want total + return vNodes.size(); + + int nNum = 0; + for(std::vector::const_iterator it = vNodes.begin(); it != vNodes.end(); ++it) + if (flags & ((*it)->fInbound ? CONNECTIONS_IN : CONNECTIONS_OUT)) + nNum++; + + return nNum; +} + +void CConnman::GetNodeStats(std::vector& vstats) +{ + vstats.clear(); + LOCK(cs_vNodes); + vstats.reserve(vNodes.size()); + for(std::vector::iterator it = vNodes.begin(); it != vNodes.end(); ++it) { + CNode* pnode = *it; + CNodeStats stats; + pnode->copyStats(stats); + vstats.push_back(stats); + } +} + +bool CConnman::DisconnectAddress(const CNetAddr& netAddr) +{ + if (CNode* pnode = FindNode(netAddr)) { + pnode->fDisconnect = true; + return true; + } + return false; +} + +bool CConnman::DisconnectSubnet(const CSubNet& subNet) +{ + if (CNode* pnode = FindNode(subNet)) { + pnode->fDisconnect = true; + return true; + } + return false; +} + +bool CConnman::DisconnectNode(const std::string& strNode) +{ + if (CNode* pnode = FindNode(strNode)) { + pnode->fDisconnect = true; + return true; + } + return false; +} + +bool CConnman::DisconnectNode(NodeId id) +{ + LOCK(cs_vNodes); + for(CNode* pnode : vNodes) { + if (id == pnode->id) { + pnode->fDisconnect = true; + return true; + } + } + return false; +} + void RelayTransaction(const CTransaction& tx) { CInv inv(MSG_TX, tx.GetHash()); diff --git a/src/net.h b/src/net.h index f343646cba78e..9e2408cd7052b 100644 --- a/src/net.h +++ b/src/net.h @@ -101,9 +101,18 @@ CNode* FindNode(const std::string& addrName); CNode* FindNode(const CService& ip); CNode* FindNode(const NodeId id); //TODO: Remove this +class CNodeStats; class CConnman { public: + + enum NumConnections { + CONNECTIONS_NONE = 0, + CONNECTIONS_IN = (1U << 0), + CONNECTIONS_OUT = (1U << 1), + CONNECTIONS_ALL = (CONNECTIONS_IN | CONNECTIONS_OUT), + }; + CConnman(); ~CConnman(); bool Start(boost::thread_group& threadGroup, CScheduler& scheduler, std::string& strNodeError); @@ -150,6 +159,13 @@ class CConnman bool RemoveAddedNode(const std::string& node); std::vector GetAddedNodeInfo(); + size_t GetNodeCount(NumConnections num); + void GetNodeStats(std::vector& vstats); + bool DisconnectAddress(const CNetAddr& addr); + bool DisconnectNode(const std::string& node); + bool DisconnectNode(NodeId id); + bool DisconnectSubnet(const CSubNet& subnet); + private: struct ListenSocket { SOCKET socket; diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 14661b857a5a5..f72bbfe6bbd09 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -50,16 +50,18 @@ ClientModel::~ClientModel() int ClientModel::getNumConnections(unsigned int flags) const { - LOCK(cs_vNodes); - if (flags == CONNECTIONS_ALL) // Shortcut if we want total - return vNodes.size(); - - int nNum = 0; - BOOST_FOREACH(const CNode* pnode, vNodes) - if (flags & (pnode->fInbound ? CONNECTIONS_IN : CONNECTIONS_OUT)) - nNum++; - - return nNum; + CConnman::NumConnections connections = CConnman::CONNECTIONS_NONE; + + if(flags == CONNECTIONS_IN) + connections = CConnman::CONNECTIONS_IN; + else if (flags == CONNECTIONS_OUT) + connections = CConnman::CONNECTIONS_OUT; + else if (flags == CONNECTIONS_ALL) + connections = CConnman::CONNECTIONS_ALL; + + if(g_connman) + return g_connman->GetNodeCount(connections); + return 0; } int ClientModel::getNumBlocks() const diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp index 0eb28f4ae18e8..a820bd791f70b 100644 --- a/src/qt/peertablemodel.cpp +++ b/src/qt/peertablemodel.cpp @@ -54,24 +54,21 @@ class PeerTablePriv void refreshPeers() { { - TRY_LOCK(cs_vNodes, lockNodes); - if (!lockNodes) - { - // skip the refresh if we can't immediately get the lock - return; - } cachedNodeStats.clear(); + std::vector vstats; + if(g_connman) + g_connman->GetNodeStats(vstats); #if QT_VERSION >= 0x040700 - cachedNodeStats.reserve(vNodes.size()); + cachedNodeStats.reserve(vstats.size()); #endif - Q_FOREACH (CNode* pnode, vNodes) + Q_FOREACH (const CNodeStats& nodestats, vstats) { CNodeCombinedStats stats; stats.nodeStateStats.nMisbehavior = 0; stats.nodeStateStats.nSyncHeight = -1; stats.nodeStateStats.nCommonHeight = -1; stats.fNodeStateStatsAvailable = false; - pnode->copyStats(stats.nodeStats); + stats.nodeStats = nodestats; cachedNodeStats.append(stats); } } diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 708be6b646e8a..f35f401d06b44 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -876,13 +876,13 @@ void RPCConsole::showBanTableContextMenu(const QPoint& point) void RPCConsole::disconnectSelectedNode() { + if(!g_connman) + return; // Get currently selected peer address - QString strNode = GUIUtil::getEntryData(ui->peerWidget, 0, PeerTableModel::Address).toString(); + NodeId id = GUIUtil::getEntryData(ui->peerWidget, 0, PeerTableModel::NetNodeId).toInt(); // Find the node, disconnect it and clear the selected node - if (CNode *bannedNode = FindNode(strNode.toStdString())) { - bannedNode->fDisconnect = true; + if(g_connman->DisconnectNode(id)) clearSelectedNode(); - } } void RPCConsole::banSelectedNode(int bantime) diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 63ecf49ecd697..7794ac619d212 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -457,7 +457,10 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) if (strMode != "template") throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode"); - if (vNodes.empty()) + if(!g_connman) + throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); + + if (g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0) throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Bitcoin is not connected!"); if (IsInitialBlockDownload()) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index e96feaa864939..f9f1615614cd9 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -89,7 +89,8 @@ UniValue getinfo(const UniValue& params, bool fHelp) #endif obj.push_back(Pair("blocks", (int)chainActive.Height())); obj.push_back(Pair("timeoffset", GetTimeOffset())); - obj.push_back(Pair("connections", (int)vNodes.size())); + if(g_connman) + obj.push_back(Pair("connections", (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL))); obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string()))); obj.push_back(Pair("difficulty", (double)GetDifficulty())); obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC())); diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index ab475f7125ffb..0d494a2e792ae 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -36,9 +36,10 @@ UniValue getconnectioncount(const UniValue& params, bool fHelp) + HelpExampleRpc("getconnectioncount", "") ); - LOCK2(cs_main, cs_vNodes); + if(!g_connman) + throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); - return (int)vNodes.size(); + return (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL); } UniValue ping(const UniValue& params, bool fHelp) @@ -64,19 +65,6 @@ UniValue ping(const UniValue& params, bool fHelp) return NullUniValue; } -static void CopyNodeStats(std::vector& vstats) -{ - vstats.clear(); - - LOCK(cs_vNodes); - vstats.reserve(vNodes.size()); - BOOST_FOREACH(CNode* pnode, vNodes) { - CNodeStats stats; - pnode->copyStats(stats); - vstats.push_back(stats); - } -} - UniValue getpeerinfo(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 0) @@ -127,10 +115,11 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp) + HelpExampleRpc("getpeerinfo", "") ); - LOCK(cs_main); + if(!g_connman) + throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); vector vstats; - CopyNodeStats(vstats); + g_connman->GetNodeStats(vstats); UniValue ret(UniValue::VARR); @@ -253,11 +242,12 @@ UniValue disconnectnode(const UniValue& params, bool fHelp) + HelpExampleRpc("disconnectnode", "\"192.168.0.6:8333\"") ); - CNode* pNode = FindNode(params[0].get_str()); - if (pNode == NULL) - throw JSONRPCError(RPC_CLIENT_NODE_NOT_CONNECTED, "Node not found in connected nodes"); + if(!g_connman) + throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); - pNode->fDisconnect = true; + bool ret = g_connman->DisconnectNode(params[0].get_str()); + if (!ret) + throw JSONRPCError(RPC_CLIENT_NODE_NOT_CONNECTED, "Node not found in connected nodes"); return NullUniValue; } @@ -435,7 +425,6 @@ UniValue getnetworkinfo(const UniValue& params, bool fHelp) ); LOCK(cs_main); - UniValue obj(UniValue::VOBJ); obj.push_back(Pair("version", CLIENT_VERSION)); obj.push_back(Pair("subversion", strSubVersion)); @@ -443,7 +432,8 @@ UniValue getnetworkinfo(const UniValue& params, bool fHelp) obj.push_back(Pair("localservices", strprintf("%016x", nLocalServices))); obj.push_back(Pair("localrelay", fRelayTxes)); obj.push_back(Pair("timeoffset", GetTimeOffset())); - obj.push_back(Pair("connections", (int)vNodes.size())); + if(g_connman) + obj.push_back(Pair("connections", (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL))); obj.push_back(Pair("networks", GetNetworksInfo())); obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()))); UniValue localAddresses(UniValue::VARR); From 53347f0cb99e514815e44a56439a4a10012238f8 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Sat, 16 Apr 2016 19:13:12 -0400 Subject: [PATCH 0845/1802] net: create generic functor accessors and move vNodes to CConnman --- src/main.cpp | 85 ++++++++++++++++++++++++-------------- src/net.cpp | 83 ++++++++++++++++++++++++++++--------- src/net.h | 27 +++++++----- src/rpc/misc.cpp | 9 ++-- src/rpc/net.cpp | 13 +++--- src/rpc/rawtransaction.cpp | 9 +++- src/wallet/wallet.cpp | 11 ++++- 7 files changed, 164 insertions(+), 73 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index f3babb71d219d..af598d48739a2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -470,7 +470,7 @@ void UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) { } } -void MaybeSetPeerAsAnnouncingHeaderAndIDs(const CNodeState* nodestate, CNode* pfrom) { +void MaybeSetPeerAsAnnouncingHeaderAndIDs(const CNodeState* nodestate, CNode* pfrom, CConnman& connman) { if (nLocalServices & NODE_WITNESS) { // Don't ever request compact blocks when segwit is enabled. return; @@ -484,11 +484,12 @@ void MaybeSetPeerAsAnnouncingHeaderAndIDs(const CNodeState* nodestate, CNode* pf if (lNodesAnnouncingHeaderAndIDs.size() >= 3) { // As per BIP152, we only get 3 of our peers to announce // blocks using compact encodings. - CNode* pnodeStop = FindNode(lNodesAnnouncingHeaderAndIDs.front()); - if (pnodeStop) { + bool found = connman.ForNode(lNodesAnnouncingHeaderAndIDs.front(), [fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion](CNode* pnodeStop){ pnodeStop->PushMessage(NetMsgType::SENDCMPCT, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion); + return true; + }); + if(found) lNodesAnnouncingHeaderAndIDs.pop_front(); - } } fAnnounceUsingCMPCTBLOCK = true; pfrom->PushMessage(NetMsgType::SENDCMPCT, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion); @@ -3089,15 +3090,15 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, int nBlockEstimate = 0; if (fCheckpointsEnabled) nBlockEstimate = Checkpoints::GetTotalBlocksEstimate(chainparams.Checkpoints()); - { - LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) { + if(connman) { + connman->ForEachNode([nNewHeight, nBlockEstimate, &vHashes](CNode* pnode) { if (nNewHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate)) { BOOST_REVERSE_FOREACH(const uint256& hash, vHashes) { pnode->PushBlockHash(hash); } } - } + return true; + }); } // Notify external listeners about the new tip. if (!vHashes.empty()) { @@ -4726,6 +4727,45 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main) return true; } +static void RelayTransaction(const CTransaction& tx, CConnman& connman) +{ + CInv inv(MSG_TX, tx.GetHash()); + connman.ForEachNode([&inv](CNode* pnode) + { + pnode->PushInventory(inv); + return true; + }); +} + +static void RelayAddress(const CAddress& addr, bool fReachable, CConnman& connman) +{ + int nRelayNodes = fReachable ? 2 : 1; // limited relaying of addresses outside our network(s) + + // Relay to a limited number of other nodes + // Use deterministic randomness to send to the same nodes for 24 hours + // at a time so the addrKnowns of the chosen nodes prevent repeats + static const uint64_t salt0 = GetRand(std::numeric_limits::max()); + static const uint64_t salt1 = GetRand(std::numeric_limits::max()); + uint64_t hashAddr = addr.GetHash(); + std::multimap mapMix; + const CSipHasher hasher = CSipHasher(salt0, salt1).Write(hashAddr << 32).Write((GetTime() + hashAddr) / (24*60*60)); + + auto sortfunc = [&mapMix, &hasher](CNode* pnode) { + if (pnode->nVersion >= CADDR_TIME_VERSION) { + uint64_t hashKey = CSipHasher(hasher).Write(pnode->id).Finalize(); + mapMix.emplace(hashKey, pnode); + } + return true; + }; + + auto pushfunc = [&addr, &mapMix, &nRelayNodes] { + for (auto mi = mapMix.begin(); mi != mapMix.end() && nRelayNodes-- > 0; ++mi) + mi->second->PushAddress(addr); + }; + + connman.ForEachNodeThen(std::move(sortfunc), std::move(pushfunc)); +} + void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParams) { std::deque::iterator it = pfrom->vRecvGetData.begin(); @@ -5135,26 +5175,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, if (addr.nTime > nSince && !pfrom->fGetAddr && vAddr.size() <= 10 && addr.IsRoutable()) { // Relay to a limited number of other nodes - { - LOCK(cs_vNodes); - // Use deterministic randomness to send to the same nodes for 24 hours - // at a time so the addrKnowns of the chosen nodes prevent repeats - static const uint64_t salt0 = GetRand(std::numeric_limits::max()); - static const uint64_t salt1 = GetRand(std::numeric_limits::max()); - uint64_t hashAddr = addr.GetHash(); - multimap mapMix; - const CSipHasher hasher = CSipHasher(salt0, salt1).Write(hashAddr << 32).Write((GetTime() + hashAddr) / (24*60*60)); - BOOST_FOREACH(CNode* pnode, vNodes) - { - if (pnode->nVersion < CADDR_TIME_VERSION) - continue; - uint64_t hashKey = CSipHasher(hasher).Write(pnode->id).Finalize(); - mapMix.insert(make_pair(hashKey, pnode)); - } - int nRelayNodes = fReachable ? 2 : 1; // limited relaying of addresses outside our network(s) - for (multimap::iterator mi = mapMix.begin(); mi != mapMix.end() && nRelayNodes-- > 0; ++mi) - ((*mi).second)->PushAddress(addr); - } + RelayAddress(addr, fReachable, connman); } // Do not store addresses outside our network if (fReachable) @@ -5448,7 +5469,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, if (!AlreadyHave(inv) && AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs)) { mempool.check(pcoinsTip); - RelayTransaction(tx); + RelayTransaction(tx, connman); for (unsigned int i = 0; i < tx.vout.size(); i++) { vWorkQueue.emplace_back(inv.hash, i); } @@ -5485,7 +5506,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, continue; if (AcceptToMemoryPool(mempool, stateDummy, orphanTx, true, &fMissingInputs2)) { LogPrint("mempool", " accepted orphan tx %s\n", orphanHash.ToString()); - RelayTransaction(orphanTx); + RelayTransaction(orphanTx, connman); for (unsigned int i = 0; i < orphanTx.vout.size(); i++) { vWorkQueue.emplace_back(orphanHash, i); } @@ -5560,7 +5581,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int nDoS = 0; if (!state.IsInvalid(nDoS) || nDoS == 0) { LogPrintf("Force relaying tx %s from whitelisted peer=%d\n", tx.GetHash().ToString(), pfrom->id); - RelayTransaction(tx); + RelayTransaction(tx, connman); } else { LogPrintf("Not relaying invalid transaction %s from whitelisted peer=%d (%s)\n", tx.GetHash().ToString(), pfrom->id, FormatStateMessage(state)); } @@ -5886,7 +5907,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, if (nodestate->fProvidesHeaderAndIDs && vGetData.size() == 1 && mapBlocksInFlight.size() == 1 && pindexLast->pprev->IsValid(BLOCK_VALID_CHAIN) && !(nLocalServices & NODE_WITNESS)) { // We seem to be rather well-synced, so it appears pfrom was the first to provide us // with this block! Let's get them to announce using compact blocks in the future. - MaybeSetPeerAsAnnouncingHeaderAndIDs(nodestate, pfrom); + MaybeSetPeerAsAnnouncingHeaderAndIDs(nodestate, pfrom, connman); // In any case, we want to download using a compact block, not a regular one vGetData[0] = CInv(MSG_CMPCT_BLOCK, vGetData[0].hash); } diff --git a/src/net.cpp b/src/net.cpp index e1cfc565d6051..f20f63e04d273 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -87,8 +87,6 @@ uint64_t nLocalHostNonce = 0; int nMaxConnections = DEFAULT_MAX_PEER_CONNECTIONS; std::string strSubVersion; -std::vector vNodes; -CCriticalSection cs_vNodes; limitedmap mapAlreadyAskedFor(MAX_INV_SZ); NodeId nLastNodeId = 0; @@ -315,7 +313,7 @@ uint64_t CNode::nMaxOutboundTotalBytesSentInCycle = 0; uint64_t CNode::nMaxOutboundTimeframe = 60*60*24; //1 day uint64_t CNode::nMaxOutboundCycleStartTime = 0; -CNode* FindNode(const CNetAddr& ip) +CNode* CConnman::FindNode(const CNetAddr& ip) { LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) @@ -324,7 +322,7 @@ CNode* FindNode(const CNetAddr& ip) return NULL; } -CNode* FindNode(const CSubNet& subNet) +CNode* CConnman::FindNode(const CSubNet& subNet) { LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) @@ -333,7 +331,7 @@ CNode* FindNode(const CSubNet& subNet) return NULL; } -CNode* FindNode(const std::string& addrName) +CNode* CConnman::FindNode(const std::string& addrName) { LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) @@ -342,7 +340,7 @@ CNode* FindNode(const std::string& addrName) return NULL; } -CNode* FindNode(const CService& addr) +CNode* CConnman::FindNode(const CService& addr) { LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) @@ -351,16 +349,6 @@ CNode* FindNode(const CService& addr) return NULL; } -//TODO: This is used in only one place in main, and should be removed -CNode* FindNode(const NodeId nodeid) -{ - LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) - if (pnode->GetId() == nodeid) - return (pnode); - return NULL; -} - CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure) { if (pszDest == NULL) { @@ -899,7 +887,8 @@ static bool CompareNodeTXTime(const NodeEvictionCandidate &a, const NodeEviction * to forge. In order to partition a node the attacker must be * simultaneously better at all of them than honest peers. */ -static bool AttemptToEvictConnection() { +bool CConnman::AttemptToEvictConnection() +{ std::vector vEvictionCandidates; { LOCK(cs_vNodes); @@ -2320,7 +2309,6 @@ bool CConnman::DisconnectNode(const std::string& strNode) } return false; } - bool CConnman::DisconnectNode(NodeId id) { LOCK(cs_vNodes); @@ -2333,7 +2321,7 @@ bool CConnman::DisconnectNode(NodeId id) return false; } -void RelayTransaction(const CTransaction& tx) +void CConnman::RelayTransaction(const CTransaction& tx) { CInv inv(MSG_TX, tx.GetHash()); LOCK(cs_vNodes); @@ -2671,6 +2659,63 @@ void CNode::EndMessage(const char* pszCommand) UNLOCK_FUNCTION(cs_vSend) LEAVE_CRITICAL_SECTION(cs_vSend); } +bool CConnman::ForNode(NodeId id, std::function func) +{ + CNode* found = nullptr; + LOCK(cs_vNodes); + for (auto&& pnode : vNodes) { + if(pnode->id == id) { + found = pnode; + break; + } + } + return found != nullptr && func(found); +} + +bool CConnman::ForEachNode(std::function func) +{ + LOCK(cs_vNodes); + for (auto&& node : vNodes) + if(!func(node)) + return false; + return true; +} + +bool CConnman::ForEachNode(std::function func) const +{ + LOCK(cs_vNodes); + for (const auto& node : vNodes) + if(!func(node)) + return false; + return true; +} + +bool CConnman::ForEachNodeThen(std::function pre, std::function post) +{ + bool ret = true; + LOCK(cs_vNodes); + for (auto&& node : vNodes) + if(!pre(node)) { + ret = false; + break; + } + post(); + return ret; +} + +bool CConnman::ForEachNodeThen(std::function pre, std::function post) const +{ + bool ret = true; + LOCK(cs_vNodes); + for (const auto& node : vNodes) + if(!pre(node)) { + ret = false; + break; + } + post(); + return ret; +} + int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds) { return nNow + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5); } diff --git a/src/net.h b/src/net.h index 9e2408cd7052b..5b1e80bfbe3a8 100644 --- a/src/net.h +++ b/src/net.h @@ -95,12 +95,7 @@ struct AddedNodeInfo bool fInbound; }; -CNode* FindNode(const CNetAddr& ip); -CNode* FindNode(const CSubNet& subNet); -CNode* FindNode(const std::string& addrName); -CNode* FindNode(const CService& ip); -CNode* FindNode(const NodeId id); //TODO: Remove this - +class CTransaction; class CNodeStats; class CConnman { @@ -120,6 +115,14 @@ class CConnman bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false, bool fFeeler = false); + bool ForNode(NodeId id, std::function func); + bool ForEachNode(std::function func); + bool ForEachNode(std::function func) const; + bool ForEachNodeThen(std::function pre, std::function post); + bool ForEachNodeThen(std::function pre, std::function post) const; + + void RelayTransaction(const CTransaction& tx); + // Addrman functions size_t GetAddressCount() const; void SetServices(const CService &addr, ServiceFlags nServices); @@ -182,6 +185,12 @@ class CConnman void ThreadSocketHandler(); void ThreadDNSAddressSeed(); + CNode* FindNode(const CNetAddr& ip); + CNode* FindNode(const CSubNet& subNet); + CNode* FindNode(const std::string& addrName); + CNode* FindNode(const CService& addr); + + bool AttemptToEvictConnection(); CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure); void DeleteNode(CNode* pnode); //!check is the banlist has unwritten changes @@ -204,6 +213,8 @@ class CConnman CCriticalSection cs_vOneShots; std::vector vAddedNodes; CCriticalSection cs_vAddedNodes; + std::vector vNodes; + mutable CCriticalSection cs_vNodes; }; extern std::unique_ptr g_connman; void MapPort(bool fUseUPnP); @@ -279,8 +290,6 @@ extern uint64_t nLocalHostNonce; /** Maximum number of connections to simultaneously allow (aka connection slots) */ extern int nMaxConnections; -extern std::vector vNodes; -extern CCriticalSection cs_vNodes; extern limitedmap mapAlreadyAskedFor; extern NodeId nLastNodeId; @@ -828,8 +837,6 @@ class CNode -class CTransaction; -void RelayTransaction(const CTransaction& tx); /** Return a timestamp in the future (in microseconds) for exponentially distributed events. */ diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index f9f1615614cd9..ffd377b4892fd 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -472,14 +472,17 @@ UniValue setmocktime(const UniValue& params, bool fHelp) // atomically with the time change to prevent peers from being // disconnected because we think we haven't communicated with them // in a long time. - LOCK2(cs_main, cs_vNodes); + LOCK(cs_main); RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM)); SetMockTime(params[0].get_int64()); uint64_t t = GetTime(); - BOOST_FOREACH(CNode* pnode, vNodes) { - pnode->nLastSend = pnode->nLastRecv = t; + if(g_connman) { + g_connman->ForEachNode([t](CNode* pnode) { + pnode->nLastSend = pnode->nLastRecv = t; + return true; + }); } return NullUniValue; diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 0d494a2e792ae..509b57aa726ed 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -55,13 +55,14 @@ UniValue ping(const UniValue& params, bool fHelp) + HelpExampleRpc("ping", "") ); - // Request that each node send a ping during next message processing pass - LOCK2(cs_main, cs_vNodes); - - BOOST_FOREACH(CNode* pNode, vNodes) { - pNode->fPingQueued = true; - } + if(!g_connman) + throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); + // Request that each node send a ping during next message processing pass + g_connman->ForEachNode([](CNode* pnode) { + pnode->fPingQueued = true; + return true; + }); return NullUniValue; } diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 9461a7280ccac..3daf1681f314a 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -891,8 +891,15 @@ UniValue sendrawtransaction(const UniValue& params, bool fHelp) } else if (fHaveChain) { throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain"); } - RelayTransaction(tx); + if(!g_connman) + throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); + CInv inv(MSG_TX, hashTx); + g_connman->ForEachNode([&inv](CNode* pnode) + { + pnode->PushInventory(inv); + return true; + }); return hashTx.GetHex(); } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 4396c2a2b0125..fd8b056bfca03 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1460,8 +1460,15 @@ bool CWalletTx::RelayWalletTransaction(CConnman* connman) { if (GetDepthInMainChain() == 0 && !isAbandoned() && InMempool()) { LogPrintf("Relaying wtx %s\n", GetHash().ToString()); - RelayTransaction((CTransaction)*this); - return true; + if (connman) { + CInv inv(MSG_TX, GetHash()); + connman->ForEachNode([&inv](CNode* pnode) + { + pnode->PushInventory(inv); + return true; + }); + return true; + } } } return false; From 6c19d92361fe4afb26dfa5d48a0748b84bca6f12 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Sun, 17 Apr 2016 18:34:32 -0400 Subject: [PATCH 0846/1802] net: move whitelist functions into CConnman --- src/init.cpp | 2 +- src/net.cpp | 9 +++------ src/net.h | 16 ++++++++-------- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 719b648c04cfd..f618e5ccc566f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1146,7 +1146,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) LookupSubNet(net.c_str(), subnet); if (!subnet.IsValid()) return InitError(strprintf(_("Invalid netmask specified in -whitelist: '%s'"), net)); - CNode::AddWhitelistedRange(subnet); + connman.AddWhitelistedRange(subnet); } } diff --git a/src/net.cpp b/src/net.cpp index f20f63e04d273..eb312ef1e4d86 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -625,10 +625,7 @@ void CConnman::SetBannedSetDirty(bool dirty) } -std::vector CNode::vWhitelistedRange; -CCriticalSection CNode::cs_vWhitelistedRange; - -bool CNode::IsWhitelistedRange(const CNetAddr &addr) { +bool CConnman::IsWhitelistedRange(const CNetAddr &addr) { LOCK(cs_vWhitelistedRange); BOOST_FOREACH(const CSubNet& subnet, vWhitelistedRange) { if (subnet.Match(addr)) @@ -637,7 +634,7 @@ bool CNode::IsWhitelistedRange(const CNetAddr &addr) { return false; } -void CNode::AddWhitelistedRange(const CSubNet &subnet) { +void CConnman::AddWhitelistedRange(const CSubNet &subnet) { LOCK(cs_vWhitelistedRange); vWhitelistedRange.push_back(subnet); } @@ -992,7 +989,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) { if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr)) LogPrintf("Warning: Unknown socket family\n"); - bool whitelisted = hListenSocket.whitelisted || CNode::IsWhitelistedRange(addr); + bool whitelisted = hListenSocket.whitelisted || IsWhitelistedRange(addr); { LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) diff --git a/src/net.h b/src/net.h index 5b1e80bfbe3a8..8d9925265dba6 100644 --- a/src/net.h +++ b/src/net.h @@ -169,6 +169,7 @@ class CConnman bool DisconnectNode(NodeId id); bool DisconnectSubnet(const CSubNet& subnet); + void AddWhitelistedRange(const CSubNet &subnet); private: struct ListenSocket { SOCKET socket; @@ -192,6 +193,8 @@ class CConnman bool AttemptToEvictConnection(); CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure); + bool IsWhitelistedRange(const CNetAddr &addr); + void DeleteNode(CNode* pnode); //!check is the banlist has unwritten changes bool BannedSetIsDirty(); @@ -203,6 +206,11 @@ class CConnman void DumpData(); void DumpBanlist(); + // Whitelisted ranges. Any node connecting from these is automatically + // whitelisted (as well as those connecting to whitelisted binds). + std::vector vWhitelistedRange; + CCriticalSection cs_vWhitelistedRange; + std::vector vhListenSocket; banmap_t setBanned; CCriticalSection cs_setBanned; @@ -432,11 +440,6 @@ class CNode const uint64_t nKeyedNetGroup; protected: - // Whitelisted ranges. Any node connecting from these is automatically - // whitelisted (as well as those connecting to whitelisted binds). - static std::vector vWhitelistedRange; - static CCriticalSection cs_vWhitelistedRange; - mapMsgCmdSize mapSendBytesPerMsgCmd; mapMsgCmdSize mapRecvBytesPerMsgCmd; @@ -803,9 +806,6 @@ class CNode void copyStats(CNodeStats &stats); - static bool IsWhitelistedRange(const CNetAddr &ip); - static void AddWhitelistedRange(const CSubNet &subnet); - // Network stats static void RecordBytesRecv(uint64_t bytes); static void RecordBytesSent(uint64_t bytes); From 551e0887db9034b1e6490a267ba864b1d26ff469 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Sun, 17 Apr 2016 20:20:34 -0400 Subject: [PATCH 0847/1802] net: move nLastNodeId to CConnman --- src/net.cpp | 24 +++++++++++------------- src/net.h | 9 +++++---- src/test/DoS_tests.cpp | 10 ++++++---- src/test/net_tests.cpp | 5 +++-- 4 files changed, 25 insertions(+), 23 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index eb312ef1e4d86..8bc8ecc436fd2 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -89,9 +89,6 @@ std::string strSubVersion; limitedmap mapAlreadyAskedFor(MAX_INV_SZ); -NodeId nLastNodeId = 0; -CCriticalSection cs_nLastNodeId; - static CSemaphore *semOutbound = NULL; boost::condition_variable messageHandlerCondition; @@ -404,7 +401,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo addrman.Attempt(addrConnect, fCountFailure); // Add node - CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false); + CNode* pnode = new CNode(GetNewNodeId(), hSocket, addrConnect, pszDest ? pszDest : "", false); GetNodeSignals().InitializeNode(pnode->GetId(), pnode); pnode->AddRef(); @@ -1038,7 +1035,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) { } } - CNode* pnode = new CNode(hSocket, addr, "", true); + CNode* pnode = new CNode(GetNewNodeId(), hSocket, addr, "", true); GetNodeSignals().InitializeNode(pnode->GetId(), pnode); pnode->AddRef(); pnode->fWhitelisted = whitelisted; @@ -2030,6 +2027,7 @@ CConnman::CConnman() { setBannedIsDirty = false; fAddressesInitialized = false; + nLastNodeId = 0; } bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler& scheduler, std::string& strNodeError) @@ -2041,9 +2039,13 @@ bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler& return ret; } -bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, std::string& strNodeError) +NodeId CConnman::GetNewNodeId() { + return nLastNodeId.fetch_add(1, std::memory_order_relaxed); +} +bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, std::string& strNodeError) +{ uiInterface.InitMessage(_("Loading addresses...")); // Load addresses from peers.dat int64_t nStart = GetTimeMillis(); @@ -2089,7 +2091,7 @@ bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, st if (pnodeLocalHost == NULL) { CNetAddr local; LookupHost("127.0.0.1", local, false); - pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService(local, 0), nLocalServices)); + pnodeLocalHost = new CNode(GetNewNodeId(), INVALID_SOCKET, CAddress(CService(local, 0), nLocalServices)); GetNodeSignals().InitializeNode(pnodeLocalHost->GetId(), pnodeLocalHost); } @@ -2478,7 +2480,7 @@ void CNode::Fuzz(int nChance) unsigned int ReceiveFloodSize() { return 1000*GetArg("-maxreceivebuffer", DEFAULT_MAXRECEIVEBUFFER); } unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER); } -CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNameIn, bool fInboundIn) : +CNode::CNode(NodeId idIn, SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNameIn, bool fInboundIn) : ssSend(SER_NETWORK, INIT_PROTO_VERSION), addr(addrIn), nKeyedNetGroup(CalculateKeyedNetGroup(addrIn)), @@ -2531,16 +2533,12 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa minFeeFilter = 0; lastSentFeeFilter = 0; nextSendTimeFeeFilter = 0; + id = idIn; BOOST_FOREACH(const std::string &msg, getAllNetMessageTypes()) mapRecvBytesPerMsgCmd[msg] = 0; mapRecvBytesPerMsgCmd[NET_MESSAGE_COMMAND_OTHER] = 0; - { - LOCK(cs_nLastNodeId); - id = nLastNodeId++; - } - if (fLogIPs) LogPrint("net", "Added connection to %s peer=%d\n", addrName, id); else diff --git a/src/net.h b/src/net.h index 8d9925265dba6..36043b0b8cb00 100644 --- a/src/net.h +++ b/src/net.h @@ -196,6 +196,9 @@ class CConnman bool IsWhitelistedRange(const CNetAddr &addr); void DeleteNode(CNode* pnode); + + NodeId GetNewNodeId(); + //!check is the banlist has unwritten changes bool BannedSetIsDirty(); //!set the "dirty" flag for the banlist @@ -223,6 +226,7 @@ class CConnman CCriticalSection cs_vAddedNodes; std::vector vNodes; mutable CCriticalSection cs_vNodes; + std::atomic nLastNodeId; }; extern std::unique_ptr g_connman; void MapPort(bool fUseUPnP); @@ -300,9 +304,6 @@ extern int nMaxConnections; extern limitedmap mapAlreadyAskedFor; -extern NodeId nLastNodeId; -extern CCriticalSection cs_nLastNodeId; - /** Subversion as sent to the P2P network in `version` messages */ extern std::string strSubVersion; @@ -501,7 +502,7 @@ class CNode CAmount lastSentFeeFilter; int64_t nextSendTimeFeeFilter; - CNode(SOCKET hSocketIn, const CAddress &addrIn, const std::string &addrNameIn = "", bool fInboundIn = false); + CNode(NodeId id, SOCKET hSocketIn, const CAddress &addrIn, const std::string &addrNameIn = "", bool fInboundIn = false); ~CNode(); private: diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index 412f94f40d9dd..652a8e2ceadf7 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -40,13 +40,15 @@ CService ip(uint32_t i) return CService(CNetAddr(s), Params().GetDefaultPort()); } +static NodeId id = 0; + BOOST_FIXTURE_TEST_SUITE(DoS_tests, TestingSetup) BOOST_AUTO_TEST_CASE(DoS_banning) { connman->ClearBanned(); CAddress addr1(ip(0xa0b0c001), NODE_NONE); - CNode dummyNode1(INVALID_SOCKET, addr1, "", true); + CNode dummyNode1(id++, INVALID_SOCKET, addr1, "", true); GetNodeSignals().InitializeNode(dummyNode1.GetId(), &dummyNode1); dummyNode1.nVersion = 1; Misbehaving(dummyNode1.GetId(), 100); // Should get banned @@ -55,7 +57,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning) BOOST_CHECK(!connman->IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned CAddress addr2(ip(0xa0b0c002), NODE_NONE); - CNode dummyNode2(INVALID_SOCKET, addr2, "", true); + CNode dummyNode2(id++, INVALID_SOCKET, addr2, "", true); GetNodeSignals().InitializeNode(dummyNode2.GetId(), &dummyNode2); dummyNode2.nVersion = 1; Misbehaving(dummyNode2.GetId(), 50); @@ -72,7 +74,7 @@ BOOST_AUTO_TEST_CASE(DoS_banscore) connman->ClearBanned(); mapArgs["-banscore"] = "111"; // because 11 is my favorite number CAddress addr1(ip(0xa0b0c001), NODE_NONE); - CNode dummyNode1(INVALID_SOCKET, addr1, "", true); + CNode dummyNode1(id++, INVALID_SOCKET, addr1, "", true); GetNodeSignals().InitializeNode(dummyNode1.GetId(), &dummyNode1); dummyNode1.nVersion = 1; Misbehaving(dummyNode1.GetId(), 100); @@ -94,7 +96,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) SetMockTime(nStartTime); // Overrides future calls to GetTime() CAddress addr(ip(0xa0b0c001), NODE_NONE); - CNode dummyNode(INVALID_SOCKET, addr, "", true); + CNode dummyNode(id++, INVALID_SOCKET, addr, "", true); GetNodeSignals().InitializeNode(dummyNode.GetId(), &dummyNode); dummyNode.nVersion = 1; diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index 267d1b55e13e8..00fb757167717 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -153,6 +153,7 @@ BOOST_AUTO_TEST_CASE(caddrdb_read_corrupted) BOOST_AUTO_TEST_CASE(cnode_simple_test) { SOCKET hSocket = INVALID_SOCKET; + NodeId id = 0; in_addr ipv4Addr; ipv4Addr.s_addr = 0xa0b0c001; @@ -162,12 +163,12 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test) bool fInboundIn = false; // Test that fFeeler is false by default. - CNode* pnode1 = new CNode(hSocket, addr, pszDest, fInboundIn); + CNode* pnode1 = new CNode(id++, hSocket, addr, pszDest, fInboundIn); BOOST_CHECK(pnode1->fInbound == false); BOOST_CHECK(pnode1->fFeeler == false); fInboundIn = true; - CNode* pnode2 = new CNode(hSocket, addr, pszDest, fInboundIn); + CNode* pnode2 = new CNode(id++, hSocket, addr, pszDest, fInboundIn); BOOST_CHECK(pnode2->fInbound == true); BOOST_CHECK(pnode2->fFeeler == false); } From 960cf2e4058a9c195bf64e1aecb46024f9ef022a Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Sun, 17 Apr 2016 20:21:58 -0400 Subject: [PATCH 0848/1802] net: move nLocalHostNonce to CConnman This behavior seems to have been quite racy and broken. Move nLocalHostNonce into CNode, and check received nonces against all non-fully-connected nodes. If there's a match, assume we've connected to ourself. --- src/main.cpp | 2 +- src/net.cpp | 14 ++++++++++++-- src/net.h | 7 ++++++- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index af598d48739a2..43ccb6374c35e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5025,7 +5025,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } // Disconnect if we connected to ourself - if (nNonce == nLocalHostNonce && nNonce > 1) + if (pfrom->fInbound && !connman.CheckIncomingNonce(nNonce)) { LogPrintf("connected to self at %s, disconnecting\n", pfrom->addr.ToString()); pfrom->fDisconnect = true; diff --git a/src/net.cpp b/src/net.cpp index 8bc8ecc436fd2..71b4b01688201 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -83,7 +83,6 @@ CCriticalSection cs_mapLocalHost; std::map mapLocalHost; static bool vfLimited[NET_MAX] = {}; static CNode* pnodeLocalHost = NULL; -uint64_t nLocalHostNonce = 0; int nMaxConnections = DEFAULT_MAX_PEER_CONNECTIONS; std::string strSubVersion; @@ -346,6 +345,16 @@ CNode* CConnman::FindNode(const CService& addr) return NULL; } +bool CConnman::CheckIncomingNonce(uint64_t nonce) +{ + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) { + if (!pnode->fSuccessfullyConnected && !pnode->fInbound && pnode->GetLocalNonce() == nonce) + return false; + } + return true; +} + CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure) { if (pszDest == NULL) { @@ -465,7 +474,6 @@ void CNode::PushVersion() int64_t nTime = (fInbound ? GetAdjustedTime() : GetTime()); CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService(), addr.nServices)); CAddress addrMe = GetLocalAddress(&addr); - GetRandBytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce)); if (fLogIPs) LogPrint("net", "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), addrYou.ToString(), id); else @@ -2535,6 +2543,8 @@ CNode::CNode(NodeId idIn, SOCKET hSocketIn, const CAddress& addrIn, const std::s nextSendTimeFeeFilter = 0; id = idIn; + GetRandBytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce)); + BOOST_FOREACH(const std::string &msg, getAllNetMessageTypes()) mapRecvBytesPerMsgCmd[msg] = 0; mapRecvBytesPerMsgCmd[NET_MESSAGE_COMMAND_OTHER] = 0; diff --git a/src/net.h b/src/net.h index 36043b0b8cb00..32668045c5ed7 100644 --- a/src/net.h +++ b/src/net.h @@ -114,6 +114,7 @@ class CConnman void Stop(); bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false, bool fFeeler = false); + bool CheckIncomingNonce(uint64_t nonce); bool ForNode(NodeId id, std::function func); bool ForEachNode(std::function func); @@ -297,7 +298,6 @@ extern bool fListen; extern ServiceFlags nLocalServices; extern ServiceFlags nRelevantServices; extern bool fRelayTxes; -extern uint64_t nLocalHostNonce; /** Maximum number of connections to simultaneously allow (aka connection slots) */ extern int nMaxConnections; @@ -523,12 +523,17 @@ class CNode static uint64_t CalculateKeyedNetGroup(const CAddress& ad); + uint64_t nLocalHostNonce; public: NodeId GetId() const { return id; } + uint64_t GetLocalNonce() const { + return nLocalHostNonce; + } + int GetRefCount() { assert(nRefCount >= 0); From ee44fa95761724a83a76dd862a36bd9af0fc021f Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Mon, 18 Apr 2016 21:33:54 -0400 Subject: [PATCH 0849/1802] net: move messageHandlerCondition to CConnman --- src/net.cpp | 11 +++++++---- src/net.h | 3 ++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 71b4b01688201..a62ee2291c2f6 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -89,7 +89,6 @@ std::string strSubVersion; limitedmap mapAlreadyAskedFor(MAX_INV_SZ); static CSemaphore *semOutbound = NULL; -boost::condition_variable messageHandlerCondition; // Signals for message handling static CNodeSignals g_signals; @@ -688,8 +687,9 @@ void CNode::copyStats(CNodeStats &stats) #undef X // requires LOCK(cs_vRecvMsg) -bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes) +bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes, bool& complete) { + complete = false; while (nBytes > 0) { // get current incomplete message, or create a new one @@ -728,7 +728,7 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes) i->second += msg.hdr.nMessageSize + CMessageHeader::HEADER_SIZE; msg.nTime = GetTimeMicros(); - messageHandlerCondition.notify_one(); + complete = true; } } @@ -1247,8 +1247,11 @@ void CConnman::ThreadSocketHandler() int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT); if (nBytes > 0) { - if (!pnode->ReceiveMsgBytes(pchBuf, nBytes)) + bool notify = false; + if (!pnode->ReceiveMsgBytes(pchBuf, nBytes, notify)) pnode->CloseSocketDisconnect(); + if(notify) + messageHandlerCondition.notify_one(); pnode->nLastRecv = GetTime(); pnode->nRecvBytes += nBytes; pnode->RecordBytesRecv(nBytes); diff --git a/src/net.h b/src/net.h index 32668045c5ed7..0e83ff4a0c99b 100644 --- a/src/net.h +++ b/src/net.h @@ -228,6 +228,7 @@ class CConnman std::vector vNodes; mutable CCriticalSection cs_vNodes; std::atomic nLastNodeId; + boost::condition_variable messageHandlerCondition; }; extern std::unique_ptr g_connman; void MapPort(bool fUseUPnP); @@ -550,7 +551,7 @@ class CNode } // requires LOCK(cs_vRecvMsg) - bool ReceiveMsgBytes(const char *pch, unsigned int nBytes); + bool ReceiveMsgBytes(const char *pch, unsigned int nBytes, bool& complete); // requires LOCK(cs_vRecvMsg) void SetRecvVersion(int nVersionIn) From adf5d4c2e4e7a2979a6ca6de806151fe04c23162 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Sat, 21 May 2016 12:04:02 +0200 Subject: [PATCH 0850/1802] net: SocketSendData returns written size --- src/net.cpp | 5 ++++- src/net.h | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index a62ee2291c2f6..aded8d05d3fb5 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -791,9 +791,10 @@ int CNetMessage::readData(const char *pch, unsigned int nBytes) // requires LOCK(cs_vSend) -void SocketSendData(CNode *pnode) +size_t SocketSendData(CNode *pnode) { std::deque::iterator it = pnode->vSendMsg.begin(); + size_t nSentSize = 0; while (it != pnode->vSendMsg.end()) { const CSerializeData &data = *it; @@ -804,6 +805,7 @@ void SocketSendData(CNode *pnode) pnode->nSendBytes += nBytes; pnode->nSendOffset += nBytes; pnode->RecordBytesSent(nBytes); + nSentSize += nBytes; if (pnode->nSendOffset == data.size()) { pnode->nSendOffset = 0; pnode->nSendSize -= data.size(); @@ -832,6 +834,7 @@ void SocketSendData(CNode *pnode) assert(pnode->nSendSize == 0); } pnode->vSendMsg.erase(pnode->vSendMsg.begin(), it); + return nSentSize; } static std::list vNodesDisconnected; diff --git a/src/net.h b/src/net.h index 0e83ff4a0c99b..503e009c49886 100644 --- a/src/net.h +++ b/src/net.h @@ -236,7 +236,7 @@ unsigned short GetListenPort(); bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler& scheduler, std::string& strNodeError); bool StopNode(CConnman& connman); -void SocketSendData(CNode *pnode); +size_t SocketSendData(CNode *pnode); struct CombinerAll { From 63cafa6329e1a0a1daf2d324931aca42ba1cbb19 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Mon, 18 Apr 2016 21:44:42 -0400 Subject: [PATCH 0851/1802] net: move send/recv statistics to CConnman --- src/init.cpp | 2 +- src/main.cpp | 10 +++--- src/net.cpp | 63 +++++++++++++++++--------------- src/net.h | 82 +++++++++++++++++++++--------------------- src/qt/clientmodel.cpp | 8 +++-- src/rpc/net.cpp | 18 +++++----- 6 files changed, 99 insertions(+), 84 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index f618e5ccc566f..a7f893c24fef0 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1240,7 +1240,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) } #endif if (mapArgs.count("-maxuploadtarget")) { - CNode::SetMaxOutboundTarget(GetArg("-maxuploadtarget", DEFAULT_MAX_UPLOAD_TARGET)*1024*1024); + connman.SetMaxOutboundTarget(GetArg("-maxuploadtarget", DEFAULT_MAX_UPLOAD_TARGET)*1024*1024); } // ********************************************************* Step 7: load block chain diff --git a/src/main.cpp b/src/main.cpp index 43ccb6374c35e..019db0bdb39e0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4766,7 +4766,7 @@ static void RelayAddress(const CAddress& addr, bool fReachable, CConnman& connma connman.ForEachNodeThen(std::move(sortfunc), std::move(pushfunc)); } -void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParams) +void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParams, CConnman& connman) { std::deque::iterator it = pfrom->vRecvGetData.begin(); @@ -4808,7 +4808,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam // disconnect node in case we have reached the outbound limit for serving historical blocks // never disconnect whitelisted nodes static const int nOneWeek = 7 * 24 * 60 * 60; // assume > 1 week = historical - if (send && CNode::OutboundTargetReached(true) && ( ((pindexBestHeader != NULL) && (pindexBestHeader->GetBlockTime() - mi->second->GetBlockTime() > nOneWeek)) || inv.type == MSG_FILTERED_BLOCK) && !pfrom->fWhitelisted) + if (send && connman.OutboundTargetReached(true) && ( ((pindexBestHeader != NULL) && (pindexBestHeader->GetBlockTime() - mi->second->GetBlockTime() > nOneWeek)) || inv.type == MSG_FILTERED_BLOCK) && !pfrom->fWhitelisted) { LogPrint("net", "historical block serving limit reached, disconnect peer=%d\n", pfrom->GetId()); @@ -5312,7 +5312,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, LogPrint("net", "received getdata for: %s peer=%d\n", vInv[0].ToString(), pfrom->id); pfrom->vRecvGetData.insert(pfrom->vRecvGetData.end(), vInv.begin(), vInv.end()); - ProcessGetData(pfrom, chainparams.GetConsensus()); + ProcessGetData(pfrom, chainparams.GetConsensus(), connman); } @@ -5986,7 +5986,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, return true; } - if (CNode::OutboundTargetReached(false) && !pfrom->fWhitelisted) + if (connman.OutboundTargetReached(false) && !pfrom->fWhitelisted) { LogPrint("net", "mempool request with bandwidth limit reached, disconnect peer=%d\n", pfrom->GetId()); pfrom->fDisconnect = true; @@ -6202,7 +6202,7 @@ bool ProcessMessages(CNode* pfrom, CConnman& connman) bool fOk = true; if (!pfrom->vRecvGetData.empty()) - ProcessGetData(pfrom, chainparams.GetConsensus()); + ProcessGetData(pfrom, chainparams.GetConsensus(), connman); // this maintains the order of responses if (!pfrom->vRecvGetData.empty()) return fOk; diff --git a/src/net.cpp b/src/net.cpp index aded8d05d3fb5..0787b16ad6039 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -298,15 +298,6 @@ bool IsReachable(const CNetAddr& addr) return IsReachable(net); } -uint64_t CNode::nTotalBytesRecv = 0; -uint64_t CNode::nTotalBytesSent = 0; -CCriticalSection CNode::cs_totalBytesRecv; -CCriticalSection CNode::cs_totalBytesSent; - -uint64_t CNode::nMaxOutboundLimit = 0; -uint64_t CNode::nMaxOutboundTotalBytesSentInCycle = 0; -uint64_t CNode::nMaxOutboundTimeframe = 60*60*24; //1 day -uint64_t CNode::nMaxOutboundCycleStartTime = 0; CNode* CConnman::FindNode(const CNetAddr& ip) { @@ -804,7 +795,6 @@ size_t SocketSendData(CNode *pnode) pnode->nLastSend = GetTime(); pnode->nSendBytes += nBytes; pnode->nSendOffset += nBytes; - pnode->RecordBytesSent(nBytes); nSentSize += nBytes; if (pnode->nSendOffset == data.size()) { pnode->nSendOffset = 0; @@ -1176,9 +1166,15 @@ void CConnman::ThreadSocketHandler() // * We process a message in the buffer (message handler thread). { TRY_LOCK(pnode->cs_vSend, lockSend); - if (lockSend && !pnode->vSendMsg.empty()) { - FD_SET(pnode->hSocket, &fdsetSend); - continue; + if (lockSend) { + if (pnode->nOptimisticBytesWritten) { + RecordBytesSent(pnode->nOptimisticBytesWritten); + pnode->nOptimisticBytesWritten = 0; + } + if (!pnode->vSendMsg.empty()) { + FD_SET(pnode->hSocket, &fdsetSend); + continue; + } } } { @@ -1257,7 +1253,7 @@ void CConnman::ThreadSocketHandler() messageHandlerCondition.notify_one(); pnode->nLastRecv = GetTime(); pnode->nRecvBytes += nBytes; - pnode->RecordBytesRecv(nBytes); + RecordBytesRecv(nBytes); } else if (nBytes == 0) { @@ -1289,8 +1285,11 @@ void CConnman::ThreadSocketHandler() if (FD_ISSET(pnode->hSocket, &fdsetSend)) { TRY_LOCK(pnode->cs_vSend, lockSend); - if (lockSend) - SocketSendData(pnode); + if (lockSend) { + size_t nBytes = SocketSendData(pnode); + if (nBytes) + RecordBytesSent(nBytes); + } } // @@ -2060,6 +2059,13 @@ NodeId CConnman::GetNewNodeId() bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, std::string& strNodeError) { + nTotalBytesRecv = 0; + nTotalBytesSent = 0; + nMaxOutboundLimit = 0; + nMaxOutboundTotalBytesSentInCycle = 0; + nMaxOutboundTimeframe = 60*60*24; //1 day + nMaxOutboundCycleStartTime = 0; + uiInterface.InitMessage(_("Loading addresses...")); // Load addresses from peers.dat int64_t nStart = GetTimeMillis(); @@ -2344,13 +2350,13 @@ void CConnman::RelayTransaction(const CTransaction& tx) } } -void CNode::RecordBytesRecv(uint64_t bytes) +void CConnman::RecordBytesRecv(uint64_t bytes) { LOCK(cs_totalBytesRecv); nTotalBytesRecv += bytes; } -void CNode::RecordBytesSent(uint64_t bytes) +void CConnman::RecordBytesSent(uint64_t bytes) { LOCK(cs_totalBytesSent); nTotalBytesSent += bytes; @@ -2367,7 +2373,7 @@ void CNode::RecordBytesSent(uint64_t bytes) nMaxOutboundTotalBytesSentInCycle += bytes; } -void CNode::SetMaxOutboundTarget(uint64_t limit) +void CConnman::SetMaxOutboundTarget(uint64_t limit) { LOCK(cs_totalBytesSent); uint64_t recommendedMinimum = (nMaxOutboundTimeframe / 600) * MAX_BLOCK_SERIALIZED_SIZE; @@ -2377,19 +2383,19 @@ void CNode::SetMaxOutboundTarget(uint64_t limit) LogPrintf("Max outbound target is very small (%s bytes) and will be overshot. Recommended minimum is %s bytes.\n", nMaxOutboundLimit, recommendedMinimum); } -uint64_t CNode::GetMaxOutboundTarget() +uint64_t CConnman::GetMaxOutboundTarget() { LOCK(cs_totalBytesSent); return nMaxOutboundLimit; } -uint64_t CNode::GetMaxOutboundTimeframe() +uint64_t CConnman::GetMaxOutboundTimeframe() { LOCK(cs_totalBytesSent); return nMaxOutboundTimeframe; } -uint64_t CNode::GetMaxOutboundTimeLeftInCycle() +uint64_t CConnman::GetMaxOutboundTimeLeftInCycle() { LOCK(cs_totalBytesSent); if (nMaxOutboundLimit == 0) @@ -2403,7 +2409,7 @@ uint64_t CNode::GetMaxOutboundTimeLeftInCycle() return (cycleEndTime < now) ? 0 : cycleEndTime - GetTime(); } -void CNode::SetMaxOutboundTimeframe(uint64_t timeframe) +void CConnman::SetMaxOutboundTimeframe(uint64_t timeframe) { LOCK(cs_totalBytesSent); if (nMaxOutboundTimeframe != timeframe) @@ -2415,7 +2421,7 @@ void CNode::SetMaxOutboundTimeframe(uint64_t timeframe) nMaxOutboundTimeframe = timeframe; } -bool CNode::OutboundTargetReached(bool historicalBlockServingLimit) +bool CConnman::OutboundTargetReached(bool historicalBlockServingLimit) { LOCK(cs_totalBytesSent); if (nMaxOutboundLimit == 0) @@ -2435,7 +2441,7 @@ bool CNode::OutboundTargetReached(bool historicalBlockServingLimit) return false; } -uint64_t CNode::GetOutboundTargetBytesLeft() +uint64_t CConnman::GetOutboundTargetBytesLeft() { LOCK(cs_totalBytesSent); if (nMaxOutboundLimit == 0) @@ -2444,13 +2450,13 @@ uint64_t CNode::GetOutboundTargetBytesLeft() return (nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit) ? 0 : nMaxOutboundLimit - nMaxOutboundTotalBytesSentInCycle; } -uint64_t CNode::GetTotalBytesRecv() +uint64_t CConnman::GetTotalBytesRecv() { LOCK(cs_totalBytesRecv); return nTotalBytesRecv; } -uint64_t CNode::GetTotalBytesSent() +uint64_t CConnman::GetTotalBytesSent() { LOCK(cs_totalBytesSent); return nTotalBytesSent; @@ -2548,6 +2554,7 @@ CNode::CNode(NodeId idIn, SOCKET hSocketIn, const CAddress& addrIn, const std::s lastSentFeeFilter = 0; nextSendTimeFeeFilter = 0; id = idIn; + nOptimisticBytesWritten = 0; GetRandBytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce)); @@ -2665,7 +2672,7 @@ void CNode::EndMessage(const char* pszCommand) UNLOCK_FUNCTION(cs_vSend) // If write queue empty, attempt "optimistic write" if (it == vSendMsg.begin()) - SocketSendData(this); + nOptimisticBytesWritten += SocketSendData(this); LEAVE_CRITICAL_SECTION(cs_vSend); } diff --git a/src/net.h b/src/net.h index 503e009c49886..e2d98a90d1a96 100644 --- a/src/net.h +++ b/src/net.h @@ -171,6 +171,31 @@ class CConnman bool DisconnectSubnet(const CSubNet& subnet); void AddWhitelistedRange(const CSubNet &subnet); + + //!set the max outbound target in bytes + void SetMaxOutboundTarget(uint64_t limit); + uint64_t GetMaxOutboundTarget(); + + //!set the timeframe for the max outbound target + void SetMaxOutboundTimeframe(uint64_t timeframe); + uint64_t GetMaxOutboundTimeframe(); + + //!check if the outbound target is reached + // if param historicalBlockServingLimit is set true, the function will + // response true if the limit for serving historical blocks has been reached + bool OutboundTargetReached(bool historicalBlockServingLimit); + + //!response the bytes left in the current max outbound cycle + // in case of no limit, it will always response 0 + uint64_t GetOutboundTargetBytesLeft(); + + //!response the time in second left in the current max outbound cycle + // in case of no limit, it will always response 0 + uint64_t GetMaxOutboundTimeLeftInCycle(); + + uint64_t GetTotalBytesRecv(); + uint64_t GetTotalBytesSent(); + private: struct ListenSocket { SOCKET socket; @@ -210,6 +235,22 @@ class CConnman void DumpData(); void DumpBanlist(); + // Network stats + void RecordBytesRecv(uint64_t bytes); + void RecordBytesSent(uint64_t bytes); + + // Network usage totals + CCriticalSection cs_totalBytesRecv; + CCriticalSection cs_totalBytesSent; + uint64_t nTotalBytesRecv; + uint64_t nTotalBytesSent; + + // outbound limit & stats + uint64_t nMaxOutboundTotalBytesSentInCycle; + uint64_t nMaxOutboundCycleStartTime; + uint64_t nMaxOutboundLimit; + uint64_t nMaxOutboundTimeframe; + // Whitelisted ranges. Any node connecting from these is automatically // whitelisted (as well as those connecting to whitelisted binds). std::vector vWhitelistedRange; @@ -396,6 +437,7 @@ class CNode CDataStream ssSend; size_t nSendSize; // total size of all vSendMsg entries size_t nSendOffset; // offset inside the first vSendMsg already sent + uint64_t nOptimisticBytesWritten; uint64_t nSendBytes; std::deque vSendMsg; CCriticalSection cs_vSend; @@ -507,18 +549,6 @@ class CNode ~CNode(); private: - // Network usage totals - static CCriticalSection cs_totalBytesRecv; - static CCriticalSection cs_totalBytesSent; - static uint64_t nTotalBytesRecv; - static uint64_t nTotalBytesSent; - - // outbound limit & stats - static uint64_t nMaxOutboundTotalBytesSentInCycle; - static uint64_t nMaxOutboundCycleStartTime; - static uint64_t nMaxOutboundLimit; - static uint64_t nMaxOutboundTimeframe; - CNode(const CNode&); void operator=(const CNode&); @@ -812,34 +842,6 @@ class CNode void CloseSocketDisconnect(); void copyStats(CNodeStats &stats); - - // Network stats - static void RecordBytesRecv(uint64_t bytes); - static void RecordBytesSent(uint64_t bytes); - - static uint64_t GetTotalBytesRecv(); - static uint64_t GetTotalBytesSent(); - - //!set the max outbound target in bytes - static void SetMaxOutboundTarget(uint64_t limit); - static uint64_t GetMaxOutboundTarget(); - - //!set the timeframe for the max outbound target - static void SetMaxOutboundTimeframe(uint64_t timeframe); - static uint64_t GetMaxOutboundTimeframe(); - - //!check if the outbound target is reached - // if param historicalBlockServingLimit is set true, the function will - // response true if the limit for serving historical blocks has been reached - static bool OutboundTargetReached(bool historicalBlockServingLimit); - - //!response the bytes left in the current max outbound cycle - // in case of no limit, it will always response 0 - static uint64_t GetOutboundTargetBytesLeft(); - - //!response the time in second left in the current max outbound cycle - // in case of no limit, it will always response 0 - static uint64_t GetMaxOutboundTimeLeftInCycle(); }; diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index f72bbfe6bbd09..83c78850e2a54 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -72,12 +72,16 @@ int ClientModel::getNumBlocks() const quint64 ClientModel::getTotalBytesRecv() const { - return CNode::GetTotalBytesRecv(); + if(!g_connman) + return 0; + return g_connman->GetTotalBytesRecv(); } quint64 ClientModel::getTotalBytesSent() const { - return CNode::GetTotalBytesSent(); + if(!g_connman) + return 0; + return g_connman->GetTotalBytesSent(); } QDateTime ClientModel::getLastBlockDate() const diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 509b57aa726ed..4fe58239928c2 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -347,19 +347,21 @@ UniValue getnettotals(const UniValue& params, bool fHelp) + HelpExampleCli("getnettotals", "") + HelpExampleRpc("getnettotals", "") ); + if(!g_connman) + throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("totalbytesrecv", CNode::GetTotalBytesRecv())); - obj.push_back(Pair("totalbytessent", CNode::GetTotalBytesSent())); + obj.push_back(Pair("totalbytesrecv", g_connman->GetTotalBytesRecv())); + obj.push_back(Pair("totalbytessent", g_connman->GetTotalBytesSent())); obj.push_back(Pair("timemillis", GetTimeMillis())); UniValue outboundLimit(UniValue::VOBJ); - outboundLimit.push_back(Pair("timeframe", CNode::GetMaxOutboundTimeframe())); - outboundLimit.push_back(Pair("target", CNode::GetMaxOutboundTarget())); - outboundLimit.push_back(Pair("target_reached", CNode::OutboundTargetReached(false))); - outboundLimit.push_back(Pair("serve_historical_blocks", !CNode::OutboundTargetReached(true))); - outboundLimit.push_back(Pair("bytes_left_in_cycle", CNode::GetOutboundTargetBytesLeft())); - outboundLimit.push_back(Pair("time_left_in_cycle", CNode::GetMaxOutboundTimeLeftInCycle())); + outboundLimit.push_back(Pair("timeframe", g_connman->GetMaxOutboundTimeframe())); + outboundLimit.push_back(Pair("target", g_connman->GetMaxOutboundTarget())); + outboundLimit.push_back(Pair("target_reached", g_connman->OutboundTargetReached(false))); + outboundLimit.push_back(Pair("serve_historical_blocks", !g_connman->OutboundTargetReached(true))); + outboundLimit.push_back(Pair("bytes_left_in_cycle", g_connman->GetOutboundTargetBytesLeft())); + outboundLimit.push_back(Pair("time_left_in_cycle", g_connman->GetMaxOutboundTimeLeftInCycle())); obj.push_back(Pair("uploadtarget", outboundLimit)); return obj; } From be9c796dc51c05cab0b84d2e66c928973c6e5ed6 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 19 Apr 2016 00:01:19 -0400 Subject: [PATCH 0852/1802] net: move SendBufferSize/ReceiveFloodSize to CConnman --- src/main.cpp | 10 +++++++--- src/net.cpp | 13 +++++++++---- src/net.h | 10 +++++++--- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 019db0bdb39e0..db9d0d3f186d1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4769,6 +4769,7 @@ static void RelayAddress(const CAddress& addr, bool fReachable, CConnman& connma void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParams, CConnman& connman) { std::deque::iterator it = pfrom->vRecvGetData.begin(); + unsigned int nMaxSendBufferSize = connman.GetSendBufferSize(); vector vNotFound; @@ -4776,7 +4777,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam while (it != pfrom->vRecvGetData.end()) { // Don't bother if send buffer is too full to respond anyway - if (pfrom->nSendSize >= SendBufferSize()) + if (pfrom->nSendSize >= nMaxSendBufferSize) break; const CInv &inv = *it; @@ -4934,6 +4935,8 @@ uint32_t GetFetchFlags(CNode* pfrom, CBlockIndex* pprev, const Consensus::Params bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CConnman& connman) { + unsigned int nMaxSendBufferSize = connman.GetSendBufferSize(); + LogPrint("net", "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->id); if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0) { @@ -5283,7 +5286,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // Track requests for our stuff GetMainSignals().Inventory(inv.hash); - if (pfrom->nSendSize > (SendBufferSize() * 2)) { + if (pfrom->nSendSize > (nMaxSendBufferSize * 2)) { Misbehaving(pfrom->GetId(), 50); return error("send buffer size() = %u", pfrom->nSendSize); } @@ -6188,6 +6191,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, bool ProcessMessages(CNode* pfrom, CConnman& connman) { const CChainParams& chainparams = Params(); + unsigned int nMaxSendBufferSize = connman.GetSendBufferSize(); //if (fDebug) // LogPrintf("%s(%u messages)\n", __func__, pfrom->vRecvMsg.size()); @@ -6210,7 +6214,7 @@ bool ProcessMessages(CNode* pfrom, CConnman& connman) std::deque::iterator it = pfrom->vRecvMsg.begin(); while (!pfrom->fDisconnect && it != pfrom->vRecvMsg.end()) { // Don't bother if send buffer is too full to respond anyway - if (pfrom->nSendSize >= SendBufferSize()) + if (pfrom->nSendSize >= nMaxSendBufferSize) break; // get next message diff --git a/src/net.cpp b/src/net.cpp index 0787b16ad6039..2839474cb95c8 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1181,7 +1181,7 @@ void CConnman::ThreadSocketHandler() TRY_LOCK(pnode->cs_vRecvMsg, lockRecv); if (lockRecv && ( pnode->vRecvMsg.empty() || !pnode->vRecvMsg.front().complete() || - pnode->GetTotalRecvSize() <= ReceiveFloodSize())) + pnode->GetTotalRecvSize() <= GetReceiveFloodSize())) FD_SET(pnode->hSocket, &fdsetRecv); } } @@ -1851,7 +1851,7 @@ void CConnman::ThreadMessageHandler() if (!GetNodeSignals().ProcessMessages(pnode, *this)) pnode->CloseSocketDisconnect(); - if (pnode->nSendSize < SendBufferSize()) + if (pnode->nSendSize < GetSendBufferSize()) { if (!pnode->vRecvGetData.empty() || (!pnode->vRecvMsg.empty() && pnode->vRecvMsg[0].complete())) { @@ -2041,6 +2041,8 @@ CConnman::CConnman() setBannedIsDirty = false; fAddressesInitialized = false; nLastNodeId = 0; + nSendBufferMaxSize = 0; + nReceiveFloodSize = 0; } bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler& scheduler, std::string& strNodeError) @@ -2066,6 +2068,9 @@ bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, st nMaxOutboundTimeframe = 60*60*24; //1 day nMaxOutboundCycleStartTime = 0; + nSendBufferMaxSize = 1000*GetArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER); + nReceiveFloodSize = 1000*GetArg("-maxreceivebuffer", DEFAULT_MAXRECEIVEBUFFER); + uiInterface.InitMessage(_("Loading addresses...")); // Load addresses from peers.dat int64_t nStart = GetTimeMillis(); @@ -2497,8 +2502,8 @@ void CNode::Fuzz(int nChance) Fuzz(2); } -unsigned int ReceiveFloodSize() { return 1000*GetArg("-maxreceivebuffer", DEFAULT_MAXRECEIVEBUFFER); } -unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER); } +unsigned int CConnman::GetReceiveFloodSize() const { return nReceiveFloodSize; } +unsigned int CConnman::GetSendBufferSize() const{ return nSendBufferMaxSize; } CNode::CNode(NodeId idIn, SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNameIn, bool fInboundIn) : ssSend(SER_NETWORK, INIT_PROTO_VERSION), diff --git a/src/net.h b/src/net.h index e2d98a90d1a96..e5fbf65492224 100644 --- a/src/net.h +++ b/src/net.h @@ -82,9 +82,6 @@ static const ServiceFlags REQUIRED_SERVICES = NODE_NETWORK; // NOTE: When adjusting this, update rpcnet:setban's help ("24h") static const unsigned int DEFAULT_MISBEHAVING_BANTIME = 60 * 60 * 24; // Default 24-hour ban -unsigned int ReceiveFloodSize(); -unsigned int SendBufferSize(); - typedef int NodeId; struct AddedNodeInfo @@ -170,6 +167,8 @@ class CConnman bool DisconnectNode(NodeId id); bool DisconnectSubnet(const CSubNet& subnet); + unsigned int GetSendBufferSize() const; + void AddWhitelistedRange(const CSubNet &subnet); //!set the max outbound target in bytes @@ -235,6 +234,8 @@ class CConnman void DumpData(); void DumpBanlist(); + unsigned int GetReceiveFloodSize() const; + // Network stats void RecordBytesRecv(uint64_t bytes); void RecordBytesSent(uint64_t bytes); @@ -256,6 +257,9 @@ class CConnman std::vector vWhitelistedRange; CCriticalSection cs_vWhitelistedRange; + unsigned int nSendBufferMaxSize; + unsigned int nReceiveFloodSize; + std::vector vhListenSocket; banmap_t setBanned; CCriticalSection cs_setBanned; From bd72937dc462b86f0e84184b270a232f7bfaa8db Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 19 Apr 2016 00:04:58 -0400 Subject: [PATCH 0853/1802] net: move nLocalServices/nRelevantServices to CConnman These are in-turn passed to CNode at connection time. This allows us to offer different services to different peers (or test the effects of doing so). --- src/init.cpp | 5 ++++- src/main.cpp | 12 ++++++------ src/net.cpp | 32 ++++++++++++++++++-------------- src/net.h | 24 ++++++++++++++++++------ src/rpc/net.cpp | 3 ++- src/test/DoS_tests.cpp | 8 ++++---- src/test/net_tests.cpp | 4 ++-- 7 files changed, 54 insertions(+), 34 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index a7f893c24fef0..644d6721e4b00 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -982,6 +982,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // Option to startup with mocktime set (used for regression testing): SetMockTime(GetArg("-mocktime", 0)); // SetMockTime(0) is a no-op + ServiceFlags nLocalServices = NODE_NETWORK; + ServiceFlags nRelevantServices = NODE_NETWORK; + if (GetBoolArg("-peerbloomfilters", DEFAULT_PEERBLOOMFILTERS)) nLocalServices = ServiceFlags(nLocalServices | NODE_BLOOM); @@ -1506,7 +1509,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) StartTorControl(threadGroup, scheduler); std::string strNodeError; - if(!StartNode(connman, threadGroup, scheduler, strNodeError)) + if(!StartNode(connman, threadGroup, scheduler, nLocalServices, nRelevantServices, strNodeError)) return InitError(strNodeError); // ********************************************************* Step 12: finished diff --git a/src/main.cpp b/src/main.cpp index db9d0d3f186d1..a916cbc12d3a3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -471,7 +471,7 @@ void UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) { } void MaybeSetPeerAsAnnouncingHeaderAndIDs(const CNodeState* nodestate, CNode* pfrom, CConnman& connman) { - if (nLocalServices & NODE_WITNESS) { + if (pfrom->GetLocalServices() & NODE_WITNESS) { // Don't ever request compact blocks when segwit is enabled. return; } @@ -4945,7 +4945,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } - if (!(nLocalServices & NODE_BLOOM) && + if (!(pfrom->GetLocalServices() & NODE_BLOOM) && (strCommand == NetMsgType::FILTERLOAD || strCommand == NetMsgType::FILTERADD || strCommand == NetMsgType::FILTERCLEAR)) @@ -5068,7 +5068,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // Advertise our address if (fListen && !IsInitialBlockDownload()) { - CAddress addr = GetLocalAddress(&pfrom->addr); + CAddress addr = GetLocalAddress(&pfrom->addr, pfrom->GetLocalServices()); if (addr.IsRoutable()) { LogPrint("net", "ProcessMessages: advertising address %s\n", addr.ToString()); @@ -5263,7 +5263,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER && (!IsWitnessEnabled(chainActive.Tip(), chainparams.GetConsensus()) || State(pfrom->GetId())->fHaveWitness)) { inv.type |= nFetchFlags; - if (nodestate->fProvidesHeaderAndIDs && !(nLocalServices & NODE_WITNESS)) + if (nodestate->fProvidesHeaderAndIDs && !(pfrom->GetLocalServices() & NODE_WITNESS)) vToFetch.push_back(CInv(MSG_CMPCT_BLOCK, inv.hash)); else vToFetch.push_back(inv); @@ -5907,7 +5907,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, pindexLast->GetBlockHash().ToString(), pindexLast->nHeight); } if (vGetData.size() > 0) { - if (nodestate->fProvidesHeaderAndIDs && vGetData.size() == 1 && mapBlocksInFlight.size() == 1 && pindexLast->pprev->IsValid(BLOCK_VALID_CHAIN) && !(nLocalServices & NODE_WITNESS)) { + if (nodestate->fProvidesHeaderAndIDs && vGetData.size() == 1 && mapBlocksInFlight.size() == 1 && pindexLast->pprev->IsValid(BLOCK_VALID_CHAIN) && !(pfrom->GetLocalServices() & NODE_WITNESS)) { // We seem to be rather well-synced, so it appears pfrom was the first to provide us // with this block! Let's get them to announce using compact blocks in the future. MaybeSetPeerAsAnnouncingHeaderAndIDs(nodestate, pfrom, connman); @@ -5982,7 +5982,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, else if (strCommand == NetMsgType::MEMPOOL) { - if (!(nLocalServices & NODE_BLOOM) && !pfrom->fWhitelisted) + if (!(pfrom->GetLocalServices() & NODE_BLOOM) && !pfrom->fWhitelisted) { LogPrint("net", "mempool request with bloom filters disabled, disconnect peer=%d\n", pfrom->GetId()); pfrom->fDisconnect = true; diff --git a/src/net.cpp b/src/net.cpp index 2839474cb95c8..66e3d91f4a11a 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -69,15 +69,11 @@ namespace { const static std::string NET_MESSAGE_COMMAND_OTHER = "*other*"; -/** Services this node implementation cares about */ -ServiceFlags nRelevantServices = NODE_NETWORK; - // // Global state variables // bool fDiscover = true; bool fListen = true; -ServiceFlags nLocalServices = NODE_NETWORK; bool fRelayTxes = true; CCriticalSection cs_mapLocalHost; std::map mapLocalHost; @@ -155,7 +151,7 @@ static std::vector convertSeed6(const std::vector &vSeedsIn // Otherwise, return the unroutable 0.0.0.0 but filled in with // the normal parameters, since the IP may be changed to a useful // one by discovery. -CAddress GetLocalAddress(const CNetAddr *paddrPeer) +CAddress GetLocalAddress(const CNetAddr *paddrPeer, ServiceFlags nLocalServices) { CAddress ret(CService(CNetAddr(),GetListenPort()), NODE_NONE); CService addr; @@ -187,7 +183,7 @@ void AdvertiseLocal(CNode *pnode) { if (fListen && pnode->fSuccessfullyConnected) { - CAddress addrLocal = GetLocalAddress(&pnode->addr); + CAddress addrLocal = GetLocalAddress(&pnode->addr, pnode->GetLocalServices()); // If discovery is enabled, sometimes give our peer the address it // tells us that it sees us as in case it has a better idea of our // address than we do. @@ -400,7 +396,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo addrman.Attempt(addrConnect, fCountFailure); // Add node - CNode* pnode = new CNode(GetNewNodeId(), hSocket, addrConnect, pszDest ? pszDest : "", false); + CNode* pnode = new CNode(GetNewNodeId(), nLocalServices, hSocket, addrConnect, pszDest ? pszDest : "", false); GetNodeSignals().InitializeNode(pnode->GetId(), pnode); pnode->AddRef(); @@ -463,7 +459,7 @@ void CNode::PushVersion() int64_t nTime = (fInbound ? GetAdjustedTime() : GetTime()); CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService(), addr.nServices)); - CAddress addrMe = GetLocalAddress(&addr); + CAddress addrMe = GetLocalAddress(&addr, nLocalServices); if (fLogIPs) LogPrint("net", "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), addrYou.ToString(), id); else @@ -1036,7 +1032,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) { } } - CNode* pnode = new CNode(GetNewNodeId(), hSocket, addr, "", true); + CNode* pnode = new CNode(GetNewNodeId(), nLocalServices, hSocket, addr, "", true); GetNodeSignals().InitializeNode(pnode->GetId(), pnode); pnode->AddRef(); pnode->fWhitelisted = whitelisted; @@ -2045,11 +2041,11 @@ CConnman::CConnman() nReceiveFloodSize = 0; } -bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler& scheduler, std::string& strNodeError) +bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServices, ServiceFlags nRelevantServices, std::string& strNodeError) { Discover(threadGroup); - bool ret = connman.Start(threadGroup, scheduler, strNodeError); + bool ret = connman.Start(threadGroup, scheduler, nLocalServices, nRelevantServices, strNodeError); return ret; } @@ -2059,13 +2055,15 @@ NodeId CConnman::GetNewNodeId() return nLastNodeId.fetch_add(1, std::memory_order_relaxed); } -bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, std::string& strNodeError) +bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServicesIn, ServiceFlags nRelevantServicesIn, std::string& strNodeError) { nTotalBytesRecv = 0; nTotalBytesSent = 0; nMaxOutboundLimit = 0; nMaxOutboundTotalBytesSentInCycle = 0; nMaxOutboundTimeframe = 60*60*24; //1 day + nLocalServices = nLocalServicesIn; + nRelevantServices = nRelevantServicesIn; nMaxOutboundCycleStartTime = 0; nSendBufferMaxSize = 1000*GetArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER); @@ -2116,7 +2114,7 @@ bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, st if (pnodeLocalHost == NULL) { CNetAddr local; LookupHost("127.0.0.1", local, false); - pnodeLocalHost = new CNode(GetNewNodeId(), INVALID_SOCKET, CAddress(CService(local, 0), nLocalServices)); + pnodeLocalHost = new CNode(GetNewNodeId(), nLocalServices, INVALID_SOCKET, CAddress(CService(local, 0), nLocalServices)); GetNodeSignals().InitializeNode(pnodeLocalHost->GetId(), pnodeLocalHost); } @@ -2467,6 +2465,11 @@ uint64_t CConnman::GetTotalBytesSent() return nTotalBytesSent; } +ServiceFlags CConnman::GetLocalServices() const +{ + return nLocalServices; +} + void CNode::Fuzz(int nChance) { if (!fSuccessfullyConnected) return; // Don't fuzz initial handshake @@ -2505,7 +2508,7 @@ void CNode::Fuzz(int nChance) unsigned int CConnman::GetReceiveFloodSize() const { return nReceiveFloodSize; } unsigned int CConnman::GetSendBufferSize() const{ return nSendBufferMaxSize; } -CNode::CNode(NodeId idIn, SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNameIn, bool fInboundIn) : +CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNameIn, bool fInboundIn) : ssSend(SER_NETWORK, INIT_PROTO_VERSION), addr(addrIn), nKeyedNetGroup(CalculateKeyedNetGroup(addrIn)), @@ -2560,6 +2563,7 @@ CNode::CNode(NodeId idIn, SOCKET hSocketIn, const CAddress& addrIn, const std::s nextSendTimeFeeFilter = 0; id = idIn; nOptimisticBytesWritten = 0; + nLocalServices = nLocalServicesIn; GetRandBytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce)); diff --git a/src/net.h b/src/net.h index e5fbf65492224..25e473c5fc30f 100644 --- a/src/net.h +++ b/src/net.h @@ -107,7 +107,7 @@ class CConnman CConnman(); ~CConnman(); - bool Start(boost::thread_group& threadGroup, CScheduler& scheduler, std::string& strNodeError); + bool Start(boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServicesIn, ServiceFlags nRelevantServicesIn, std::string& strNodeError); void Stop(); bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false, bool fFeeler = false); @@ -171,6 +171,8 @@ class CConnman void AddWhitelistedRange(const CSubNet &subnet); + ServiceFlags GetLocalServices() const; + //!set the max outbound target in bytes void SetMaxOutboundTarget(uint64_t limit); uint64_t GetMaxOutboundTarget(); @@ -274,12 +276,18 @@ class CConnman mutable CCriticalSection cs_vNodes; std::atomic nLastNodeId; boost::condition_variable messageHandlerCondition; + + /** Services this instance offers */ + ServiceFlags nLocalServices; + + /** Services this instance cares about */ + ServiceFlags nRelevantServices; }; extern std::unique_ptr g_connman; void MapPort(bool fUseUPnP); unsigned short GetListenPort(); bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); -bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler& scheduler, std::string& strNodeError); +bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServices, ServiceFlags nRelevantServices, std::string& strNodeError); bool StopNode(CConnman& connman); size_t SocketSendData(CNode *pnode); @@ -336,13 +344,11 @@ bool IsLocal(const CService& addr); bool GetLocal(CService &addr, const CNetAddr *paddrPeer = NULL); bool IsReachable(enum Network net); bool IsReachable(const CNetAddr &addr); -CAddress GetLocalAddress(const CNetAddr *paddrPeer = NULL); +CAddress GetLocalAddress(const CNetAddr *paddrPeer, ServiceFlags nLocalServices); extern bool fDiscover; extern bool fListen; -extern ServiceFlags nLocalServices; -extern ServiceFlags nRelevantServices; extern bool fRelayTxes; /** Maximum number of connections to simultaneously allow (aka connection slots) */ @@ -549,7 +555,7 @@ class CNode CAmount lastSentFeeFilter; int64_t nextSendTimeFeeFilter; - CNode(NodeId id, SOCKET hSocketIn, const CAddress &addrIn, const std::string &addrNameIn = "", bool fInboundIn = false); + CNode(NodeId id, ServiceFlags nLocalServicesIn, SOCKET hSocketIn, const CAddress &addrIn, const std::string &addrNameIn = "", bool fInboundIn = false); ~CNode(); private: @@ -559,6 +565,7 @@ class CNode static uint64_t CalculateKeyedNetGroup(const CAddress& ad); uint64_t nLocalHostNonce; + ServiceFlags nLocalServices; public: NodeId GetId() const { @@ -846,6 +853,11 @@ class CNode void CloseSocketDisconnect(); void copyStats(CNodeStats &stats); + + ServiceFlags GetLocalServices() const + { + return nLocalServices; + } }; diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 4fe58239928c2..61b6b62c9a0b6 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -432,7 +432,8 @@ UniValue getnetworkinfo(const UniValue& params, bool fHelp) obj.push_back(Pair("version", CLIENT_VERSION)); obj.push_back(Pair("subversion", strSubVersion)); obj.push_back(Pair("protocolversion",PROTOCOL_VERSION)); - obj.push_back(Pair("localservices", strprintf("%016x", nLocalServices))); + if(g_connman) + obj.push_back(Pair("localservices", strprintf("%016x", g_connman->GetLocalServices()))); obj.push_back(Pair("localrelay", fRelayTxes)); obj.push_back(Pair("timeoffset", GetTimeOffset())); if(g_connman) diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index 652a8e2ceadf7..2265f43a6e14c 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -48,7 +48,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning) { connman->ClearBanned(); CAddress addr1(ip(0xa0b0c001), NODE_NONE); - CNode dummyNode1(id++, INVALID_SOCKET, addr1, "", true); + CNode dummyNode1(id++, NODE_NETWORK, INVALID_SOCKET, addr1, "", true); GetNodeSignals().InitializeNode(dummyNode1.GetId(), &dummyNode1); dummyNode1.nVersion = 1; Misbehaving(dummyNode1.GetId(), 100); // Should get banned @@ -57,7 +57,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning) BOOST_CHECK(!connman->IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned CAddress addr2(ip(0xa0b0c002), NODE_NONE); - CNode dummyNode2(id++, INVALID_SOCKET, addr2, "", true); + CNode dummyNode2(id++, NODE_NETWORK, INVALID_SOCKET, addr2, "", true); GetNodeSignals().InitializeNode(dummyNode2.GetId(), &dummyNode2); dummyNode2.nVersion = 1; Misbehaving(dummyNode2.GetId(), 50); @@ -74,7 +74,7 @@ BOOST_AUTO_TEST_CASE(DoS_banscore) connman->ClearBanned(); mapArgs["-banscore"] = "111"; // because 11 is my favorite number CAddress addr1(ip(0xa0b0c001), NODE_NONE); - CNode dummyNode1(id++, INVALID_SOCKET, addr1, "", true); + CNode dummyNode1(id++, NODE_NETWORK, INVALID_SOCKET, addr1, "", true); GetNodeSignals().InitializeNode(dummyNode1.GetId(), &dummyNode1); dummyNode1.nVersion = 1; Misbehaving(dummyNode1.GetId(), 100); @@ -96,7 +96,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) SetMockTime(nStartTime); // Overrides future calls to GetTime() CAddress addr(ip(0xa0b0c001), NODE_NONE); - CNode dummyNode(id++, INVALID_SOCKET, addr, "", true); + CNode dummyNode(id++, NODE_NETWORK, INVALID_SOCKET, addr, "", true); GetNodeSignals().InitializeNode(dummyNode.GetId(), &dummyNode); dummyNode.nVersion = 1; diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index 00fb757167717..1019b12c1c57a 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -163,12 +163,12 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test) bool fInboundIn = false; // Test that fFeeler is false by default. - CNode* pnode1 = new CNode(id++, hSocket, addr, pszDest, fInboundIn); + CNode* pnode1 = new CNode(id++, NODE_NETWORK, hSocket, addr, pszDest, fInboundIn); BOOST_CHECK(pnode1->fInbound == false); BOOST_CHECK(pnode1->fFeeler == false); fInboundIn = true; - CNode* pnode2 = new CNode(id++, hSocket, addr, pszDest, fInboundIn); + CNode* pnode2 = new CNode(id++, NODE_NETWORK, hSocket, addr, pszDest, fInboundIn); BOOST_CHECK(pnode2->fInbound == true); BOOST_CHECK(pnode2->fFeeler == false); } From 8a593694b1495656411717fbae5d3167576df973 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 19 Apr 2016 00:15:52 -0400 Subject: [PATCH 0854/1802] net: move semOutbound to CConnman --- src/net.cpp | 3 +-- src/net.h | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 66e3d91f4a11a..853c0cdd65f76 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -84,8 +84,6 @@ std::string strSubVersion; limitedmap mapAlreadyAskedFor(MAX_INV_SZ); -static CSemaphore *semOutbound = NULL; - // Signals for message handling static CNodeSignals g_signals; CNodeSignals& GetNodeSignals() { return g_signals; } @@ -2039,6 +2037,7 @@ CConnman::CConnman() nLastNodeId = 0; nSendBufferMaxSize = 0; nReceiveFloodSize = 0; + semOutbound = NULL; } bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServices, ServiceFlags nRelevantServices, std::string& strNodeError) diff --git a/src/net.h b/src/net.h index 25e473c5fc30f..36ebadf13cb19 100644 --- a/src/net.h +++ b/src/net.h @@ -282,6 +282,8 @@ class CConnman /** Services this instance cares about */ ServiceFlags nRelevantServices; + + CSemaphore *semOutbound; }; extern std::unique_ptr g_connman; void MapPort(bool fUseUPnP); From fdf69ff21aef8ed8071a757979f4239537f7afba Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Sun, 22 May 2016 09:52:03 +0200 Subject: [PATCH 0855/1802] net: move max/max-outbound to CConnman --- src/init.cpp | 5 +++-- src/net.cpp | 24 +++++++++++++----------- src/net.h | 11 ++++++----- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 644d6721e4b00..599dac39b2562 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -861,7 +861,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // Make sure enough file descriptors are available int nBind = std::max((int)mapArgs.count("-bind") + (int)mapArgs.count("-whitebind"), 1); int nUserMaxConnections = GetArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS); - nMaxConnections = std::max(nUserMaxConnections, 0); + int nMaxConnections = std::max(nUserMaxConnections, 0); // Trim requested connection counts, to fit into system limitations nMaxConnections = std::max(std::min(nMaxConnections, (int)(FD_SETSIZE - nBind - MIN_CORE_FILEDESCRIPTORS)), 0); @@ -1509,7 +1509,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) StartTorControl(threadGroup, scheduler); std::string strNodeError; - if(!StartNode(connman, threadGroup, scheduler, nLocalServices, nRelevantServices, strNodeError)) + int nMaxOutbound = std::min(MAX_OUTBOUND_CONNECTIONS, nMaxConnections); + if(!StartNode(connman, threadGroup, scheduler, nLocalServices, nRelevantServices, nMaxConnections, nMaxOutbound, strNodeError)) return InitError(strNodeError); // ********************************************************* Step 12: finished diff --git a/src/net.cpp b/src/net.cpp index 853c0cdd65f76..fe4daaaebf03a 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -63,7 +63,6 @@ namespace { - const int MAX_OUTBOUND_CONNECTIONS = 8; const int MAX_FEELER_CONNECTIONS = 1; } @@ -79,7 +78,6 @@ CCriticalSection cs_mapLocalHost; std::map mapLocalHost; static bool vfLimited[NET_MAX] = {}; static CNode* pnodeLocalHost = NULL; -int nMaxConnections = DEFAULT_MAX_PEER_CONNECTIONS; std::string strSubVersion; limitedmap mapAlreadyAskedFor(MAX_INV_SZ); @@ -974,7 +972,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) { SOCKET hSocket = accept(hListenSocket.socket, (struct sockaddr*)&sockaddr, &len); CAddress addr; int nInbound = 0; - int nMaxInbound = nMaxConnections - (MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS); + int nMaxInbound = nMaxConnections - (nMaxOutbound + MAX_FEELER_CONNECTIONS); assert(nMaxInbound > 0); if (hSocket != INVALID_SOCKET) @@ -1626,7 +1624,7 @@ void CConnman::ThreadOpenConnections() } } } - assert(nOutbound <= (MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS)); + assert(nOutbound <= (nMaxOutbound + MAX_FEELER_CONNECTIONS)); // Feeler Connections // @@ -1641,7 +1639,7 @@ void CConnman::ThreadOpenConnections() // * Only make a feeler connection once every few minutes. // bool fFeeler = false; - if (nOutbound >= MAX_OUTBOUND_CONNECTIONS) { + if (nOutbound >= nMaxOutbound) { int64_t nTime = GetTimeMicros(); // The current time right now (in microseconds). if (nTime > nNextFeeler) { nNextFeeler = PoissonNextSend(nTime, FEELER_INTERVAL); @@ -2038,13 +2036,15 @@ CConnman::CConnman() nSendBufferMaxSize = 0; nReceiveFloodSize = 0; semOutbound = NULL; + nMaxConnections = 0; + nMaxOutbound = 0; } -bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServices, ServiceFlags nRelevantServices, std::string& strNodeError) +bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServices, ServiceFlags nRelevantServices, int nMaxConnectionsIn, int nMaxOutboundIn, std::string& strNodeError) { Discover(threadGroup); - bool ret = connman.Start(threadGroup, scheduler, nLocalServices, nRelevantServices, strNodeError); + bool ret = connman.Start(threadGroup, scheduler, nLocalServices, nRelevantServices, nMaxConnectionsIn, nMaxOutboundIn, strNodeError); return ret; } @@ -2054,7 +2054,7 @@ NodeId CConnman::GetNewNodeId() return nLastNodeId.fetch_add(1, std::memory_order_relaxed); } -bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServicesIn, ServiceFlags nRelevantServicesIn, std::string& strNodeError) +bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServicesIn, ServiceFlags nRelevantServicesIn, int nMaxConnectionsIn, int nMaxOutboundIn, std::string& strNodeError) { nTotalBytesRecv = 0; nTotalBytesSent = 0; @@ -2065,6 +2065,9 @@ bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, Se nRelevantServices = nRelevantServicesIn; nMaxOutboundCycleStartTime = 0; + nMaxConnections = nMaxConnectionsIn; + nMaxOutbound = std::min((nMaxOutboundIn), nMaxConnections); + nSendBufferMaxSize = 1000*GetArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER); nReceiveFloodSize = 1000*GetArg("-maxreceivebuffer", DEFAULT_MAXRECEIVEBUFFER); @@ -2106,8 +2109,7 @@ bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, Se if (semOutbound == NULL) { // initialize semaphore - int nMaxOutbound = std::min((MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS), nMaxConnections); - semOutbound = new CSemaphore(nMaxOutbound); + semOutbound = new CSemaphore(std::min((nMaxOutbound + MAX_FEELER_CONNECTIONS), nMaxConnections)); } if (pnodeLocalHost == NULL) { @@ -2174,7 +2176,7 @@ instance_of_cnetcleanup; void CConnman::Stop() { if (semOutbound) - for (int i=0; i<(MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS); i++) + for (int i=0; i<(nMaxOutbound + MAX_FEELER_CONNECTIONS); i++) semOutbound->post(); if (fAddressesInitialized) diff --git a/src/net.h b/src/net.h index 36ebadf13cb19..0859190d3679d 100644 --- a/src/net.h +++ b/src/net.h @@ -54,6 +54,8 @@ static const unsigned int MAX_ADDR_TO_SEND = 1000; static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH = 4 * 1000 * 1000; /** Maximum length of strSubVer in `version` message */ static const unsigned int MAX_SUBVERSION_LENGTH = 256; +/** Maximum number of outgoing nodes */ +static const int MAX_OUTBOUND_CONNECTIONS = 8; /** -listen default */ static const bool DEFAULT_LISTEN = true; /** -upnp default */ @@ -107,7 +109,7 @@ class CConnman CConnman(); ~CConnman(); - bool Start(boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServicesIn, ServiceFlags nRelevantServicesIn, std::string& strNodeError); + bool Start(boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServicesIn, ServiceFlags nRelevantServicesIn, int nMaxConnectionsIn, int nMaxOutboundIn, std::string& strNodeError); void Stop(); bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false, bool fFeeler = false); @@ -284,12 +286,14 @@ class CConnman ServiceFlags nRelevantServices; CSemaphore *semOutbound; + int nMaxConnections; + int nMaxOutbound; }; extern std::unique_ptr g_connman; void MapPort(bool fUseUPnP); unsigned short GetListenPort(); bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); -bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServices, ServiceFlags nRelevantServices, std::string& strNodeError); +bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServices, ServiceFlags nRelevantServices, int nMaxConnections, int nMaxOutbound, std::string& strNodeError); bool StopNode(CConnman& connman); size_t SocketSendData(CNode *pnode); @@ -353,9 +357,6 @@ extern bool fDiscover; extern bool fListen; extern bool fRelayTxes; -/** Maximum number of connections to simultaneously allow (aka connection slots) */ -extern int nMaxConnections; - extern limitedmap mapAlreadyAskedFor; /** Subversion as sent to the P2P network in `version` messages */ From f60b9059e4958245bda82e9656c52a31d5268ad9 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 24 May 2016 16:42:17 -0400 Subject: [PATCH 0856/1802] net: Pass best block known height into CConnman CConnman then passes the current best height into CNode at creation time. This way CConnman/CNode have no dependency on main for height, and the signals only move in one direction. This also helps to prevent identity leakage a tiny bit. Before this change, an attacker could theoretically make 2 connections on different interfaces. They would connect fully on one, and only establish the initial connection on the other. Once they receive a new block, they would relay it to your first connection, and immediately commence the version handshake on the second. Since the new block height is reflected immediately, they could attempt to learn whether the two connections were correlated. This is, of course, incredibly unlikely to work due to the small timings involved and receipt from other senders. But it doesn't hurt to lock-in nBestHeight at the time of connection, rather than letting the remote choose the time. --- src/init.cpp | 2 +- src/main.cpp | 10 ++-------- src/net.cpp | 36 ++++++++++++++++++++++++------------ src/net.h | 13 +++++++++---- src/test/DoS_tests.cpp | 8 ++++---- src/test/net_tests.cpp | 5 +++-- 6 files changed, 43 insertions(+), 31 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 599dac39b2562..4dce8be819cb5 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1510,7 +1510,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) std::string strNodeError; int nMaxOutbound = std::min(MAX_OUTBOUND_CONNECTIONS, nMaxConnections); - if(!StartNode(connman, threadGroup, scheduler, nLocalServices, nRelevantServices, nMaxConnections, nMaxOutbound, strNodeError)) + if(!StartNode(connman, threadGroup, scheduler, nLocalServices, nRelevantServices, nMaxConnections, nMaxOutbound, chainActive.Height(), strNodeError)) return InitError(strNodeError); // ********************************************************* Step 12: finished diff --git a/src/main.cpp b/src/main.cpp index a916cbc12d3a3..1835d9712b025 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -325,12 +325,6 @@ CNodeState *State(NodeId pnode) { return &it->second; } -int GetHeight() -{ - LOCK(cs_main); - return chainActive.Height(); -} - void UpdatePreferredDownload(CNode* node, CNodeState* state) { nPreferredDownload -= state->fPreferredDownload; @@ -639,7 +633,6 @@ bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) { void RegisterNodeSignals(CNodeSignals& nodeSignals) { - nodeSignals.GetHeight.connect(&GetHeight); nodeSignals.ProcessMessages.connect(&ProcessMessages); nodeSignals.SendMessages.connect(&SendMessages); nodeSignals.InitializeNode.connect(&InitializeNode); @@ -648,7 +641,6 @@ void RegisterNodeSignals(CNodeSignals& nodeSignals) void UnregisterNodeSignals(CNodeSignals& nodeSignals) { - nodeSignals.GetHeight.disconnect(&GetHeight); nodeSignals.ProcessMessages.disconnect(&ProcessMessages); nodeSignals.SendMessages.disconnect(&SendMessages); nodeSignals.InitializeNode.disconnect(&InitializeNode); @@ -3058,6 +3050,8 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, // When we reach this point, we switched to a new tip (stored in pindexNewTip). // Notifications/callbacks that can run without cs_main + if(connman) + connman->SetBestHeight(nNewHeight); // throw all transactions though the signal-interface // while _not_ holding the cs_main lock diff --git a/src/net.cpp b/src/net.cpp index fe4daaaebf03a..d510952551a33 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -392,7 +392,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo addrman.Attempt(addrConnect, fCountFailure); // Add node - CNode* pnode = new CNode(GetNewNodeId(), nLocalServices, hSocket, addrConnect, pszDest ? pszDest : "", false); + CNode* pnode = new CNode(GetNewNodeId(), nLocalServices, GetBestHeight(), hSocket, addrConnect, pszDest ? pszDest : "", false); GetNodeSignals().InitializeNode(pnode->GetId(), pnode); pnode->AddRef(); @@ -451,17 +451,15 @@ void CNode::CloseSocketDisconnect() void CNode::PushVersion() { - int nBestHeight = GetNodeSignals().GetHeight().get_value_or(0); - int64_t nTime = (fInbound ? GetAdjustedTime() : GetTime()); CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService(), addr.nServices)); CAddress addrMe = GetLocalAddress(&addr, nLocalServices); if (fLogIPs) - LogPrint("net", "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), addrYou.ToString(), id); + LogPrint("net", "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", PROTOCOL_VERSION, nMyStartingHeight, addrMe.ToString(), addrYou.ToString(), id); else - LogPrint("net", "send version message: version %d, blocks=%d, us=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), id); + LogPrint("net", "send version message: version %d, blocks=%d, us=%s, peer=%d\n", PROTOCOL_VERSION, nMyStartingHeight, addrMe.ToString(), id); PushMessage(NetMsgType::VERSION, PROTOCOL_VERSION, (uint64_t)nLocalServices, nTime, addrYou, addrMe, - nLocalHostNonce, strSubVersion, nBestHeight, ::fRelayTxes); + nLocalHostNonce, strSubVersion, nMyStartingHeight, ::fRelayTxes); } @@ -1028,7 +1026,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) { } } - CNode* pnode = new CNode(GetNewNodeId(), nLocalServices, hSocket, addr, "", true); + CNode* pnode = new CNode(GetNewNodeId(), nLocalServices, GetBestHeight(), hSocket, addr, "", true); GetNodeSignals().InitializeNode(pnode->GetId(), pnode); pnode->AddRef(); pnode->fWhitelisted = whitelisted; @@ -2038,13 +2036,14 @@ CConnman::CConnman() semOutbound = NULL; nMaxConnections = 0; nMaxOutbound = 0; + nBestHeight = 0; } -bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServices, ServiceFlags nRelevantServices, int nMaxConnectionsIn, int nMaxOutboundIn, std::string& strNodeError) +bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServices, ServiceFlags nRelevantServices, int nMaxConnectionsIn, int nMaxOutboundIn, int nBestHeightIn, std::string& strNodeError) { Discover(threadGroup); - bool ret = connman.Start(threadGroup, scheduler, nLocalServices, nRelevantServices, nMaxConnectionsIn, nMaxOutboundIn, strNodeError); + bool ret = connman.Start(threadGroup, scheduler, nLocalServices, nRelevantServices, nMaxConnectionsIn, nMaxOutboundIn, nBestHeightIn, strNodeError); return ret; } @@ -2054,7 +2053,7 @@ NodeId CConnman::GetNewNodeId() return nLastNodeId.fetch_add(1, std::memory_order_relaxed); } -bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServicesIn, ServiceFlags nRelevantServicesIn, int nMaxConnectionsIn, int nMaxOutboundIn, std::string& strNodeError) +bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServicesIn, ServiceFlags nRelevantServicesIn, int nMaxConnectionsIn, int nMaxOutboundIn, int nBestHeightIn, std::string& strNodeError) { nTotalBytesRecv = 0; nTotalBytesSent = 0; @@ -2071,6 +2070,8 @@ bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, Se nSendBufferMaxSize = 1000*GetArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER); nReceiveFloodSize = 1000*GetArg("-maxreceivebuffer", DEFAULT_MAXRECEIVEBUFFER); + SetBestHeight(nBestHeightIn); + uiInterface.InitMessage(_("Loading addresses...")); // Load addresses from peers.dat int64_t nStart = GetTimeMillis(); @@ -2115,7 +2116,7 @@ bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, Se if (pnodeLocalHost == NULL) { CNetAddr local; LookupHost("127.0.0.1", local, false); - pnodeLocalHost = new CNode(GetNewNodeId(), nLocalServices, INVALID_SOCKET, CAddress(CService(local, 0), nLocalServices)); + pnodeLocalHost = new CNode(GetNewNodeId(), nLocalServices, GetBestHeight(), INVALID_SOCKET, CAddress(CService(local, 0), nLocalServices)); GetNodeSignals().InitializeNode(pnodeLocalHost->GetId(), pnodeLocalHost); } @@ -2471,6 +2472,16 @@ ServiceFlags CConnman::GetLocalServices() const return nLocalServices; } +void CConnman::SetBestHeight(int height) +{ + nBestHeight.store(height, std::memory_order_release); +} + +int CConnman::GetBestHeight() const +{ + return nBestHeight.load(std::memory_order_acquire); +} + void CNode::Fuzz(int nChance) { if (!fSuccessfullyConnected) return; // Don't fuzz initial handshake @@ -2509,7 +2520,7 @@ void CNode::Fuzz(int nChance) unsigned int CConnman::GetReceiveFloodSize() const { return nReceiveFloodSize; } unsigned int CConnman::GetSendBufferSize() const{ return nSendBufferMaxSize; } -CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNameIn, bool fInboundIn) : +CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNameIn, bool fInboundIn) : ssSend(SER_NETWORK, INIT_PROTO_VERSION), addr(addrIn), nKeyedNetGroup(CalculateKeyedNetGroup(addrIn)), @@ -2567,6 +2578,7 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, SOCKET hSocketIn, const nLocalServices = nLocalServicesIn; GetRandBytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce)); + nMyStartingHeight = nMyStartingHeightIn; BOOST_FOREACH(const std::string &msg, getAllNetMessageTypes()) mapRecvBytesPerMsgCmd[msg] = 0; diff --git a/src/net.h b/src/net.h index 0859190d3679d..852822d85b71c 100644 --- a/src/net.h +++ b/src/net.h @@ -109,7 +109,7 @@ class CConnman CConnman(); ~CConnman(); - bool Start(boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServicesIn, ServiceFlags nRelevantServicesIn, int nMaxConnectionsIn, int nMaxOutboundIn, std::string& strNodeError); + bool Start(boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServicesIn, ServiceFlags nRelevantServicesIn, int nMaxConnectionsIn, int nMaxOutboundIn, int nBestHeightIn, std::string& strNodeError); void Stop(); bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false, bool fFeeler = false); @@ -199,6 +199,10 @@ class CConnman uint64_t GetTotalBytesRecv(); uint64_t GetTotalBytesSent(); + void SetBestHeight(int height); + int GetBestHeight() const; + + private: struct ListenSocket { SOCKET socket; @@ -288,12 +292,13 @@ class CConnman CSemaphore *semOutbound; int nMaxConnections; int nMaxOutbound; + std::atomic nBestHeight; }; extern std::unique_ptr g_connman; void MapPort(bool fUseUPnP); unsigned short GetListenPort(); bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); -bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServices, ServiceFlags nRelevantServices, int nMaxConnections, int nMaxOutbound, std::string& strNodeError); +bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServices, ServiceFlags nRelevantServices, int nMaxConnections, int nMaxOutbound, int nBestHeightIn, std::string& strNodeError); bool StopNode(CConnman& connman); size_t SocketSendData(CNode *pnode); @@ -315,7 +320,6 @@ struct CombinerAll // Signals for message handling struct CNodeSignals { - boost::signals2::signal GetHeight; boost::signals2::signal ProcessMessages; boost::signals2::signal SendMessages; boost::signals2::signal InitializeNode; @@ -558,7 +562,7 @@ class CNode CAmount lastSentFeeFilter; int64_t nextSendTimeFeeFilter; - CNode(NodeId id, ServiceFlags nLocalServicesIn, SOCKET hSocketIn, const CAddress &addrIn, const std::string &addrNameIn = "", bool fInboundIn = false); + CNode(NodeId id, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress &addrIn, const std::string &addrNameIn = "", bool fInboundIn = false); ~CNode(); private: @@ -569,6 +573,7 @@ class CNode uint64_t nLocalHostNonce; ServiceFlags nLocalServices; + int nMyStartingHeight; public: NodeId GetId() const { diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index 2265f43a6e14c..33f107d84bfdd 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -48,7 +48,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning) { connman->ClearBanned(); CAddress addr1(ip(0xa0b0c001), NODE_NONE); - CNode dummyNode1(id++, NODE_NETWORK, INVALID_SOCKET, addr1, "", true); + CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, "", true); GetNodeSignals().InitializeNode(dummyNode1.GetId(), &dummyNode1); dummyNode1.nVersion = 1; Misbehaving(dummyNode1.GetId(), 100); // Should get banned @@ -57,7 +57,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning) BOOST_CHECK(!connman->IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned CAddress addr2(ip(0xa0b0c002), NODE_NONE); - CNode dummyNode2(id++, NODE_NETWORK, INVALID_SOCKET, addr2, "", true); + CNode dummyNode2(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr2, "", true); GetNodeSignals().InitializeNode(dummyNode2.GetId(), &dummyNode2); dummyNode2.nVersion = 1; Misbehaving(dummyNode2.GetId(), 50); @@ -74,7 +74,7 @@ BOOST_AUTO_TEST_CASE(DoS_banscore) connman->ClearBanned(); mapArgs["-banscore"] = "111"; // because 11 is my favorite number CAddress addr1(ip(0xa0b0c001), NODE_NONE); - CNode dummyNode1(id++, NODE_NETWORK, INVALID_SOCKET, addr1, "", true); + CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, "", true); GetNodeSignals().InitializeNode(dummyNode1.GetId(), &dummyNode1); dummyNode1.nVersion = 1; Misbehaving(dummyNode1.GetId(), 100); @@ -96,7 +96,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) SetMockTime(nStartTime); // Overrides future calls to GetTime() CAddress addr(ip(0xa0b0c001), NODE_NONE); - CNode dummyNode(id++, NODE_NETWORK, INVALID_SOCKET, addr, "", true); + CNode dummyNode(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr, "", true); GetNodeSignals().InitializeNode(dummyNode.GetId(), &dummyNode); dummyNode.nVersion = 1; diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index 1019b12c1c57a..bc9a98ab04cf8 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -154,6 +154,7 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test) { SOCKET hSocket = INVALID_SOCKET; NodeId id = 0; + int height = 0; in_addr ipv4Addr; ipv4Addr.s_addr = 0xa0b0c001; @@ -163,12 +164,12 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test) bool fInboundIn = false; // Test that fFeeler is false by default. - CNode* pnode1 = new CNode(id++, NODE_NETWORK, hSocket, addr, pszDest, fInboundIn); + CNode* pnode1 = new CNode(id++, NODE_NETWORK, height, hSocket, addr, pszDest, fInboundIn); BOOST_CHECK(pnode1->fInbound == false); BOOST_CHECK(pnode1->fFeeler == false); fInboundIn = true; - CNode* pnode2 = new CNode(id++, NODE_NETWORK, hSocket, addr, pszDest, fInboundIn); + CNode* pnode2 = new CNode(id++, NODE_NETWORK, height, hSocket, addr, pszDest, fInboundIn); BOOST_CHECK(pnode2->fInbound == true); BOOST_CHECK(pnode2->fFeeler == false); } From e81a602cf02edfb21c3ec097bd7cf71f189ed783 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 25 May 2016 21:26:46 -0400 Subject: [PATCH 0857/1802] net: pass CClientUIInterface into CConnman --- src/init.cpp | 2 +- src/net.cpp | 27 +++++++++++++++++---------- src/net.h | 7 +++++-- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 4dce8be819cb5..9e2ed62a922b9 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1510,7 +1510,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) std::string strNodeError; int nMaxOutbound = std::min(MAX_OUTBOUND_CONNECTIONS, nMaxConnections); - if(!StartNode(connman, threadGroup, scheduler, nLocalServices, nRelevantServices, nMaxConnections, nMaxOutbound, chainActive.Height(), strNodeError)) + if(!StartNode(connman, threadGroup, scheduler, nLocalServices, nRelevantServices, nMaxConnections, nMaxOutbound, chainActive.Height(), &uiInterface, strNodeError)) return InitError(strNodeError); // ********************************************************* Step 12: finished diff --git a/src/net.cpp b/src/net.cpp index d510952551a33..13218b4221fbd 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -474,7 +474,8 @@ void CConnman::ClearBanned() setBannedIsDirty = true; } DumpBanlist(); //store banlist to disk - uiInterface.BannedListChanged(); + if(clientInterface) + clientInterface->BannedListChanged(); } bool CConnman::IsBanned(CNetAddr ip) @@ -534,7 +535,8 @@ void CConnman::Ban(const CSubNet& subNet, const BanReason &banReason, int64_t ba else return; } - uiInterface.BannedListChanged(); + if(clientInterface) + clientInterface->BannedListChanged(); { LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) { @@ -558,7 +560,8 @@ bool CConnman::Unban(const CSubNet &subNet) { return false; setBannedIsDirty = true; } - uiInterface.BannedListChanged(); + if(clientInterface) + clientInterface->BannedListChanged(); DumpBanlist(); //store banlist to disk immediately return true; } @@ -1104,7 +1107,8 @@ void CConnman::ThreadSocketHandler() } if(vNodes.size() != nPrevNodeCount) { nPrevNodeCount = vNodes.size(); - uiInterface.NotifyNumConnectionsChanged(nPrevNodeCount); + if(clientInterface) + clientInterface->NotifyNumConnectionsChanged(nPrevNodeCount); } // @@ -2037,13 +2041,14 @@ CConnman::CConnman() nMaxConnections = 0; nMaxOutbound = 0; nBestHeight = 0; + clientInterface = NULL; } -bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServices, ServiceFlags nRelevantServices, int nMaxConnectionsIn, int nMaxOutboundIn, int nBestHeightIn, std::string& strNodeError) +bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServices, ServiceFlags nRelevantServices, int nMaxConnectionsIn, int nMaxOutboundIn, int nBestHeightIn, CClientUIInterface* interfaceIn, std::string& strNodeError) { Discover(threadGroup); - bool ret = connman.Start(threadGroup, scheduler, nLocalServices, nRelevantServices, nMaxConnectionsIn, nMaxOutboundIn, nBestHeightIn, strNodeError); + bool ret = connman.Start(threadGroup, scheduler, nLocalServices, nRelevantServices, nMaxConnectionsIn, nMaxOutboundIn, nBestHeightIn, interfaceIn, strNodeError); return ret; } @@ -2053,7 +2058,7 @@ NodeId CConnman::GetNewNodeId() return nLastNodeId.fetch_add(1, std::memory_order_relaxed); } -bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServicesIn, ServiceFlags nRelevantServicesIn, int nMaxConnectionsIn, int nMaxOutboundIn, int nBestHeightIn, std::string& strNodeError) +bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServicesIn, ServiceFlags nRelevantServicesIn, int nMaxConnectionsIn, int nMaxOutboundIn, int nBestHeightIn, CClientUIInterface* interfaceIn, std::string& strNodeError) { nTotalBytesRecv = 0; nTotalBytesSent = 0; @@ -2072,7 +2077,9 @@ bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, Se SetBestHeight(nBestHeightIn); - uiInterface.InitMessage(_("Loading addresses...")); + clientInterface = interfaceIn; + if (clientInterface) + clientInterface->InitMessage(_("Loading addresses...")); // Load addresses from peers.dat int64_t nStart = GetTimeMillis(); { @@ -2085,8 +2092,8 @@ bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, Se DumpAddresses(); } } - - uiInterface.InitMessage(_("Loading banlist...")); + if (clientInterface) + clientInterface->InitMessage(_("Loading banlist...")); // Load addresses from banlist.dat nStart = GetTimeMillis(); CBanDB bandb; diff --git a/src/net.h b/src/net.h index 852822d85b71c..a45e18da6725d 100644 --- a/src/net.h +++ b/src/net.h @@ -96,6 +96,8 @@ struct AddedNodeInfo class CTransaction; class CNodeStats; +class CClientUIInterface; + class CConnman { public: @@ -109,7 +111,7 @@ class CConnman CConnman(); ~CConnman(); - bool Start(boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServicesIn, ServiceFlags nRelevantServicesIn, int nMaxConnectionsIn, int nMaxOutboundIn, int nBestHeightIn, std::string& strNodeError); + bool Start(boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServicesIn, ServiceFlags nRelevantServicesIn, int nMaxConnectionsIn, int nMaxOutboundIn, int nBestHeightIn, CClientUIInterface* interfaceIn, std::string& strNodeError); void Stop(); bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false, bool fFeeler = false); @@ -293,12 +295,13 @@ class CConnman int nMaxConnections; int nMaxOutbound; std::atomic nBestHeight; + CClientUIInterface* clientInterface; }; extern std::unique_ptr g_connman; void MapPort(bool fUseUPnP); unsigned short GetListenPort(); bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); -bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServices, ServiceFlags nRelevantServices, int nMaxConnections, int nMaxOutbound, int nBestHeightIn, std::string& strNodeError); +bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServices, ServiceFlags nRelevantServices, int nMaxConnections, int nMaxOutbound, int nBestHeightIn, CClientUIInterface* interfaceIn, std::string& strNodeError); bool StopNode(CConnman& connman); size_t SocketSendData(CNode *pnode); From bafa5fc5a1ba33337b5eb3d8ae24ba2fac2949f8 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 26 May 2016 23:29:39 -0400 Subject: [PATCH 0858/1802] net: Drop StartNode/StopNode and use CConnman directly --- src/init.cpp | 10 ++++++++-- src/net.cpp | 24 ++---------------------- src/net.h | 3 +-- 3 files changed, 11 insertions(+), 26 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 9e2ed62a922b9..4e1c8e1b61184 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -199,7 +199,8 @@ void Shutdown() if (pwalletMain) pwalletMain->Flush(false); #endif - StopNode(*g_connman); + MapPort(false); + g_connman->Stop(); g_connman.reset(); StopTorControl(); @@ -1508,9 +1509,14 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION)) StartTorControl(threadGroup, scheduler); + Discover(threadGroup); + + // Map ports with UPnP + MapPort(GetBoolArg("-upnp", DEFAULT_UPNP)); + std::string strNodeError; int nMaxOutbound = std::min(MAX_OUTBOUND_CONNECTIONS, nMaxConnections); - if(!StartNode(connman, threadGroup, scheduler, nLocalServices, nRelevantServices, nMaxConnections, nMaxOutbound, chainActive.Height(), &uiInterface, strNodeError)) + if(!connman.Start(threadGroup, scheduler, nLocalServices, nRelevantServices, nMaxConnections, nMaxOutbound, chainActive.Height(), &uiInterface, strNodeError)) return InitError(strNodeError); // ********************************************************* Step 12: finished diff --git a/src/net.cpp b/src/net.cpp index 13218b4221fbd..15c066cd7ce4d 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1979,7 +1979,7 @@ bool CConnman::BindListenPort(const CService &addrBind, std::string& strError, b return true; } -void static Discover(boost::thread_group& threadGroup) +void Discover(boost::thread_group& threadGroup) { if (!fDiscover) return; @@ -2044,15 +2044,6 @@ CConnman::CConnman() clientInterface = NULL; } -bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServices, ServiceFlags nRelevantServices, int nMaxConnectionsIn, int nMaxOutboundIn, int nBestHeightIn, CClientUIInterface* interfaceIn, std::string& strNodeError) -{ - Discover(threadGroup); - - bool ret = connman.Start(threadGroup, scheduler, nLocalServices, nRelevantServices, nMaxConnectionsIn, nMaxOutboundIn, nBestHeightIn, interfaceIn, strNodeError); - - return ret; -} - NodeId CConnman::GetNewNodeId() { return nLastNodeId.fetch_add(1, std::memory_order_relaxed); @@ -2136,9 +2127,6 @@ bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, Se else threadGroup.create_thread(boost::bind(&TraceThread >, "dnsseed", boost::function(boost::bind(&CConnman::ThreadDNSAddressSeed, this)))); - // Map ports with UPnP - MapPort(GetBoolArg("-upnp", DEFAULT_UPNP)); - // Send and receive from sockets, accept connections threadGroup.create_thread(boost::bind(&TraceThread >, "net", boost::function(boost::bind(&CConnman::ThreadSocketHandler, this)))); @@ -2157,15 +2145,6 @@ bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, Se return true; } -bool StopNode(CConnman& connman) -{ - LogPrintf("StopNode()\n"); - MapPort(false); - - connman.Stop(); - return true; -} - class CNetCleanup { public: @@ -2183,6 +2162,7 @@ instance_of_cnetcleanup; void CConnman::Stop() { + LogPrintf("%s\n",__func__); if (semOutbound) for (int i=0; i<(nMaxOutbound + MAX_FEELER_CONNECTIONS); i++) semOutbound->post(); diff --git a/src/net.h b/src/net.h index a45e18da6725d..e08409e81e217 100644 --- a/src/net.h +++ b/src/net.h @@ -298,11 +298,10 @@ class CConnman CClientUIInterface* clientInterface; }; extern std::unique_ptr g_connman; +void Discover(boost::thread_group& threadGroup); void MapPort(bool fUseUPnP); unsigned short GetListenPort(); bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); -bool StartNode(CConnman& connman, boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServices, ServiceFlags nRelevantServices, int nMaxConnections, int nMaxOutbound, int nBestHeightIn, CClientUIInterface* interfaceIn, std::string& strNodeError); -bool StopNode(CConnman& connman); size_t SocketSendData(CNode *pnode); struct CombinerAll From a19553b992f40b9f98e6e0be4cd529a89746ef50 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 26 May 2016 23:53:08 -0400 Subject: [PATCH 0859/1802] net: Introduce CConnection::Options to avoid passing so many params --- src/init.cpp | 11 +++++++++-- src/net.cpp | 14 +++++++------- src/net.h | 11 ++++++++++- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 4e1c8e1b61184..e1080364393df 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1515,8 +1515,15 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) MapPort(GetBoolArg("-upnp", DEFAULT_UPNP)); std::string strNodeError; - int nMaxOutbound = std::min(MAX_OUTBOUND_CONNECTIONS, nMaxConnections); - if(!connman.Start(threadGroup, scheduler, nLocalServices, nRelevantServices, nMaxConnections, nMaxOutbound, chainActive.Height(), &uiInterface, strNodeError)) + CConnman::Options connOptions; + connOptions.nLocalServices = nLocalServices; + connOptions.nRelevantServices = nRelevantServices; + connOptions.nMaxConnections = nMaxConnections; + connOptions.nMaxOutbound = std::min(MAX_OUTBOUND_CONNECTIONS, connOptions.nMaxConnections); + connOptions.nBestHeight = chainActive.Height(); + connOptions.uiInterface = &uiInterface; + + if(!connman.Start(threadGroup, scheduler, strNodeError, connOptions)) return InitError(strNodeError); // ********************************************************* Step 12: finished diff --git a/src/net.cpp b/src/net.cpp index 15c066cd7ce4d..8ea600b371cae 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2049,26 +2049,26 @@ NodeId CConnman::GetNewNodeId() return nLastNodeId.fetch_add(1, std::memory_order_relaxed); } -bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServicesIn, ServiceFlags nRelevantServicesIn, int nMaxConnectionsIn, int nMaxOutboundIn, int nBestHeightIn, CClientUIInterface* interfaceIn, std::string& strNodeError) +bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, std::string& strNodeError, Options connOptions) { nTotalBytesRecv = 0; nTotalBytesSent = 0; nMaxOutboundLimit = 0; nMaxOutboundTotalBytesSentInCycle = 0; nMaxOutboundTimeframe = 60*60*24; //1 day - nLocalServices = nLocalServicesIn; - nRelevantServices = nRelevantServicesIn; nMaxOutboundCycleStartTime = 0; - nMaxConnections = nMaxConnectionsIn; - nMaxOutbound = std::min((nMaxOutboundIn), nMaxConnections); + nRelevantServices = connOptions.nRelevantServices; + nLocalServices = connOptions.nLocalServices; + nMaxConnections = connOptions.nMaxConnections; + nMaxOutbound = std::min((connOptions.nMaxOutbound), nMaxConnections); nSendBufferMaxSize = 1000*GetArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER); nReceiveFloodSize = 1000*GetArg("-maxreceivebuffer", DEFAULT_MAXRECEIVEBUFFER); - SetBestHeight(nBestHeightIn); + SetBestHeight(connOptions.nBestHeight); - clientInterface = interfaceIn; + clientInterface = connOptions.uiInterface; if (clientInterface) clientInterface->InitMessage(_("Loading addresses...")); // Load addresses from peers.dat diff --git a/src/net.h b/src/net.h index e08409e81e217..8067ee68a7d39 100644 --- a/src/net.h +++ b/src/net.h @@ -109,9 +109,18 @@ class CConnman CONNECTIONS_ALL = (CONNECTIONS_IN | CONNECTIONS_OUT), }; + struct Options + { + ServiceFlags nLocalServices = NODE_NONE; + ServiceFlags nRelevantServices = NODE_NONE; + int nMaxConnections = 0; + int nMaxOutbound = 0; + int nBestHeight = 0; + CClientUIInterface* uiInterface = nullptr; + }; CConnman(); ~CConnman(); - bool Start(boost::thread_group& threadGroup, CScheduler& scheduler, ServiceFlags nLocalServicesIn, ServiceFlags nRelevantServicesIn, int nMaxConnectionsIn, int nMaxOutboundIn, int nBestHeightIn, CClientUIInterface* interfaceIn, std::string& strNodeError); + bool Start(boost::thread_group& threadGroup, CScheduler& scheduler, std::string& strNodeError, Options options); void Stop(); bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false, bool fFeeler = false); From fa2f8bc47fa17deccb281b750ff6c48402c5b1ce Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 27 May 2016 00:00:02 -0400 Subject: [PATCH 0860/1802] net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options --- src/init.cpp | 2 ++ src/net.cpp | 4 ++-- src/net.h | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index e1080364393df..8f7cef20c1266 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1522,6 +1522,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) connOptions.nMaxOutbound = std::min(MAX_OUTBOUND_CONNECTIONS, connOptions.nMaxConnections); connOptions.nBestHeight = chainActive.Height(); connOptions.uiInterface = &uiInterface; + connOptions.nSendBufferMaxSize = 1000*GetArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER); + connOptions.nReceiveFloodSize = 1000*GetArg("-maxreceivebuffer", DEFAULT_MAXRECEIVEBUFFER); if(!connman.Start(threadGroup, scheduler, strNodeError, connOptions)) return InitError(strNodeError); diff --git a/src/net.cpp b/src/net.cpp index 8ea600b371cae..9b18a32743b4f 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2063,8 +2063,8 @@ bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, st nMaxConnections = connOptions.nMaxConnections; nMaxOutbound = std::min((connOptions.nMaxOutbound), nMaxConnections); - nSendBufferMaxSize = 1000*GetArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER); - nReceiveFloodSize = 1000*GetArg("-maxreceivebuffer", DEFAULT_MAXRECEIVEBUFFER); + nSendBufferMaxSize = connOptions.nSendBufferMaxSize; + nReceiveFloodSize = connOptions.nSendBufferMaxSize; SetBestHeight(connOptions.nBestHeight); diff --git a/src/net.h b/src/net.h index 8067ee68a7d39..a50066da9a9ab 100644 --- a/src/net.h +++ b/src/net.h @@ -117,6 +117,8 @@ class CConnman int nMaxOutbound = 0; int nBestHeight = 0; CClientUIInterface* uiInterface = nullptr; + unsigned int nSendBufferMaxSize = 0; + unsigned int nReceiveFloodSize = 0; }; CConnman(); ~CConnman(); From 98591c50273b13cfc5419548b527280d6a84a43d Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 27 May 2016 01:00:01 -0400 Subject: [PATCH 0861/1802] net: move vNodesDisconnected into CConnman --- src/net.cpp | 2 -- src/net.h | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 9b18a32743b4f..508b0dd962e90 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -820,8 +820,6 @@ size_t SocketSendData(CNode *pnode) return nSentSize; } -static std::list vNodesDisconnected; - struct NodeEvictionCandidate { NodeId id; diff --git a/src/net.h b/src/net.h index a50066da9a9ab..018126d67706a 100644 --- a/src/net.h +++ b/src/net.h @@ -292,6 +292,7 @@ class CConnman std::vector vAddedNodes; CCriticalSection cs_vAddedNodes; std::vector vNodes; + std::list vNodesDisconnected; mutable CCriticalSection cs_vNodes; std::atomic nLastNodeId; boost::condition_variable messageHandlerCondition; From d1a2295f0d58423652b124b48fc887a9721b765c Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Wed, 15 Jun 2016 19:28:04 -0400 Subject: [PATCH 0862/1802] Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting --- src/main.cpp | 3 --- src/net.cpp | 37 +++++++++++++++++++++++++++++++++---- src/net.h | 12 ++++++++---- src/rpc/misc.cpp | 1 - src/rpc/net.cpp | 1 - src/rpc/rawtransaction.cpp | 1 - src/wallet/wallet.cpp | 1 - 7 files changed, 41 insertions(+), 15 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 1835d9712b025..e4c9ce5626a43 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3091,7 +3091,6 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, pnode->PushBlockHash(hash); } } - return true; }); } // Notify external listeners about the new tip. @@ -4727,7 +4726,6 @@ static void RelayTransaction(const CTransaction& tx, CConnman& connman) connman.ForEachNode([&inv](CNode* pnode) { pnode->PushInventory(inv); - return true; }); } @@ -4749,7 +4747,6 @@ static void RelayAddress(const CAddress& addr, bool fReachable, CConnman& connma uint64_t hashKey = CSipHasher(hasher).Write(pnode->id).Finalize(); mapMix.emplace(hashKey, pnode); } - return true; }; auto pushfunc = [&addr, &mapMix, &nRelayNodes] { diff --git a/src/net.cpp b/src/net.cpp index 508b0dd962e90..bf5cc07db1927 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2697,7 +2697,7 @@ bool CConnman::ForNode(NodeId id, std::function func) return found != nullptr && func(found); } -bool CConnman::ForEachNode(std::function func) +bool CConnman::ForEachNodeContinueIf(std::function func) { LOCK(cs_vNodes); for (auto&& node : vNodes) @@ -2706,7 +2706,7 @@ bool CConnman::ForEachNode(std::function func) return true; } -bool CConnman::ForEachNode(std::function func) const +bool CConnman::ForEachNodeContinueIf(std::function func) const { LOCK(cs_vNodes); for (const auto& node : vNodes) @@ -2715,7 +2715,7 @@ bool CConnman::ForEachNode(std::function func) const return true; } -bool CConnman::ForEachNodeThen(std::function pre, std::function post) +bool CConnman::ForEachNodeContinueIfThen(std::function pre, std::function post) { bool ret = true; LOCK(cs_vNodes); @@ -2728,7 +2728,7 @@ bool CConnman::ForEachNodeThen(std::function pre, std::funct return ret; } -bool CConnman::ForEachNodeThen(std::function pre, std::function post) const +bool CConnman::ForEachNodeContinueIfThen(std::function pre, std::function post) const { bool ret = true; LOCK(cs_vNodes); @@ -2741,6 +2741,35 @@ bool CConnman::ForEachNodeThen(std::function pre, std: return ret; } +void CConnman::ForEachNode(std::function func) +{ + LOCK(cs_vNodes); + for (auto&& node : vNodes) + func(node); +} + +void CConnman::ForEachNode(std::function func) const +{ + LOCK(cs_vNodes); + for (const auto& node : vNodes) + func(node); +} + +void CConnman::ForEachNodeThen(std::function pre, std::function post) +{ + LOCK(cs_vNodes); + for (auto&& node : vNodes) + pre(node); + post(); +} + +void CConnman::ForEachNodeThen(std::function pre, std::function post) const +{ + LOCK(cs_vNodes); + for (const auto& node : vNodes) + pre(node); + post(); +} int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds) { return nNow + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5); } diff --git a/src/net.h b/src/net.h index 018126d67706a..6ee0430f2214c 100644 --- a/src/net.h +++ b/src/net.h @@ -129,10 +129,14 @@ class CConnman bool CheckIncomingNonce(uint64_t nonce); bool ForNode(NodeId id, std::function func); - bool ForEachNode(std::function func); - bool ForEachNode(std::function func) const; - bool ForEachNodeThen(std::function pre, std::function post); - bool ForEachNodeThen(std::function pre, std::function post) const; + bool ForEachNodeContinueIf(std::function func); + bool ForEachNodeContinueIf(std::function func) const; + bool ForEachNodeContinueIfThen(std::function pre, std::function post); + bool ForEachNodeContinueIfThen(std::function pre, std::function post) const; + void ForEachNode(std::function func); + void ForEachNode(std::function func) const; + void ForEachNodeThen(std::function pre, std::function post); + void ForEachNodeThen(std::function pre, std::function post) const; void RelayTransaction(const CTransaction& tx); diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index ffd377b4892fd..2b5782367ce16 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -481,7 +481,6 @@ UniValue setmocktime(const UniValue& params, bool fHelp) if(g_connman) { g_connman->ForEachNode([t](CNode* pnode) { pnode->nLastSend = pnode->nLastRecv = t; - return true; }); } diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 61b6b62c9a0b6..b011029f51c29 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -61,7 +61,6 @@ UniValue ping(const UniValue& params, bool fHelp) // Request that each node send a ping during next message processing pass g_connman->ForEachNode([](CNode* pnode) { pnode->fPingQueued = true; - return true; }); return NullUniValue; } diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 3daf1681f314a..d2ad0a52b7004 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -898,7 +898,6 @@ UniValue sendrawtransaction(const UniValue& params, bool fHelp) g_connman->ForEachNode([&inv](CNode* pnode) { pnode->PushInventory(inv); - return true; }); return hashTx.GetHex(); } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index fd8b056bfca03..60ac2ea16611b 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1465,7 +1465,6 @@ bool CWalletTx::RelayWalletTransaction(CConnman* connman) connman->ForEachNode([&inv](CNode* pnode) { pnode->PushInventory(inv); - return true; }); return true; } From e700cd0bc885340563df9e6b7a5b6c6603b8c984 Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Sun, 19 Jun 2016 21:42:15 -0400 Subject: [PATCH 0863/1802] Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead --- src/net.cpp | 73 ------------------------------------------- src/net.h | 90 ++++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 82 insertions(+), 81 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index bf5cc07db1927..19c14e105e597 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2697,79 +2697,6 @@ bool CConnman::ForNode(NodeId id, std::function func) return found != nullptr && func(found); } -bool CConnman::ForEachNodeContinueIf(std::function func) -{ - LOCK(cs_vNodes); - for (auto&& node : vNodes) - if(!func(node)) - return false; - return true; -} - -bool CConnman::ForEachNodeContinueIf(std::function func) const -{ - LOCK(cs_vNodes); - for (const auto& node : vNodes) - if(!func(node)) - return false; - return true; -} - -bool CConnman::ForEachNodeContinueIfThen(std::function pre, std::function post) -{ - bool ret = true; - LOCK(cs_vNodes); - for (auto&& node : vNodes) - if(!pre(node)) { - ret = false; - break; - } - post(); - return ret; -} - -bool CConnman::ForEachNodeContinueIfThen(std::function pre, std::function post) const -{ - bool ret = true; - LOCK(cs_vNodes); - for (const auto& node : vNodes) - if(!pre(node)) { - ret = false; - break; - } - post(); - return ret; -} - -void CConnman::ForEachNode(std::function func) -{ - LOCK(cs_vNodes); - for (auto&& node : vNodes) - func(node); -} - -void CConnman::ForEachNode(std::function func) const -{ - LOCK(cs_vNodes); - for (const auto& node : vNodes) - func(node); -} - -void CConnman::ForEachNodeThen(std::function pre, std::function post) -{ - LOCK(cs_vNodes); - for (auto&& node : vNodes) - pre(node); - post(); -} - -void CConnman::ForEachNodeThen(std::function pre, std::function post) const -{ - LOCK(cs_vNodes); - for (const auto& node : vNodes) - pre(node); - post(); -} int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds) { return nNow + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5); } diff --git a/src/net.h b/src/net.h index 6ee0430f2214c..97604ca56e679 100644 --- a/src/net.h +++ b/src/net.h @@ -129,14 +129,88 @@ class CConnman bool CheckIncomingNonce(uint64_t nonce); bool ForNode(NodeId id, std::function func); - bool ForEachNodeContinueIf(std::function func); - bool ForEachNodeContinueIf(std::function func) const; - bool ForEachNodeContinueIfThen(std::function pre, std::function post); - bool ForEachNodeContinueIfThen(std::function pre, std::function post) const; - void ForEachNode(std::function func); - void ForEachNode(std::function func) const; - void ForEachNodeThen(std::function pre, std::function post); - void ForEachNodeThen(std::function pre, std::function post) const; + + template + bool ForEachNodeContinueIf(Callable&& func) + { + LOCK(cs_vNodes); + for (auto&& node : vNodes) + if(!func(node)) + return false; + return true; + }; + + template + bool ForEachNodeContinueIf(Callable&& func) const + { + LOCK(cs_vNodes); + for (const auto& node : vNodes) + if(!func(node)) + return false; + return true; + }; + + template + bool ForEachNodeContinueIfThen(Callable&& pre, CallableAfter&& post) + { + bool ret = true; + LOCK(cs_vNodes); + for (auto&& node : vNodes) + if(!pre(node)) { + ret = false; + break; + } + post(); + return ret; + }; + + template + bool ForEachNodeContinueIfThen(Callable&& pre, CallableAfter&& post) const + { + bool ret = true; + LOCK(cs_vNodes); + for (const auto& node : vNodes) + if(!pre(node)) { + ret = false; + break; + } + post(); + return ret; + }; + + template + void ForEachNode(Callable&& func) + { + LOCK(cs_vNodes); + for (auto&& node : vNodes) + func(node); + }; + + template + void ForEachNode(Callable&& func) const + { + LOCK(cs_vNodes); + for (const auto& node : vNodes) + func(node); + }; + + template + void ForEachNodeThen(Callable&& pre, CallableAfter&& post) + { + LOCK(cs_vNodes); + for (auto&& node : vNodes) + pre(node); + post(); + }; + + template + void ForEachNodeThen(Callable&& pre, CallableAfter&& post) const + { + LOCK(cs_vNodes); + for (const auto& node : vNodes) + pre(node); + post(); + }; void RelayTransaction(const CTransaction& tx); From 0103c5b90fa61b5d159a825fcb5a05ca31d0d1c3 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 31 Aug 2016 13:17:28 -0400 Subject: [PATCH 0864/1802] net: move MAX_FEELER_CONNECTIONS into connman --- src/init.cpp | 1 + src/net.cpp | 14 +++++--------- src/net.h | 2 ++ 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 8f7cef20c1266..a8b2cde36bb72 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1520,6 +1520,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) connOptions.nRelevantServices = nRelevantServices; connOptions.nMaxConnections = nMaxConnections; connOptions.nMaxOutbound = std::min(MAX_OUTBOUND_CONNECTIONS, connOptions.nMaxConnections); + connOptions.nMaxFeeler = 1; connOptions.nBestHeight = chainActive.Height(); connOptions.uiInterface = &uiInterface; connOptions.nSendBufferMaxSize = 1000*GetArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER); diff --git a/src/net.cpp b/src/net.cpp index 19c14e105e597..b39ef9f54a1af 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -61,11 +61,6 @@ #endif #endif - -namespace { - const int MAX_FEELER_CONNECTIONS = 1; -} - const static std::string NET_MESSAGE_COMMAND_OTHER = "*other*"; // @@ -971,7 +966,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) { SOCKET hSocket = accept(hListenSocket.socket, (struct sockaddr*)&sockaddr, &len); CAddress addr; int nInbound = 0; - int nMaxInbound = nMaxConnections - (nMaxOutbound + MAX_FEELER_CONNECTIONS); + int nMaxInbound = nMaxConnections - (nMaxOutbound + nMaxFeeler); assert(nMaxInbound > 0); if (hSocket != INVALID_SOCKET) @@ -1624,7 +1619,7 @@ void CConnman::ThreadOpenConnections() } } } - assert(nOutbound <= (nMaxOutbound + MAX_FEELER_CONNECTIONS)); + assert(nOutbound <= (nMaxOutbound + nMaxFeeler)); // Feeler Connections // @@ -2060,6 +2055,7 @@ bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, st nLocalServices = connOptions.nLocalServices; nMaxConnections = connOptions.nMaxConnections; nMaxOutbound = std::min((connOptions.nMaxOutbound), nMaxConnections); + nMaxFeeler = connOptions.nMaxFeeler; nSendBufferMaxSize = connOptions.nSendBufferMaxSize; nReceiveFloodSize = connOptions.nSendBufferMaxSize; @@ -2106,7 +2102,7 @@ bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, st if (semOutbound == NULL) { // initialize semaphore - semOutbound = new CSemaphore(std::min((nMaxOutbound + MAX_FEELER_CONNECTIONS), nMaxConnections)); + semOutbound = new CSemaphore(std::min((nMaxOutbound + nMaxFeeler), nMaxConnections)); } if (pnodeLocalHost == NULL) { @@ -2162,7 +2158,7 @@ void CConnman::Stop() { LogPrintf("%s\n",__func__); if (semOutbound) - for (int i=0; i<(nMaxOutbound + MAX_FEELER_CONNECTIONS); i++) + for (int i=0; i<(nMaxOutbound + nMaxFeeler); i++) semOutbound->post(); if (fAddressesInitialized) diff --git a/src/net.h b/src/net.h index 97604ca56e679..a48ee02c44906 100644 --- a/src/net.h +++ b/src/net.h @@ -115,6 +115,7 @@ class CConnman ServiceFlags nRelevantServices = NODE_NONE; int nMaxConnections = 0; int nMaxOutbound = 0; + int nMaxFeeler = 0; int nBestHeight = 0; CClientUIInterface* uiInterface = nullptr; unsigned int nSendBufferMaxSize = 0; @@ -384,6 +385,7 @@ class CConnman CSemaphore *semOutbound; int nMaxConnections; int nMaxOutbound; + int nMaxFeeler; std::atomic nBestHeight; CClientUIInterface* clientInterface; }; From 64d9507ea5724634783cdaa290943292132086a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Fri, 2 Sep 2016 22:05:47 +0200 Subject: [PATCH 0865/1802] [WIP] Remove unused statement in serialization --- src/addrdb.h | 1 - src/qt/recentrequeststablemodel.h | 1 - src/qt/walletmodel.h | 1 - src/wallet/wallet.h | 1 - src/wallet/walletdb.h | 2 -- 5 files changed, 6 deletions(-) diff --git a/src/addrdb.h b/src/addrdb.h index d8c66d872bb18..62835a6fb40d4 100644 --- a/src/addrdb.h +++ b/src/addrdb.h @@ -48,7 +48,6 @@ class CBanEntry template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { READWRITE(this->nVersion); - nVersion = this->nVersion; READWRITE(nCreateTime); READWRITE(nBanUntil); READWRITE(banReason); diff --git a/src/qt/recentrequeststablemodel.h b/src/qt/recentrequeststablemodel.h index f3cf03f4e3d1b..0193e748d75c2 100644 --- a/src/qt/recentrequeststablemodel.h +++ b/src/qt/recentrequeststablemodel.h @@ -31,7 +31,6 @@ class RecentRequestEntry unsigned int nDate = date.toTime_t(); READWRITE(this->nVersion); - nVersion = this->nVersion; READWRITE(id); READWRITE(nDate); READWRITE(recipient); diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index a15ecf899b87a..6515faceac635 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -75,7 +75,6 @@ class SendCoinsRecipient std::string sAuthenticatedMerchant = authenticatedMerchant.toStdString(); READWRITE(this->nVersion); - nVersion = this->nVersion; READWRITE(sAddress); READWRITE(sLabel); READWRITE(amount); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 7a771350cba43..016e4a3d74ff4 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -194,7 +194,6 @@ class CMerkleTx : public CTransaction inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { std::vector vMerkleBranch; // For compatibility with older versions. READWRITE(*(CTransaction*)this); - nVersion = this->nVersion; READWRITE(hashBlock); READWRITE(vMerkleBranch); READWRITE(nIndex); diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 5addd5c5c0225..9c9d4922a40a3 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -57,7 +57,6 @@ class CHDChain inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { READWRITE(this->nVersion); - nVersion = this->nVersion; READWRITE(nExternalChainCounter); READWRITE(masterKeyID); } @@ -96,7 +95,6 @@ class CKeyMetadata template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { READWRITE(this->nVersion); - nVersion = this->nVersion; READWRITE(nCreateTime); if (this->nVersion >= VERSION_WITH_HDDATA) { From 62ffbbdec30699941069baeae61716ff12155ba6 Mon Sep 17 00:00:00 2001 From: instagibbs Date: Fri, 9 Sep 2016 12:13:18 -0400 Subject: [PATCH 0866/1802] add witness address to address book --- src/wallet/rpcwallet.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 0ba6706baf830..533220ff85dc0 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -1087,6 +1087,8 @@ UniValue addwitnessaddress(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_WALLET_ERROR, "Public key or redeemscript not known to wallet"); } + pwalletMain->SetAddressBook(w.result, "", "receive"); + return CBitcoinAddress(w.result).ToString(); } From 1d635ae61b26d1dd613c1cc1cac796627af2a31e Mon Sep 17 00:00:00 2001 From: rodasmith Date: Sat, 10 Sep 2016 11:41:01 -0700 Subject: [PATCH 0867/1802] fix op order to append first alert --- src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index cb6e942272994..593897f5163c1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4659,12 +4659,12 @@ std::string GetWarnings(const std::string& strFor) if (fLargeWorkForkFound) { strStatusBar = strRPC = "Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues."; - strGUI += strGUI.empty() ? "" : uiAlertSeperator + _("Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues."); + strGUI += (strGUI.empty() ? "" : uiAlertSeperator) + _("Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues."); } else if (fLargeWorkInvalidChainFound) { strStatusBar = strRPC = "Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade."; - strGUI += strGUI.empty() ? "" : uiAlertSeperator + _("Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade."); + strGUI += (strGUI.empty() ? "" : uiAlertSeperator) + _("Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade."); } if (strFor == "gui") From 159597a2b8967c8bc8106d98705d68932500b58a Mon Sep 17 00:00:00 2001 From: isle2983 Date: Wed, 7 Sep 2016 19:21:41 -0600 Subject: [PATCH 0868/1802] [devtools] script support for managing source file copyright headers Three subcommands to this script: 1) ./copyright_header.py report Examines git-tracked files with extensions that match: INCLUDE = ['*.h', '*.cpp', '*.cc', '*.c', '*.py'] Helps to: -> Identify source files without copyright -> Identify source files added with something other than "The Bitcoin Core developers" holder so we can be sure it is appropriate -> Identify unintentional typos in the copyright line 2) ./copyright_header.py update Replaces fix-copyright-headers.py. It does file editing in native python rather than subprocessing out to perl as was the case with fix-copyright-headers.py. It also shares code with the 'report' functions. 3) ./copyright_header.py insert Inserts a copyright header into a source file with the proper format and dates. --- contrib/devtools/README.md | 61 ++- contrib/devtools/copyright_header.py | 610 ++++++++++++++++++++++ contrib/devtools/fix-copyright-headers.py | 67 --- 3 files changed, 662 insertions(+), 76 deletions(-) create mode 100755 contrib/devtools/copyright_header.py delete mode 100755 contrib/devtools/fix-copyright-headers.py diff --git a/contrib/devtools/README.md b/contrib/devtools/README.md index af5c000b0305e..b13dc6d3f0fc7 100644 --- a/contrib/devtools/README.md +++ b/contrib/devtools/README.md @@ -24,21 +24,64 @@ the script should be called from the git root folder as follows. ``` git diff -U0 HEAD~1.. | ./contrib/devtools/clang-format-diff.py -p1 -i -v ``` +copyright\_header.py +==================== -fix-copyright-headers.py -======================== +Provides utilities for managing copyright headers of `The Bitcoin Core +developers` in repository source files. It has three subcommands: -Every year newly updated files need to have its copyright headers updated to reflect the current year. -If you run this script from the root folder it will automatically update the year on the copyright header for all -source files if these have a git commit from the current year. +``` +$ ./copyright_header.py report [verbose] +$ ./copyright_header.py update +$ ./copyright_header.py insert +``` +Running these subcommands without arguments displays a usage string. -For example a file changed in 2015 (with 2015 being the current year): +copyright\_header.py report \ [verbose] +--------------------------------------------------------- -```// Copyright (c) 2009-2013 The Bitcoin Core developers``` +Produces a report of all copyright header notices found inside the source files +of a repository. Useful to quickly visualize the state of the headers. +Specifying `verbose` will list the full filenames of files of each category. -would be changed to: +copyright\_header.py update \ [verbose] +--------------------------------------------------------- +Updates all the copyright headers of `The Bitcoin Core developers` which were +changed in a year more recent than is listed. For example: +``` +// Copyright (c) - The Bitcoin Core developers +``` +will be updated to: +``` +// Copyright (c) - The Bitcoin Core developers +``` +where `` is obtained from the `git log` history. -```// Copyright (c) 2009-2015 The Bitcoin Core developers``` +This subcommand also handles copyright headers that have only a single year. In +those cases: +``` +// Copyright (c) The Bitcoin Core developers +``` +will be updated to: +``` +// Copyright (c) - The Bitcoin Core developers +``` +where the update is appropriate. + +copyright\_header.py insert \ +------------------------------------ +Inserts a copyright header for `The Bitcoin Core developers` at the top of the +file in either Python or C++ style as determined by the file extension. If the +file is a Python file and it has `#!` starting the first line, the header is +inserted in the line below it. + +The copyright dates will be set to be `-` where +`` is according to the `git log` history. If +`` is equal to ``, it will be set as a single +year rather than two hyphenated years. + +If the file already has a copyright for `The Bitcoin Core developers`, the +script will exit. git-subtree-check.sh ==================== diff --git a/contrib/devtools/copyright_header.py b/contrib/devtools/copyright_header.py new file mode 100755 index 0000000000000..9f35c378bf54f --- /dev/null +++ b/contrib/devtools/copyright_header.py @@ -0,0 +1,610 @@ +#!/usr/bin/env python3 +# Copyright (c) 2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import re +import fnmatch +import sys +import subprocess +import datetime +import os + +################################################################################ +# file filtering +################################################################################ + +EXCLUDE = [ + # libsecp256k1: + 'src/secp256k1/include/secp256k1.h', + 'src/secp256k1/include/secp256k1_ecdh.h', + 'src/secp256k1/include/secp256k1_recovery.h', + 'src/secp256k1/include/secp256k1_schnorr.h', + 'src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c', + 'src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h', + 'src/secp256k1/src/java/org_bitcoin_Secp256k1Context.c', + 'src/secp256k1/src/java/org_bitcoin_Secp256k1Context.h', + # auto generated: + 'src/univalue/lib/univalue_escapes.h', + 'src/qt/bitcoinstrings.cpp', + 'src/chainparamsseeds.h', + # other external copyrights: + 'src/tinyformat.h', + 'src/leveldb/util/env_win.cc', + 'src/crypto/ctaes/bench.c', + 'qa/rpc-tests/test_framework/bignum.py', + # python init: + '*__init__.py', +] +EXCLUDE_COMPILED = re.compile('|'.join([fnmatch.translate(m) for m in EXCLUDE])) + +INCLUDE = ['*.h', '*.cpp', '*.cc', '*.c', '*.py'] +INCLUDE_COMPILED = re.compile('|'.join([fnmatch.translate(m) for m in INCLUDE])) + +def applies_to_file(filename): + return ((EXCLUDE_COMPILED.match(filename) is None) and + (INCLUDE_COMPILED.match(filename) is not None)) + +################################################################################ +# obtain list of files in repo according to INCLUDE and EXCLUDE +################################################################################ + +GIT_LS_CMD = 'git ls-files' + +def call_git_ls(): + out = subprocess.check_output(GIT_LS_CMD.split(' ')) + return [f for f in out.decode("utf-8").split('\n') if f != ''] + +def get_filenames_to_examine(): + filenames = call_git_ls() + return sorted([filename for filename in filenames if + applies_to_file(filename)]) + +################################################################################ +# define and compile regexes for the patterns we are looking for +################################################################################ + + +COPYRIGHT_WITH_C = 'Copyright \(c\)' +COPYRIGHT_WITHOUT_C = 'Copyright' +ANY_COPYRIGHT_STYLE = '(%s|%s)' % (COPYRIGHT_WITH_C, COPYRIGHT_WITHOUT_C) + +YEAR = "20[0-9][0-9]" +YEAR_RANGE = '(%s)(-%s)?' % (YEAR, YEAR) +YEAR_LIST = '(%s)(, %s)+' % (YEAR, YEAR) +ANY_YEAR_STYLE = '(%s|%s)' % (YEAR_RANGE, YEAR_LIST) +ANY_COPYRIGHT_STYLE_OR_YEAR_STYLE = ("%s %s" % (ANY_COPYRIGHT_STYLE, + ANY_YEAR_STYLE)) + +ANY_COPYRIGHT_COMPILED = re.compile(ANY_COPYRIGHT_STYLE_OR_YEAR_STYLE) + +def compile_copyright_regex(copyright_style, year_style, name): + return re.compile('%s %s %s' % (copyright_style, year_style, name)) + +EXPECTED_HOLDER_NAMES = [ + "Satoshi Nakamoto\n", + "The Bitcoin Core developers\n", + "The Bitcoin Core developers \n", + "Bitcoin Core Developers\n", + "the Bitcoin Core developers\n", + "The Bitcoin developers\n", + "The LevelDB Authors\. All rights reserved\.\n", + "BitPay Inc\.\n", + "BitPay, Inc\.\n", + "University of Illinois at Urbana-Champaign\.\n", + "MarcoFalke\n", + "Pieter Wuille\n", + "Pieter Wuille +\*\n", + "Pieter Wuille, Gregory Maxwell +\*\n", + "Pieter Wuille, Andrew Poelstra +\*\n", + "Andrew Poelstra +\*\n", + "Wladimir J. van der Laan\n", + "Jeff Garzik\n", + "Diederik Huys, Pieter Wuille +\*\n", + "Thomas Daede, Cory Fields +\*\n", + "Jan-Klaas Kollhof\n", + "Sam Rushing\n", + "ArtForz -- public domain half-a-node\n", +] + +DOMINANT_STYLE_COMPILED = {} +YEAR_LIST_STYLE_COMPILED = {} +WITHOUT_C_STYLE_COMPILED = {} + +for holder_name in EXPECTED_HOLDER_NAMES: + DOMINANT_STYLE_COMPILED[holder_name] = ( + compile_copyright_regex(COPYRIGHT_WITH_C, YEAR_RANGE, holder_name)) + YEAR_LIST_STYLE_COMPILED[holder_name] = ( + compile_copyright_regex(COPYRIGHT_WITH_C, YEAR_LIST, holder_name)) + WITHOUT_C_STYLE_COMPILED[holder_name] = ( + compile_copyright_regex(COPYRIGHT_WITHOUT_C, ANY_YEAR_STYLE, + holder_name)) + +################################################################################ +# search file contents for copyright message of particular category +################################################################################ + +def get_count_of_copyrights_of_any_style_any_holder(contents): + return len(ANY_COPYRIGHT_COMPILED.findall(contents)) + +def file_has_dominant_style_copyright_for_holder(contents, holder_name): + match = DOMINANT_STYLE_COMPILED[holder_name].search(contents) + return match is not None + +def file_has_year_list_style_copyright_for_holder(contents, holder_name): + match = YEAR_LIST_STYLE_COMPILED[holder_name].search(contents) + return match is not None + +def file_has_without_c_style_copyright_for_holder(contents, holder_name): + match = WITHOUT_C_STYLE_COMPILED[holder_name].search(contents) + return match is not None + +################################################################################ +# get file info +################################################################################ + +def read_file(filename): + return open(os.path.abspath(filename), 'r').read() + +def gather_file_info(filename): + info = {} + info['filename'] = filename + c = read_file(filename) + info['contents'] = c + + info['all_copyrights'] = get_count_of_copyrights_of_any_style_any_holder(c) + + info['classified_copyrights'] = 0 + info['dominant_style'] = {} + info['year_list_style'] = {} + info['without_c_style'] = {} + for holder_name in EXPECTED_HOLDER_NAMES: + has_dominant_style = ( + file_has_dominant_style_copyright_for_holder(c, holder_name)) + has_year_list_style = ( + file_has_year_list_style_copyright_for_holder(c, holder_name)) + has_without_c_style = ( + file_has_without_c_style_copyright_for_holder(c, holder_name)) + info['dominant_style'][holder_name] = has_dominant_style + info['year_list_style'][holder_name] = has_year_list_style + info['without_c_style'][holder_name] = has_without_c_style + if has_dominant_style or has_year_list_style or has_without_c_style: + info['classified_copyrights'] = info['classified_copyrights'] + 1 + return info + +################################################################################ +# report execution +################################################################################ + +SEPARATOR = '-'.join(['' for _ in range(80)]) + +def print_filenames(filenames, verbose): + if not verbose: + return + for filename in filenames: + print("\t%s" % filename) + +def print_report(file_infos, verbose): + print(SEPARATOR) + examined = [i['filename'] for i in file_infos] + print("%d files examined according to INCLUDE and EXCLUDE fnmatch rules" % + len(examined)) + print_filenames(examined, verbose) + + print(SEPARATOR) + print('') + zero_copyrights = [i['filename'] for i in file_infos if + i['all_copyrights'] == 0] + print("%4d with zero copyrights" % len(zero_copyrights)) + print_filenames(zero_copyrights, verbose) + one_copyright = [i['filename'] for i in file_infos if + i['all_copyrights'] == 1] + print("%4d with one copyright" % len(one_copyright)) + print_filenames(one_copyright, verbose) + two_copyrights = [i['filename'] for i in file_infos if + i['all_copyrights'] == 2] + print("%4d with two copyrights" % len(two_copyrights)) + print_filenames(two_copyrights, verbose) + three_copyrights = [i['filename'] for i in file_infos if + i['all_copyrights'] == 3] + print("%4d with three copyrights" % len(three_copyrights)) + print_filenames(three_copyrights, verbose) + four_or_more_copyrights = [i['filename'] for i in file_infos if + i['all_copyrights'] >= 4] + print("%4d with four or more copyrights" % len(four_or_more_copyrights)) + print_filenames(four_or_more_copyrights, verbose) + print('') + print(SEPARATOR) + print('Copyrights with dominant style:\ne.g. "Copyright (c)" and ' + '"" or "-":\n') + for holder_name in EXPECTED_HOLDER_NAMES: + dominant_style = [i['filename'] for i in file_infos if + i['dominant_style'][holder_name]] + if len(dominant_style) > 0: + print("%4d with '%s'" % (len(dominant_style), + holder_name.replace('\n', '\\n'))) + print_filenames(dominant_style, verbose) + print('') + print(SEPARATOR) + print('Copyrights with year list style:\ne.g. "Copyright (c)" and ' + '", , ...":\n') + for holder_name in EXPECTED_HOLDER_NAMES: + year_list_style = [i['filename'] for i in file_infos if + i['year_list_style'][holder_name]] + if len(year_list_style) > 0: + print("%4d with '%s'" % (len(year_list_style), + holder_name.replace('\n', '\\n'))) + print_filenames(year_list_style, verbose) + print('') + print(SEPARATOR) + print('Copyrights with no "(c)" style:\ne.g. "Copyright" and "" or ' + '"-":\n') + for holder_name in EXPECTED_HOLDER_NAMES: + without_c_style = [i['filename'] for i in file_infos if + i['without_c_style'][holder_name]] + if len(without_c_style) > 0: + print("%4d with '%s'" % (len(without_c_style), + holder_name.replace('\n', '\\n'))) + print_filenames(without_c_style, verbose) + + print('') + print(SEPARATOR) + + unclassified_copyrights = [i['filename'] for i in file_infos if + i['classified_copyrights'] < i['all_copyrights']] + print("%d with unexpected copyright holder names" % + len(unclassified_copyrights)) + print_filenames(unclassified_copyrights, verbose) + print(SEPARATOR) + +def exec_report(base_directory, verbose): + original_cwd = os.getcwd() + os.chdir(base_directory) + filenames = get_filenames_to_examine() + file_infos = [gather_file_info(f) for f in filenames] + print_report(file_infos, verbose) + os.chdir(original_cwd) + +################################################################################ +# report cmd +################################################################################ + +REPORT_USAGE = """ +Produces a report of all copyright header notices found inside the source files +of a repository. + +Usage: + $ ./copyright_header.py report [verbose] + +Arguments: + - The base directory of a bitcoin source code repository. + [verbose] - Includes a list of every file of each subcategory in the report. +""" + +def report_cmd(argv): + if len(argv) == 2: + sys.exit(REPORT_USAGE) + + base_directory = argv[2] + if not os.path.exists(base_directory): + sys.exit("*** bad : %s" % base_directory) + + if len(argv) == 3: + verbose = False + elif argv[3] == 'verbose': + verbose = True + else: + sys.exit("*** unknown argument: %s" % argv[2]) + + exec_report(base_directory, verbose) + +################################################################################ +# query git for year of last change +################################################################################ + +GIT_LOG_CMD = "git log --pretty=format:%%ai %s" + +def call_git_log(filename): + out = subprocess.check_output((GIT_LOG_CMD % filename).split(' ')) + return out.decode("utf-8").split('\n') + +def get_git_change_years(filename): + git_log_lines = call_git_log(filename) + if len(git_log_lines) == 0: + return [datetime.date.today().year] + # timestamp is in ISO 8601 format. e.g. "2016-09-05 14:25:32 -0600" + return [line.split(' ')[0].split('-')[0] for line in git_log_lines] + +def get_most_recent_git_change_year(filename): + return max(get_git_change_years(filename)) + +################################################################################ +# read and write to file +################################################################################ + +def read_file_lines(filename): + f = open(os.path.abspath(filename), 'r') + file_lines = f.readlines() + f.close() + return file_lines + +def write_file_lines(filename, file_lines): + f = open(os.path.abspath(filename), 'w') + f.write(''.join(file_lines)) + f.close() + +################################################################################ +# update header years execution +################################################################################ + +COPYRIGHT = 'Copyright \(c\)' +YEAR = "20[0-9][0-9]" +YEAR_RANGE = '(%s)(-%s)?' % (YEAR, YEAR) +HOLDER = 'The Bitcoin Core developers' +UPDATEABLE_LINE_COMPILED = re.compile(' '.join([COPYRIGHT, YEAR_RANGE, HOLDER])) + +def get_updatable_copyright_line(file_lines): + index = 0 + for line in file_lines: + if UPDATEABLE_LINE_COMPILED.search(line) is not None: + return index, line + index = index + 1 + return None, None + +def parse_year_range(year_range): + year_split = year_range.split('-') + start_year = year_split[0] + if len(year_split) == 1: + return start_year, start_year + return start_year, year_split[1] + +def year_range_to_str(start_year, end_year): + if start_year == end_year: + return start_year + return "%s-%s" % (start_year, end_year) + +def create_updated_copyright_line(line, last_git_change_year): + copyright_splitter = 'Copyright (c) ' + copyright_split = line.split(copyright_splitter) + # Preserve characters on line that are ahead of the start of the copyright + # notice - they are part of the comment block and vary from file-to-file. + before_copyright = copyright_split[0] + after_copyright = copyright_split[1] + + space_split = after_copyright.split(' ') + year_range = space_split[0] + start_year, end_year = parse_year_range(year_range) + if end_year == last_git_change_year: + return line + return (before_copyright + copyright_splitter + + year_range_to_str(start_year, last_git_change_year) + ' ' + + ' '.join(space_split[1:])) + +def update_updatable_copyright(filename): + file_lines = read_file_lines(filename) + index, line = get_updatable_copyright_line(file_lines) + if not line: + print_file_action_message(filename, "No updatable copyright.") + return + last_git_change_year = get_most_recent_git_change_year(filename) + new_line = create_updated_copyright_line(line, last_git_change_year) + if line == new_line: + print_file_action_message(filename, "Copyright up-to-date.") + return + file_lines[index] = new_line + write_file_lines(filename, file_lines) + print_file_action_message(filename, + "Copyright updated! -> %s" % last_git_change_year) + +def exec_update_header_year(base_directory): + original_cwd = os.getcwd() + os.chdir(base_directory) + for filename in get_filenames_to_examine(): + update_updatable_copyright(filename) + os.chdir(original_cwd) + +################################################################################ +# update cmd +################################################################################ + +UPDATE_USAGE = """ +Updates all the copyright headers of "The Bitcoin Core developers" which were +changed in a year more recent than is listed. For example: + +// Copyright (c) - The Bitcoin Core developers + +will be updated to: + +// Copyright (c) - The Bitcoin Core developers + +where is obtained from the 'git log' history. + +This subcommand also handles copyright headers that have only a single year. In those cases: + +// Copyright (c) The Bitcoin Core developers + +will be updated to: + +// Copyright (c) - The Bitcoin Core developers + +where the update is appropriate. + +Usage: + $ ./copyright_header.py update + +Arguments: + - The base directory of a bitcoin source code repository. +""" + +def print_file_action_message(filename, action): + print("%-52s %s" % (filename, action)) + +def update_cmd(argv): + if len(argv) != 3: + sys.exit(UPDATE_USAGE) + + base_directory = argv[2] + if not os.path.exists(base_directory): + sys.exit("*** bad base_directory: %s" % base_directory) + exec_update_header_year(base_directory) + +################################################################################ +# inserted copyright header format +################################################################################ + +def get_header_lines(header, start_year, end_year): + lines = header.split('\n')[1:-1] + lines[0] = lines[0] % year_range_to_str(start_year, end_year) + return [line + '\n' for line in lines] + +CPP_HEADER = ''' +// Copyright (c) %s The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +''' + +def get_cpp_header_lines_to_insert(start_year, end_year): + return reversed(get_header_lines(CPP_HEADER, start_year, end_year)) + +PYTHON_HEADER = ''' +# Copyright (c) %s The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +''' + +def get_python_header_lines_to_insert(start_year, end_year): + return reversed(get_header_lines(PYTHON_HEADER, start_year, end_year)) + +################################################################################ +# query git for year of last change +################################################################################ + +def get_git_change_year_range(filename): + years = get_git_change_years(filename) + return min(years), max(years) + +################################################################################ +# check for existing core copyright +################################################################################ + +def file_already_has_core_copyright(file_lines): + index, _ = get_updatable_copyright_line(file_lines) + return index != None + +################################################################################ +# insert header execution +################################################################################ + +def file_has_hashbang(file_lines): + if len(file_lines) < 1: + return False + if len(file_lines[0]) <= 2: + return False + return file_lines[0][:2] == '#!' + +def insert_python_header(filename, file_lines, start_year, end_year): + if file_has_hashbang(file_lines): + insert_idx = 1 + else: + insert_idx = 0 + header_lines = get_python_header_lines_to_insert(start_year, end_year) + for line in header_lines: + file_lines.insert(insert_idx, line) + write_file_lines(filename, file_lines) + +def insert_cpp_header(filename, file_lines, start_year, end_year): + header_lines = get_cpp_header_lines_to_insert(start_year, end_year) + for line in header_lines: + file_lines.insert(0, line) + write_file_lines(filename, file_lines) + +def exec_insert_header(filename, style): + file_lines = read_file_lines(filename) + if file_already_has_core_copyright(file_lines): + sys.exit('*** %s already has a copyright by The Bitcoin Core developers' + % (filename)) + start_year, end_year = get_git_change_year_range(filename) + if style == 'python': + insert_python_header(filename, file_lines, start_year, end_year) + else: + insert_cpp_header(filename, file_lines, start_year, end_year) + +################################################################################ +# insert cmd +################################################################################ + +INSERT_USAGE = """ +Inserts a copyright header for "The Bitcoin Core developers" at the top of the +file in either Python or C++ style as determined by the file extension. If the +file is a Python file and it has a '#!' starting the first line, the header is +inserted in the line below it. + +The copyright dates will be set to be: + +"-" + +where is according to the 'git log' history. If + is equal to , the date will be set to be: + +"" + +If the file already has a copyright for "The Bitcoin Core developers", the +script will exit. + +Usage: + $ ./copyright_header.py insert + +Arguments: + - A source file in the bitcoin repository. +""" + +def insert_cmd(argv): + if len(argv) != 3: + sys.exit(INSERT_USAGE) + + filename = argv[2] + if not os.path.isfile(filename): + sys.exit("*** bad filename: %s" % filename) + _, extension = os.path.splitext(filename) + if extension not in ['.h', '.cpp', '.cc', '.c', '.py']: + sys.exit("*** cannot insert for file extension %s" % extension) + + if extension == '.py': + style = 'python' + else: + style = 'cpp' + exec_insert_header(filename, style) + +################################################################################ +# UI +################################################################################ + +USAGE = """ +copyright_header.py - utilities for managing copyright headers of 'The Bitcoin +Core developers' in repository source files. + +Usage: + $ ./copyright_header + +Subcommands: + report + update + insert + +To see subcommand usage, run them without arguments. +""" + +SUBCOMMANDS = ['report', 'update', 'insert'] + +if __name__ == "__main__": + if len(sys.argv) == 1: + sys.exit(USAGE) + subcommand = sys.argv[1] + if subcommand not in SUBCOMMANDS: + sys.exit(USAGE) + if subcommand == 'report': + report_cmd(sys.argv) + elif subcommand == 'update': + update_cmd(sys.argv) + elif subcommand == 'insert': + insert_cmd(sys.argv) diff --git a/contrib/devtools/fix-copyright-headers.py b/contrib/devtools/fix-copyright-headers.py deleted file mode 100755 index 54836bd83f592..0000000000000 --- a/contrib/devtools/fix-copyright-headers.py +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/bin/env python3 -""" -Run this script to update all the copyright headers of files -that were changed this year. - -For example: - -// Copyright (c) 2009-2012 The Bitcoin Core developers - -it will change it to - -// Copyright (c) 2009-2015 The Bitcoin Core developers -""" -import subprocess -import time -import re - -CMD_GIT_LIST_FILES = ['git', 'ls-files'] -CMD_GIT_DATE = ['git', 'log', '--format=%ad', '--date=short', '-1'] -CMD_PERL_REGEX = ['perl', '-pi', '-e'] -REGEX_TEMPLATE = 's/(20\\d\\d)(?:-20\\d\\d)? The Bitcoin/$1-%s The Bitcoin/' - -FOLDERS = ["qa/", "src/"] -EXTENSIONS = [".cpp",".h", ".py"] - - -def get_git_date(file_path): - d = subprocess.run(CMD_GIT_DATE + [file_path], - stdout=subprocess.PIPE, - check=True, - universal_newlines=True).stdout - # yyyy-mm-dd - return d.split('-')[0] - - -def skip_file(file_path): - for ext in EXTENSIONS: - if file_path.endswith(ext): - return False - else: - return True - -if __name__ == "__main__": - year = str(time.gmtime()[0]) - regex_current = re.compile("%s The Bitcoin" % year) - n = 1 - for folder in FOLDERS: - for file_path in subprocess.run( - CMD_GIT_LIST_FILES + [folder], - stdout=subprocess.PIPE, - check=True, - universal_newlines=True - ).stdout.split("\n"): - if skip_file(file_path): - # print(file_path, "(skip)") - continue - git_date = get_git_date(file_path) - if not year == git_date: - # print(file_path, year, "(skip)") - continue - if regex_current.search(open(file_path, "r").read()) is not None: - # already up to date - # print(file_path, year, "(skip)") - continue - print(n, file_path, "(update to %s)" % year) - subprocess.run(CMD_PERL_REGEX + [REGEX_TEMPLATE % year, file_path], check=True) - n = n + 1 From 0766d1cac38d7ea27a6323d7ca206154b2686f9b Mon Sep 17 00:00:00 2001 From: isle2983 Date: Sun, 11 Sep 2016 13:36:22 -0600 Subject: [PATCH 0869/1802] [copyright] add MIT license headers to .sh scripts where missing Years are set according to 'git log' history --- contrib/devtools/git-subtree-check.sh | 3 +++ contrib/macdeploy/detached-sig-apply.sh | 4 ++++ contrib/macdeploy/detached-sig-create.sh | 4 ++++ contrib/macdeploy/extract-osx-sdk.sh | 4 ++++ contrib/qos/tc.sh | 4 ++++ contrib/tidy_datadir.sh | 3 +++ contrib/verify-commits/gpg.sh | 4 ++++ contrib/verify-commits/pre-push-hook.sh | 4 ++++ contrib/verify-commits/verify-commits.sh | 4 ++++ contrib/verifybinaries/verify.sh | 3 +++ src/qt/res/movies/makespinner.sh | 4 ++++ 11 files changed, 41 insertions(+) diff --git a/contrib/devtools/git-subtree-check.sh b/contrib/devtools/git-subtree-check.sh index 1cb82fe6826c7..2384d66cad2aa 100755 --- a/contrib/devtools/git-subtree-check.sh +++ b/contrib/devtools/git-subtree-check.sh @@ -1,4 +1,7 @@ #!/bin/sh +# Copyright (c) 2015 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. DIR="$1" COMMIT="$2" diff --git a/contrib/macdeploy/detached-sig-apply.sh b/contrib/macdeploy/detached-sig-apply.sh index 781fe315edab5..91674a92e6fa6 100755 --- a/contrib/macdeploy/detached-sig-apply.sh +++ b/contrib/macdeploy/detached-sig-apply.sh @@ -1,4 +1,8 @@ #!/bin/sh +# Copyright (c) 2014-2015 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + set -e UNSIGNED="$1" diff --git a/contrib/macdeploy/detached-sig-create.sh b/contrib/macdeploy/detached-sig-create.sh index 89a2da32f7a1c..5022ea88bc221 100755 --- a/contrib/macdeploy/detached-sig-create.sh +++ b/contrib/macdeploy/detached-sig-create.sh @@ -1,4 +1,8 @@ #!/bin/sh +# Copyright (c) 2014-2015 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + set -e ROOTDIR=dist diff --git a/contrib/macdeploy/extract-osx-sdk.sh b/contrib/macdeploy/extract-osx-sdk.sh index 46d2d825d4523..ff9fbd58df071 100755 --- a/contrib/macdeploy/extract-osx-sdk.sh +++ b/contrib/macdeploy/extract-osx-sdk.sh @@ -1,4 +1,8 @@ #!/bin/bash +# Copyright (c) 2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + set -e INPUTFILE="Xcode_7.3.1.dmg" diff --git a/contrib/qos/tc.sh b/contrib/qos/tc.sh index f62060421202c..aaf5e1fa11ed7 100644 --- a/contrib/qos/tc.sh +++ b/contrib/qos/tc.sh @@ -1,3 +1,7 @@ +# Copyright (c) 2013 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + #network interface on which to limit traffic IF="eth0" #limit of the network interface in question diff --git a/contrib/tidy_datadir.sh b/contrib/tidy_datadir.sh index 5d6d8264442fb..8960f8811d81e 100755 --- a/contrib/tidy_datadir.sh +++ b/contrib/tidy_datadir.sh @@ -1,4 +1,7 @@ #!/bin/bash +# Copyright (c) 2013 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. if [ -d "$1" ]; then cd "$1" diff --git a/contrib/verify-commits/gpg.sh b/contrib/verify-commits/gpg.sh index 375d711725707..09ff23754473f 100755 --- a/contrib/verify-commits/gpg.sh +++ b/contrib/verify-commits/gpg.sh @@ -1,4 +1,8 @@ #!/bin/sh +# Copyright (c) 2014-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + INPUT=$(cat /dev/stdin) VALID=false REVSIG=false diff --git a/contrib/verify-commits/pre-push-hook.sh b/contrib/verify-commits/pre-push-hook.sh index c57222818ab8a..c21febb9e9249 100755 --- a/contrib/verify-commits/pre-push-hook.sh +++ b/contrib/verify-commits/pre-push-hook.sh @@ -1,4 +1,8 @@ #!/bin/bash +# Copyright (c) 2014-2015 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + if ! [[ "$2" =~ ^(git@)?(www.)?github.com(:|/)bitcoin/bitcoin(.git)?$ ]]; then exit 0 fi diff --git a/contrib/verify-commits/verify-commits.sh b/contrib/verify-commits/verify-commits.sh index 5219331e2e5bc..cfe4f11a0b7a2 100755 --- a/contrib/verify-commits/verify-commits.sh +++ b/contrib/verify-commits/verify-commits.sh @@ -1,4 +1,8 @@ #!/bin/sh +# Copyright (c) 2014-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + # Not technically POSIX-compliant due to use of "local", but almost every # shell anyone uses today supports it, so its probably fine diff --git a/contrib/verifybinaries/verify.sh b/contrib/verifybinaries/verify.sh index e22b911743b8f..e20770c96a967 100755 --- a/contrib/verifybinaries/verify.sh +++ b/contrib/verifybinaries/verify.sh @@ -1,4 +1,7 @@ #!/bin/bash +# Copyright (c) 2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. ### This script attempts to download the signature file SHA256SUMS.asc from bitcoin.org ### It first checks if the signature passes, and then downloads the files specified in diff --git a/src/qt/res/movies/makespinner.sh b/src/qt/res/movies/makespinner.sh index a4c2fddbbfe53..d0deb1238c2b8 100755 --- a/src/qt/res/movies/makespinner.sh +++ b/src/qt/res/movies/makespinner.sh @@ -1,3 +1,7 @@ +# Copyright (c) 2014-2015 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + FRAMEDIR=$(dirname $0) for i in {0..35} do From 783e930e68a312bc7654d833053cceead18dd688 Mon Sep 17 00:00:00 2001 From: isle2983 Date: Sun, 11 Sep 2016 15:25:51 -0600 Subject: [PATCH 0870/1802] [copyright] Add missing copyright headers --- contrib/devtools/optimize-pngs.py | 3 +++ contrib/gitian-build.sh | 4 ++++ contrib/qt_translations.py | 3 +++ contrib/seeds/makeseeds.py | 3 +++ contrib/spendfrom/setup.py | 3 +++ contrib/spendfrom/spendfrom.py | 3 +++ contrib/testgen/base58.py | 3 +++ contrib/testgen/gen_base58_test_vectors.py | 3 +++ qa/rpc-tests/test_framework/blockstore.py | 3 +++ 9 files changed, 28 insertions(+) diff --git a/contrib/devtools/optimize-pngs.py b/contrib/devtools/optimize-pngs.py index 799e0cc7d0fb1..b7b8dc00820d2 100755 --- a/contrib/devtools/optimize-pngs.py +++ b/contrib/devtools/optimize-pngs.py @@ -1,4 +1,7 @@ #!/usr/bin/env python +# Copyright (c) 2014-2015 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. ''' Run this script every time you change one of the png files. Using pngcrush, it will optimize the png files, remove various color profiles, remove ancillary chunks (alla) and text chunks (text). #pngcrush -brute -ow -rem gAMA -rem cHRM -rem iCCP -rem sRGB -rem alla -rem text diff --git a/contrib/gitian-build.sh b/contrib/gitian-build.sh index ee47d138f3798..53c24e3a876ca 100755 --- a/contrib/gitian-build.sh +++ b/contrib/gitian-build.sh @@ -1,3 +1,7 @@ +# Copyright (c) 2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + # What to do sign=false verify=false diff --git a/contrib/qt_translations.py b/contrib/qt_translations.py index fd8a8b71298c6..cfdeed41aba26 100755 --- a/contrib/qt_translations.py +++ b/contrib/qt_translations.py @@ -1,4 +1,7 @@ #!/usr/bin/env python +# Copyright (c) 2011 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. # Helpful little script that spits out a comma-separated list of # language codes for Qt icons that should be included diff --git a/contrib/seeds/makeseeds.py b/contrib/seeds/makeseeds.py index 4072405ef509a..041f224f40ebe 100755 --- a/contrib/seeds/makeseeds.py +++ b/contrib/seeds/makeseeds.py @@ -1,4 +1,7 @@ #!/usr/bin/env python +# Copyright (c) 2013-2015 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. # # Generate seeds.txt from Pieter's DNS seeder # diff --git a/contrib/spendfrom/setup.py b/contrib/spendfrom/setup.py index 01b9768a5b06a..f80736752ae4f 100644 --- a/contrib/spendfrom/setup.py +++ b/contrib/spendfrom/setup.py @@ -1,3 +1,6 @@ +# Copyright (c) 2013 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. from distutils.core import setup setup(name='btcspendfrom', version='1.0', diff --git a/contrib/spendfrom/spendfrom.py b/contrib/spendfrom/spendfrom.py index 72ee0425eb236..086b91b267ef4 100755 --- a/contrib/spendfrom/spendfrom.py +++ b/contrib/spendfrom/spendfrom.py @@ -1,4 +1,7 @@ #!/usr/bin/env python +# Copyright (c) 2013 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. # # Use the raw transactions API to spend bitcoins received on particular addresses, # and send any change back to that same address. diff --git a/contrib/testgen/base58.py b/contrib/testgen/base58.py index b716495145f77..72b288b2dc9f3 100644 --- a/contrib/testgen/base58.py +++ b/contrib/testgen/base58.py @@ -1,3 +1,6 @@ +# Copyright (c) 2012 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. ''' Bitcoin base58 encoding and decoding. diff --git a/contrib/testgen/gen_base58_test_vectors.py b/contrib/testgen/gen_base58_test_vectors.py index 181343695363a..8518774db3d15 100755 --- a/contrib/testgen/gen_base58_test_vectors.py +++ b/contrib/testgen/gen_base58_test_vectors.py @@ -1,4 +1,7 @@ #!/usr/bin/env python +# Copyright (c) 2012 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. ''' Generate valid and invalid base58 address and private key test vectors. diff --git a/qa/rpc-tests/test_framework/blockstore.py b/qa/rpc-tests/test_framework/blockstore.py index 6120dd574b5dd..1e2bbb277ac5c 100644 --- a/qa/rpc-tests/test_framework/blockstore.py +++ b/qa/rpc-tests/test_framework/blockstore.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright (c) 2015-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. # BlockStore: a helper class that keeps a map of blocks and implements # helper functions for responding to getheaders and getdata, # and for constructing a getheaders message From 37a7fe9e440b83e2364d5498931253937abe9294 Mon Sep 17 00:00:00 2001 From: isle2983 Date: Sun, 11 Sep 2016 15:26:53 -0600 Subject: [PATCH 0871/1802] [copyright] add MIT License copyright header to zmq_sub.py --- contrib/zmq/zmq_sub.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contrib/zmq/zmq_sub.py b/contrib/zmq/zmq_sub.py index 6268123dd8e53..3dea5e3c1440c 100755 --- a/contrib/zmq/zmq_sub.py +++ b/contrib/zmq/zmq_sub.py @@ -1,4 +1,7 @@ #!/usr/bin/env python2 +# Copyright (c) 2014-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. import array import binascii From 4677b197f7aa8d35bfc20a5961c3e1c41bb7de39 Mon Sep 17 00:00:00 2001 From: isle2983 Date: Sun, 11 Sep 2016 15:32:22 -0600 Subject: [PATCH 0872/1802] [copyright] add MIT License copyright header to remaining Python files --- contrib/devtools/security-check.py | 3 +++ contrib/devtools/test-security-check.py | 3 +++ share/qt/extract_strings_qt.py | 3 +++ 3 files changed, 9 insertions(+) diff --git a/contrib/devtools/security-check.py b/contrib/devtools/security-check.py index c61d652641767..b4b4b4603dbad 100755 --- a/contrib/devtools/security-check.py +++ b/contrib/devtools/security-check.py @@ -1,4 +1,7 @@ #!/usr/bin/env python +# Copyright (c) 2015-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. ''' Perform basic ELF security checks on a series of executables. Exit status will be 0 if successful, and the program will be silent. diff --git a/contrib/devtools/test-security-check.py b/contrib/devtools/test-security-check.py index 324b7bcd85ae3..c0f120392e622 100755 --- a/contrib/devtools/test-security-check.py +++ b/contrib/devtools/test-security-check.py @@ -1,4 +1,7 @@ #!/usr/bin/env python2 +# Copyright (c) 2015-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. ''' Test script for security-check.py ''' diff --git a/share/qt/extract_strings_qt.py b/share/qt/extract_strings_qt.py index 9624abf1fcdd3..92e0df259e790 100755 --- a/share/qt/extract_strings_qt.py +++ b/share/qt/extract_strings_qt.py @@ -1,4 +1,7 @@ #!/usr/bin/env python +# Copyright (c) 2012-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. ''' Extract _("...") strings for translation and convert to Qt stringdefs so that they can be picked up by Qt linguist. From 1f951c67a4d1e94895783d2c6b9bd235b2bf66b8 Mon Sep 17 00:00:00 2001 From: R E Broadley Date: Tue, 13 Sep 2016 09:10:22 +0700 Subject: [PATCH 0873/1802] Allow filterclear messages for enabling TX relay only. An example of where this might be useful is allowing a node to connect blocksonly during IBD but then becoming a full-node once caught up with the latest block. This might also even want to be the default behaviour since during IBD most TXs appear to be orphans, and are routinely dropped (for example when a node disconnects). Therefore, this can waste a lot of bandwidth. Additionally, another pull could be written to stop relaying of TXs to nodes that are clearly far behind the latest block and are running a node that doesn't store many orphan TXs, such as recent versions of Bitcoin Core. --- src/main.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index cb6e942272994..6e3f9daf45ed1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4941,8 +4941,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, if (!(pfrom->GetLocalServices() & NODE_BLOOM) && (strCommand == NetMsgType::FILTERLOAD || - strCommand == NetMsgType::FILTERADD || - strCommand == NetMsgType::FILTERCLEAR)) + strCommand == NetMsgType::FILTERADD)) { if (pfrom->nVersion >= NO_BLOOM_VERSION) { LOCK(cs_main); @@ -6128,8 +6127,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, else if (strCommand == NetMsgType::FILTERCLEAR) { LOCK(pfrom->cs_filter); - delete pfrom->pfilter; - pfrom->pfilter = new CBloomFilter(); + if (pfrom->GetLocalServices() & NODE_BLOOM) { + delete pfrom->pfilter; + pfrom->pfilter = new CBloomFilter(); + } pfrom->fRelayTxes = true; } From 86c3f8db0bf64693313a81d5fe92ef603499030a Mon Sep 17 00:00:00 2001 From: Johnson Lau Date: Mon, 12 Sep 2016 02:03:55 +0800 Subject: [PATCH 0874/1802] Remove createwitnessaddress This RPC command is unsafe as it will return an address even if the script is invalid. --- src/rpc/misc.cpp | 38 -------------------------------------- 1 file changed, 38 deletions(-) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 2b5782367ce16..5afcf6353c731 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -321,43 +321,6 @@ UniValue createmultisig(const UniValue& params, bool fHelp) return result; } -UniValue createwitnessaddress(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() < 1 || params.size() > 1) - { - string msg = "createwitnessaddress \"script\"\n" - "\nCreates a witness address for a particular script.\n" - "It returns a json object with the address and witness script.\n" - - "\nArguments:\n" - "1. \"script\" (string, required) A hex encoded script\n" - - "\nResult:\n" - "{\n" - " \"address\":\"multisigaddress\", (string) The value of the new address (P2SH of witness script).\n" - " \"witnessScript\":\"script\" (string) The string value of the hex-encoded witness script.\n" - "}\n" - ; - throw runtime_error(msg); - } - - if (!IsHex(params[0].get_str())) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Script must be hex-encoded"); - } - - std::vector code = ParseHex(params[0].get_str()); - CScript script(code.begin(), code.end()); - CScript witscript = GetScriptForWitness(script); - CScriptID witscriptid(witscript); - CBitcoinAddress address(witscriptid); - - UniValue result(UniValue::VOBJ); - result.push_back(Pair("address", address.ToString())); - result.push_back(Pair("witnessScript", HexStr(witscript.begin(), witscript.end()))); - - return result; -} - UniValue verifymessage(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 3) @@ -493,7 +456,6 @@ static const CRPCCommand commands[] = { "control", "getinfo", &getinfo, true }, /* uses wallet if enabled */ { "util", "validateaddress", &validateaddress, true }, /* uses wallet if enabled */ { "util", "createmultisig", &createmultisig, true }, - { "util", "createwitnessaddress", &createwitnessaddress, true }, { "util", "verifymessage", &verifymessage, true }, { "util", "signmessagewithprivkey", &signmessagewithprivkey, true }, From 86726d8680c3398c41e62924588c44f4a394367e Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 1 Sep 2016 15:24:45 +0200 Subject: [PATCH 0875/1802] Rename `-optintofullrbf` option to `-walletrbf` This makes it clear that this is a wallet option. --- src/wallet/wallet.cpp | 8 ++++---- src/wallet/wallet.h | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 5542a536e1d39..67a0174e1ba8e 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -40,7 +40,7 @@ CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE); unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET; bool bSpendZeroConfChange = DEFAULT_SPEND_ZEROCONF_CHANGE; bool fSendFreeTransactions = DEFAULT_SEND_FREE_TRANSACTIONS; -bool fOptIntoFullRbf = DEFAULT_OPT_INTO_FULL_RBF; +bool fWalletRbf = DEFAULT_WALLET_RBF; const char * DEFAULT_WALLET_DAT = "wallet.dat"; const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000; @@ -2366,7 +2366,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt // behavior." BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins) txNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second,CScript(), - std::numeric_limits::max() - (fOptIntoFullRbf ? 2 : 1))); + std::numeric_limits::max() - (fWalletRbf ? 2 : 1))); // Sign int nIn = 0; @@ -3247,7 +3247,7 @@ std::string CWallet::GetWalletHelpString(bool showDebug) strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), DEFAULT_SPEND_ZEROCONF_CHANGE)); strUsage += HelpMessageOpt("-txconfirmtarget=", strprintf(_("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)"), DEFAULT_TX_CONFIRM_TARGET)); strUsage += HelpMessageOpt("-usehd", _("Use hierarchical deterministic key generation (HD) after BIP32. Only has effect during wallet creation/first start") + " " + strprintf(_("(default: %u)"), DEFAULT_USE_HD_WALLET)); - strUsage += HelpMessageOpt("-optintofullrbf", strprintf(_("Send transactions with full-RBF opt-in enabled (default: %u)"), DEFAULT_OPT_INTO_FULL_RBF)); + strUsage += HelpMessageOpt("-walletrbf", strprintf(_("Send transactions with full-RBF opt-in enabled (default: %u)"), DEFAULT_WALLET_RBF)); strUsage += HelpMessageOpt("-upgradewallet", _("Upgrade wallet to latest format on startup")); strUsage += HelpMessageOpt("-wallet=", _("Specify wallet file (within data directory)") + " " + strprintf(_("(default: %s)"), DEFAULT_WALLET_DAT)); strUsage += HelpMessageOpt("-walletbroadcast", _("Make the wallet broadcast transactions") + " " + strprintf(_("(default: %u)"), DEFAULT_WALLETBROADCAST)); @@ -3488,7 +3488,7 @@ bool CWallet::ParameterInteraction() nTxConfirmTarget = GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET); bSpendZeroConfChange = GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE); fSendFreeTransactions = GetBoolArg("-sendfreetransactions", DEFAULT_SEND_FREE_TRANSACTIONS); - fOptIntoFullRbf = GetBoolArg("-optintofullrbf", DEFAULT_OPT_INTO_FULL_RBF); + fWalletRbf = GetBoolArg("-walletrbf", DEFAULT_WALLET_RBF); return true; } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 5d93d2c4d96d8..220b1e52b57e4 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -37,7 +37,7 @@ extern CFeeRate payTxFee; extern unsigned int nTxConfirmTarget; extern bool bSpendZeroConfChange; extern bool fSendFreeTransactions; -extern bool fOptIntoFullRbf; +extern bool fWalletRbf; static const unsigned int DEFAULT_KEYPOOL_SIZE = 100; //! -paytxfee default @@ -54,8 +54,8 @@ static const bool DEFAULT_SPEND_ZEROCONF_CHANGE = true; static const bool DEFAULT_SEND_FREE_TRANSACTIONS = false; //! -txconfirmtarget default static const unsigned int DEFAULT_TX_CONFIRM_TARGET = 2; -//! -optintofullrbf default -static const bool DEFAULT_OPT_INTO_FULL_RBF = false; +//! -walletrbf default +static const bool DEFAULT_WALLET_RBF = false; //! Largest (in bytes) free transaction we're willing to create static const unsigned int MAX_FREE_TRANSACTION_CREATE_SIZE = 1000; static const bool DEFAULT_WALLETBROADCAST = true; From d8b062ef5eea3addff00a09bad1dab162452b4b5 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 13 Sep 2016 16:36:24 +0200 Subject: [PATCH 0876/1802] [Qt] only update "amount of blocks left" when the header chain is in-sync --- src/qt/bitcoingui.cpp | 7 +++++-- src/qt/clientmodel.cpp | 10 +++++++++- src/qt/clientmodel.h | 4 ++-- src/qt/forms/modaloverlay.ui | 3 +++ src/qt/modaloverlay.cpp | 15 ++++++++++++--- src/qt/modaloverlay.h | 2 +- 6 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 628d35b5ea8b5..c184745dbe4fd 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -500,7 +500,7 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel) setTrayIconVisible(optionsModel->getHideTrayIcon()); } - modalOverlay->setKnownBestHeight(clientModel->getHeaderHeight()); + modalOverlay->setKnownBestHeight(clientModel->getHeaderTipHeight(), QDateTime::fromTime_t(clientModel->getHeaderTipTime())); } else { // Disable possibility to show main window via action toggleHideAction->setEnabled(false); @@ -718,7 +718,10 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer if (modalOverlay) { if (header) - modalOverlay->setKnownBestHeight(count); + { + /* use clientmodels getHeaderTipHeight and getHeaderTipTime because the NotifyHeaderTip signal does not fire when updating the best header */ + modalOverlay->setKnownBestHeight(clientModel->getHeaderTipHeight(), QDateTime::fromTime_t(clientModel->getHeaderTipTime())); + } else modalOverlay->tipUpdate(count, blockDate, nVerificationProgress); } diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index e3240b95a25f8..fb0cce59ccda3 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -68,7 +68,7 @@ int ClientModel::getNumBlocks() const return chainActive.Height(); } -int ClientModel::getHeaderHeight() const +int ClientModel::getHeaderTipHeight() const { LOCK(cs_main); if (!pindexBestHeader) @@ -76,6 +76,14 @@ int ClientModel::getHeaderHeight() const return pindexBestHeader->nHeight; } +int64_t ClientModel::getHeaderTipTime() const +{ + LOCK(cs_main); + if (!pindexBestHeader) + return 0; + return pindexBestHeader->GetBlockTime(); +} + quint64 ClientModel::getTotalBytesRecv() const { return CNode::GetTotalBytesRecv(); diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index f0c9a7988a62e..3fd8404cbb70b 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -51,8 +51,8 @@ class ClientModel : public QObject //! Return number of connections, default is in- and outbound (total) int getNumConnections(unsigned int flags = CONNECTIONS_ALL) const; int getNumBlocks() const; - int getHeaderHeight() const; - + int getHeaderTipHeight() const; + int64_t getHeaderTipTime() const; //! Return number of transactions in the mempool long getMempoolSize() const; //! Return the dynamic memory usage of the mempool diff --git a/src/qt/forms/modaloverlay.ui b/src/qt/forms/modaloverlay.ui index f1967a7c05721..ce9ceaaadd7e4 100644 --- a/src/qt/forms/modaloverlay.ui +++ b/src/qt/forms/modaloverlay.ui @@ -82,6 +82,9 @@ QLabel { color: rgb(40,40,40); } + + false + diff --git a/src/qt/modaloverlay.cpp b/src/qt/modaloverlay.cpp index 1cd5b199661b7..c54889039133c 100644 --- a/src/qt/modaloverlay.cpp +++ b/src/qt/modaloverlay.cpp @@ -63,10 +63,17 @@ bool ModalOverlay::event(QEvent* ev) { return QWidget::event(ev); } -void ModalOverlay::setKnownBestHeight(int count) +void ModalOverlay::setKnownBestHeight(int count, const QDateTime& blockDate) { - if (count > bestBlockHeight) - bestBlockHeight = count; + + /* only update the blockheight if the headerschain-tip is not older then 30 days */ + int64_t now = QDateTime::currentDateTime().toTime_t(); + int64_t btime = blockDate.toTime_t(); + if (btime+3600*24*30 > now) + { + if (count > bestBlockHeight) + bestBlockHeight = count; + } } void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVerificationProgress) @@ -122,6 +129,8 @@ void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVeri // show remaining amount of blocks if (bestBlockHeight > 0) ui->amountOfBlocksLeft->setText(QString::number(bestBlockHeight-count)); + else + ui->expectedTimeLeft->setText(tr("Unknown. Syncing Headers...")); } void ModalOverlay::showHide(bool hide, bool userRequested) diff --git a/src/qt/modaloverlay.h b/src/qt/modaloverlay.h index 5bf913a3f3d6f..bdbe3c39a70ac 100644 --- a/src/qt/modaloverlay.h +++ b/src/qt/modaloverlay.h @@ -23,7 +23,7 @@ class ModalOverlay : public QWidget public Q_SLOTS: void tipUpdate(int count, const QDateTime& blockDate, double nVerificationProgress); - void setKnownBestHeight(int count); + void setKnownBestHeight(int count, const QDateTime& blockDate); // will show or hide the modal layer void showHide(bool hide = false, bool userRequested = false); From 1b6bcdd3aa379a50c960e23d7c55db8294e76f7f Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 13 Sep 2016 18:08:17 +0200 Subject: [PATCH 0877/1802] Remove maxuploadtargets recommended minimum --- doc/reduce-traffic.md | 3 +-- src/net.cpp | 4 ---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/doc/reduce-traffic.md b/doc/reduce-traffic.md index 2d86588eb2ac6..697099beabe96 100644 --- a/doc/reduce-traffic.md +++ b/doc/reduce-traffic.md @@ -19,8 +19,7 @@ This is *not* a hard limit; only a threshold to minimize the outbound traffic. When the limit is about to be reached, the uploaded data is cut by no longer serving historic blocks (blocks older than one week). Keep in mind that new nodes require other nodes that are willing to serve -historic blocks. **The recommended minimum is 144 blocks per day (max. 144MB -per day)** +historic blocks. Whitelisted peers will never be disconnected, although their traffic counts for calculating the target. diff --git a/src/net.cpp b/src/net.cpp index b39ef9f54a1af..888ed44377815 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2362,11 +2362,7 @@ void CConnman::RecordBytesSent(uint64_t bytes) void CConnman::SetMaxOutboundTarget(uint64_t limit) { LOCK(cs_totalBytesSent); - uint64_t recommendedMinimum = (nMaxOutboundTimeframe / 600) * MAX_BLOCK_SERIALIZED_SIZE; nMaxOutboundLimit = limit; - - if (limit > 0 && limit < recommendedMinimum) - LogPrintf("Max outbound target is very small (%s bytes) and will be overshot. Recommended minimum is %s bytes.\n", nMaxOutboundLimit, recommendedMinimum); } uint64_t CConnman::GetMaxOutboundTarget() From fa27d990ee38a9dce1da71098be010e4a81b18c3 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Tue, 13 Sep 2016 19:35:35 +0200 Subject: [PATCH 0878/1802] [qa] create_cache: Delete temp dir when done --- qa/rpc-tests/create_cache.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/qa/rpc-tests/create_cache.py b/qa/rpc-tests/create_cache.py index b6161e0917d07..1ace6310d0d06 100755 --- a/qa/rpc-tests/create_cache.py +++ b/qa/rpc-tests/create_cache.py @@ -12,9 +12,15 @@ class CreateCache(BitcoinTestFramework): + def __init__(self): + super().__init__() + + # Test network and test nodes are not required: + self.num_nodes = 0 + self.nodes = [] + def setup_network(self): - # Don't setup any test nodes - self.options.noshutdown = True + pass def run_test(self): pass From 1111ddb9e59239f7831a9e3a81a1f67a3725c5ec Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 11 Sep 2016 20:06:20 +0200 Subject: [PATCH 0879/1802] gitignore: Remove unused lines --- .gitignore | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitignore b/.gitignore index 892b2a3e08e0c..b9db7cbd39917 100644 --- a/.gitignore +++ b/.gitignore @@ -103,10 +103,7 @@ linux-build win32-build qa/pull-tester/run-bitcoind-for-test.sh qa/pull-tester/tests_config.py -qa/pull-tester/test.*/* -qa/tmp qa/cache/* -share/BitcoindComparisonTool.jar !src/leveldb*/Makefile From a56037805c68bf34331a6a05d487ae4872261538 Mon Sep 17 00:00:00 2001 From: Spencer Lievens Date: Tue, 13 Sep 2016 23:30:32 +0100 Subject: [PATCH 0880/1802] [WALLET] Addition of ImmatureCreditCached to MarkDirty() To protect against possible invalidation and to bring conformity to the code. --- src/wallet/wallet.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 61aff6e45a967..0d096488f67b5 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -361,6 +361,7 @@ class CWalletTx : public CMerkleTx { fCreditCached = false; fAvailableCreditCached = false; + fImmatureCreditCached = false; fWatchDebitCached = false; fWatchCreditCached = false; fAvailableWatchCreditCached = false; From 36fa01f217fbc32afb90314fd257650c71a47045 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 13 Sep 2016 14:42:55 -0400 Subject: [PATCH 0881/1802] net: only delete CConnman if it's been created In the case of (for example) an already-running bitcoind, the shutdown sequence begins before CConnman has been created, leading to a null-pointer dereference when g_connman->Stop() is called. Instead, Just let the CConnman dtor take care of stopping. --- src/init.cpp | 1 - src/net.cpp | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/init.cpp b/src/init.cpp index e9552da67d116..8d1e330a05a55 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -200,7 +200,6 @@ void Shutdown() pwalletMain->Flush(false); #endif MapPort(false); - g_connman->Stop(); g_connman.reset(); StopTorControl(); diff --git a/src/net.cpp b/src/net.cpp index b39ef9f54a1af..30513a3b9a2a4 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2205,6 +2205,7 @@ void CConnman::DeleteNode(CNode* pnode) CConnman::~CConnman() { + Stop(); } size_t CConnman::GetAddressCount() const From fa644d0053ca40740b9e7b8982ff6c5d5640e4af Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Tue, 13 Sep 2016 22:00:55 +0200 Subject: [PATCH 0882/1802] [qa] wallet: Check legacy wallet as well --- qa/rpc-tests/wallet.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py index 5d96e7a6e5bec..3420be1a2ed1e 100755 --- a/qa/rpc-tests/wallet.py +++ b/qa/rpc-tests/wallet.py @@ -18,9 +18,10 @@ def __init__(self): super().__init__() self.setup_clean_chain = True self.num_nodes = 4 + self.extra_args = [['-usehd={:d}'.format(i%2==0)] for i in range(4)] def setup_network(self, split=False): - self.nodes = start_nodes(3, self.options.tmpdir) + self.nodes = start_nodes(3, self.options.tmpdir, self.extra_args[:3]) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) @@ -154,7 +155,7 @@ def run_test (self): txid2 = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1) sync_mempools(self.nodes) - self.nodes.append(start_node(3, self.options.tmpdir)) + self.nodes.append(start_node(3, self.options.tmpdir, self.extra_args[3])) connect_nodes_bi(self.nodes, 0, 3) sync_blocks(self.nodes) From dad932c241a3fe9ef8e4dc36596381666ab4f879 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20=C3=98yvind=20Urke-S=C3=A6tre?= Date: Wed, 14 Sep 2016 13:05:18 +0200 Subject: [PATCH 0883/1802] Minor change in section name Changed 'build' to 'create', as the section name have changed in newer versions of release-process.md --- doc/gitian-building.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/gitian-building.md b/doc/gitian-building.md index 938f92ff1281f..84dce3f082ff9 100644 --- a/doc/gitian-building.md +++ b/doc/gitian-building.md @@ -337,7 +337,7 @@ Getting and building the inputs -------------------------------- Follow the instructions in [doc/release-process.md](release-process.md#fetch-and-build-inputs-first-time-or-when-dependency-versions-change) -in the bitcoin repository under 'Fetch and build inputs' to install sources which require +in the bitcoin repository under 'Fetch and create inputs' to install sources which require manual intervention. Also optionally follow the next step: 'Seed the Gitian sources cache and offline git repositories' which will fetch the remaining files required for building offline. From fad41f308f5e0e0650e3eed96c8c8575b3f7c33e Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 14 Sep 2016 16:28:50 +0200 Subject: [PATCH 0884/1802] [qa] walletbackup: Sync blocks inside the loop --- qa/rpc-tests/walletbackup.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/qa/rpc-tests/walletbackup.py b/qa/rpc-tests/walletbackup.py index b991d5c761862..e12cb10a50ad7 100755 --- a/qa/rpc-tests/walletbackup.py +++ b/qa/rpc-tests/walletbackup.py @@ -45,12 +45,12 @@ def __init__(self): super().__init__() self.setup_clean_chain = True self.num_nodes = 4 + # nodes 1, 2,3 are spenders, let's give them a keypool=100 + self.extra_args = [["-keypool=100"], ["-keypool=100"], ["-keypool=100"], []] # This mirrors how the network was setup in the bash test def setup_network(self, split=False): - # nodes 1, 2,3 are spenders, let's give them a keypool=100 - extra_args = [["-keypool=100"], ["-keypool=100"], ["-keypool=100"], []] - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args) + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args) connect_nodes(self.nodes[0], 3) connect_nodes(self.nodes[1], 3) connect_nodes(self.nodes[2], 3) @@ -79,6 +79,7 @@ def do_one_round(self): # Must sync mempools before mining. sync_mempools(self.nodes) self.nodes[3].generate(1) + sync_blocks(self.nodes) # As above, this mirrors the original bash test. def start_three(self): From f3552da81393a8e78ce3e2afed0b9c9d1ff5cee0 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Mon, 12 Sep 2016 15:04:20 -0400 Subject: [PATCH 0885/1802] net: fix maxuploadtarget setting This was broken by 63cafa6329e1a. Note that while this fixes the settings, it doesn't fix the actual usage of -maxuploadtarget completely, as there is currently a bug in the nOptimisticBytesWritten accounting that causes a delayed response if the target is reached. That bug will be addressed separately. --- src/init.cpp | 8 +++++++- src/net.cpp | 5 +++-- src/net.h | 4 ++++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 8d1e330a05a55..dd3fbf8502602 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1249,8 +1249,11 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) RegisterValidationInterface(pzmqNotificationInterface); } #endif + uint64_t nMaxOutboundLimit = 0; //unlimited unless -maxuploadtarget is set + uint64_t nMaxOutboundTimeframe = MAX_UPLOAD_TIMEFRAME; + if (mapArgs.count("-maxuploadtarget")) { - connman.SetMaxOutboundTarget(GetArg("-maxuploadtarget", DEFAULT_MAX_UPLOAD_TARGET)*1024*1024); + nMaxOutboundLimit = GetArg("-maxuploadtarget", DEFAULT_MAX_UPLOAD_TARGET)*1024*1024; } // ********************************************************* Step 7: load block chain @@ -1533,6 +1536,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) connOptions.nSendBufferMaxSize = 1000*GetArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER); connOptions.nReceiveFloodSize = 1000*GetArg("-maxreceivebuffer", DEFAULT_MAXRECEIVEBUFFER); + connOptions.nMaxOutboundTimeframe = nMaxOutboundTimeframe; + connOptions.nMaxOutboundLimit = nMaxOutboundLimit; + if(!connman.Start(threadGroup, scheduler, strNodeError, connOptions)) return InitError(strNodeError); diff --git a/src/net.cpp b/src/net.cpp index cc9728b85395e..ac64b28ea86a7 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2046,9 +2046,7 @@ bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, st { nTotalBytesRecv = 0; nTotalBytesSent = 0; - nMaxOutboundLimit = 0; nMaxOutboundTotalBytesSentInCycle = 0; - nMaxOutboundTimeframe = 60*60*24; //1 day nMaxOutboundCycleStartTime = 0; nRelevantServices = connOptions.nRelevantServices; @@ -2060,6 +2058,9 @@ bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, st nSendBufferMaxSize = connOptions.nSendBufferMaxSize; nReceiveFloodSize = connOptions.nSendBufferMaxSize; + nMaxOutboundLimit = connOptions.nMaxOutboundLimit; + nMaxOutboundTimeframe = connOptions.nMaxOutboundTimeframe; + SetBestHeight(connOptions.nBestHeight); clientInterface = connOptions.uiInterface; diff --git a/src/net.h b/src/net.h index a48ee02c44906..dbed8b3dd5ccb 100644 --- a/src/net.h +++ b/src/net.h @@ -72,6 +72,8 @@ static const size_t SETASKFOR_MAX_SZ = 2 * MAX_INV_SZ; static const unsigned int DEFAULT_MAX_PEER_CONNECTIONS = 125; /** The default for -maxuploadtarget. 0 = Unlimited */ static const uint64_t DEFAULT_MAX_UPLOAD_TARGET = 0; +/** The default timeframe for -maxuploadtarget. 1 day. */ +static const uint64_t MAX_UPLOAD_TIMEFRAME = 60 * 60 * 24; /** Default for blocks only*/ static const bool DEFAULT_BLOCKSONLY = false; @@ -120,6 +122,8 @@ class CConnman CClientUIInterface* uiInterface = nullptr; unsigned int nSendBufferMaxSize = 0; unsigned int nReceiveFloodSize = 0; + uint64_t nMaxOutboundTimeframe = 0; + uint64_t nMaxOutboundLimit = 0; }; CConnman(); ~CConnman(); From 64047f8e7feb518fc2fa79feee1af983798883cc Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 14 Sep 2016 17:25:53 +0000 Subject: [PATCH 0886/1802] depends: Add libevent compatibility patch for windows Add a patch that seems to be necessary for compatibilty of libevent 2.0.22 with recent mingw-w64 gcc versions (at least GCC 5.3.1 from Ubuntu 16.04). Without this patch the Content-Length in the HTTP header ends up as `Content-Length: zu`, causing communication between the RPC client and server to break down. See discussion in #8653. Source: https://sourceforge.net/p/levent/bugs/363/ Thanks to @sstone for the suggestion. --- depends/packages/libevent.mk | 5 +++-- .../patches/libevent/libevent-2-fixes.patch | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 depends/patches/libevent/libevent-2-fixes.patch diff --git a/depends/packages/libevent.mk b/depends/packages/libevent.mk index 2e9be1e98cced..4b02b2eff9eb4 100644 --- a/depends/packages/libevent.mk +++ b/depends/packages/libevent.mk @@ -3,10 +3,11 @@ $(package)_version=2.0.22 $(package)_download_path=https://github.com/libevent/libevent/releases/download/release-2.0.22-stable $(package)_file_name=$(package)-$($(package)_version)-stable.tar.gz $(package)_sha256_hash=71c2c49f0adadacfdbe6332a372c38cf9c8b7895bb73dabeaa53cdcc1d4e1fa3 -$(package)_patches=reuseaddr.patch +$(package)_patches=reuseaddr.patch libevent-2-fixes.patch define $(package)_preprocess_cmds - patch -p1 < $($(package)_patch_dir)/reuseaddr.patch + patch -p1 < $($(package)_patch_dir)/reuseaddr.patch && \ + patch -p1 < $($(package)_patch_dir)/libevent-2-fixes.patch endef define $(package)_set_vars diff --git a/depends/patches/libevent/libevent-2-fixes.patch b/depends/patches/libevent/libevent-2-fixes.patch new file mode 100644 index 0000000000000..79fec8a48851c --- /dev/null +++ b/depends/patches/libevent/libevent-2-fixes.patch @@ -0,0 +1,18 @@ +--- a/util-internal.h 2013-11-01 12:18:57.000000000 -0600 ++++ b/util-internal.h 2015-07-20 20:19:43.199560900 -0500 +@@ -299,8 +299,13 @@ HANDLE evutil_load_windows_system_librar + + #if defined(__STDC__) && defined(__STDC_VERSION__) + #if (__STDC_VERSION__ >= 199901L) +-#define EV_SIZE_FMT "%zu" +-#define EV_SSIZE_FMT "%zd" ++ #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__) ++ #define EV_SIZE_FMT "%Iu" ++ #define EV_SSIZE_FMT "%Id" ++ #else ++ #define EV_SIZE_FMT "%zu" ++ #define EV_SSIZE_FMT "%zd" ++ #endif + #define EV_SIZE_ARG(x) (x) + #define EV_SSIZE_ARG(x) (x) + #endif From 159ed95f7452ab5454e9d660f6f095b8476b1eed Mon Sep 17 00:00:00 2001 From: Jiaxing Wang Date: Thu, 15 Sep 2016 17:39:54 +0800 Subject: [PATCH 0887/1802] base58: Improve DecodeBase58 performance. Improve DecodeBase58 performance the same way as commit 3252208 did for EncodeBase58. --- src/base58.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/base58.cpp b/src/base58.cpp index d1d60a6f1dcf5..405b67c153711 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -25,12 +25,14 @@ bool DecodeBase58(const char* psz, std::vector& vch) psz++; // Skip and count leading '1's. int zeroes = 0; + int length = 0; while (*psz == '1') { zeroes++; psz++; } // Allocate enough space in big-endian base256 representation. - std::vector b256(strlen(psz) * 733 / 1000 + 1); // log(58) / log(256), rounded up. + int size = strlen(psz) * 733 /1000 + 1; // log(58) / log(256), rounded up. + std::vector b256(size); // Process the characters. while (*psz && !isspace(*psz)) { // Decode base58 character @@ -39,12 +41,14 @@ bool DecodeBase58(const char* psz, std::vector& vch) return false; // Apply "b256 = b256 * 58 + ch". int carry = ch - pszBase58; - for (std::vector::reverse_iterator it = b256.rbegin(); it != b256.rend(); it++) { + int i = 0; + for (std::vector::reverse_iterator it = b256.rbegin(); (carry != 0 || i < length) && (it != b256.rend()); it++, i++) { carry += 58 * (*it); *it = carry % 256; carry /= 256; } assert(carry == 0); + length = i; psz++; } // Skip trailing spaces. @@ -53,7 +57,7 @@ bool DecodeBase58(const char* psz, std::vector& vch) if (*psz != 0) return false; // Skip leading zeroes in b256. - std::vector::iterator it = b256.begin(); + std::vector::iterator it = b256.begin() + (size - length); while (it != b256.end() && *it == 0) it++; // Copy result into output vector. From b4fb51271905f9ef39e5c2bc7e8c15e7489394a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Thu, 15 Sep 2016 12:40:09 +0200 Subject: [PATCH 0888/1802] UndoReadFromDisk works on undo files (rev), not on block files. --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 593897f5163c1..10cb54e94b7bb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2062,7 +2062,7 @@ bool UndoReadFromDisk(CBlockUndo& blockundo, const CDiskBlockPos& pos, const uin // Open history file to read CAutoFile filein(OpenUndoFile(pos, true), SER_DISK, CLIENT_VERSION); if (filein.IsNull()) - return error("%s: OpenBlockFile failed", __func__); + return error("%s: OpenUndoFile failed", __func__); // Read block uint256 hashChecksum; From 59adc86680911a83dcccf5b23db299a370fc92f2 Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Fri, 9 Sep 2016 18:53:23 -0700 Subject: [PATCH 0889/1802] Add CWallet::ListAccountCreditDebit Simple pass through for CWalletDB::ListAccountCreditDebit --- src/wallet/test/accounting_tests.cpp | 2 +- src/wallet/wallet.cpp | 5 +++++ src/wallet/wallet.h | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/wallet/test/accounting_tests.cpp b/src/wallet/test/accounting_tests.cpp index a6cada46a226c..1863652fd72fc 100644 --- a/src/wallet/test/accounting_tests.cpp +++ b/src/wallet/test/accounting_tests.cpp @@ -23,7 +23,7 @@ GetResults(CWalletDB& walletdb, std::map& results) results.clear(); BOOST_CHECK(walletdb.ReorderTransactions(pwalletMain) == DB_LOAD_OK); - walletdb.ListAccountCreditDebit("", aes); + pwalletMain->ListAccountCreditDebit("", aes); BOOST_FOREACH(CAccountingEntry& ae, aes) { results[ae.nOrderPos] = ae; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 4c10ea0edbf0a..7b55111673708 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2501,6 +2501,11 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CCon return true; } +void CWallet::ListAccountCreditDebit(const std::string& strAccount, std::list& entries) { + CWalletDB walletdb(strWalletFile); + return walletdb.ListAccountCreditDebit(strAccount, entries); +} + bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry, CWalletDB & pwalletdb) { if (!pwalletdb.WriteAccountingEntry_Backend(acentry)) diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 61aff6e45a967..160e097a8e7a4 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -775,6 +775,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface std::string& strFailReason, const CCoinControl *coinControl = NULL, bool sign = true); bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CConnman* connman); + void ListAccountCreditDebit(const std::string& strAccount, std::list& entries); bool AddAccountingEntry(const CAccountingEntry&, CWalletDB & pwalletdb); static CFeeRate minTxFee; From d2e678d7d220e2f430c2cb4bde559acee00c8c7c Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Fri, 9 Sep 2016 19:21:44 -0700 Subject: [PATCH 0890/1802] Add CWallet::ReorderTransactions and use in accounting_tests.cpp --- src/wallet/test/accounting_tests.cpp | 2 +- src/wallet/wallet.cpp | 6 ++++++ src/wallet/wallet.h | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/wallet/test/accounting_tests.cpp b/src/wallet/test/accounting_tests.cpp index 1863652fd72fc..ad2f081b4edc8 100644 --- a/src/wallet/test/accounting_tests.cpp +++ b/src/wallet/test/accounting_tests.cpp @@ -22,7 +22,7 @@ GetResults(CWalletDB& walletdb, std::map& results) std::list aes; results.clear(); - BOOST_CHECK(walletdb.ReorderTransactions(pwalletMain) == DB_LOAD_OK); + BOOST_CHECK(pwalletMain->ReorderTransactions() == DB_LOAD_OK); pwalletMain->ListAccountCreditDebit("", aes); BOOST_FOREACH(CAccountingEntry& ae, aes) { diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 7b55111673708..fe9671926a8d1 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -649,6 +649,12 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) return true; } +DBErrors CWallet::ReorderTransactions() +{ + CWalletDB walletdb(strWalletFile); + return walletdb.ReorderTransactions(this); +} + int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb) { AssertLockHeld(cs_wallet); // nOrderPosNext diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 160e097a8e7a4..2b978ba1ee092 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -741,6 +741,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface * @return next transaction order id */ int64_t IncOrderPosNext(CWalletDB *pwalletdb = NULL); + DBErrors ReorderTransactions(); bool AccountMove(std::string strFrom, std::string strTo, CAmount nAmount, std::string strComment = ""); bool GetAccountPubkey(CPubKey &pubKey, std::string strAccount, bool bForceNew = false); From 157254a4bfdfc4ca3ad5bf2d84e82f290bd0c7f2 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Wed, 14 Sep 2016 21:00:53 -0400 Subject: [PATCH 0891/1802] Fix broken sendcmpct test in p2p-compactblocks.py Python lambda use was incorrect. sendcmpct messages need to be synchronized with RPC calls to generate(). Headers need to be synced (eg with getheaders) for cmpctblock announcements to start. Last test omitted sending a sendcmpct message. --- qa/rpc-tests/p2p-compactblocks.py | 58 ++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/qa/rpc-tests/p2p-compactblocks.py b/qa/rpc-tests/p2p-compactblocks.py index 7fe7ecc16c6e1..bf4fb43add3df 100755 --- a/qa/rpc-tests/p2p-compactblocks.py +++ b/qa/rpc-tests/p2p-compactblocks.py @@ -78,6 +78,13 @@ def send_header_for_blocks(self, new_blocks): headers_message.headers = [CBlockHeader(b) for b in new_blocks] self.send_message(headers_message) + def request_headers_and_sync(self, locator, hashstop=0): + self.clear_block_announcement() + self.get_headers(locator, hashstop) + assert(wait_until(self.received_block_announcement, timeout=30)) + assert(self.received_block_announcement()) + self.clear_block_announcement() + class CompactBlocksTest(BitcoinTestFramework): def __init__(self): @@ -130,7 +137,7 @@ def make_utxos(self): # Test "sendcmpct": # - No compact block announcements or getdata(MSG_CMPCT_BLOCK) unless # sendcmpct is sent. - # - If sendcmpct is sent with version > 0, the message is ignored. + # - If sendcmpct is sent with version > 1, the message is ignored. # - If sendcmpct is sent with boolean 0, then block announcements are not # made with compact blocks. # - If sendcmpct is then sent with boolean 1, then new block announcements @@ -142,57 +149,66 @@ def test_sendcmpct(self): def received_sendcmpct(): return (self.test_node.last_sendcmpct is not None) got_message = wait_until(received_sendcmpct, timeout=30) + assert(received_sendcmpct()) assert(got_message) assert_equal(self.test_node.last_sendcmpct.version, 1) tip = int(self.nodes[0].getbestblockhash(), 16) def check_announcement_of_new_block(node, peer, predicate): - self.test_node.clear_block_announcement() + peer.clear_block_announcement() node.generate(1) - got_message = wait_until(peer.received_block_announcement, timeout=30) + got_message = wait_until(lambda: peer.block_announced, timeout=30) + assert(peer.block_announced) assert(got_message) with mininode_lock: - assert(predicate) + assert(predicate(peer)) # We shouldn't get any block announcements via cmpctblock yet. - check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is None) + check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is None) # Try one more time, this time after requesting headers. - self.test_node.clear_block_announcement() - self.test_node.get_headers(locator=[tip], hashstop=0) - wait_until(self.test_node.received_block_announcement, timeout=30) - self.test_node.clear_block_announcement() + self.test_node.request_headers_and_sync(locator=[tip]) + check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is None and p.last_inv is not None) - check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is None and self.test_node.last_inv is not None) + # Test a few ways of using sendcmpct that should NOT + # result in compact block announcements. + # Before each test, sync the headers chain. + self.test_node.request_headers_and_sync(locator=[tip]) # Now try a SENDCMPCT message with too-high version sendcmpct = msg_sendcmpct() sendcmpct.version = 2 - self.test_node.send_message(sendcmpct) + self.test_node.send_and_ping(sendcmpct) + check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is None) - check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is None) + # Headers sync before next test. + self.test_node.request_headers_and_sync(locator=[tip]) # Now try a SENDCMPCT message with valid version, but announce=False - self.test_node.send_message(msg_sendcmpct()) - check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is None) + self.test_node.send_and_ping(msg_sendcmpct()) + check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is None) + + # Headers sync before next test. + self.test_node.request_headers_and_sync(locator=[tip]) # Finally, try a SENDCMPCT message with announce=True sendcmpct.version = 1 sendcmpct.announce = True - self.test_node.send_message(sendcmpct) - check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is not None) + self.test_node.send_and_ping(sendcmpct) + check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is not None) - # Try one more time - check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is not None) + # Try one more time (no headers sync should be needed!) + check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is not None) # Try one more time, after turning on sendheaders - self.test_node.send_message(msg_sendheaders()) - check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is not None) + self.test_node.send_and_ping(msg_sendheaders()) + check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is not None) # Now turn off announcements sendcmpct.announce = False - check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is None and self.test_node.last_headers is not None) + self.test_node.send_and_ping(sendcmpct) + check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is None and p.last_headers is not None) # This test actually causes bitcoind to (reasonably!) disconnect us, so do this last. def test_invalid_cmpctblock_message(self): From 02e2a815367945ea556a1ae9c3596917553ddfdb Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Fri, 9 Sep 2016 19:22:59 -0700 Subject: [PATCH 0892/1802] Remove pwalletdb parameter from CWallet::AddAccountingEntry --- src/wallet/test/accounting_tests.cpp | 8 ++++---- src/wallet/wallet.cpp | 15 +++++++++++---- src/wallet/wallet.h | 3 ++- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/wallet/test/accounting_tests.cpp b/src/wallet/test/accounting_tests.cpp index ad2f081b4edc8..6fc3a32aefe3a 100644 --- a/src/wallet/test/accounting_tests.cpp +++ b/src/wallet/test/accounting_tests.cpp @@ -45,7 +45,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) ae.nTime = 1333333333; ae.strOtherAccount = "b"; ae.strComment = ""; - pwalletMain->AddAccountingEntry(ae, walletdb); + pwalletMain->AddAccountingEntry(ae); wtx.mapValue["comment"] = "z"; pwalletMain->AddToWallet(wtx); @@ -55,7 +55,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) ae.nTime = 1333333336; ae.strOtherAccount = "c"; - pwalletMain->AddAccountingEntry(ae, walletdb); + pwalletMain->AddAccountingEntry(ae); GetResults(walletdb, results); @@ -71,7 +71,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) ae.nTime = 1333333330; ae.strOtherAccount = "d"; ae.nOrderPos = pwalletMain->IncOrderPosNext(); - pwalletMain->AddAccountingEntry(ae, walletdb); + pwalletMain->AddAccountingEntry(ae); GetResults(walletdb, results); @@ -121,7 +121,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) ae.nTime = 1333333334; ae.strOtherAccount = "e"; ae.nOrderPos = -1; - pwalletMain->AddAccountingEntry(ae, walletdb); + pwalletMain->AddAccountingEntry(ae); GetResults(walletdb, results); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index fe9671926a8d1..1d7ddd99a3360 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -683,7 +683,7 @@ bool CWallet::AccountMove(std::string strFrom, std::string strTo, CAmount nAmoun debit.nTime = nNow; debit.strOtherAccount = strTo; debit.strComment = strComment; - AddAccountingEntry(debit, walletdb); + AddAccountingEntry(debit, &walletdb); // Credit CAccountingEntry credit; @@ -693,7 +693,7 @@ bool CWallet::AccountMove(std::string strFrom, std::string strTo, CAmount nAmoun credit.nTime = nNow; credit.strOtherAccount = strFrom; credit.strComment = strComment; - AddAccountingEntry(credit, walletdb); + AddAccountingEntry(credit, &walletdb); if (!walletdb.TxnCommit()) return false; @@ -2512,9 +2512,16 @@ void CWallet::ListAccountCreditDebit(const std::string& strAccount, std::listWriteAccountingEntry_Backend(acentry)) return false; laccentries.push_back(acentry); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 2b978ba1ee092..584f013204931 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -777,7 +777,8 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CConnman* connman); void ListAccountCreditDebit(const std::string& strAccount, std::list& entries); - bool AddAccountingEntry(const CAccountingEntry&, CWalletDB & pwalletdb); + bool AddAccountingEntry(const CAccountingEntry&); + bool AddAccountingEntry(const CAccountingEntry&, CWalletDB *pwalletdb); static CFeeRate minTxFee; static CFeeRate fallbackFee; From 2ca6b9df1dfe50c294b01b5f06c5c5c7489f46c3 Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Fri, 9 Sep 2016 19:23:36 -0700 Subject: [PATCH 0893/1802] Remove last reference to CWalletDB from accounting_tests.cpp --- src/wallet/test/accounting_tests.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/wallet/test/accounting_tests.cpp b/src/wallet/test/accounting_tests.cpp index 6fc3a32aefe3a..a833be13d065a 100644 --- a/src/wallet/test/accounting_tests.cpp +++ b/src/wallet/test/accounting_tests.cpp @@ -3,7 +3,6 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "wallet/wallet.h" -#include "wallet/walletdb.h" #include "wallet/test/wallet_test_fixture.h" @@ -17,7 +16,7 @@ extern CWallet* pwalletMain; BOOST_FIXTURE_TEST_SUITE(accounting_tests, WalletTestingSetup) static void -GetResults(CWalletDB& walletdb, std::map& results) +GetResults(std::map& results) { std::list aes; @@ -32,7 +31,6 @@ GetResults(CWalletDB& walletdb, std::map& results) BOOST_AUTO_TEST_CASE(acc_orderupgrade) { - CWalletDB walletdb(pwalletMain->strWalletFile); std::vector vpwtx; CWalletTx wtx; CAccountingEntry ae; @@ -57,7 +55,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) ae.strOtherAccount = "c"; pwalletMain->AddAccountingEntry(ae); - GetResults(walletdb, results); + GetResults(results); BOOST_CHECK(pwalletMain->nOrderPosNext == 3); BOOST_CHECK(2 == results.size()); @@ -73,7 +71,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) ae.nOrderPos = pwalletMain->IncOrderPosNext(); pwalletMain->AddAccountingEntry(ae); - GetResults(walletdb, results); + GetResults(results); BOOST_CHECK(results.size() == 3); BOOST_CHECK(pwalletMain->nOrderPosNext == 4); @@ -105,7 +103,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) vpwtx[2]->nTimeReceived = (unsigned int)1333333329; vpwtx[2]->nOrderPos = -1; - GetResults(walletdb, results); + GetResults(results); BOOST_CHECK(results.size() == 3); BOOST_CHECK(pwalletMain->nOrderPosNext == 6); @@ -123,7 +121,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) ae.nOrderPos = -1; pwalletMain->AddAccountingEntry(ae); - GetResults(walletdb, results); + GetResults(results); BOOST_CHECK(results.size() == 4); BOOST_CHECK(pwalletMain->nOrderPosNext == 7); From d9c99c3058c90f4f7075cf5c495b8dcd2e7519a7 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 15 Sep 2016 23:32:45 +0200 Subject: [PATCH 0894/1802] net: No longer send local address in addrMe After #8594 the addrFrom sent by a node is not used anymore at all, so don't bother sending it. Also mitigates the privacy issue in (#8616). It doesn't completely solve the issue as GetLocalAddress is also called in AdvertiseLocal, but at least when advertising addresses it stands out less as *our* address. --- src/net.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net.cpp b/src/net.cpp index cc9728b85395e..38b1e7926a900 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -448,7 +448,7 @@ void CNode::PushVersion() { int64_t nTime = (fInbound ? GetAdjustedTime() : GetTime()); CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService(), addr.nServices)); - CAddress addrMe = GetLocalAddress(&addr, nLocalServices); + CAddress addrMe = CAddress(CService(), nLocalServices); if (fLogIPs) LogPrint("net", "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", PROTOCOL_VERSION, nMyStartingHeight, addrMe.ToString(), addrYou.ToString(), id); else From c4084c208509c42f796ebaa3eaded5f1cd40c506 Mon Sep 17 00:00:00 2001 From: fanquake Date: Fri, 16 Sep 2016 11:45:08 +0800 Subject: [PATCH 0895/1802] Specify Protobuf version 2 in paymentrequest.proto --- src/qt/paymentrequest.proto | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/qt/paymentrequest.proto b/src/qt/paymentrequest.proto index b2281c4c7b340..d2721a34bde8f 100644 --- a/src/qt/paymentrequest.proto +++ b/src/qt/paymentrequest.proto @@ -6,6 +6,8 @@ // https://en.bitcoin.it/wiki/Payment_Request // +syntax = "proto2"; + package payments; option java_package = "org.bitcoin.protocols.payments"; option java_outer_classname = "Protos"; From 6b6cbddb4c028e38913730eb7f8c0dfbb55809b9 Mon Sep 17 00:00:00 2001 From: fanquake Date: Fri, 29 Jul 2016 10:48:13 +0800 Subject: [PATCH 0896/1802] [depends] expat 2.2.0 --- depends/packages/expat.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/depends/packages/expat.mk b/depends/packages/expat.mk index bd2927563850b..81a660e83a557 100644 --- a/depends/packages/expat.mk +++ b/depends/packages/expat.mk @@ -1,8 +1,8 @@ package=expat -$(package)_version=2.1.1 +$(package)_version=2.2.0 $(package)_download_path=https://downloads.sourceforge.net/project/expat/expat/$($(package)_version) $(package)_file_name=$(package)-$($(package)_version).tar.bz2 -$(package)_sha256_hash=aff584e5a2f759dcfc6d48671e9529f6afe1e30b0cd6a4cec200cbe3f793de67 +$(package)_sha256_hash=d9e50ff2d19b3538bd2127902a89987474e1a4db8e43a66a4d1a712ab9a504ff define $(package)_set_vars $(package)_config_opts=--disable-static From 9616ac8a404dc73e7b5e8036a7ba14ccbe7b2616 Mon Sep 17 00:00:00 2001 From: fanquake Date: Fri, 29 Jul 2016 10:48:43 +0800 Subject: [PATCH 0897/1802] [depends] ccache 3.3.1 --- depends/packages/native_ccache.mk | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/depends/packages/native_ccache.mk b/depends/packages/native_ccache.mk index 9216e175983a9..a3a58604e583c 100644 --- a/depends/packages/native_ccache.mk +++ b/depends/packages/native_ccache.mk @@ -1,8 +1,8 @@ package=native_ccache -$(package)_version=3.2.5 -$(package)_download_path=http://samba.org/ftp/ccache +$(package)_version=3.3.1 +$(package)_download_path=https://samba.org/ftp/ccache $(package)_file_name=ccache-$($(package)_version).tar.bz2 -$(package)_sha256_hash=7a553809e90faf9de3a23ee9c5b5f786cfd4836bf502744bedb824a24bee1097 +$(package)_sha256_hash=cb6e4bafbb19ba0a2ec43386b123a5f92a20e1e3384c071d5d13e0cb3c84bf73 define $(package)_set_vars $(package)_config_opts= From 86d410d91b2188405a56bba5f1a1f74694be886a Mon Sep 17 00:00:00 2001 From: fanquake Date: Sat, 3 Sep 2016 15:29:26 +0800 Subject: [PATCH 0898/1802] [depends] fontconfig 2.12.1 --- depends/packages/fontconfig.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/depends/packages/fontconfig.mk b/depends/packages/fontconfig.mk index 2cf553ed9657b..fb97e0b9ec1b3 100644 --- a/depends/packages/fontconfig.mk +++ b/depends/packages/fontconfig.mk @@ -1,8 +1,8 @@ package=fontconfig -$(package)_version=2.11.1 +$(package)_version=2.12.1 $(package)_download_path=http://www.freedesktop.org/software/fontconfig/release/ $(package)_file_name=$(package)-$($(package)_version).tar.bz2 -$(package)_sha256_hash=dc62447533bca844463a3c3fd4083b57c90f18a70506e7a9f4936b5a1e516a99 +$(package)_sha256_hash=b449a3e10c47e1d1c7a6ec6e2016cca73d3bd68fbbd4f0ae5cc6b573f7d6c7f3 $(package)_dependencies=freetype expat define $(package)_set_vars From e892dc1268d33bfba01f35b70359b286bb9d6376 Mon Sep 17 00:00:00 2001 From: Jiaxing Wang Date: Fri, 16 Sep 2016 19:13:01 +0800 Subject: [PATCH 0899/1802] Use prefix operator in for loop of DecodeBase58. --- src/base58.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base58.cpp b/src/base58.cpp index 405b67c153711..f7768b5a647fb 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -42,7 +42,7 @@ bool DecodeBase58(const char* psz, std::vector& vch) // Apply "b256 = b256 * 58 + ch". int carry = ch - pszBase58; int i = 0; - for (std::vector::reverse_iterator it = b256.rbegin(); (carry != 0 || i < length) && (it != b256.rend()); it++, i++) { + for (std::vector::reverse_iterator it = b256.rbegin(); (carry != 0 || i < length) && (it != b256.rend()); ++it, ++i) { carry += 58 * (*it); *it = carry % 256; carry /= 256; From dddd04f979392a8c69cc11f5c54d817702eeed3e Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sat, 17 Sep 2016 11:47:51 +0200 Subject: [PATCH 0900/1802] [qa] Refactor RPCTestHandler to prevent TimeoutExpired --- qa/pull-tester/rpc-tests.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index 771f6c7a0f348..9e187b019bc8e 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -251,21 +251,27 @@ def get_next(self): self.num_running += 1 t = self.test_list.pop(0) port_seed = ["--portseed=%s" % len(self.test_list)] + log_stdout = tempfile.SpooledTemporaryFile(max_size=2**16) + log_stderr = tempfile.SpooledTemporaryFile(max_size=2**16) self.jobs.append((t, time.time(), subprocess.Popen((RPC_TESTS_DIR + t).split() + self.flags + port_seed, universal_newlines=True, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE))) + stdout=log_stdout, + stderr=log_stderr), + log_stdout, + log_stderr)) if not self.jobs: raise IndexError('pop from empty list') while True: # Return first proc that finishes time.sleep(.5) for j in self.jobs: - (name, time0, proc) = j + (name, time0, proc, log_out, log_err) = j if proc.poll() is not None: - (stdout, stderr) = proc.communicate(timeout=3) + log_out.seek(0), log_err.seek(0) + [stdout, stderr] = [l.read().decode('utf-8') for l in (log_out, log_err)] + log_out.close(), log_err.close() passed = stderr == "" and proc.returncode == 0 self.num_running -= 1 self.jobs.remove(j) From b16a7f609fdb2efa9a8a1b82f09748b95b5ae4f6 Mon Sep 17 00:00:00 2001 From: Michael Ford Date: Sun, 18 Sep 2016 19:53:02 +0800 Subject: [PATCH 0901/1802] [Doc] Target protobuf 2.6 in OS X build notes. Homebrew now installs Protobuf version 3 by default, which doesn't currently compile. Install Protobuf 2.6.x from the versions tap instead. --- doc/build-osx.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/build-osx.md b/doc/build-osx.md index c9eb4225abb5c..bc90a305622d5 100644 --- a/doc/build-osx.md +++ b/doc/build-osx.md @@ -16,7 +16,7 @@ Then install [Homebrew](http://brew.sh). Dependencies ---------------------- - brew install automake berkeley-db4 libtool boost --c++11 miniupnpc openssl pkg-config protobuf --c++11 qt5 libevent + brew install automake berkeley-db4 libtool boost --c++11 miniupnpc openssl pkg-config homebrew/versions/protobuf260 --c++11 qt5 libevent NOTE: Building with Qt4 is still supported, however, could result in a broken UI. Building with Qt5 is recommended. From d9ff591d42158e8a0a4ebdcf5fbb74978c483202 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 9 Sep 2016 12:48:10 +0200 Subject: [PATCH 0902/1802] Move static global randomizer seeds into CConnman --- src/init.cpp | 2 +- src/main.cpp | 6 +++--- src/net.cpp | 23 +++++++++++++---------- src/net.h | 13 ++++++++++--- src/test/DoS_tests.cpp | 8 ++++---- src/test/net_tests.cpp | 4 ++-- src/test/test_bitcoin.cpp | 2 +- 7 files changed, 34 insertions(+), 24 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 32b17192580c1..7b20e5b07ad08 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1116,7 +1116,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // ********************************************************* Step 6: network initialization assert(!g_connman); - g_connman = std::unique_ptr(new CConnman()); + g_connman = std::unique_ptr(new CConnman(GetRand(std::numeric_limits::max()), GetRand(std::numeric_limits::max()))); CConnman& connman = *g_connman; RegisterNodeSignals(GetNodeSignals()); diff --git a/src/main.cpp b/src/main.cpp index 593897f5163c1..1e191421b9d3b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -113,6 +113,8 @@ CScript COINBASE_FLAGS; const string strMessageMagic = "Bitcoin Signed Message:\n"; +static const uint64_t RANDOMIZER_ID_ADDRESS_RELAY = 0x3cac0035b5866b90ULL; // SHA256("main address relay")[0:8] + // Internal stuff namespace { @@ -4739,11 +4741,9 @@ static void RelayAddress(const CAddress& addr, bool fReachable, CConnman& connma // Relay to a limited number of other nodes // Use deterministic randomness to send to the same nodes for 24 hours // at a time so the addrKnowns of the chosen nodes prevent repeats - static const uint64_t salt0 = GetRand(std::numeric_limits::max()); - static const uint64_t salt1 = GetRand(std::numeric_limits::max()); uint64_t hashAddr = addr.GetHash(); std::multimap mapMix; - const CSipHasher hasher = CSipHasher(salt0, salt1).Write(hashAddr << 32).Write((GetTime() + hashAddr) / (24*60*60)); + const CSipHasher hasher = connman.GetDeterministicRandomizer(RANDOMIZER_ID_ADDRESS_RELAY).Write(hashAddr << 32).Write((GetTime() + hashAddr) / (24*60*60)); auto sortfunc = [&mapMix, &hasher](CNode* pnode) { if (pnode->nVersion >= CADDR_TIME_VERSION) { diff --git a/src/net.cpp b/src/net.cpp index 38b1e7926a900..5863f9d3f7ee1 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -63,6 +63,7 @@ const static std::string NET_MESSAGE_COMMAND_OTHER = "*other*"; +static const uint64_t RANDOMIZER_ID_NETGROUP = 0x6c0edd8036ef4036ULL; // SHA256("netgroup")[0:8] // // Global state variables // @@ -387,7 +388,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo addrman.Attempt(addrConnect, fCountFailure); // Add node - CNode* pnode = new CNode(GetNewNodeId(), nLocalServices, GetBestHeight(), hSocket, addrConnect, pszDest ? pszDest : "", false); + CNode* pnode = new CNode(GetNewNodeId(), nLocalServices, GetBestHeight(), hSocket, addrConnect, CalculateKeyedNetGroup(addrConnect), pszDest ? pszDest : "", false); GetNodeSignals().InitializeNode(pnode->GetId(), pnode); pnode->AddRef(); @@ -1022,7 +1023,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) { } } - CNode* pnode = new CNode(GetNewNodeId(), nLocalServices, GetBestHeight(), hSocket, addr, "", true); + CNode* pnode = new CNode(GetNewNodeId(), nLocalServices, GetBestHeight(), hSocket, addr, CalculateKeyedNetGroup(addr), "", true); GetNodeSignals().InitializeNode(pnode->GetId(), pnode); pnode->AddRef(); pnode->fWhitelisted = whitelisted; @@ -2023,7 +2024,7 @@ void Discover(boost::thread_group& threadGroup) #endif } -CConnman::CConnman() +CConnman::CConnman(uint64_t nSeed0In, uint64_t nSeed1In) : nSeed0(nSeed0In), nSeed1(nSeed1In) { setBannedIsDirty = false; fAddressesInitialized = false; @@ -2108,7 +2109,7 @@ bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, st if (pnodeLocalHost == NULL) { CNetAddr local; LookupHost("127.0.0.1", local, false); - pnodeLocalHost = new CNode(GetNewNodeId(), nLocalServices, GetBestHeight(), INVALID_SOCKET, CAddress(CService(local, 0), nLocalServices)); + pnodeLocalHost = new CNode(GetNewNodeId(), nLocalServices, GetBestHeight(), INVALID_SOCKET, CAddress(CService(local, 0), nLocalServices), 0); GetNodeSignals().InitializeNode(pnodeLocalHost->GetId(), pnodeLocalHost); } @@ -2498,10 +2499,10 @@ void CNode::Fuzz(int nChance) unsigned int CConnman::GetReceiveFloodSize() const { return nReceiveFloodSize; } unsigned int CConnman::GetSendBufferSize() const{ return nSendBufferMaxSize; } -CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNameIn, bool fInboundIn) : +CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress& addrIn, uint64_t nKeyedNetGroupIn, const std::string& addrNameIn, bool fInboundIn) : ssSend(SER_NETWORK, INIT_PROTO_VERSION), addr(addrIn), - nKeyedNetGroup(CalculateKeyedNetGroup(addrIn)), + nKeyedNetGroup(nKeyedNetGroupIn), addrKnown(5000, 0.001), filterInventoryKnown(50000, 0.000001) { @@ -2694,12 +2695,14 @@ int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds) { return nNow + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5); } -/* static */ uint64_t CNode::CalculateKeyedNetGroup(const CAddress& ad) +CSipHasher CConnman::GetDeterministicRandomizer(uint64_t id) { - static const uint64_t k0 = GetRand(std::numeric_limits::max()); - static const uint64_t k1 = GetRand(std::numeric_limits::max()); + return CSipHasher(nSeed0, nSeed1).Write(id); +} +uint64_t CConnman::CalculateKeyedNetGroup(const CAddress& ad) +{ std::vector vchNetGroup(ad.GetGroup()); - return CSipHasher(k0, k1).Write(&vchNetGroup[0], vchNetGroup.size()).Finalize(); + return GetDeterministicRandomizer(RANDOMIZER_ID_NETGROUP).Write(&vchNetGroup[0], vchNetGroup.size()).Finalize(); } diff --git a/src/net.h b/src/net.h index a48ee02c44906..07760f9d58d28 100644 --- a/src/net.h +++ b/src/net.h @@ -11,6 +11,7 @@ #include "amount.h" #include "bloom.h" #include "compat.h" +#include "hash.h" #include "limitedmap.h" #include "netaddress.h" #include "protocol.h" @@ -121,7 +122,7 @@ class CConnman unsigned int nSendBufferMaxSize = 0; unsigned int nReceiveFloodSize = 0; }; - CConnman(); + CConnman(uint64_t seed0, uint64_t seed1); ~CConnman(); bool Start(boost::thread_group& threadGroup, CScheduler& scheduler, std::string& strNodeError, Options options); void Stop(); @@ -294,6 +295,8 @@ class CConnman void SetBestHeight(int height); int GetBestHeight() const; + /** Get a unique deterministic randomizer. */ + CSipHasher GetDeterministicRandomizer(uint64_t id); private: struct ListenSocket { @@ -311,6 +314,8 @@ class CConnman void ThreadSocketHandler(); void ThreadDNSAddressSeed(); + uint64_t CalculateKeyedNetGroup(const CAddress& ad); + CNode* FindNode(const CNetAddr& ip); CNode* FindNode(const CSubNet& subNet); CNode* FindNode(const std::string& addrName); @@ -388,6 +393,9 @@ class CConnman int nMaxFeeler; std::atomic nBestHeight; CClientUIInterface* clientInterface; + + /** SipHasher seeds for deterministic randomness */ + const uint64_t nSeed0, nSeed1; }; extern std::unique_ptr g_connman; void Discover(boost::thread_group& threadGroup); @@ -656,14 +664,13 @@ class CNode CAmount lastSentFeeFilter; int64_t nextSendTimeFeeFilter; - CNode(NodeId id, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress &addrIn, const std::string &addrNameIn = "", bool fInboundIn = false); + CNode(NodeId id, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress &addrIn, uint64_t nKeyedNetGroupIn, const std::string &addrNameIn = "", bool fInboundIn = false); ~CNode(); private: CNode(const CNode&); void operator=(const CNode&); - static uint64_t CalculateKeyedNetGroup(const CAddress& ad); uint64_t nLocalHostNonce; ServiceFlags nLocalServices; diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index 33f107d84bfdd..97abeb7211c8b 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -48,7 +48,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning) { connman->ClearBanned(); CAddress addr1(ip(0xa0b0c001), NODE_NONE); - CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, "", true); + CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 0, "", true); GetNodeSignals().InitializeNode(dummyNode1.GetId(), &dummyNode1); dummyNode1.nVersion = 1; Misbehaving(dummyNode1.GetId(), 100); // Should get banned @@ -57,7 +57,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning) BOOST_CHECK(!connman->IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned CAddress addr2(ip(0xa0b0c002), NODE_NONE); - CNode dummyNode2(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr2, "", true); + CNode dummyNode2(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr2, 1, "", true); GetNodeSignals().InitializeNode(dummyNode2.GetId(), &dummyNode2); dummyNode2.nVersion = 1; Misbehaving(dummyNode2.GetId(), 50); @@ -74,7 +74,7 @@ BOOST_AUTO_TEST_CASE(DoS_banscore) connman->ClearBanned(); mapArgs["-banscore"] = "111"; // because 11 is my favorite number CAddress addr1(ip(0xa0b0c001), NODE_NONE); - CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, "", true); + CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 3, "", true); GetNodeSignals().InitializeNode(dummyNode1.GetId(), &dummyNode1); dummyNode1.nVersion = 1; Misbehaving(dummyNode1.GetId(), 100); @@ -96,7 +96,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) SetMockTime(nStartTime); // Overrides future calls to GetTime() CAddress addr(ip(0xa0b0c001), NODE_NONE); - CNode dummyNode(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr, "", true); + CNode dummyNode(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr, 4, "", true); GetNodeSignals().InitializeNode(dummyNode.GetId(), &dummyNode); dummyNode.nVersion = 1; diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index bc9a98ab04cf8..680708533e475 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -164,12 +164,12 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test) bool fInboundIn = false; // Test that fFeeler is false by default. - CNode* pnode1 = new CNode(id++, NODE_NETWORK, height, hSocket, addr, pszDest, fInboundIn); + CNode* pnode1 = new CNode(id++, NODE_NETWORK, height, hSocket, addr, 0, pszDest, fInboundIn); BOOST_CHECK(pnode1->fInbound == false); BOOST_CHECK(pnode1->fFeeler == false); fInboundIn = true; - CNode* pnode2 = new CNode(id++, NODE_NETWORK, height, hSocket, addr, pszDest, fInboundIn); + CNode* pnode2 = new CNode(id++, NODE_NETWORK, height, hSocket, addr, 1, pszDest, fInboundIn); BOOST_CHECK(pnode2->fInbound == true); BOOST_CHECK(pnode2->fFeeler == false); } diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index b1ceef4f64d07..02843d8525ea0 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -72,7 +72,7 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha nScriptCheckThreads = 3; for (int i=0; i < nScriptCheckThreads-1; i++) threadGroup.create_thread(&ThreadScriptCheck); - g_connman = std::unique_ptr(new CConnman()); + g_connman = std::unique_ptr(new CConnman(0x1337, 0x1337)); // Deterministic randomness for tests. connman = g_connman.get(); RegisterNodeSignals(GetNodeSignals()); } From faddd62518c7b81c56ea2c9936cf850878c03e0b Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 19 Sep 2016 15:52:48 +0200 Subject: [PATCH 0903/1802] init: Get rid of some ENABLE_WALLET --- src/init.cpp | 19 +++---------------- src/wallet/wallet.cpp | 9 +++++++++ 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 32b17192580c1..455eb8592003d 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -759,10 +759,7 @@ void InitParameterInteraction() if (GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY)) { if (SoftSetBoolArg("-whitelistrelay", false)) LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -whitelistrelay=0\n", __func__); -#ifdef ENABLE_WALLET - if (SoftSetBoolArg("-walletbroadcast", false)) - LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -walletbroadcast=0\n", __func__); -#endif + // walletbroadcast is disabled in CWallet::ParameterInteraction() } // Forcing relay from whitelisted hosts implies we will accept relays from them in the first place. @@ -821,12 +818,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) return InitError("Initializing networking failed"); #ifndef WIN32 - if (GetBoolArg("-sysperms", false)) { -#ifdef ENABLE_WALLET - if (!GetBoolArg("-disablewallet", false)) - return InitError("-sysperms is not allowed in combination with enabled wallet functionality"); -#endif - } else { + if (!GetBoolArg("-sysperms", false)) { umask(077); } @@ -854,15 +846,10 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // also see: InitParameterInteraction() - // if using block pruning, then disable txindex + // if using block pruning, then disallow txindex if (GetArg("-prune", 0)) { if (GetBoolArg("-txindex", DEFAULT_TXINDEX)) return InitError(_("Prune mode is incompatible with -txindex.")); -#ifdef ENABLE_WALLET - if (GetBoolArg("-rescan", false)) { - return InitError(_("Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.")); - } -#endif } // Make sure enough file descriptors are available diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 4c10ea0edbf0a..5638cec6a655d 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3446,6 +3446,15 @@ bool CWallet::InitLoadWallet() bool CWallet::ParameterInteraction() { + if (GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY) && SoftSetBoolArg("-walletbroadcast", false)) { + LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -walletbroadcast=0\n", __func__); + } + + if (GetBoolArg("-sysperms", false)) + return InitError("-sysperms is not allowed in combination with enabled wallet functionality"); + if (GetArg("-prune", 0) && GetBoolArg("-rescan", false)) + return InitError(_("Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.")); + if (mapArgs.count("-mintxfee")) { CAmount n = 0; From 12a721b45e16124f48ea85f96079feec18e948ca Mon Sep 17 00:00:00 2001 From: Marty Jones Date: Mon, 19 Sep 2016 21:17:27 -0500 Subject: [PATCH 0904/1802] Trivial: Fix typo --- doc/translation_process.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/translation_process.md b/doc/translation_process.md index a443a16fe240e..9e9ced245722a 100644 --- a/doc/translation_process.md +++ b/doc/translation_process.md @@ -6,7 +6,7 @@ The Bitcoin-Core project has been designed to support multiple localisations. Th ### Helping to translate (using Transifex) Transifex is setup to monitor the Github repo for updates, and when code containing new translations is found, Transifex will process any changes. It may take several hours after a pull-request has been merged, to appear in the Transifex web interface. -Multiple language support is critical in assisting Bitcoin’s global adoption, and growth. One of Bitcoin’s greatest strengths is cross-boarder money transfers, any help making that easier is greatly appreciated. +Multiple language support is critical in assisting Bitcoin’s global adoption, and growth. One of Bitcoin’s greatest strengths is cross-border money transfers, any help making that easier is greatly appreciated. See the [Transifex Bitcoin project](https://www.transifex.com/projects/p/bitcoin/) to assist in translations. You should also join the translation mailing list for announcements - see details below. From 94a34a5d951cee59ef9c9274c5ad49ac2a91ab8a Mon Sep 17 00:00:00 2001 From: maiiz Date: Mon, 18 Jul 2016 15:01:34 +0800 Subject: [PATCH 0905/1802] Fix relaypriority calculation error --- src/coins.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coins.cpp b/src/coins.cpp index 39db7dedfbbe1..8ff652b474bc8 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -275,7 +275,7 @@ double CCoinsViewCache::GetPriority(const CTransaction &tx, int nHeight, CAmount assert(coins); if (!coins->IsAvailable(txin.prevout.n)) continue; if (coins->nHeight <= nHeight) { - dResult += coins->vout[txin.prevout.n].nValue * (nHeight-coins->nHeight); + dResult += (double)(coins->vout[txin.prevout.n].nValue) * (nHeight-coins->nHeight); inChainInputValue += coins->vout[txin.prevout.n].nValue; } } From c6f5ca822f1308983431bf1b3c91f8aaccff51a0 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 20 Sep 2016 16:18:24 +0200 Subject: [PATCH 0906/1802] [Wallet] remove "unused" ThreadFlushWalletDB from removeprunedfunds --- src/wallet/rpcdump.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 42ebdb9b9b861..e80fa7dff81d8 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -344,8 +344,6 @@ UniValue removeprunedfunds(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INTERNAL_ERROR, "Transaction does not exist in wallet."); } - ThreadFlushWalletDB(pwalletMain->strWalletFile); - return NullUniValue; } From fab91070d38aa248a852e04c56dcb73e4022872d Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 19 Sep 2016 16:09:38 +0200 Subject: [PATCH 0907/1802] init: Get rid of fDisableWallet --- src/init.cpp | 30 ++++++++++-------------------- src/wallet/rpcwallet.cpp | 3 +++ src/wallet/wallet.cpp | 12 ++++++++++++ 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index a15f1f1a4f29a..75182345ee9f0 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -935,9 +935,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) RegisterAllCoreRPCCommands(tableRPC); #ifdef ENABLE_WALLET - bool fDisableWallet = GetBoolArg("-disablewallet", false); - if (!fDisableWallet) - RegisterWalletRPCCommands(tableRPC); + RegisterWalletRPCCommands(tableRPC); #endif nConnectTimeout = GetArg("-timeout", DEFAULT_CONNECT_TIMEOUT); @@ -965,9 +963,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) nBytesPerSigOp = GetArg("-bytespersigop", nBytesPerSigOp); #ifdef ENABLE_WALLET - if (!fDisableWallet && !CWallet::ParameterInteraction()) + if (!CWallet::ParameterInteraction()) return false; -#endif // ENABLE_WALLET +#endif fIsBareMultisigStd = GetBoolArg("-permitbaremultisig", DEFAULT_PERMIT_BAREMULTISIG); fAcceptDatacarrier = GetBoolArg("-datacarrier", DEFAULT_ACCEPT_DATACARRIER); @@ -1095,11 +1093,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // ********************************************************* Step 5: verify wallet database integrity #ifdef ENABLE_WALLET - if (!fDisableWallet) { - if (!CWallet::Verify()) - return false; - } // (!fDisableWallet) -#endif // ENABLE_WALLET + if (!CWallet::Verify()) + return false; +#endif // ********************************************************* Step 6: network initialization assert(!g_connman); @@ -1427,17 +1423,11 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // ********************************************************* Step 8: load wallet #ifdef ENABLE_WALLET - if (fDisableWallet) { - pwalletMain = NULL; - LogPrintf("Wallet disabled!\n"); - } else { - CWallet::InitLoadWallet(); - if (!pwalletMain) - return false; - } -#else // ENABLE_WALLET + if (!CWallet::InitLoadWallet()) + return false; +#else LogPrintf("No wallet support compiled in!\n"); -#endif // !ENABLE_WALLET +#endif // ********************************************************* Step 9: data directory maintenance diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 993caad400c94..3eb7e5d9ba885 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2630,6 +2630,9 @@ static const CRPCCommand commands[] = void RegisterWalletRPCCommands(CRPCTable &t) { + if (GetBoolArg("-disablewallet", false)) + return; + for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) t.appendCommand(commands[vcidx].name, &commands[vcidx]); } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 7469fd7519297..27dd4c0a95b47 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -414,6 +414,9 @@ void CWallet::Flush(bool shutdown) bool CWallet::Verify() { + if (GetBoolArg("-disablewallet", false)) + return true; + LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(0, 0, 0)); std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT); @@ -3293,6 +3296,12 @@ std::string CWallet::GetWalletHelpString(bool showDebug) bool CWallet::InitLoadWallet() { + if (GetBoolArg("-disablewallet", false)) { + pwalletMain = NULL; + LogPrintf("Wallet disabled!\n"); + return true; + } + std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT); // needed to restore wallet transaction meta data after -zapwallettxes @@ -3464,6 +3473,9 @@ bool CWallet::InitLoadWallet() bool CWallet::ParameterInteraction() { + if (GetBoolArg("-disablewallet", false)) + return true; + if (GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY) && SoftSetBoolArg("-walletbroadcast", false)) { LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -walletbroadcast=0\n", __func__); } From 04d91f4a8c2ae683c60e94f86dce5f7bd7e716b2 Mon Sep 17 00:00:00 2001 From: unsystemizer Date: Wed, 21 Sep 2016 03:38:38 +0800 Subject: [PATCH 0908/1802] Trivial: Fix ISO URL, capitalization - Changed Debian 8.5.0 ISO CD ROM URL by redirecting from current (which now has only 8.6.0) to a persistent archive link which should not change anytime soon. - Added a link to official Debian checksum verification procedure (which is more verbose and also acts as a backup source of SHA256sum's) - Fix capitalization (iso) --- doc/gitian-building.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/gitian-building.md b/doc/gitian-building.md index 84dce3f082ff9..aaf0b4ae87cf5 100644 --- a/doc/gitian-building.md +++ b/doc/gitian-building.md @@ -95,14 +95,14 @@ After creating the VM, we need to configure it. - Click `Ok` twice to save. -Get the [Debian 8.x net installer](http://cdimage.debian.org/debian-cd/8.5.0/amd64/iso-cd/debian-8.5.0-amd64-netinst.iso) (a more recent minor version should also work, see also [Debian Network installation](https://www.debian.org/CD/netinst/)). -This DVD image can be validated using a SHA256 hashing tool, for example on +Get the [Debian 8.x net installer](http://cdimage.debian.org/mirror/cdimage/archive/8.5.0/amd64/iso-cd/debian-8.5.0-amd64-netinst.iso) (a more recent minor version should also work, see also [Debian Network installation](https://www.debian.org/CD/netinst/)). +This DVD image can be [validated](https://www.debian.org/CD/verify) using a SHA256 hashing tool, for example on Unixy OSes by entering the following in a terminal: echo "ad4e8c27c561ad8248d5ebc1d36eb172f884057bfeb2c22ead823f59fa8c3dff debian-8.5.0-amd64-netinst.iso" | sha256sum -c # (must return OK) -Then start the VM. On the first launch you will be asked for a CD or DVD image. Choose the downloaded iso. +Then start the VM. On the first launch you will be asked for a CD or DVD image. Choose the downloaded ISO. ![](gitian-building/select_startup_disk.png) From 6f933c6bb606d35a9f4fb87a75f7cf66afd4b695 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Wed, 21 Sep 2016 09:48:12 +0000 Subject: [PATCH 0909/1802] Trivial Bugfix: doc/gitian-building.md: Link to release-process needs to be updated Section was renamed in c907f4d56b0a27ecd002a6d7d89a38cfc6d45ee3 --- doc/gitian-building.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/gitian-building.md b/doc/gitian-building.md index 84dce3f082ff9..88bae468477bc 100644 --- a/doc/gitian-building.md +++ b/doc/gitian-building.md @@ -336,7 +336,7 @@ There will be a lot of warnings printed during the build of the image. These can Getting and building the inputs -------------------------------- -Follow the instructions in [doc/release-process.md](release-process.md#fetch-and-build-inputs-first-time-or-when-dependency-versions-change) +Follow the instructions in [doc/release-process.md](release-process.md#fetch-and-create-inputs-first-time-or-when-dependency-versions-change) in the bitcoin repository under 'Fetch and create inputs' to install sources which require manual intervention. Also optionally follow the next step: 'Seed the Gitian sources cache and offline git repositories' which will fetch the remaining files required for building From fa58edbffe929da45004d4406d7d1ffc7d14dc98 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 21 Sep 2016 12:15:18 +0200 Subject: [PATCH 0910/1802] [wallet] Introduce DEFAULT_DISABLE_WALLET --- src/qt/bitcoingui.cpp | 2 +- src/wallet/wallet.cpp | 6 +++--- src/wallet/wallet.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 272df3fdae42c..dcd3f155b9281 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -123,7 +123,7 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *platformStyle, const NetworkStyle *n QString windowTitle = tr(PACKAGE_NAME) + " - "; #ifdef ENABLE_WALLET /* if compiled with wallet support, -disablewallet can still disable the wallet */ - enableWallet = !GetBoolArg("-disablewallet", false); + enableWallet = !GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET); #else enableWallet = false; #endif // ENABLE_WALLET diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 27dd4c0a95b47..abb1ea7e76e86 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -414,7 +414,7 @@ void CWallet::Flush(bool shutdown) bool CWallet::Verify() { - if (GetBoolArg("-disablewallet", false)) + if (GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) return true; LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(0, 0, 0)); @@ -3296,7 +3296,7 @@ std::string CWallet::GetWalletHelpString(bool showDebug) bool CWallet::InitLoadWallet() { - if (GetBoolArg("-disablewallet", false)) { + if (GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) { pwalletMain = NULL; LogPrintf("Wallet disabled!\n"); return true; @@ -3473,7 +3473,7 @@ bool CWallet::InitLoadWallet() bool CWallet::ParameterInteraction() { - if (GetBoolArg("-disablewallet", false)) + if (GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) return true; if (GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY) && SoftSetBoolArg("-walletbroadcast", false)) { diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 584f013204931..f6c658928f64c 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -59,7 +59,7 @@ static const bool DEFAULT_WALLET_RBF = false; //! Largest (in bytes) free transaction we're willing to create static const unsigned int MAX_FREE_TRANSACTION_CREATE_SIZE = 1000; static const bool DEFAULT_WALLETBROADCAST = true; - +static const bool DEFAULT_DISABLE_WALLET = false; //! if set, all keys will be derived by using BIP32 static const bool DEFAULT_USE_HD_WALLET = true; From 6666ca63791788c951109b87b75c24ca99b917cd Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 21 Sep 2016 12:37:00 +0200 Subject: [PATCH 0911/1802] [qt] WalletModel: Expose disablewallet --- src/qt/bitcoingui.cpp | 6 ++---- src/qt/walletmodel.cpp | 5 +++++ src/qt/walletmodel.h | 2 ++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index dcd3f155b9281..8bfd63b31f048 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -77,6 +77,7 @@ const QString BitcoinGUI::DEFAULT_WALLET = "~Default"; BitcoinGUI::BitcoinGUI(const PlatformStyle *platformStyle, const NetworkStyle *networkStyle, QWidget *parent) : QMainWindow(parent), + enableWallet(false), clientModel(0), walletFrame(0), unitDisplayControl(0), @@ -122,10 +123,7 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *platformStyle, const NetworkStyle *n QString windowTitle = tr(PACKAGE_NAME) + " - "; #ifdef ENABLE_WALLET - /* if compiled with wallet support, -disablewallet can still disable the wallet */ - enableWallet = !GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET); -#else - enableWallet = false; + enableWallet = WalletModel::isWalletEnabled(); #endif // ENABLE_WALLET if(enableWallet) { diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 73851e97fc1f1..ad3ba996f1f91 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -684,6 +684,11 @@ bool WalletModel::abandonTransaction(uint256 hash) const return wallet->AbandonTransaction(hash); } +bool WalletModel::isWalletEnabled() +{ + return !GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET); +} + bool WalletModel::hdEnabled() const { return wallet->IsHDEnabled(); diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index a15ecf899b87a..4456215512271 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -203,6 +203,8 @@ class WalletModel : public QObject bool transactionCanBeAbandoned(uint256 hash) const; bool abandonTransaction(uint256 hash) const; + static bool isWalletEnabled(); + bool hdEnabled() const; private: From 381826dfee6258accafac29eef93ad264a90aaf6 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 14 Sep 2016 15:08:34 +0200 Subject: [PATCH 0912/1802] bitcoin-cli: More detailed error reporting Register a evhttp error handler to get a more detailed error message if the HTTP request fails. --- src/bitcoin-cli.cpp | 42 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index a04101d3ed847..68f5d90f5103d 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -116,17 +116,42 @@ static bool AppInitRPC(int argc, char* argv[]) /** Reply structure for request_done to fill in */ struct HTTPReply { + HTTPReply(): status(0), error(-1) {} + int status; + int error; std::string body; }; +const char *http_errorstring(int code) +{ + switch(code) { +#if LIBEVENT_VERSION_NUMBER >= 0x02010300 + case EVREQ_HTTP_TIMEOUT: + return "timeout reached"; + case EVREQ_HTTP_EOF: + return "EOF reached"; + case EVREQ_HTTP_INVALID_HEADER: + return "error while reading header, or invalid header"; + case EVREQ_HTTP_BUFFER_ERROR: + return "error encountered while reading or writing"; + case EVREQ_HTTP_REQUEST_CANCEL: + return "request was canceled"; + case EVREQ_HTTP_DATA_TOO_LONG: + return "response body is larger than allowed"; +#endif + default: + return "unknown"; + } +} + static void http_request_done(struct evhttp_request *req, void *ctx) { HTTPReply *reply = static_cast(ctx); if (req == NULL) { - /* If req is NULL, it means an error occurred while connecting, but - * I'm not sure how to find out which one. We also don't really care. + /* If req is NULL, it means an error occurred while connecting: the + * error code will have been passed to http_error_cb. */ reply->status = 0; return; @@ -145,6 +170,14 @@ static void http_request_done(struct evhttp_request *req, void *ctx) } } +#if LIBEVENT_VERSION_NUMBER >= 0x02010300 +static void http_error_cb(enum evhttp_request_error err, void *ctx) +{ + HTTPReply *reply = static_cast(ctx); + reply->error = err; +} +#endif + UniValue CallRPC(const string& strMethod, const UniValue& params) { std::string host = GetArg("-rpcconnect", DEFAULT_RPCCONNECT); @@ -165,6 +198,9 @@ UniValue CallRPC(const string& strMethod, const UniValue& params) struct evhttp_request *req = evhttp_request_new(http_request_done, (void*)&response); // TODO RAII if (req == NULL) throw runtime_error("create http request failed"); +#if LIBEVENT_VERSION_NUMBER >= 0x02010300 + evhttp_request_set_error_cb(req, http_error_cb); +#endif // Get credentials std::string strRPCUserColonPass; @@ -204,7 +240,7 @@ UniValue CallRPC(const string& strMethod, const UniValue& params) event_base_free(base); if (response.status == 0) - throw CConnectionFailed("couldn't connect to server"); + throw CConnectionFailed(strprintf("couldn't connect to server (%d %s)", response.error, http_errorstring(response.error))); else if (response.status == HTTP_UNAUTHORIZED) throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)"); else if (response.status >= 400 && response.status != HTTP_BAD_REQUEST && response.status != HTTP_NOT_FOUND && response.status != HTTP_INTERNAL_SERVER_ERROR) From fa81d09e8d2cdc6c8d42bb50f71ae53dac3f0912 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 21 Sep 2016 19:21:25 +0200 Subject: [PATCH 0913/1802] [contrib] Delete spendfrom --- contrib/README.md | 8 - contrib/spendfrom/README.md | 35 ----- contrib/spendfrom/setup.py | 12 -- contrib/spendfrom/spendfrom.py | 270 --------------------------------- 4 files changed, 325 deletions(-) delete mode 100644 contrib/spendfrom/README.md delete mode 100644 contrib/spendfrom/setup.py delete mode 100755 contrib/spendfrom/spendfrom.py diff --git a/contrib/README.md b/contrib/README.md index 3e3c83da5f1e6..ab5f57587e0d9 100644 --- a/contrib/README.md +++ b/contrib/README.md @@ -1,11 +1,3 @@ -Wallet Tools ---------------------- - -### [SpendFrom](/contrib/spendfrom) ### - -Use the raw transactions API to send coins received on a particular -address (or addresses). - Repository Tools --------------------- diff --git a/contrib/spendfrom/README.md b/contrib/spendfrom/README.md deleted file mode 100644 index c0a9c9ccf93d3..0000000000000 --- a/contrib/spendfrom/README.md +++ /dev/null @@ -1,35 +0,0 @@ -### SpendFrom ### - -Use the raw transactions API to send coins received on a particular -address (or addresses). - -### Usage: ### -Depends on [jsonrpc](http://json-rpc.org/). - - spendfrom.py --from=FROMADDRESS1[,FROMADDRESS2] --to=TOADDRESS --amount=amount \ - --fee=fee --datadir=/path/to/.bitcoin --testnet --dry_run - -With no arguments, outputs a list of amounts associated with addresses. - -With arguments, sends coins received by the `FROMADDRESS` addresses to the `TOADDRESS`. - -### Notes ### - -- You may explicitly specify how much fee to pay (a fee more than 1% of the amount -will fail, though, to prevent bitcoin-losing accidents). Spendfrom may fail if -it thinks the transaction would never be confirmed (if the amount being sent is -too small, or if the transaction is too many bytes for the fee). - -- If a change output needs to be created, the change will be sent to the last -`FROMADDRESS` (if you specify just one `FROMADDRESS`, change will go back to it). - -- If `--datadir` is not specified, the default datadir is used. - -- The `--dry_run` option will just create and sign the transaction and print -the transaction data (as hexadecimal), instead of broadcasting it. - -- If the transaction is created and broadcast successfully, a transaction id -is printed. - -- If this was a tool for end-users and not programmers, it would have much friendlier -error-handling. diff --git a/contrib/spendfrom/setup.py b/contrib/spendfrom/setup.py deleted file mode 100644 index f80736752ae4f..0000000000000 --- a/contrib/spendfrom/setup.py +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2013 The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. -from distutils.core import setup -setup(name='btcspendfrom', - version='1.0', - description='Command-line utility for bitcoin "coin control"', - author='Gavin Andresen', - author_email='gavin@bitcoinfoundation.org', - requires=['jsonrpc'], - scripts=['spendfrom.py'], - ) diff --git a/contrib/spendfrom/spendfrom.py b/contrib/spendfrom/spendfrom.py deleted file mode 100755 index 086b91b267ef4..0000000000000 --- a/contrib/spendfrom/spendfrom.py +++ /dev/null @@ -1,270 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2013 The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. -# -# Use the raw transactions API to spend bitcoins received on particular addresses, -# and send any change back to that same address. -# -# Example usage: -# spendfrom.py # Lists available funds -# spendfrom.py --from=ADDRESS --to=ADDRESS --amount=11.00 -# -# Assumes it will talk to a bitcoind or Bitcoin-Qt running -# on localhost. -# -# Depends on jsonrpc -# - -from decimal import * -import getpass -import math -import os -import os.path -import platform -import sys -import time -from jsonrpc import ServiceProxy, json - -BASE_FEE=Decimal("0.001") - -def check_json_precision(): - """Make sure json library being used does not lose precision converting BTC values""" - n = Decimal("20000000.00000003") - satoshis = int(json.loads(json.dumps(float(n)))*1.0e8) - if satoshis != 2000000000000003: - raise RuntimeError("JSON encode/decode loses precision") - -def determine_db_dir(): - """Return the default location of the bitcoin data directory""" - if platform.system() == "Darwin": - return os.path.expanduser("~/Library/Application Support/Bitcoin/") - elif platform.system() == "Windows": - return os.path.join(os.environ['APPDATA'], "Bitcoin") - return os.path.expanduser("~/.bitcoin") - -def read_bitcoin_config(dbdir): - """Read the bitcoin.conf file from dbdir, returns dictionary of settings""" - from ConfigParser import SafeConfigParser - - class FakeSecHead(object): - def __init__(self, fp): - self.fp = fp - self.sechead = '[all]\n' - def readline(self): - if self.sechead: - try: return self.sechead - finally: self.sechead = None - else: - s = self.fp.readline() - if s.find('#') != -1: - s = s[0:s.find('#')].strip() +"\n" - return s - - config_parser = SafeConfigParser() - config_parser.readfp(FakeSecHead(open(os.path.join(dbdir, "bitcoin.conf")))) - return dict(config_parser.items("all")) - -def connect_JSON(config): - """Connect to a bitcoin JSON-RPC server""" - testnet = config.get('testnet', '0') - testnet = (int(testnet) > 0) # 0/1 in config file, convert to True/False - if not 'rpcport' in config: - config['rpcport'] = 18332 if testnet else 8332 - connect = "http://%s:%s@127.0.0.1:%s"%(config['rpcuser'], config['rpcpassword'], config['rpcport']) - try: - result = ServiceProxy(connect) - # ServiceProxy is lazy-connect, so send an RPC command mostly to catch connection errors, - # but also make sure the bitcoind we're talking to is/isn't testnet: - if result.getmininginfo()['testnet'] != testnet: - sys.stderr.write("RPC server at "+connect+" testnet setting mismatch\n") - sys.exit(1) - return result - except: - sys.stderr.write("Error connecting to RPC server at "+connect+"\n") - sys.exit(1) - -def unlock_wallet(bitcoind): - info = bitcoind.getinfo() - if 'unlocked_until' not in info: - return True # wallet is not encrypted - t = int(info['unlocked_until']) - if t <= time.time(): - try: - passphrase = getpass.getpass("Wallet is locked; enter passphrase: ") - bitcoind.walletpassphrase(passphrase, 5) - except: - sys.stderr.write("Wrong passphrase\n") - - info = bitcoind.getinfo() - return int(info['unlocked_until']) > time.time() - -def list_available(bitcoind): - address_summary = dict() - - address_to_account = dict() - for info in bitcoind.listreceivedbyaddress(0): - address_to_account[info["address"]] = info["account"] - - unspent = bitcoind.listunspent(0) - for output in unspent: - # listunspent doesn't give addresses, so: - rawtx = bitcoind.getrawtransaction(output['txid'], 1) - vout = rawtx["vout"][output['vout']] - pk = vout["scriptPubKey"] - - # This code only deals with ordinary pay-to-bitcoin-address - # or pay-to-script-hash outputs right now; anything exotic is ignored. - if pk["type"] != "pubkeyhash" and pk["type"] != "scripthash": - continue - - address = pk["addresses"][0] - if address in address_summary: - address_summary[address]["total"] += vout["value"] - address_summary[address]["outputs"].append(output) - else: - address_summary[address] = { - "total" : vout["value"], - "outputs" : [output], - "account" : address_to_account.get(address, "") - } - - return address_summary - -def select_coins(needed, inputs): - # Feel free to improve this, this is good enough for my simple needs: - outputs = [] - have = Decimal("0.0") - n = 0 - while have < needed and n < len(inputs): - outputs.append({ "txid":inputs[n]["txid"], "vout":inputs[n]["vout"]}) - have += inputs[n]["amount"] - n += 1 - return (outputs, have-needed) - -def create_tx(bitcoind, fromaddresses, toaddress, amount, fee): - all_coins = list_available(bitcoind) - - total_available = Decimal("0.0") - needed = amount+fee - potential_inputs = [] - for addr in fromaddresses: - if addr not in all_coins: - continue - potential_inputs.extend(all_coins[addr]["outputs"]) - total_available += all_coins[addr]["total"] - - if total_available < needed: - sys.stderr.write("Error, only %f BTC available, need %f\n"%(total_available, needed)); - sys.exit(1) - - # - # Note: - # Python's json/jsonrpc modules have inconsistent support for Decimal numbers. - # Instead of wrestling with getting json.dumps() (used by jsonrpc) to encode - # Decimals, I'm casting amounts to float before sending them to bitcoind. - # - outputs = { toaddress : float(amount) } - (inputs, change_amount) = select_coins(needed, potential_inputs) - if change_amount > BASE_FEE: # don't bother with zero or tiny change - change_address = fromaddresses[-1] - if change_address in outputs: - outputs[change_address] += float(change_amount) - else: - outputs[change_address] = float(change_amount) - - rawtx = bitcoind.createrawtransaction(inputs, outputs) - signed_rawtx = bitcoind.signrawtransaction(rawtx) - if not signed_rawtx["complete"]: - sys.stderr.write("signrawtransaction failed\n") - sys.exit(1) - txdata = signed_rawtx["hex"] - - return txdata - -def compute_amount_in(bitcoind, txinfo): - result = Decimal("0.0") - for vin in txinfo['vin']: - in_info = bitcoind.getrawtransaction(vin['txid'], 1) - vout = in_info['vout'][vin['vout']] - result = result + vout['value'] - return result - -def compute_amount_out(txinfo): - result = Decimal("0.0") - for vout in txinfo['vout']: - result = result + vout['value'] - return result - -def sanity_test_fee(bitcoind, txdata_hex, max_fee): - class FeeError(RuntimeError): - pass - try: - txinfo = bitcoind.decoderawtransaction(txdata_hex) - total_in = compute_amount_in(bitcoind, txinfo) - total_out = compute_amount_out(txinfo) - if total_in-total_out > max_fee: - raise FeeError("Rejecting transaction, unreasonable fee of "+str(total_in-total_out)) - - tx_size = len(txdata_hex)/2 - kb = tx_size/1000 # integer division rounds down - if kb > 1 and fee < BASE_FEE: - raise FeeError("Rejecting no-fee transaction, larger than 1000 bytes") - if total_in < 0.01 and fee < BASE_FEE: - raise FeeError("Rejecting no-fee, tiny-amount transaction") - # Exercise for the reader: compute transaction priority, and - # warn if this is a very-low-priority transaction - - except FeeError as err: - sys.stderr.write((str(err)+"\n")) - sys.exit(1) - -def main(): - import optparse - - parser = optparse.OptionParser(usage="%prog [options]") - parser.add_option("--from", dest="fromaddresses", default=None, - help="addresses to get bitcoins from") - parser.add_option("--to", dest="to", default=None, - help="address to get send bitcoins to") - parser.add_option("--amount", dest="amount", default=None, - help="amount to send") - parser.add_option("--fee", dest="fee", default="0.0", - help="fee to include") - parser.add_option("--datadir", dest="datadir", default=determine_db_dir(), - help="location of bitcoin.conf file with RPC username/password (default: %default)") - parser.add_option("--testnet", dest="testnet", default=False, action="store_true", - help="Use the test network") - parser.add_option("--dry_run", dest="dry_run", default=False, action="store_true", - help="Don't broadcast the transaction, just create and print the transaction data") - - (options, args) = parser.parse_args() - - check_json_precision() - config = read_bitcoin_config(options.datadir) - if options.testnet: config['testnet'] = True - bitcoind = connect_JSON(config) - - if options.amount is None: - address_summary = list_available(bitcoind) - for address,info in address_summary.iteritems(): - n_transactions = len(info['outputs']) - if n_transactions > 1: - print("%s %.8f %s (%d transactions)"%(address, info['total'], info['account'], n_transactions)) - else: - print("%s %.8f %s"%(address, info['total'], info['account'])) - else: - fee = Decimal(options.fee) - amount = Decimal(options.amount) - while unlock_wallet(bitcoind) == False: - pass # Keep asking for passphrase until they get it right - txdata = create_tx(bitcoind, options.fromaddresses.split(","), options.to, amount, fee) - sanity_test_fee(bitcoind, txdata, amount*Decimal("0.01")) - if options.dry_run: - print(txdata) - else: - txid = bitcoind.sendrawtransaction(txdata) - print(txid) - -if __name__ == '__main__': - main() From ddddaafa4aca2725a18606a38c3341a8637b0c3b Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 21 Sep 2016 21:01:42 +0200 Subject: [PATCH 0914/1802] [rpc] Deprecate getinfo This was replaced by getmininginfo, getnetworkinfo and getwalletinfo --- qa/rpc-tests/p2p-versionbits-warning.py | 13 ++++++++----- qa/rpc-tests/rpcbind_test.py | 4 ++-- src/rpc/misc.cpp | 2 +- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/qa/rpc-tests/p2p-versionbits-warning.py b/qa/rpc-tests/p2p-versionbits-warning.py index 962cafef0b17b..c17bacfc79abc 100755 --- a/qa/rpc-tests/p2p-versionbits-warning.py +++ b/qa/rpc-tests/p2p-versionbits-warning.py @@ -122,8 +122,9 @@ def run_test(self): # Fill rest of period with regular version blocks self.nodes[0].generate(VB_PERIOD - VB_THRESHOLD + 1) # Check that we're not getting any versionbit-related errors in - # getinfo() - assert(not self.vb_pattern.match(self.nodes[0].getinfo()["errors"])) + # get*info() + assert(not self.vb_pattern.match(self.nodes[0].getmininginfo()["errors"])) + assert(not self.vb_pattern.match(self.nodes[0].getnetworkinfo()["warnings"])) # 3. Now build one period of blocks with >= VB_THRESHOLD blocks signaling # some unknown bit @@ -132,8 +133,9 @@ def run_test(self): # Might not get a versionbits-related alert yet, as we should # have gotten a different alert due to more than 51/100 blocks # being of unexpected version. - # Check that getinfo() shows some kind of error. - assert(len(self.nodes[0].getinfo()["errors"]) != 0) + # Check that get*info() shows some kind of error. + assert("Unknown block versions" in self.nodes[0].getmininginfo()["errors"]) + assert("Unknown block versions" in self.nodes[0].getnetworkinfo()["warnings"]) # Mine a period worth of expected blocks so the generic block-version warning # is cleared, and restart the node. This should move the versionbit state @@ -148,7 +150,8 @@ def run_test(self): # Connecting one block should be enough to generate an error. self.nodes[0].generate(1) - assert(len(self.nodes[0].getinfo()["errors"]) != 0) + assert("unknown new rules" in self.nodes[0].getmininginfo()["errors"]) + assert("unknown new rules" in self.nodes[0].getnetworkinfo()["warnings"]) stop_node(self.nodes[0], 0) wait_bitcoinds() self.test_versionbits_in_alert_file() diff --git a/qa/rpc-tests/rpcbind_test.py b/qa/rpc-tests/rpcbind_test.py index 3ac32140ba898..144c2f4cd41d7 100755 --- a/qa/rpc-tests/rpcbind_test.py +++ b/qa/rpc-tests/rpcbind_test.py @@ -44,7 +44,7 @@ def run_bind_test(self, allow_ips, connect_to, addresses, expected): def run_allowip_test(self, allow_ips, rpchost, rpcport): ''' - Start a node with rpcwallow IP, and request getinfo + Start a node with rpcwallow IP, and request getnetworkinfo at a non-localhost IP. ''' base_args = ['-disablewallet', '-nolisten'] + ['-rpcallowip='+x for x in allow_ips] @@ -52,7 +52,7 @@ def run_allowip_test(self, allow_ips, rpchost, rpcport): try: # connect to node through non-loopback interface node = get_rpc_proxy(rpc_url(0, "%s:%d" % (rpchost, rpcport)), 0) - node.getinfo() + node.getnetworkinfo() finally: node = None # make sure connection will be garbage collected and closed stop_nodes(self.nodes) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 5afcf6353c731..f0b7e0a07cffa 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -44,7 +44,7 @@ UniValue getinfo(const UniValue& params, bool fHelp) if (fHelp || params.size() != 0) throw runtime_error( "getinfo\n" - "Returns an object containing various state info.\n" + "\nDEPRECATED. Returns an object containing various state info.\n" "\nResult:\n" "{\n" " \"version\": xxxxx, (numeric) the server version\n" From faf87aff166489f5b6b63f4274ea995e23e1f4cc Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 21 Sep 2016 21:45:15 +0200 Subject: [PATCH 0915/1802] [contrib] delete qt_translations.py follow-up of 1a97b22 #4185 --- contrib/qt_translations.py | 25 ------------------------- 1 file changed, 25 deletions(-) delete mode 100755 contrib/qt_translations.py diff --git a/contrib/qt_translations.py b/contrib/qt_translations.py deleted file mode 100755 index cfdeed41aba26..0000000000000 --- a/contrib/qt_translations.py +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2011 The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. - -# Helpful little script that spits out a comma-separated list of -# language codes for Qt icons that should be included -# in binary bitcoin distributions - -import glob -import os -import re -import sys - -if len(sys.argv) != 3: - sys.exit("Usage: %s $QTDIR/translations $BITCOINDIR/src/qt/locale"%sys.argv[0]) - -d1 = sys.argv[1] -d2 = sys.argv[2] - -l1 = set([ re.search(r'qt_(.*).qm', f).group(1) for f in glob.glob(os.path.join(d1, 'qt_*.qm')) ]) -l2 = set([ re.search(r'bitcoin_(.*).qm', f).group(1) for f in glob.glob(os.path.join(d2, 'bitcoin_*.qm')) ]) - -print ",".join(sorted(l1.intersection(l2))) - From f4dffdd6bffc58377b7505b639f0431244321c32 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Wed, 21 Sep 2016 22:31:23 +0000 Subject: [PATCH 0916/1802] Add MIT license to Makefiles --- Makefile.am | 4 ++++ src/Makefile.am | 4 ++++ src/Makefile.bench.include | 4 ++++ src/Makefile.leveldb.include | 4 ++++ src/Makefile.qt.include | 4 ++++ src/Makefile.qttest.include | 4 ++++ src/Makefile.test.include | 4 ++++ 7 files changed, 28 insertions(+) diff --git a/Makefile.am b/Makefile.am index 2e061c3773580..44fdf9c9fb2da 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,3 +1,7 @@ +# Copyright (c) 2013-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + ACLOCAL_AMFLAGS = -I build-aux/m4 SUBDIRS = src if ENABLE_MAN diff --git a/src/Makefile.am b/src/Makefile.am index ebdddc87f54a2..e7f1d82b8b88a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,3 +1,7 @@ +# Copyright (c) 2013-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + DIST_SUBDIRS = secp256k1 univalue AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS) $(HARDENED_LDFLAGS) diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include index 4067ceb3993e8..8c024a8c4ad81 100644 --- a/src/Makefile.bench.include +++ b/src/Makefile.bench.include @@ -1,3 +1,7 @@ +# Copyright (c) 2015-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + bin_PROGRAMS += bench/bench_bitcoin BENCH_SRCDIR = bench BENCH_BINARY = bench/bench_bitcoin$(EXEEXT) diff --git a/src/Makefile.leveldb.include b/src/Makefile.leveldb.include index 4b3cd6364a29b..d7346aa181d24 100644 --- a/src/Makefile.leveldb.include +++ b/src/Makefile.leveldb.include @@ -1,3 +1,7 @@ +# Copyright (c) 2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + LIBLEVELDB_INT = leveldb/libleveldb.a LIBMEMENV_INT = leveldb/libmemenv.a diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 8947aeaca0b14..35a1f68907277 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -1,3 +1,7 @@ +# Copyright (c) 2013-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + bin_PROGRAMS += qt/bitcoin-qt EXTRA_LIBRARIES += qt/libbitcoinqt.a diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include index 0a7efb5d5b2e5..cb310d5a1b157 100644 --- a/src/Makefile.qttest.include +++ b/src/Makefile.qttest.include @@ -1,3 +1,7 @@ +# Copyright (c) 2013-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + bin_PROGRAMS += qt/test/test_bitcoin-qt TESTS += qt/test/test_bitcoin-qt diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 0748d1a39d232..5ce1bbb8963c1 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -1,3 +1,7 @@ +# Copyright (c) 2013-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + TESTS += test/test_bitcoin bin_PROGRAMS += test/test_bitcoin TEST_SRCDIR = test From fa13c5ce4fe66289b93c3c9665fcd8f0831e0225 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 22 Sep 2016 00:48:02 +0200 Subject: [PATCH 0917/1802] [share] remove qt/protobuf.pri follow up of 35b8af92265ed74de63c3818e5290c27b3f35df2 (#2943) --- share/qt/protobuf.pri | 35 ----------------------------------- 1 file changed, 35 deletions(-) delete mode 100644 share/qt/protobuf.pri diff --git a/share/qt/protobuf.pri b/share/qt/protobuf.pri deleted file mode 100644 index 865fe865550ae..0000000000000 --- a/share/qt/protobuf.pri +++ /dev/null @@ -1,35 +0,0 @@ -# Based on: http://code.google.com/p/ostinato/source/browse/protobuf.pri -# -# Qt qmake integration with Google Protocol Buffers compiler protoc -# -# To compile protocol buffers with qt qmake, specify PROTOS variable and -# include this file -# -# Example: -# PROTOS = a.proto b.proto -# include(protobuf.pri) -# -# Set PROTO_PATH if you need to set the protoc --proto_path search path -# Set PROTOC to the path to the protoc compiler if it is not in your $PATH -# - -isEmpty(PROTO_DIR):PROTO_DIR = . -isEmpty(PROTOC):PROTOC = protoc - -PROTOPATHS = -for(p, PROTO_PATH):PROTOPATHS += --proto_path=$${p} - -protobuf_decl.name = protobuf header -protobuf_decl.input = PROTOS -protobuf_decl.output = $${PROTO_DIR}/${QMAKE_FILE_BASE}.pb.h -protobuf_decl.commands = $${PROTOC} --cpp_out="$${PROTO_DIR}" $${PROTOPATHS} --proto_path=${QMAKE_FILE_IN_PATH} ${QMAKE_FILE_NAME} -protobuf_decl.variable_out = GENERATED_FILES -QMAKE_EXTRA_COMPILERS += protobuf_decl - -protobuf_impl.name = protobuf implementation -protobuf_impl.input = PROTOS -protobuf_impl.output = $${PROTO_DIR}/${QMAKE_FILE_BASE}.pb.cc -protobuf_impl.depends = $${PROTO_DIR}/${QMAKE_FILE_BASE}.pb.h -protobuf_impl.commands = $$escape_expand(\\n) -protobuf_impl.variable_out = GENERATED_SOURCES -QMAKE_EXTRA_COMPILERS += protobuf_impl From 3b4b6dcdd77f3ba76fb0cda6f2c277ec1629d8d3 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Wed, 21 Sep 2016 22:35:21 +0000 Subject: [PATCH 0918/1802] Add MIT license to autogen.sh and share/genbuild.sh --- autogen.sh | 4 ++++ share/genbuild.sh | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/autogen.sh b/autogen.sh index 46e36ff5b216c..27417daf76915 100755 --- a/autogen.sh +++ b/autogen.sh @@ -1,4 +1,8 @@ #!/bin/sh +# Copyright (c) 2013-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + set -e srcdir="$(dirname $0)" cd "$srcdir" diff --git a/share/genbuild.sh b/share/genbuild.sh index 1ef77d706f7aa..eecac4bd00b92 100755 --- a/share/genbuild.sh +++ b/share/genbuild.sh @@ -1,4 +1,8 @@ #!/bin/sh +# Copyright (c) 2012-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + if [ $# -gt 1 ]; then cd "$2" fi From 3f8a5d8f6e95c3c1aa62433abc5edb0c93caae11 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Wed, 21 Sep 2016 22:54:49 +0000 Subject: [PATCH 0919/1802] Trivial: build-aux/m4/l_atomic: Fix typo --- build-aux/m4/l_atomic.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-aux/m4/l_atomic.m4 b/build-aux/m4/l_atomic.m4 index 906724b6405d8..1cb13587a9fb0 100644 --- a/build-aux/m4/l_atomic.m4 +++ b/build-aux/m4/l_atomic.m4 @@ -32,7 +32,7 @@ AC_DEFUN([CHECK_ATOMIC], [ AC_MSG_RESULT([yes]) ],[ AC_MSG_RESULT([no]) - AC_MSG_FAILURE([cannot figure our how to use std::atomic]) + AC_MSG_FAILURE([cannot figure out how to use std::atomic]) ]) ]) From 0c4e6ce88f58c13ed81807e3a5bef28b673aa503 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Wed, 21 Sep 2016 22:54:41 +0000 Subject: [PATCH 0920/1802] Add MIT license to build-aux/m4 scripts --- build-aux/m4/bitcoin_find_bdb48.m4 | 4 ++++ build-aux/m4/bitcoin_qt.m4 | 4 ++++ build-aux/m4/bitcoin_subdir_to_include.m4 | 4 ++++ build-aux/m4/l_atomic.m4 | 6 ++++++ 4 files changed, 18 insertions(+) diff --git a/build-aux/m4/bitcoin_find_bdb48.m4 b/build-aux/m4/bitcoin_find_bdb48.m4 index 2aa493a6af6b4..0c3d49c2bc0af 100644 --- a/build-aux/m4/bitcoin_find_bdb48.m4 +++ b/build-aux/m4/bitcoin_find_bdb48.m4 @@ -1,3 +1,7 @@ +dnl Copyright (c) 2013-2015 The Bitcoin Core developers +dnl Distributed under the MIT software license, see the accompanying +dnl file COPYING or http://www.opensource.org/licenses/mit-license.php. + AC_DEFUN([BITCOIN_FIND_BDB48],[ AC_MSG_CHECKING([for Berkeley DB C++ headers]) BDB_CPPFLAGS= diff --git a/build-aux/m4/bitcoin_qt.m4 b/build-aux/m4/bitcoin_qt.m4 index d26136cbe9a45..509283a0b9cd9 100644 --- a/build-aux/m4/bitcoin_qt.m4 +++ b/build-aux/m4/bitcoin_qt.m4 @@ -1,3 +1,7 @@ +dnl Copyright (c) 2013-2016 The Bitcoin Core developers +dnl Distributed under the MIT software license, see the accompanying +dnl file COPYING or http://www.opensource.org/licenses/mit-license.php. + dnl Helper for cases where a qt dependency is not met. dnl Output: If qt version is auto, set bitcoin_enable_qt to false. Else, exit. AC_DEFUN([BITCOIN_QT_FAIL],[ diff --git a/build-aux/m4/bitcoin_subdir_to_include.m4 b/build-aux/m4/bitcoin_subdir_to_include.m4 index 66f106c7d47b9..7841042ac877b 100644 --- a/build-aux/m4/bitcoin_subdir_to_include.m4 +++ b/build-aux/m4/bitcoin_subdir_to_include.m4 @@ -1,3 +1,7 @@ +dnl Copyright (c) 2013-2014 The Bitcoin Core developers +dnl Distributed under the MIT software license, see the accompanying +dnl file COPYING or http://www.opensource.org/licenses/mit-license.php. + dnl BITCOIN_SUBDIR_TO_INCLUDE([CPPFLAGS-VARIABLE-NAME],[SUBDIRECTORY-NAME],[HEADER-FILE]) dnl SUBDIRECTORY-NAME must end with a path separator AC_DEFUN([BITCOIN_SUBDIR_TO_INCLUDE],[ diff --git a/build-aux/m4/l_atomic.m4 b/build-aux/m4/l_atomic.m4 index 1cb13587a9fb0..75c43f9a92d3d 100644 --- a/build-aux/m4/l_atomic.m4 +++ b/build-aux/m4/l_atomic.m4 @@ -1,3 +1,9 @@ +dnl Copyright (c) 2015 Tim Kosse +dnl Copying and distribution of this file, with or without modification, are +dnl permitted in any medium without royalty provided the copyright notice +dnl and this notice are preserved. This file is offered as-is, without any +dnl warranty. + # Some versions of gcc/libstdc++ require linking with -latomic if # using the C++ atomic library. # From fa427cef130583440779bce9eacfda537c2e6d14 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 22 Sep 2016 12:41:01 +0200 Subject: [PATCH 0921/1802] [qa] pull-tester: Only print output when failed --- qa/pull-tester/rpc-tests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index 9e187b019bc8e..07cd16cba6b8f 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -215,8 +215,8 @@ def runtests(): time_sum += duration print('\n' + BOLD[1] + name + BOLD[0] + ":") - print(stdout) - print('stderr:\n' if not stderr == '' else '', stderr) + print('' if passed else stdout + '\n', end='') + print('' if stderr == '' else 'stderr:\n' + stderr + '\n', end='') results += "%s | %s | %s s\n" % (name.ljust(max_len_name), str(passed).ljust(6), duration) print("Pass: %s%s%s, Duration: %s s\n" % (BOLD[1], passed, BOLD[0], duration)) results += BOLD[1] + "\n%s | %s | %s s (accumulated)" % ("ALL".ljust(max_len_name), str(all_passed).ljust(6), time_sum) + BOLD[0] From 3333bd2d155cc38ed6f1e8cc90ea85817a7b6445 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 22 Sep 2016 12:51:50 +0200 Subject: [PATCH 0922/1802] [test] Remove redundant print in addrman_tests --- src/test/addrman_tests.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp index 5f150e4812af5..5ccaeb57bbe2f 100644 --- a/src/test/addrman_tests.cpp +++ b/src/test/addrman_tests.cpp @@ -257,8 +257,7 @@ BOOST_AUTO_TEST_CASE(addrman_tried_collisions) addrman.Good(CAddress(addr, NODE_NONE)); //Test 15: No collision in tried table yet. - BOOST_TEST_MESSAGE(addrman.size()); - BOOST_CHECK(addrman.size() == i); + BOOST_CHECK_EQUAL(addrman.size(), i); } //Test 16: tried table collision! @@ -543,4 +542,4 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket) // than 64 buckets. BOOST_CHECK(buckets.size() > 64); } -BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file +BOOST_AUTO_TEST_SUITE_END() From fa16991e7bb133ac23cc51e566b5b5f3c8e8b9a4 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 22 Sep 2016 13:07:11 +0200 Subject: [PATCH 0923/1802] [travis] cross-mac: explicitly enable gui --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0b38fd45fe46e..d201cea732d66 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,7 +34,7 @@ env: # No wallet - HOST=x86_64-unknown-linux-gnu PACKAGES="python3" DEP_OPTS="NO_WALLET=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" # Cross-Mac - - HOST=x86_64-apple-darwin11 PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev" BITCOIN_CONFIG="--enable-reduce-exports" OSX_SDK=10.11 GOAL="deploy" + - HOST=x86_64-apple-darwin11 PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev" BITCOIN_CONFIG="--enable-gui --enable-reduce-exports" OSX_SDK=10.11 GOAL="deploy" before_install: - export PATH=$(echo $PATH | tr ':' "\n" | sed '/\/opt\/python/d' | tr "\n" ":" | sed "s|::|:|g") From b5ccded57faff58f6291a0b19bb2db978ab0e8e0 Mon Sep 17 00:00:00 2001 From: instagibbs Date: Wed, 21 Sep 2016 17:34:10 -0400 Subject: [PATCH 0924/1802] Comment on CConnman::nLocalServices meaning --- src/net.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/net.h b/src/net.h index 0173854669ba7..d0b2773623f43 100644 --- a/src/net.h +++ b/src/net.h @@ -677,6 +677,7 @@ class CNode uint64_t nLocalHostNonce; + // Services offered to this peer ServiceFlags nLocalServices; int nMyStartingHeight; public: From 4b6740204d0768279d36544a8141f2867fd98359 Mon Sep 17 00:00:00 2001 From: Andrew Chow Date: Wed, 21 Sep 2016 21:58:18 -0400 Subject: [PATCH 0925/1802] Mandatory copyright agreement All contributions to the repository will agree to use the MIT license --- CONTRIBUTING.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 62ebc7917aad4..c8cb666b4de6d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -198,3 +198,11 @@ Release Policy -------------- The project leader is the release manager for each Bitcoin Core release. + +Copyright +--------- + +By contributing to this repository, you agree to license your work under the +MIT license unless specified otherwise in `contrib/debian/copyright` or at +the top of the file itself. Any work contributed where you are not the original +author must contain its license header with the original author(s) and source. From fd5654cab1e5d317119f747abd245c620e8ba29b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Thu, 22 Sep 2016 16:36:03 +0200 Subject: [PATCH 0926/1802] Check and enable -Wshadow by default. --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index 25b828f18c6fd..c95489d4d726b 100644 --- a/configure.ac +++ b/configure.ac @@ -203,6 +203,7 @@ if test "x$CXXFLAGS_overridden" = "xno"; then AX_CHECK_COMPILE_FLAG([-Wextra],[CXXFLAGS="$CXXFLAGS -Wextra"],,[[$CXXFLAG_WERROR]]) AX_CHECK_COMPILE_FLAG([-Wformat],[CXXFLAGS="$CXXFLAGS -Wformat"],,[[$CXXFLAG_WERROR]]) AX_CHECK_COMPILE_FLAG([-Wformat-security],[CXXFLAGS="$CXXFLAGS -Wformat-security"],,[[$CXXFLAG_WERROR]]) + AX_CHECK_COMPILE_FLAG([-Wshadow],[CXXFLAGS="$CXXFLAGS -Wshadow"],,[[$CXXFLAG_WERROR]]) ## Some compilers (gcc) ignore unknown -Wno-* options, but warn about all ## unknown options if any other warning is produced. Test the -Wfoo case, and From faa91bc335da1c0f20b7a3375b1cfcfdc7b10af5 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 21 Sep 2016 11:44:05 +0200 Subject: [PATCH 0927/1802] CONTRIBUTING: Mention not to open several pulls --- CONTRIBUTING.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 62ebc7917aad4..7e9b4f10df1ea 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -87,6 +87,15 @@ before it will be merged. The basic squashing workflow is shown below. # save and quit git push -f # (force push to GitHub) +If you have problems with squashing (or other workflows with `git`), you can +alternatively enable "Allow edits from maintainers" in the right GitHub +sidebar and ask for help in the pull request. + +Please refrain from creating several pull requests for the same change. +Use the pull request that is already open (or was created earlier) to amend +changes. This preserves the discussion and review that happened earlier for +the respective change set. + The length of time required for peer review is unpredictable and will vary from pull request to pull request. From 3f58a283ee108595cf3cc29aee9a4db2c1fcecd3 Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Wed, 21 Sep 2016 22:10:59 -0500 Subject: [PATCH 0928/1802] [Doc] Add missing autogen to example builds --- doc/build-windows.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/build-windows.md b/doc/build-windows.md index 129774491b2ff..ec5f26c88b0df 100644 --- a/doc/build-windows.md +++ b/doc/build-windows.md @@ -27,6 +27,7 @@ To build executables for Windows 32-bit: cd depends make HOST=i686-w64-mingw32 -j4 cd .. + ./autogen.sh # not required when building from tarball ./configure --prefix=`pwd`/depends/i686-w64-mingw32 make @@ -35,6 +36,7 @@ To build executables for Windows 64-bit: cd depends make HOST=x86_64-w64-mingw32 -j4 cd .. + ./autogen.sh # not required when building from tarball ./configure --prefix=`pwd`/depends/x86_64-w64-mingw32 make From c72c5b1e3bd42e84465677e94aa83316ff3d9a14 Mon Sep 17 00:00:00 2001 From: Johnson Lau Date: Fri, 23 Sep 2016 13:06:45 +0800 Subject: [PATCH 0929/1802] Make non-minimal OP_IF/NOTIF argument non-standard for P2WSH --- src/policy/policy.h | 1 + src/script/interpreter.cpp | 6 +++ src/script/interpreter.h | 4 ++ src/script/script_error.cpp | 2 + src/script/script_error.h | 3 +- src/test/data/script_tests.json | 85 ++++++++++++++++++++++++++++++++- src/test/script_tests.cpp | 1 + src/test/transaction_tests.cpp | 1 + 8 files changed, 101 insertions(+), 2 deletions(-) diff --git a/src/policy/policy.h b/src/policy/policy.h index 6bf5ca0ee5567..458ec4a0cb4aa 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -42,6 +42,7 @@ static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY SCRIPT_VERIFY_NULLDUMMY | SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS | SCRIPT_VERIFY_CLEANSTACK | + SCRIPT_VERIFY_MINIMALIF | SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY | SCRIPT_VERIFY_CHECKSEQUENCEVERIFY | SCRIPT_VERIFY_LOW_S | diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 47ea261e31040..fd356fed0ab43 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -428,6 +428,12 @@ bool EvalScript(vector >& stack, const CScript& script, un if (stack.size() < 1) return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL); valtype& vch = stacktop(-1); + if (sigversion == SIGVERSION_WITNESS_V0 && (flags & SCRIPT_VERIFY_MINIMALIF)) { + if (vch.size() > 1) + return set_error(serror, SCRIPT_ERR_MINIMALIF); + if (vch.size() == 1 && vch[0] != 1) + return set_error(serror, SCRIPT_ERR_MINIMALIF); + } fValue = CastToBool(vch); if (opcode == OP_NOTIF) fValue = !fValue; diff --git a/src/script/interpreter.h b/src/script/interpreter.h index e5d7865cd3de6..2ce4b23e54f62 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -94,6 +94,10 @@ enum // Making v1-v16 witness program non-standard // SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM = (1U << 12), + + // Segwit script only: Require the argument of OP_IF/NOTIF to be exactly 0x01 or empty vector + // + SCRIPT_VERIFY_MINIMALIF = (1U << 13), }; bool CheckSignatureEncoding(const std::vector &vchSig, unsigned int flags, ScriptError* serror); diff --git a/src/script/script_error.cpp b/src/script/script_error.cpp index cef807edcf475..9969c232fc340 100644 --- a/src/script/script_error.cpp +++ b/src/script/script_error.cpp @@ -63,6 +63,8 @@ const char* ScriptErrorString(const ScriptError serror) return "Non-canonical signature: S value is unnecessarily high"; case SCRIPT_ERR_SIG_NULLDUMMY: return "Dummy CHECKMULTISIG argument must be zero"; + case SCRIPT_ERR_MINIMALIF: + return "OP_IF/NOTIF argument must be minimal"; case SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS: return "NOPx reserved for soft-fork upgrades"; case SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM: diff --git a/src/script/script_error.h b/src/script/script_error.h index 09dc6945adb45..6d34d37925bcf 100644 --- a/src/script/script_error.h +++ b/src/script/script_error.h @@ -39,7 +39,7 @@ typedef enum ScriptError_t SCRIPT_ERR_NEGATIVE_LOCKTIME, SCRIPT_ERR_UNSATISFIED_LOCKTIME, - /* BIP62 */ + /* Malleability */ SCRIPT_ERR_SIG_HASHTYPE, SCRIPT_ERR_SIG_DER, SCRIPT_ERR_MINIMALDATA, @@ -48,6 +48,7 @@ typedef enum ScriptError_t SCRIPT_ERR_SIG_NULLDUMMY, SCRIPT_ERR_PUBKEYTYPE, SCRIPT_ERR_CLEANSTACK, + SCRIPT_ERR_MINIMALIF, /* softfork safeness */ SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS, diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json index fcd5457386dda..d456a8beffd67 100644 --- a/src/test/data/script_tests.json +++ b/src/test/data/script_tests.json @@ -2125,5 +2125,88 @@ ["0", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME", "CSV fails if stack top bit 1 << 31 is set and the tx version < 2"], ["4294967296", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME", "CSV fails if stack top bit 1 << 31 is not set, and tx version < 2"], -["The End"] + +["MINIMALIF tests"], +["MINIMALIF is not applied to non-segwit scripts"], +["1", "IF 1 ENDIF", "P2SH,WITNESS,MINIMALIF", "OK"], +["2", "IF 1 ENDIF", "P2SH,WITNESS,MINIMALIF", "OK"], +["0x02 0x0100", "IF 1 ENDIF", "P2SH,WITNESS,MINIMALIF", "OK"], +["0", "IF 1 ENDIF", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"], +["0x01 0x00", "IF 1 ENDIF", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"], +["1", "NOTIF 1 ENDIF", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"], +["2", "NOTIF 1 ENDIF", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"], +["0x02 0x0100", "NOTIF 1 ENDIF", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"], +["0", "NOTIF 1 ENDIF", "P2SH,WITNESS,MINIMALIF", "OK"], +["0x01 0x00", "NOTIF 1 ENDIF", "P2SH,WITNESS,MINIMALIF", "OK"], +["Normal P2SH IF 1 ENDIF"], +["1 0x03 0x635168", "HASH160 0x14 0xe7309652a8e3f600f06f5d8d52d6df03d2176cc3 EQUAL", "P2SH,WITNESS,MINIMALIF", "OK"], +["2 0x03 0x635168", "HASH160 0x14 0xe7309652a8e3f600f06f5d8d52d6df03d2176cc3 EQUAL", "P2SH,WITNESS,MINIMALIF", "OK"], +["0x02 0x0100 0x03 0x635168", "HASH160 0x14 0xe7309652a8e3f600f06f5d8d52d6df03d2176cc3 EQUAL", "P2SH,WITNESS,MINIMALIF", "OK"], +["0 0x03 0x635168", "HASH160 0x14 0xe7309652a8e3f600f06f5d8d52d6df03d2176cc3 EQUAL", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"], +["0x01 0x00 0x03 0x635168", "HASH160 0x14 0xe7309652a8e3f600f06f5d8d52d6df03d2176cc3 EQUAL", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"], +["0x03 0x635168", "HASH160 0x14 0xe7309652a8e3f600f06f5d8d52d6df03d2176cc3 EQUAL", "P2SH,WITNESS,MINIMALIF", "UNBALANCED_CONDITIONAL"], +["Normal P2SH NOTIF 1 ENDIF"], +["1 0x03 0x645168", "HASH160 0x14 0x0c3f8fe3d6ca266e76311ecda544c67d15fdd5b0 EQUAL", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"], +["2 0x03 0x645168", "HASH160 0x14 0x0c3f8fe3d6ca266e76311ecda544c67d15fdd5b0 EQUAL", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"], +["0x02 0x0100 0x03 0x645168", "HASH160 0x14 0x0c3f8fe3d6ca266e76311ecda544c67d15fdd5b0 EQUAL", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"], +["0 0x03 0x645168", "HASH160 0x14 0x0c3f8fe3d6ca266e76311ecda544c67d15fdd5b0 EQUAL", "P2SH,WITNESS,MINIMALIF", "OK"], +["0x01 0x00 0x03 0x645168", "HASH160 0x14 0x0c3f8fe3d6ca266e76311ecda544c67d15fdd5b0 EQUAL", "P2SH,WITNESS,MINIMALIF", "OK"], +["0x03 0x645168", "HASH160 0x14 0x0c3f8fe3d6ca266e76311ecda544c67d15fdd5b0 EQUAL", "P2SH,WITNESS,MINIMALIF", "UNBALANCED_CONDITIONAL"], +["P2WSH IF 1 ENDIF"], +[["01", "635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS", "OK"], +[["02", "635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS", "OK"], +[["0100", "635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS", "OK"], +[["", "635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS", "EVAL_FALSE"], +[["00", "635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS", "EVAL_FALSE"], +[["01", "635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS,MINIMALIF", "OK"], +[["02", "635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"], +[["0100", "635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"], +[["", "635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"], +[["00", "635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"], +[["635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS", "UNBALANCED_CONDITIONAL"], +[["635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS,MINIMALIF", "UNBALANCED_CONDITIONAL"], +["P2WSH NOTIF 1 ENDIF"], +[["01", "645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS", "EVAL_FALSE"], +[["02", "645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS", "EVAL_FALSE"], +[["0100", "645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS", "EVAL_FALSE"], +[["", "645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS", "OK"], +[["00", "645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS", "OK"], +[["01", "645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"], +[["02", "645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"], +[["0100", "645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"], +[["", "645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS,MINIMALIF", "OK"], +[["00", "645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"], +[["645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS", "UNBALANCED_CONDITIONAL"], +[["645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS,MINIMALIF", "UNBALANCED_CONDITIONAL"], + + + +["P2SH-P2WSH IF 1 ENDIF"], +[["01", "635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS", "OK"], +[["02", "635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS", "OK"], +[["0100", "635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS", "OK"], +[["", "635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS", "EVAL_FALSE"], +[["00", "635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS", "EVAL_FALSE"], +[["01", "635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS,MINIMALIF", "OK"], +[["02", "635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"], +[["0100", "635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"], +[["", "635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"], +[["00", "635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"], +[["635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS", "UNBALANCED_CONDITIONAL"], +[["635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS,MINIMALIF", "UNBALANCED_CONDITIONAL"], +["P2SH-P2WSH NOTIF 1 ENDIF"], +[["01", "645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS", "EVAL_FALSE"], +[["02", "645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS", "EVAL_FALSE"], +[["0100", "645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS", "EVAL_FALSE"], +[["", "645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS", "OK"], +[["00", "645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS", "OK"], +[["01", "645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"], +[["02", "645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"], +[["0100", "645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"], +[["", "645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS,MINIMALIF", "OK"], +[["00", "645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"], +[["645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS", "UNBALANCED_CONDITIONAL"], +[["645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS,MINIMALIF", "UNBALANCED_CONDITIONAL"], + + ["The End"] ] diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 5a9aaf9bc0738..36c591d616f92 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -89,6 +89,7 @@ static ScriptErrorDesc script_errors[]={ {SCRIPT_ERR_SIG_NULLDUMMY, "SIG_NULLDUMMY"}, {SCRIPT_ERR_PUBKEYTYPE, "PUBKEYTYPE"}, {SCRIPT_ERR_CLEANSTACK, "CLEANSTACK"}, + {SCRIPT_ERR_MINIMALIF, "MINIMALIF"}, {SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS, "DISCOURAGE_UPGRADABLE_NOPS"}, {SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM, "DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"}, {SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH, "WITNESS_PROGRAM_WRONG_LENGTH"}, diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index b5af400bc54b5..165dfd9a3e06b 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -50,6 +50,7 @@ static std::map mapFlagNames = boost::assign::map_list_of (string("NULLDUMMY"), (unsigned int)SCRIPT_VERIFY_NULLDUMMY) (string("DISCOURAGE_UPGRADABLE_NOPS"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) (string("CLEANSTACK"), (unsigned int)SCRIPT_VERIFY_CLEANSTACK) + (string("MINIMALIF"), (unsigned int)SCRIPT_VERIFY_MINIMALIF) (string("CHECKLOCKTIMEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY) (string("CHECKSEQUENCEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKSEQUENCEVERIFY) (string("WITNESS"), (unsigned int)SCRIPT_VERIFY_WITNESS) From f8393504205089112cdec27ac1829282b76b94a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Fri, 9 Sep 2016 13:43:29 +0200 Subject: [PATCH 0930/1802] Do not shadow in src/qt --- src/qt/addressbookpage.cpp | 16 +++++------ src/qt/addresstablemodel.cpp | 12 ++++---- src/qt/askpassphrasedialog.cpp | 8 +++--- src/qt/bitcoingui.cpp | 44 ++++++++++++++-------------- src/qt/clientmodel.cpp | 4 +-- src/qt/coincontroldialog.cpp | 12 ++++---- src/qt/csvmodelwriter.cpp | 8 +++--- src/qt/editaddressdialog.cpp | 18 ++++++------ src/qt/guiutil.cpp | 4 +-- src/qt/intro.cpp | 4 +-- src/qt/networkstyle.cpp | 6 ++-- src/qt/notificator.cpp | 12 ++++---- src/qt/optionsdialog.cpp | 12 ++++---- src/qt/overviewpage.cpp | 4 +-- src/qt/paymentserver.cpp | 4 +-- src/qt/platformstyle.cpp | 10 +++---- src/qt/qvalidatedlineedit.cpp | 8 +++--- src/qt/qvaluecombobox.cpp | 4 +-- src/qt/receivecoinsdialog.cpp | 26 ++++++++--------- src/qt/receiverequestdialog.cpp | 12 ++++---- src/qt/rpcconsole.cpp | 8 +++--- src/qt/sendcoinsdialog.cpp | 46 +++++++++++++++--------------- src/qt/sendcoinsentry.cpp | 12 ++++---- src/qt/signverifymessagedialog.cpp | 8 +++--- src/qt/transactionfilterproxy.cpp | 8 +++--- src/qt/transactionrecord.h | 12 ++++---- src/qt/transactiontablemodel.cpp | 18 ++++++------ src/qt/transactionview.cpp | 16 +++++------ src/qt/walletframe.cpp | 8 +++--- src/qt/walletmodel.cpp | 12 ++++---- src/qt/walletmodel.h | 8 +++--- src/qt/walletmodeltransaction.cpp | 4 +-- src/qt/walletview.cpp | 44 ++++++++++++++-------------- 33 files changed, 216 insertions(+), 216 deletions(-) diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp index 135f15ffa85ad..58cf4dede046e 100644 --- a/src/qt/addressbookpage.cpp +++ b/src/qt/addressbookpage.cpp @@ -21,12 +21,12 @@ #include #include -AddressBookPage::AddressBookPage(const PlatformStyle *platformStyle, Mode mode, Tabs tab, QWidget *parent) : +AddressBookPage::AddressBookPage(const PlatformStyle *platformStyle, Mode _mode, Tabs _tab, QWidget *parent) : QDialog(parent), ui(new Ui::AddressBookPage), model(0), - mode(mode), - tab(tab) + mode(_mode), + tab(_tab) { ui->setupUi(this); @@ -107,14 +107,14 @@ AddressBookPage::~AddressBookPage() delete ui; } -void AddressBookPage::setModel(AddressTableModel *model) +void AddressBookPage::setModel(AddressTableModel *_model) { - this->model = model; - if(!model) + this->model = _model; + if(!_model) return; proxyModel = new QSortFilterProxyModel(this); - proxyModel->setSourceModel(model); + proxyModel->setSourceModel(_model); proxyModel->setDynamicSortFilter(true); proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); @@ -147,7 +147,7 @@ void AddressBookPage::setModel(AddressTableModel *model) this, SLOT(selectionChanged())); // Select row for newly created address - connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(selectNewAddress(QModelIndex,int,int))); + connect(_model, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(selectNewAddress(QModelIndex,int,int))); selectionChanged(); } diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp index 71ed3618e415e..830c9cdf19bb7 100644 --- a/src/qt/addresstablemodel.cpp +++ b/src/qt/addresstablemodel.cpp @@ -31,8 +31,8 @@ struct AddressTableEntry QString address; AddressTableEntry() {} - AddressTableEntry(Type type, const QString &label, const QString &address): - type(type), label(label), address(address) {} + AddressTableEntry(Type _type, const QString &_label, const QString &_address): + type(_type), label(_label), address(_address) {} }; struct AddressTableEntryLessThan @@ -73,8 +73,8 @@ class AddressTablePriv QList cachedAddressTable; AddressTableModel *parent; - AddressTablePriv(CWallet *wallet, AddressTableModel *parent): - wallet(wallet), parent(parent) {} + AddressTablePriv(CWallet *_wallet, AddressTableModel *_parent): + wallet(_wallet), parent(_parent) {} void refreshAddressTable() { @@ -164,8 +164,8 @@ class AddressTablePriv } }; -AddressTableModel::AddressTableModel(CWallet *wallet, WalletModel *parent) : - QAbstractTableModel(parent),walletModel(parent),wallet(wallet),priv(0) +AddressTableModel::AddressTableModel(CWallet *_wallet, WalletModel *parent) : + QAbstractTableModel(parent),walletModel(parent),wallet(_wallet),priv(0) { columns << tr("Label") << tr("Address"); priv = new AddressTablePriv(wallet, this); diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp index e8aa79679c04a..129ea1efa4f04 100644 --- a/src/qt/askpassphrasedialog.cpp +++ b/src/qt/askpassphrasedialog.cpp @@ -18,10 +18,10 @@ #include #include -AskPassphraseDialog::AskPassphraseDialog(Mode mode, QWidget *parent) : +AskPassphraseDialog::AskPassphraseDialog(Mode _mode, QWidget *parent) : QDialog(parent), ui(new Ui::AskPassphraseDialog), - mode(mode), + mode(_mode), model(0), fCapsLock(false) { @@ -81,9 +81,9 @@ AskPassphraseDialog::~AskPassphraseDialog() delete ui; } -void AskPassphraseDialog::setModel(WalletModel *model) +void AskPassphraseDialog::setModel(WalletModel *_model) { - this->model = model; + this->model = _model; } void AskPassphraseDialog::accept() diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 8bfd63b31f048..16d7778a272c5 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -75,7 +75,7 @@ const std::string BitcoinGUI::DEFAULT_UIPLATFORM = const QString BitcoinGUI::DEFAULT_WALLET = "~Default"; -BitcoinGUI::BitcoinGUI(const PlatformStyle *platformStyle, const NetworkStyle *networkStyle, QWidget *parent) : +BitcoinGUI::BitcoinGUI(const PlatformStyle *_platformStyle, const NetworkStyle *networkStyle, QWidget *parent) : QMainWindow(parent), enableWallet(false), clientModel(0), @@ -117,7 +117,7 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *platformStyle, const NetworkStyle *n helpMessageDialog(0), prevBlocks(0), spinnerFrame(0), - platformStyle(platformStyle) + platformStyle(_platformStyle) { GUIUtil::restoreWindowGeometry("nWindow", QSize(850, 550), this); @@ -146,13 +146,13 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *platformStyle, const NetworkStyle *n setUnifiedTitleAndToolBarOnMac(true); #endif - rpcConsole = new RPCConsole(platformStyle, 0); + rpcConsole = new RPCConsole(_platformStyle, 0); helpMessageDialog = new HelpMessageDialog(this, false); #ifdef ENABLE_WALLET if(enableWallet) { /** Create wallet frame and make it the central widget */ - walletFrame = new WalletFrame(platformStyle, this); + walletFrame = new WalletFrame(_platformStyle, this); setCentralWidget(walletFrame); } else #endif // ENABLE_WALLET @@ -449,38 +449,38 @@ void BitcoinGUI::createToolBars() } } -void BitcoinGUI::setClientModel(ClientModel *clientModel) +void BitcoinGUI::setClientModel(ClientModel *_clientModel) { - this->clientModel = clientModel; - if(clientModel) + this->clientModel = _clientModel; + if(_clientModel) { // Create system tray menu (or setup the dock menu) that late to prevent users from calling actions, // while the client has not yet fully loaded createTrayIconMenu(); // Keep up to date with client - setNumConnections(clientModel->getNumConnections()); - connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int))); + setNumConnections(_clientModel->getNumConnections()); + connect(_clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int))); - setNumBlocks(clientModel->getNumBlocks(), clientModel->getLastBlockDate(), clientModel->getVerificationProgress(NULL), false); - connect(clientModel, SIGNAL(numBlocksChanged(int,QDateTime,double,bool)), this, SLOT(setNumBlocks(int,QDateTime,double,bool))); + setNumBlocks(_clientModel->getNumBlocks(), _clientModel->getLastBlockDate(), _clientModel->getVerificationProgress(NULL), false); + connect(_clientModel, SIGNAL(numBlocksChanged(int,QDateTime,double,bool)), this, SLOT(setNumBlocks(int,QDateTime,double,bool))); // Receive and report messages from client model - connect(clientModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int))); + connect(_clientModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int))); // Show progress dialog - connect(clientModel, SIGNAL(showProgress(QString,int)), this, SLOT(showProgress(QString,int))); + connect(_clientModel, SIGNAL(showProgress(QString,int)), this, SLOT(showProgress(QString,int))); - rpcConsole->setClientModel(clientModel); + rpcConsole->setClientModel(_clientModel); #ifdef ENABLE_WALLET if(walletFrame) { - walletFrame->setClientModel(clientModel); + walletFrame->setClientModel(_clientModel); } #endif // ENABLE_WALLET - unitDisplayControl->setOptionsModel(clientModel->getOptionsModel()); + unitDisplayControl->setOptionsModel(_clientModel->getOptionsModel()); - OptionsModel* optionsModel = clientModel->getOptionsModel(); + OptionsModel* optionsModel = _clientModel->getOptionsModel(); if(optionsModel) { // be aware of the tray icon disable state change reported by the OptionsModel object. @@ -1168,17 +1168,17 @@ void UnitDisplayStatusBarControl::createContextMenu() } /** Lets the control know about the Options Model (and its signals) */ -void UnitDisplayStatusBarControl::setOptionsModel(OptionsModel *optionsModel) +void UnitDisplayStatusBarControl::setOptionsModel(OptionsModel *_optionsModel) { - if (optionsModel) + if (_optionsModel) { - this->optionsModel = optionsModel; + this->optionsModel = _optionsModel; // be aware of a display unit change reported by the OptionsModel object. - connect(optionsModel,SIGNAL(displayUnitChanged(int)),this,SLOT(updateDisplayUnit(int))); + connect(_optionsModel,SIGNAL(displayUnitChanged(int)),this,SLOT(updateDisplayUnit(int))); // initialize the display units label with the current value in the model. - updateDisplayUnit(optionsModel->getDisplayUnit()); + updateDisplayUnit(_optionsModel->getDisplayUnit()); } } diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 83c78850e2a54..62a70bacd93c7 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -27,9 +27,9 @@ static const int64_t nClientStartupTime = GetTime(); static int64_t nLastHeaderTipUpdateNotification = 0; static int64_t nLastBlockTipUpdateNotification = 0; -ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) : +ClientModel::ClientModel(OptionsModel *_optionsModel, QObject *parent) : QObject(parent), - optionsModel(optionsModel), + optionsModel(_optionsModel), peerTableModel(0), banTableModel(0), pollTimer(0) diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index f53242100cac7..86fd4ebd656f1 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -35,11 +35,11 @@ QList CoinControlDialog::payAmounts; CCoinControl* CoinControlDialog::coinControl = new CCoinControl(); bool CoinControlDialog::fSubtractFeeFromAmount = false; -CoinControlDialog::CoinControlDialog(const PlatformStyle *platformStyle, QWidget *parent) : +CoinControlDialog::CoinControlDialog(const PlatformStyle *_platformStyle, QWidget *parent) : QDialog(parent), ui(new Ui::CoinControlDialog), model(0), - platformStyle(platformStyle) + platformStyle(_platformStyle) { ui->setupUi(this); @@ -152,15 +152,15 @@ CoinControlDialog::~CoinControlDialog() delete ui; } -void CoinControlDialog::setModel(WalletModel *model) +void CoinControlDialog::setModel(WalletModel *_model) { - this->model = model; + this->model = _model; - if(model && model->getOptionsModel() && model->getAddressTableModel()) + if(_model && _model->getOptionsModel() && _model->getAddressTableModel()) { updateView(); updateLabelLocked(); - CoinControlDialog::updateLabels(model, this); + CoinControlDialog::updateLabels(_model, this); } } diff --git a/src/qt/csvmodelwriter.cpp b/src/qt/csvmodelwriter.cpp index 8a1a49bb06c5c..f424e6cd98243 100644 --- a/src/qt/csvmodelwriter.cpp +++ b/src/qt/csvmodelwriter.cpp @@ -8,15 +8,15 @@ #include #include -CSVModelWriter::CSVModelWriter(const QString &filename, QObject *parent) : +CSVModelWriter::CSVModelWriter(const QString &_filename, QObject *parent) : QObject(parent), - filename(filename), model(0) + filename(_filename), model(0) { } -void CSVModelWriter::setModel(const QAbstractItemModel *model) +void CSVModelWriter::setModel(const QAbstractItemModel *_model) { - this->model = model; + this->model = _model; } void CSVModelWriter::addColumn(const QString &title, int column, int role) diff --git a/src/qt/editaddressdialog.cpp b/src/qt/editaddressdialog.cpp index 5f45031e9eb54..a9ffe016fd91d 100644 --- a/src/qt/editaddressdialog.cpp +++ b/src/qt/editaddressdialog.cpp @@ -11,11 +11,11 @@ #include #include -EditAddressDialog::EditAddressDialog(Mode mode, QWidget *parent) : +EditAddressDialog::EditAddressDialog(Mode _mode, QWidget *parent) : QDialog(parent), ui(new Ui::EditAddressDialog), mapper(0), - mode(mode), + mode(_mode), model(0) { ui->setupUi(this); @@ -49,13 +49,13 @@ EditAddressDialog::~EditAddressDialog() delete ui; } -void EditAddressDialog::setModel(AddressTableModel *model) +void EditAddressDialog::setModel(AddressTableModel *_model) { - this->model = model; - if(!model) + this->model = _model; + if(!_model) return; - mapper->setModel(model); + mapper->setModel(_model); mapper->addMapping(ui->labelEdit, AddressTableModel::Label); mapper->addMapping(ui->addressEdit, AddressTableModel::Address); } @@ -137,8 +137,8 @@ QString EditAddressDialog::getAddress() const return address; } -void EditAddressDialog::setAddress(const QString &address) +void EditAddressDialog::setAddress(const QString &_address) { - this->address = address; - ui->addressEdit->setText(address); + this->address = _address; + ui->addressEdit->setText(_address); } diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 444e35de8af5c..277a9a1d10124 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -462,9 +462,9 @@ void SubstituteFonts(const QString& language) #endif } -ToolTipToRichTextFilter::ToolTipToRichTextFilter(int size_threshold, QObject *parent) : +ToolTipToRichTextFilter::ToolTipToRichTextFilter(int _size_threshold, QObject *parent) : QObject(parent), - size_threshold(size_threshold) + size_threshold(_size_threshold) { } diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index 1a241ae0f0e67..5a336b105ec7b 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -63,9 +63,9 @@ public Q_SLOTS: #include "intro.moc" -FreespaceChecker::FreespaceChecker(Intro *intro) +FreespaceChecker::FreespaceChecker(Intro *_intro) { - this->intro = intro; + this->intro = _intro; } void FreespaceChecker::check() diff --git a/src/qt/networkstyle.cpp b/src/qt/networkstyle.cpp index 5f31f49372724..acbfee08684d1 100644 --- a/src/qt/networkstyle.cpp +++ b/src/qt/networkstyle.cpp @@ -22,9 +22,9 @@ static const struct { static const unsigned network_styles_count = sizeof(network_styles)/sizeof(*network_styles); // titleAddText needs to be const char* for tr() -NetworkStyle::NetworkStyle(const QString &appName, const int iconColorHueShift, const int iconColorSaturationReduction, const char *titleAddText): - appName(appName), - titleAddText(qApp->translate("SplashScreen", titleAddText)) +NetworkStyle::NetworkStyle(const QString &_appName, const int iconColorHueShift, const int iconColorSaturationReduction, const char *_titleAddText): + appName(_appName), + titleAddText(qApp->translate("SplashScreen", _titleAddText)) { // load pixmap QPixmap pixmap(":/icons/bitcoin"); diff --git a/src/qt/notificator.cpp b/src/qt/notificator.cpp index a45afde5660da..8277e20c909ba 100644 --- a/src/qt/notificator.cpp +++ b/src/qt/notificator.cpp @@ -33,17 +33,17 @@ const int FREEDESKTOP_NOTIFICATION_ICON_SIZE = 128; #endif -Notificator::Notificator(const QString &programName, QSystemTrayIcon *trayicon, QWidget *parent) : - QObject(parent), - parent(parent), - programName(programName), +Notificator::Notificator(const QString &_programName, QSystemTrayIcon *_trayIcon, QWidget *_parent) : + QObject(_parent), + parent(_parent), + programName(_programName), mode(None), - trayIcon(trayicon) + trayIcon(_trayIcon) #ifdef USE_DBUS ,interface(0) #endif { - if(trayicon && trayicon->supportsMessages()) + if(_trayIcon && _trayIcon->supportsMessages()) { mode = QSystemTray; } diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index f73bb87064088..588059d0c577a 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -135,22 +135,22 @@ OptionsDialog::~OptionsDialog() delete ui; } -void OptionsDialog::setModel(OptionsModel *model) +void OptionsDialog::setModel(OptionsModel *_model) { - this->model = model; + this->model = _model; - if(model) + if(_model) { /* check if client restart is needed and show persistent message */ - if (model->isRestartRequired()) + if (_model->isRestartRequired()) showRestartWarning(true); - QString strLabel = model->getOverriddenByCommandLine(); + QString strLabel = _model->getOverriddenByCommandLine(); if (strLabel.isEmpty()) strLabel = tr("none"); ui->overriddenByCommandLineLabel->setText(strLabel); - mapper->setModel(model); + mapper->setModel(_model); setMapper(); mapper->toFirst(); diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 6a0404cbf702f..788d917bcc0df 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -25,9 +25,9 @@ class TxViewDelegate : public QAbstractItemDelegate { Q_OBJECT public: - TxViewDelegate(const PlatformStyle *platformStyle): + TxViewDelegate(const PlatformStyle *_platformStyle): QAbstractItemDelegate(), unit(BitcoinUnits::BTC), - platformStyle(platformStyle) + platformStyle(_platformStyle) { } diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index c80aebb0098d8..9f23e77a13700 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -749,9 +749,9 @@ void PaymentServer::reportSslErrors(QNetworkReply* reply, const QList Q_EMIT message(tr("Network request error"), errString, CClientUIInterface::MSG_ERROR); } -void PaymentServer::setOptionsModel(OptionsModel *optionsModel) +void PaymentServer::setOptionsModel(OptionsModel *_optionsModel) { - this->optionsModel = optionsModel; + this->optionsModel = _optionsModel; } void PaymentServer::handlePaymentACK(const QString& paymentACKMsg) diff --git a/src/qt/platformstyle.cpp b/src/qt/platformstyle.cpp index 11cbc7a47c06f..e4438cc43d83c 100644 --- a/src/qt/platformstyle.cpp +++ b/src/qt/platformstyle.cpp @@ -73,11 +73,11 @@ QIcon ColorizeIcon(const QString& filename, const QColor& colorbase) } -PlatformStyle::PlatformStyle(const QString &name, bool imagesOnButtons, bool colorizeIcons, bool useExtraSpacing): - name(name), - imagesOnButtons(imagesOnButtons), - colorizeIcons(colorizeIcons), - useExtraSpacing(useExtraSpacing), +PlatformStyle::PlatformStyle(const QString &_name, bool _imagesOnButtons, bool _colorizeIcons, bool _useExtraSpacing): + name(_name), + imagesOnButtons(_imagesOnButtons), + colorizeIcons(_colorizeIcons), + useExtraSpacing(_useExtraSpacing), singleColor(0,0,0), textColor(0,0,0) { diff --git a/src/qt/qvalidatedlineedit.cpp b/src/qt/qvalidatedlineedit.cpp index baa2eb67f7621..492b96ff09b61 100644 --- a/src/qt/qvalidatedlineedit.cpp +++ b/src/qt/qvalidatedlineedit.cpp @@ -15,14 +15,14 @@ QValidatedLineEdit::QValidatedLineEdit(QWidget *parent) : connect(this, SIGNAL(textChanged(QString)), this, SLOT(markValid())); } -void QValidatedLineEdit::setValid(bool valid) +void QValidatedLineEdit::setValid(bool _valid) { - if(valid == this->valid) + if(_valid == this->valid) { return; } - if(valid) + if(_valid) { setStyleSheet(""); } @@ -30,7 +30,7 @@ void QValidatedLineEdit::setValid(bool valid) { setStyleSheet(STYLE_INVALID); } - this->valid = valid; + this->valid = _valid; } void QValidatedLineEdit::focusInEvent(QFocusEvent *evt) diff --git a/src/qt/qvaluecombobox.cpp b/src/qt/qvaluecombobox.cpp index 146f3dd57850c..2f2478783c02c 100644 --- a/src/qt/qvaluecombobox.cpp +++ b/src/qt/qvaluecombobox.cpp @@ -20,9 +20,9 @@ void QValueComboBox::setValue(const QVariant &value) setCurrentIndex(findData(value, role)); } -void QValueComboBox::setRole(int role) +void QValueComboBox::setRole(int _role) { - this->role = role; + this->role = _role; } void QValueComboBox::handleSelectionChanged(int idx) diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp index 0b355837ab3c4..5c6dc97b20b90 100644 --- a/src/qt/receivecoinsdialog.cpp +++ b/src/qt/receivecoinsdialog.cpp @@ -22,24 +22,24 @@ #include #include -ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *platformStyle, QWidget *parent) : +ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *_platformStyle, QWidget *parent) : QDialog(parent), ui(new Ui::ReceiveCoinsDialog), model(0), - platformStyle(platformStyle) + platformStyle(_platformStyle) { ui->setupUi(this); - if (!platformStyle->getImagesOnButtons()) { + if (!_platformStyle->getImagesOnButtons()) { ui->clearButton->setIcon(QIcon()); ui->receiveButton->setIcon(QIcon()); ui->showRequestButton->setIcon(QIcon()); ui->removeRequestButton->setIcon(QIcon()); } else { - ui->clearButton->setIcon(platformStyle->SingleColorIcon(":/icons/remove")); - ui->receiveButton->setIcon(platformStyle->SingleColorIcon(":/icons/receiving_addresses")); - ui->showRequestButton->setIcon(platformStyle->SingleColorIcon(":/icons/edit")); - ui->removeRequestButton->setIcon(platformStyle->SingleColorIcon(":/icons/remove")); + ui->clearButton->setIcon(_platformStyle->SingleColorIcon(":/icons/remove")); + ui->receiveButton->setIcon(_platformStyle->SingleColorIcon(":/icons/receiving_addresses")); + ui->showRequestButton->setIcon(_platformStyle->SingleColorIcon(":/icons/edit")); + ui->removeRequestButton->setIcon(_platformStyle->SingleColorIcon(":/icons/remove")); } // context menu actions @@ -62,21 +62,21 @@ ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *platformStyle, QWidg connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear())); } -void ReceiveCoinsDialog::setModel(WalletModel *model) +void ReceiveCoinsDialog::setModel(WalletModel *_model) { - this->model = model; + this->model = _model; - if(model && model->getOptionsModel()) + if(_model && _model->getOptionsModel()) { - model->getRecentRequestsTableModel()->sort(RecentRequestsTableModel::Date, Qt::DescendingOrder); - connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); + _model->getRecentRequestsTableModel()->sort(RecentRequestsTableModel::Date, Qt::DescendingOrder); + connect(_model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); updateDisplayUnit(); QTableView* tableView = ui->recentRequestsView; tableView->verticalHeader()->hide(); tableView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - tableView->setModel(model->getRecentRequestsTableModel()); + tableView->setModel(_model->getRecentRequestsTableModel()); tableView->setAlternatingRowColors(true); tableView->setSelectionBehavior(QAbstractItemView::SelectRows); tableView->setSelectionMode(QAbstractItemView::ContiguousSelection); diff --git a/src/qt/receiverequestdialog.cpp b/src/qt/receiverequestdialog.cpp index b13ea3df709bb..998c9176d7bca 100644 --- a/src/qt/receiverequestdialog.cpp +++ b/src/qt/receiverequestdialog.cpp @@ -109,20 +109,20 @@ ReceiveRequestDialog::~ReceiveRequestDialog() delete ui; } -void ReceiveRequestDialog::setModel(OptionsModel *model) +void ReceiveRequestDialog::setModel(OptionsModel *_model) { - this->model = model; + this->model = _model; - if (model) - connect(model, SIGNAL(displayUnitChanged(int)), this, SLOT(update())); + if (_model) + connect(_model, SIGNAL(displayUnitChanged(int)), this, SLOT(update())); // update the display unit if necessary update(); } -void ReceiveRequestDialog::setInfo(const SendCoinsRecipient &info) +void ReceiveRequestDialog::setInfo(const SendCoinsRecipient &_info) { - this->info = info; + this->info = _info; update(); } diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index a316b951c4ff6..ace9f1ceaad6b 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -83,8 +83,8 @@ class QtRPCTimerBase: public QObject, public RPCTimerBase { Q_OBJECT public: - QtRPCTimerBase(boost::function& func, int64_t millis): - func(func) + QtRPCTimerBase(boost::function& _func, int64_t millis): + func(_func) { timer.setSingleShot(true); connect(&timer, SIGNAL(timeout()), this, SLOT(timeout())); @@ -335,13 +335,13 @@ void RPCExecutor::request(const QString &command) } } -RPCConsole::RPCConsole(const PlatformStyle *platformStyle, QWidget *parent) : +RPCConsole::RPCConsole(const PlatformStyle *_platformStyle, QWidget *parent) : QWidget(parent), ui(new Ui::RPCConsole), clientModel(0), historyPtr(0), cachedNodeid(-1), - platformStyle(platformStyle), + platformStyle(_platformStyle), peersTableContextMenu(0), banTableContextMenu(0), consoleFontSize(0) diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 8433818a64838..4b2ba7d6241d2 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -30,25 +30,25 @@ #define SEND_CONFIRM_DELAY 3 -SendCoinsDialog::SendCoinsDialog(const PlatformStyle *platformStyle, QWidget *parent) : +SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, QWidget *parent) : QDialog(parent), ui(new Ui::SendCoinsDialog), clientModel(0), model(0), fNewRecipientAllowed(true), fFeeMinimized(true), - platformStyle(platformStyle) + platformStyle(_platformStyle) { ui->setupUi(this); - if (!platformStyle->getImagesOnButtons()) { + if (!_platformStyle->getImagesOnButtons()) { ui->addButton->setIcon(QIcon()); ui->clearButton->setIcon(QIcon()); ui->sendButton->setIcon(QIcon()); } else { - ui->addButton->setIcon(platformStyle->SingleColorIcon(":/icons/add")); - ui->clearButton->setIcon(platformStyle->SingleColorIcon(":/icons/remove")); - ui->sendButton->setIcon(platformStyle->SingleColorIcon(":/icons/send")); + ui->addButton->setIcon(_platformStyle->SingleColorIcon(":/icons/add")); + ui->clearButton->setIcon(_platformStyle->SingleColorIcon(":/icons/remove")); + ui->sendButton->setIcon(_platformStyle->SingleColorIcon(":/icons/send")); } GUIUtil::setupAddressWidget(ui->lineEditCoinControlChange, this); @@ -116,40 +116,40 @@ SendCoinsDialog::SendCoinsDialog(const PlatformStyle *platformStyle, QWidget *pa minimizeFeeSection(settings.value("fFeeSectionMinimized").toBool()); } -void SendCoinsDialog::setClientModel(ClientModel *clientModel) +void SendCoinsDialog::setClientModel(ClientModel *_clientModel) { - this->clientModel = clientModel; + this->clientModel = _clientModel; - if (clientModel) { - connect(clientModel, SIGNAL(numBlocksChanged(int,QDateTime,double,bool)), this, SLOT(updateSmartFeeLabel())); + if (_clientModel) { + connect(_clientModel, SIGNAL(numBlocksChanged(int,QDateTime,double,bool)), this, SLOT(updateSmartFeeLabel())); } } -void SendCoinsDialog::setModel(WalletModel *model) +void SendCoinsDialog::setModel(WalletModel *_model) { - this->model = model; + this->model = _model; - if(model && model->getOptionsModel()) + if(_model && _model->getOptionsModel()) { for(int i = 0; i < ui->entries->count(); ++i) { SendCoinsEntry *entry = qobject_cast(ui->entries->itemAt(i)->widget()); if(entry) { - entry->setModel(model); + entry->setModel(_model); } } - setBalance(model->getBalance(), model->getUnconfirmedBalance(), model->getImmatureBalance(), - model->getWatchBalance(), model->getWatchUnconfirmedBalance(), model->getWatchImmatureBalance()); - connect(model, SIGNAL(balanceChanged(CAmount,CAmount,CAmount,CAmount,CAmount,CAmount)), this, SLOT(setBalance(CAmount,CAmount,CAmount,CAmount,CAmount,CAmount))); - connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); + setBalance(_model->getBalance(), _model->getUnconfirmedBalance(), _model->getImmatureBalance(), + _model->getWatchBalance(), _model->getWatchUnconfirmedBalance(), _model->getWatchImmatureBalance()); + connect(_model, SIGNAL(balanceChanged(CAmount,CAmount,CAmount,CAmount,CAmount,CAmount)), this, SLOT(setBalance(CAmount,CAmount,CAmount,CAmount,CAmount,CAmount))); + connect(_model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); updateDisplayUnit(); // Coin Control - connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(coinControlUpdateLabels())); - connect(model->getOptionsModel(), SIGNAL(coinControlFeaturesChanged(bool)), this, SLOT(coinControlFeatureChanged(bool))); - ui->frameCoinControl->setVisible(model->getOptionsModel()->getCoinControlFeatures()); + connect(_model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(coinControlUpdateLabels())); + connect(_model->getOptionsModel(), SIGNAL(coinControlFeaturesChanged(bool)), this, SLOT(coinControlFeatureChanged(bool))); + ui->frameCoinControl->setVisible(_model->getOptionsModel()->getCoinControlFeatures()); coinControlUpdateLabels(); // fee section @@ -826,9 +826,9 @@ void SendCoinsDialog::coinControlUpdateLabels() } } -SendConfirmationDialog::SendConfirmationDialog(const QString &title, const QString &text, int secDelay, +SendConfirmationDialog::SendConfirmationDialog(const QString &title, const QString &text, int _secDelay, QWidget *parent) : - QMessageBox(QMessageBox::Question, title, text, QMessageBox::Yes | QMessageBox::Cancel, parent), secDelay(secDelay) + QMessageBox(QMessageBox::Question, title, text, QMessageBox::Yes | QMessageBox::Cancel, parent), secDelay(_secDelay) { setDefaultButton(QMessageBox::Cancel); yesButton = button(QMessageBox::Yes); diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp index d063f2c89104a..7eb1eb7e3a128 100644 --- a/src/qt/sendcoinsentry.cpp +++ b/src/qt/sendcoinsentry.cpp @@ -15,11 +15,11 @@ #include #include -SendCoinsEntry::SendCoinsEntry(const PlatformStyle *platformStyle, QWidget *parent) : +SendCoinsEntry::SendCoinsEntry(const PlatformStyle *_platformStyle, QWidget *parent) : QStackedWidget(parent), ui(new Ui::SendCoinsEntry), model(0), - platformStyle(platformStyle) + platformStyle(_platformStyle) { ui->setupUi(this); @@ -79,12 +79,12 @@ void SendCoinsEntry::on_payTo_textChanged(const QString &address) updateLabel(address); } -void SendCoinsEntry::setModel(WalletModel *model) +void SendCoinsEntry::setModel(WalletModel *_model) { - this->model = model; + this->model = _model; - if (model && model->getOptionsModel()) - connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); + if (_model && _model->getOptionsModel()) + connect(_model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); clear(); } diff --git a/src/qt/signverifymessagedialog.cpp b/src/qt/signverifymessagedialog.cpp index 8e2e8a509876e..4061909b719fb 100644 --- a/src/qt/signverifymessagedialog.cpp +++ b/src/qt/signverifymessagedialog.cpp @@ -20,11 +20,11 @@ #include -SignVerifyMessageDialog::SignVerifyMessageDialog(const PlatformStyle *platformStyle, QWidget *parent) : +SignVerifyMessageDialog::SignVerifyMessageDialog(const PlatformStyle *_platformStyle, QWidget *parent) : QDialog(parent), ui(new Ui::SignVerifyMessageDialog), model(0), - platformStyle(platformStyle) + platformStyle(_platformStyle) { ui->setupUi(this); @@ -60,9 +60,9 @@ SignVerifyMessageDialog::~SignVerifyMessageDialog() delete ui; } -void SignVerifyMessageDialog::setModel(WalletModel *model) +void SignVerifyMessageDialog::setModel(WalletModel *_model) { - this->model = model; + this->model = _model; } void SignVerifyMessageDialog::setAddress_SM(const QString &address) diff --git a/src/qt/transactionfilterproxy.cpp b/src/qt/transactionfilterproxy.cpp index 9dcb72f55e44a..e21b89b935483 100644 --- a/src/qt/transactionfilterproxy.cpp +++ b/src/qt/transactionfilterproxy.cpp @@ -66,9 +66,9 @@ void TransactionFilterProxy::setDateRange(const QDateTime &from, const QDateTime invalidateFilter(); } -void TransactionFilterProxy::setAddressPrefix(const QString &addrPrefix) +void TransactionFilterProxy::setAddressPrefix(const QString &_addrPrefix) { - this->addrPrefix = addrPrefix; + this->addrPrefix = _addrPrefix; invalidateFilter(); } @@ -95,9 +95,9 @@ void TransactionFilterProxy::setLimit(int limit) this->limitRows = limit; } -void TransactionFilterProxy::setShowInactive(bool showInactive) +void TransactionFilterProxy::setShowInactive(bool _showInactive) { - this->showInactive = showInactive; + this->showInactive = _showInactive; invalidateFilter(); } diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h index 8c754c3aadc28..8eff302affe11 100644 --- a/src/qt/transactionrecord.h +++ b/src/qt/transactionrecord.h @@ -88,16 +88,16 @@ class TransactionRecord { } - TransactionRecord(uint256 hash, qint64 time): - hash(hash), time(time), type(Other), address(""), debit(0), + TransactionRecord(uint256 _hash, qint64 _time): + hash(_hash), time(_time), type(Other), address(""), debit(0), credit(0), idx(0) { } - TransactionRecord(uint256 hash, qint64 time, - Type type, const std::string &address, - const CAmount& debit, const CAmount& credit): - hash(hash), time(time), type(type), address(address), debit(debit), credit(credit), + TransactionRecord(uint256 _hash, qint64 _time, + Type _type, const std::string &_address, + const CAmount& _debit, const CAmount& _credit): + hash(_hash), time(_time), type(_type), address(_address), debit(_debit), credit(_credit), idx(0) { } diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index b29ecf83486b0..52261ff04b34b 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -59,9 +59,9 @@ struct TxLessThan class TransactionTablePriv { public: - TransactionTablePriv(CWallet *wallet, TransactionTableModel *parent) : - wallet(wallet), - parent(parent) + TransactionTablePriv(CWallet *_wallet, TransactionTableModel *_parent) : + wallet(_wallet), + parent(_parent) { } @@ -235,13 +235,13 @@ class TransactionTablePriv } }; -TransactionTableModel::TransactionTableModel(const PlatformStyle *platformStyle, CWallet* wallet, WalletModel *parent): +TransactionTableModel::TransactionTableModel(const PlatformStyle *_platformStyle, CWallet* _wallet, WalletModel *parent): QAbstractTableModel(parent), - wallet(wallet), + wallet(_wallet), walletModel(parent), - priv(new TransactionTablePriv(wallet, this)), + priv(new TransactionTablePriv(_wallet, this)), fProcessingQueuedTransactions(false), - platformStyle(platformStyle) + platformStyle(_platformStyle) { columns << QString() << QString() << tr("Date") << tr("Type") << tr("Label") << BitcoinUnits::getAmountColumnTitle(walletModel->getOptionsModel()->getDisplayUnit()); priv->refreshWallet(); @@ -714,8 +714,8 @@ struct TransactionNotification { public: TransactionNotification() {} - TransactionNotification(uint256 hash, ChangeType status, bool showTransaction): - hash(hash), status(status), showTransaction(showTransaction) {} + TransactionNotification(uint256 _hash, ChangeType _status, bool _showTransaction): + hash(_hash), status(_status), showTransaction(_showTransaction) {} void invoke(QObject *ttm) { diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index 48cf94050297b..856b16d2c46ee 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -184,13 +184,13 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa connect(showDetailsAction, SIGNAL(triggered()), this, SLOT(showDetails())); } -void TransactionView::setModel(WalletModel *model) +void TransactionView::setModel(WalletModel *_model) { - this->model = model; - if(model) + this->model = _model; + if(_model) { transactionProxyModel = new TransactionFilterProxy(this); - transactionProxyModel->setSourceModel(model->getTransactionTableModel()); + transactionProxyModel->setSourceModel(_model->getTransactionTableModel()); transactionProxyModel->setDynamicSortFilter(true); transactionProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); transactionProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); @@ -214,10 +214,10 @@ void TransactionView::setModel(WalletModel *model) columnResizingFixer = new GUIUtil::TableViewLastColumnResizingFixer(transactionView, AMOUNT_MINIMUM_COLUMN_WIDTH, MINIMUM_COLUMN_WIDTH); - if (model->getOptionsModel()) + if (_model->getOptionsModel()) { // Add third party transaction URLs to context menu - QStringList listUrls = model->getOptionsModel()->getThirdPartyTxUrls().split("|", QString::SkipEmptyParts); + QStringList listUrls = _model->getOptionsModel()->getThirdPartyTxUrls().split("|", QString::SkipEmptyParts); for (int i = 0; i < listUrls.size(); ++i) { QString host = QUrl(listUrls[i].trimmed(), QUrl::StrictMode).host(); @@ -234,10 +234,10 @@ void TransactionView::setModel(WalletModel *model) } // show/hide column Watch-only - updateWatchOnlyColumn(model->haveWatchOnly()); + updateWatchOnlyColumn(_model->haveWatchOnly()); // Watch-only signal - connect(model, SIGNAL(notifyWatchonlyChanged(bool)), this, SLOT(updateWatchOnlyColumn(bool))); + connect(_model, SIGNAL(notifyWatchonlyChanged(bool)), this, SLOT(updateWatchOnlyColumn(bool))); } } diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp index e4ca5e1831d15..640be4d7a7e16 100644 --- a/src/qt/walletframe.cpp +++ b/src/qt/walletframe.cpp @@ -12,10 +12,10 @@ #include #include -WalletFrame::WalletFrame(const PlatformStyle *platformStyle, BitcoinGUI *_gui) : +WalletFrame::WalletFrame(const PlatformStyle *_platformStyle, BitcoinGUI *_gui) : QFrame(_gui), gui(_gui), - platformStyle(platformStyle) + platformStyle(_platformStyle) { // Leave HBox hook for adding a list view later QHBoxLayout *walletFrameLayout = new QHBoxLayout(this); @@ -33,9 +33,9 @@ WalletFrame::~WalletFrame() { } -void WalletFrame::setClientModel(ClientModel *clientModel) +void WalletFrame::setClientModel(ClientModel *_clientModel) { - this->clientModel = clientModel; + this->clientModel = _clientModel; } bool WalletFrame::addWallet(const QString& name, WalletModel *walletModel) diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index ad3ba996f1f91..c8a2cb37ec3f3 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -27,8 +27,8 @@ #include -WalletModel::WalletModel(const PlatformStyle *platformStyle, CWallet *wallet, OptionsModel *optionsModel, QObject *parent) : - QObject(parent), wallet(wallet), optionsModel(optionsModel), addressTableModel(0), +WalletModel::WalletModel(const PlatformStyle *platformStyle, CWallet *_wallet, OptionsModel *_optionsModel, QObject *parent) : + QObject(parent), wallet(_wallet), optionsModel(_optionsModel), addressTableModel(0), transactionTableModel(0), recentRequestsTableModel(0), cachedBalance(0), cachedUnconfirmedBalance(0), cachedImmatureBalance(0), @@ -531,10 +531,10 @@ WalletModel::UnlockContext WalletModel::requestUnlock() return UnlockContext(this, valid, was_locked); } -WalletModel::UnlockContext::UnlockContext(WalletModel *wallet, bool valid, bool relock): - wallet(wallet), - valid(valid), - relock(relock) +WalletModel::UnlockContext::UnlockContext(WalletModel *_wallet, bool _valid, bool _relock): + wallet(_wallet), + valid(_valid), + relock(_relock) { } diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index 4456215512271..e233fa690d5df 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -38,8 +38,8 @@ class SendCoinsRecipient { public: explicit SendCoinsRecipient() : amount(0), fSubtractFeeFromAmount(false), nVersion(SendCoinsRecipient::CURRENT_VERSION) { } - explicit SendCoinsRecipient(const QString &addr, const QString &label, const CAmount& amount, const QString &message): - address(addr), label(label), amount(amount), message(message), fSubtractFeeFromAmount(false), nVersion(SendCoinsRecipient::CURRENT_VERSION) {} + explicit SendCoinsRecipient(const QString &addr, const QString &_label, const CAmount& _amount, const QString &_message): + address(addr), label(_label), amount(_amount), message(_message), fSubtractFeeFromAmount(false), nVersion(SendCoinsRecipient::CURRENT_VERSION) {} // If from an unauthenticated payment request, this is used for storing // the addresses, e.g. address-A
address-B
address-C. @@ -145,8 +145,8 @@ class WalletModel : public QObject // Return status record for SendCoins, contains error id + information struct SendCoinsReturn { - SendCoinsReturn(StatusCode status = OK): - status(status) {} + SendCoinsReturn(StatusCode _status = OK): + status(_status) {} StatusCode status; }; diff --git a/src/qt/walletmodeltransaction.cpp b/src/qt/walletmodeltransaction.cpp index ffadf89cc8536..fdec6a1c863a0 100644 --- a/src/qt/walletmodeltransaction.cpp +++ b/src/qt/walletmodeltransaction.cpp @@ -7,8 +7,8 @@ #include "policy/policy.h" #include "wallet/wallet.h" -WalletModelTransaction::WalletModelTransaction(const QList &recipients) : - recipients(recipients), +WalletModelTransaction::WalletModelTransaction(const QList &_recipients) : + recipients(_recipients), walletTransaction(0), keyChange(0), fee(0) diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index 495ebfd834bfc..2b61ca1c640da 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -29,11 +29,11 @@ #include #include -WalletView::WalletView(const PlatformStyle *platformStyle, QWidget *parent): +WalletView::WalletView(const PlatformStyle *_platformStyle, QWidget *parent): QStackedWidget(parent), clientModel(0), walletModel(0), - platformStyle(platformStyle) + platformStyle(_platformStyle) { // Create tabs overviewPage = new OverviewPage(platformStyle); @@ -104,47 +104,47 @@ void WalletView::setBitcoinGUI(BitcoinGUI *gui) } } -void WalletView::setClientModel(ClientModel *clientModel) +void WalletView::setClientModel(ClientModel *_clientModel) { - this->clientModel = clientModel; + this->clientModel = _clientModel; - overviewPage->setClientModel(clientModel); - sendCoinsPage->setClientModel(clientModel); + overviewPage->setClientModel(_clientModel); + sendCoinsPage->setClientModel(_clientModel); } -void WalletView::setWalletModel(WalletModel *walletModel) +void WalletView::setWalletModel(WalletModel *_walletModel) { - this->walletModel = walletModel; + this->walletModel = _walletModel; // Put transaction list in tabs - transactionView->setModel(walletModel); - overviewPage->setWalletModel(walletModel); - receiveCoinsPage->setModel(walletModel); - sendCoinsPage->setModel(walletModel); - usedReceivingAddressesPage->setModel(walletModel->getAddressTableModel()); - usedSendingAddressesPage->setModel(walletModel->getAddressTableModel()); - - if (walletModel) + transactionView->setModel(_walletModel); + overviewPage->setWalletModel(_walletModel); + receiveCoinsPage->setModel(_walletModel); + sendCoinsPage->setModel(_walletModel); + usedReceivingAddressesPage->setModel(_walletModel->getAddressTableModel()); + usedSendingAddressesPage->setModel(_walletModel->getAddressTableModel()); + + if (_walletModel) { // Receive and pass through messages from wallet model - connect(walletModel, SIGNAL(message(QString,QString,unsigned int)), this, SIGNAL(message(QString,QString,unsigned int))); + connect(_walletModel, SIGNAL(message(QString,QString,unsigned int)), this, SIGNAL(message(QString,QString,unsigned int))); // Handle changes in encryption status - connect(walletModel, SIGNAL(encryptionStatusChanged(int)), this, SIGNAL(encryptionStatusChanged(int))); + connect(_walletModel, SIGNAL(encryptionStatusChanged(int)), this, SIGNAL(encryptionStatusChanged(int))); updateEncryptionStatus(); // update HD status - Q_EMIT hdEnabledStatusChanged(walletModel->hdEnabled()); + Q_EMIT hdEnabledStatusChanged(_walletModel->hdEnabled()); // Balloon pop-up for new transaction - connect(walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), + connect(_walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(processNewTransaction(QModelIndex,int,int))); // Ask for passphrase if needed - connect(walletModel, SIGNAL(requireUnlock()), this, SLOT(unlockWallet())); + connect(_walletModel, SIGNAL(requireUnlock()), this, SLOT(unlockWallet())); // Show progress dialog - connect(walletModel, SIGNAL(showProgress(QString,int)), this, SLOT(showProgress(QString,int))); + connect(_walletModel, SIGNAL(showProgress(QString,int)), this, SLOT(showProgress(QString,int))); } } From 08827df3ecce925928dc3bedcdef63bfca290300 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Wed, 21 Sep 2016 10:29:57 +0200 Subject: [PATCH 0931/1802] [Qt] modalinfolayer: removed unused comments, renamed signal, code style overhaul --- src/qt/bitcoingui.cpp | 8 ++++---- src/qt/forms/modaloverlay.ui | 4 ++-- src/qt/modaloverlay.cpp | 7 +++---- src/qt/walletframe.cpp | 4 ++-- src/qt/walletframe.h | 2 +- src/qt/walletview.cpp | 4 ++-- src/qt/walletview.h | 2 +- 7 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index c184745dbe4fd..2a9afc51a0c03 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -247,7 +247,7 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *platformStyle, const NetworkStyle *n modalOverlay = new ModalOverlay(this->centralWidget()); #ifdef ENABLE_WALLET if(enableWallet) - connect(walletFrame, SIGNAL(requestedOfSyncWarningInfo()), this, SLOT(showModalOverlay())); + connect(walletFrame, SIGNAL(requestedSyncWarningInfo()), this, SLOT(showModalOverlay())); #endif } @@ -717,13 +717,13 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer { if (modalOverlay) { - if (header) - { + if (header) { /* use clientmodels getHeaderTipHeight and getHeaderTipTime because the NotifyHeaderTip signal does not fire when updating the best header */ modalOverlay->setKnownBestHeight(clientModel->getHeaderTipHeight(), QDateTime::fromTime_t(clientModel->getHeaderTipTime())); } - else + else { modalOverlay->tipUpdate(count, blockDate, nVerificationProgress); + } } if (!clientModel) return; diff --git a/src/qt/forms/modaloverlay.ui b/src/qt/forms/modaloverlay.ui index ce9ceaaadd7e4..ccec1b3e1e50f 100644 --- a/src/qt/forms/modaloverlay.ui +++ b/src/qt/forms/modaloverlay.ui @@ -130,7 +130,7 @@ QLabel { color: rgb(40,40,40); }
- 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. + 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. This means that recent transactions will not be visible, and the balance will not be up-to-date until this process has completed. Qt::RichText @@ -149,7 +149,7 @@ QLabel { color: rgb(40,40,40); } - This means that recent transactions will not be visible, and the balance will not be up-to-date until this process has completed. Spending bitcoins is not possible during that phase! + Spending bitcoins may not be possible during that phase! Qt::RichText diff --git a/src/qt/modaloverlay.cpp b/src/qt/modaloverlay.cpp index c54889039133c..7b121e9e88b45 100644 --- a/src/qt/modaloverlay.cpp +++ b/src/qt/modaloverlay.cpp @@ -86,7 +86,6 @@ void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVeri // show progress speed if we have more then one sample if (blockProcessTime.size() >= 2) { - // try to get the window from the last 500 seconds or at least 10 samples double progressStart = blockProcessTime[0].second; double progressDelta = 0; double progressPerHour = 0; @@ -114,9 +113,9 @@ void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVeri ui->expectedTimeLeft->setText(GUIUtil::formateNiceTimeOffset(remainingMSecs/1000.0)); // keep maximal 5000 samples - static int maxSamples = 5000; - if (blockProcessTime.count() > maxSamples) - blockProcessTime.remove(maxSamples, blockProcessTime.count()-maxSamples); + static const int MAX_SAMPLES = 5000; + if (blockProcessTime.count() > MAX_SAMPLES) + blockProcessTime.remove(MAX_SAMPLES, blockProcessTime.count()-MAX_SAMPLES); } // show the last block date diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp index 9d68e54e3a27b..518d9ea90a25f 100644 --- a/src/qt/walletframe.cpp +++ b/src/qt/walletframe.cpp @@ -199,5 +199,5 @@ WalletView *WalletFrame::currentWalletView() void WalletFrame::outOfSyncWarningClicked() { - Q_EMIT requestedOfSyncWarningInfo(); -} \ No newline at end of file + Q_EMIT requestedSyncWarningInfo(); +} diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h index 7e3a5690eb00a..00c2f5636379a 100644 --- a/src/qt/walletframe.h +++ b/src/qt/walletframe.h @@ -40,7 +40,7 @@ class WalletFrame : public QFrame Q_SIGNALS: /** Notify that the user has requested more information about the out-of-sync warning */ - void requestedOfSyncWarningInfo(); + void requestedSyncWarningInfo(); private: QStackedWidget *walletStack; diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index 656b21586f838..b163ce3dcfc4c 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -66,7 +66,7 @@ WalletView::WalletView(const PlatformStyle *platformStyle, QWidget *parent): // Clicking on a transaction on the overview pre-selects the transaction on the transaction history page connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), transactionView, SLOT(focusTransaction(QModelIndex))); - connect(overviewPage, SIGNAL(outOfSyncWarningClicked()), this, SLOT(requestedOfSyncWarningInfo())); + connect(overviewPage, SIGNAL(outOfSyncWarningClicked()), this, SLOT(requestedSyncWarningInfo())); // Double-clicking on a transaction on the transaction history page shows details connect(transactionView, SIGNAL(doubleClicked(QModelIndex)), transactionView, SLOT(showDetails())); @@ -324,7 +324,7 @@ void WalletView::showProgress(const QString &title, int nProgress) progressDialog->setValue(nProgress); } -void WalletView::requestedOfSyncWarningInfo() +void WalletView::requestedSyncWarningInfo() { Q_EMIT outOfSyncWarningClicked(); } diff --git a/src/qt/walletview.h b/src/qt/walletview.h index c0a27ab98970d..aaa6aacbf0747 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -111,7 +111,7 @@ public Q_SLOTS: void showProgress(const QString &title, int nProgress); /** User has requested more information about the out of sync state */ - void requestedOfSyncWarningInfo(); + void requestedSyncWarningInfo(); Q_SIGNALS: /** Signal that we want to show the main window */ From edeaf24e4c3409d5b176433cc9e4e027b87a2f6e Mon Sep 17 00:00:00 2001 From: Mitchell Cash Date: Sat, 24 Sep 2016 13:46:08 +1000 Subject: [PATCH 0932/1802] Fix future copyright year --- src/qt/modaloverlay.cpp | 2 +- src/qt/modaloverlay.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qt/modaloverlay.cpp b/src/qt/modaloverlay.cpp index 7b121e9e88b45..7951bd784ee40 100644 --- a/src/qt/modaloverlay.cpp +++ b/src/qt/modaloverlay.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017 The Bitcoin Core developers +// Copyright (c) 2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/modaloverlay.h b/src/qt/modaloverlay.h index bdbe3c39a70ac..670c9e58ab3ec 100644 --- a/src/qt/modaloverlay.h +++ b/src/qt/modaloverlay.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017 The Bitcoin Core developers +// Copyright (c) 2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. From c9ce17beedba69c158fb77713b95eb48f30e7705 Mon Sep 17 00:00:00 2001 From: Derek Miller Date: Sat, 24 Sep 2016 12:22:47 -0500 Subject: [PATCH 0933/1802] Trivial: Grammar and capitalization --- src/qt/forms/modaloverlay.ui | 8 ++++---- src/qt/modaloverlay.cpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/qt/forms/modaloverlay.ui b/src/qt/forms/modaloverlay.ui index ccec1b3e1e50f..b16ecafbe430e 100644 --- a/src/qt/forms/modaloverlay.ui +++ b/src/qt/forms/modaloverlay.ui @@ -204,7 +204,7 @@ QLabel { color: rgb(40,40,40); } 10 - + 75 @@ -212,12 +212,12 @@ QLabel { color: rgb(40,40,40); } - Amount of blocks left + Number of blocks left - + unknown... @@ -289,7 +289,7 @@ QLabel { color: rgb(40,40,40); } - Progress increase per Hour + Progress increase per hour diff --git a/src/qt/modaloverlay.cpp b/src/qt/modaloverlay.cpp index 7b121e9e88b45..35a4a56044cd6 100644 --- a/src/qt/modaloverlay.cpp +++ b/src/qt/modaloverlay.cpp @@ -125,9 +125,9 @@ void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVeri ui->percentageProgress->setText(QString::number(nVerificationProgress*100, 'f', 2)+"%"); ui->progressBar->setValue(nVerificationProgress*100); - // show remaining amount of blocks + // show remaining number of blocks if (bestBlockHeight > 0) - ui->amountOfBlocksLeft->setText(QString::number(bestBlockHeight-count)); + ui->numberOfBlocksLeft->setText(QString::number(bestBlockHeight-count)); else ui->expectedTimeLeft->setText(tr("Unknown. Syncing Headers...")); } From b1948723c9bc045aa43a7a2771c62d413bfd0e20 Mon Sep 17 00:00:00 2001 From: fanquake Date: Fri, 16 Sep 2016 12:36:46 +0800 Subject: [PATCH 0934/1802] Remove old manpages from contrib/debian --- contrib/debian/bitcoin-qt.manpages | 1 + contrib/debian/bitcoin-tx.manpages | 1 + contrib/debian/bitcoind.manpages | 5 ++--- contrib/debian/copyright | 4 ---- contrib/debian/manpages/bitcoin-cli.1 | 21 ------------------ contrib/debian/manpages/bitcoin-qt.1 | 13 ----------- contrib/debian/manpages/bitcoin.conf.5 | 19 ---------------- contrib/debian/manpages/bitcoind.1 | 30 -------------------------- contrib/debian/rules | 3 --- contrib/rpm/bitcoin.spec | 10 +++------ doc/release-process.md | 2 ++ 11 files changed, 9 insertions(+), 100 deletions(-) create mode 100644 contrib/debian/bitcoin-qt.manpages create mode 100644 contrib/debian/bitcoin-tx.manpages delete mode 100644 contrib/debian/manpages/bitcoin-cli.1 delete mode 100644 contrib/debian/manpages/bitcoin-qt.1 delete mode 100644 contrib/debian/manpages/bitcoin.conf.5 delete mode 100644 contrib/debian/manpages/bitcoind.1 diff --git a/contrib/debian/bitcoin-qt.manpages b/contrib/debian/bitcoin-qt.manpages new file mode 100644 index 0000000000000..9a3cc31c09a8f --- /dev/null +++ b/contrib/debian/bitcoin-qt.manpages @@ -0,0 +1 @@ +doc/man/bitcoin-qt.1 diff --git a/contrib/debian/bitcoin-tx.manpages b/contrib/debian/bitcoin-tx.manpages new file mode 100644 index 0000000000000..861d49d07022e --- /dev/null +++ b/contrib/debian/bitcoin-tx.manpages @@ -0,0 +1 @@ +doc/man/bitcoin-tx.1 diff --git a/contrib/debian/bitcoind.manpages b/contrib/debian/bitcoind.manpages index 6d3e683855018..bab644ece1369 100644 --- a/contrib/debian/bitcoind.manpages +++ b/contrib/debian/bitcoind.manpages @@ -1,3 +1,2 @@ -debian/manpages/bitcoind.1 -debian/manpages/bitcoin.conf.5 -debian/manpages/bitcoin-cli.1 +doc/man/bitcoind.1 +doc/man/bitcoin-cli.1 diff --git a/contrib/debian/copyright b/contrib/debian/copyright index cc4606ca88ad9..5cac6e533c5f3 100644 --- a/contrib/debian/copyright +++ b/contrib/debian/copyright @@ -15,10 +15,6 @@ Copyright: 2010-2011, Jonas Smedegaard 2011, Matt Corallo License: GPL-2+ -Files: debian/manpages/* -Copyright: Micah Anderson -License: GPL-3+ - Files: src/qt/res/icons/add.png src/qt/res/icons/address-book.png src/qt/res/icons/chevron.png diff --git a/contrib/debian/manpages/bitcoin-cli.1 b/contrib/debian/manpages/bitcoin-cli.1 deleted file mode 100644 index 16c338dd3e511..0000000000000 --- a/contrib/debian/manpages/bitcoin-cli.1 +++ /dev/null @@ -1,21 +0,0 @@ -.TH BITCOIN-CLI "1" "February 2016" "bitcoin-cli 0.12" -.SH NAME -bitcoin-cli \- a remote procedure call client for Bitcoin Core. -.SH SYNOPSIS -bitcoin-cli [options] [params] \- Send command to Bitcoin Core. -.TP -bitcoin-cli [options] help \- Asks Bitcoin Core for a list of supported commands. -.SH DESCRIPTION -This manual page documents the bitcoin-cli program. bitcoin-cli is an RPC client used to send commands to Bitcoin Core. - -.SH OPTIONS -.TP -\fB\-?\fR -Show possible options. - -.SH "SEE ALSO" -\fBbitcoind\fP, \fBbitcoin.conf\fP -.SH AUTHOR -This manual page was written by Ciemon Dunville . Permission is granted to copy, distribute and/or modify this document under the terms of the MIT License. - -The complete text of the MIT License can be found on the web at \fIhttp://opensource.org/licenses/MIT\fP. diff --git a/contrib/debian/manpages/bitcoin-qt.1 b/contrib/debian/manpages/bitcoin-qt.1 deleted file mode 100644 index 685a282080e2b..0000000000000 --- a/contrib/debian/manpages/bitcoin-qt.1 +++ /dev/null @@ -1,13 +0,0 @@ -.TH BITCOIN-QT "1" "February 2016" "bitcoin-qt 0.12" -.SH NAME -bitcoin-qt \- peer-to-peer network based digital currency -.SH DESCRIPTION -.SS "Usage:" -.IP -bitcoin\-qt [command\-line options] -.SH OPTIONS -.TP -\-? -List options. -.SH "SEE ALSO" -bitcoind(1) diff --git a/contrib/debian/manpages/bitcoin.conf.5 b/contrib/debian/manpages/bitcoin.conf.5 deleted file mode 100644 index 839dc26c1aa57..0000000000000 --- a/contrib/debian/manpages/bitcoin.conf.5 +++ /dev/null @@ -1,19 +0,0 @@ -.TH BITCOIN.CONF "5" "February 2016" "bitcoin.conf 0.12" -.SH NAME -bitcoin.conf \- bitcoin configuration file -.SH SYNOPSIS -All command-line options (except for '\-conf') may be specified in a configuration file, and all configuration file options may also be specified on the command line. Command-line options override values set in the configuration file. -.TP -The configuration file is a list of 'setting=value' pairs, one per line, with optional comments starting with the '#' character. Please refer to bitcoind(1) for a up to date list of valid options. -.TP -The configuration file is not automatically created; you can create it using your favorite plain-text editor. By default, bitcoind(1) will look for a file named bitcoin.conf(5) in the bitcoin data directory, but both the data directory and the configuration file path may be changed using the '\-datadir' and '\-conf' command-line arguments. -.SH LOCATION -bitcoin.conf should be located in $HOME/.bitcoin - -.SH "SEE ALSO" -bitcoind(1) -.SH AUTHOR -This manual page was written by Micah Anderson for the Debian system (but may be used by others). Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 3 or any later version published by the Free Software Foundation. - -On Debian systems, the complete text of the GNU General Public License can be found in /usr/share/common-licenses/GPL. - diff --git a/contrib/debian/manpages/bitcoind.1 b/contrib/debian/manpages/bitcoind.1 deleted file mode 100644 index 5c3e52f441e9e..0000000000000 --- a/contrib/debian/manpages/bitcoind.1 +++ /dev/null @@ -1,30 +0,0 @@ -.TH BITCOIND "1" "February 2016" "bitcoind 0.12" -.SH NAME -bitcoind \- peer-to-peer network based digital currency -.SH SYNOPSIS -bitcoin [options] [params] -.TP -bitcoin [options] help \- Get help for a command -.SH DESCRIPTION -This manual page documents the bitcoind program. Bitcoin is an experimental new digital currency that enables instant payments to anyone, anywhere in the world. Bitcoin uses peer-to-peer technology to operate with no central authority: managing transactions and issuing money are carried out collectively by the network. Bitcoin Core is the name of open source software which enables the use of this currency. - -.SH OPTIONS -.TP -\-? -List of possible options. -.SH COMMANDS -.TP -\fBhelp\fR -List commands. - -.TP -\fBhelp 'command'\fR -Get help for a command. - -.SH "SEE ALSO" -bitcoin.conf(5) -.SH AUTHOR -This manual page was written by Micah Anderson for the Debian system (but may be used by others). Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 3 or any later version published by the Free Software Foundation. - -On Debian systems, the complete text of the GNU General Public License can be found in /usr/share/common-licenses/GPL. - diff --git a/contrib/debian/rules b/contrib/debian/rules index 52b357cf01a50..3896d2caa3116 100755 --- a/contrib/debian/rules +++ b/contrib/debian/rules @@ -5,9 +5,6 @@ #build/bitcoind:: # $(if $(filter nocheck,$(DEB_BUILD_OPTIONS)),,src/test_bitcoin) -DEB_INSTALL_EXAMPLES_bitcoind += debian/examples/* -DEB_INSTALL_MANPAGES_bitcoind += debian/manpages/* - %: dh --with bash-completion $@ diff --git a/contrib/rpm/bitcoin.spec b/contrib/rpm/bitcoin.spec index 38ae038180766..516f42334ec14 100644 --- a/contrib/rpm/bitcoin.spec +++ b/contrib/rpm/bitcoin.spec @@ -27,10 +27,9 @@ Source1: http://download.oracle.com/berkeley-db/db-%{bdbv}.NC.tar.gz Source10: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/debian/examples/bitcoin.conf #man pages -Source20: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/debian/manpages/bitcoind.1 -Source21: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/debian/manpages/bitcoin-cli.1 -Source22: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/debian/manpages/bitcoin-qt.1 -Source23: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/debian/manpages/bitcoin.conf.5 +Source20: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/doc/man/bitcoind.1 +Source21: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/doc/man/bitcoin-cli.1 +Source22: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/doc/man/bitcoin-qt.1 #selinux Source30: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/rpm/bitcoin.te @@ -306,7 +305,6 @@ install -p %{SOURCE21} %{buildroot}%{_mandir}/man1/bitcoin-cli.1 %if %{_buildqt} install -p %{SOURCE22} %{buildroot}%{_mandir}/man1/bitcoin-qt.1 %endif -install -D -p %{SOURCE23} %{buildroot}%{_mandir}/man5/bitcoin.conf.5 # nuke these, we do extensive testing of binaries in %%check before packaging rm -f %{buildroot}%{_bindir}/test_* @@ -415,7 +413,6 @@ rm -rf %{buildroot} %config(noreplace) %attr(0600,root,root) %{_sysconfdir}/sysconfig/bitcoin %attr(0644,root,root) %{_datadir}/selinux/*/*.pp %attr(0644,root,root) %{_mandir}/man1/bitcoind.1* -%attr(0644,root,root) %{_mandir}/man5/bitcoin.conf.5* %files utils %defattr(-,root,root,-) @@ -425,7 +422,6 @@ rm -rf %{buildroot} %attr(0755,root,root) %{_bindir}/bitcoin-tx %attr(0755,root,root) %{_bindir}/bench_bitcoin %attr(0644,root,root) %{_mandir}/man1/bitcoin-cli.1* -%attr(0644,root,root) %{_mandir}/man5/bitcoin.conf.5* diff --git a/doc/release-process.md b/doc/release-process.md index 394b159b31ae5..04d9473c2005b 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -5,6 +5,8 @@ Before every release candidate: * Update translations (ping wumpus on IRC) see [translation_process.md](https://github.com/bitcoin/bitcoin/blob/master/doc/translation_process.md#synchronising-translations). +* Update manpages, see [gen-manpages.sh](https://github.com/bitcoin/bitcoin/blob/master/contrib/devtools/README.md#gen-manpagessh). + Before every minor and major release: * Update [bips.md](bips.md) to account for changes since the last release. From fa6e71b27d00766897f3e69775d450924a58a153 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 25 Sep 2016 15:01:31 +0200 Subject: [PATCH 0935/1802] [qa] Add getinfo smoke tests and rework versionbits test --- qa/rpc-tests/p2p-versionbits-warning.py | 41 +++++++++++++------------ qa/rpc-tests/rpcbind_test.py | 2 +- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/qa/rpc-tests/p2p-versionbits-warning.py b/qa/rpc-tests/p2p-versionbits-warning.py index c17bacfc79abc..00dbbc02cf3c7 100755 --- a/qa/rpc-tests/p2p-versionbits-warning.py +++ b/qa/rpc-tests/p2p-versionbits-warning.py @@ -6,6 +6,7 @@ from test_framework.mininode import * from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * +import re import time from test_framework.blocktools import create_block, create_coinbase @@ -21,6 +22,10 @@ VB_TOP_BITS = 0x20000000 VB_UNKNOWN_BIT = 27 # Choose a bit unassigned to any deployment +WARN_UNKNOWN_RULES_MINED = "Unknown block versions being mined! It's possible unknown rules are in effect" +WARN_UNKNOWN_RULES_ACTIVE = "unknown new rules activated (versionbit {})".format(VB_UNKNOWN_BIT) +VB_PATTERN = re.compile("^Warning.*versionbit") + # TestNode: bare-bones "peer". Used mostly as a conduit for a test to sending # p2p messages to a node, generating the messages in the main testing logic. class TestNode(NodeConnCB): @@ -65,16 +70,12 @@ def __init__(self): self.num_nodes = 1 def setup_network(self): - self.nodes = [] self.alert_filename = os.path.join(self.options.tmpdir, "alert.txt") # Open and close to create zero-length file - with open(self.alert_filename, 'w') as f: + with open(self.alert_filename, 'w') as _: pass - self.node_options = ["-debug", "-logtimemicros=1", "-alertnotify=echo %s >> \"" + self.alert_filename + "\""] - self.nodes.append(start_node(0, self.options.tmpdir, self.node_options)) - - import re - self.vb_pattern = re.compile("^Warning.*versionbit") + self.extra_args = [["-debug", "-logtimemicros=1", "-alertnotify=echo %s >> \"" + self.alert_filename + "\""]] + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args) # Send numblocks blocks via peer with nVersionToUse set. def send_blocks_with_version(self, peer, numblocks, nVersionToUse): @@ -83,7 +84,7 @@ def send_blocks_with_version(self, peer, numblocks, nVersionToUse): block_time = self.nodes[0].getblockheader(tip)["time"]+1 tip = int(tip, 16) - for i in range(numblocks): + for _ in range(numblocks): block = create_block(tip, create_coinbase(height+1), block_time) block.nVersion = nVersionToUse block.solve() @@ -96,7 +97,7 @@ def send_blocks_with_version(self, peer, numblocks, nVersionToUse): def test_versionbits_in_alert_file(self): with open(self.alert_filename, 'r') as f: alert_text = f.read() - assert(self.vb_pattern.match(alert_text)) + assert(VB_PATTERN.match(alert_text)) def run_test(self): # Setup the p2p connection and start up the network thread. @@ -123,8 +124,9 @@ def run_test(self): self.nodes[0].generate(VB_PERIOD - VB_THRESHOLD + 1) # Check that we're not getting any versionbit-related errors in # get*info() - assert(not self.vb_pattern.match(self.nodes[0].getmininginfo()["errors"])) - assert(not self.vb_pattern.match(self.nodes[0].getnetworkinfo()["warnings"])) + assert(not VB_PATTERN.match(self.nodes[0].getinfo()["errors"])) + assert(not VB_PATTERN.match(self.nodes[0].getmininginfo()["errors"])) + assert(not VB_PATTERN.match(self.nodes[0].getnetworkinfo()["warnings"])) # 3. Now build one period of blocks with >= VB_THRESHOLD blocks signaling # some unknown bit @@ -134,8 +136,9 @@ def run_test(self): # have gotten a different alert due to more than 51/100 blocks # being of unexpected version. # Check that get*info() shows some kind of error. - assert("Unknown block versions" in self.nodes[0].getmininginfo()["errors"]) - assert("Unknown block versions" in self.nodes[0].getnetworkinfo()["warnings"]) + assert(WARN_UNKNOWN_RULES_MINED in self.nodes[0].getinfo()["errors"]) + assert(WARN_UNKNOWN_RULES_MINED in self.nodes[0].getmininginfo()["errors"]) + assert(WARN_UNKNOWN_RULES_MINED in self.nodes[0].getnetworkinfo()["warnings"]) # Mine a period worth of expected blocks so the generic block-version warning # is cleared, and restart the node. This should move the versionbit state @@ -144,21 +147,21 @@ def run_test(self): stop_node(self.nodes[0], 0) wait_bitcoinds() # Empty out the alert file - with open(self.alert_filename, 'w') as f: + with open(self.alert_filename, 'w') as _: pass - self.nodes[0] = start_node(0, self.options.tmpdir, ["-debug", "-logtimemicros=1", "-alertnotify=echo %s >> \"" + self.alert_filename + "\""]) + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args) # Connecting one block should be enough to generate an error. self.nodes[0].generate(1) - assert("unknown new rules" in self.nodes[0].getmininginfo()["errors"]) - assert("unknown new rules" in self.nodes[0].getnetworkinfo()["warnings"]) + assert(WARN_UNKNOWN_RULES_ACTIVE in self.nodes[0].getinfo()["errors"]) + assert(WARN_UNKNOWN_RULES_ACTIVE in self.nodes[0].getmininginfo()["errors"]) + assert(WARN_UNKNOWN_RULES_ACTIVE in self.nodes[0].getnetworkinfo()["warnings"]) stop_node(self.nodes[0], 0) wait_bitcoinds() self.test_versionbits_in_alert_file() # Test framework expects the node to still be running... - self.nodes[0] = start_node(0, self.options.tmpdir, ["-debug", "-logtimemicros=1", "-alertnotify=echo %s >> \"" + self.alert_filename + "\""]) - + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args) if __name__ == '__main__': VersionBitsWarningTest().main() diff --git a/qa/rpc-tests/rpcbind_test.py b/qa/rpc-tests/rpcbind_test.py index 144c2f4cd41d7..085024e268384 100755 --- a/qa/rpc-tests/rpcbind_test.py +++ b/qa/rpc-tests/rpcbind_test.py @@ -44,7 +44,7 @@ def run_bind_test(self, allow_ips, connect_to, addresses, expected): def run_allowip_test(self, allow_ips, rpchost, rpcport): ''' - Start a node with rpcwallow IP, and request getnetworkinfo + Start a node with rpcallow IP, and request getnetworkinfo at a non-localhost IP. ''' base_args = ['-disablewallet', '-nolisten'] + ['-rpcallowip='+x for x in allow_ips] From 3650668cdbbf369dd8f30c8e8eb5bb883325942d Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 25 Sep 2016 15:19:23 +0200 Subject: [PATCH 0936/1802] Squashed 'src/univalue/' changes from f32df99..daf1285 daf1285 Merge pull request #2 from jgarzik/master d9e62d3 Merge pull request #24 from MarcoFalke/Mf1608-cleanup faf260f Rem unused vars and prefer prefix operator for non-primitive type 09a2693 Merge pull request #22 from laanwj/2016_04_unicode c74a04c Merge pull request #23 from paveljanik/20160527_Wshadow fceb4f8 Do not shadow variables git-subtree-dir: src/univalue git-subtree-split: daf1285af60c2c73801c0f41469c9802c849343d --- include/univalue.h | 26 +++++++++++++------------- lib/univalue.cpp | 25 +++++++++++-------------- 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/include/univalue.h b/include/univalue.h index 8428b1c683ac3..e48b905bfb857 100644 --- a/include/univalue.h +++ b/include/univalue.h @@ -56,7 +56,7 @@ class UniValue { bool setNumStr(const std::string& val); bool setInt(uint64_t val); bool setInt(int64_t val); - bool setInt(int val) { return setInt((int64_t)val); } + bool setInt(int val_) { return setInt((int64_t)val_); } bool setFloat(double val); bool setStr(const std::string& val); bool setArray(); @@ -95,28 +95,28 @@ class UniValue { bool push_backV(const std::vector& vec); bool pushKV(const std::string& key, const UniValue& val); - bool pushKV(const std::string& key, const std::string& val) { - UniValue tmpVal(VSTR, val); + bool pushKV(const std::string& key, const std::string& val_) { + UniValue tmpVal(VSTR, val_); return pushKV(key, tmpVal); } bool pushKV(const std::string& key, const char *val_) { - std::string val(val_); - return pushKV(key, val); + std::string _val(val_); + return pushKV(key, _val); } - bool pushKV(const std::string& key, int64_t val) { - UniValue tmpVal(val); + bool pushKV(const std::string& key, int64_t val_) { + UniValue tmpVal(val_); return pushKV(key, tmpVal); } - bool pushKV(const std::string& key, uint64_t val) { - UniValue tmpVal(val); + bool pushKV(const std::string& key, uint64_t val_) { + UniValue tmpVal(val_); return pushKV(key, tmpVal); } - bool pushKV(const std::string& key, int val) { - UniValue tmpVal((int64_t)val); + bool pushKV(const std::string& key, int val_) { + UniValue tmpVal((int64_t)val_); return pushKV(key, tmpVal); } - bool pushKV(const std::string& key, double val) { - UniValue tmpVal(val); + bool pushKV(const std::string& key, double val_) { + UniValue tmpVal(val_); return pushKV(key, tmpVal); } bool pushKVs(const UniValue& obj); diff --git a/lib/univalue.cpp b/lib/univalue.cpp index 0076d6678ec79..1f8cee6d29839 100644 --- a/lib/univalue.cpp +++ b/lib/univalue.cpp @@ -119,32 +119,29 @@ bool UniValue::setNumStr(const string& val_) return true; } -bool UniValue::setInt(uint64_t val) +bool UniValue::setInt(uint64_t val_) { - string s; ostringstream oss; - oss << val; + oss << val_; return setNumStr(oss.str()); } -bool UniValue::setInt(int64_t val) +bool UniValue::setInt(int64_t val_) { - string s; ostringstream oss; - oss << val; + oss << val_; return setNumStr(oss.str()); } -bool UniValue::setFloat(double val) +bool UniValue::setFloat(double val_) { - string s; ostringstream oss; - oss << std::setprecision(16) << val; + oss << std::setprecision(16) << val_; bool ret = setNumStr(oss.str()); typ = VNUM; @@ -173,12 +170,12 @@ bool UniValue::setObject() return true; } -bool UniValue::push_back(const UniValue& val) +bool UniValue::push_back(const UniValue& val_) { if (typ != VARR) return false; - values.push_back(val); + values.push_back(val_); return true; } @@ -192,13 +189,13 @@ bool UniValue::push_backV(const std::vector& vec) return true; } -bool UniValue::pushKV(const std::string& key, const UniValue& val) +bool UniValue::pushKV(const std::string& key, const UniValue& val_) { if (typ != VOBJ) return false; keys.push_back(key); - values.push_back(val); + values.push_back(val_); return true; } @@ -228,7 +225,7 @@ int UniValue::findKey(const std::string& key) const bool UniValue::checkObject(const std::map& t) { for (std::map::const_iterator it = t.begin(); - it != t.end(); it++) { + it != t.end(); ++it) { int idx = findKey(it->first); if (idx < 0) return false; From 0637b02fce04c800acc6747687c91c9b22f642e5 Mon Sep 17 00:00:00 2001 From: Johnson Lau Date: Sat, 24 Sep 2016 16:26:26 +0800 Subject: [PATCH 0937/1802] Ping regularly in p2p-segwit.py to keep connection alive This pings regularly while building a big block in p2p-segwit.py, to prevent timeout --- qa/rpc-tests/p2p-segwit.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/qa/rpc-tests/p2p-segwit.py b/qa/rpc-tests/p2p-segwit.py index 22ec0ad8c87f5..5c1eb21b1ffd5 100755 --- a/qa/rpc-tests/p2p-segwit.py +++ b/qa/rpc-tests/p2p-segwit.py @@ -1392,6 +1392,9 @@ def sign_P2PK_witness_input(script, txTo, inIdx, hashtype, value, key): block = self.build_next_block() used_sighash_single_out_of_bounds = False for i in range(NUM_TESTS): + # Ping regularly to keep the connection alive + if (not i % 100): + self.test_node.sync_with_ping() # Choose random number of inputs to use. num_inputs = random.randint(1, 10) # Create a slight bias for producing more utxos From 42f6aed731874d937d6f8c9f9c9a6b64d59852d8 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sun, 25 Sep 2016 20:02:14 +0200 Subject: [PATCH 0938/1802] tests: Add exception error message for JSONRPCException This improves error reporting if `JSONRPCException` is not specifically caught and ends up in Python's default backtrace handler. Before: ``` Traceback (most recent call last): File "/.../projects/bitcoin/bitcoin/qa/rpc-tests/test_framework/authproxy.py", line 153, in __call__ raise JSONRPCException(response['error']) test_framework.authproxy.JSONRPCException ``` After: ``` Traceback (most recent call last): File "/.../projects/bitcoin/bitcoin/qa/rpc-tests/test_framework/authproxy.py", line 152, in __call__ raise JSONRPCException(response['error']) test_framework.authproxy.JSONRPCException: Unknown named parameter random (-8) ``` --- qa/rpc-tests/test_framework/authproxy.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/qa/rpc-tests/test_framework/authproxy.py b/qa/rpc-tests/test_framework/authproxy.py index d095a56ce75e3..f5e0be20d1ec9 100644 --- a/qa/rpc-tests/test_framework/authproxy.py +++ b/qa/rpc-tests/test_framework/authproxy.py @@ -55,7 +55,11 @@ class JSONRPCException(Exception): def __init__(self, rpc_error): - Exception.__init__(self) + try: + errmsg = '%(message)s (%(code)i)' % rpc_error + except (KeyError, TypeError): + errmsg = '' + Exception.__init__(self, errmsg) self.error = rpc_error From faef293cf311a1063b31f90b645cb491d0140930 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Fri, 8 Jan 2016 01:14:09 +0100 Subject: [PATCH 0939/1802] [wallet] Add high transaction fee warnings --- src/init.cpp | 6 +++--- src/ui_interface.cpp | 5 +++++ src/ui_interface.h | 2 ++ src/wallet/wallet.cpp | 19 ++++++++++++++----- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 75182345ee9f0..b20675dd9e981 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -951,10 +951,10 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (mapArgs.count("-minrelaytxfee")) { CAmount n = 0; - if (ParseMoney(mapArgs["-minrelaytxfee"], n) && n > 0) - ::minRelayTxFee = CFeeRate(n); - else + if (!ParseMoney(mapArgs["-minrelaytxfee"], n)) return InitError(AmountErrMsg("minrelaytxfee", mapArgs["-minrelaytxfee"])); + // High fee check is done afterward in CWallet::ParameterInteraction() + ::minRelayTxFee = CFeeRate(n); } fRequireStandard = !GetBoolArg("-acceptnonstdtxn", !Params().RequireStandard()); diff --git a/src/ui_interface.cpp b/src/ui_interface.cpp index c778e40a9053a..74a13e0e052bc 100644 --- a/src/ui_interface.cpp +++ b/src/ui_interface.cpp @@ -18,6 +18,11 @@ void InitWarning(const std::string& str) uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_WARNING); } +std::string AmountHighWarn(const std::string& optname) +{ + return strprintf(_("%s is set very high!"), optname); +} + std::string AmountErrMsg(const char* const optname, const std::string& strValue) { return strprintf(_("Invalid amount for -%s=: '%s'"), optname, strValue); diff --git a/src/ui_interface.h b/src/ui_interface.h index 7e6557f8e21b0..177ff238db8b3 100644 --- a/src/ui_interface.h +++ b/src/ui_interface.h @@ -112,6 +112,8 @@ void InitWarning(const std::string& str); /** Show error message **/ bool InitError(const std::string& str); +std::string AmountHighWarn(const std::string& optname); + std::string AmountErrMsg(const char* const optname, const std::string& strValue); extern CClientUIInterface uiInterface; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index abb1ea7e76e86..50d63182ae181 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3485,13 +3485,19 @@ bool CWallet::ParameterInteraction() if (GetArg("-prune", 0) && GetBoolArg("-rescan", false)) return InitError(_("Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.")); + if (::minRelayTxFee.GetFeePerK() > HIGH_TX_FEE_PER_KB) + InitWarning(AmountHighWarn("-minrelaytxfee") + " " + + _("The wallet will avoid paying less than the minimum relay fee.")); + if (mapArgs.count("-mintxfee")) { CAmount n = 0; - if (ParseMoney(mapArgs["-mintxfee"], n) && n > 0) - CWallet::minTxFee = CFeeRate(n); - else + if (!ParseMoney(mapArgs["-mintxfee"], n)) return InitError(AmountErrMsg("mintxfee", mapArgs["-mintxfee"])); + if (n > HIGH_TX_FEE_PER_KB) + InitWarning(AmountHighWarn("-mintxfee") + " " + + _("This is the minimum transaction fee you pay on every transaction.")); + CWallet::minTxFee = CFeeRate(n); } if (mapArgs.count("-fallbackfee")) { @@ -3499,7 +3505,8 @@ bool CWallet::ParameterInteraction() if (!ParseMoney(mapArgs["-fallbackfee"], nFeePerK)) return InitError(strprintf(_("Invalid amount for -fallbackfee=: '%s'"), mapArgs["-fallbackfee"])); if (nFeePerK > HIGH_TX_FEE_PER_KB) - InitWarning(_("-fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available.")); + InitWarning(AmountHighWarn("-fallbackfee") + " " + + _("This is the transaction fee you may pay when fee estimates are not available.")); CWallet::fallbackFee = CFeeRate(nFeePerK); } if (mapArgs.count("-paytxfee")) @@ -3508,7 +3515,9 @@ bool CWallet::ParameterInteraction() if (!ParseMoney(mapArgs["-paytxfee"], nFeePerK)) return InitError(AmountErrMsg("paytxfee", mapArgs["-paytxfee"])); if (nFeePerK > HIGH_TX_FEE_PER_KB) - InitWarning(_("-paytxfee is set very high! This is the transaction fee you will pay if you send a transaction.")); + InitWarning(AmountHighWarn("-paytxfee") + " " + + _("This is the transaction fee you will pay if you send a transaction.")); + payTxFee = CFeeRate(nFeePerK, 1000); if (payTxFee < ::minRelayTxFee) { From 9a75d29b6f0d6c4834e451b0fae2200786655a35 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 23 Jun 2016 16:52:12 +0200 Subject: [PATCH 0940/1802] devtools: Check for high-entropy ASLR in 64-bit PE executables check_PE_PIE only checked for DYNAMIC_BASE, this is not enough for (secure) ASLR on 64-bit. --- contrib/devtools/security-check.py | 48 +++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/contrib/devtools/security-check.py b/contrib/devtools/security-check.py index 301fea85c1f6f..8271240859601 100755 --- a/contrib/devtools/security-check.py +++ b/contrib/devtools/security-check.py @@ -12,6 +12,7 @@ READELF_CMD = os.getenv('READELF', '/usr/bin/readelf') OBJDUMP_CMD = os.getenv('OBJDUMP', '/usr/bin/objdump') +NONFATAL = {'HIGH_ENTROPY_VA'} # checks which are non-fatal for now but only generate a warning def check_ELF_PIE(executable): ''' @@ -114,26 +115,50 @@ def check_ELF_Canary(executable): def get_PE_dll_characteristics(executable): ''' - Get PE DllCharacteristics bits + Get PE DllCharacteristics bits. + Returns a tuple (arch,bits) where arch is 'i386:x86-64' or 'i386' + and bits is the DllCharacteristics value. ''' p = subprocess.Popen([OBJDUMP_CMD, '-x', executable], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) (stdout, stderr) = p.communicate() if p.returncode: raise IOError('Error opening file') + arch = '' + bits = 0 for line in stdout.split('\n'): tokens = line.split() + if len(tokens)>=2 and tokens[0] == 'architecture:': + arch = tokens[1].rstrip(',') if len(tokens)>=2 and tokens[0] == 'DllCharacteristics': - return int(tokens[1],16) - return 0 + bits = int(tokens[1],16) + return (arch,bits) +IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA = 0x0020 +IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE = 0x0040 +IMAGE_DLL_CHARACTERISTICS_NX_COMPAT = 0x0100 -def check_PE_PIE(executable): +def check_PE_DYNAMIC_BASE(executable): '''PIE: DllCharacteristics bit 0x40 signifies dynamicbase (ASLR)''' - return bool(get_PE_dll_characteristics(executable) & 0x40) + (arch,bits) = get_PE_dll_characteristics(executable) + reqbits = IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE + return (bits & reqbits) == reqbits + +# On 64 bit, must support high-entropy 64-bit address space layout randomization in addition to DYNAMIC_BASE +# to have secure ASLR. +def check_PE_HIGH_ENTROPY_VA(executable): + '''PIE: DllCharacteristics bit 0x20 signifies high-entropy ASLR''' + (arch,bits) = get_PE_dll_characteristics(executable) + if arch == 'i386:x86-64': + reqbits = IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA + else: # Unnecessary on 32-bit + assert(arch == 'i386') + reqbits = 0 + return (bits & reqbits) == reqbits def check_PE_NX(executable): '''NX: DllCharacteristics bit 0x100 signifies nxcompat (DEP)''' - return bool(get_PE_dll_characteristics(executable) & 0x100) + (arch,bits) = get_PE_dll_characteristics(executable) + return (bits & IMAGE_DLL_CHARACTERISTICS_NX_COMPAT) == IMAGE_DLL_CHARACTERISTICS_NX_COMPAT CHECKS = { 'ELF': [ @@ -143,7 +168,8 @@ def check_PE_NX(executable): ('Canary', check_ELF_Canary) ], 'PE': [ - ('PIE', check_PE_PIE), + ('DYNAMIC_BASE', check_PE_DYNAMIC_BASE), + ('HIGH_ENTROPY_VA', check_PE_HIGH_ENTROPY_VA), ('NX', check_PE_NX) ] } @@ -168,12 +194,18 @@ def identify_executable(executable): continue failed = [] + warning = [] for (name, func) in CHECKS[etype]: if not func(filename): - failed.append(name) + if name in NONFATAL: + warning.append(name) + else: + failed.append(name) if failed: print('%s: failed %s' % (filename, ' '.join(failed))) retval = 1 + if warning: + print('%s: warning %s' % (filename, ' '.join(warning))) except IOError: print('%s: cannot open' % filename) retval = 1 From 62c291596bccca43609e61a01a027e86a81f69b2 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 23 Jun 2016 16:54:28 +0200 Subject: [PATCH 0941/1802] build: supply `-Wl,--high-entropy-va` This should enable high-entropy ASLR on 64-bit targets, for better mitigation of exploits. --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index 97af58bd7cd85..44094e8ceea17 100644 --- a/configure.ac +++ b/configure.ac @@ -488,6 +488,7 @@ if test x$use_hardening != xno; then AX_CHECK_LINK_FLAG([[-Wl,--dynamicbase]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--dynamicbase"]) AX_CHECK_LINK_FLAG([[-Wl,--nxcompat]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--nxcompat"]) + AX_CHECK_LINK_FLAG([[-Wl,--high-entropy-va]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--high-entropy-va"]) AX_CHECK_LINK_FLAG([[-Wl,-z,relro]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-z,relro"]) AX_CHECK_LINK_FLAG([[-Wl,-z,now]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-z,now"]) From a92bf4af66f8b5a2e6bc28baa6670065ce76daf2 Mon Sep 17 00:00:00 2001 From: Matthew King Date: Tue, 28 Jun 2016 09:35:41 +0300 Subject: [PATCH 0942/1802] bitcoind: Daemonize using daemon(3) Simplified version of #8278. Assumes that every OS that (a) is supported by Bitcoin Core (b) supports daemonization has the `daemon()` function in its C library. - Removes the fallback path for operating systems that support daemonization but not `daemon()`. This prevents never-exercised code from ending up in the repository (see discussion here: https://github.com/bitcoin/bitcoin/pull/8278#issuecomment-242704745). - Removes the windows-specific path. Windows doesn't support `daemon()`, so it don't support daemonization there, automatically. Original code by Matthew King, adapted by Wladimir van der Laan. --- configure.ac | 3 +++ src/bitcoind.cpp | 23 ++++++++--------------- src/init.cpp | 2 +- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/configure.ac b/configure.ac index 25b828f18c6fd..e129b58461b7c 100644 --- a/configure.ac +++ b/configure.ac @@ -508,6 +508,9 @@ AC_SEARCH_LIBS([inet_pton], [nsl resolv], [AC_DEFINE(HAVE_INET_PTON, 1, [Define AC_CHECK_DECLS([strnlen]) +# Check for daemon(3), unrelated to --with-daemon (although used by it) +AC_CHECK_DECLS([daemon]) + AC_CHECK_DECLS([le16toh, le32toh, le64toh, htole16, htole32, htole64, be16toh, be32toh, be64toh, htobe16, htobe32, htobe64],,, [#if HAVE_ENDIAN_H #include diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 322298d1b38ab..25d720e1e8ccb 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -9,6 +9,7 @@ #include "chainparams.h" #include "clientversion.h" +#include "compat.h" #include "rpc/server.h" #include "init.h" #include "noui.h" @@ -127,29 +128,21 @@ bool AppInit(int argc, char* argv[]) fprintf(stderr, "Error: There is no RPC client functionality in bitcoind anymore. Use the bitcoin-cli utility instead.\n"); exit(1); } -#ifndef WIN32 if (GetBoolArg("-daemon", false)) { +#if HAVE_DECL_DAEMON fprintf(stdout, "Bitcoin server starting\n"); // Daemonize - pid_t pid = fork(); - if (pid < 0) - { - fprintf(stderr, "Error: fork() returned %d errno %d\n", pid, errno); + if (daemon(1, 0)) { // don't chdir (1), do close FDs (0) + fprintf(stderr, "Error: daemon() failed: %s\n", strerror(errno)); return false; } - if (pid > 0) // Parent process, pid is child process id - { - return true; - } - // Child process falls through to rest of initialization - - pid_t sid = setsid(); - if (sid < 0) - fprintf(stderr, "Error: setsid() returned %d errno %d\n", sid, errno); +#else + fprintf(stderr, "Error: -daemon is not supported on this operating system\n"); + return false; +#endif // HAVE_DECL_DAEMON } -#endif SoftSetBoolArg("-server", true); // Set this early so that parameter interactions go to console diff --git a/src/init.cpp b/src/init.cpp index 75182345ee9f0..3c4466b853759 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -324,7 +324,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-conf=", strprintf(_("Specify configuration file (default: %s)"), BITCOIN_CONF_FILENAME)); if (mode == HMM_BITCOIND) { -#ifndef WIN32 +#if HAVE_DECL_DAEMON strUsage += HelpMessageOpt("-daemon", _("Run in the background as a daemon and accept commands")); #endif } From fa4bfb48193a03d99d1dfdfd1e67b613293755bf Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 26 Sep 2016 14:49:47 +0200 Subject: [PATCH 0943/1802] [wallet, policy] ParameterInteraction: Don't allow 0 fee --- src/init.cpp | 2 +- src/wallet/wallet.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index b20675dd9e981..cb8da06d6444d 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -951,7 +951,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (mapArgs.count("-minrelaytxfee")) { CAmount n = 0; - if (!ParseMoney(mapArgs["-minrelaytxfee"], n)) + if (!ParseMoney(mapArgs["-minrelaytxfee"], n) || 0 == n) return InitError(AmountErrMsg("minrelaytxfee", mapArgs["-minrelaytxfee"])); // High fee check is done afterward in CWallet::ParameterInteraction() ::minRelayTxFee = CFeeRate(n); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 50d63182ae181..a5bfde6595f92 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3492,7 +3492,7 @@ bool CWallet::ParameterInteraction() if (mapArgs.count("-mintxfee")) { CAmount n = 0; - if (!ParseMoney(mapArgs["-mintxfee"], n)) + if (!ParseMoney(mapArgs["-mintxfee"], n) || 0 == n) return InitError(AmountErrMsg("mintxfee", mapArgs["-mintxfee"])); if (n > HIGH_TX_FEE_PER_KB) InitWarning(AmountHighWarn("-mintxfee") + " " + From c14ffd524b3477d6fdf142e9dc8281b780b45923 Mon Sep 17 00:00:00 2001 From: jonnynewbs Date: Fri, 16 Sep 2016 14:54:44 -0400 Subject: [PATCH 0944/1802] [trivial] fix mempool comment (outdated by BIP125) --- src/txmempool.h | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/txmempool.h b/src/txmempool.h index 2c2127f326de2..6f67dd91d685c 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -328,14 +328,17 @@ struct TxMempoolInfo }; /** - * CTxMemPool stores valid-according-to-the-current-best-chain - * transactions that may be included in the next block. + * CTxMemPool stores valid-according-to-the-current-best-chain transactions + * that may be included in the next block. * - * Transactions are added when they are seen on the network - * (or created by the local node), but not all transactions seen - * are added to the pool: if a new transaction double-spends - * an input of a transaction in the pool, it is dropped, - * as are non-standard transactions. + * Transactions are added when they are seen on the network (or created by the + * local node), but not all transactions seen are added to the pool. For + * example, the following new transactions will not be added to the mempool: + * - a transaction which doesn't make the mimimum fee requirements. + * - a new transaction that double-spends an input of a transaction already in + * the pool where the new transaction does not meet the Replace-By-Fee + * requirements as defined in BIP 125. + * - a non-standard transaction. * * CTxMemPool::mapTx, and CTxMemPoolEntry bookkeeping: * From faa4de2a2ac2eb9bb6a419940da83fa898d16a3c Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 26 Sep 2016 18:58:51 +0200 Subject: [PATCH 0945/1802] [qt] sync-overlay: Don't block during reindex --- src/qt/clientmodel.cpp | 2 +- src/qt/modaloverlay.cpp | 31 +++++++++++++++++++------------ src/qt/modaloverlay.h | 3 ++- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 6d19b3d122b70..87704c641d489 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -256,7 +256,7 @@ static void BlockTipChanged(ClientModel *clientmodel, bool initialSync, const CB int64_t& nLastUpdateNotification = fHeader ? nLastHeaderTipUpdateNotification : nLastBlockTipUpdateNotification; // if we are in-sync, update the UI regardless of last update time - if (fHeader || !initialSync || now - nLastUpdateNotification > MODEL_UPDATE_DELAY) { + if (!initialSync || now - nLastUpdateNotification > MODEL_UPDATE_DELAY) { //pass a async signal to the UI thread QMetaObject::invokeMethod(clientmodel, "numBlocksChanged", Qt::QueuedConnection, Q_ARG(int, pIndex->nHeight), diff --git a/src/qt/modaloverlay.cpp b/src/qt/modaloverlay.cpp index 2de2dde16ad51..461077ff76e5c 100644 --- a/src/qt/modaloverlay.cpp +++ b/src/qt/modaloverlay.cpp @@ -13,7 +13,8 @@ ModalOverlay::ModalOverlay(QWidget *parent) : QWidget(parent), ui(new Ui::ModalOverlay), -bestBlockHeight(0), +bestHeaderHeight(0), +bestHeaderDate(QDateTime()), layerIsVisible(false), userClosed(false) { @@ -65,14 +66,9 @@ bool ModalOverlay::event(QEvent* ev) { void ModalOverlay::setKnownBestHeight(int count, const QDateTime& blockDate) { - - /* only update the blockheight if the headerschain-tip is not older then 30 days */ - int64_t now = QDateTime::currentDateTime().toTime_t(); - int64_t btime = blockDate.toTime_t(); - if (btime+3600*24*30 > now) - { - if (count > bestBlockHeight) - bestBlockHeight = count; + if (count > bestHeaderHeight) { + bestHeaderHeight = count; + bestHeaderDate = blockDate; } } @@ -125,11 +121,22 @@ void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVeri ui->percentageProgress->setText(QString::number(nVerificationProgress*100, 'f', 2)+"%"); ui->progressBar->setValue(nVerificationProgress*100); + if (!bestHeaderDate.isValid()) + // not syncing + return; + + // estimate the number of headers left based on nPowTargetSpacing + // and check if the gui is not aware of the the best header (happens rarely) + int estimateNumHeadersLeft = bestHeaderDate.secsTo(currentDate) / 600; + bool hasBestHeader = bestHeaderHeight >= count; + // show remaining number of blocks - if (bestBlockHeight > 0) - ui->numberOfBlocksLeft->setText(QString::number(bestBlockHeight-count)); - else + if (estimateNumHeadersLeft < 24 && hasBestHeader) { + ui->numberOfBlocksLeft->setText(QString::number(bestHeaderHeight - count)); + } else { + ui->numberOfBlocksLeft->setText("~" + QString::number(bestHeaderHeight + estimateNumHeadersLeft - count)); ui->expectedTimeLeft->setText(tr("Unknown. Syncing Headers...")); + } } void ModalOverlay::showHide(bool hide, bool userRequested) diff --git a/src/qt/modaloverlay.h b/src/qt/modaloverlay.h index 670c9e58ab3ec..66c0aa78cfb95 100644 --- a/src/qt/modaloverlay.h +++ b/src/qt/modaloverlay.h @@ -35,7 +35,8 @@ public Q_SLOTS: private: Ui::ModalOverlay *ui; - int bestBlockHeight; //best known height (based on the headers) + int bestHeaderHeight; //best known height (based on the headers) + QDateTime bestHeaderDate; QVector > blockProcessTime; bool layerIsVisible; bool userClosed; From 16f88230885bf962286c5a00fe092d3c56d4eab4 Mon Sep 17 00:00:00 2001 From: fanquake Date: Tue, 27 Sep 2016 10:34:54 +0800 Subject: [PATCH 0946/1802] [depends] Boost 1.61.0 --- depends/packages/boost.mk | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk index ef1307c241b66..4173c0d168f5b 100644 --- a/depends/packages/boost.mk +++ b/depends/packages/boost.mk @@ -1,8 +1,8 @@ package=boost -$(package)_version=1_59_0 -$(package)_download_path=http://sourceforge.net/projects/boost/files/boost/1.59.0 +$(package)_version=1_61_0 +$(package)_download_path=https://sourceforge.net/projects/boost/files/boost/1.61.0 $(package)_file_name=$(package)_$($(package)_version).tar.bz2 -$(package)_sha256_hash=727a932322d94287b62abb1bd2d41723eec4356a7728909e38adb65ca25241ca +$(package)_sha256_hash=a547bd06c2fd9a71ba1d169d9cf0339da7ebf4753849a8f7d6fdb8feee99b640 define $(package)_set_vars $(package)_config_opts_release=variant=release From 5776e8a5965f1d614516dc89da5fedb324baf62a Mon Sep 17 00:00:00 2001 From: fanquake Date: Tue, 27 Sep 2016 12:32:20 +0800 Subject: [PATCH 0947/1802] [depends] Fix Qt compilation with Xcode 8 --- depends/packages/qt.mk | 3 ++- depends/patches/qt/configure-xcoderun.patch | 25 +++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 depends/patches/qt/configure-xcoderun.patch diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index d41d0b9ea5b15..bdde15aa173df 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -8,7 +8,7 @@ $(package)_dependencies=openssl $(package)_linux_dependencies=freetype fontconfig libxcb libX11 xproto libXext $(package)_build_subdir=qtbase $(package)_qt_libs=corelib network widgets gui plugins testlib -$(package)_patches=mac-qmake.conf mingw-uuidof.patch pidlist_absolute.patch fix-xcb-include-order.patch fix_qt_pkgconfig.patch +$(package)_patches=mac-qmake.conf configure-xcoderun.patch mingw-uuidof.patch pidlist_absolute.patch fix-xcb-include-order.patch fix_qt_pkgconfig.patch $(package)_qttranslations_file_name=qttranslations-$($(package)_suffix) $(package)_qttranslations_sha256_hash=dcc1534d247babca1840cb6d0a000671801a341ea352d0535474f86adadaf028 @@ -134,6 +134,7 @@ define $(package)_preprocess_cmds 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 && \ + patch -p1 < $($(package)_patch_dir)/configure-xcoderun.patch && \ patch -p1 < $($(package)_patch_dir)/mingw-uuidof.patch && \ patch -p1 < $($(package)_patch_dir)/pidlist_absolute.patch && \ patch -p1 < $($(package)_patch_dir)/fix-xcb-include-order.patch && \ diff --git a/depends/patches/qt/configure-xcoderun.patch b/depends/patches/qt/configure-xcoderun.patch new file mode 100644 index 0000000000000..08286d8420bb3 --- /dev/null +++ b/depends/patches/qt/configure-xcoderun.patch @@ -0,0 +1,25 @@ +--- old/qtbase/configure ++++ new/qtbase/configure +@@ -543,7 +543,7 @@ if [ "$BUILD_ON_MAC" = "yes" ]; then + exit 2 + fi + +- if ! /usr/bin/xcrun -find xcrun >/dev/null 2>&1; then ++ if ! /usr/bin/xcrun -find xcodebuild >/dev/null 2>&1; then + echo >&2 + echo " Xcode not set up properly. You may need to confirm the license" >&2 + echo " agreement by running /usr/bin/xcodebuild without arguments." >&2 +diff --git a/mkspecs/features/mac/default_pre.prf b/mkspecs/features/mac/default_pre.prf +index 0cc8cd6..5df99d1 100644 +--- old/qtbase/mkspecs/features/mac/default_pre.prf ++++ new/qtbase/mkspecs/features/mac/default_pre.prf +@@ -12,7 +12,7 @@ isEmpty(QMAKE_XCODE_DEVELOPER_PATH) { + error("Xcode is not installed in $${QMAKE_XCODE_DEVELOPER_PATH}. Please use xcode-select to choose Xcode installation path.") + + # Make sure Xcode is set up properly +- isEmpty($$list($$system("/usr/bin/xcrun -find xcrun 2>/dev/null"))): \ ++ isEmpty($$list($$system("/usr/bin/xcrun -find xcodebuild 2>/dev/null"))): \ + error("Xcode not set up properly. You may need to confirm the license agreement by running /usr/bin/xcodebuild.") + } + +-- From 4731cab8fbff51a8178c85d572e2482040278616 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Fri, 2 Sep 2016 18:19:01 +0200 Subject: [PATCH 0948/1802] Do not shadow variables --- src/bloom.cpp | 8 +++---- src/key.cpp | 6 ++--- src/main.cpp | 28 ++++++++++++------------ src/pubkey.cpp | 6 ++--- src/pubkey.h | 4 ++-- src/reverselock.h | 6 ++--- src/rpc/blockchain.cpp | 8 +++---- src/rpc/mining.cpp | 4 ++-- src/support/pagelocker.h | 6 ++--- src/test/crypto_tests.cpp | 20 ++++++++--------- src/test/net_tests.cpp | 4 ++-- src/test/script_tests.cpp | 8 +++---- src/torcontrol.cpp | 46 +++++++++++++++++++-------------------- src/txmempool.cpp | 8 +++---- src/wallet/wallet.cpp | 16 +++++++------- 15 files changed, 89 insertions(+), 89 deletions(-) diff --git a/src/bloom.cpp b/src/bloom.cpp index fd328e8e96e53..2677652ada2ce 100644 --- a/src/bloom.cpp +++ b/src/bloom.cpp @@ -280,8 +280,8 @@ void CRollingBloomFilter::insert(const std::vector& vKey) void CRollingBloomFilter::insert(const uint256& hash) { - vector data(hash.begin(), hash.end()); - insert(data); + vector vData(hash.begin(), hash.end()); + insert(vData); } bool CRollingBloomFilter::contains(const std::vector& vKey) const @@ -300,8 +300,8 @@ bool CRollingBloomFilter::contains(const std::vector& vKey) const bool CRollingBloomFilter::contains(const uint256& hash) const { - vector data(hash.begin(), hash.end()); - return contains(data); + vector vData(hash.begin(), hash.end()); + return contains(vData); } void CRollingBloomFilter::reset() diff --git a/src/key.cpp b/src/key.cpp index 79023566c3e61..aae9b042ac6db 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -243,12 +243,12 @@ bool CKey::Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const return ret; } -bool CExtKey::Derive(CExtKey &out, unsigned int nChild) const { +bool CExtKey::Derive(CExtKey &out, unsigned int _nChild) const { out.nDepth = nDepth + 1; CKeyID id = key.GetPubKey().GetID(); memcpy(&out.vchFingerprint[0], &id, 4); - out.nChild = nChild; - return key.Derive(out.key, out.chaincode, nChild, chaincode); + out.nChild = _nChild; + return key.Derive(out.key, out.chaincode, _nChild, chaincode); } void CExtKey::SetMaster(const unsigned char *seed, unsigned int nSeedLen) { diff --git a/src/main.cpp b/src/main.cpp index 60bda426a67df..c33b41ac4eb75 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1185,9 +1185,9 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C bool fReplacementOptOut = true; if (fEnableReplacement) { - BOOST_FOREACH(const CTxIn &txin, ptxConflicting->vin) + BOOST_FOREACH(const CTxIn &_txin, ptxConflicting->vin) { - if (txin.nSequence < std::numeric_limits::max()-1) + if (_txin.nSequence < std::numeric_limits::max()-1) { fReplacementOptOut = false; break; @@ -2499,14 +2499,14 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (pindex->GetUndoPos().IsNull() || !pindex->IsValid(BLOCK_VALID_SCRIPTS)) { if (pindex->GetUndoPos().IsNull()) { - CDiskBlockPos pos; - if (!FindUndoPos(state, pindex->nFile, pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 40)) + CDiskBlockPos _pos; + if (!FindUndoPos(state, pindex->nFile, _pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 40)) return error("ConnectBlock(): FindUndoPos failed"); - if (!UndoWriteToDisk(blockundo, pos, pindex->pprev->GetBlockHash(), chainparams.MessageStart())) + if (!UndoWriteToDisk(blockundo, _pos, pindex->pprev->GetBlockHash(), chainparams.MessageStart())) return AbortNode(state, "Failed to write undo data"); // update nUndoPos in block index - pindex->nUndoPos = pos.nPos; + pindex->nUndoPos = _pos.nPos; pindex->nStatus |= BLOCK_HAVE_UNDO; } @@ -3819,10 +3819,10 @@ void PruneOneBlockFile(const int fileNumber) // mapBlocksUnlinked or setBlockIndexCandidates. std::pair::iterator, std::multimap::iterator> range = mapBlocksUnlinked.equal_range(pindex->pprev); while (range.first != range.second) { - std::multimap::iterator it = range.first; + std::multimap::iterator _it = range.first; range.first++; - if (it->second == pindex) { - mapBlocksUnlinked.erase(it); + if (_it->second == pindex) { + mapBlocksUnlinked.erase(_it); } } } @@ -5550,9 +5550,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } if (!fRejectedParents) { BOOST_FOREACH(const CTxIn& txin, tx.vin) { - CInv inv(MSG_TX, txin.prevout.hash); - pfrom->AddInventoryKnown(inv); - if (!AlreadyHave(inv)) pfrom->AskFor(inv); + CInv _inv(MSG_TX, txin.prevout.hash); + pfrom->AddInventoryKnown(_inv); + if (!AlreadyHave(_inv)) pfrom->AskFor(_inv); } AddOrphanTx(tx, pfrom->GetId()); @@ -6317,9 +6317,9 @@ class CompareInvMempoolOrder { CTxMemPool *mp; public: - CompareInvMempoolOrder(CTxMemPool *mempool) + CompareInvMempoolOrder(CTxMemPool *_mempool) { - mp = mempool; + mp = _mempool; } bool operator()(std::set::iterator a, std::set::iterator b) diff --git a/src/pubkey.cpp b/src/pubkey.cpp index be4ee27cd48d5..91a657593a4a6 100644 --- a/src/pubkey.cpp +++ b/src/pubkey.cpp @@ -264,12 +264,12 @@ void CExtPubKey::Decode(const unsigned char code[BIP32_EXTKEY_SIZE]) { pubkey.Set(code+41, code+BIP32_EXTKEY_SIZE); } -bool CExtPubKey::Derive(CExtPubKey &out, unsigned int nChild) const { +bool CExtPubKey::Derive(CExtPubKey &out, unsigned int _nChild) const { out.nDepth = nDepth + 1; CKeyID id = pubkey.GetID(); memcpy(&out.vchFingerprint[0], &id, 4); - out.nChild = nChild; - return pubkey.Derive(out.pubkey, out.chaincode, nChild, chaincode); + out.nChild = _nChild; + return pubkey.Derive(out.pubkey, out.chaincode, _nChild, chaincode); } /* static */ bool CPubKey::CheckLowS(const std::vector& vchSig) { diff --git a/src/pubkey.h b/src/pubkey.h index aebfdbc826628..3a554877f8000 100644 --- a/src/pubkey.h +++ b/src/pubkey.h @@ -88,9 +88,9 @@ class CPubKey } //! Construct a public key from a byte vector. - CPubKey(const std::vector& vch) + CPubKey(const std::vector& _vch) { - Set(vch.begin(), vch.end()); + Set(_vch.begin(), _vch.end()); } //! Simple read-only vector-like interface to the pubkey data. diff --git a/src/reverselock.h b/src/reverselock.h index fac1ccb7931ad..1fd8de5d80747 100644 --- a/src/reverselock.h +++ b/src/reverselock.h @@ -13,9 +13,9 @@ class reverse_lock { public: - explicit reverse_lock(Lock& lock) : lock(lock) { - lock.unlock(); - lock.swap(templock); + explicit reverse_lock(Lock& _lock) : lock(_lock) { + _lock.unlock(); + _lock.swap(templock); } ~reverse_lock() { diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index f05f8ff3587ad..91d3197cd0a26 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -497,10 +497,10 @@ UniValue getmempoolancestors(const UniValue& params, bool fHelp) UniValue o(UniValue::VOBJ); BOOST_FOREACH(CTxMemPool::txiter ancestorIt, setAncestors) { const CTxMemPoolEntry &e = *ancestorIt; - const uint256& hash = e.GetTx().GetHash(); + const uint256& _hash = e.GetTx().GetHash(); UniValue info(UniValue::VOBJ); entryToJSON(info, e); - o.push_back(Pair(hash.ToString(), info)); + o.push_back(Pair(_hash.ToString(), info)); } return o; } @@ -561,10 +561,10 @@ UniValue getmempooldescendants(const UniValue& params, bool fHelp) UniValue o(UniValue::VOBJ); BOOST_FOREACH(CTxMemPool::txiter descendantIt, setDescendants) { const CTxMemPoolEntry &e = *descendantIt; - const uint256& hash = e.GetTx().GetHash(); + const uint256& _hash = e.GetTx().GetHash(); UniValue info(UniValue::VOBJ); entryToJSON(info, e); - o.push_back(Pair(hash.ToString(), info)); + o.push_back(Pair(_hash.ToString(), info)); } return o; } diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 7794ac619d212..6b13aa5bab02a 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -607,8 +607,8 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) UniValue aRules(UniValue::VARR); UniValue vbavailable(UniValue::VOBJ); - for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++i) { - Consensus::DeploymentPos pos = Consensus::DeploymentPos(i); + for (int j = 0; j < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) { + Consensus::DeploymentPos pos = Consensus::DeploymentPos(j); ThresholdState state = VersionBitsState(pindexPrev, consensusParams, pos, versionbitscache); switch (state) { case THRESHOLD_DEFINED: diff --git a/src/support/pagelocker.h b/src/support/pagelocker.h index 6b3979e5513b1..538bf39453e39 100644 --- a/src/support/pagelocker.h +++ b/src/support/pagelocker.h @@ -28,11 +28,11 @@ template class LockedPageManagerBase { public: - LockedPageManagerBase(size_t page_size) : page_size(page_size) + LockedPageManagerBase(size_t _page_size) : page_size(_page_size) { // Determine bitmask for extracting page from address - assert(!(page_size & (page_size - 1))); // size must be power of two - page_mask = ~(page_size - 1); + assert(!(_page_size & (_page_size - 1))); // size must be power of two + page_mask = ~(_page_size - 1); } ~LockedPageManagerBase() diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index 58a62ee02262d..ff0adae1d22b7 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -133,13 +133,13 @@ void TestAES128CBC(const std::string &hexkey, const std::string &hexiv, bool pad { std::vector sub(i, in.end()); std::vector subout(sub.size() + AES_BLOCKSIZE); - int size = enc.Encrypt(&sub[0], sub.size(), &subout[0]); - if (size != 0) + int _size = enc.Encrypt(&sub[0], sub.size(), &subout[0]); + if (_size != 0) { - subout.resize(size); + subout.resize(_size); std::vector subdecrypted(subout.size()); - size = dec.Decrypt(&subout[0], subout.size(), &subdecrypted[0]); - subdecrypted.resize(size); + _size = dec.Decrypt(&subout[0], subout.size(), &subdecrypted[0]); + subdecrypted.resize(_size); BOOST_CHECK(decrypted.size() == in.size()); BOOST_CHECK_MESSAGE(subdecrypted == sub, HexStr(subdecrypted) + std::string(" != ") + HexStr(sub)); } @@ -174,13 +174,13 @@ void TestAES256CBC(const std::string &hexkey, const std::string &hexiv, bool pad { std::vector sub(i, in.end()); std::vector subout(sub.size() + AES_BLOCKSIZE); - int size = enc.Encrypt(&sub[0], sub.size(), &subout[0]); - if (size != 0) + int _size = enc.Encrypt(&sub[0], sub.size(), &subout[0]); + if (_size != 0) { - subout.resize(size); + subout.resize(_size); std::vector subdecrypted(subout.size()); - size = dec.Decrypt(&subout[0], subout.size(), &subdecrypted[0]); - subdecrypted.resize(size); + _size = dec.Decrypt(&subout[0], subout.size(), &subdecrypted[0]); + subdecrypted.resize(_size); BOOST_CHECK(decrypted.size() == in.size()); BOOST_CHECK_MESSAGE(subdecrypted == sub, HexStr(subdecrypted) + std::string(" != ") + HexStr(sub)); } diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index 680708533e475..4a7d6e778f5dc 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -62,11 +62,11 @@ class CAddrManCorrupted : public CAddrManSerializationMock } }; -CDataStream AddrmanToStream(CAddrManSerializationMock& addrman) +CDataStream AddrmanToStream(CAddrManSerializationMock& _addrman) { CDataStream ssPeersIn(SER_DISK, CLIENT_VERSION); ssPeersIn << FLATDATA(Params().MessageStart()); - ssPeersIn << addrman; + ssPeersIn << _addrman; std::string str = ssPeersIn.str(); vector vchData(str.begin(), str.end()); return CDataStream(vchData, SER_DISK, CLIENT_VERSION); diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 5a9aaf9bc0738..dad82baed5cda 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -323,10 +323,10 @@ class TestBuilder return *this; } - TestBuilder& Add(const CScript& script) + TestBuilder& Add(const CScript& _script) { DoPush(); - spendTx.vin[0].scriptSig += script; + spendTx.vin[0].scriptSig += _script; return *this; } @@ -343,8 +343,8 @@ class TestBuilder return *this; } - TestBuilder& Push(const CScript& script) { - DoPush(std::vector(script.begin(), script.end())); + TestBuilder& Push(const CScript& _script) { + DoPush(std::vector(_script.begin(), _script.end())); return *this; } diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index 99c45d489cb21..1ca6b4656661e 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -122,8 +122,8 @@ class TorControlConnection static void eventcb(struct bufferevent *bev, short what, void *ctx); }; -TorControlConnection::TorControlConnection(struct event_base *base): - base(base), b_conn(0) +TorControlConnection::TorControlConnection(struct event_base *_base): + base(_base), b_conn(0) { } @@ -194,7 +194,7 @@ void TorControlConnection::eventcb(struct bufferevent *bev, short what, void *ct } } -bool TorControlConnection::Connect(const std::string &target, const ConnectionCB& connected, const ConnectionCB& disconnected) +bool TorControlConnection::Connect(const std::string &target, const ConnectionCB& _connected, const ConnectionCB& _disconnected) { if (b_conn) Disconnect(); @@ -213,8 +213,8 @@ bool TorControlConnection::Connect(const std::string &target, const ConnectionCB return false; bufferevent_setcb(b_conn, TorControlConnection::readcb, NULL, TorControlConnection::eventcb, this); bufferevent_enable(b_conn, EV_READ|EV_WRITE); - this->connected = connected; - this->disconnected = disconnected; + this->connected = _connected; + this->disconnected = _disconnected; // Finally, connect to target if (bufferevent_socket_connect(b_conn, (struct sockaddr*)&connect_to_addr, connect_to_addrlen) < 0) { @@ -394,18 +394,18 @@ class TorController static void reconnect_cb(evutil_socket_t fd, short what, void *arg); }; -TorController::TorController(struct event_base* baseIn, const std::string& target): - base(baseIn), - target(target), conn(base), reconnect(true), reconnect_ev(0), +TorController::TorController(struct event_base* _base, const std::string& _target): + base(_base), + target(_target), conn(base), reconnect(true), reconnect_ev(0), reconnect_timeout(RECONNECT_TIMEOUT_START) { reconnect_ev = event_new(base, -1, 0, reconnect_cb, this); if (!reconnect_ev) LogPrintf("tor: Failed to create event for reconnection: out of memory?\n"); // Start connection attempts immediately - if (!conn.Connect(target, boost::bind(&TorController::connected_cb, this, _1), + if (!conn.Connect(_target, boost::bind(&TorController::connected_cb, this, _1), boost::bind(&TorController::disconnected_cb, this, _1) )) { - LogPrintf("tor: Initiating connection to Tor control port %s failed\n", target); + LogPrintf("tor: Initiating connection to Tor control port %s failed\n", _target); } // Read service private key if cached std::pair pkf = ReadBinaryFile(GetPrivateKeyFile()); @@ -426,7 +426,7 @@ TorController::~TorController() } } -void TorController::add_onion_cb(TorControlConnection& conn, const TorControlReply& reply) +void TorController::add_onion_cb(TorControlConnection& _conn, const TorControlReply& reply) { if (reply.code == 250) { LogPrint("tor", "tor: ADD_ONION successful\n"); @@ -454,7 +454,7 @@ void TorController::add_onion_cb(TorControlConnection& conn, const TorControlRep } } -void TorController::auth_cb(TorControlConnection& conn, const TorControlReply& reply) +void TorController::auth_cb(TorControlConnection& _conn, const TorControlReply& reply) { if (reply.code == 250) { LogPrint("tor", "tor: Authentication successful\n"); @@ -474,7 +474,7 @@ void TorController::auth_cb(TorControlConnection& conn, const TorControlReply& r // Request hidden service, redirect port. // Note that the 'virtual' port doesn't have to be the same as our internal port, but this is just a convenient // choice. TODO; refactor the shutdown sequence some day. - conn.Command(strprintf("ADD_ONION %s Port=%i,127.0.0.1:%i", private_key, GetListenPort(), GetListenPort()), + _conn.Command(strprintf("ADD_ONION %s Port=%i,127.0.0.1:%i", private_key, GetListenPort(), GetListenPort()), boost::bind(&TorController::add_onion_cb, this, _1, _2)); } else { LogPrintf("tor: Authentication failed\n"); @@ -508,7 +508,7 @@ static std::vector ComputeResponse(const std::string &key, const std::v return computedHash; } -void TorController::authchallenge_cb(TorControlConnection& conn, const TorControlReply& reply) +void TorController::authchallenge_cb(TorControlConnection& _conn, const TorControlReply& reply) { if (reply.code == 250) { LogPrint("tor", "tor: SAFECOOKIE authentication challenge successful\n"); @@ -530,7 +530,7 @@ void TorController::authchallenge_cb(TorControlConnection& conn, const TorContro } std::vector computedClientHash = ComputeResponse(TOR_SAFE_CLIENTKEY, cookie, clientNonce, serverNonce); - conn.Command("AUTHENTICATE " + HexStr(computedClientHash), boost::bind(&TorController::auth_cb, this, _1, _2)); + _conn.Command("AUTHENTICATE " + HexStr(computedClientHash), boost::bind(&TorController::auth_cb, this, _1, _2)); } else { LogPrintf("tor: Invalid reply to AUTHCHALLENGE\n"); } @@ -539,7 +539,7 @@ void TorController::authchallenge_cb(TorControlConnection& conn, const TorContro } } -void TorController::protocolinfo_cb(TorControlConnection& conn, const TorControlReply& reply) +void TorController::protocolinfo_cb(TorControlConnection& _conn, const TorControlReply& reply) { if (reply.code == 250) { std::set methods; @@ -579,23 +579,23 @@ void TorController::protocolinfo_cb(TorControlConnection& conn, const TorControl if (methods.count("HASHEDPASSWORD")) { LogPrint("tor", "tor: Using HASHEDPASSWORD authentication\n"); boost::replace_all(torpassword, "\"", "\\\""); - conn.Command("AUTHENTICATE \"" + torpassword + "\"", boost::bind(&TorController::auth_cb, this, _1, _2)); + _conn.Command("AUTHENTICATE \"" + torpassword + "\"", boost::bind(&TorController::auth_cb, this, _1, _2)); } else { LogPrintf("tor: Password provided with -torpassword, but HASHEDPASSWORD authentication is not available\n"); } } else if (methods.count("NULL")) { LogPrint("tor", "tor: Using NULL authentication\n"); - conn.Command("AUTHENTICATE", boost::bind(&TorController::auth_cb, this, _1, _2)); + _conn.Command("AUTHENTICATE", boost::bind(&TorController::auth_cb, this, _1, _2)); } else if (methods.count("SAFECOOKIE")) { // Cookie: hexdump -e '32/1 "%02x""\n"' ~/.tor/control_auth_cookie LogPrint("tor", "tor: Using SAFECOOKIE authentication, reading cookie authentication from %s\n", cookiefile); std::pair status_cookie = ReadBinaryFile(cookiefile, TOR_COOKIE_SIZE); if (status_cookie.first && status_cookie.second.size() == TOR_COOKIE_SIZE) { - // conn.Command("AUTHENTICATE " + HexStr(status_cookie.second), boost::bind(&TorController::auth_cb, this, _1, _2)); + // _conn.Command("AUTHENTICATE " + HexStr(status_cookie.second), boost::bind(&TorController::auth_cb, this, _1, _2)); cookie = std::vector(status_cookie.second.begin(), status_cookie.second.end()); clientNonce = std::vector(TOR_NONCE_SIZE, 0); GetRandBytes(&clientNonce[0], TOR_NONCE_SIZE); - conn.Command("AUTHCHALLENGE SAFECOOKIE " + HexStr(clientNonce), boost::bind(&TorController::authchallenge_cb, this, _1, _2)); + _conn.Command("AUTHCHALLENGE SAFECOOKIE " + HexStr(clientNonce), boost::bind(&TorController::authchallenge_cb, this, _1, _2)); } else { if (status_cookie.first) { LogPrintf("tor: Authentication cookie %s is not exactly %i bytes, as is required by the spec\n", cookiefile, TOR_COOKIE_SIZE); @@ -613,15 +613,15 @@ void TorController::protocolinfo_cb(TorControlConnection& conn, const TorControl } } -void TorController::connected_cb(TorControlConnection& conn) +void TorController::connected_cb(TorControlConnection& _conn) { reconnect_timeout = RECONNECT_TIMEOUT_START; // First send a PROTOCOLINFO command to figure out what authentication is expected - if (!conn.Command("PROTOCOLINFO 1", boost::bind(&TorController::protocolinfo_cb, this, _1, _2))) + if (!_conn.Command("PROTOCOLINFO 1", boost::bind(&TorController::protocolinfo_cb, this, _1, _2))) LogPrintf("tor: Error sending initial protocolinfo command\n"); } -void TorController::disconnected_cb(TorControlConnection& conn) +void TorController::disconnected_cb(TorControlConnection& _conn) { // Stop advertising service when disconnected if (service.IsValid()) diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 0a00d757a225a..3586123d3e00d 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -1116,8 +1116,8 @@ void CTxMemPool::TrimToSize(size_t sizelimit, std::vector* pvNoSpendsRe std::vector txn; if (pvNoSpendsRemaining) { txn.reserve(stage.size()); - BOOST_FOREACH(txiter it, stage) - txn.push_back(it->GetTx()); + BOOST_FOREACH(txiter iter, stage) + txn.push_back(iter->GetTx()); } RemoveStaged(stage, false); if (pvNoSpendsRemaining) { @@ -1125,8 +1125,8 @@ void CTxMemPool::TrimToSize(size_t sizelimit, std::vector* pvNoSpendsRe BOOST_FOREACH(const CTxIn& txin, tx.vin) { if (exists(txin.prevout.hash)) continue; - auto it = mapNextTx.lower_bound(COutPoint(txin.prevout.hash, 0)); - if (it == mapNextTx.end() || it->first->hash != txin.prevout.hash) + auto iter = mapNextTx.lower_bound(COutPoint(txin.prevout.hash, 0)); + if (iter == mapNextTx.end() || iter->first->hash != txin.prevout.hash) pvNoSpendsRemaining->push_back(txin.prevout.hash); } } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 50d63182ae181..85219c24c8d78 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -401,8 +401,8 @@ set CWallet::GetConflicts(const uint256& txid) const if (mapTxSpends.count(txin.prevout) <= 1) continue; // No conflict if zero or one spends range = mapTxSpends.equal_range(txin.prevout); - for (TxSpends::const_iterator it = range.first; it != range.second; ++it) - result.insert(it->second); + for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it) + result.insert(_it->second); } return result; } @@ -1281,9 +1281,9 @@ int CWalletTx::GetRequestCount() const // How about the block it's in? if (nRequests == 0 && !hashUnset()) { - map::const_iterator mi = pwallet->mapRequestCount.find(hashBlock); - if (mi != pwallet->mapRequestCount.end()) - nRequests = (*mi).second; + map::const_iterator _mi = pwallet->mapRequestCount.find(hashBlock); + if (_mi != pwallet->mapRequestCount.end()) + nRequests = (*_mi).second; else nRequests = 1; // If it's in someone else's block it must have got out } @@ -2938,17 +2938,17 @@ set< set > CWallet::GetAddressGroupings() set< set* > uniqueGroupings; // a set of pointers to groups of addresses map< CTxDestination, set* > setmap; // map addresses to the unique group containing it - BOOST_FOREACH(set grouping, groupings) + BOOST_FOREACH(set _grouping, groupings) { // make a set of all the groups hit by this new group set< set* > hits; map< CTxDestination, set* >::iterator it; - BOOST_FOREACH(CTxDestination address, grouping) + BOOST_FOREACH(CTxDestination address, _grouping) if ((it = setmap.find(address)) != setmap.end()) hits.insert((*it).second); // merge all hit groups into a new single group and delete old groups - set* merged = new set(grouping); + set* merged = new set(_grouping); BOOST_FOREACH(set* hit, hits) { merged->insert(hit->begin(), hit->end()); From ac01ff22bed73993261983b355c7cb3e2f3cb7cf Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 27 Sep 2016 15:03:12 +0200 Subject: [PATCH 0949/1802] doc: Add privacy recommendation when running hidden service --- doc/tor.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/doc/tor.md b/doc/tor.md index 79f1563021094..2f376af4c7a7f 100644 --- a/doc/tor.md +++ b/doc/tor.md @@ -113,4 +113,13 @@ the user running bitcoind to the same group and setting permissions appropriatel Debian-based systems the user running bitcoind can be added to the debian-tor group, which has the appropriate permissions. An alternative authentication method is the use of the `-torpassword` flag and a `hash-password` which can be enabled and specified in -Tor configuration. \ No newline at end of file +Tor configuration. + +4. Privacy recommendations +--------------------------- + +- Do not add anything but bitcoin ports to the hidden service created in section 2. + If you run a web service too, create a new hidden service for that. + Otherwise it is trivial to link them, which may reduce privacy. Hidden + services created automatically (as in section 3) always have only one port + open. From e41bd449ab2b8d01260795383af2c40b659d8587 Mon Sep 17 00:00:00 2001 From: Johnson Lau Date: Thu, 22 Sep 2016 15:06:54 +0800 Subject: [PATCH 0950/1802] Add policy: null signature for failed CHECK(MULTI)SIG --- src/policy/policy.h | 1 + src/script/interpreter.cpp | 14 +++++++++++++- src/script/interpreter.h | 4 ++++ src/script/script_error.cpp | 2 ++ src/script/script_error.h | 1 + src/test/data/script_tests.json | 33 ++++++++++++++++++++++++++++++++- src/test/script_tests.cpp | 1 + src/test/transaction_tests.cpp | 1 + 8 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/policy/policy.h b/src/policy/policy.h index 458ec4a0cb4aa..9d6ff1233b6aa 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -43,6 +43,7 @@ static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS | SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_MINIMALIF | + SCRIPT_VERIFY_NULLFAIL | SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY | SCRIPT_VERIFY_CHECKSEQUENCEVERIFY | SCRIPT_VERIFY_LOW_S | diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index fd356fed0ab43..41756ea71196d 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -885,6 +885,9 @@ bool EvalScript(vector >& stack, const CScript& script, un } bool fSuccess = checker.CheckSig(vchSig, vchPubKey, scriptCode, sigversion); + if (!fSuccess && (flags & SCRIPT_VERIFY_NULLFAIL) && vchSig.size()) + return set_error(serror, SCRIPT_ERR_SIG_NULLFAIL); + popstack(stack); popstack(stack); stack.push_back(fSuccess ? vchTrue : vchFalse); @@ -914,6 +917,9 @@ bool EvalScript(vector >& stack, const CScript& script, un if (nOpCount > MAX_OPS_PER_SCRIPT) return set_error(serror, SCRIPT_ERR_OP_COUNT); int ikey = ++i; + // ikey2 is the position of last non-signature item in the stack. Top stack item = 1. + // With SCRIPT_VERIFY_NULLFAIL, this is used for cleanup if operation fails. + int ikey2 = nKeysCount + 2; i += nKeysCount; if ((int)stack.size() < i) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); @@ -970,8 +976,14 @@ bool EvalScript(vector >& stack, const CScript& script, un } // Clean up stack of actual arguments - while (i-- > 1) + while (i-- > 1) { + // If the operation failed, we require that all signatures must be empty vector + if (!fSuccess && (flags & SCRIPT_VERIFY_NULLFAIL) && !ikey2 && stacktop(-1).size()) + return set_error(serror, SCRIPT_ERR_SIG_NULLFAIL); + if (ikey2 > 0) + ikey2--; popstack(stack); + } // A bug causes CHECKMULTISIG to consume one extra argument // whose contents were not checked in any way. diff --git a/src/script/interpreter.h b/src/script/interpreter.h index 2ce4b23e54f62..0adc9482ffec6 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -98,6 +98,10 @@ enum // Segwit script only: Require the argument of OP_IF/NOTIF to be exactly 0x01 or empty vector // SCRIPT_VERIFY_MINIMALIF = (1U << 13), + + // Signature(s) must be empty vector if an CHECK(MULTI)SIG operation failed + // + SCRIPT_VERIFY_NULLFAIL = (1U << 14), }; bool CheckSignatureEncoding(const std::vector &vchSig, unsigned int flags, ScriptError* serror); diff --git a/src/script/script_error.cpp b/src/script/script_error.cpp index 9969c232fc340..e27b715c2cfea 100644 --- a/src/script/script_error.cpp +++ b/src/script/script_error.cpp @@ -65,6 +65,8 @@ const char* ScriptErrorString(const ScriptError serror) return "Dummy CHECKMULTISIG argument must be zero"; case SCRIPT_ERR_MINIMALIF: return "OP_IF/NOTIF argument must be minimal"; + case SCRIPT_ERR_SIG_NULLFAIL: + return "Signature must be zero for failed CHECK(MULTI)SIG operation"; case SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS: return "NOPx reserved for soft-fork upgrades"; case SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM: diff --git a/src/script/script_error.h b/src/script/script_error.h index 6d34d37925bcf..bccfdb99e23bb 100644 --- a/src/script/script_error.h +++ b/src/script/script_error.h @@ -49,6 +49,7 @@ typedef enum ScriptError_t SCRIPT_ERR_PUBKEYTYPE, SCRIPT_ERR_CLEANSTACK, SCRIPT_ERR_MINIMALIF, + SCRIPT_ERR_SIG_NULLFAIL, /* softfork safeness */ SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS, diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json index d456a8beffd67..06103ea5bdd66 100644 --- a/src/test/data/script_tests.json +++ b/src/test/data/script_tests.json @@ -1491,6 +1491,27 @@ "OK", "BIP66 example 4, with DERSIG" ], +[ + "0x09 0x300602010102010101", + "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", + "DERSIG", + "OK", + "BIP66 example 4, with DERSIG, non-null DER-compliant signature" +], +[ + "0", + "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", + "DERSIG,NULLFAIL", + "OK", + "BIP66 example 4, with DERSIG and NULLFAIL" +], +[ + "0x09 0x300602010102010101", + "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", + "DERSIG,NULLFAIL", + "NULLFAIL", + "BIP66 example 4, with DERSIG and NULLFAIL, non-null DER-compliant signature" +], [ "1", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", @@ -2208,5 +2229,15 @@ [["645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS", "UNBALANCED_CONDITIONAL"], [["645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS,MINIMALIF", "UNBALANCED_CONDITIONAL"], - ["The End"] +["NULLFAIL should cover all signatures and signatures only"], +["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG", "OK", "BIP66 and NULLFAIL-compliant"], +["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "OK", "BIP66 and NULLFAIL-compliant"], +["1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "OK", "BIP66 and NULLFAIL-compliant, not NULLDUMMY-compliant"], +["1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL,NULLDUMMY", "SIG_NULLDUMMY", "BIP66 and NULLFAIL-compliant, not NULLDUMMY-compliant"], +["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0x09 0x300602010102010101", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG", "OK", "BIP66-compliant but not NULLFAIL-compliant"], +["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0x09 0x300602010102010101", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "NULLFAIL", "BIP66-compliant but not NULLFAIL-compliant"], +["0 0x09 0x300602010102010101 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG", "OK", "BIP66-compliant but not NULLFAIL-compliant"], +["0 0x09 0x300602010102010101 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "NULLFAIL", "BIP66-compliant but not NULLFAIL-compliant"], + +["The End"] ] diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index ee0f14ee5e896..7971b5122ffc9 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -90,6 +90,7 @@ static ScriptErrorDesc script_errors[]={ {SCRIPT_ERR_PUBKEYTYPE, "PUBKEYTYPE"}, {SCRIPT_ERR_CLEANSTACK, "CLEANSTACK"}, {SCRIPT_ERR_MINIMALIF, "MINIMALIF"}, + {SCRIPT_ERR_SIG_NULLFAIL, "NULLFAIL"}, {SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS, "DISCOURAGE_UPGRADABLE_NOPS"}, {SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM, "DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"}, {SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH, "WITNESS_PROGRAM_WRONG_LENGTH"}, diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 165dfd9a3e06b..6163d2f630604 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -51,6 +51,7 @@ static std::map mapFlagNames = boost::assign::map_list_of (string("DISCOURAGE_UPGRADABLE_NOPS"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) (string("CLEANSTACK"), (unsigned int)SCRIPT_VERIFY_CLEANSTACK) (string("MINIMALIF"), (unsigned int)SCRIPT_VERIFY_MINIMALIF) + (string("NULLFAIL"), (unsigned int)SCRIPT_VERIFY_NULLFAIL) (string("CHECKLOCKTIMEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY) (string("CHECKSEQUENCEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKSEQUENCEVERIFY) (string("WITNESS"), (unsigned int)SCRIPT_VERIFY_WITNESS) From 41e58faf043864a64a6db08a8df527fa5fd1ec5b Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 27 Sep 2016 14:05:24 +0200 Subject: [PATCH 0951/1802] net: Consistent checksum handling In principle, the checksums of P2P packets are simply 4-byte blobs which are the first four bytes of SHA256(SHA256(payload)). Currently they are handled as little-endian 32-bit integers half of the time, as blobs the other half, sometimes copying the one to the other, resulting in somewhat confused code. This PR changes the handling to be consistent both at packet creation and receiving, making it (I think) easier to understand. --- src/main.cpp | 9 +++++---- src/net.cpp | 6 ++---- src/protocol.cpp | 4 ++-- src/protocol.h | 4 ++-- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index c33b41ac4eb75..ab672197144e6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6253,11 +6253,12 @@ bool ProcessMessages(CNode* pfrom, CConnman& connman) // Checksum CDataStream& vRecv = msg.vRecv; uint256 hash = Hash(vRecv.begin(), vRecv.begin() + nMessageSize); - unsigned int nChecksum = ReadLE32((unsigned char*)&hash); - if (nChecksum != hdr.nChecksum) + if (memcmp(hash.begin(), hdr.pchChecksum, CMessageHeader::CHECKSUM_SIZE) != 0) { - LogPrintf("%s(%s, %u bytes): CHECKSUM ERROR nChecksum=%08x hdr.nChecksum=%08x\n", __func__, - SanitizeString(strCommand), nMessageSize, nChecksum, hdr.nChecksum); + LogPrintf("%s(%s, %u bytes): CHECKSUM ERROR expected %s was %s\n", __func__, + SanitizeString(strCommand), nMessageSize, + HexStr(hash.begin(), hash.begin()+CMessageHeader::CHECKSUM_SIZE), + HexStr(hdr.pchChecksum, hdr.pchChecksum+CMessageHeader::CHECKSUM_SIZE)); continue; } diff --git a/src/net.cpp b/src/net.cpp index cce06f2d64cf0..770e2d2959998 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2661,10 +2661,8 @@ void CNode::EndMessage(const char* pszCommand) UNLOCK_FUNCTION(cs_vSend) // Set the checksum uint256 hash = Hash(ssSend.begin() + CMessageHeader::HEADER_SIZE, ssSend.end()); - unsigned int nChecksum = 0; - memcpy(&nChecksum, &hash, sizeof(nChecksum)); - assert(ssSend.size () >= CMessageHeader::CHECKSUM_OFFSET + sizeof(nChecksum)); - memcpy((char*)&ssSend[CMessageHeader::CHECKSUM_OFFSET], &nChecksum, sizeof(nChecksum)); + assert(ssSend.size () >= CMessageHeader::CHECKSUM_OFFSET + CMessageHeader::CHECKSUM_SIZE); + memcpy((char*)&ssSend[CMessageHeader::CHECKSUM_OFFSET], hash.begin(), CMessageHeader::CHECKSUM_SIZE); LogPrint("net", "(%d bytes) peer=%d\n", nSize, id); diff --git a/src/protocol.cpp b/src/protocol.cpp index 247c6c212073e..54ad62b1a2a95 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -79,7 +79,7 @@ CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn) memcpy(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE); memset(pchCommand, 0, sizeof(pchCommand)); nMessageSize = -1; - nChecksum = 0; + memset(pchChecksum, 0, CHECKSUM_SIZE); } CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn, const char* pszCommand, unsigned int nMessageSizeIn) @@ -88,7 +88,7 @@ CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn, const memset(pchCommand, 0, sizeof(pchCommand)); strncpy(pchCommand, pszCommand, COMMAND_SIZE); nMessageSize = nMessageSizeIn; - nChecksum = 0; + memset(pchChecksum, 0, CHECKSUM_SIZE); } std::string CMessageHeader::GetCommand() const diff --git a/src/protocol.h b/src/protocol.h index 9b474ec79c8dd..177d74530815c 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -45,7 +45,7 @@ class CMessageHeader READWRITE(FLATDATA(pchMessageStart)); READWRITE(FLATDATA(pchCommand)); READWRITE(nMessageSize); - READWRITE(nChecksum); + READWRITE(FLATDATA(pchChecksum)); } // TODO: make private (improves encapsulation) @@ -62,7 +62,7 @@ class CMessageHeader char pchMessageStart[MESSAGE_START_SIZE]; char pchCommand[COMMAND_SIZE]; unsigned int nMessageSize; - unsigned int nChecksum; + uint8_t pchChecksum[CHECKSUM_SIZE]; }; /** From 305087bdf640a5c0b3eeeb90d33ee255d2456eba Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 28 Sep 2016 15:33:45 +0200 Subject: [PATCH 0952/1802] net: Hardcode protocol sizes and use fixed-size types The P2P network uses a fixed protocol, these sizes shouldn't change based on what happens to be the architecture. --- src/protocol.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/protocol.h b/src/protocol.h index 177d74530815c..1bc1c25b3714f 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -52,8 +52,8 @@ class CMessageHeader public: enum { COMMAND_SIZE = 12, - MESSAGE_SIZE_SIZE = sizeof(int), - CHECKSUM_SIZE = sizeof(int), + MESSAGE_SIZE_SIZE = 4, + CHECKSUM_SIZE = 4, MESSAGE_SIZE_OFFSET = MESSAGE_START_SIZE + COMMAND_SIZE, CHECKSUM_OFFSET = MESSAGE_SIZE_OFFSET + MESSAGE_SIZE_SIZE, @@ -61,7 +61,7 @@ class CMessageHeader }; char pchMessageStart[MESSAGE_START_SIZE]; char pchCommand[COMMAND_SIZE]; - unsigned int nMessageSize; + uint32_t nMessageSize; uint8_t pchChecksum[CHECKSUM_SIZE]; }; From 7e5fd7198e3b1fae65e1feec7dae7c0083e28203 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Wed, 28 Sep 2016 16:40:20 +0200 Subject: [PATCH 0953/1802] Do not include env_win.cc on non-Windows systems --- src/Makefile.leveldb.include | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Makefile.leveldb.include b/src/Makefile.leveldb.include index 4b3cd6364a29b..6f25fd005e78a 100644 --- a/src/Makefile.leveldb.include +++ b/src/Makefile.leveldb.include @@ -113,7 +113,6 @@ leveldb_libleveldb_a_SOURCES += leveldb/util/comparator.cc leveldb_libleveldb_a_SOURCES += leveldb/util/crc32c.cc leveldb_libleveldb_a_SOURCES += leveldb/util/env.cc leveldb_libleveldb_a_SOURCES += leveldb/util/env_posix.cc -leveldb_libleveldb_a_SOURCES += leveldb/util/env_win.cc leveldb_libleveldb_a_SOURCES += leveldb/util/filter_policy.cc leveldb_libleveldb_a_SOURCES += leveldb/util/hash.cc leveldb_libleveldb_a_SOURCES += leveldb/util/histogram.cc From a0f8482f3e9b07e37c3f1b6fa09683b448810955 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Wed, 28 Sep 2016 11:08:08 -0400 Subject: [PATCH 0954/1802] [qa] Split up slow RPC calls to avoid pruning test timeouts --- qa/rpc-tests/pruning.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/qa/rpc-tests/pruning.py b/qa/rpc-tests/pruning.py index 7cbe69c29b2b9..287dbc776e1b2 100755 --- a/qa/rpc-tests/pruning.py +++ b/qa/rpc-tests/pruning.py @@ -157,7 +157,10 @@ def reorg_test(self): print("Usage possibly still high bc of stale blocks in block files:", calc_usage(self.prunedir)) print("Mine 220 more blocks so we have requisite history (some blocks will be big and cause pruning of previous chain)") - self.nodes[0].generate(220) #node 0 has many large tx's in its mempool from the disconnects + for i in range(22): + # This can be slow, so do this in multiple RPC calls to avoid + # RPC timeouts. + self.nodes[0].generate(10) #node 0 has many large tx's in its mempool from the disconnects sync_blocks(self.nodes[0:3], timeout=300) usage = calc_usage(self.prunedir) From 54e5d7c1b81e1b76f5789abfa2cb1f5963cd9d72 Mon Sep 17 00:00:00 2001 From: jnewbery Date: Wed, 28 Sep 2016 13:36:36 -0400 Subject: [PATCH 0955/1802] Add bitcoin-tx JSON tests --- src/test/data/bitcoin-util-test.json | 85 ++++++++- src/test/data/blanktx.json | 10 + src/test/data/tt-delin1-out.json | 216 ++++++++++++++++++++++ src/test/data/tt-delout1-out.json | 212 +++++++++++++++++++++ src/test/data/tt-locktime317000-out.json | 225 +++++++++++++++++++++++ src/test/data/txcreate1.json | 63 +++++++ src/test/data/txcreate2.json | 0 src/test/data/txcreatedata1.json | 41 +++++ src/test/data/txcreatedata2.json | 41 +++++ src/test/data/txcreatedata_seq0.json | 32 ++++ src/test/data/txcreatedata_seq1.json | 41 +++++ src/test/data/txcreatesign.json | 32 ++++ 12 files changed, 997 insertions(+), 1 deletion(-) create mode 100644 src/test/data/blanktx.json create mode 100644 src/test/data/tt-delin1-out.json create mode 100644 src/test/data/tt-delout1-out.json create mode 100644 src/test/data/tt-locktime317000-out.json create mode 100644 src/test/data/txcreate1.json create mode 100644 src/test/data/txcreate2.json create mode 100644 src/test/data/txcreatedata1.json create mode 100644 src/test/data/txcreatedata2.json create mode 100644 src/test/data/txcreatedata_seq0.json create mode 100644 src/test/data/txcreatedata_seq1.json create mode 100644 src/test/data/txcreatesign.json diff --git a/src/test/data/bitcoin-util-test.json b/src/test/data/bitcoin-util-test.json index 5cb383de85a06..9df61a7e7932e 100644 --- a/src/test/data/bitcoin-util-test.json +++ b/src/test/data/bitcoin-util-test.json @@ -1,18 +1,32 @@ [ - { "exec": "././bitcoin-tx", + { "exec": "./bitcoin-tx", "args": ["-create"], "output_cmp": "blanktx.hex" }, + { "exec": "./bitcoin-tx", + "args": ["-json","-create"], + "output_cmp": "blanktx.json" + }, { "exec": "./bitcoin-tx", "args": ["-"], "input": "blanktx.hex", "output_cmp": "blanktx.hex" }, + { "exec": "./bitcoin-tx", + "args": ["-json","-"], + "input": "blanktx.hex", + "output_cmp": "blanktx.json" + }, { "exec": "./bitcoin-tx", "args": ["-", "delin=1"], "input": "tx394b54bb.hex", "output_cmp": "tt-delin1-out.hex" }, + { "exec": "./bitcoin-tx", + "args": ["-json", "-", "delin=1"], + "input": "tx394b54bb.hex", + "output_cmp": "tt-delin1-out.json" + }, { "exec": "./bitcoin-tx", "args": ["-", "delin=31"], "input": "tx394b54bb.hex", @@ -23,6 +37,11 @@ "input": "tx394b54bb.hex", "output_cmp": "tt-delout1-out.hex" }, + { "exec": "./bitcoin-tx", + "args": ["-json", "-", "delout=1"], + "input": "tx394b54bb.hex", + "output_cmp": "tt-delout1-out.json" + }, { "exec": "./bitcoin-tx", "args": ["-", "delout=2"], "input": "tx394b54bb.hex", @@ -33,6 +52,11 @@ "input": "tx394b54bb.hex", "output_cmp": "tt-locktime317000-out.hex" }, + { "exec": "./bitcoin-tx", + "args": ["-json", "-", "locktime=317000"], + "input": "tx394b54bb.hex", + "output_cmp": "tt-locktime317000-out.json" + }, { "exec": "./bitcoin-tx", "args": ["-create", @@ -43,10 +67,25 @@ "outaddr=4:1P8yWvZW8jVihP1bzHeqfE4aoXNX8AVa46"], "output_cmp": "txcreate1.hex" }, + { "exec": "./bitcoin-tx", + "args": + ["-json", + "-create", + "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", + "in=bf829c6bcf84579331337659d31f89dfd138f7f7785802d5501c92333145ca7c:18", + "in=22a6f904655d53ae2ff70e701a0bbd90aa3975c0f40bfc6cc996a9049e31cdfc:1", + "outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o", + "outaddr=4:1P8yWvZW8jVihP1bzHeqfE4aoXNX8AVa46"], + "output_cmp": "txcreate1.json" + }, { "exec": "./bitcoin-tx", "args": ["-create", "outscript=0:"], "output_cmp": "txcreate2.hex" }, + { "exec": "./bitcoin-tx", + "args": ["-json", "-create", "outscript=0:"], + "output_cmp": "txcreate2.json" + }, { "exec": "./bitcoin-tx", "args": ["-create", @@ -57,6 +96,17 @@ "outaddr=0.001:193P6LtvS4nCnkDvM9uXn1gsSRqh4aDAz7"], "output_cmp": "txcreatesign.hex" }, + { "exec": "./bitcoin-tx", + "args": + ["-json", + "-create", + "in=4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485:0", + "set=privatekeys:[\"5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf\"]", + "set=prevtxs:[{\"txid\":\"4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485\",\"vout\":0,\"scriptPubKey\":\"76a91491b24bf9f5288532960ac687abb035127b1d28a588ac\"}]", + "sign=ALL", + "outaddr=0.001:193P6LtvS4nCnkDvM9uXn1gsSRqh4aDAz7"], + "output_cmp": "txcreatesign.json" + }, { "exec": "./bitcoin-tx", "args": ["-create", @@ -79,6 +129,15 @@ "outdata=4:54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e"], "output_cmp": "txcreatedata1.hex" }, + { "exec": "./bitcoin-tx", + "args": + ["-json", + "-create", + "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", + "outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o", + "outdata=4:54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e"], + "output_cmp": "txcreatedata1.json" + }, { "exec": "./bitcoin-tx", "args": ["-create", @@ -87,6 +146,15 @@ "outdata=54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e"], "output_cmp": "txcreatedata2.hex" }, + { "exec": "./bitcoin-tx", + "args": + ["-json", + "-create", + "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", + "outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o", + "outdata=54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e"], + "output_cmp": "txcreatedata2.json" + }, { "exec": "./bitcoin-tx", "args": ["-create", @@ -94,10 +162,25 @@ "outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o"], "output_cmp": "txcreatedata_seq0.hex" }, + { "exec": "./bitcoin-tx", + "args": + ["-json", + "-create", + "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0:4294967293", + "outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o"], + "output_cmp": "txcreatedata_seq0.json" + }, { "exec": "./bitcoin-tx", "args": ["01000000011f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000fdffffff0180a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac00000000", "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0:1"], "output_cmp": "txcreatedata_seq1.hex" + }, + { "exec": "./bitcoin-tx", + "args": + ["-json", + "01000000011f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000fdffffff0180a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac00000000", + "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0:1"], + "output_cmp": "txcreatedata_seq1.json" } ] diff --git a/src/test/data/blanktx.json b/src/test/data/blanktx.json new file mode 100644 index 0000000000000..f6d6ab58842c7 --- /dev/null +++ b/src/test/data/blanktx.json @@ -0,0 +1,10 @@ +{ + "txid": "d21633ba23f70118185227be58a63527675641ad37967e2aa461559f577aec43", + "version": 1, + "locktime": 0, + "vin": [ + ], + "vout": [ + ], + "hex": "01000000000000000000" +} diff --git a/src/test/data/tt-delin1-out.json b/src/test/data/tt-delin1-out.json new file mode 100644 index 0000000000000..2c7a68636a2fb --- /dev/null +++ b/src/test/data/tt-delin1-out.json @@ -0,0 +1,216 @@ +{ + "txid": "81b2035be1da1abe745c6141174a73d151009ec17b3d5ebffa2e177408c50dfd", + "version": 1, + "locktime": 0, + "vin": [ + { + "txid": "27871a1a27d833e99cd392a502a647beaaeda6da535417501c76312d52235cfd", + "vout": 332, + "scriptSig": { + "asm": "3046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "752f7f69b915637dc1c2f7aed1466ad676f6f3e24cf922809705f664e97ab3c1", + "vout": 1, + "scriptSig": { + "asm": "3044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba[ALL] 027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34", + "hex": "473044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34" + }, + "sequence": 4294967295 + }, + { + "txid": "b0ac9cca2e69cd02410e31b1f4402a25758e71abd1ab06c265ef9077dc05d0ed", + "vout": 209, + "scriptSig": { + "asm": "304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "48304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "a135eafb595eaf4c1ea59ccb111cdc0eae1b2c979b226a1e5aa8b76fe2d628df", + "vout": 0, + "scriptSig": { + "asm": "3045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374[ALL] 03a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52", + "hex": "483045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52" + }, + "sequence": 4294967295 + }, + { + "txid": "a5d6bf53ba21140b8a4d554feb00fe8bb9a62430ff9e4624aa2f58a120232aae", + "vout": 1, + "scriptSig": { + "asm": "3046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "1b299cf14f1a22e81ea56d71b7affbd7cf386807bf2b4d4b79a18a54125accb3", + "vout": 0, + "scriptSig": { + "asm": "3045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967[ALL] 03a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52", + "hex": "483045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52" + }, + "sequence": 4294967295 + }, + { + "txid": "071df1cdcb3f0070f9d6af7b0274f02d0be2324a274727cfd288383167531485", + "vout": 21, + "scriptSig": { + "asm": "3045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "483045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "b012e500eb7adf7a13ed332dd6ece849f94f7a62bb3eac5babab356d1fc19282", + "vout": 9, + "scriptSig": { + "asm": "304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "58840fee9c833f2f2d40575842f30f4b8d2553094d06ad88b03d06869acf3d88", + "vout": 30, + "scriptSig": { + "asm": "30440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "4730440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "e69f9cd16946e570a665245354428a3f507ea69f4568b581e4af98edb3db9766", + "vout": 114, + "scriptSig": { + "asm": "304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "47304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "595d1257f654ed2cbe5a65421e8aefd2b4d70b5b6c89a03f1d7e518221fc3f02", + "vout": 103, + "scriptSig": { + "asm": "3046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "06fc818f9555a261248ecd7aad0993eafb5a82ceb2b5c87c3ddfb06671c7f816", + "vout": 1, + "scriptSig": { + "asm": "3045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec7669018[ALL] 0234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd", + "hex": "483045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec766901801210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd" + }, + "sequence": 4294967295 + }, + { + "txid": "fb416c8155d6bb1d43f9395466ca90a638a7c2dd3ff617aadf3a7ac8f3967b19", + "vout": 0, + "scriptSig": { + "asm": "304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a[ALL] 027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34", + "hex": "49304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34" + }, + "sequence": 4294967295 + }, + { + "txid": "3940b9683bd6104ad24c978e640ba4095993cafdb27d2ed91baa27ee61a2d920", + "vout": 221, + "scriptSig": { + "asm": "3045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "483045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "711b5714d3b5136147c02194cd95bde94a4648c4263ca6f972d86cd1d579f150", + "vout": 1, + "scriptSig": { + "asm": "3045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba9074[ALL] 0234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd", + "hex": "483045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba907401210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd" + }, + "sequence": 4294967295 + }, + { + "txid": "6364b5c5efe018430789e7fb4e338209546cae5d9c5f5e300aac68155d861b55", + "vout": 27, + "scriptSig": { + "asm": "304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "0bb57f6e38012c86d4c5a28c904f2675082859147921a707d48961015a3e5057", + "vout": 1095, + "scriptSig": { + "asm": "304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "9b34274814a2540bb062107117f8f3e75ef85d953e9372d8261a3e9dfbc1163f", + "vout": 37, + "scriptSig": { + "asm": "3045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "483045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "b86b5cc0d8a7374d94e277850b0a249cb26a7b42ddf014f28a49b8859da64241", + "vout": 20, + "scriptSig": { + "asm": "304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "3d0a2353eeec44d3c10aed259038db321912122cd4150048f7bfa4c0ecfee236", + "vout": 242, + "scriptSig": { + "asm": "3046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + } + ], + "vout": [ + { + "value": 1.3782, + "n": 0, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 8fd139bb39ced713f231c58a4d07bf6954d1c201 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9148fd139bb39ced713f231c58a4d07bf6954d1c20188ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "1E7SGgAZFCHDnVZLuRViX3gUmxpMfdvd2o" + ] + } + }, + { + "value": 0.01000001, + "n": 1, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 6c772e9cf96371bba3da8cb733da70a2fcf20078 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9146c772e9cf96371bba3da8cb733da70a2fcf2007888ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "1AtWkdmfmYkErU16d3KYykJUbEp9MAj9Sb" + ] + } + } + ], + "hex": "0100000014fd5c23522d31761c50175453daa6edaabe47a602a592d39ce933d8271a1a87274c0100006c493046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffc1b37ae964f605978022f94ce2f3f676d66a46d1aef7c2c17d6315b9697f2f75010000006a473044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34ffffffffedd005dc7790ef65c206abd1ab718e75252a40f4b1310e4102cd692eca9cacb0d10000006b48304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffdf28d6e26fb7a85a1e6a229b972c1bae0edc1c11cb9ca51e4caf5e59fbea35a1000000006b483045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52ffffffffae2a2320a1582faa24469eff3024a6b98bfe00eb4f554d8a0b1421ba53bfd6a5010000006c493046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffb3cc5a12548aa1794b4d2bbf076838cfd7fbafb7716da51ee8221a4ff19c291b000000006b483045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52ffffffff85145367313888d2cf2747274a32e20b2df074027bafd6f970003fcbcdf11d07150000006b483045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff8292c11f6d35abab5bac3ebb627a4ff949e8ecd62d33ed137adf7aeb00e512b0090000006b48304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff883dcf9a86063db088ad064d0953258d4b0ff3425857402d2f3f839cee0f84581e0000006a4730440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff6697dbb3ed98afe481b568459fa67e503f8a4254532465a670e54669d19c9fe6720000006a47304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff023ffc2182517e1d3fa0896c5b0bd7b4d2ef8a1e42655abe2ced54f657125d59670000006c493046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff16f8c77166b0df3d7cc8b5b2ce825afbea9309ad7acd8e2461a255958f81fc06010000006b483045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec766901801210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cdffffffff197b96f3c87a3adfaa17f63fddc2a738a690ca665439f9431dbbd655816c41fb000000006c49304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34ffffffff20d9a261ee27aa1bd92e7db2fdca935909a40b648e974cd24a10d63b68b94039dd0000006b483045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff50f179d5d16cd872f9a63c26c448464ae9bd95cd9421c0476113b5d314571b71010000006b483045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba907401210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cdffffffff551b865d1568ac0a305e5f9c5dae6c540982334efbe789074318e0efc5b564631b0000006b48304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff57503e5a016189d407a721791459280875264f908ca2c5d4862c01386e7fb50b470400006b48304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff3f16c1fb9d3e1a26d872933e955df85ee7f3f817711062b00b54a2144827349b250000006b483045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff4142a69d85b8498af214f0dd427b6ab29c240a0b8577e2944d37a7d8c05c6bb8140000006b48304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff36e2feecc0a4bff7480015d42c12121932db389025ed0ac1d344ecee53230a3df20000006c493046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff0260f73608000000001976a9148fd139bb39ced713f231c58a4d07bf6954d1c20188ac41420f00000000001976a9146c772e9cf96371bba3da8cb733da70a2fcf2007888ac00000000" +} diff --git a/src/test/data/tt-delout1-out.json b/src/test/data/tt-delout1-out.json new file mode 100644 index 0000000000000..9cf8cbb16c01e --- /dev/null +++ b/src/test/data/tt-delout1-out.json @@ -0,0 +1,212 @@ +{ + "txid": "c46ccd75b5050e942b2e86a3648f843f525fe6fc000bf0534ba5973063354493", + "version": 1, + "locktime": 0, + "vin": [ + { + "txid": "27871a1a27d833e99cd392a502a647beaaeda6da535417501c76312d52235cfd", + "vout": 332, + "scriptSig": { + "asm": "3046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "a72ec96bd0d022d1b0c2f9078cdd46b3725b8eecdd001e17b21e3ababad14ecb", + "vout": 0, + "scriptSig": { + "asm": "3046022100a9b617843b68c284715d3e02fd120479cd0d96a6c43bf01e697fb0a460a21a3a022100ba0a12fbe8b993d4e7911fa3467615765dbe421ddf5c51b57a9c1ee19dcc00ba[ALL] 03e633b4fa4ceb705c2da712390767199be8ef2448b3095dc01652e11b2b751505", + "hex": "493046022100a9b617843b68c284715d3e02fd120479cd0d96a6c43bf01e697fb0a460a21a3a022100ba0a12fbe8b993d4e7911fa3467615765dbe421ddf5c51b57a9c1ee19dcc00ba012103e633b4fa4ceb705c2da712390767199be8ef2448b3095dc01652e11b2b751505" + }, + "sequence": 4294967295 + }, + { + "txid": "752f7f69b915637dc1c2f7aed1466ad676f6f3e24cf922809705f664e97ab3c1", + "vout": 1, + "scriptSig": { + "asm": "3044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba[ALL] 027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34", + "hex": "473044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34" + }, + "sequence": 4294967295 + }, + { + "txid": "b0ac9cca2e69cd02410e31b1f4402a25758e71abd1ab06c265ef9077dc05d0ed", + "vout": 209, + "scriptSig": { + "asm": "304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "48304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "a135eafb595eaf4c1ea59ccb111cdc0eae1b2c979b226a1e5aa8b76fe2d628df", + "vout": 0, + "scriptSig": { + "asm": "3045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374[ALL] 03a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52", + "hex": "483045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52" + }, + "sequence": 4294967295 + }, + { + "txid": "a5d6bf53ba21140b8a4d554feb00fe8bb9a62430ff9e4624aa2f58a120232aae", + "vout": 1, + "scriptSig": { + "asm": "3046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "1b299cf14f1a22e81ea56d71b7affbd7cf386807bf2b4d4b79a18a54125accb3", + "vout": 0, + "scriptSig": { + "asm": "3045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967[ALL] 03a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52", + "hex": "483045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52" + }, + "sequence": 4294967295 + }, + { + "txid": "071df1cdcb3f0070f9d6af7b0274f02d0be2324a274727cfd288383167531485", + "vout": 21, + "scriptSig": { + "asm": "3045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "483045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "b012e500eb7adf7a13ed332dd6ece849f94f7a62bb3eac5babab356d1fc19282", + "vout": 9, + "scriptSig": { + "asm": "304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "58840fee9c833f2f2d40575842f30f4b8d2553094d06ad88b03d06869acf3d88", + "vout": 30, + "scriptSig": { + "asm": "30440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "4730440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "e69f9cd16946e570a665245354428a3f507ea69f4568b581e4af98edb3db9766", + "vout": 114, + "scriptSig": { + "asm": "304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "47304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "595d1257f654ed2cbe5a65421e8aefd2b4d70b5b6c89a03f1d7e518221fc3f02", + "vout": 103, + "scriptSig": { + "asm": "3046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "06fc818f9555a261248ecd7aad0993eafb5a82ceb2b5c87c3ddfb06671c7f816", + "vout": 1, + "scriptSig": { + "asm": "3045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec7669018[ALL] 0234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd", + "hex": "483045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec766901801210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd" + }, + "sequence": 4294967295 + }, + { + "txid": "fb416c8155d6bb1d43f9395466ca90a638a7c2dd3ff617aadf3a7ac8f3967b19", + "vout": 0, + "scriptSig": { + "asm": "304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a[ALL] 027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34", + "hex": "49304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34" + }, + "sequence": 4294967295 + }, + { + "txid": "3940b9683bd6104ad24c978e640ba4095993cafdb27d2ed91baa27ee61a2d920", + "vout": 221, + "scriptSig": { + "asm": "3045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "483045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "711b5714d3b5136147c02194cd95bde94a4648c4263ca6f972d86cd1d579f150", + "vout": 1, + "scriptSig": { + "asm": "3045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba9074[ALL] 0234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd", + "hex": "483045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba907401210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd" + }, + "sequence": 4294967295 + }, + { + "txid": "6364b5c5efe018430789e7fb4e338209546cae5d9c5f5e300aac68155d861b55", + "vout": 27, + "scriptSig": { + "asm": "304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "0bb57f6e38012c86d4c5a28c904f2675082859147921a707d48961015a3e5057", + "vout": 1095, + "scriptSig": { + "asm": "304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "9b34274814a2540bb062107117f8f3e75ef85d953e9372d8261a3e9dfbc1163f", + "vout": 37, + "scriptSig": { + "asm": "3045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "483045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "b86b5cc0d8a7374d94e277850b0a249cb26a7b42ddf014f28a49b8859da64241", + "vout": 20, + "scriptSig": { + "asm": "304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "3d0a2353eeec44d3c10aed259038db321912122cd4150048f7bfa4c0ecfee236", + "vout": 242, + "scriptSig": { + "asm": "3046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + } + ], + "vout": [ + { + "value": 1.3782, + "n": 0, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 8fd139bb39ced713f231c58a4d07bf6954d1c201 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9148fd139bb39ced713f231c58a4d07bf6954d1c20188ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "1E7SGgAZFCHDnVZLuRViX3gUmxpMfdvd2o" + ] + } + } + ], + "hex": "0100000015fd5c23522d31761c50175453daa6edaabe47a602a592d39ce933d8271a1a87274c0100006c493046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffcb4ed1baba3a1eb2171e00ddec8e5b72b346dd8c07f9c2b0d122d0d06bc92ea7000000006c493046022100a9b617843b68c284715d3e02fd120479cd0d96a6c43bf01e697fb0a460a21a3a022100ba0a12fbe8b993d4e7911fa3467615765dbe421ddf5c51b57a9c1ee19dcc00ba012103e633b4fa4ceb705c2da712390767199be8ef2448b3095dc01652e11b2b751505ffffffffc1b37ae964f605978022f94ce2f3f676d66a46d1aef7c2c17d6315b9697f2f75010000006a473044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34ffffffffedd005dc7790ef65c206abd1ab718e75252a40f4b1310e4102cd692eca9cacb0d10000006b48304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffdf28d6e26fb7a85a1e6a229b972c1bae0edc1c11cb9ca51e4caf5e59fbea35a1000000006b483045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52ffffffffae2a2320a1582faa24469eff3024a6b98bfe00eb4f554d8a0b1421ba53bfd6a5010000006c493046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffb3cc5a12548aa1794b4d2bbf076838cfd7fbafb7716da51ee8221a4ff19c291b000000006b483045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52ffffffff85145367313888d2cf2747274a32e20b2df074027bafd6f970003fcbcdf11d07150000006b483045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff8292c11f6d35abab5bac3ebb627a4ff949e8ecd62d33ed137adf7aeb00e512b0090000006b48304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff883dcf9a86063db088ad064d0953258d4b0ff3425857402d2f3f839cee0f84581e0000006a4730440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff6697dbb3ed98afe481b568459fa67e503f8a4254532465a670e54669d19c9fe6720000006a47304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff023ffc2182517e1d3fa0896c5b0bd7b4d2ef8a1e42655abe2ced54f657125d59670000006c493046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff16f8c77166b0df3d7cc8b5b2ce825afbea9309ad7acd8e2461a255958f81fc06010000006b483045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec766901801210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cdffffffff197b96f3c87a3adfaa17f63fddc2a738a690ca665439f9431dbbd655816c41fb000000006c49304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34ffffffff20d9a261ee27aa1bd92e7db2fdca935909a40b648e974cd24a10d63b68b94039dd0000006b483045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff50f179d5d16cd872f9a63c26c448464ae9bd95cd9421c0476113b5d314571b71010000006b483045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba907401210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cdffffffff551b865d1568ac0a305e5f9c5dae6c540982334efbe789074318e0efc5b564631b0000006b48304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff57503e5a016189d407a721791459280875264f908ca2c5d4862c01386e7fb50b470400006b48304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff3f16c1fb9d3e1a26d872933e955df85ee7f3f817711062b00b54a2144827349b250000006b483045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff4142a69d85b8498af214f0dd427b6ab29c240a0b8577e2944d37a7d8c05c6bb8140000006b48304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff36e2feecc0a4bff7480015d42c12121932db389025ed0ac1d344ecee53230a3df20000006c493046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff0160f73608000000001976a9148fd139bb39ced713f231c58a4d07bf6954d1c20188ac00000000" +} diff --git a/src/test/data/tt-locktime317000-out.json b/src/test/data/tt-locktime317000-out.json new file mode 100644 index 0000000000000..65b6a4451b26a --- /dev/null +++ b/src/test/data/tt-locktime317000-out.json @@ -0,0 +1,225 @@ +{ + "txid": "aded538f642c17e15f4d3306b8be7e1a4d1ae0c4616d641ab51ea09ba65e5cb5", + "version": 1, + "locktime": 317000, + "vin": [ + { + "txid": "27871a1a27d833e99cd392a502a647beaaeda6da535417501c76312d52235cfd", + "vout": 332, + "scriptSig": { + "asm": "3046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "a72ec96bd0d022d1b0c2f9078cdd46b3725b8eecdd001e17b21e3ababad14ecb", + "vout": 0, + "scriptSig": { + "asm": "3046022100a9b617843b68c284715d3e02fd120479cd0d96a6c43bf01e697fb0a460a21a3a022100ba0a12fbe8b993d4e7911fa3467615765dbe421ddf5c51b57a9c1ee19dcc00ba[ALL] 03e633b4fa4ceb705c2da712390767199be8ef2448b3095dc01652e11b2b751505", + "hex": "493046022100a9b617843b68c284715d3e02fd120479cd0d96a6c43bf01e697fb0a460a21a3a022100ba0a12fbe8b993d4e7911fa3467615765dbe421ddf5c51b57a9c1ee19dcc00ba012103e633b4fa4ceb705c2da712390767199be8ef2448b3095dc01652e11b2b751505" + }, + "sequence": 4294967295 + }, + { + "txid": "752f7f69b915637dc1c2f7aed1466ad676f6f3e24cf922809705f664e97ab3c1", + "vout": 1, + "scriptSig": { + "asm": "3044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba[ALL] 027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34", + "hex": "473044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34" + }, + "sequence": 4294967295 + }, + { + "txid": "b0ac9cca2e69cd02410e31b1f4402a25758e71abd1ab06c265ef9077dc05d0ed", + "vout": 209, + "scriptSig": { + "asm": "304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "48304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "a135eafb595eaf4c1ea59ccb111cdc0eae1b2c979b226a1e5aa8b76fe2d628df", + "vout": 0, + "scriptSig": { + "asm": "3045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374[ALL] 03a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52", + "hex": "483045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52" + }, + "sequence": 4294967295 + }, + { + "txid": "a5d6bf53ba21140b8a4d554feb00fe8bb9a62430ff9e4624aa2f58a120232aae", + "vout": 1, + "scriptSig": { + "asm": "3046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "1b299cf14f1a22e81ea56d71b7affbd7cf386807bf2b4d4b79a18a54125accb3", + "vout": 0, + "scriptSig": { + "asm": "3045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967[ALL] 03a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52", + "hex": "483045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52" + }, + "sequence": 4294967295 + }, + { + "txid": "071df1cdcb3f0070f9d6af7b0274f02d0be2324a274727cfd288383167531485", + "vout": 21, + "scriptSig": { + "asm": "3045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "483045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "b012e500eb7adf7a13ed332dd6ece849f94f7a62bb3eac5babab356d1fc19282", + "vout": 9, + "scriptSig": { + "asm": "304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "58840fee9c833f2f2d40575842f30f4b8d2553094d06ad88b03d06869acf3d88", + "vout": 30, + "scriptSig": { + "asm": "30440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "4730440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "e69f9cd16946e570a665245354428a3f507ea69f4568b581e4af98edb3db9766", + "vout": 114, + "scriptSig": { + "asm": "304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "47304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "595d1257f654ed2cbe5a65421e8aefd2b4d70b5b6c89a03f1d7e518221fc3f02", + "vout": 103, + "scriptSig": { + "asm": "3046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "06fc818f9555a261248ecd7aad0993eafb5a82ceb2b5c87c3ddfb06671c7f816", + "vout": 1, + "scriptSig": { + "asm": "3045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec7669018[ALL] 0234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd", + "hex": "483045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec766901801210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd" + }, + "sequence": 4294967295 + }, + { + "txid": "fb416c8155d6bb1d43f9395466ca90a638a7c2dd3ff617aadf3a7ac8f3967b19", + "vout": 0, + "scriptSig": { + "asm": "304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a[ALL] 027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34", + "hex": "49304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34" + }, + "sequence": 4294967295 + }, + { + "txid": "3940b9683bd6104ad24c978e640ba4095993cafdb27d2ed91baa27ee61a2d920", + "vout": 221, + "scriptSig": { + "asm": "3045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "483045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "711b5714d3b5136147c02194cd95bde94a4648c4263ca6f972d86cd1d579f150", + "vout": 1, + "scriptSig": { + "asm": "3045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba9074[ALL] 0234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd", + "hex": "483045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba907401210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd" + }, + "sequence": 4294967295 + }, + { + "txid": "6364b5c5efe018430789e7fb4e338209546cae5d9c5f5e300aac68155d861b55", + "vout": 27, + "scriptSig": { + "asm": "304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "0bb57f6e38012c86d4c5a28c904f2675082859147921a707d48961015a3e5057", + "vout": 1095, + "scriptSig": { + "asm": "304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "9b34274814a2540bb062107117f8f3e75ef85d953e9372d8261a3e9dfbc1163f", + "vout": 37, + "scriptSig": { + "asm": "3045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "483045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "b86b5cc0d8a7374d94e277850b0a249cb26a7b42ddf014f28a49b8859da64241", + "vout": 20, + "scriptSig": { + "asm": "304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "3d0a2353eeec44d3c10aed259038db321912122cd4150048f7bfa4c0ecfee236", + "vout": 242, + "scriptSig": { + "asm": "3046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + } + ], + "vout": [ + { + "value": 1.3782, + "n": 0, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 8fd139bb39ced713f231c58a4d07bf6954d1c201 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9148fd139bb39ced713f231c58a4d07bf6954d1c20188ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "1E7SGgAZFCHDnVZLuRViX3gUmxpMfdvd2o" + ] + } + }, + { + "value": 0.01000001, + "n": 1, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 6c772e9cf96371bba3da8cb733da70a2fcf20078 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9146c772e9cf96371bba3da8cb733da70a2fcf2007888ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "1AtWkdmfmYkErU16d3KYykJUbEp9MAj9Sb" + ] + } + } + ], + "hex": "0100000015fd5c23522d31761c50175453daa6edaabe47a602a592d39ce933d8271a1a87274c0100006c493046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffcb4ed1baba3a1eb2171e00ddec8e5b72b346dd8c07f9c2b0d122d0d06bc92ea7000000006c493046022100a9b617843b68c284715d3e02fd120479cd0d96a6c43bf01e697fb0a460a21a3a022100ba0a12fbe8b993d4e7911fa3467615765dbe421ddf5c51b57a9c1ee19dcc00ba012103e633b4fa4ceb705c2da712390767199be8ef2448b3095dc01652e11b2b751505ffffffffc1b37ae964f605978022f94ce2f3f676d66a46d1aef7c2c17d6315b9697f2f75010000006a473044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34ffffffffedd005dc7790ef65c206abd1ab718e75252a40f4b1310e4102cd692eca9cacb0d10000006b48304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffdf28d6e26fb7a85a1e6a229b972c1bae0edc1c11cb9ca51e4caf5e59fbea35a1000000006b483045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52ffffffffae2a2320a1582faa24469eff3024a6b98bfe00eb4f554d8a0b1421ba53bfd6a5010000006c493046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffb3cc5a12548aa1794b4d2bbf076838cfd7fbafb7716da51ee8221a4ff19c291b000000006b483045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52ffffffff85145367313888d2cf2747274a32e20b2df074027bafd6f970003fcbcdf11d07150000006b483045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff8292c11f6d35abab5bac3ebb627a4ff949e8ecd62d33ed137adf7aeb00e512b0090000006b48304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff883dcf9a86063db088ad064d0953258d4b0ff3425857402d2f3f839cee0f84581e0000006a4730440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff6697dbb3ed98afe481b568459fa67e503f8a4254532465a670e54669d19c9fe6720000006a47304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff023ffc2182517e1d3fa0896c5b0bd7b4d2ef8a1e42655abe2ced54f657125d59670000006c493046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff16f8c77166b0df3d7cc8b5b2ce825afbea9309ad7acd8e2461a255958f81fc06010000006b483045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec766901801210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cdffffffff197b96f3c87a3adfaa17f63fddc2a738a690ca665439f9431dbbd655816c41fb000000006c49304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34ffffffff20d9a261ee27aa1bd92e7db2fdca935909a40b648e974cd24a10d63b68b94039dd0000006b483045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff50f179d5d16cd872f9a63c26c448464ae9bd95cd9421c0476113b5d314571b71010000006b483045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba907401210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cdffffffff551b865d1568ac0a305e5f9c5dae6c540982334efbe789074318e0efc5b564631b0000006b48304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff57503e5a016189d407a721791459280875264f908ca2c5d4862c01386e7fb50b470400006b48304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff3f16c1fb9d3e1a26d872933e955df85ee7f3f817711062b00b54a2144827349b250000006b483045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff4142a69d85b8498af214f0dd427b6ab29c240a0b8577e2944d37a7d8c05c6bb8140000006b48304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff36e2feecc0a4bff7480015d42c12121932db389025ed0ac1d344ecee53230a3df20000006c493046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff0260f73608000000001976a9148fd139bb39ced713f231c58a4d07bf6954d1c20188ac41420f00000000001976a9146c772e9cf96371bba3da8cb733da70a2fcf2007888ac48d60400" +} diff --git a/src/test/data/txcreate1.json b/src/test/data/txcreate1.json new file mode 100644 index 0000000000000..3890dbaf6e096 --- /dev/null +++ b/src/test/data/txcreate1.json @@ -0,0 +1,63 @@ +{ + "txid": "f70f0d6c71416ed538e37549f430ab3665fee2437a42f10238c1bd490e782231", + "version": 1, + "locktime": 0, + "vin": [ + { + "txid": "5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f", + "vout": 0, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 4294967295 + }, + { + "txid": "bf829c6bcf84579331337659d31f89dfd138f7f7785802d5501c92333145ca7c", + "vout": 18, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 4294967295 + }, + { + "txid": "22a6f904655d53ae2ff70e701a0bbd90aa3975c0f40bfc6cc996a9049e31cdfc", + "vout": 1, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 4294967295 + } + ], + "vout": [ + { + "value": 0.18, + "n": 0, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "13tuJJDR2RgArmgfv6JScSdreahzgc4T6o" + ] + } + }, + { + "value": 4.00, + "n": 1, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 f2d4db28cad6502226ee484ae24505c2885cb12d OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a914f2d4db28cad6502226ee484ae24505c2885cb12d88ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "1P8yWvZW8jVihP1bzHeqfE4aoXNX8AVa46" + ] + } + } + ], + "hex": "01000000031f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000ffffffff7cca453133921c50d5025878f7f738d1df891fd359763331935784cf6b9c82bf1200000000fffffffffccd319e04a996c96cfc0bf4c07539aa90bd0b1a700ef72fae535d6504f9a6220100000000ffffffff0280a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac0084d717000000001976a914f2d4db28cad6502226ee484ae24505c2885cb12d88ac00000000" +} diff --git a/src/test/data/txcreate2.json b/src/test/data/txcreate2.json new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/src/test/data/txcreatedata1.json b/src/test/data/txcreatedata1.json new file mode 100644 index 0000000000000..2fed228108728 --- /dev/null +++ b/src/test/data/txcreatedata1.json @@ -0,0 +1,41 @@ +{ + "txid": "07894b4d12fe7853dd911402db1620920d261b9627c447f931417d330c25f06e", + "version": 1, + "locktime": 0, + "vin": [ + { + "txid": "5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f", + "vout": 0, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 4294967295 + } + ], + "vout": [ + { + "value": 0.18, + "n": 0, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "13tuJJDR2RgArmgfv6JScSdreahzgc4T6o" + ] + } + }, + { + "value": 4.00, + "n": 1, + "scriptPubKey": { + "asm": "OP_RETURN 54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e", + "hex": "6a4c4f54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e", + "type": "nulldata" + } + } + ], + "hex": "01000000011f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000ffffffff0280a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac0084d71700000000526a4c4f54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e00000000" +} diff --git a/src/test/data/txcreatedata2.json b/src/test/data/txcreatedata2.json new file mode 100644 index 0000000000000..3d4d367f37be5 --- /dev/null +++ b/src/test/data/txcreatedata2.json @@ -0,0 +1,41 @@ +{ + "txid": "4ed17118f5e932ba8c75c461787d171bc02a016d8557cb5bcf34cd416c27bb8b", + "version": 1, + "locktime": 0, + "vin": [ + { + "txid": "5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f", + "vout": 0, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 4294967295 + } + ], + "vout": [ + { + "value": 0.18, + "n": 0, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "13tuJJDR2RgArmgfv6JScSdreahzgc4T6o" + ] + } + }, + { + "value": 0.00, + "n": 1, + "scriptPubKey": { + "asm": "OP_RETURN 54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e", + "hex": "6a4c4f54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e", + "type": "nulldata" + } + } + ], + "hex": "01000000011f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000ffffffff0280a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac0000000000000000526a4c4f54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e00000000" +} diff --git a/src/test/data/txcreatedata_seq0.json b/src/test/data/txcreatedata_seq0.json new file mode 100644 index 0000000000000..f25aa43c2b275 --- /dev/null +++ b/src/test/data/txcreatedata_seq0.json @@ -0,0 +1,32 @@ +{ + "txid": "71603ccb1cd76d73d76eb6cfd5f0b9df6d65d90d76860ee52cb461c4be7032e8", + "version": 1, + "locktime": 0, + "vin": [ + { + "txid": "5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f", + "vout": 0, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 4294967293 + } + ], + "vout": [ + { + "value": 0.18, + "n": 0, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "13tuJJDR2RgArmgfv6JScSdreahzgc4T6o" + ] + } + } + ], + "hex": "01000000011f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000fdffffff0180a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac00000000" +} diff --git a/src/test/data/txcreatedata_seq1.json b/src/test/data/txcreatedata_seq1.json new file mode 100644 index 0000000000000..33585d6dfad82 --- /dev/null +++ b/src/test/data/txcreatedata_seq1.json @@ -0,0 +1,41 @@ +{ + "txid": "c4dea671b0d7b48f8ab10bc46650e8329d3c5766931f548f513847a19f5ba75b", + "version": 1, + "locktime": 0, + "vin": [ + { + "txid": "5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f", + "vout": 0, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 4294967293 + }, + { + "txid": "5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f", + "vout": 0, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 1 + } + ], + "vout": [ + { + "value": 0.18, + "n": 0, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "13tuJJDR2RgArmgfv6JScSdreahzgc4T6o" + ] + } + } + ], + "hex": "01000000021f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000fdffffff1f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000010000000180a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac00000000" +} diff --git a/src/test/data/txcreatesign.json b/src/test/data/txcreatesign.json new file mode 100644 index 0000000000000..057fe9b010292 --- /dev/null +++ b/src/test/data/txcreatesign.json @@ -0,0 +1,32 @@ +{ + "txid": "977e7cd286cb72cd470d539ba6cb48400f8f387d97451d45cdb8819437a303af", + "version": 1, + "locktime": 0, + "vin": [ + { + "txid": "4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485", + "vout": 0, + "scriptSig": { + "asm": "304502210096a75056c9e2cc62b7214777b3d2a592cfda7092520126d4ebfcd6d590c99bd8022051bb746359cf98c0603f3004477eac68701132380db8facba19c89dc5ab5c5e2[ALL] 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", + "hex": "48304502210096a75056c9e2cc62b7214777b3d2a592cfda7092520126d4ebfcd6d590c99bd8022051bb746359cf98c0603f3004477eac68701132380db8facba19c89dc5ab5c5e201410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8" + }, + "sequence": 4294967295 + } + ], + "vout": [ + { + "value": 0.001, + "n": 0, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 5834479edbbe0539b31ffd3a8f8ebadc2165ed01 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9145834479edbbe0539b31ffd3a8f8ebadc2165ed0188ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "193P6LtvS4nCnkDvM9uXn1gsSRqh4aDAz7" + ] + } + } + ], + "hex": "01000000018594c5bdcaec8f06b78b596f31cd292a294fd031e24eec716f43dac91ea7494d000000008b48304502210096a75056c9e2cc62b7214777b3d2a592cfda7092520126d4ebfcd6d590c99bd8022051bb746359cf98c0603f3004477eac68701132380db8facba19c89dc5ab5c5e201410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ffffffff01a0860100000000001976a9145834479edbbe0539b31ffd3a8f8ebadc2165ed0188ac00000000" +} From fa05cfdf256f3bc13b89ea80231e342f4302d204 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 28 Sep 2016 21:05:11 +0200 Subject: [PATCH 0956/1802] [rpc] throw JSONRPCError when utxo set can not be read --- src/rpc/blockchain.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 91d3197cd0a26..41d862934a1b5 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -848,6 +848,8 @@ UniValue gettxoutsetinfo(const UniValue& params, bool fHelp) ret.push_back(Pair("bytes_serialized", (int64_t)stats.nSerializedSize)); ret.push_back(Pair("hash_serialized", stats.hashSerialized.GetHex())); ret.push_back(Pair("total_amount", ValueFromAmount(stats.nTotalAmount))); + } else { + throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to read UTXO set"); } return ret; } From fa9cd25ed0587078e3218965606c79ebf8138d53 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 29 Sep 2016 11:21:33 +0200 Subject: [PATCH 0957/1802] [qa] blockstore: Switch to dumb dbm --- qa/rpc-tests/test_framework/blockstore.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/qa/rpc-tests/test_framework/blockstore.py b/qa/rpc-tests/test_framework/blockstore.py index 1e2bbb277ac5c..28a6b92b8192f 100644 --- a/qa/rpc-tests/test_framework/blockstore.py +++ b/qa/rpc-tests/test_framework/blockstore.py @@ -9,11 +9,11 @@ from .mininode import * from io import BytesIO -import dbm.ndbm +import dbm.dumb as dbmd class BlockStore(object): def __init__(self, datadir): - self.blockDB = dbm.ndbm.open(datadir + "/blocks", 'c') + self.blockDB = dbmd.open(datadir + "/blocks", 'c') self.currentBlock = 0 self.headers_map = dict() @@ -123,7 +123,7 @@ def get_locator(self, current_tip=None): class TxStore(object): def __init__(self, datadir): - self.txDB = dbm.ndbm.open(datadir + "/transactions", 'c') + self.txDB = dbmd.open(datadir + "/transactions", 'c') def close(self): self.txDB.close() From fa85e860a9261e6c585ec40e67845fa93a20c6e7 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 29 Sep 2016 13:23:54 +0200 Subject: [PATCH 0958/1802] [qt] sync-overlay: Don't show estimated number of headers left --- src/qt/modaloverlay.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/qt/modaloverlay.cpp b/src/qt/modaloverlay.cpp index 461077ff76e5c..5caade7d381c9 100644 --- a/src/qt/modaloverlay.cpp +++ b/src/qt/modaloverlay.cpp @@ -134,7 +134,6 @@ void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVeri if (estimateNumHeadersLeft < 24 && hasBestHeader) { ui->numberOfBlocksLeft->setText(QString::number(bestHeaderHeight - count)); } else { - ui->numberOfBlocksLeft->setText("~" + QString::number(bestHeaderHeight + estimateNumHeadersLeft - count)); ui->expectedTimeLeft->setText(tr("Unknown. Syncing Headers...")); } } From b82f4939385e87805b4c1896442f0e179e7d9465 Mon Sep 17 00:00:00 2001 From: jnewbery Date: Wed, 28 Sep 2016 10:25:51 -0400 Subject: [PATCH 0959/1802] Add option to run bitcoin-util-test.py manually --- src/test/README.md | 8 ++++++++ src/test/bitcoin-util-test.py | 22 +++++++++++++++++++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/test/README.md b/src/test/README.md index 61462642bfb9c..3afdefe5fcd41 100644 --- a/src/test/README.md +++ b/src/test/README.md @@ -30,3 +30,11 @@ example, to run just the getarg_tests verbosely: Run `test_bitcoin --help` for the full list. +### bitcoin-util-test.py + +The test directory also contains the bitcoin-util-test.py tool, which tests bitcoin utils (currently just bitcoin-tx). This test gets run automatically during the `make check` build process. It is also possible to run the test manually from the src directory: + +``` +test/bitcoin-util-test.py --srcdir=[current directory] + +``` \ No newline at end of file diff --git a/src/test/bitcoin-util-test.py b/src/test/bitcoin-util-test.py index 882b5c67b862d..225b3324e9fc8 100755 --- a/src/test/bitcoin-util-test.py +++ b/src/test/bitcoin-util-test.py @@ -6,8 +6,24 @@ import os import bctest import buildenv +import argparse -if __name__ == '__main__': - bctest.bctester(os.environ["srcdir"] + "/test/data", - "bitcoin-util-test.json",buildenv) +help_text="""Test framework for bitcoin utils. + +Runs automatically during `make check`. + +Can also be run manually from the src directory by specifiying the source directory: +test/bitcoin-util-test.py --src=[srcdir] +""" + + +if __name__ == '__main__': + try: + srcdir = os.environ["srcdir"] + except: + parser = argparse.ArgumentParser(description=help_text) + parser.add_argument('-s', '--srcdir') + args = parser.parse_args() + srcdir = args.srcdir + bctest.bctester(srcdir + "/test/data", "bitcoin-util-test.json", buildenv) From fa156c604e7d86d84f7731b05d7530bc91d2736b Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 29 Sep 2016 15:34:04 +0200 Subject: [PATCH 0960/1802] [qa] nulldummy: Don't run unused code --- qa/rpc-tests/nulldummy.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/qa/rpc-tests/nulldummy.py b/qa/rpc-tests/nulldummy.py index eaed7a8c78970..6488a92364e79 100755 --- a/qa/rpc-tests/nulldummy.py +++ b/qa/rpc-tests/nulldummy.py @@ -3,11 +3,10 @@ # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. -from test_framework.test_framework import ComparisonTestFramework +from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * from test_framework.mininode import CTransaction, NetworkThread from test_framework.blocktools import create_coinbase, create_block, add_witness_commitment -from test_framework.comptool import TestManager from test_framework.script import CScript from io import BytesIO import time @@ -37,11 +36,12 @@ def trueDummy(tx): [Policy/Consensus] Check that the new NULLDUMMY rules are enforced on the 432nd block. ''' -class NULLDUMMYTest(ComparisonTestFramework): +class NULLDUMMYTest(BitcoinTestFramework): def __init__(self): super().__init__() self.num_nodes = 1 + self.setup_clean_chain = True def setup_network(self): # Must set the blockversion for this test @@ -54,8 +54,6 @@ def run_test(self): self.wit_address = self.nodes[0].addwitnessaddress(self.address) self.wit_ms_address = self.nodes[0].addwitnessaddress(self.ms_address) - test = TestManager(self, self.options.tmpdir) - test.add_all_connections(self.nodes) NetworkThread().start() # Start up network handling in another thread self.coinbase_blocks = self.nodes[0].generate(2) # Block 2 coinbase_txid = [] @@ -145,4 +143,4 @@ def block_submit(self, node, txs, witness = False, accept = False): assert_equal(node.getbestblockhash(), self.lastblockhash) if __name__ == '__main__': - NULLDUMMYTest().main() \ No newline at end of file + NULLDUMMYTest().main() From da9469770847df56e67e629986129a087b5bd7a5 Mon Sep 17 00:00:00 2001 From: jnewbery Date: Thu, 29 Sep 2016 10:13:16 -0400 Subject: [PATCH 0961/1802] bitcoin-util-test.py should fail if the output file is empty --- src/test/bctest.py | 3 +++ src/test/data/txcreate2.json | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/test/bctest.py b/src/test/bctest.py index 8105b87ffa34c..39a27fcd0c4a5 100644 --- a/src/test/bctest.py +++ b/src/test/bctest.py @@ -24,6 +24,9 @@ def bctest(testDir, testObj, exeext): if "output_cmp" in testObj: outputFn = testObj['output_cmp'] outputData = open(testDir + "/" + outputFn).read() + if not outputData: + print("Output data missing for " + outputFn) + sys.exit(1) proc = subprocess.Popen(execrun, stdin=stdinCfg, stdout=subprocess.PIPE, stderr=subprocess.PIPE,universal_newlines=True) try: outs = proc.communicate(input=inputData) diff --git a/src/test/data/txcreate2.json b/src/test/data/txcreate2.json index e69de29bb2d1d..c56293eaf2c66 100644 --- a/src/test/data/txcreate2.json +++ b/src/test/data/txcreate2.json @@ -0,0 +1,19 @@ +{ + "txid": "cf90229625e9eb10f6be8156bf6aa5ec2eca19a42b1e05c11f3029b560a32e13", + "version": 1, + "locktime": 0, + "vin": [ + ], + "vout": [ + { + "value": 0.00, + "n": 0, + "scriptPubKey": { + "asm": "", + "hex": "", + "type": "nonstandard" + } + } + ], + "hex": "01000000000100000000000000000000000000" +} From 1d28faf9e94fcf240ece7336d61ec297b064bc37 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 29 Sep 2016 15:02:08 +0000 Subject: [PATCH 0962/1802] test: Avoid ConnectionResetErrors during RPC tests This is necessary on FreeBSD and MacOSX, at least. See https://github.com/bitcoin/bitcoin/pull/8834#issuecomment-250450213 --- qa/rpc-tests/test_framework/authproxy.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/qa/rpc-tests/test_framework/authproxy.py b/qa/rpc-tests/test_framework/authproxy.py index f5e0be20d1ec9..fd7f32b5c6353 100644 --- a/qa/rpc-tests/test_framework/authproxy.py +++ b/qa/rpc-tests/test_framework/authproxy.py @@ -130,8 +130,9 @@ def _request(self, method, path, postdata): return self._get_response() else: raise - except BrokenPipeError: - # Python 3.5+ raises this instead of BadStatusLine when the connection was reset + except (BrokenPipeError,ConnectionResetError): + # Python 3.5+ raises BrokenPipeError instead of BadStatusLine when the connection was reset + # ConnectionResetError happens on FreeBSD with Python 3.4 self.__conn.close() self.__conn.request(method, path, postdata, headers) return self._get_response() From 30930e847e2483c7c8163cc581b392bc288250e9 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 29 Sep 2016 15:34:44 +0000 Subject: [PATCH 0963/1802] test: Explicitly set encoding to utf8 when opening text files These are text files but their encoding does not depend on the locale. Not all of them require utf8 but it is better to fix it at something to remove potential unpredictability. This is necessary on FreeBSD where no locale is set by default, and apparently Python defaults not only the terminal encoding to the locale but that of every text file. So without LOCALE environment it defaults text file encoding to ASCII. This causes problems with e.g. `bitcoin.conf`. Luckily the locale doesn't affect the default encoding for str.encode() and bytes.decode() on Python 3, so this is the only change necessary. --- qa/rpc-tests/forknotify.py | 6 +++--- qa/rpc-tests/multi_rpc.py | 2 +- qa/rpc-tests/p2p-versionbits-warning.py | 6 +++--- qa/rpc-tests/test_framework/coverage.py | 4 ++-- qa/rpc-tests/test_framework/netutil.py | 2 +- qa/rpc-tests/test_framework/util.py | 2 +- qa/rpc-tests/wallet-dump.py | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/qa/rpc-tests/forknotify.py b/qa/rpc-tests/forknotify.py index 5a3f75c808741..a1901aedab890 100755 --- a/qa/rpc-tests/forknotify.py +++ b/qa/rpc-tests/forknotify.py @@ -22,7 +22,7 @@ def __init__(self): def setup_network(self): self.nodes = [] self.alert_filename = os.path.join(self.options.tmpdir, "alert.txt") - with open(self.alert_filename, 'w') as f: + with open(self.alert_filename, 'w', encoding='utf8') as f: pass # Just open then close to create zero-length file self.nodes.append(start_node(0, self.options.tmpdir, ["-blockversion=2", "-alertnotify=echo %s >> \"" + self.alert_filename + "\""])) @@ -44,7 +44,7 @@ def run_test(self): self.nodes[1].generate(1) self.sync_all() - with open(self.alert_filename, 'r') as f: + with open(self.alert_filename, 'r', encoding='utf8') as f: alert_text = f.read() if len(alert_text) == 0: @@ -56,7 +56,7 @@ def run_test(self): self.nodes[1].generate(1) self.sync_all() - with open(self.alert_filename, 'r') as f: + with open(self.alert_filename, 'r', encoding='utf8') as f: alert_text2 = f.read() if alert_text != alert_text2: diff --git a/qa/rpc-tests/multi_rpc.py b/qa/rpc-tests/multi_rpc.py index 24373b257d7e6..cdeb94caa0998 100755 --- a/qa/rpc-tests/multi_rpc.py +++ b/qa/rpc-tests/multi_rpc.py @@ -26,7 +26,7 @@ def setup_chain(self): #Append rpcauth to bitcoin.conf before initialization rpcauth = "rpcauth=rt:93648e835a54c573682c2eb19f882535$7681e9c5b74bdd85e78166031d2058e1069b3ed7ed967c93fc63abba06f31144" rpcauth2 = "rpcauth=rt2:f8607b1a88861fac29dfccf9b52ff9f$ff36a0c23c8c62b4846112e50fa888416e94c17bfd4c42f88fd8f55ec6a3137e" - with open(os.path.join(self.options.tmpdir+"/node0", "bitcoin.conf"), 'a') as f: + with open(os.path.join(self.options.tmpdir+"/node0", "bitcoin.conf"), 'a', encoding='utf8') as f: f.write(rpcauth+"\n") f.write(rpcauth2+"\n") diff --git a/qa/rpc-tests/p2p-versionbits-warning.py b/qa/rpc-tests/p2p-versionbits-warning.py index 00dbbc02cf3c7..cceaa37b3dd75 100755 --- a/qa/rpc-tests/p2p-versionbits-warning.py +++ b/qa/rpc-tests/p2p-versionbits-warning.py @@ -72,7 +72,7 @@ def __init__(self): def setup_network(self): self.alert_filename = os.path.join(self.options.tmpdir, "alert.txt") # Open and close to create zero-length file - with open(self.alert_filename, 'w') as _: + with open(self.alert_filename, 'w', encoding='utf8') as _: pass self.extra_args = [["-debug", "-logtimemicros=1", "-alertnotify=echo %s >> \"" + self.alert_filename + "\""]] self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args) @@ -95,7 +95,7 @@ def send_blocks_with_version(self, peer, numblocks, nVersionToUse): peer.sync_with_ping() def test_versionbits_in_alert_file(self): - with open(self.alert_filename, 'r') as f: + with open(self.alert_filename, 'r', encoding='utf8') as f: alert_text = f.read() assert(VB_PATTERN.match(alert_text)) @@ -147,7 +147,7 @@ def run_test(self): stop_node(self.nodes[0], 0) wait_bitcoinds() # Empty out the alert file - with open(self.alert_filename, 'w') as _: + with open(self.alert_filename, 'w', encoding='utf8') as _: pass self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args) diff --git a/qa/rpc-tests/test_framework/coverage.py b/qa/rpc-tests/test_framework/coverage.py index 23fce61014040..13b33869f5472 100644 --- a/qa/rpc-tests/test_framework/coverage.py +++ b/qa/rpc-tests/test_framework/coverage.py @@ -50,7 +50,7 @@ def __call__(self, *args, **kwargs): rpc_method = self.auth_service_proxy_instance._service_name if self.coverage_logfile: - with open(self.coverage_logfile, 'a+') as f: + with open(self.coverage_logfile, 'a+', encoding='utf8') as f: f.write("%s\n" % rpc_method) return return_val @@ -100,7 +100,7 @@ def write_all_rpc_commands(dirname, node): if line and not line.startswith('='): commands.add("%s\n" % line.split()[0]) - with open(filename, 'w') as f: + with open(filename, 'w', encoding='utf8') as f: f.writelines(list(commands)) return True diff --git a/qa/rpc-tests/test_framework/netutil.py b/qa/rpc-tests/test_framework/netutil.py index 573b06772d7b3..b92a9f6e1ce43 100644 --- a/qa/rpc-tests/test_framework/netutil.py +++ b/qa/rpc-tests/test_framework/netutil.py @@ -58,7 +58,7 @@ def netstat(typ='tcp'): To get pid of all network process running on system, you must run this script as superuser ''' - with open('/proc/net/'+typ,'r') as f: + with open('/proc/net/'+typ,'r',encoding='utf8') as f: content = f.readlines() content.pop(0) result = [] diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index eee77f1a104cc..2f0d909a6e661 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -161,7 +161,7 @@ def initialize_datadir(dirname, n): if not os.path.isdir(datadir): os.makedirs(datadir) rpc_u, rpc_p = rpc_auth_pair(n) - with open(os.path.join(datadir, "bitcoin.conf"), 'w') as f: + with open(os.path.join(datadir, "bitcoin.conf"), 'w', encoding='utf8') as f: f.write("regtest=1\n") f.write("rpcuser=" + rpc_u + "\n") f.write("rpcpassword=" + rpc_p + "\n") diff --git a/qa/rpc-tests/wallet-dump.py b/qa/rpc-tests/wallet-dump.py index 6028d2c20b191..a37096a40ce94 100755 --- a/qa/rpc-tests/wallet-dump.py +++ b/qa/rpc-tests/wallet-dump.py @@ -12,7 +12,7 @@ def read_dump(file_name, addrs, hd_master_addr_old): Read the given dump, count the addrs that match, count change and reserve. Also check that the old hd_master is inactive """ - with open(file_name) as inputfile: + with open(file_name, encoding='utf8') as inputfile: found_addr = 0 found_addr_chg = 0 found_addr_rsv = 0 From 46a4774d2bb9cc863e43507212ef989fa10d56d4 Mon Sep 17 00:00:00 2001 From: Johnson Lau Date: Fri, 30 Sep 2016 00:18:13 +0800 Subject: [PATCH 0964/1802] Fix nulldummy.py test --- qa/rpc-tests/nulldummy.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qa/rpc-tests/nulldummy.py b/qa/rpc-tests/nulldummy.py index 6488a92364e79..54b7eac3765e6 100755 --- a/qa/rpc-tests/nulldummy.py +++ b/qa/rpc-tests/nulldummy.py @@ -119,6 +119,8 @@ def tx_submit(self, node, tx, msg = ""): node.sendrawtransaction(bytes_to_hex_str(tx.serialize_with_witness()), True) except JSONRPCException as exp: assert_equal(exp.error["message"], msg) + else: + assert_equal('', msg) return tx.hash From 2fa0063c26c80c719a1c0d30e548e338689ac917 Mon Sep 17 00:00:00 2001 From: Johnson Lau Date: Fri, 30 Sep 2016 23:08:29 +0800 Subject: [PATCH 0965/1802] Add NULLDUMMY verify flag in bitcoinconsensus.h --- doc/shared-libraries.md | 5 +++++ src/script/bitcoinconsensus.h | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/doc/shared-libraries.md b/doc/shared-libraries.md index ec6f16c8aafe9..dc363582cc8de 100644 --- a/doc/shared-libraries.md +++ b/doc/shared-libraries.md @@ -30,12 +30,17 @@ The interface is defined in the C header `bitcoinconsensus.h` located in `src/s - `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_NONE` - `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_P2SH` - Evaluate P2SH ([BIP16](https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki)) subscripts - `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_DERSIG` - Enforce strict DER ([BIP66](https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki)) compliance +- `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_NULLDUMMY` - Enforce NULLDUMMY ([BIP147](https://github.com/bitcoin/bips/blob/master/bip-0147.mediawiki)) +- `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_CHECKLOCKTIMEVERIFY` - Enable CHECKLOCKTIMEVERIFY ([BIP65](https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki)) +- `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_CHECKSEQUENCEVERIFY` - Enable CHECKSEQUENCEVERIFY ([BIP112](https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki)) +- `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS` - Enable WITNESS ([BIP141](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki)) ##### Errors - `bitcoinconsensus_ERR_OK` - No errors with input parameters *(see the return value of `bitcoinconsensus_verify_script` for the verification status)* - `bitcoinconsensus_ERR_TX_INDEX` - An invalid index for `txTo` - `bitcoinconsensus_ERR_TX_SIZE_MISMATCH` - `txToLen` did not match with the size of `txTo` - `bitcoinconsensus_ERR_DESERIALIZE` - An error deserializing `txTo` +- `bitcoinconsensus_ERR_AMOUNT_REQUIRED` - Input amount is required if WITNESS is used ### Example Implementations - [NBitcoin](https://github.com/NicolasDorier/NBitcoin/blob/master/NBitcoin/Script.cs#L814) (.NET Bindings) diff --git a/src/script/bitcoinconsensus.h b/src/script/bitcoinconsensus.h index f73a8e30bc6c4..1d2d5c23e471c 100644 --- a/src/script/bitcoinconsensus.h +++ b/src/script/bitcoinconsensus.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2015 The Bitcoin Core developers +// Copyright (c) 2009-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -50,6 +50,7 @@ enum bitcoinconsensus_SCRIPT_FLAGS_VERIFY_NONE = 0, bitcoinconsensus_SCRIPT_FLAGS_VERIFY_P2SH = (1U << 0), // evaluate P2SH (BIP16) subscripts bitcoinconsensus_SCRIPT_FLAGS_VERIFY_DERSIG = (1U << 2), // enforce strict DER (BIP66) compliance + bitcoinconsensus_SCRIPT_FLAGS_VERIFY_NULLDUMMY = (1U << 4), // enforce NULLDUMMY (BIP147) bitcoinconsensus_SCRIPT_FLAGS_VERIFY_CHECKLOCKTIMEVERIFY = (1U << 9), // enable CHECKLOCKTIMEVERIFY (BIP65) bitcoinconsensus_SCRIPT_FLAGS_VERIFY_CHECKSEQUENCEVERIFY = (1U << 10), // enable CHECKSEQUENCEVERIFY (BIP112) bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS = (1U << 11), // enable WITNESS (BIP141) From 47314e6daad8157c9e36af90a47b3ae7fa0587de Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 30 Sep 2016 17:19:51 +0200 Subject: [PATCH 0966/1802] prevector: add C++11-like data() method This returns a pointer to the beginning of the vector's data. --- src/prevector.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/prevector.h b/src/prevector.h index a0e1e140b4013..d840dfcd08468 100644 --- a/src/prevector.h +++ b/src/prevector.h @@ -475,6 +475,14 @@ class prevector { return ((size_t)(sizeof(T))) * _union.capacity; } } + + value_type* data() noexcept { + return item_ptr(0); + } + + const value_type* data() const { + return item_ptr(0); + } }; #pragma pack(pop) From e198c521d39bb0ec17f42dfe72026969984af2c7 Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Tue, 19 Jul 2016 16:43:11 -0700 Subject: [PATCH 0967/1802] Move key derivation logic from GenerateNewKey to DeriveNewChildKey --- src/wallet/wallet.cpp | 78 +++++++++++++++++++++++-------------------- src/wallet/wallet.h | 1 + 2 files changed, 42 insertions(+), 37 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 43e22383f4e16..a1f69dd94dd6c 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -100,43 +100,7 @@ CPubKey CWallet::GenerateNewKey() // use HD key derivation if HD was enabled during wallet creation if (IsHDEnabled()) { - // for now we use a fixed keypath scheme of m/0'/0'/k - CKey key; //master key seed (256bit) - CExtKey masterKey; //hd master key - CExtKey accountKey; //key at m/0' - CExtKey externalChainChildKey; //key at m/0'/0' - CExtKey childKey; //key at m/0'/0'/' - - // try to get the master key - if (!GetKey(hdChain.masterKeyID, key)) - throw std::runtime_error(std::string(__func__) + ": Master key not found"); - - masterKey.SetMaster(key.begin(), key.size()); - - // derive m/0' - // use hardened derivation (child keys >= 0x80000000 are hardened after bip32) - masterKey.Derive(accountKey, BIP32_HARDENED_KEY_LIMIT); - - // derive m/0'/0' - accountKey.Derive(externalChainChildKey, BIP32_HARDENED_KEY_LIMIT); - - // derive child key at next index, skip keys already known to the wallet - do - { - // always derive hardened keys - // childIndex | BIP32_HARDENED_KEY_LIMIT = derive childIndex in hardened child-index-range - // example: 1 | BIP32_HARDENED_KEY_LIMIT == 0x80000001 == 2147483649 - externalChainChildKey.Derive(childKey, hdChain.nExternalChainCounter | BIP32_HARDENED_KEY_LIMIT); - metadata.hdKeypath = "m/0'/0'/"+std::to_string(hdChain.nExternalChainCounter)+"'"; - metadata.hdMasterKeyID = hdChain.masterKeyID; - // increment childkey index - hdChain.nExternalChainCounter++; - } while(HaveKey(childKey.key.GetPubKey().GetID())); - secret = childKey.key; - - // update the chain model in the database - if (!CWalletDB(strWalletFile).WriteHDChain(hdChain)) - throw std::runtime_error(std::string(__func__) + ": Writing HD chain model failed"); + DeriveNewChildKey(metadata, secret); } else { secret.MakeNewKey(fCompressed); } @@ -157,6 +121,46 @@ CPubKey CWallet::GenerateNewKey() return pubkey; } +void CWallet::DeriveNewChildKey(CKeyMetadata& metadata, CKey& secret) +{ + // for now we use a fixed keypath scheme of m/0'/0'/k + CKey key; //master key seed (256bit) + CExtKey masterKey; //hd master key + CExtKey accountKey; //key at m/0' + CExtKey externalChainChildKey; //key at m/0'/0' + CExtKey childKey; //key at m/0'/0'/' + + // try to get the master key + if (!GetKey(hdChain.masterKeyID, key)) + throw std::runtime_error(std::string(__func__) + ": Master key not found"); + + masterKey.SetMaster(key.begin(), key.size()); + + // derive m/0' + // use hardened derivation (child keys >= 0x80000000 are hardened after bip32) + masterKey.Derive(accountKey, BIP32_HARDENED_KEY_LIMIT); + + // derive m/0'/0' + accountKey.Derive(externalChainChildKey, BIP32_HARDENED_KEY_LIMIT); + + // derive child key at next index, skip keys already known to the wallet + do { + // always derive hardened keys + // childIndex | BIP32_HARDENED_KEY_LIMIT = derive childIndex in hardened child-index-range + // example: 1 | BIP32_HARDENED_KEY_LIMIT == 0x80000001 == 2147483649 + externalChainChildKey.Derive(childKey, hdChain.nExternalChainCounter | BIP32_HARDENED_KEY_LIMIT); + metadata.hdKeypath = "m/0'/0'/" + std::to_string(hdChain.nExternalChainCounter) + "'"; + metadata.hdMasterKeyID = hdChain.masterKeyID; + // increment childkey index + hdChain.nExternalChainCounter++; + } while (HaveKey(childKey.key.GetPubKey().GetID())); + secret = childKey.key; + + // update the chain model in the database + if (!CWalletDB(strWalletFile).WriteHDChain(hdChain)) + throw std::runtime_error(std::string(__func__) + ": Writing HD chain model failed"); +} + bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey) { AssertLockHeld(cs_wallet); // mapKeyMetadata diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index c700e0ca7c433..077edcab2daa9 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -698,6 +698,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface * Generate a new key */ CPubKey GenerateNewKey(); + void DeriveNewChildKey(CKeyMetadata& metadata, CKey& secret); //! Adds a key to the store, and saves it to disk. bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey); //! Adds a key to the store, without saving it to disk (used by LoadWallet) From 2ca7faab4205822b06dc2ab2bbda0a9a70fce7e0 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Fri, 30 Sep 2016 19:58:11 +0200 Subject: [PATCH 0968/1802] Squashed 'src/univalue/' changes from daf1285..16a1f7f 16a1f7f Merge #3: Pull upstream 3f03bfd Merge pull request #27 from laanwj/2016_09_const_refs 5668ca3 Return const references from getKeys, getValues, get_str cedda14 Merge pull request #28 from MarcoFalke/patch-1 9f0b997 [travis] Work around osx libtool issue git-subtree-dir: src/univalue git-subtree-split: 16a1f7f6e9ed932bec7c7855003affea1e165fb5 --- .travis.yml | 2 +- include/univalue.h | 6 +++--- lib/univalue.cpp | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index d318d9cc8f6bf..132743d34930d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,3 @@ - language: cpp compiler: @@ -26,6 +25,7 @@ addons: - pkg-config before_script: + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew uninstall libtool; brew install libtool; fi - if [ -n "$USE_SHELL" ]; then export CONFIG_SHELL="$USE_SHELL"; fi - test -n "$USE_SHELL" && eval '"$USE_SHELL" -c "./autogen.sh"' || ./autogen.sh diff --git a/include/univalue.h b/include/univalue.h index e48b905bfb857..e8ce283519fed 100644 --- a/include/univalue.h +++ b/include/univalue.h @@ -142,10 +142,10 @@ class UniValue { public: // Strict type-specific getters, these throw std::runtime_error if the // value is of unexpected type - std::vector getKeys() const; - std::vector getValues() const; + const std::vector& getKeys() const; + const std::vector& getValues() const; bool get_bool() const; - std::string get_str() const; + const std::string& get_str() const; int get_int() const; int64_t get_int64() const; double get_real() const; diff --git a/lib/univalue.cpp b/lib/univalue.cpp index 1f8cee6d29839..5a2860c13f8d6 100644 --- a/lib/univalue.cpp +++ b/lib/univalue.cpp @@ -283,14 +283,14 @@ const UniValue& find_value(const UniValue& obj, const std::string& name) return NullUniValue; } -std::vector UniValue::getKeys() const +const std::vector& UniValue::getKeys() const { if (typ != VOBJ) throw std::runtime_error("JSON value is not an object as expected"); return keys; } -std::vector UniValue::getValues() const +const std::vector& UniValue::getValues() const { if (typ != VOBJ && typ != VARR) throw std::runtime_error("JSON value is not an object or array as expected"); @@ -304,7 +304,7 @@ bool UniValue::get_bool() const return getBool(); } -std::string UniValue::get_str() const +const std::string& UniValue::get_str() const { if (typ != VSTR) throw std::runtime_error("JSON value is not a string as expected"); From 203e2ddad8e544803491d1e9e9ca2b6e26a15f8e Mon Sep 17 00:00:00 2001 From: Lauda Date: Thu, 22 Sep 2016 15:14:19 +0200 Subject: [PATCH 0969/1802] Mention Gitian building script in doc. --- doc/gitian-building.md | 2 ++ doc/release-process.md | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/doc/gitian-building.md b/doc/gitian-building.md index 4914d90df4daf..442d2d605ffbc 100644 --- a/doc/gitian-building.md +++ b/doc/gitian-building.md @@ -336,6 +336,8 @@ There will be a lot of warnings printed during the build of the image. These can Getting and building the inputs -------------------------------- +At this point you have two options, you can either use the automated script (found in [contrib/gitian-build.sh](/contrib/gitian-build.sh)) or you could manually do everything by following this guide. If you're using the automated script, then run it with the "--setup" command. Afterwards, run it with the "--build" command (example: "contrib/gitian-building.sh -b signer 0.13.0"). Otherwise ignore this. + Follow the instructions in [doc/release-process.md](release-process.md#fetch-and-create-inputs-first-time-or-when-dependency-versions-change) in the bitcoin repository under 'Fetch and create inputs' to install sources which require manual intervention. Also optionally follow the next step: 'Seed the Gitian sources cache diff --git a/doc/release-process.md b/doc/release-process.md index 394b159b31ae5..e2ad3949d6db4 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -17,6 +17,8 @@ Before every major release: ### First time / New builders +If you're using the automated script (found in [contrib/gitian-build.sh](/contrib/gitian-build.sh)), then at this point you should run it with the "--setup" command. Otherwise ignore this. + Check out the source code in the following directory hierarchy. cd /path/to/your/toplevel/build @@ -60,6 +62,8 @@ Tag version (or release candidate) in git ### Setup and perform Gitian builds +If you're using the automated script (found in [contrib/gitian-build.sh](/contrib/gitian-build.sh)), then at this point you should run it with the "--build" command. Otherwise ignore this. + Setup Gitian descriptors: pushd ./bitcoin From b5fd666984fdb7125cb809c773b36034f32128cc Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Fri, 30 Sep 2016 20:54:30 -0400 Subject: [PATCH 0970/1802] [qa] Fix race condition in p2p-compactblocks test Also fix a bug in the sync_with_ping() helper function --- qa/rpc-tests/p2p-compactblocks.py | 2 ++ qa/rpc-tests/test_framework/mininode.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/qa/rpc-tests/p2p-compactblocks.py b/qa/rpc-tests/p2p-compactblocks.py index bf4fb43add3df..ac4655a841ec5 100755 --- a/qa/rpc-tests/p2p-compactblocks.py +++ b/qa/rpc-tests/p2p-compactblocks.py @@ -237,6 +237,8 @@ def test_compactblock_construction(self): for i in range(num_transactions): self.nodes[0].sendtoaddress(address, 0.1) + self.test_node.sync_with_ping() + # Now mine a block, and look at the resulting compact block. self.test_node.clear_block_announcement() block_hash = int(self.nodes[0].generate(1)[0], 16) diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index caffab35351df..0b7b17cdb5684 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -1536,7 +1536,7 @@ def sync_with_ping(self, timeout=30): def received_pong(): return (self.last_pong.nonce == self.ping_counter) self.send_message(msg_ping(nonce=self.ping_counter)) - success = wait_until(received_pong, timeout) + success = wait_until(received_pong, timeout=timeout) self.ping_counter += 1 return success From 3450c18a125f125aec76bfef79c69317eaad935d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Tim=C3=B3n?= Date: Wed, 28 Sep 2016 10:10:15 +0200 Subject: [PATCH 0971/1802] Globals: Decouple GetConfigFile and ReadConfigFile from global mapArgs --- src/bitcoin-cli.cpp | 4 ++-- src/bitcoind.cpp | 2 +- src/init.cpp | 2 +- src/qt/bitcoin.cpp | 2 +- src/util.cpp | 9 +++++---- src/util.h | 4 ++-- 6 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 68f5d90f5103d..9d4c4e53bd26b 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -92,7 +92,7 @@ static bool AppInitRPC(int argc, char* argv[]) return false; } try { - ReadConfigFile(mapArgs, mapMultiArgs); + ReadConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME), mapArgs, mapMultiArgs); } catch (const std::exception& e) { fprintf(stderr,"Error reading configuration file: %s\n", e.what()); return false; @@ -209,7 +209,7 @@ UniValue CallRPC(const string& strMethod, const UniValue& params) if (!GetAuthCookie(&strRPCUserColonPass)) { throw runtime_error(strprintf( _("Could not locate RPC credentials. No authentication cookie could be found, and no rpcpassword is set in the configuration file (%s)"), - GetConfigFile().string().c_str())); + GetConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME)).string().c_str())); } } else { diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 25d720e1e8ccb..351463c256e39 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -104,7 +104,7 @@ bool AppInit(int argc, char* argv[]) } try { - ReadConfigFile(mapArgs, mapMultiArgs); + ReadConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME), mapArgs, mapMultiArgs); } catch (const std::exception& e) { fprintf(stderr,"Error reading configuration file: %s\n", e.what()); return false; diff --git a/src/init.cpp b/src/init.cpp index cf92347952a5d..eefef7ba0b253 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1064,7 +1064,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) LogPrintf("Startup time: %s\n", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime())); LogPrintf("Default data directory %s\n", GetDefaultDataDir().string()); LogPrintf("Using data directory %s\n", strDataDir); - LogPrintf("Using config file %s\n", GetConfigFile().string()); + LogPrintf("Using config file %s\n", GetConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME)).string()); LogPrintf("Using at most %i connections (%i file descriptors available)\n", nMaxConnections, nFD); LogPrintf("Using %u threads for script verification\n", nScriptCheckThreads); diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 430e6dd0e8df8..9986af4957643 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -590,7 +590,7 @@ int main(int argc, char *argv[]) return 1; } try { - ReadConfigFile(mapArgs, mapMultiArgs); + ReadConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME), mapArgs, mapMultiArgs); } catch (const std::exception& e) { QMessageBox::critical(0, QObject::tr(PACKAGE_NAME), QObject::tr("Error: Cannot parse configuration file: %1. Only use key=value syntax.").arg(e.what())); diff --git a/src/util.cpp b/src/util.cpp index 93cc0412b5eb4..c20ede62210b1 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -518,19 +518,20 @@ void ClearDatadirCache() pathCachedNetSpecific = boost::filesystem::path(); } -boost::filesystem::path GetConfigFile() +boost::filesystem::path GetConfigFile(const std::string& confPath) { - boost::filesystem::path pathConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME)); + boost::filesystem::path pathConfigFile(confPath); if (!pathConfigFile.is_complete()) pathConfigFile = GetDataDir(false) / pathConfigFile; return pathConfigFile; } -void ReadConfigFile(map& mapSettingsRet, +void ReadConfigFile(const std::string& confPath, + map& mapSettingsRet, map >& mapMultiSettingsRet) { - boost::filesystem::ifstream streamConfig(GetConfigFile()); + boost::filesystem::ifstream streamConfig(GetConfigFile(confPath)); if (!streamConfig.good()) return; // No bitcoin.conf file is OK diff --git a/src/util.h b/src/util.h index 45b365855781a..bbb9b5db825de 100644 --- a/src/util.h +++ b/src/util.h @@ -102,12 +102,12 @@ bool TryCreateDirectory(const boost::filesystem::path& p); boost::filesystem::path GetDefaultDataDir(); const boost::filesystem::path &GetDataDir(bool fNetSpecific = true); void ClearDatadirCache(); -boost::filesystem::path GetConfigFile(); +boost::filesystem::path GetConfigFile(const std::string& confPath); #ifndef WIN32 boost::filesystem::path GetPidFile(); void CreatePidFile(const boost::filesystem::path &path, pid_t pid); #endif -void ReadConfigFile(std::map& mapSettingsRet, std::map >& mapMultiSettingsRet); +void ReadConfigFile(const std::string& confPath, std::map& mapSettingsRet, std::map >& mapMultiSettingsRet); #ifdef WIN32 boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate = true); #endif From 1c80386bceb216ca5b5da657e03a29f9c779d58b Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sat, 1 Oct 2016 16:57:25 +0200 Subject: [PATCH 0972/1802] rpc: Generate auth cookie in hex instead of base64 Base64 contains '/', and the '/' character in credentials is problematic for AuthServiceProxy which represents the RPC endpoint as an URI with user and password embedded. Closes #8399. --- src/rpc/protocol.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/rpc/protocol.cpp b/src/rpc/protocol.cpp index f5275062a2482..bb885bb5a655d 100644 --- a/src/rpc/protocol.cpp +++ b/src/rpc/protocol.cpp @@ -77,9 +77,10 @@ boost::filesystem::path GetAuthCookieFile() bool GenerateAuthCookie(std::string *cookie_out) { - unsigned char rand_pwd[32]; - GetRandBytes(rand_pwd, 32); - std::string cookie = COOKIEAUTH_USER + ":" + EncodeBase64(&rand_pwd[0],32); + const size_t COOKIE_SIZE = 32; + unsigned char rand_pwd[COOKIE_SIZE]; + GetRandBytes(rand_pwd, COOKIE_SIZE); + std::string cookie = COOKIEAUTH_USER + ":" + HexStr(rand_pwd, rand_pwd+COOKIE_SIZE); /** the umask determines what permissions are used to create this file - * these are set to 077 in init.cpp unless overridden with -sysperms. From 905bc68d05595f41cca36b3df83accd10c00cc48 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Mon, 12 Sep 2016 21:32:53 -0400 Subject: [PATCH 0973/1802] net: fix a few cases where messages were sent rather than dropped upon disconnection 75ead758 turned these into crashes in the event of a handshake failure, most notably when a peer does not offer the expected services. There are likely other cases that these assertions will find as well. --- src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index ab672197144e6..437e972382acd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6351,7 +6351,7 @@ bool SendMessages(CNode* pto, CConnman& connman) // Ping automatically sent as a latency probe & keepalive. pingSend = true; } - if (pingSend) { + if (pingSend && !pto->fDisconnect) { uint64_t nonce = 0; while (nonce == 0) { GetRandBytes((unsigned char*)&nonce, sizeof(nonce)); @@ -6432,7 +6432,7 @@ bool SendMessages(CNode* pto, CConnman& connman) if (pindexBestHeader == NULL) pindexBestHeader = chainActive.Tip(); bool fFetch = state.fPreferredDownload || (nPreferredDownload == 0 && !pto->fClient && !pto->fOneShot); // Download if this is a nice peer, or we have no nice peers and this one might do. - if (!state.fSyncStarted && !pto->fClient && !fImporting && !fReindex) { + if (!state.fSyncStarted && !pto->fClient && !pto->fDisconnect && !fImporting && !fReindex) { // Only actively request headers from a single peer, unless we're close to today. if ((nSyncStarted == 0 && fFetch) || pindexBestHeader->GetBlockTime() > GetAdjustedTime() - 24 * 60 * 60) { state.fSyncStarted = true; From f00705ae7ff3c1db805859e3be41e58ac70625b6 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 30 Sep 2016 17:21:12 +0200 Subject: [PATCH 0974/1802] serialize: Deprecate `begin_ptr` / `end_ptr` Implement `begin_ptr` and `end_ptr` in terms of C++11 code, and add a comment that they are deprecated. Follow-up to developer notes update in 654a21162252294b7dbd6c982fec88008af7335e. --- src/prevector.h | 2 +- src/serialize.h | 21 ++++++++++----------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/prevector.h b/src/prevector.h index d840dfcd08468..25bce522dc9b1 100644 --- a/src/prevector.h +++ b/src/prevector.h @@ -476,7 +476,7 @@ class prevector { } } - value_type* data() noexcept { + value_type* data() { return item_ptr(0); } diff --git a/src/serialize.h b/src/serialize.h index 04ab9aa2e7762..1f51da82fffa2 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -44,33 +44,32 @@ inline T* NCONST_PTR(const T* val) return const_cast(val); } -/** - * Get begin pointer of vector (non-const version). - * @note These functions avoid the undefined case of indexing into an empty - * vector, as well as that of indexing after the end of the vector. +/** + * Important: Do not use the following functions in new code, but use v.data() + * and v.data() + v.size() respectively directly. They were once introduced to + * have a compatible, safe way to get the begin and end pointer of a vector. + * However with C++11 the language has built-in functionality for this and it's + * more readable to just use that. */ template inline typename V::value_type* begin_ptr(V& v) { - return v.empty() ? NULL : &v[0]; + return v.data(); } -/** Get begin pointer of vector (const version) */ template inline const typename V::value_type* begin_ptr(const V& v) { - return v.empty() ? NULL : &v[0]; + return v.data(); } -/** Get end pointer of vector (non-const version) */ template inline typename V::value_type* end_ptr(V& v) { - return v.empty() ? NULL : (&v[0] + v.size()); + return v.data() + v.size(); } -/** Get end pointer of vector (const version) */ template inline const typename V::value_type* end_ptr(const V& v) { - return v.empty() ? NULL : (&v[0] + v.size()); + return v.data() + v.size(); } /* From fa7c35c4ec630838178b4674288da33561a66f08 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sat, 1 Oct 2016 21:07:31 +0200 Subject: [PATCH 0975/1802] [qa] util: Move wait_bitcoinds() into stop_nodes() --- qa/rpc-tests/bip9-softforks.py | 1 - qa/rpc-tests/fundrawtransaction.py | 1 - qa/rpc-tests/p2p-versionbits-warning.py | 6 ++---- qa/rpc-tests/reindex.py | 16 +++++++++------- qa/rpc-tests/rpcbind_test.py | 2 -- qa/rpc-tests/test_framework/test_framework.py | 4 ---- qa/rpc-tests/test_framework/util.py | 2 +- qa/rpc-tests/wallet.py | 3 --- 8 files changed, 12 insertions(+), 23 deletions(-) diff --git a/qa/rpc-tests/bip9-softforks.py b/qa/rpc-tests/bip9-softforks.py index 979d1410c2616..be6ddde112ea2 100755 --- a/qa/rpc-tests/bip9-softforks.py +++ b/qa/rpc-tests/bip9-softforks.py @@ -195,7 +195,6 @@ def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignatu # Restart all self.test.block_store.close() stop_nodes(self.nodes) - wait_bitcoinds() shutil.rmtree(self.options.tmpdir) self.setup_chain() self.setup_network() diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py index eeb8476634fcb..8c45578fcfbdd 100755 --- a/qa/rpc-tests/fundrawtransaction.py +++ b/qa/rpc-tests/fundrawtransaction.py @@ -470,7 +470,6 @@ def run_test(self): self.nodes[1].encryptwallet("test") self.nodes.pop(1) stop_nodes(self.nodes) - wait_bitcoinds() self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) # This test is not meant to test fee estimation and we'd like diff --git a/qa/rpc-tests/p2p-versionbits-warning.py b/qa/rpc-tests/p2p-versionbits-warning.py index cceaa37b3dd75..fc3eddddee17b 100755 --- a/qa/rpc-tests/p2p-versionbits-warning.py +++ b/qa/rpc-tests/p2p-versionbits-warning.py @@ -144,8 +144,7 @@ def run_test(self): # is cleared, and restart the node. This should move the versionbit state # to ACTIVE. self.nodes[0].generate(VB_PERIOD) - stop_node(self.nodes[0], 0) - wait_bitcoinds() + stop_nodes(self.nodes) # Empty out the alert file with open(self.alert_filename, 'w', encoding='utf8') as _: pass @@ -156,8 +155,7 @@ def run_test(self): assert(WARN_UNKNOWN_RULES_ACTIVE in self.nodes[0].getinfo()["errors"]) assert(WARN_UNKNOWN_RULES_ACTIVE in self.nodes[0].getmininginfo()["errors"]) assert(WARN_UNKNOWN_RULES_ACTIVE in self.nodes[0].getnetworkinfo()["warnings"]) - stop_node(self.nodes[0], 0) - wait_bitcoinds() + stop_nodes(self.nodes) self.test_versionbits_in_alert_file() # Test framework expects the node to still be running... diff --git a/qa/rpc-tests/reindex.py b/qa/rpc-tests/reindex.py index abbbb1033693b..25cf4c1679b98 100755 --- a/qa/rpc-tests/reindex.py +++ b/qa/rpc-tests/reindex.py @@ -7,7 +7,11 @@ # Test -reindex and -reindex-chainstate with CheckBlockIndex # from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * +from test_framework.util import ( + start_nodes, + stop_nodes, + assert_equal, +) import time class ReindexTest(BitcoinTestFramework): @@ -18,16 +22,14 @@ def __init__(self): self.num_nodes = 1 def setup_network(self): - self.nodes = [] - self.is_network_split = False - self.nodes.append(start_node(0, self.options.tmpdir)) + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) def reindex(self, justchainstate=False): self.nodes[0].generate(3) blockcount = self.nodes[0].getblockcount() - stop_node(self.nodes[0], 0) - wait_bitcoinds() - self.nodes[0]=start_node(0, self.options.tmpdir, ["-debug", "-reindex-chainstate" if justchainstate else "-reindex", "-checkblockindex=1"]) + stop_nodes(self.nodes) + extra_args = [["-debug", "-reindex-chainstate" if justchainstate else "-reindex", "-checkblockindex=1"]] + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args) while self.nodes[0].getblockcount() < blockcount: time.sleep(0.1) assert_equal(self.nodes[0].getblockcount(), blockcount) diff --git a/qa/rpc-tests/rpcbind_test.py b/qa/rpc-tests/rpcbind_test.py index 085024e268384..d78d0b884e9ed 100755 --- a/qa/rpc-tests/rpcbind_test.py +++ b/qa/rpc-tests/rpcbind_test.py @@ -40,7 +40,6 @@ def run_bind_test(self, allow_ips, connect_to, addresses, expected): assert_equal(set(get_bind_addrs(pid)), set(expected)) finally: stop_nodes(self.nodes) - wait_bitcoinds() def run_allowip_test(self, allow_ips, rpchost, rpcport): ''' @@ -56,7 +55,6 @@ def run_allowip_test(self, allow_ips, rpchost, rpcport): finally: node = None # make sure connection will be garbage collected and closed stop_nodes(self.nodes) - wait_bitcoinds() def run_test(self): # due to OS-specific network stats queries, this test works only on Linux diff --git a/qa/rpc-tests/test_framework/test_framework.py b/qa/rpc-tests/test_framework/test_framework.py index 186cf866cfda6..e6fc5fd8a20e4 100755 --- a/qa/rpc-tests/test_framework/test_framework.py +++ b/qa/rpc-tests/test_framework/test_framework.py @@ -21,7 +21,6 @@ sync_mempools, stop_nodes, stop_node, - wait_bitcoinds, enable_coverage, check_json_precision, initialize_chain_clean, @@ -81,7 +80,6 @@ def split_network(self): """ assert not self.is_network_split stop_nodes(self.nodes) - wait_bitcoinds() self.setup_network(True) def sync_all(self): @@ -100,7 +98,6 @@ def join_network(self): """ assert self.is_network_split stop_nodes(self.nodes) - wait_bitcoinds() self.setup_network(False) def main(self): @@ -170,7 +167,6 @@ def main(self): if not self.options.noshutdown: print("Stopping nodes") stop_nodes(self.nodes) - wait_bitcoinds() else: print("Note: bitcoinds were not stopped and may still be running") diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index 2f0d909a6e661..c6b0367b419d6 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -266,7 +266,6 @@ def initialize_chain(test_dir, num_nodes, cachedir): # Shut them down, and clean up cache directories: stop_nodes(rpcs) - wait_bitcoinds() disable_mocktime() for i in range(MAX_NODES): os.remove(log_filename(cachedir, i, "debug.log")) @@ -365,6 +364,7 @@ def stop_nodes(nodes): except http.client.CannotSendRequest as e: print("WARN: Unable to stop node: " + repr(e)) del nodes[:] # Emptying array closes connections as a side effect + wait_bitcoinds() def set_node_times(nodes, t): for node in nodes: diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py index 3420be1a2ed1e..e43f6ea5d225e 100755 --- a/qa/rpc-tests/wallet.py +++ b/qa/rpc-tests/wallet.py @@ -199,7 +199,6 @@ def run_test (self): #do some -walletbroadcast tests stop_nodes(self.nodes) - wait_bitcoinds() self.nodes = start_nodes(3, self.options.tmpdir, [["-walletbroadcast=0"],["-walletbroadcast=0"],["-walletbroadcast=0"]]) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) @@ -225,7 +224,6 @@ def run_test (self): #restart the nodes with -walletbroadcast=1 stop_nodes(self.nodes) - wait_bitcoinds() self.nodes = start_nodes(3, self.options.tmpdir) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) @@ -335,7 +333,6 @@ def run_test (self): for m in maintenance: print("check " + m) stop_nodes(self.nodes) - wait_bitcoinds() self.nodes = start_nodes(3, self.options.tmpdir, [[m]] * 3) while m == '-reindex' and [block_count] * 3 != [self.nodes[i].getblockcount() for i in range(3)]: # reindex will leave rpc warm up "early"; Wait for it to finish From fa666094cf5b9ac4a7c1732a7ffa001afffcd938 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sat, 1 Oct 2016 11:36:25 +0200 Subject: [PATCH 0976/1802] [qa] mininode: Only allow named args in wait_until --- qa/rpc-tests/maxuploadtarget.py | 2 +- qa/rpc-tests/p2p-mempool.py | 2 +- qa/rpc-tests/test_framework/mininode.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/qa/rpc-tests/maxuploadtarget.py b/qa/rpc-tests/maxuploadtarget.py index 125d4eb275190..d0e9fe9a3f592 100755 --- a/qa/rpc-tests/maxuploadtarget.py +++ b/qa/rpc-tests/maxuploadtarget.py @@ -75,7 +75,7 @@ def sync_with_ping(self, timeout=30): def received_pong(): return (self.last_pong.nonce == self.ping_counter) self.connection.send_message(msg_ping(nonce=self.ping_counter)) - success = wait_until(received_pong, timeout) + success = wait_until(received_pong, timeout=timeout) self.ping_counter += 1 return success diff --git a/qa/rpc-tests/p2p-mempool.py b/qa/rpc-tests/p2p-mempool.py index 5c5d778f429b9..382d7f1e82ca0 100755 --- a/qa/rpc-tests/p2p-mempool.py +++ b/qa/rpc-tests/p2p-mempool.py @@ -63,7 +63,7 @@ def sync_with_ping(self, timeout=30): def received_pong(): return (self.last_pong.nonce == self.ping_counter) self.connection.send_message(msg_ping(nonce=self.ping_counter)) - success = wait_until(received_pong, timeout) + success = wait_until(received_pong, timeout=timeout) self.ping_counter += 1 return success diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index 0b7b17cdb5684..88a3b7e0f7144 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -1320,7 +1320,7 @@ def __repr__(self): % (self.message, self.code, self.reason, self.data) # Helper function -def wait_until(predicate, attempts=float('inf'), timeout=float('inf')): +def wait_until(predicate, *, attempts=float('inf'), timeout=float('inf')): attempt = 0 elapsed = 0 From 5f274a1749acfdf331bc2931e25ac80c346e5faa Mon Sep 17 00:00:00 2001 From: jnewbery Date: Tue, 27 Sep 2016 13:40:16 -0400 Subject: [PATCH 0977/1802] log block size and weight correctly. --- src/miner.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/miner.cpp b/src/miner.cpp index 9575858840df0..6cb40dae8d97e 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -168,7 +168,6 @@ CBlockTemplate* BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn) nLastBlockTx = nBlockTx; nLastBlockSize = nBlockSize; nLastBlockWeight = nBlockWeight; - LogPrintf("CreateNewBlock(): total size %u txs: %u fees: %ld sigops %d\n", nBlockSize, nBlockTx, nFees, nBlockSigOpsCost); // Create coinbase transaction. CMutableTransaction coinbaseTx; @@ -182,6 +181,9 @@ CBlockTemplate* BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn) pblocktemplate->vchCoinbaseCommitment = GenerateCoinbaseCommitment(*pblock, pindexPrev, chainparams.GetConsensus()); pblocktemplate->vTxFees[0] = -nFees; + uint64_t nSerializeSize = GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION); + LogPrintf("CreateNewBlock(): total size: %u block weight: %u txs: %u fees: %ld sigops %d\n", nSerializeSize, GetBlockWeight(*pblock), nBlockTx, nFees, nBlockSigOpsCost); + // Fill in header pblock->hashPrevBlock = pindexPrev->GetBlockHash(); UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev); From f9bd92d235a187a9bfea4c956bf74e2e08cebb46 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 4 Oct 2016 11:11:21 +0000 Subject: [PATCH 0978/1802] version.h: s/shord/short/ in comment --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index 68ccd6d378323..87bd65506670a 100644 --- a/src/version.h +++ b/src/version.h @@ -39,7 +39,7 @@ static const int SENDHEADERS_VERSION = 70012; //! "feefilter" tells peers to filter invs to you by fee starts with this version static const int FEEFILTER_VERSION = 70013; -//! shord-id-based block download starts with this version +//! short-id-based block download starts with this version static const int SHORT_IDS_BLOCKS_VERSION = 70014; #endif // BITCOIN_VERSION_H From 2c09a5209ab00573a2422e1e65c437a6e2f59624 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 4 Oct 2016 11:12:23 +0000 Subject: [PATCH 0979/1802] protocol.h: Move MESSAGE_START_SIZE into CMessageHeader Also move the enum to the top, and remove a deceptive TODO comment. --- src/main.cpp | 6 +++--- src/protocol.h | 23 ++++++++++------------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 437e972382acd..9b66aad429f99 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4358,11 +4358,11 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB unsigned int nSize = 0; try { // locate a header - unsigned char buf[MESSAGE_START_SIZE]; + unsigned char buf[CMessageHeader::MESSAGE_START_SIZE]; blkdat.FindByte(chainparams.MessageStart()[0]); nRewind = blkdat.GetPos()+1; blkdat >> FLATDATA(buf); - if (memcmp(buf, chainparams.MessageStart(), MESSAGE_START_SIZE)) + if (memcmp(buf, chainparams.MessageStart(), CMessageHeader::MESSAGE_START_SIZE)) continue; // read size blkdat >> nSize; @@ -6232,7 +6232,7 @@ bool ProcessMessages(CNode* pfrom, CConnman& connman) it++; // Scan for message start - if (memcmp(msg.hdr.pchMessageStart, chainparams.MessageStart(), MESSAGE_START_SIZE) != 0) { + if (memcmp(msg.hdr.pchMessageStart, chainparams.MessageStart(), CMessageHeader::MESSAGE_START_SIZE) != 0) { LogPrintf("PROCESSMESSAGE: INVALID MESSAGESTART %s peer=%d\n", SanitizeString(msg.hdr.GetCommand()), pfrom->id); fOk = false; break; diff --git a/src/protocol.h b/src/protocol.h index 1bc1c25b3714f..cdb76b90381c5 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -18,8 +18,6 @@ #include #include -#define MESSAGE_START_SIZE 4 - /** Message header. * (4) message start. * (12) command. @@ -29,6 +27,16 @@ class CMessageHeader { public: + enum { + MESSAGE_START_SIZE = 4, + COMMAND_SIZE = 12, + MESSAGE_SIZE_SIZE = 4, + CHECKSUM_SIZE = 4, + + MESSAGE_SIZE_OFFSET = MESSAGE_START_SIZE + COMMAND_SIZE, + CHECKSUM_OFFSET = MESSAGE_SIZE_OFFSET + MESSAGE_SIZE_SIZE, + HEADER_SIZE = MESSAGE_START_SIZE + COMMAND_SIZE + MESSAGE_SIZE_SIZE + CHECKSUM_SIZE + }; typedef unsigned char MessageStartChars[MESSAGE_START_SIZE]; CMessageHeader(const MessageStartChars& pchMessageStartIn); @@ -48,17 +56,6 @@ class CMessageHeader READWRITE(FLATDATA(pchChecksum)); } - // TODO: make private (improves encapsulation) -public: - enum { - COMMAND_SIZE = 12, - MESSAGE_SIZE_SIZE = 4, - CHECKSUM_SIZE = 4, - - MESSAGE_SIZE_OFFSET = MESSAGE_START_SIZE + COMMAND_SIZE, - CHECKSUM_OFFSET = MESSAGE_SIZE_OFFSET + MESSAGE_SIZE_SIZE, - HEADER_SIZE = MESSAGE_START_SIZE + COMMAND_SIZE + MESSAGE_SIZE_SIZE + CHECKSUM_SIZE - }; char pchMessageStart[MESSAGE_START_SIZE]; char pchCommand[COMMAND_SIZE]; uint32_t nMessageSize; From eeeebdd3cba1e69835f826236f7d71ee8d76ace4 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 21 Sep 2016 12:21:13 +0200 Subject: [PATCH 0980/1802] [doc] Rework docs * Minor formatting such as adjusting links * Move sections of `doc/multiwallet-qt.md` to the source code and delete the file, as it is outdated * Fix typo in the release notes * Amend release process to mention update of BLOCK_CHAIN_SIZE --- doc/README.md | 10 +++-- doc/multiwallet-qt.md | 48 ----------------------- doc/release-notes/release-notes-0.13.0.md | 2 +- doc/release-process.md | 1 + doc/{travis-ci.txt => travis-ci.md} | 9 +++-- src/qt/bitcoingui.cpp | 2 + src/qt/walletframe.h | 7 ++++ 7 files changed, 24 insertions(+), 55 deletions(-) delete mode 100644 doc/multiwallet-qt.md rename doc/{travis-ci.txt => travis-ci.md} (88%) diff --git a/doc/README.md b/doc/README.md index 09a507c9ce6e9..e4fa49614ac8c 100644 --- a/doc/README.md +++ b/doc/README.md @@ -3,7 +3,9 @@ Bitcoin Core 0.13.99 Setup --------------------- -[Bitcoin Core](http://bitcoin.org/en/download) is the original Bitcoin client and it builds the backbone of the network. However, it downloads and stores the entire history of Bitcoin transactions (which is currently several GBs); depending on the speed of your computer and network connection, the synchronization process can take anywhere from a few hours to a day or more. +Bitcoin Core is the original Bitcoin client and it builds the backbone of the network. However, it downloads and stores the entire history of Bitcoin transactions (which is currently several GBs); depending on the speed of your computer and network connection, the synchronization process can take anywhere from a few hours to a day or more. + +To download Bitcoin Core, visit [bitcoincore.org](https://bitcoincore.org/en/releases/). Running --------------------- @@ -46,13 +48,13 @@ Development The Bitcoin repo's [root README](/README.md) contains relevant information on the development process and automated testing. - [Developer Notes](developer-notes.md) -- [Multiwallet Qt Development](multiwallet-qt.md) - [Release Notes](release-notes.md) - [Release Process](release-process.md) - [Source Code Documentation (External Link)](https://dev.visucore.com/bitcoin/doxygen/) - [Translation Process](translation_process.md) - [Translation Strings Policy](translation_strings_policy.md) - [Unit Tests](unit-tests.md) +- [Travis CI](travis-ci.md) - [Unauthenticated REST Interface](REST-interface.md) - [Shared Libraries](shared-libraries.md) - [BIPS](bips.md) @@ -67,11 +69,13 @@ The Bitcoin repo's [root README](/README.md) contains relevant information on th ### Miscellaneous - [Assets Attribution](assets-attribution.md) - [Files](files.md) +- [Reduce Traffic](reduce-traffic.md) - [Tor Support](tor.md) - [Init Scripts (systemd/upstart/openrc)](init.md) +- [ZMQ](zmq.md) License --------------------- -Distributed under the [MIT software license](http://www.opensource.org/licenses/mit-license.php). +Distributed under the [MIT software license](/COPYING). This product includes software developed by the OpenSSL Project for use in the [OpenSSL Toolkit](https://www.openssl.org/). This product includes cryptographic software written by Eric Young ([eay@cryptsoft.com](mailto:eay@cryptsoft.com)), and UPnP software written by Thomas Bernard. diff --git a/doc/multiwallet-qt.md b/doc/multiwallet-qt.md deleted file mode 100644 index 3caab818076b8..0000000000000 --- a/doc/multiwallet-qt.md +++ /dev/null @@ -1,48 +0,0 @@ -Multiwallet Qt Development and Integration Strategy -=================================================== - -In order to support loading of multiple wallets in bitcoin-qt, a few changes in the UI architecture will be needed. -Fortunately, only four of the files in the existing project are affected by this change. - -Two new classes have been implemented in two new .h/.cpp file pairs, with much of the functionality that was previously -implemented in the BitcoinGUI class moved over to these new classes. - -The two existing files most affected, by far, are bitcoingui.h and bitcoingui.cpp, as the BitcoinGUI class will require -some major retrofitting. - -Only requiring some minor changes is bitcoin.cpp. - -Finally, two new headers and source files will have to be added to bitcoin-qt.pro. - -Changes to class BitcoinGUI ---------------------------- -The principal change to the BitcoinGUI class concerns the QStackedWidget instance called centralWidget. -This widget owns five page views: overviewPage, transactionsPage, addressBookPage, receiveCoinsPage, and sendCoinsPage. - -A new class called *WalletView* inheriting from QStackedWidget has been written to handle all renderings and updates of -these page views. In addition to owning these five page views, a WalletView also has a pointer to a WalletModel instance. -This allows the construction of multiple WalletView objects, each rendering a distinct wallet. - -A second class called *WalletFrame* inheriting from QFrame has been written as a container for embedding all wallet-related -controls into BitcoinGUI. At present it contains the WalletView instances for the wallets and does little more than passing on messages -from BitcoinGUI to the currently selected WalletView. It is a WalletFrame instance -that takes the place of what used to be centralWidget in BitcoinGUI. The purpose of this class is to allow future -refinements of the wallet controls with minimal need for further modifications to BitcoinGUI, thus greatly simplifying -merges while reducing the risk of breaking top-level stuff. - -Changes to bitcoin.cpp ----------------------- -bitcoin.cpp is the entry point into bitcoin-qt, and as such, will require some minor modifications to provide hooks for -multiple wallet support. Most importantly will be the way it instantiates WalletModels and passes them to the -singleton BitcoinGUI instance called window. Formerly, BitcoinGUI kept a pointer to a single instance of a WalletModel. -The initial change required is very simple: rather than calling `window.setWalletModel(&walletModel);` we perform the -following two steps: - - window.addWallet("~Default", &walletModel); - window.setCurrentWallet("~Default"); - -The string parameter is just an arbitrary name given to the default wallet. It's been prepended with a tilde to avoid name collisions in the future with additional wallets. - -The shutdown call `window.setWalletModel(0)` has also been removed. In its place is now: - -window.removeAllWallets(); diff --git a/doc/release-notes/release-notes-0.13.0.md b/doc/release-notes/release-notes-0.13.0.md index 5dd3f5a651ea2..f9bf3d75de09d 100644 --- a/doc/release-notes/release-notes-0.13.0.md +++ b/doc/release-notes/release-notes-0.13.0.md @@ -643,7 +643,7 @@ git merge commit are mentioned. - #8041 `5b736dd` Fix bip9-softforks blockstore issue (MarcoFalke) - #7994 `1f01443` Add op csv tests to script_tests.json (Christewart) - #8038 `e2bf830` Various minor fixes (MarcoFalke) -- #8072 `1b87e5b` Travis: 'make check' in parallel and verbose (MarcoFalke) +- #8072 `1b87e5b` Travis: 'make check' in parallel and verbose (theuni) - #8056 `8844ef1` Remove hardcoded "4 nodes" from test_framework (MarcoFalke) - #8047 `37f9a1f` Test_framework: Set wait-timeout for bitcoind procs (MarcoFalke) - #8095 `6700cc9` Test framework: only cleanup on successful test runs (sdaftuar) diff --git a/doc/release-process.md b/doc/release-process.md index d07f9a89ad9c5..63f75fb3992a2 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -16,6 +16,7 @@ Before every minor and major release: Before every major release: * Update hardcoded [seeds](/contrib/seeds/README.md), see [this pull request](https://github.com/bitcoin/bitcoin/pull/7415) for an example. +* Update [`BLOCK_CHAIN_SIZE`](/src/qt/intro.cpp) to the current size plus some overhead. ### First time / New builders diff --git a/doc/travis-ci.txt b/doc/travis-ci.md similarity index 88% rename from doc/travis-ci.txt rename to doc/travis-ci.md index 06410405d6de8..38085cec353ad 100644 --- a/doc/travis-ci.txt +++ b/doc/travis-ci.md @@ -1,5 +1,8 @@ +Travis CI +========= + Support for using travis-ci has been added in order to automate pull-testing. -See https://travis-ci.org/ for more info +See [travis-ci.org](https://travis-ci.org/) for more info This procedure is different than the pull-tester that came before it in a few ways. @@ -7,7 +10,7 @@ ways. There is nothing to administer. This is a major feature as it means that builds have no local state. Because there is no ability to login to the builders to install packages (tools, dependencies, etc), the entire build -procedure must instead be controlled by a declarative script (.travis.yml). +procedure must instead be controlled by a declarative script `.travis.yml`. This script declares each build configuration, creates virtual machines as necessary, builds, then discards the virtual machines. @@ -16,7 +19,7 @@ than a single pass/fail. This helps to catch build failures and logic errors that present on platforms other than the ones the author has tested. This matrix is defined in the build script and can be changed at any time. -All builders use the dependency-generator in the depends dir, rather than +All builders use the dependency-generator in the [depends dir](/depends), rather than using apt-get to install build dependencies. This guarantees that the tester is using the same versions as Gitian, so the build results are nearly identical to what would be found in a final release. However, this also means that builds diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index dd022ee7624b5..af767aa6c62c0 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -74,6 +74,8 @@ const std::string BitcoinGUI::DEFAULT_UIPLATFORM = #endif ; +/** Display name for default wallet name. Uses tilde to avoid name + * collisions in the future with additional wallets */ const QString BitcoinGUI::DEFAULT_WALLET = "~Default"; BitcoinGUI::BitcoinGUI(const PlatformStyle *_platformStyle, const NetworkStyle *networkStyle, QWidget *parent) : diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h index 00c2f5636379a..7bc6412910393 100644 --- a/src/qt/walletframe.h +++ b/src/qt/walletframe.h @@ -19,6 +19,13 @@ QT_BEGIN_NAMESPACE class QStackedWidget; QT_END_NAMESPACE +/** + * A container for embedding all wallet-related + * controls into BitcoinGUI. The purpose of this class is to allow future + * refinements of the wallet controls with minimal need for further + * modifications to BitcoinGUI, thus greatly simplifying merges while + * reducing the risk of breaking top-level stuff. + */ class WalletFrame : public QFrame { Q_OBJECT From 06128da751371797683eabb577298a4966b2ce28 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 3 Oct 2016 13:00:14 -0400 Subject: [PATCH 0981/1802] Make GetFetchFlags always request witness objects from witness peers This fixes a bug where we might (in exceedingly rare circumstances) accidentally ban a node for sending us the first (potentially few) segwit blocks in non-segwit mode. --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 437e972382acd..40c31b6ca6c76 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4922,7 +4922,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam uint32_t GetFetchFlags(CNode* pfrom, CBlockIndex* pprev, const Consensus::Params& chainparams) { uint32_t nFetchFlags = 0; - if (IsWitnessEnabled(pprev, chainparams) && State(pfrom->GetId())->fHaveWitness) { + if ((pfrom->GetLocalServices() & NODE_WITNESS) && State(pfrom->GetId())->fHaveWitness) { nFetchFlags |= MSG_WITNESS_FLAG; } return nFetchFlags; From be7555f0c03057bb5537cc42ca9d4937389f0670 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 3 Oct 2016 13:33:07 -0400 Subject: [PATCH 0982/1802] Fix overly-prescriptive p2p-segwit test for new fetch logic --- qa/rpc-tests/p2p-segwit.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/qa/rpc-tests/p2p-segwit.py b/qa/rpc-tests/p2p-segwit.py index 5c1eb21b1ffd5..c2ea20bb845c8 100755 --- a/qa/rpc-tests/p2p-segwit.py +++ b/qa/rpc-tests/p2p-segwit.py @@ -912,14 +912,6 @@ def test_witness_tx_relay_before_segwit_activation(self): # But eliminating the witness should fix it self.test_node.test_transaction_acceptance(tx, with_witness=False, accepted=True) - # Verify that inv's to test_node come with getdata's for non-witness tx's - # Just tweak the transaction, announce it, and verify we get a getdata - # for a normal tx - tx.vout[0].scriptPubKey = CScript([OP_TRUE, OP_TRUE]) - tx.rehash() - self.test_node.announce_tx_and_wait_for_getdata(tx) - assert(self.test_node.last_getdata.inv[0].type == 1) - # Cleanup: mine the first transaction and update utxo self.nodes[0].generate(1) assert_equal(len(self.nodes[0].getrawmempool()), 0) @@ -1025,7 +1017,7 @@ def test_tx_relay_after_segwit_activation(self): def test_block_relay(self, segwit_activated): print("\tTesting block relay") - blocktype = 2|MSG_WITNESS_FLAG if segwit_activated else 2 + blocktype = 2|MSG_WITNESS_FLAG # test_node has set NODE_WITNESS, so all getdata requests should be for # witness blocks. From 87e7d7280739cccfabaffbbfbbbcfa21e943da3a Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 30 Sep 2016 17:40:03 -0400 Subject: [PATCH 0983/1802] Make validationinterface.UpdatedBlockTip more verbose In anticipation of making all the callbacks out of block processing flow through it. Note that vHashes will always have something in it since pindexFork != pindexNewTip. --- src/main.cpp | 6 ++---- src/validationinterface.cpp | 4 ++-- src/validationinterface.h | 4 ++-- src/zmq/zmqnotificationinterface.cpp | 7 +++++-- src/zmq/zmqnotificationinterface.h | 2 +- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index ab672197144e6..37a0a2f30d055 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3099,11 +3099,9 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, } }); } - // Notify external listeners about the new tip. - if (!vHashes.empty()) { - GetMainSignals().UpdatedBlockTip(pindexNewTip); - } } + // Notify external listeners about the new tip. + GetMainSignals().UpdatedBlockTip(pindexNewTip, pindexFork, fInitialDownload); } } while (pindexNewTip != pindexMostWork); CheckBlockIndex(chainparams.GetConsensus()); diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index 6ddf37658d854..d0aa7b5f393ff 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -13,7 +13,7 @@ CMainSignals& GetMainSignals() } void RegisterValidationInterface(CValidationInterface* pwalletIn) { - g_signals.UpdatedBlockTip.connect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1)); + g_signals.UpdatedBlockTip.connect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3)); g_signals.SyncTransaction.connect(boost::bind(&CValidationInterface::SyncTransaction, pwalletIn, _1, _2, _3)); g_signals.UpdatedTransaction.connect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1)); g_signals.SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1)); @@ -33,7 +33,7 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn) { g_signals.SetBestChain.disconnect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1)); g_signals.UpdatedTransaction.disconnect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1)); g_signals.SyncTransaction.disconnect(boost::bind(&CValidationInterface::SyncTransaction, pwalletIn, _1, _2, _3)); - g_signals.UpdatedBlockTip.disconnect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1)); + g_signals.UpdatedBlockTip.disconnect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3)); } void UnregisterAllValidationInterfaces() { diff --git a/src/validationinterface.h b/src/validationinterface.h index 0c91ec8308eed..683f8fe20cbae 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -33,7 +33,7 @@ void SyncWithWallets(const CTransaction& tx, const CBlockIndex *pindex, int posI class CValidationInterface { protected: - virtual void UpdatedBlockTip(const CBlockIndex *pindex) {} + virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) {} virtual void SyncTransaction(const CTransaction &tx, const CBlockIndex *pindex, int posInBlock) {} virtual void SetBestChain(const CBlockLocator &locator) {} virtual void UpdatedTransaction(const uint256 &hash) {} @@ -49,7 +49,7 @@ class CValidationInterface { struct CMainSignals { /** Notifies listeners of updated block chain tip */ - boost::signals2::signal UpdatedBlockTip; + boost::signals2::signal UpdatedBlockTip; /** Notifies listeners of updated transaction data (transaction, and optionally the block it is found in. */ boost::signals2::signal SyncTransaction; /** Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible). */ diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp index 376e7dec590b5..020cdfbdc724a 100644 --- a/src/zmq/zmqnotificationinterface.cpp +++ b/src/zmq/zmqnotificationinterface.cpp @@ -124,12 +124,15 @@ void CZMQNotificationInterface::Shutdown() } } -void CZMQNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindex) +void CZMQNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) { + if (fInitialDownload) + return; + for (std::list::iterator i = notifiers.begin(); i!=notifiers.end(); ) { CZMQAbstractNotifier *notifier = *i; - if (notifier->NotifyBlock(pindex)) + if (notifier->NotifyBlock(pindexNew)) { i++; } diff --git a/src/zmq/zmqnotificationinterface.h b/src/zmq/zmqnotificationinterface.h index a853447267f31..037470ec17f9f 100644 --- a/src/zmq/zmqnotificationinterface.h +++ b/src/zmq/zmqnotificationinterface.h @@ -25,7 +25,7 @@ class CZMQNotificationInterface : public CValidationInterface // CValidationInterface void SyncTransaction(const CTransaction& tx, const CBlockIndex *pindex, int posInBlock); - void UpdatedBlockTip(const CBlockIndex *pindex); + void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload); private: CZMQNotificationInterface(); From 0278fb5f48ae9e42ec0772f85e201051077f633c Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 30 Sep 2016 18:19:57 -0400 Subject: [PATCH 0984/1802] Remove duplicate nBlocksEstimate cmp (we already checked IsIBD()) --- src/main.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 37a0a2f30d055..2eb641e543f6e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3087,12 +3087,9 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, } } // Relay inventory, but don't relay old inventory during initial block download. - int nBlockEstimate = 0; - if (fCheckpointsEnabled) - nBlockEstimate = Checkpoints::GetTotalBlocksEstimate(chainparams.Checkpoints()); if(connman) { - connman->ForEachNode([nNewHeight, nBlockEstimate, &vHashes](CNode* pnode) { - if (nNewHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate)) { + connman->ForEachNode([nNewHeight, &vHashes](CNode* pnode) { + if (nNewHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : 0)) { BOOST_REVERSE_FOREACH(const uint256& hash, vHashes) { pnode->PushBlockHash(hash); } From 6aa28abf53ef4694692474b4a3b0a8fa7559b50b Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 25 Jun 2016 19:17:45 +0200 Subject: [PATCH 0985/1802] Use cmpctblock type 2 for segwit-enabled transfer Contains version negotiation logic by Matt Corallo and bugfixes by Suhas Daftuar. --- src/blockencodings.cpp | 4 +- src/blockencodings.h | 2 +- src/main.cpp | 78 ++++++++++++++++++++++--------- src/test/blockencodings_tests.cpp | 6 +-- src/txmempool.cpp | 2 +- src/txmempool.h | 2 +- 6 files changed, 64 insertions(+), 30 deletions(-) diff --git a/src/blockencodings.cpp b/src/blockencodings.cpp index df237f8f26f58..93d3fa372b3c0 100644 --- a/src/blockencodings.cpp +++ b/src/blockencodings.cpp @@ -17,7 +17,7 @@ #define MIN_TRANSACTION_BASE_SIZE (::GetSerializeSize(CTransaction(), SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS)) -CBlockHeaderAndShortTxIDs::CBlockHeaderAndShortTxIDs(const CBlock& block) : +CBlockHeaderAndShortTxIDs::CBlockHeaderAndShortTxIDs(const CBlock& block, bool fUseWTXID) : nonce(GetRand(std::numeric_limits::max())), shorttxids(block.vtx.size() - 1), prefilledtxn(1), header(block) { FillShortTxIDSelector(); @@ -25,7 +25,7 @@ CBlockHeaderAndShortTxIDs::CBlockHeaderAndShortTxIDs(const CBlock& block) : prefilledtxn[0] = {0, block.vtx[0]}; for (size_t i = 1; i < block.vtx.size(); i++) { const CTransaction& tx = block.vtx[i]; - shorttxids[i - 1] = GetShortID(tx.GetHash()); + shorttxids[i - 1] = GetShortID(fUseWTXID ? tx.GetWitnessHash() : tx.GetHash()); } } diff --git a/src/blockencodings.h b/src/blockencodings.h index 349fcbd50f8c7..99b1cb140d0a4 100644 --- a/src/blockencodings.h +++ b/src/blockencodings.h @@ -146,7 +146,7 @@ class CBlockHeaderAndShortTxIDs { // Dummy for deserialization CBlockHeaderAndShortTxIDs() {} - CBlockHeaderAndShortTxIDs(const CBlock& block); + CBlockHeaderAndShortTxIDs(const CBlock& block, bool fUseWTXID); uint64_t GetShortID(const uint256& txhash) const; diff --git a/src/main.cpp b/src/main.cpp index 40c31b6ca6c76..c92a38be98f23 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -289,10 +289,21 @@ struct CNodeState { bool fPreferHeaders; //! Whether this peer wants invs or cmpctblocks (when possible) for block announcements. bool fPreferHeaderAndIDs; - //! Whether this peer will send us cmpctblocks if we request them + /** + * Whether this peer will send us cmpctblocks if we request them. + * This is not used to gate request logic, as we really only care about fSupportsDesiredCmpctVersion, + * but is used as a flag to "lock in" the version of compact blocks (fWantsCmpctWitness) we send. + */ bool fProvidesHeaderAndIDs; //! Whether this peer can give us witnesses bool fHaveWitness; + //! Whether this peer wants witnesses in cmpctblocks/blocktxns + bool fWantsCmpctWitness; + /** + * If we've announced NODE_WITNESS to this peer: whether the peer sends witnesses in cmpctblocks/blocktxns, + * otherwise: whether this peer sends non-witnesses in cmpctblocks/blocktxns. + */ + bool fSupportsDesiredCmpctVersion; CNodeState() { fCurrentlyConnected = false; @@ -313,6 +324,8 @@ struct CNodeState { fPreferHeaderAndIDs = false; fProvidesHeaderAndIDs = false; fHaveWitness = false; + fWantsCmpctWitness = false; + fSupportsDesiredCmpctVersion = false; } }; @@ -467,8 +480,8 @@ void UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) { } void MaybeSetPeerAsAnnouncingHeaderAndIDs(const CNodeState* nodestate, CNode* pfrom, CConnman& connman) { - if (pfrom->GetLocalServices() & NODE_WITNESS) { - // Don't ever request compact blocks when segwit is enabled. + if (!nodestate->fSupportsDesiredCmpctVersion) { + // Never ask from peers who can't provide witnesses. return; } if (nodestate->fProvidesHeaderAndIDs) { @@ -476,7 +489,7 @@ void MaybeSetPeerAsAnnouncingHeaderAndIDs(const CNodeState* nodestate, CNode* pf if (nodeid == pfrom->GetId()) return; bool fAnnounceUsingCMPCTBLOCK = false; - uint64_t nCMPCTBLOCKVersion = 1; + uint64_t nCMPCTBLOCKVersion = (pfrom->GetLocalServices() & NODE_WITNESS) ? 2 : 1; if (lNodesAnnouncingHeaderAndIDs.size() >= 3) { // As per BIP152, we only get 3 of our peers to announce // blocks using compact encodings. @@ -4856,11 +4869,12 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam // they wont have a useful mempool to match against a compact block, // and we don't feel like constructing the object for them, so // instead we respond with the full, non-compact block. + bool fPeerWantsWitness = State(pfrom->GetId())->fWantsCmpctWitness; if (mi->second->nHeight >= chainActive.Height() - 10) { - CBlockHeaderAndShortTxIDs cmpctblock(block); - pfrom->PushMessageWithFlag(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::CMPCTBLOCK, cmpctblock); + CBlockHeaderAndShortTxIDs cmpctblock(block, fPeerWantsWitness); + pfrom->PushMessageWithFlag(fPeerWantsWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::CMPCTBLOCK, cmpctblock); } else - pfrom->PushMessageWithFlag(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCK, block); + pfrom->PushMessageWithFlag(fPeerWantsWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCK, block); } // Trigger the peer node to send a getblocks request for the next batch of inventory @@ -5128,13 +5142,16 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, pfrom->PushMessage(NetMsgType::SENDHEADERS); } if (pfrom->nVersion >= SHORT_IDS_BLOCKS_VERSION) { - // Tell our peer we are willing to provide version-1 cmpctblocks + // Tell our peer we are willing to provide version 1 or 2 cmpctblocks // However, we do not request new block announcements using // cmpctblock messages. // We send this to non-NODE NETWORK peers as well, because // they may wish to request compact blocks from us bool fAnnounceUsingCMPCTBLOCK = false; - uint64_t nCMPCTBLOCKVersion = 1; + uint64_t nCMPCTBLOCKVersion = 2; + if (pfrom->GetLocalServices() & NODE_WITNESS) + pfrom->PushMessage(NetMsgType::SENDCMPCT, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion); + nCMPCTBLOCKVersion = 1; pfrom->PushMessage(NetMsgType::SENDCMPCT, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion); } } @@ -5195,12 +5212,23 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, else if (strCommand == NetMsgType::SENDCMPCT) { bool fAnnounceUsingCMPCTBLOCK = false; - uint64_t nCMPCTBLOCKVersion = 1; + uint64_t nCMPCTBLOCKVersion = 0; vRecv >> fAnnounceUsingCMPCTBLOCK >> nCMPCTBLOCKVersion; - if (nCMPCTBLOCKVersion == 1) { + if (nCMPCTBLOCKVersion == 1 || ((pfrom->GetLocalServices() & NODE_WITNESS) && nCMPCTBLOCKVersion == 2)) { LOCK(cs_main); - State(pfrom->GetId())->fProvidesHeaderAndIDs = true; - State(pfrom->GetId())->fPreferHeaderAndIDs = fAnnounceUsingCMPCTBLOCK; + // fProvidesHeaderAndIDs is used to "lock in" version of compact blocks we send (fWantsCmpctWitness) + if (!State(pfrom->GetId())->fProvidesHeaderAndIDs) { + State(pfrom->GetId())->fProvidesHeaderAndIDs = true; + State(pfrom->GetId())->fWantsCmpctWitness = nCMPCTBLOCKVersion == 2; + } + if (State(pfrom->GetId())->fWantsCmpctWitness == (nCMPCTBLOCKVersion == 2)) // ignore later version announces + State(pfrom->GetId())->fPreferHeaderAndIDs = fAnnounceUsingCMPCTBLOCK; + if (!State(pfrom->GetId())->fSupportsDesiredCmpctVersion) { + if (pfrom->GetLocalServices() & NODE_WITNESS) + State(pfrom->GetId())->fSupportsDesiredCmpctVersion = (nCMPCTBLOCKVersion == 2); + else + State(pfrom->GetId())->fSupportsDesiredCmpctVersion = (nCMPCTBLOCKVersion == 1); + } } } @@ -5258,7 +5286,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER && (!IsWitnessEnabled(chainActive.Tip(), chainparams.GetConsensus()) || State(pfrom->GetId())->fHaveWitness)) { inv.type |= nFetchFlags; - if (nodestate->fProvidesHeaderAndIDs && !(pfrom->GetLocalServices() & NODE_WITNESS)) + if (nodestate->fSupportsDesiredCmpctVersion) vToFetch.push_back(CInv(MSG_CMPCT_BLOCK, inv.hash)); else vToFetch.push_back(inv); @@ -5386,7 +5414,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } resp.txn[i] = block.vtx[req.indexes[i]]; } - pfrom->PushMessageWithFlag(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCKTXN, resp); + pfrom->PushMessageWithFlag(State(pfrom->GetId())->fWantsCmpctWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCKTXN, resp); } @@ -5650,7 +5678,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // We requested this block for some reason, but our mempool will probably be useless // so we just grab the block via normal getdata std::vector vInv(1); - vInv[0] = CInv(MSG_BLOCK, cmpctblock.header.GetHash()); + vInv[0] = CInv(MSG_BLOCK | GetFetchFlags(pfrom, pindex->pprev, chainparams.GetConsensus()), cmpctblock.header.GetHash()); pfrom->PushMessage(NetMsgType::GETDATA, vInv); } return true; @@ -5662,6 +5690,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, CNodeState *nodestate = State(pfrom->GetId()); + if (IsWitnessEnabled(pindex->pprev, chainparams.GetConsensus()) && !nodestate->fSupportsDesiredCmpctVersion) { + // Don't bother trying to process compact blocks from v1 peers + // after segwit activates. + return true; + } + // We want to be a bit conservative just to be extra careful about DoS // possibilities in compact block processing... if (pindex->nHeight <= chainActive.Height() + 2) { @@ -5688,7 +5722,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } else if (status == READ_STATUS_FAILED) { // Duplicate txindexes, the block is now in-flight, so just request it std::vector vInv(1); - vInv[0] = CInv(MSG_BLOCK, cmpctblock.header.GetHash()); + vInv[0] = CInv(MSG_BLOCK | GetFetchFlags(pfrom, pindex->pprev, chainparams.GetConsensus()), cmpctblock.header.GetHash()); pfrom->PushMessage(NetMsgType::GETDATA, vInv); return true; } @@ -5715,7 +5749,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // We requested this block, but its far into the future, so our // mempool will probably be useless - request the block normally std::vector vInv(1); - vInv[0] = CInv(MSG_BLOCK, cmpctblock.header.GetHash()); + vInv[0] = CInv(MSG_BLOCK | GetFetchFlags(pfrom, pindex->pprev, chainparams.GetConsensus()), cmpctblock.header.GetHash()); pfrom->PushMessage(NetMsgType::GETDATA, vInv); return true; } else { @@ -5757,7 +5791,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } else if (status == READ_STATUS_FAILED) { // Might have collided, fall back to getdata now :( std::vector invs; - invs.push_back(CInv(MSG_BLOCK, resp.blockhash)); + invs.push_back(CInv(MSG_BLOCK | GetFetchFlags(pfrom, chainActive.Tip(), chainparams.GetConsensus()), resp.blockhash)); pfrom->PushMessage(NetMsgType::GETDATA, invs); } else { CValidationState state; @@ -5906,7 +5940,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, pindexLast->GetBlockHash().ToString(), pindexLast->nHeight); } if (vGetData.size() > 0) { - if (nodestate->fProvidesHeaderAndIDs && vGetData.size() == 1 && mapBlocksInFlight.size() == 1 && pindexLast->pprev->IsValid(BLOCK_VALID_CHAIN) && !(pfrom->GetLocalServices() & NODE_WITNESS)) { + if (nodestate->fSupportsDesiredCmpctVersion && vGetData.size() == 1 && mapBlocksInFlight.size() == 1 && pindexLast->pprev->IsValid(BLOCK_VALID_CHAIN)) { // We seem to be rather well-synced, so it appears pfrom was the first to provide us // with this block! Let's get them to announce using compact blocks in the future. MaybeSetPeerAsAnnouncingHeaderAndIDs(nodestate, pfrom, connman); @@ -6536,8 +6570,8 @@ bool SendMessages(CNode* pto, CConnman& connman) //TODO: Shouldn't need to reload block from disk, but requires refactor CBlock block; assert(ReadBlockFromDisk(block, pBestIndex, consensusParams)); - CBlockHeaderAndShortTxIDs cmpctblock(block); - pto->PushMessageWithFlag(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::CMPCTBLOCK, cmpctblock); + CBlockHeaderAndShortTxIDs cmpctblock(block, state.fWantsCmpctWitness); + pto->PushMessageWithFlag(state.fWantsCmpctWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::CMPCTBLOCK, cmpctblock); state.pindexBestHeaderSent = pBestIndex; } else if (state.fPreferHeaders) { if (vHeaders.size() > 1) { diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp index d2392cfb22f0d..7530b013bd285 100644 --- a/src/test/blockencodings_tests.cpp +++ b/src/test/blockencodings_tests.cpp @@ -64,7 +64,7 @@ BOOST_AUTO_TEST_CASE(SimpleRoundTripTest) // Do a simple ShortTxIDs RT { - CBlockHeaderAndShortTxIDs shortIDs(block); + CBlockHeaderAndShortTxIDs shortIDs(block, true); CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); stream << shortIDs; @@ -116,7 +116,7 @@ class TestHeaderAndShortIDs { stream >> *this; } TestHeaderAndShortIDs(const CBlock& block) : - TestHeaderAndShortIDs(CBlockHeaderAndShortTxIDs(block)) {} + TestHeaderAndShortIDs(CBlockHeaderAndShortTxIDs(block, true)) {} uint64_t GetShortID(const uint256& txhash) const { CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); @@ -267,7 +267,7 @@ BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest) // Test simple header round-trip with only coinbase { - CBlockHeaderAndShortTxIDs shortIDs(block); + CBlockHeaderAndShortTxIDs shortIDs(block, false); CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); stream << shortIDs; diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 3586123d3e00d..15fa6fbca3b09 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -444,7 +444,7 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, totalTxSize += entry.GetTxSize(); minerPolicyEstimator->processTransaction(entry, fCurrentEstimate); - vTxHashes.emplace_back(hash, newit); + vTxHashes.emplace_back(tx.GetWitnessHash(), newit); newit->vTxHashesIdx = vTxHashes.size() - 1; return true; diff --git a/src/txmempool.h b/src/txmempool.h index 6f67dd91d685c..941644b2b21c1 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -465,7 +465,7 @@ class CTxMemPool indexed_transaction_set mapTx; typedef indexed_transaction_set::nth_index<0>::type::iterator txiter; - std::vector > vTxHashes; //!< All tx hashes/entries in mapTx, in random order + std::vector > vTxHashes; //!< All tx witness hashes/entries in mapTx, in random order struct CompareIteratorByHash { bool operator()(const txiter &a, const txiter &b) const { From f5b9b8f437c040205896ad0d7a6656efa08b5601 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Sat, 17 Sep 2016 22:11:00 -0400 Subject: [PATCH 0986/1802] [qa] Fix bug in mininode witness deserialization Also improve tx printing --- qa/rpc-tests/test_framework/mininode.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index 88a3b7e0f7144..34beb0d30d30f 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -452,7 +452,7 @@ def deserialize(self, f): else: self.vout = deser_vector(f, CTxOut) if flags != 0: - self.wit.vtxinwit = [CTxInWitness()]*len(self.vin) + self.wit.vtxinwit = [CTxInWitness() for i in range(len(self.vin))] self.wit.deserialize(f) self.nLockTime = struct.unpack(" Date: Wed, 14 Sep 2016 21:00:29 -0400 Subject: [PATCH 0987/1802] [qa] Add support for compactblocks v2 to mininode --- qa/rpc-tests/test_framework/mininode.py | 35 ++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index 34beb0d30d30f..4d238c08d9c3f 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -755,6 +755,9 @@ def serialize(self, with_witness=False): r += self.tx.serialize_without_witness() return r + def serialize_with_witness(self): + return self.serialize(with_witness=True) + def __repr__(self): return "PrefilledTransaction(index=%d, tx=%s)" % (self.index, repr(self.tx)) @@ -779,6 +782,7 @@ def deserialize(self, f): self.prefilled_txn = deser_vector(f, PrefilledTransaction) self.prefilled_txn_length = len(self.prefilled_txn) + # When using version 2 compact blocks, we must serialize with_witness. def serialize(self, with_witness=False): r = b"" r += self.header.serialize() @@ -787,12 +791,20 @@ def serialize(self, with_witness=False): for x in self.shortids: # We only want the first 6 bytes r += struct.pack(" Date: Fri, 16 Sep 2016 20:48:23 -0400 Subject: [PATCH 0988/1802] [qa] Update p2p-compactblocks.py for compactblocks v2 --- qa/rpc-tests/p2p-compactblocks.py | 583 ++++++++++++++++++++---------- 1 file changed, 389 insertions(+), 194 deletions(-) diff --git a/qa/rpc-tests/p2p-compactblocks.py b/qa/rpc-tests/p2p-compactblocks.py index ac4655a841ec5..d91e10d77cb4b 100755 --- a/qa/rpc-tests/p2p-compactblocks.py +++ b/qa/rpc-tests/p2p-compactblocks.py @@ -12,14 +12,16 @@ ''' CompactBlocksTest -- test compact blocks (BIP 152) -''' +Version 1 compact blocks are pre-segwit (txids) +Version 2 compact blocks are post-segwit (wtxids) +''' # TestNode: A peer we use to send messages to bitcoind, and store responses. class TestNode(SingleNodeConnCB): def __init__(self): SingleNodeConnCB.__init__(self) - self.last_sendcmpct = None + self.last_sendcmpct = [] self.last_headers = None self.last_inv = None self.last_cmpctblock = None @@ -30,7 +32,7 @@ def __init__(self): self.last_blocktxn = None def on_sendcmpct(self, conn, message): - self.last_sendcmpct = message + self.last_sendcmpct.append(message) def on_block(self, conn, message): self.last_block = message @@ -90,29 +92,31 @@ class CompactBlocksTest(BitcoinTestFramework): def __init__(self): super().__init__() self.setup_clean_chain = True - self.num_nodes = 1 + # Node0 = pre-segwit, node1 = segwit-aware + self.num_nodes = 2 self.utxos = [] def setup_network(self): self.nodes = [] - # Turn off segwit in this test, as compact blocks don't currently work - # with segwit. (After BIP 152 is updated to support segwit, we can - # test behavior with and without segwit enabled by adding a second node - # to the test.) - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [["-debug", "-logtimemicros=1", "-bip9params=segwit:0:0"]]) + # Start up node0 to be a version 1, pre-segwit node. + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, + [["-debug", "-logtimemicros=1", "-bip9params=segwit:0:0"], + ["-debug", "-logtimemicros", "-txindex"]]) + connect_nodes(self.nodes[0], 1) - def build_block_on_tip(self): - height = self.nodes[0].getblockcount() - tip = self.nodes[0].getbestblockhash() - mtp = self.nodes[0].getblockheader(tip)['mediantime'] + def build_block_on_tip(self, node): + height = node.getblockcount() + tip = node.getbestblockhash() + mtp = node.getblockheader(tip)['mediantime'] block = create_block(int(tip, 16), create_coinbase(height + 1), mtp + 1) block.solve() return block # Create 10 more anyone-can-spend utxo's for testing. def make_utxos(self): - block = self.build_block_on_tip() + # Doesn't matter which node we use, just use node0. + block = self.build_block_on_tip(self.nodes[0]) self.test_node.send_and_ping(msg_block(block)) assert(int(self.nodes[0].getbestblockhash(), 16) == block.sha256) self.nodes[0].generate(100) @@ -125,7 +129,7 @@ def make_utxos(self): tx.vout.append(CTxOut(out_value, CScript([OP_TRUE]))) tx.rehash() - block2 = self.build_block_on_tip() + block2 = self.build_block_on_tip(self.nodes[0]) block2.vtx.append(tx) block2.hashMerkleRoot = block2.calc_merkle_root() block2.solve() @@ -134,26 +138,30 @@ def make_utxos(self): self.utxos.extend([[tx.sha256, i, out_value] for i in range(10)]) return - # Test "sendcmpct": - # - No compact block announcements or getdata(MSG_CMPCT_BLOCK) unless - # sendcmpct is sent. - # - If sendcmpct is sent with version > 1, the message is ignored. + # Test "sendcmpct" (between peers preferring the same version): + # - No compact block announcements unless sendcmpct is sent. + # - If sendcmpct is sent with version > preferred_version, the message is ignored. # - If sendcmpct is sent with boolean 0, then block announcements are not # made with compact blocks. # - If sendcmpct is then sent with boolean 1, then new block announcements # are made with compact blocks. - def test_sendcmpct(self): - print("Testing SENDCMPCT p2p message... ") - - # Make sure we get a version 0 SENDCMPCT message from our peer + # If old_node is passed in, request compact blocks with version=preferred-1 + # and verify that it receives block announcements via compact block. + def test_sendcmpct(self, node, test_node, preferred_version, old_node=None): + # Make sure we get a SENDCMPCT message from our peer def received_sendcmpct(): - return (self.test_node.last_sendcmpct is not None) + return (len(test_node.last_sendcmpct) > 0) got_message = wait_until(received_sendcmpct, timeout=30) assert(received_sendcmpct()) assert(got_message) - assert_equal(self.test_node.last_sendcmpct.version, 1) + with mininode_lock: + # Check that the first version received is the preferred one + assert_equal(test_node.last_sendcmpct[0].version, preferred_version) + # And that we receive versions down to 1. + assert_equal(test_node.last_sendcmpct[-1].version, 1) + test_node.last_sendcmpct = [] - tip = int(self.nodes[0].getbestblockhash(), 16) + tip = int(node.getbestblockhash(), 16) def check_announcement_of_new_block(node, peer, predicate): peer.clear_block_announcement() @@ -165,56 +173,75 @@ def check_announcement_of_new_block(node, peer, predicate): assert(predicate(peer)) # We shouldn't get any block announcements via cmpctblock yet. - check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is None) + check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is None) # Try one more time, this time after requesting headers. - self.test_node.request_headers_and_sync(locator=[tip]) - check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is None and p.last_inv is not None) + test_node.request_headers_and_sync(locator=[tip]) + check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is None and p.last_inv is not None) # Test a few ways of using sendcmpct that should NOT # result in compact block announcements. # Before each test, sync the headers chain. - self.test_node.request_headers_and_sync(locator=[tip]) + test_node.request_headers_and_sync(locator=[tip]) # Now try a SENDCMPCT message with too-high version sendcmpct = msg_sendcmpct() - sendcmpct.version = 2 - self.test_node.send_and_ping(sendcmpct) - check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is None) + sendcmpct.version = preferred_version+1 + sendcmpct.announce = True + test_node.send_and_ping(sendcmpct) + check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is None) # Headers sync before next test. - self.test_node.request_headers_and_sync(locator=[tip]) + test_node.request_headers_and_sync(locator=[tip]) # Now try a SENDCMPCT message with valid version, but announce=False - self.test_node.send_and_ping(msg_sendcmpct()) - check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is None) + sendcmpct.version = preferred_version + sendcmpct.announce = False + test_node.send_and_ping(sendcmpct) + check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is None) # Headers sync before next test. - self.test_node.request_headers_and_sync(locator=[tip]) + test_node.request_headers_and_sync(locator=[tip]) # Finally, try a SENDCMPCT message with announce=True - sendcmpct.version = 1 + sendcmpct.version = preferred_version sendcmpct.announce = True - self.test_node.send_and_ping(sendcmpct) - check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is not None) + test_node.send_and_ping(sendcmpct) + check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is not None) # Try one more time (no headers sync should be needed!) - check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is not None) + check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is not None) # Try one more time, after turning on sendheaders - self.test_node.send_and_ping(msg_sendheaders()) - check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is not None) + test_node.send_and_ping(msg_sendheaders()) + check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is not None) + + # Try one more time, after sending a version-1, announce=false message. + sendcmpct.version = preferred_version-1 + sendcmpct.announce = False + test_node.send_and_ping(sendcmpct) + check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is not None) # Now turn off announcements + sendcmpct.version = preferred_version sendcmpct.announce = False - self.test_node.send_and_ping(sendcmpct) - check_announcement_of_new_block(self.nodes[0], self.test_node, lambda p: p.last_cmpctblock is None and p.last_headers is not None) + test_node.send_and_ping(sendcmpct) + check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is None and p.last_headers is not None) + + if old_node is not None: + # Verify that a peer using an older protocol version can receive + # announcements from this node. + sendcmpct.version = preferred_version-1 + sendcmpct.announce = True + old_node.send_and_ping(sendcmpct) + # Header sync + old_node.request_headers_and_sync(locator=[tip]) + check_announcement_of_new_block(node, old_node, lambda p: p.last_cmpctblock is not None) # This test actually causes bitcoind to (reasonably!) disconnect us, so do this last. def test_invalid_cmpctblock_message(self): - print("Testing invalid index in cmpctblock message...") self.nodes[0].generate(101) - block = self.build_block_on_tip() + block = self.build_block_on_tip(self.nodes[0]) cmpct_block = P2PHeaderAndShortIDs() cmpct_block.header = CBlockHeader(block) @@ -227,45 +254,61 @@ def test_invalid_cmpctblock_message(self): # Compare the generated shortids to what we expect based on BIP 152, given # bitcoind's choice of nonce. - def test_compactblock_construction(self): - print("Testing compactblock headers and shortIDs are correct...") - + def test_compactblock_construction(self, node, test_node, version, use_witness_address): # Generate a bunch of transactions. - self.nodes[0].generate(101) + node.generate(101) num_transactions = 25 - address = self.nodes[0].getnewaddress() + address = node.getnewaddress() + if use_witness_address: + # Want at least one segwit spend, so move all funds to + # a witness address. + address = node.addwitnessaddress(address) + value_to_send = node.getbalance() + node.sendtoaddress(address, satoshi_round(value_to_send-Decimal(0.1))) + node.generate(1) + + segwit_tx_generated = False for i in range(num_transactions): - self.nodes[0].sendtoaddress(address, 0.1) + txid = node.sendtoaddress(address, 0.1) + hex_tx = node.gettransaction(txid)["hex"] + tx = FromHex(CTransaction(), hex_tx) + if not tx.wit.is_null(): + segwit_tx_generated = True + + if use_witness_address: + assert(segwit_tx_generated) # check that our test is not broken self.test_node.sync_with_ping() # Now mine a block, and look at the resulting compact block. - self.test_node.clear_block_announcement() - block_hash = int(self.nodes[0].generate(1)[0], 16) + test_node.clear_block_announcement() + block_hash = int(node.generate(1)[0], 16) # Store the raw block in our internal format. - block = FromHex(CBlock(), self.nodes[0].getblock("%02x" % block_hash, False)) + block = FromHex(CBlock(), node.getblock("%02x" % block_hash, False)) [tx.calc_sha256() for tx in block.vtx] block.rehash() # Don't care which type of announcement came back for this test; just # request the compact block if we didn't get one yet. - wait_until(self.test_node.received_block_announcement, timeout=30) + wait_until(test_node.received_block_announcement, timeout=30) + assert(test_node.received_block_announcement()) with mininode_lock: - if self.test_node.last_cmpctblock is None: - self.test_node.clear_block_announcement() + if test_node.last_cmpctblock is None: + test_node.clear_block_announcement() inv = CInv(4, block_hash) # 4 == "CompactBlock" - self.test_node.send_message(msg_getdata([inv])) + test_node.send_message(msg_getdata([inv])) - wait_until(self.test_node.received_block_announcement, timeout=30) + wait_until(test_node.received_block_announcement, timeout=30) + assert(test_node.received_block_announcement()) # Now we should have the compactblock header_and_shortids = None with mininode_lock: - assert(self.test_node.last_cmpctblock is not None) + assert(test_node.last_cmpctblock is not None) # Convert the on-the-wire representation to absolute indexes - header_and_shortids = HeaderAndShortIDs(self.test_node.last_cmpctblock.header_and_shortids) + header_and_shortids = HeaderAndShortIDs(test_node.last_cmpctblock.header_and_shortids) # Check that we got the right block! header_and_shortids.header.calc_sha256() @@ -278,8 +321,17 @@ def test_compactblock_construction(self): # Check that all prefilled_txn entries match what's in the block. for entry in header_and_shortids.prefilled_txn: entry.tx.calc_sha256() + # This checks the non-witness parts of the tx agree assert_equal(entry.tx.sha256, block.vtx[entry.index].sha256) + # And this checks the witness + wtxid = entry.tx.calc_sha256(True) + if version == 2: + assert_equal(wtxid, block.vtx[entry.index].calc_sha256(True)) + else: + # Shouldn't have received a witness + assert(entry.tx.wit.is_null()) + # Check that the cmpctblock message announced all the transactions. assert_equal(len(header_and_shortids.prefilled_txn) + len(header_and_shortids.shortids), len(block.vtx)) @@ -294,7 +346,10 @@ def test_compactblock_construction(self): # Already checked prefilled transactions above header_and_shortids.prefilled_txn.pop(0) else: - shortid = calculate_shortid(k0, k1, block.vtx[index].sha256) + tx_hash = block.vtx[index].sha256 + if version == 2: + tx_hash = block.vtx[index].calc_sha256(True) + shortid = calculate_shortid(k0, k1, tx_hash) assert_equal(shortid, header_and_shortids.shortids[0]) header_and_shortids.shortids.pop(0) index += 1 @@ -302,49 +357,50 @@ def test_compactblock_construction(self): # Test that bitcoind requests compact blocks when we announce new blocks # via header or inv, and that responding to getblocktxn causes the block # to be successfully reconstructed. - def test_compactblock_requests(self): - print("Testing compactblock requests... ") - + # Post-segwit: upgraded nodes would only make this request of cb-version-2, + # NODE_WITNESS peers. Unupgraded nodes would still make this request of + # any cb-version-1-supporting peer. + def test_compactblock_requests(self, node, test_node): # Try announcing a block with an inv or header, expect a compactblock # request for announce in ["inv", "header"]: - block = self.build_block_on_tip() + block = self.build_block_on_tip(node) with mininode_lock: - self.test_node.last_getdata = None + test_node.last_getdata = None if announce == "inv": - self.test_node.send_message(msg_inv([CInv(2, block.sha256)])) + test_node.send_message(msg_inv([CInv(2, block.sha256)])) else: - self.test_node.send_header_for_blocks([block]) - success = wait_until(lambda: self.test_node.last_getdata is not None, timeout=30) + test_node.send_header_for_blocks([block]) + success = wait_until(lambda: test_node.last_getdata is not None, timeout=30) assert(success) - assert_equal(len(self.test_node.last_getdata.inv), 1) - assert_equal(self.test_node.last_getdata.inv[0].type, 4) - assert_equal(self.test_node.last_getdata.inv[0].hash, block.sha256) + assert_equal(len(test_node.last_getdata.inv), 1) + assert_equal(test_node.last_getdata.inv[0].type, 4) + assert_equal(test_node.last_getdata.inv[0].hash, block.sha256) # Send back a compactblock message that omits the coinbase comp_block = HeaderAndShortIDs() comp_block.header = CBlockHeader(block) comp_block.nonce = 0 comp_block.shortids = [1] # this is useless, and wrong - self.test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) - assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.hashPrevBlock) + test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) + assert_equal(int(node.getbestblockhash(), 16), block.hashPrevBlock) # Expect a getblocktxn message. with mininode_lock: - assert(self.test_node.last_getblocktxn is not None) - absolute_indexes = self.test_node.last_getblocktxn.block_txn_request.to_absolute() + assert(test_node.last_getblocktxn is not None) + absolute_indexes = test_node.last_getblocktxn.block_txn_request.to_absolute() assert_equal(absolute_indexes, [0]) # should be a coinbase request # Send the coinbase, and verify that the tip advances. msg = msg_blocktxn() msg.block_transactions.blockhash = block.sha256 msg.block_transactions.transactions = [block.vtx[0]] - self.test_node.send_and_ping(msg) - assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256) + test_node.send_and_ping(msg) + assert_equal(int(node.getbestblockhash(), 16), block.sha256) # Create a chain of transactions from given utxo, and add to a new block. - def build_block_with_transactions(self, utxo, num_transactions): - block = self.build_block_on_tip() + def build_block_with_transactions(self, node, utxo, num_transactions): + block = self.build_block_on_tip(node) for i in range(num_transactions): tx = CTransaction() @@ -361,118 +417,113 @@ def build_block_with_transactions(self, utxo, num_transactions): # Test that we only receive getblocktxn requests for transactions that the # node needs, and that responding to them causes the block to be # reconstructed. - def test_getblocktxn_requests(self): - print("Testing getblocktxn requests...") + def test_getblocktxn_requests(self, node, test_node, version): + with_witness = (version==2) + + def test_getblocktxn_response(compact_block, peer, expected_result): + msg = msg_cmpctblock(compact_block.to_p2p()) + peer.send_and_ping(msg) + with mininode_lock: + assert(peer.last_getblocktxn is not None) + absolute_indexes = peer.last_getblocktxn.block_txn_request.to_absolute() + assert_equal(absolute_indexes, expected_result) + + def test_tip_after_message(node, peer, msg, tip): + peer.send_and_ping(msg) + assert_equal(int(node.getbestblockhash(), 16), tip) # First try announcing compactblocks that won't reconstruct, and verify # that we receive getblocktxn messages back. utxo = self.utxos.pop(0) - block = self.build_block_with_transactions(utxo, 5) + block = self.build_block_with_transactions(node, utxo, 5) self.utxos.append([block.vtx[-1].sha256, 0, block.vtx[-1].vout[0].nValue]) - comp_block = HeaderAndShortIDs() - comp_block.initialize_from_block(block) + comp_block.initialize_from_block(block, use_witness=with_witness) - self.test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) - with mininode_lock: - assert(self.test_node.last_getblocktxn is not None) - absolute_indexes = self.test_node.last_getblocktxn.block_txn_request.to_absolute() - assert_equal(absolute_indexes, [1, 2, 3, 4, 5]) - msg = msg_blocktxn() - msg.block_transactions = BlockTransactions(block.sha256, block.vtx[1:]) - self.test_node.send_and_ping(msg) - assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256) + test_getblocktxn_response(comp_block, test_node, [1, 2, 3, 4, 5]) + + msg_bt = msg_blocktxn() + if with_witness: + msg_bt = msg_witness_blocktxn() # serialize with witnesses + msg_bt.block_transactions = BlockTransactions(block.sha256, block.vtx[1:]) + test_tip_after_message(node, test_node, msg_bt, block.sha256) utxo = self.utxos.pop(0) - block = self.build_block_with_transactions(utxo, 5) + block = self.build_block_with_transactions(node, utxo, 5) self.utxos.append([block.vtx[-1].sha256, 0, block.vtx[-1].vout[0].nValue]) # Now try interspersing the prefilled transactions - comp_block.initialize_from_block(block, prefill_list=[0, 1, 5]) - self.test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) - with mininode_lock: - assert(self.test_node.last_getblocktxn is not None) - absolute_indexes = self.test_node.last_getblocktxn.block_txn_request.to_absolute() - assert_equal(absolute_indexes, [2, 3, 4]) - msg.block_transactions = BlockTransactions(block.sha256, block.vtx[2:5]) - self.test_node.send_and_ping(msg) - assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256) + comp_block.initialize_from_block(block, prefill_list=[0, 1, 5], use_witness=with_witness) + test_getblocktxn_response(comp_block, test_node, [2, 3, 4]) + msg_bt.block_transactions = BlockTransactions(block.sha256, block.vtx[2:5]) + test_tip_after_message(node, test_node, msg_bt, block.sha256) # Now try giving one transaction ahead of time. utxo = self.utxos.pop(0) - block = self.build_block_with_transactions(utxo, 5) + block = self.build_block_with_transactions(node, utxo, 5) self.utxos.append([block.vtx[-1].sha256, 0, block.vtx[-1].vout[0].nValue]) - self.test_node.send_and_ping(msg_tx(block.vtx[1])) - assert(block.vtx[1].hash in self.nodes[0].getrawmempool()) + test_node.send_and_ping(msg_tx(block.vtx[1])) + assert(block.vtx[1].hash in node.getrawmempool()) # Prefill 4 out of the 6 transactions, and verify that only the one # that was not in the mempool is requested. - comp_block.initialize_from_block(block, prefill_list=[0, 2, 3, 4]) - self.test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) - with mininode_lock: - assert(self.test_node.last_getblocktxn is not None) - absolute_indexes = self.test_node.last_getblocktxn.block_txn_request.to_absolute() - assert_equal(absolute_indexes, [5]) + comp_block.initialize_from_block(block, prefill_list=[0, 2, 3, 4], use_witness=with_witness) + test_getblocktxn_response(comp_block, test_node, [5]) - msg.block_transactions = BlockTransactions(block.sha256, [block.vtx[5]]) - self.test_node.send_and_ping(msg) - assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256) + msg_bt.block_transactions = BlockTransactions(block.sha256, [block.vtx[5]]) + test_tip_after_message(node, test_node, msg_bt, block.sha256) # Now provide all transactions to the node before the block is # announced and verify reconstruction happens immediately. utxo = self.utxos.pop(0) - block = self.build_block_with_transactions(utxo, 10) + block = self.build_block_with_transactions(node, utxo, 10) self.utxos.append([block.vtx[-1].sha256, 0, block.vtx[-1].vout[0].nValue]) for tx in block.vtx[1:]: - self.test_node.send_message(msg_tx(tx)) - self.test_node.sync_with_ping() + test_node.send_message(msg_tx(tx)) + test_node.sync_with_ping() # Make sure all transactions were accepted. - mempool = self.nodes[0].getrawmempool() + mempool = node.getrawmempool() for tx in block.vtx[1:]: assert(tx.hash in mempool) # Clear out last request. with mininode_lock: - self.test_node.last_getblocktxn = None + test_node.last_getblocktxn = None # Send compact block - comp_block.initialize_from_block(block, prefill_list=[0]) - self.test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) + comp_block.initialize_from_block(block, prefill_list=[0], use_witness=with_witness) + test_tip_after_message(node, test_node, msg_cmpctblock(comp_block.to_p2p()), block.sha256) with mininode_lock: # Shouldn't have gotten a request for any transaction - assert(self.test_node.last_getblocktxn is None) - # Tip should have updated - assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256) + assert(test_node.last_getblocktxn is None) # Incorrectly responding to a getblocktxn shouldn't cause the block to be # permanently failed. - def test_incorrect_blocktxn_response(self): - print("Testing handling of incorrect blocktxn responses...") - + def test_incorrect_blocktxn_response(self, node, test_node, version): if (len(self.utxos) == 0): self.make_utxos() utxo = self.utxos.pop(0) - block = self.build_block_with_transactions(utxo, 10) + block = self.build_block_with_transactions(node, utxo, 10) self.utxos.append([block.vtx[-1].sha256, 0, block.vtx[-1].vout[0].nValue]) # Relay the first 5 transactions from the block in advance for tx in block.vtx[1:6]: - self.test_node.send_message(msg_tx(tx)) - self.test_node.sync_with_ping() + test_node.send_message(msg_tx(tx)) + test_node.sync_with_ping() # Make sure all transactions were accepted. - mempool = self.nodes[0].getrawmempool() + mempool = node.getrawmempool() for tx in block.vtx[1:6]: assert(tx.hash in mempool) # Send compact block comp_block = HeaderAndShortIDs() - comp_block.initialize_from_block(block, prefill_list=[0]) - self.test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) + comp_block.initialize_from_block(block, prefill_list=[0], use_witness=(version == 2)) + test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) absolute_indexes = [] with mininode_lock: - assert(self.test_node.last_getblocktxn is not None) - absolute_indexes = self.test_node.last_getblocktxn.block_txn_request.to_absolute() + assert(test_node.last_getblocktxn is not None) + absolute_indexes = test_node.last_getblocktxn.block_txn_request.to_absolute() assert_equal(absolute_indexes, [6, 7, 8, 9, 10]) # Now give an incorrect response. @@ -484,100 +535,107 @@ def test_incorrect_blocktxn_response(self): # verifying that the block isn't marked bad permanently. This is good # enough for now. msg = msg_blocktxn() + if version==2: + msg = msg_witness_blocktxn() msg.block_transactions = BlockTransactions(block.sha256, [block.vtx[5]] + block.vtx[7:]) - self.test_node.send_and_ping(msg) + test_node.send_and_ping(msg) # Tip should not have updated - assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.hashPrevBlock) + assert_equal(int(node.getbestblockhash(), 16), block.hashPrevBlock) # We should receive a getdata request - success = wait_until(lambda: self.test_node.last_getdata is not None, timeout=10) + success = wait_until(lambda: test_node.last_getdata is not None, timeout=10) assert(success) - assert_equal(len(self.test_node.last_getdata.inv), 1) - assert_equal(self.test_node.last_getdata.inv[0].type, 2) - assert_equal(self.test_node.last_getdata.inv[0].hash, block.sha256) + assert_equal(len(test_node.last_getdata.inv), 1) + assert(test_node.last_getdata.inv[0].type == 2 or test_node.last_getdata.inv[0].type == 2|MSG_WITNESS_FLAG) + assert_equal(test_node.last_getdata.inv[0].hash, block.sha256) # Deliver the block - self.test_node.send_and_ping(msg_block(block)) - assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256) - - def test_getblocktxn_handler(self): - print("Testing getblocktxn handler...") + if version==2: + test_node.send_and_ping(msg_witness_block(block)) + else: + test_node.send_and_ping(msg_block(block)) + assert_equal(int(node.getbestblockhash(), 16), block.sha256) + def test_getblocktxn_handler(self, node, test_node, version): # bitcoind won't respond for blocks whose height is more than 15 blocks # deep. MAX_GETBLOCKTXN_DEPTH = 15 - chain_height = self.nodes[0].getblockcount() + chain_height = node.getblockcount() current_height = chain_height while (current_height >= chain_height - MAX_GETBLOCKTXN_DEPTH): - block_hash = self.nodes[0].getblockhash(current_height) - block = FromHex(CBlock(), self.nodes[0].getblock(block_hash, False)) + block_hash = node.getblockhash(current_height) + block = FromHex(CBlock(), node.getblock(block_hash, False)) msg = msg_getblocktxn() msg.block_txn_request = BlockTransactionsRequest(int(block_hash, 16), []) num_to_request = random.randint(1, len(block.vtx)) msg.block_txn_request.from_absolute(sorted(random.sample(range(len(block.vtx)), num_to_request))) - self.test_node.send_message(msg) - success = wait_until(lambda: self.test_node.last_blocktxn is not None, timeout=10) + test_node.send_message(msg) + success = wait_until(lambda: test_node.last_blocktxn is not None, timeout=10) assert(success) [tx.calc_sha256() for tx in block.vtx] with mininode_lock: - assert_equal(self.test_node.last_blocktxn.block_transactions.blockhash, int(block_hash, 16)) + assert_equal(test_node.last_blocktxn.block_transactions.blockhash, int(block_hash, 16)) all_indices = msg.block_txn_request.to_absolute() for index in all_indices: - tx = self.test_node.last_blocktxn.block_transactions.transactions.pop(0) + tx = test_node.last_blocktxn.block_transactions.transactions.pop(0) tx.calc_sha256() assert_equal(tx.sha256, block.vtx[index].sha256) - self.test_node.last_blocktxn = None + if version == 1: + # Witnesses should have been stripped + assert(tx.wit.is_null()) + else: + # Check that the witness matches + assert_equal(tx.calc_sha256(True), block.vtx[index].calc_sha256(True)) + test_node.last_blocktxn = None current_height -= 1 # Next request should be ignored, as we're past the allowed depth. - block_hash = self.nodes[0].getblockhash(current_height) + block_hash = node.getblockhash(current_height) msg.block_txn_request = BlockTransactionsRequest(int(block_hash, 16), [0]) - self.test_node.send_and_ping(msg) + test_node.send_and_ping(msg) with mininode_lock: - assert_equal(self.test_node.last_blocktxn, None) - - def test_compactblocks_not_at_tip(self): - print("Testing compactblock requests/announcements not at chain tip...") + assert_equal(test_node.last_blocktxn, None) + def test_compactblocks_not_at_tip(self, node, test_node): # Test that requesting old compactblocks doesn't work. MAX_CMPCTBLOCK_DEPTH = 11 new_blocks = [] for i in range(MAX_CMPCTBLOCK_DEPTH): - self.test_node.clear_block_announcement() - new_blocks.append(self.nodes[0].generate(1)[0]) - wait_until(self.test_node.received_block_announcement, timeout=30) + test_node.clear_block_announcement() + new_blocks.append(node.generate(1)[0]) + wait_until(test_node.received_block_announcement, timeout=30) - self.test_node.clear_block_announcement() - self.test_node.send_message(msg_getdata([CInv(4, int(new_blocks[0], 16))])) - success = wait_until(lambda: self.test_node.last_cmpctblock is not None, timeout=30) + test_node.clear_block_announcement() + test_node.send_message(msg_getdata([CInv(4, int(new_blocks[0], 16))])) + success = wait_until(lambda: test_node.last_cmpctblock is not None, timeout=30) assert(success) - self.test_node.clear_block_announcement() - self.nodes[0].generate(1) - wait_until(self.test_node.received_block_announcement, timeout=30) - self.test_node.clear_block_announcement() - self.test_node.send_message(msg_getdata([CInv(4, int(new_blocks[0], 16))])) - success = wait_until(lambda: self.test_node.last_block is not None, timeout=30) + test_node.clear_block_announcement() + node.generate(1) + wait_until(test_node.received_block_announcement, timeout=30) + test_node.clear_block_announcement() + test_node.send_message(msg_getdata([CInv(4, int(new_blocks[0], 16))])) + success = wait_until(lambda: test_node.last_block is not None, timeout=30) assert(success) with mininode_lock: - self.test_node.last_block.block.calc_sha256() - assert_equal(self.test_node.last_block.block.sha256, int(new_blocks[0], 16)) + test_node.last_block.block.calc_sha256() + assert_equal(test_node.last_block.block.sha256, int(new_blocks[0], 16)) # Generate an old compactblock, and verify that it's not accepted. - cur_height = self.nodes[0].getblockcount() - hashPrevBlock = int(self.nodes[0].getblockhash(cur_height-5), 16) - block = self.build_block_on_tip() + cur_height = node.getblockcount() + hashPrevBlock = int(node.getblockhash(cur_height-5), 16) + block = self.build_block_on_tip(node) block.hashPrevBlock = hashPrevBlock block.solve() comp_block = HeaderAndShortIDs() comp_block.initialize_from_block(block) - self.test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) + test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) - tips = self.nodes[0].getchaintips() + tips = node.getchaintips() found = False for x in tips: if x["hash"] == block.hash: @@ -591,18 +649,61 @@ def test_compactblocks_not_at_tip(self): msg = msg_getblocktxn() msg.block_txn_request = BlockTransactionsRequest(block.sha256, [0]) with mininode_lock: - self.test_node.last_blocktxn = None - self.test_node.send_and_ping(msg) + test_node.last_blocktxn = None + test_node.send_and_ping(msg) with mininode_lock: - assert(self.test_node.last_blocktxn is None) + assert(test_node.last_blocktxn is None) + + def activate_segwit(self, node): + node.generate(144*3) + assert_equal(get_bip9_status(node, "segwit")["status"], 'active') + + def test_end_to_end_block_relay(self, node, listeners): + utxo = self.utxos.pop(0) + + block = self.build_block_with_transactions(node, utxo, 10) + + [l.clear_block_announcement() for l in listeners] + + # ToHex() won't serialize with witness, but this block has no witnesses + # anyway. TODO: repeat this test with witness tx's to a segwit node. + node.submitblock(ToHex(block)) + + for l in listeners: + wait_until(lambda: l.received_block_announcement(), timeout=30) + with mininode_lock: + for l in listeners: + assert(l.last_cmpctblock is not None) + l.last_cmpctblock.header_and_shortids.header.calc_sha256() + assert_equal(l.last_cmpctblock.header_and_shortids.header.sha256, block.sha256) + + # Helper for enabling cb announcements + # Send the sendcmpct request and sync headers + def request_cb_announcements(self, peer, node, version): + tip = node.getbestblockhash() + peer.get_headers(locator=[int(tip, 16)], hashstop=0) + + msg = msg_sendcmpct() + msg.version = version + msg.announce = True + peer.send_and_ping(msg) + def run_test(self): # Setup the p2p connections and start up the network thread. self.test_node = TestNode() + self.segwit_node = TestNode() + self.old_node = TestNode() # version 1 peer <--> segwit node connections = [] connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], self.test_node)) + connections.append(NodeConn('127.0.0.1', p2p_port(1), self.nodes[1], + self.segwit_node, services=NODE_NETWORK|NODE_WITNESS)) + connections.append(NodeConn('127.0.0.1', p2p_port(1), self.nodes[1], + self.old_node, services=NODE_NETWORK)) self.test_node.add_connection(connections[0]) + self.segwit_node.add_connection(connections[1]) + self.old_node.add_connection(connections[2]) NetworkThread().start() # Start up network handling in another thread @@ -612,13 +713,107 @@ def run_test(self): # We will need UTXOs to construct transactions in later tests. self.make_utxos() - self.test_sendcmpct() - self.test_compactblock_construction() - self.test_compactblock_requests() - self.test_getblocktxn_requests() - self.test_getblocktxn_handler() - self.test_compactblocks_not_at_tip() - self.test_incorrect_blocktxn_response() + print("Running tests, pre-segwit activation:") + + print("\tTesting SENDCMPCT p2p message... ") + self.test_sendcmpct(self.nodes[0], self.test_node, 1) + sync_blocks(self.nodes) + self.test_sendcmpct(self.nodes[1], self.segwit_node, 2, old_node=self.old_node) + sync_blocks(self.nodes) + + print("\tTesting compactblock construction...") + self.test_compactblock_construction(self.nodes[0], self.test_node, 1, False) + sync_blocks(self.nodes) + self.test_compactblock_construction(self.nodes[1], self.segwit_node, 2, False) + sync_blocks(self.nodes) + + print("\tTesting compactblock requests... ") + self.test_compactblock_requests(self.nodes[0], self.test_node) + sync_blocks(self.nodes) + self.test_compactblock_requests(self.nodes[1], self.segwit_node) + sync_blocks(self.nodes) + + print("\tTesting getblocktxn requests...") + self.test_getblocktxn_requests(self.nodes[0], self.test_node, 1) + sync_blocks(self.nodes) + self.test_getblocktxn_requests(self.nodes[1], self.segwit_node, 2) + sync_blocks(self.nodes) + + print("\tTesting getblocktxn handler...") + self.test_getblocktxn_handler(self.nodes[0], self.test_node, 1) + sync_blocks(self.nodes) + self.test_getblocktxn_handler(self.nodes[1], self.segwit_node, 2) + self.test_getblocktxn_handler(self.nodes[1], self.old_node, 1) + sync_blocks(self.nodes) + + print("\tTesting compactblock requests/announcements not at chain tip...") + self.test_compactblocks_not_at_tip(self.nodes[0], self.test_node) + sync_blocks(self.nodes) + self.test_compactblocks_not_at_tip(self.nodes[1], self.segwit_node) + self.test_compactblocks_not_at_tip(self.nodes[1], self.old_node) + sync_blocks(self.nodes) + + print("\tTesting handling of incorrect blocktxn responses...") + self.test_incorrect_blocktxn_response(self.nodes[0], self.test_node, 1) + sync_blocks(self.nodes) + self.test_incorrect_blocktxn_response(self.nodes[1], self.segwit_node, 2) + sync_blocks(self.nodes) + + # End-to-end block relay tests + print("\tTesting end-to-end block relay...") + self.request_cb_announcements(self.test_node, self.nodes[0], 1) + self.request_cb_announcements(self.old_node, self.nodes[1], 1) + self.request_cb_announcements(self.segwit_node, self.nodes[1], 2) + self.test_end_to_end_block_relay(self.nodes[0], [self.segwit_node, self.test_node, self.old_node]) + self.test_end_to_end_block_relay(self.nodes[1], [self.segwit_node, self.test_node, self.old_node]) + + # Advance to segwit activation + print ("\nAdvancing to segwit activation\n") + self.activate_segwit(self.nodes[1]) + print ("Running tests, post-segwit activation...") + + print("\tTesting compactblock construction...") + self.test_compactblock_construction(self.nodes[1], self.old_node, 1, True) + self.test_compactblock_construction(self.nodes[1], self.segwit_node, 2, True) + sync_blocks(self.nodes) + + print("\tTesting compactblock requests (unupgraded node)... ") + self.test_compactblock_requests(self.nodes[0], self.test_node) + + print("\tTesting getblocktxn requests (unupgraded node)...") + self.test_getblocktxn_requests(self.nodes[0], self.test_node, 1) + + # Need to manually sync node0 and node1, because post-segwit activation, + # node1 will not download blocks from node0. + print("\tSyncing nodes...") + assert(self.nodes[0].getbestblockhash() != self.nodes[1].getbestblockhash()) + while (self.nodes[0].getblockcount() > self.nodes[1].getblockcount()): + block_hash = self.nodes[0].getblockhash(self.nodes[1].getblockcount()+1) + self.nodes[1].submitblock(self.nodes[0].getblock(block_hash, False)) + assert_equal(self.nodes[0].getbestblockhash(), self.nodes[1].getbestblockhash()) + + print("\tTesting compactblock requests (segwit node)... ") + self.test_compactblock_requests(self.nodes[1], self.segwit_node) + + print("\tTesting getblocktxn requests (segwit node)...") + self.test_getblocktxn_requests(self.nodes[1], self.segwit_node, 2) + sync_blocks(self.nodes) + + print("\tTesting getblocktxn handler (segwit node should return witnesses)...") + self.test_getblocktxn_handler(self.nodes[1], self.segwit_node, 2) + self.test_getblocktxn_handler(self.nodes[1], self.old_node, 1) + + # Test that if we submitblock to node1, we'll get a compact block + # announcement to all peers. + # (Post-segwit activation, blocks won't propagate from node0 to node1 + # automatically, so don't bother testing a block announced to node0.) + print("\tTesting end-to-end block relay...") + self.request_cb_announcements(self.test_node, self.nodes[0], 1) + self.request_cb_announcements(self.old_node, self.nodes[1], 1) + self.request_cb_announcements(self.segwit_node, self.nodes[1], 2) + self.test_end_to_end_block_relay(self.nodes[1], [self.segwit_node, self.test_node, self.old_node]) + + print("\tTesting invalid index in cmpctblock message...") self.test_invalid_cmpctblock_message() From aefcb7b70c923ccd341329a2d5e22238dc14ac3b Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 4 Oct 2016 13:36:11 -0400 Subject: [PATCH 0989/1802] Move net-processing logic definitions together in main.h --- src/main.h | 56 +++++++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/src/main.h b/src/main.h index 2646d8f86b0a3..3c587569f635d 100644 --- a/src/main.h +++ b/src/main.h @@ -41,7 +41,6 @@ class CValidationInterface; class CValidationState; struct PrecomputedTransactionData; -struct CNodeStateStats; struct LockPoints; /** Default for DEFAULT_WHITELISTRELAY. */ @@ -206,11 +205,6 @@ static const unsigned int DEFAULT_CHECKLEVEL = 3; // Setting the target to > than 550MB will make it likely we can respect the target. static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024; -/** Register with a network node to receive its signals */ -void RegisterNodeSignals(CNodeSignals& nodeSignals); -/** Unregister a network node */ -void UnregisterNodeSignals(CNodeSignals& nodeSignals); - /** * Process an incoming block. This only returns after the best known valid * block is made active. Note that it does not, however, guarantee that the @@ -240,15 +234,6 @@ bool InitBlockIndex(const CChainParams& chainparams); bool LoadBlockIndex(); /** Unload database information */ void UnloadBlockIndex(); -/** Process protocol messages received from a given node */ -bool ProcessMessages(CNode* pfrom, CConnman& connman); -/** - * Send queued protocol messages to be sent to a give node. - * - * @param[in] pto The node which we are sending messages to. - * @param[in] connman The connection manager for that node. - */ -bool SendMessages(CNode* pto, CConnman& connman); /** Run an instance of the script checking thread */ void ThreadScriptCheck(); /** Check whether we are doing an initial block download (synchronizing from disk or network) */ @@ -291,10 +276,6 @@ void UnlinkPrunedFiles(std::set& setFilesToPrune); /** Create a new block index entry for a given block hash */ CBlockIndex * InsertBlockIndex(uint256 hash); -/** Get statistics from node state */ -bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats); -/** Increase a node's misbehavior score. */ -void Misbehaving(NodeId nodeid, int howmuch); /** Flush all state, indexes and buffers to disk. */ void FlushStateToDisk(); /** Prune block files and flush state to disk. */ @@ -310,13 +291,6 @@ std::string FormatStateMessage(const CValidationState &state); /** Get the BIP9 state for a given deployment at the current tip. */ ThresholdState VersionBitsTipState(const Consensus::Params& params, Consensus::DeploymentPos pos); -struct CNodeStateStats { - int nMisbehavior; - int nSyncHeight; - int nCommonHeight; - std::vector vHeightInFlight; -}; - /** @@ -545,4 +519,34 @@ static const unsigned int REJECT_ALREADY_KNOWN = 0x101; /** Transaction conflicts with a transaction already known */ static const unsigned int REJECT_CONFLICT = 0x102; +// The following things handle network-processing logic +// (and should be moved to a separate file) + +/** Register with a network node to receive its signals */ +void RegisterNodeSignals(CNodeSignals& nodeSignals); +/** Unregister a network node */ +void UnregisterNodeSignals(CNodeSignals& nodeSignals); + +struct CNodeStateStats { + int nMisbehavior; + int nSyncHeight; + int nCommonHeight; + std::vector vHeightInFlight; +}; + +/** Get statistics from node state */ +bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats); +/** Increase a node's misbehavior score. */ +void Misbehaving(NodeId nodeid, int howmuch); + +/** Process protocol messages received from a given node */ +bool ProcessMessages(CNode* pfrom, CConnman& connman); +/** + * Send queued protocol messages to be sent to a give node. + * + * @param[in] pto The node which we are sending messages to. + * @param[in] connman The connection manager for that node. + */ +bool SendMessages(CNode* pto, CConnman& connman); + #endif // BITCOIN_MAIN_H From fef1010199b70026fd6d56ebac5c277552757307 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 4 Oct 2016 13:49:44 -0400 Subject: [PATCH 0990/1802] Use CValidationInterface from chain logic to notify peer logic This adds a new CValidationInterface subclass, defined in main.h, to receive notifications of UpdatedBlockTip and use that to push blocks to peers, instead of doing it directly from ActivateBestChain. --- src/init.cpp | 5 +++++ src/main.cpp | 56 ++++++++++++++++++++++++++++++---------------------- src/main.h | 11 +++++++++++ 3 files changed, 48 insertions(+), 24 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index eefef7ba0b253..7045b3e6e1f4d 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -72,6 +72,7 @@ static const bool DEFAULT_DISABLE_SAFEMODE = false; static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false; std::unique_ptr g_connman; +std::unique_ptr peerLogic; #if ENABLE_ZMQ static CZMQNotificationInterface* pzmqNotificationInterface = NULL; @@ -200,6 +201,8 @@ void Shutdown() pwalletMain->Flush(false); #endif MapPort(false); + UnregisterValidationInterface(peerLogic.get()); + peerLogic.reset(); g_connman.reset(); StopTorControl(); @@ -1102,6 +1105,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) g_connman = std::unique_ptr(new CConnman(GetRand(std::numeric_limits::max()), GetRand(std::numeric_limits::max()))); CConnman& connman = *g_connman; + peerLogic.reset(new PeerLogicValidation(&connman)); + RegisterValidationInterface(peerLogic.get()); RegisterNodeSignals(GetNodeSignals()); // sanitize comments per BIP-0014, format user agent and check total size diff --git a/src/main.cpp b/src/main.cpp index 2eb641e543f6e..e042a73822b67 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3073,30 +3073,6 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, if (pindexFork != pindexNewTip) { uiInterface.NotifyBlockTip(fInitialDownload, pindexNewTip); - if (!fInitialDownload) { - // Find the hashes of all blocks that weren't previously in the best chain. - std::vector vHashes; - CBlockIndex *pindexToAnnounce = pindexNewTip; - while (pindexToAnnounce != pindexFork) { - vHashes.push_back(pindexToAnnounce->GetBlockHash()); - pindexToAnnounce = pindexToAnnounce->pprev; - if (vHashes.size() == MAX_BLOCKS_TO_ANNOUNCE) { - // Limit announcements in case of a huge reorganization. - // Rely on the peer's synchronization mechanism in that case. - break; - } - } - // Relay inventory, but don't relay old inventory during initial block download. - if(connman) { - connman->ForEachNode([nNewHeight, &vHashes](CNode* pnode) { - if (nNewHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : 0)) { - BOOST_REVERSE_FOREACH(const uint256& hash, vHashes) { - pnode->PushBlockHash(hash); - } - } - }); - } - } // Notify external listeners about the new tip. GetMainSignals().UpdatedBlockTip(pindexNewTip, pindexFork, fInitialDownload); } @@ -4682,6 +4658,38 @@ std::string GetWarnings(const std::string& strFor) +////////////////////////////////////////////////////////////////////////////// +// +// blockchain -> download logic notification +// + +void PeerLogicValidation::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) { + const int nNewHeight = pindexNew->nHeight; + + if (!fInitialDownload) { + // Find the hashes of all blocks that weren't previously in the best chain. + std::vector vHashes; + const CBlockIndex *pindexToAnnounce = pindexNew; + while (pindexToAnnounce != pindexFork) { + vHashes.push_back(pindexToAnnounce->GetBlockHash()); + pindexToAnnounce = pindexToAnnounce->pprev; + if (vHashes.size() == MAX_BLOCKS_TO_ANNOUNCE) { + // Limit announcements in case of a huge reorganization. + // Rely on the peer's synchronization mechanism in that case. + break; + } + } + // Relay inventory, but don't relay old inventory during initial block download. + connman->ForEachNode([nNewHeight, &vHashes](CNode* pnode) { + if (nNewHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : 0)) { + BOOST_REVERSE_FOREACH(const uint256& hash, vHashes) { + pnode->PushBlockHash(hash); + } + } + }); + } +} + ////////////////////////////////////////////////////////////////////////////// // // Messages diff --git a/src/main.h b/src/main.h index 3c587569f635d..bb5e26b0b2743 100644 --- a/src/main.h +++ b/src/main.h @@ -16,6 +16,7 @@ #include "net.h" #include "script/script_error.h" #include "sync.h" +#include "validationinterface.h" #include "versionbits.h" #include @@ -527,6 +528,16 @@ void RegisterNodeSignals(CNodeSignals& nodeSignals); /** Unregister a network node */ void UnregisterNodeSignals(CNodeSignals& nodeSignals); +class PeerLogicValidation : public CValidationInterface { +private: + CConnman* connman; + +public: + PeerLogicValidation(CConnman* connmanIn) : connman(connmanIn) {} + + virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload); +}; + struct CNodeStateStats { int nMisbehavior; int nSyncHeight; From f5efa283931ce1d52c59234b58988a221d42ecb4 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 30 Sep 2016 18:38:05 -0400 Subject: [PATCH 0991/1802] Remove CConnman parameter from ProcessNewBlock/ActivateBestChain --- src/main.cpp | 10 +++++----- src/main.h | 4 ++-- src/rpc/blockchain.cpp | 4 ++-- src/rpc/mining.cpp | 4 ++-- src/test/miner_tests.cpp | 2 +- src/test/test_bitcoin.cpp | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index e042a73822b67..4ad7348db0b43 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3013,7 +3013,7 @@ static void NotifyHeaderTip() { * or an activated best chain. pblock is either NULL or a pointer to a block * that is already loaded (to avoid loading it again from disk). */ -bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, const CBlock *pblock, CConnman* connman) { +bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, const CBlock *pblock) { CBlockIndex *pindexMostWork = NULL; CBlockIndex *pindexNewTip = NULL; std::vector> txChanged; @@ -3703,7 +3703,7 @@ static bool AcceptBlock(const CBlock& block, CValidationState& state, const CCha return true; } -bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp, CConnman* connman) +bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp) { { LOCK(cs_main); @@ -3725,7 +3725,7 @@ bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, C NotifyHeaderTip(); - if (!ActivateBestChain(state, chainparams, pblock, connman)) + if (!ActivateBestChain(state, chainparams, pblock)) return error("%s: ActivateBestChain failed", __func__); return true; @@ -5764,7 +5764,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, pfrom->PushMessage(NetMsgType::GETDATA, invs); } else { CValidationState state; - ProcessNewBlock(state, chainparams, pfrom, &block, false, NULL, &connman); + ProcessNewBlock(state, chainparams, pfrom, &block, false, NULL); int nDoS; if (state.IsInvalid(nDoS)) { assert (state.GetRejectCode() < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes @@ -5940,7 +5940,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // Such an unrequested block may still be processed, subject to the // conditions in AcceptBlock(). bool forceProcessing = pfrom->fWhitelisted && !IsInitialBlockDownload(); - ProcessNewBlock(state, chainparams, pfrom, &block, forceProcessing, NULL, &connman); + ProcessNewBlock(state, chainparams, pfrom, &block, forceProcessing, NULL); int nDoS; if (state.IsInvalid(nDoS)) { assert (state.GetRejectCode() < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes diff --git a/src/main.h b/src/main.h index bb5e26b0b2743..77179b25b98d8 100644 --- a/src/main.h +++ b/src/main.h @@ -218,7 +218,7 @@ static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024; * @param[out] dbp The already known disk position of pblock, or NULL if not yet stored. * @return True if state.IsValid() */ -bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp, CConnman* connman); +bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp); /** Check whether enough disk space is available for an incoming block */ bool CheckDiskSpace(uint64_t nAdditionalBytes = 0); /** Open a block file (blk?????.dat) */ @@ -250,7 +250,7 @@ std::string GetWarnings(const std::string& strFor); /** Retrieve a transaction (from memory pool, or from disk, if possible) */ bool GetTransaction(const uint256 &hash, CTransaction &tx, const Consensus::Params& params, uint256 &hashBlock, bool fAllowSlow = false); /** Find the best known block, and make it the tip of the block chain */ -bool ActivateBestChain(CValidationState& state, const CChainParams& chainparams, const CBlock* pblock = NULL, CConnman* connman = NULL); +bool ActivateBestChain(CValidationState& state, const CChainParams& chainparams, const CBlock* pblock = NULL); CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams); /** diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 41d862934a1b5..d85f6fed6380f 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1279,7 +1279,7 @@ UniValue invalidateblock(const UniValue& params, bool fHelp) } if (state.IsValid()) { - ActivateBestChain(state, Params(), NULL, g_connman.get()); + ActivateBestChain(state, Params(), NULL); } if (!state.IsValid()) { @@ -1317,7 +1317,7 @@ UniValue reconsiderblock(const UniValue& params, bool fHelp) } CValidationState state; - ActivateBestChain(state, Params(), NULL, g_connman.get()); + ActivateBestChain(state, Params(), NULL); if (!state.IsValid()) { throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 6b13aa5bab02a..a54931720e45b 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -131,7 +131,7 @@ UniValue generateBlocks(boost::shared_ptr coinbaseScript, int nG continue; } CValidationState state; - if (!ProcessNewBlock(state, Params(), NULL, pblock, true, NULL, g_connman.get())) + if (!ProcessNewBlock(state, Params(), NULL, pblock, true, NULL)) throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted"); ++nHeight; blockHashes.push_back(pblock->GetHash().GetHex()); @@ -757,7 +757,7 @@ UniValue submitblock(const UniValue& params, bool fHelp) CValidationState state; submitblock_StateCatcher sc(block.GetHash()); RegisterValidationInterface(&sc); - bool fAccepted = ProcessNewBlock(state, Params(), NULL, &block, true, NULL, g_connman.get()); + bool fAccepted = ProcessNewBlock(state, Params(), NULL, &block, true, NULL); UnregisterValidationInterface(&sc); if (fBlockPresent) { diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index d3aa2364d1f7b..15fceb963a59f 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -222,7 +222,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) pblock->hashMerkleRoot = BlockMerkleRoot(*pblock); pblock->nNonce = blockinfo[i].nonce; CValidationState state; - BOOST_CHECK(ProcessNewBlock(state, chainparams, NULL, pblock, true, NULL, connman)); + BOOST_CHECK(ProcessNewBlock(state, chainparams, NULL, pblock, true, NULL)); BOOST_CHECK(state.IsValid()); pblock->hashPrevBlock = pblock->GetHash(); } diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index 02843d8525ea0..f36c5486556b2 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -124,7 +124,7 @@ TestChain100Setup::CreateAndProcessBlock(const std::vector& while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce; CValidationState state; - ProcessNewBlock(state, chainparams, NULL, &block, true, NULL, connman); + ProcessNewBlock(state, chainparams, NULL, &block, true, NULL); CBlock result = block; delete pblocktemplate; From 12ee1fe018e99bba6c2b74940ece3b39a45ed8d3 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 4 Oct 2016 13:52:57 -0400 Subject: [PATCH 0992/1802] Always call UpdatedBlockTip, even if blocks were only disconnected --- src/main.cpp | 11 ++++------- src/zmq/zmqnotificationinterface.cpp | 2 +- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 4ad7348db0b43..189c265ec034e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3028,7 +3028,6 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, const CBlockIndex *pindexFork; std::list txConflicted; bool fInitialDownload; - int nNewHeight; { LOCK(cs_main); CBlockIndex *pindexOldTip = chainActive.Tip(); @@ -3051,13 +3050,10 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, pindexNewTip = chainActive.Tip(); pindexFork = chainActive.FindFork(pindexOldTip); fInitialDownload = IsInitialBlockDownload(); - nNewHeight = chainActive.Height(); } // When we reach this point, we switched to a new tip (stored in pindexNewTip). // Notifications/callbacks that can run without cs_main - if(connman) - connman->SetBestHeight(nNewHeight); // throw all transactions though the signal-interface // while _not_ holding the cs_main lock @@ -3069,12 +3065,12 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, for(unsigned int i = 0; i < txChanged.size(); i++) SyncWithWallets(std::get<0>(txChanged[i]), std::get<1>(txChanged[i]), std::get<2>(txChanged[i])); + // Notify external listeners about the new tip. + GetMainSignals().UpdatedBlockTip(pindexNewTip, pindexFork, fInitialDownload); + // Always notify the UI if a new block tip was connected if (pindexFork != pindexNewTip) { uiInterface.NotifyBlockTip(fInitialDownload, pindexNewTip); - - // Notify external listeners about the new tip. - GetMainSignals().UpdatedBlockTip(pindexNewTip, pindexFork, fInitialDownload); } } while (pindexNewTip != pindexMostWork); CheckBlockIndex(chainparams.GetConsensus()); @@ -4665,6 +4661,7 @@ std::string GetWarnings(const std::string& strFor) void PeerLogicValidation::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) { const int nNewHeight = pindexNew->nHeight; + connman->SetBestHeight(nNewHeight); if (!fInitialDownload) { // Find the hashes of all blocks that weren't previously in the best chain. diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp index 020cdfbdc724a..a0196fe18418c 100644 --- a/src/zmq/zmqnotificationinterface.cpp +++ b/src/zmq/zmqnotificationinterface.cpp @@ -126,7 +126,7 @@ void CZMQNotificationInterface::Shutdown() void CZMQNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) { - if (fInitialDownload) + if (fInitialDownload || pindexNew == pindexFork) // In IBD or blocks were disconnected without any new ones return; for (std::list::iterator i = notifiers.begin(); i!=notifiers.end(); ) From 7565e03b962cfa8d8e54aa0f9068f41194915523 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sat, 1 Oct 2016 15:29:40 -0400 Subject: [PATCH 0993/1802] Remove SyncWithWallets wrapper function --- src/main.cpp | 8 ++++---- src/validationinterface.cpp | 4 ---- src/validationinterface.h | 4 ++-- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 189c265ec034e..2f35288329a88 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1542,7 +1542,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C } } - SyncWithWallets(tx, NULL); + GetMainSignals().SyncTransaction(tx, NULL, CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK); return true; } @@ -2775,7 +2775,7 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara // Let wallets know transactions went from 1-confirmed to // 0-confirmed or conflicted: BOOST_FOREACH(const CTransaction &tx, block.vtx) { - SyncWithWallets(tx, pindexDelete->pprev); + GetMainSignals().SyncTransaction(tx, pindexDelete->pprev, CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK); } return true; } @@ -3059,11 +3059,11 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, // while _not_ holding the cs_main lock BOOST_FOREACH(const CTransaction &tx, txConflicted) { - SyncWithWallets(tx, pindexNewTip); + GetMainSignals().SyncTransaction(tx, pindexNewTip, CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK); } // ... and about transactions that got confirmed: for(unsigned int i = 0; i < txChanged.size(); i++) - SyncWithWallets(std::get<0>(txChanged[i]), std::get<1>(txChanged[i]), std::get<2>(txChanged[i])); + GetMainSignals().SyncTransaction(std::get<0>(txChanged[i]), std::get<1>(txChanged[i]), std::get<2>(txChanged[i])); // Notify external listeners about the new tip. GetMainSignals().UpdatedBlockTip(pindexNewTip, pindexFork, fInitialDownload); diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index d0aa7b5f393ff..085c336ccf6a9 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -47,7 +47,3 @@ void UnregisterAllValidationInterfaces() { g_signals.SyncTransaction.disconnect_all_slots(); g_signals.UpdatedBlockTip.disconnect_all_slots(); } - -void SyncWithWallets(const CTransaction &tx, const CBlockIndex *pindex, int posInBlock) { - g_signals.SyncTransaction(tx, pindex, posInBlock); -} diff --git a/src/validationinterface.h b/src/validationinterface.h index 683f8fe20cbae..a29859999bfab 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -28,8 +28,6 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn); void UnregisterValidationInterface(CValidationInterface* pwalletIn); /** Unregister all wallets from core */ void UnregisterAllValidationInterfaces(); -/** Push an updated transaction to all registered wallets */ -void SyncWithWallets(const CTransaction& tx, const CBlockIndex *pindex, int posInBlock = -1); class CValidationInterface { protected: @@ -50,6 +48,8 @@ class CValidationInterface { struct CMainSignals { /** Notifies listeners of updated block chain tip */ boost::signals2::signal UpdatedBlockTip; + /** A posInBlock value for SyncTransaction which indicates the transaction was conflicted, disconnected, or not in a block */ + static const int SYNC_TRANSACTION_NOT_IN_BLOCK = -1; /** Notifies listeners of updated transaction data (transaction, and optionally the block it is found in. */ boost::signals2::signal SyncTransaction; /** Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible). */ From a9aec5c24d8c4efe9e1ede54e8b8039b4b3f0835 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 4 Oct 2016 13:54:29 -0400 Subject: [PATCH 0994/1802] Use BlockChecked signal to send reject messages from mapBlockSource --- src/main.cpp | 32 ++++++++++++++++++++------------ src/main.h | 1 + 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 2f35288329a88..a6a43699cd296 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1857,17 +1857,6 @@ void static InvalidChainFound(CBlockIndex* pindexNew) } void static InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state) { - int nDoS = 0; - if (state.IsInvalid(nDoS)) { - std::map::iterator it = mapBlockSource.find(pindex->GetBlockHash()); - if (it != mapBlockSource.end() && State(it->second)) { - assert (state.GetRejectCode() < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes - CBlockReject reject = {(unsigned char)state.GetRejectCode(), state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), pindex->GetBlockHash()}; - State(it->second)->rejects.push_back(reject); - if (nDoS > 0) - Misbehaving(it->second, nDoS); - } - } if (!state.CorruptionPossible()) { pindex->nStatus |= BLOCK_FAILED_VALID; setDirtyBlockIndex.insert(pindex); @@ -2814,7 +2803,6 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, InvalidBlockFound(pindexNew, state); return error("ConnectTip(): ConnectBlock %s failed", pindexNew->GetBlockHash().ToString()); } - mapBlockSource.erase(pindexNew->GetBlockHash()); nTime3 = GetTimeMicros(); nTimeConnectTotal += nTime3 - nTime2; LogPrint("bench", " - Connect total: %.2fms [%.2fs]\n", (nTime3 - nTime2) * 0.001, nTimeConnectTotal * 0.000001); assert(view.Flush()); @@ -4687,6 +4675,26 @@ void PeerLogicValidation::UpdatedBlockTip(const CBlockIndex *pindexNew, const CB } } +void PeerLogicValidation::BlockChecked(const CBlock& block, const CValidationState& state) { + LOCK(cs_main); + + const uint256 hash(block.GetHash()); + std::map::iterator it = mapBlockSource.find(hash); + + int nDoS = 0; + if (state.IsInvalid(nDoS)) { + if (it != mapBlockSource.end() && State(it->second)) { + assert (state.GetRejectCode() < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes + CBlockReject reject = {(unsigned char)state.GetRejectCode(), state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), hash}; + State(it->second)->rejects.push_back(reject); + if (nDoS > 0) + Misbehaving(it->second, nDoS); + } + } + if (it != mapBlockSource.end()) + mapBlockSource.erase(it); +} + ////////////////////////////////////////////////////////////////////////////// // // Messages diff --git a/src/main.h b/src/main.h index 77179b25b98d8..889b6a2da1bf4 100644 --- a/src/main.h +++ b/src/main.h @@ -536,6 +536,7 @@ class PeerLogicValidation : public CValidationInterface { PeerLogicValidation(CConnman* connmanIn) : connman(connmanIn) {} virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload); + virtual void BlockChecked(const CBlock& block, const CValidationState& state); }; struct CNodeStateStats { From 6976db2f4687d575e1b4bee5aaf1d93a794f23c3 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Tue, 4 Oct 2016 15:17:19 -0400 Subject: [PATCH 0995/1802] [qa] Another attempt to fix race condition in p2p-compactblocks.py sync_with_ping() only guarantees that the node has processed messages it's received from the peer, not that block announcements from the node have made it back to the peer. Replace sync_with_ping() with an explicit check that the node's tip has been announced. --- qa/rpc-tests/p2p-compactblocks.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/qa/rpc-tests/p2p-compactblocks.py b/qa/rpc-tests/p2p-compactblocks.py index ac4655a841ec5..cd680437696a6 100755 --- a/qa/rpc-tests/p2p-compactblocks.py +++ b/qa/rpc-tests/p2p-compactblocks.py @@ -28,6 +28,10 @@ def __init__(self): self.last_getblocktxn = None self.last_block = None self.last_blocktxn = None + # Store the hashes of blocks we've seen announced. + # This is for synchronizing the p2p message traffic, + # so we can eg wait until a particular block is announced. + self.set_announced_blockhashes = set() def on_sendcmpct(self, conn, message): self.last_sendcmpct = message @@ -38,14 +42,22 @@ def on_block(self, conn, message): def on_cmpctblock(self, conn, message): self.last_cmpctblock = message self.block_announced = True + self.last_cmpctblock.header_and_shortids.header.calc_sha256() + self.set_announced_blockhashes.add(self.last_cmpctblock.header_and_shortids.header.sha256) def on_headers(self, conn, message): self.last_headers = message self.block_announced = True + for x in self.last_headers.headers: + x.calc_sha256() + self.set_announced_blockhashes.add(x.sha256) def on_inv(self, conn, message): self.last_inv = message - self.block_announced = True + for x in self.last_inv.inv: + if x.type == 2: + self.block_announced = True + self.set_announced_blockhashes.add(x.hash) def on_getdata(self, conn, message): self.last_getdata = message @@ -85,6 +97,12 @@ def request_headers_and_sync(self, locator, hashstop=0): assert(self.received_block_announcement()) self.clear_block_announcement() + # Block until a block announcement for a particular block hash is + # received. + def wait_for_block_announcement(self, block_hash, timeout=30): + def received_hash(): + return (block_hash in self.set_announced_blockhashes) + return wait_until(received_hash, timeout=timeout) class CompactBlocksTest(BitcoinTestFramework): def __init__(self): @@ -237,7 +255,9 @@ def test_compactblock_construction(self): for i in range(num_transactions): self.nodes[0].sendtoaddress(address, 0.1) - self.test_node.sync_with_ping() + # Wait until we've seen the block announcement for the resulting tip + tip = int(self.nodes[0].getbestblockhash(), 16) + assert(self.test_node.wait_for_block_announcement(tip)) # Now mine a block, and look at the resulting compact block. self.test_node.clear_block_announcement() From 1880aeb0336324ed543c7d181c7b1509bc1cce7a Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 8 Sep 2016 07:17:33 +0000 Subject: [PATCH 0996/1802] Qt: Get the private key for signing messages via WalletModel --- src/qt/signverifymessagedialog.cpp | 2 +- src/qt/walletmodel.cpp | 5 +++++ src/qt/walletmodel.h | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/qt/signverifymessagedialog.cpp b/src/qt/signverifymessagedialog.cpp index 96f50a26563ff..fa8cf9d6866e5 100644 --- a/src/qt/signverifymessagedialog.cpp +++ b/src/qt/signverifymessagedialog.cpp @@ -142,7 +142,7 @@ void SignVerifyMessageDialog::on_signMessageButton_SM_clicked() } CKey key; - if (!pwalletMain->GetKey(keyID, key)) + if (!model->getPrivKey(keyID, key)) { ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }"); ui->statusLabel_SM->setText(tr("Private key for the entered address is not available.")); diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 690ea0811e9a8..62655be5178e8 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -563,6 +563,11 @@ bool WalletModel::havePrivKey(const CKeyID &address) const return wallet->HaveKey(address); } +bool WalletModel::getPrivKey(const CKeyID &address, CKey& vchPrivKeyOut) const +{ + return wallet->GetKey(address, vchPrivKeyOut); +} + // returns a list of COutputs from COutPoints void WalletModel::getOutputs(const std::vector& vOutpoints, std::vector& vOutputs) { diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index a5e877d81f6aa..f15e5fc6f4d64 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -188,6 +188,7 @@ class WalletModel : public QObject bool getPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const; bool havePrivKey(const CKeyID &address) const; + bool getPrivKey(const CKeyID &address, CKey& vchPrivKeyOut) const; void getOutputs(const std::vector& vOutpoints, std::vector& vOutputs); bool isSpent(const COutPoint& outpoint) const; void listCoins(std::map >& mapCoins) const; From 178cd887eca1123fde39f530ee2b198db48363fe Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 8 Sep 2016 19:58:30 +0000 Subject: [PATCH 0997/1802] Qt/splash: Specifically keep track of which wallet(s) we are connected to for later disconnecting --- src/qt/splashscreen.cpp | 12 +++++++----- src/qt/splashscreen.h | 5 +++++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index c15b64c327f76..69ed44b81f9df 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -151,9 +151,10 @@ static void ShowProgress(SplashScreen *splash, const std::string &title, int nPr } #ifdef ENABLE_WALLET -static void ConnectWallet(SplashScreen *splash, CWallet* wallet) +void SplashScreen::ConnectWallet(CWallet* wallet) { - wallet->ShowProgress.connect(boost::bind(ShowProgress, splash, _1, _2)); + wallet->ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2)); + connectedWallets.push_back(wallet); } #endif @@ -163,7 +164,7 @@ void SplashScreen::subscribeToCoreSignals() uiInterface.InitMessage.connect(boost::bind(InitMessage, this, _1)); uiInterface.ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2)); #ifdef ENABLE_WALLET - uiInterface.LoadWallet.connect(boost::bind(ConnectWallet, this, _1)); + uiInterface.LoadWallet.connect(boost::bind(&SplashScreen::ConnectWallet, this, _1)); #endif } @@ -173,8 +174,9 @@ void SplashScreen::unsubscribeFromCoreSignals() uiInterface.InitMessage.disconnect(boost::bind(InitMessage, this, _1)); uiInterface.ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2)); #ifdef ENABLE_WALLET - if(pwalletMain) - pwalletMain->ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2)); + Q_FOREACH(CWallet* const & pwallet, connectedWallets) { + pwallet->ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2)); + } #endif } diff --git a/src/qt/splashscreen.h b/src/qt/splashscreen.h index 29d16d4eae2d6..8761343a7aafa 100644 --- a/src/qt/splashscreen.h +++ b/src/qt/splashscreen.h @@ -7,6 +7,7 @@ #include +class CWallet; class NetworkStyle; /** Class for the splashscreen with information of the running client. @@ -39,11 +40,15 @@ public Q_SLOTS: void subscribeToCoreSignals(); /** Disconnect core signals to splash screen */ void unsubscribeFromCoreSignals(); + /** Connect wallet signals to splash screen */ + void ConnectWallet(CWallet*); QPixmap pixmap; QString curMessage; QColor curColor; int curAlignment; + + QList connectedWallets; }; #endif // BITCOIN_QT_SPLASHSCREEN_H From a78e5428acb862bfb47e6faff39f4889f5c73269 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Tue, 4 Oct 2016 22:20:07 +0000 Subject: [PATCH 0998/1802] Bugfix: Trivial: RPC: getblockchaininfo help: pruneheight is the lowest, not highest, block --- src/rpc/blockchain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 20eefa1c574c5..675d9ba904c8c 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -892,7 +892,7 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) " \"verificationprogress\": xxxx, (numeric) estimate of verification progress [0..1]\n" " \"chainwork\": \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n" " \"pruned\": xx, (boolean) if the blocks are subject to pruning\n" - " \"pruneheight\": xxxxxx, (numeric) heighest block available\n" + " \"pruneheight\": xxxxxx, (numeric) lowest-height complete block stored\n" " \"softforks\": [ (array) status of softforks in progress\n" " {\n" " \"id\": \"xxxx\", (string) name of softfork\n" From cb78c60534e5be205f9190cb0cde700f9e9fa38d Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 4 Oct 2016 19:27:11 -0400 Subject: [PATCH 0999/1802] gui: fix ban from qt console Rather than doing a circle and re-resolving the node's IP, just use the one from nodestats directly. This requires syncing the addr field from CNode. --- src/net.cpp | 1 + src/net.h | 1 + src/qt/rpcconsole.cpp | 25 +++++++++++++------------ 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 770e2d2959998..19dd040997ad1 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -629,6 +629,7 @@ void CNode::copyStats(CNodeStats &stats) { stats.nodeid = this->GetId(); X(nServices); + X(addr); X(fRelayTxes); X(nLastSend); X(nLastRecv); diff --git a/src/net.h b/src/net.h index d0b2773623f43..67f0abe4be820 100644 --- a/src/net.h +++ b/src/net.h @@ -505,6 +505,7 @@ class CNodeStats double dPingWait; double dPingMin; std::string addrLocal; + CAddress addr; }; diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index ace9f1ceaad6b..b6ed75535c8d1 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -981,20 +981,21 @@ void RPCConsole::banSelectedNode(int bantime) if (!clientModel || !g_connman) return; - // Get currently selected peer address - QString strNode = GUIUtil::getEntryData(ui->peerWidget, 0, PeerTableModel::Address).toString(); - // Find possible nodes, ban it and clear the selected node - std::string nStr = strNode.toStdString(); - std::string addr; - int port = 0; - SplitHostPort(nStr, port, addr); + if(cachedNodeid == -1) + return; - CNetAddr resolved; - if(!LookupHost(addr.c_str(), resolved, false)) + // Get currently selected peer address + int detailNodeRow = clientModel->getPeerTableModel()->getRowByNodeId(cachedNodeid); + if(detailNodeRow < 0) return; - g_connman->Ban(resolved, BanReasonManuallyAdded, bantime); - clearSelectedNode(); - clientModel->getBanTableModel()->refresh(); + + // Find possible nodes, ban it and clear the selected node + const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats(detailNodeRow); + if(stats) { + g_connman->Ban(stats->nodeStats.addr, BanReasonManuallyAdded, bantime); + clearSelectedNode(); + clientModel->getBanTableModel()->refresh(); + } } void RPCConsole::unbanSelectedNode() From f2e939bdbceef1ee90d59fab9ab99b944b44bce1 Mon Sep 17 00:00:00 2001 From: fanquake Date: Wed, 5 Oct 2016 12:59:44 +0800 Subject: [PATCH 1000/1802] [Doc] Update Doxygen configuration file --- doc/Doxyfile | 2746 +++++++++++++++++++++++++++++++------------------- 1 file changed, 1727 insertions(+), 1019 deletions(-) diff --git a/doc/Doxyfile b/doc/Doxyfile index 22850db835429..a0cbf7139a42c 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -1,106 +1,122 @@ -# Doxyfile 1.7.4 - -# !!! Invoke doxygen from project root using: -# doxygen doc/Doxyfile +# Doxyfile 1.8.12 # This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. # -# All text after a hash (#) is considered a comment and will be ignored +# All text after a single hash (#) is considered a comment and will be ignored. # The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# http://www.gnu.org/software/libiconv for the list of possible encodings. +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. PROJECT_NAME = Bitcoin -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. PROJECT_NUMBER = 0.13.99 -# Using the PROJECT_BRIEF tag one can provide an optional one line description -# for a project that appears at the top of each page and should give viewer -# a quick idea about the purpose of the project. Keep the description short. +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = "P2P Digital Currency" -# With the PROJECT_LOGO tag one can specify an logo or icon that is -# included in the documentation. The maximum height of the logo should not -# exceed 55 pixels and the maximum width should not exceed 200 pixels. -# Doxygen will copy the logo to the output directory. +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. PROJECT_LOGO = doc/bitcoin_logo_doxygen.png -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. OUTPUT_DIRECTORY = doc/doxygen -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. CREATE_SUBDIRS = NO -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, -# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English -# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, -# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, -# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. OUTPUT_LANGUAGE = English -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. BRIEF_MEMBER_DESC = YES -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. +# The default value is: YES. REPEAT_BRIEF = YES -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ @@ -114,531 +130,690 @@ ABBREVIATE_BRIEF = "The $name class" \ an \ the -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief # description. +# The default value is: NO. ALWAYS_DETAILED_SEC = NO -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. +# The default value is: NO. INLINE_INHERITED_MEMB = NO -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. FULL_PATH_NAMES = YES -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. -STRIP_FROM_PATH = +STRIP_FROM_PATH = -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. -STRIP_FROM_INC_PATH = +STRIP_FROM_INC_PATH = -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful if your file system -# doesn't support long names like on DOS, Mac, or CD-ROM. +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. SHORT_NAMES = NO -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. JAVADOC_AUTOBRIEF = YES -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. QT_AUTOBRIEF = NO -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. INHERIT_DOCS = YES -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. SEPARATE_MEMBER_PAGES = NO -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 8 -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n in the value part of an alias to insert newlines. +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. -ALIASES = +TCL_SUBST = -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = NO -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for -# Java. For instance, namespaces will be presented as packages, qualified -# scopes will look different, etc. +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources only. Doxygen will then generate output that is more tailored for -# Fortran. +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for -# VHDL. +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO -# Doxygen selects the parser to use depending on the extension of the files it -# parses. With this tag you can assign which parser to use for a given extension. -# Doxygen has a built-in mapping, but you can override or extend it using this -# tag. The format is ext=language, where ext is a file extension, and language -# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, -# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make -# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C -# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions -# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. - -EXTENSION_MAPPING = - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also makes the inheritance and collaboration +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 0. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 0 + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. +# The default value is: NO. BUILTIN_STL_SUPPORT = NO -# If you use Microsoft's C++/CLI language, you should set this option to YES to +# If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. +# The default value is: NO. CPP_CLI_SUPPORT = NO -# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -# Doxygen will parse them like normal C++ but will assume all classes use public -# instead of private inheritance when no explicit protection keyword is present. +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. SIP_SUPPORT = NO -# For Microsoft's IDL there are propget and propput attributes to indicate getter -# and setter methods for a property. Setting this option to YES (the default) -# will make doxygen replace the get and set methods by a property in the -# documentation. This will only work if the methods are indeed getting or -# setting a simple type. If this is not the case, or you want to show the -# methods anyway, you should set this option to NO. +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. IDL_PROPERTY_SUPPORT = YES -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. +# The default value is: NO. DISTRIBUTE_GROUP_DOC = NO -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. SUBGROUPING = YES -# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and -# unions are shown inside the group in which they are included (e.g. using -# @ingroup) instead of on a separate page (for HTML and Man pages) or -# section (for LaTeX and RTF). +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. INLINE_GROUPED_CLASSES = NO -# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum -# is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically -# be useful for C code in case the coding convention dictates that all compound +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. TYPEDEF_HIDES_STRUCT = NO -# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to -# determine which symbols to keep in memory and which to flush to disk. -# When the cache is full, less often used symbols will be written to disk. -# For small to medium size projects (<1000 input files) the default value is -# probably good enough. For larger projects a too small cache size can cause -# doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penalty. -# If the system has enough physical memory increasing the cache will improve the -# performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will roughly double the -# memory usage. The cache size is given by this formula: -# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols - -SYMBOL_CACHE_SIZE = 0 +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. EXTRACT_ALL = YES -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. EXTRACT_PRIVATE = YES -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. EXTRACT_STATIC = NO -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. EXTRACT_LOCAL_CLASSES = YES -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. EXTRACT_LOCAL_METHODS = NO -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base -# name of the file that contains the anonymous namespace. By default -# anonymous namespaces are hidden. +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. EXTRACT_ANON_NSPACES = NO -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. HIDE_UNDOC_MEMBERS = NO -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. HIDE_UNDOC_CLASSES = NO -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO, these declarations will be +# included in the documentation. +# The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. HIDE_IN_BODY_DOCS = NO -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. INTERNAL_DOCS = NO -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES, upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. +# The default value is: system dependent. CASE_SENSE_NAMES = NO -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. HIDE_SCOPE_NAMES = NO -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. SHOW_INCLUDE_FILES = YES -# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen -# will list include files with double quotes in the documentation -# rather than with sharp brackets. +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. FORCE_LOCAL_INCLUDES = NO -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. INLINE_INFO = YES -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. SORT_MEMBER_DOCS = YES -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. SORT_BRIEF_DOCS = NO -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen -# will sort the (brief and detailed) documentation of class members so that -# constructors and destructors are listed first. If set to NO (the default) -# the constructors will appear in the respective orders defined by -# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. -# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO -# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -# hierarchy of group names into alphabetical order. If set to NO (the default) -# the group names will appear in their defined order. +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. SORT_GROUP_NAMES = NO -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. SORT_BY_SCOPE_NAME = NO -# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to -# do proper type resolution of all parameters of a function it will reject a -# match between the prototype and the implementation of a member function even -# if there is only one candidate or it is obvious which candidate to choose -# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen -# will still accept a match between prototype and implementation in such cases. +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. STRICT_PROTO_MATCHING = NO -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. GENERATE_TODOLIST = YES -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. GENERATE_TESTLIST = YES -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. GENERATE_BUGLIST = YES -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. GENERATE_DEPRECATEDLIST= YES -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. -ENABLED_SECTIONS = +ENABLED_SECTIONS = -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or macro consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and macros in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the # list will mention the files that were used to generate the documentation. +# The default value is: YES. SHOW_USED_FILES = YES -# If the sources in your project are distributed over multiple directories -# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy -# in the documentation. The default is NO. - -SHOW_DIRECTORIES = NO - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -# This will remove the Files entry from the Quick Index and from the -# Folder Tree View (if specified). The default is YES. +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. SHOW_FILES = YES -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the -# Namespaces page. This will remove the Namespaces entry from the Quick Index -# and from the Folder Tree View (if specified). The default is YES. +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. SHOW_NAMESPACES = YES -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command , where is the value of -# the FILE_VERSION_FILTER tag, and is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. -FILE_VERSION_FILTER = +LAYOUT_FILE = -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed -# by doxygen. The layout file controls the global structure of the generated -# output files in an output format independent way. The create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. -# You can optionally specify a file name after the option, if omitted -# DoxygenLayout.xml will be used as the name of the layout file. +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. -LAYOUT_FILE = +CITE_BIB_FILES = #--------------------------------------------------------------------------- -# configuration options related to warning and progress messages +# Configuration options related to warning and progress messages #--------------------------------------------------------------------------- -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. QUIET = NO -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. WARNINGS = YES -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. WARN_IF_UNDOCUMENTED = YES -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. WARN_IF_DOC_ERROR = YES -# The WARN_NO_PARAMDOC option can be enabled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. +# The default value is: NO. WARN_NO_PARAMDOC = NO -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). -WARN_LOGFILE = +WARN_LOGFILE = #--------------------------------------------------------------------------- -# configuration options related to the input files +# Configuration options related to the input files #--------------------------------------------------------------------------- -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. INPUT = src -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -# also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for -# the list of possible encodings. +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. INPUT_ENCODING = UTF-8 -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh -# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py -# *.f90 *.f *.for *.vhd *.vhdl +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, +# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf. FILE_PATTERNS = *.c \ *.cc \ @@ -673,875 +848,1300 @@ FILE_PATTERNS = *.c \ *.vhd \ *.vhdl -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. RECURSIVE = YES -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. -EXCLUDE = src/leveldb src/json src/test /src/qt/test +EXCLUDE = src/leveldb \ + src/json \ + src/test \ + src/qt/test -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or -# directories that are symbolic links (a Unix file system feature) are excluded +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded # from the input. +# The default value is: NO. EXCLUDE_SYMLINKS = NO -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* -EXCLUDE_PATTERNS = +EXCLUDE_PATTERNS = -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* -EXCLUDE_SYMBOLS = boost google +EXCLUDE_SYMBOLS = boost \ + google -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). -EXAMPLE_PATH = +EXAMPLE_PATH = -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. EXAMPLE_PATTERNS = * -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. EXAMPLE_RECURSIVE = NO -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). -IMAGE_PATH = +IMAGE_PATH = -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. If FILTER_PATTERNS is specified, this tag will be -# ignored. +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. -INPUT_FILTER = +FILTER_PATTERNS = -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty or if -# non of the patterns match the file name, INPUT_FILTER is applied. +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. -FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. -FILTER_SOURCE_FILES = NO +FILTER_SOURCE_PATTERNS = -# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file -# pattern. A pattern will override the setting for FILTER_PATTERN (if any) -# and it is also possible to disable source filtering for a specific pattern -# using *.ext= (so without naming a filter). This option only has effect when -# FILTER_SOURCE_FILES is enabled. +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. -FILTER_SOURCE_PATTERNS = +USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- -# configuration options related to source browsing +# Configuration options related to source browsing #--------------------------------------------------------------------------- -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. SOURCE_BROWSER = YES -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. INLINE_SOURCES = NO -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. STRIP_CODE_COMMENTS = YES -# If the REFERENCED_BY_RELATION tag is set to YES -# then for each documented function all documented -# functions referencing it will be listed. +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. REFERENCED_BY_RELATION = NO -# If the REFERENCES_RELATION tag is set to YES -# then for each documented function all documented entities -# called/used by that function will be listed. +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. REFERENCES_RELATION = NO -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. Otherwise they will link to the documentation. +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. REFERENCES_LINK_SOURCE = YES -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index +# Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. ALPHABETICAL_INDEX = YES -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 5 -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. -IGNORE_PREFIX = +IGNORE_PREFIX = #--------------------------------------------------------------------------- -# configuration options related to the HTML output +# Configuration options related to the HTML output #--------------------------------------------------------------------------- -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. GENERATE_HTML = YES -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. Note that when using a custom header you are responsible -# for the proper inclusion of any scripts and style sheets that doxygen -# needs, which is dependent on the configuration options used. -# It is adviced to generate a default header using "doxygen -w html -# header.html footer.html stylesheet.css YourConfigFile" and then modify -# that header. Note that the header is subject to change so you typically -# have to redo this when upgrading to a newer version of doxygen or when -# changing the value of configuration settings such as GENERATE_TREEVIEW! - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! - -HTML_STYLESHEET = - -# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or -# other source files which should be copied to the HTML output directory. Note -# that these files will be copied to the base HTML output directory. Use the -# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these -# files. In the HTML_STYLESHEET file, use the file name only. Also note that -# the files will be copied as-is; there are no commands or markers available. - -HTML_EXTRA_FILES = - -# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. -# Doxygen will adjust the colors in the stylesheet and background images -# according to this color. Hue is specified as an angle on a colorwheel, -# see http://en.wikipedia.org/wiki/Hue for more information. -# For instance the value 0 represents red, 60 is yellow, 120 is green, -# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. -# The allowed range is 0 to 359. +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 220 -# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of -# the colors in the HTML output. For a value of 0 the output will use -# grayscales only. A value of 255 will produce the most vivid colors. +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 100 -# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to -# the luminance component of the colors in the HTML output. Values below -# 100 gradually make the output lighter, whereas values above 100 make -# the output darker. The value divided by 100 is the actual gamma applied, -# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, -# and 100 does not change the gamma. +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 80 -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting -# this to NO can help when comparing the output of multiple runs. +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = YES -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. For this to work a browser that supports -# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox -# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO -# If the GENERATE_DOCSET tag is set to YES, additional index files -# will be generated that can be used as input for Apple's Xcode 3 -# integrated development environment, introduced with OSX 10.5 (Leopard). -# To create a documentation set, doxygen will generate a Makefile in the -# HTML output directory. Running make will produce the docset in that -# directory and running "make install" will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -# it at startup. -# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO -# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -# feed. A documentation feed provides an umbrella under which multiple -# documentation sets from a single provider (such as a company or product suite) -# can be grouped. +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" -# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -# should uniquely identify the documentation set bundle. This should be a -# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen -# will append .docset to the name. +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. -DOCSET_BUNDLE_ID = org.doxygen.Project +DOCSET_BUNDLE_ID = org.bitcoin.Bitcoin-Core -# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify -# the documentation publisher. This should be a reverse domain-name style +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. -DOCSET_PUBLISHER_ID = org.doxygen.Publisher +DOCSET_PUBLISHER_ID = org.bitcoin.Bitcoin-Core -# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) -# of the generated HTML documentation. +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be # written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. -CHM_FILE = +CHM_FILE = -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. -HHC_LOCATION = +HHC_LOCATION = -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING -# is used to encode HtmlHelp index (hhk), content (hhc) and project file -# content. +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. -CHM_INDEX_ENCODING = +CHM_INDEX_ENCODING = -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and -# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated -# that can be used as input for Qt's qhelpgenerator to generate a -# Qt Compressed Help (.qch) of the generated HTML documentation. +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can -# be used to specify the file name of the resulting .qch file. -# The path specified is relative to the HTML output folder. +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. -QCH_FILE = +QCH_FILE = -# The QHP_NAMESPACE tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#namespace +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#virtual-folders +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc -# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to -# add. For more information please see -# http://doc.trolltech.com/qthelpproject.html#custom-filters +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. -QHP_CUST_FILTER_NAME = +QHP_CUST_FILTER_NAME = -# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the -# custom filter to add. For more information please see -# -# Qt Help Project / Custom Filters. +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. -QHP_CUST_FILTER_ATTRS = +QHP_CUST_FILTER_ATTRS = -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this -# project's -# filter section matches. -# -# Qt Help Project / Filter Attributes. +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. -QHP_SECT_FILTER_ATTRS = +QHP_SECT_FILTER_ATTRS = -# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can -# be used to specify the location of Qt's qhelpgenerator. -# If non-empty doxygen will try to run qhelpgenerator on the generated -# .qhp file. +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. -QHG_LOCATION = +QHG_LOCATION = -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files -# will be generated, which together with the HTML files, form an Eclipse help -# plugin. To install this plugin and make it available under the help contents -# menu in Eclipse, the contents of the directory containing the HTML and XML -# files needs to be copied into the plugins directory of eclipse. The name of -# the directory within the plugins directory should be the same as -# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before -# the help appears. +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO -# A unique identifier for the eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have -# this name. +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO -# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values -# (range [0,1..20]) that doxygen will group on one line in the generated HTML -# documentation. Note that a value of 0 will completely suppress the enum -# values from appearing in the overview section. - -ENUM_VALUES_PER_LINE = 4 - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. -# If the tag value is set to YES, a side panel will be generated -# containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). -# Windows users are probably better off using the HTML help feature. +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NO -# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, -# and Class Hierarchy pages using a tree view instead of an ordered list. +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. -USE_INLINE_TREES = NO +ENUM_VALUES_PER_LINE = 4 -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 -# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open -# links to external symbols imported via tag files in a separate window. +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO -# Use this tag to change the font size of Latex formulas included -# as images in the HTML documentation. The default is 10. Note that -# when you change the font size after a successful doxygen run you need -# to manually remove any form_*.png images from the HTML output directory -# to force them to be regenerated. +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 -# Use the FORMULA_TRANPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are -# not supported properly for IE 6.0, but are supported on all modern browsers. -# Note that when changing this option you need to delete any form_*.png files -# in the HTML output before the changes have effect. +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES -# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax -# (see http://www.mathjax.org) which uses client side Javascript for the -# rendering instead of using prerendered bitmaps. Use this if you do not -# have LaTeX installed or if you want to formulas look prettier in the HTML -# output. When enabled you also need to install MathJax separately and -# configure the path to it using the MATHJAX_RELPATH option. +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO -# When MathJax is enabled you need to specify the location relative to the -# HTML output directory using the MATHJAX_RELPATH option. The destination -# directory should contain the MathJax.js script. For instance, if the mathjax -# directory is located at the same level as the HTML output directory, then -# MATHJAX_RELPATH should be ../mathjax. The default value points to the -# mathjax.org site, so you can quickly see the result without installing -# MathJax, but it is strongly recommended to install a local copy of MathJax -# before deployment. +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://www.mathjax.org/mathjax -# When the SEARCHENGINE tag is enabled doxygen will generate a search box -# for the HTML output. The underlying search engine uses javascript -# and DHTML and should work on any modern browser. Note that when using -# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets -# (GENERATE_DOCSET) there is already a search function so this one should -# typically be disabled. For large projects the javascript based search engine -# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , / 24 + + + diff --git a/src/qt/modaloverlay.cpp b/src/qt/modaloverlay.cpp index 5caade7d381c9..ae0d8f5f63676 100644 --- a/src/qt/modaloverlay.cpp +++ b/src/qt/modaloverlay.cpp @@ -77,7 +77,7 @@ void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVeri QDateTime currentDate = QDateTime::currentDateTime(); // keep a vector of samples of verification progress at height - blockProcessTime.push_front(qMakePair(currentDate.currentMSecsSinceEpoch(), nVerificationProgress)); + blockProcessTime.push_front(qMakePair(currentDate.toMSecsSinceEpoch(), nVerificationProgress)); // show progress speed if we have more then one sample if (blockProcessTime.size() >= 2) @@ -93,8 +93,7 @@ void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVeri QPair sample = blockProcessTime[i]; // take first sample after 500 seconds or last available one - if (sample.first < (currentDate.currentMSecsSinceEpoch() - 500*1000) || i == blockProcessTime.size()-1) - { + if (sample.first < (currentDate.toMSecsSinceEpoch() - 500 * 1000) || i == blockProcessTime.size() - 1) { progressDelta = progressStart-sample.second; timeDelta = blockProcessTime[0].first - sample.first; progressPerHour = progressDelta/(double)timeDelta*1000*3600; @@ -108,7 +107,6 @@ void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVeri // show expected remaining time ui->expectedTimeLeft->setText(GUIUtil::formateNiceTimeOffset(remainingMSecs/1000.0)); - // keep maximal 5000 samples static const int MAX_SAMPLES = 5000; if (blockProcessTime.count() > MAX_SAMPLES) blockProcessTime.remove(MAX_SAMPLES, blockProcessTime.count()-MAX_SAMPLES); From 4cdece40419bcc97345357f9268e03b0aff400b5 Mon Sep 17 00:00:00 2001 From: Dagur Valberg Johannsson Date: Sun, 9 Oct 2016 15:47:55 -0400 Subject: [PATCH 1010/1802] [qa] Fix compact block shortids for a test case --- qa/rpc-tests/p2p-compactblocks.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/qa/rpc-tests/p2p-compactblocks.py b/qa/rpc-tests/p2p-compactblocks.py index d91e10d77cb4b..97e7190d16f13 100755 --- a/qa/rpc-tests/p2p-compactblocks.py +++ b/qa/rpc-tests/p2p-compactblocks.py @@ -382,7 +382,9 @@ def test_compactblock_requests(self, node, test_node): comp_block = HeaderAndShortIDs() comp_block.header = CBlockHeader(block) comp_block.nonce = 0 - comp_block.shortids = [1] # this is useless, and wrong + [k0, k1] = comp_block.get_siphash_keys() + comp_block.shortids = [ + calculate_shortid(k0, k1, block.vtx[0].sha256) ] test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) assert_equal(int(node.getbestblockhash(), 16), block.hashPrevBlock) # Expect a getblocktxn message. From 8aed5f6c23cbaae6bf56be04f2b8d861eacf588d Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 11 Oct 2016 17:41:45 +0200 Subject: [PATCH 1011/1802] qt: Translate all files, even if wallet disabled This passes all QT cpp files to the lupdate executable which extracts translations, no matter what conditional functionality is enabled. --- src/Makefile.qt.include | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index a2ed4f47d8de7..1f9a901d75882 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -289,7 +289,7 @@ RES_ICONS = \ qt/res/icons/warning.png \ qt/res/icons/verify.png -BITCOIN_QT_CPP = \ +BITCOIN_QT_BASE_CPP = \ qt/bantablemodel.cpp \ qt/bitcoinaddressvalidator.cpp \ qt/bitcoinamountfield.cpp \ @@ -313,12 +313,9 @@ BITCOIN_QT_CPP = \ qt/trafficgraphwidget.cpp \ qt/utilitydialog.cpp -if TARGET_WINDOWS -BITCOIN_QT_CPP += qt/winshutdownmonitor.cpp -endif +BITCOIN_QT_WINDOWS_CPP = qt/winshutdownmonitor.cpp -if ENABLE_WALLET -BITCOIN_QT_CPP += \ +BITCOIN_QT_WALLET_CPP = \ qt/addressbookpage.cpp \ qt/addresstablemodel.cpp \ qt/askpassphrasedialog.cpp \ @@ -345,6 +342,13 @@ BITCOIN_QT_CPP += \ qt/walletmodel.cpp \ qt/walletmodeltransaction.cpp \ qt/walletview.cpp + +BITCOIN_QT_CPP = $(BITCOIN_QT_BASE_CPP) +if TARGET_WINDOWS +BITCOIN_QT_CPP += $(BITCOIN_QT_WINDOWS_CPP) +endif +if ENABLE_WALLET +BITCOIN_QT_CPP += $(BITCOIN_QT_WALLET_CPP) endif RES_IMAGES = @@ -413,7 +417,7 @@ $(srcdir)/qt/bitcoinstrings.cpp: $(libbitcoin_server_a_SOURCES) $(libbitcoin_wal @test -n $(XGETTEXT) || echo "xgettext is required for updating translations" $(AM_V_GEN) cd $(srcdir); XGETTEXT=$(XGETTEXT) PACKAGE_NAME="$(PACKAGE_NAME)" COPYRIGHT_HOLDERS="$(COPYRIGHT_HOLDERS)" COPYRIGHT_HOLDERS_SUBSTITUTION="$(COPYRIGHT_HOLDERS_SUBSTITUTION)" $(PYTHON) ../share/qt/extract_strings_qt.py $^ -translate: $(srcdir)/qt/bitcoinstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_QT_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM) +translate: $(srcdir)/qt/bitcoinstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_QT_BASE_CPP) $(BITCOIN_QT_WINDOWS_CPP) $(BITCOIN_QT_WALLET_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM) @test -n $(LUPDATE) || echo "lupdate is required for updating translations" $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(LUPDATE) $^ -locations relative -no-obsolete -ts $(srcdir)/qt/locale/bitcoin_en.ts From 3f92bc9e83094421d4bfd3802fc98ac9e26405e1 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 5 Oct 2016 10:58:57 +0200 Subject: [PATCH 1012/1802] doc: Add build instructions for FreeBSD --- doc/build-unix.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/doc/build-unix.md b/doc/build-unix.md index 62e3e793e97f3..5202072f8b8e1 100644 --- a/doc/build-unix.md +++ b/doc/build-unix.md @@ -308,3 +308,35 @@ To build executables for ARM: For further documentation on the depends system see [README.md](../depends/README.md) in the depends directory. + +Building on FreeBSD +-------------------- + +(Updated as of FreeBSD 10.3) + +Clang is installed by default as `cc` compiler, this makes it easier to get +started than on [OpenBSD](build-openbsd.md). Installing dependencies: + + pkg install autoconf automake libtool pkgconf + pkg install boost-libs openssl libevent2 + +(`libressl` instead of `openssl` will also work) + +For the wallet (optional): + + pkg install db5 + +This will give a warning "configure: WARNING: Found Berkeley DB other +than 4.8; wallets opened by this build will not be portable!", but as FreeBSD never +had a binary release, this may not matter. If backwards compatibility +with 4.8-built Bitcoin Core is needed follow the steps under "Berkeley DB" above. + +Then build using: + + ./autogen.sh + ./configure --with-incompatible-bdb CPPFLAGS=-I/usr/local/include/db5 LDFLAGS=-L/usr/local/lib/db5 + make + +*Note on debugging*: The version of `gdb` installed by default is [ancient and considered harmful](https://wiki.freebsd.org/GdbRetirement). +It is not suitable for debugging a multi-threaded C++ program, not even for getting backtraces. Please install the package `gdb` and +use the versioned gdb command e.g. `gdb7111`. From 36f60a5d5b1bc9a12b87d6475e3245b8236775e4 Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Thu, 13 Oct 2016 19:31:52 +0200 Subject: [PATCH 1013/1802] Add copyright/patent issues to possible NACK reasons Adding in response to a Slack discussion where someone was unclear on the fact that a NACK may be justified if code can't be accepted due to copyright/patent issues. For example, it would be reasonable and prudent to NACK a contribution of AGPL-licensed consensus code on the basis that the license terms are incompatible with the MIT license used by the rest of the codebase. --- CONTRIBUTING.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fd1a912c4fdf7..06fcd8dd81301 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -178,7 +178,9 @@ language is used within pull-request comments: - ACK means "I have tested the code and I agree it should be merged"; - NACK means "I disagree this should be merged", and must be accompanied by - sound technical justification. NACKs without accompanying reasoning may be disregarded; + sound technical justification (or in certain cases of copyright/patent/licensing + issues, legal justification). NACKs without accompanying reasoning may be + disregarded; - utACK means "I have not tested the code, but I have reviewed it and it looks OK, I agree it can be merged"; - Concept ACK means "I agree in the general principle of this pull request"; From 21f5a6364d5bad738d51e75ff96c8f8b88557d11 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 13 Oct 2016 23:27:26 +0000 Subject: [PATCH 1014/1802] Qt: Add "Copy URI" to payment request context menu --- src/qt/receivecoinsdialog.cpp | 39 ++++++++++++++++++++++++++++------- src/qt/receivecoinsdialog.h | 2 ++ 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp index 7fb68cc32a209..e89f06484ce46 100644 --- a/src/qt/receivecoinsdialog.cpp +++ b/src/qt/receivecoinsdialog.cpp @@ -43,18 +43,21 @@ ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *platformStyle, QWidg } // context menu actions + QAction *copyURIAction = new QAction(tr("Copy URI"), this); QAction *copyLabelAction = new QAction(tr("Copy label"), this); QAction *copyMessageAction = new QAction(tr("Copy message"), this); QAction *copyAmountAction = new QAction(tr("Copy amount"), this); // context menu contextMenu = new QMenu(); + contextMenu->addAction(copyURIAction); contextMenu->addAction(copyLabelAction); contextMenu->addAction(copyMessageAction); contextMenu->addAction(copyAmountAction); // context menu signals connect(ui->recentRequestsView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showMenu(QPoint))); + connect(copyURIAction, SIGNAL(triggered()), this, SLOT(copyURI())); connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(copyLabel())); connect(copyMessageAction, SIGNAL(triggered()), this, SLOT(copyMessage())); connect(copyAmountAction, SIGNAL(triggered()), this, SLOT(copyAmount())); @@ -227,30 +230,50 @@ void ReceiveCoinsDialog::keyPressEvent(QKeyEvent *event) this->QDialog::keyPressEvent(event); } -// copy column of selected row to clipboard -void ReceiveCoinsDialog::copyColumnToClipboard(int column) +QModelIndex ReceiveCoinsDialog::selectedRow() { if(!model || !model->getRecentRequestsTableModel() || !ui->recentRequestsView->selectionModel()) - return; + return QModelIndex(); QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows(); if(selection.empty()) - return; + return QModelIndex(); // correct for selection mode ContiguousSelection QModelIndex firstIndex = selection.at(0); + return firstIndex; +} + +// copy column of selected row to clipboard +void ReceiveCoinsDialog::copyColumnToClipboard(int column) +{ + QModelIndex firstIndex = selectedRow(); + if (!firstIndex.isValid()) { + return; + } GUIUtil::setClipboard(model->getRecentRequestsTableModel()->data(firstIndex.child(firstIndex.row(), column), Qt::EditRole).toString()); } // context menu void ReceiveCoinsDialog::showMenu(const QPoint &point) { - if(!model || !model->getRecentRequestsTableModel() || !ui->recentRequestsView->selectionModel()) - return; - QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows(); - if(selection.empty()) + if (!selectedRow().isValid()) { return; + } contextMenu->exec(QCursor::pos()); } +// context menu action: copy URI +void ReceiveCoinsDialog::copyURI() +{ + QModelIndex sel = selectedRow(); + if (!sel.isValid()) { + return; + } + + const RecentRequestsTableModel * const submodel = model->getRecentRequestsTableModel(); + const QString uri = GUIUtil::formatBitcoinURI(submodel->entry(sel.row()).recipient); + GUIUtil::setClipboard(uri); +} + // context menu action: copy label void ReceiveCoinsDialog::copyLabel() { diff --git a/src/qt/receivecoinsdialog.h b/src/qt/receivecoinsdialog.h index eaaf129a91d5d..9612da318c9be 100644 --- a/src/qt/receivecoinsdialog.h +++ b/src/qt/receivecoinsdialog.h @@ -60,6 +60,7 @@ public Q_SLOTS: QMenu *contextMenu; const PlatformStyle *platformStyle; + QModelIndex selectedRow(); void copyColumnToClipboard(int column); virtual void resizeEvent(QResizeEvent *event); @@ -71,6 +72,7 @@ private Q_SLOTS: void recentRequestsView_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected); void updateDisplayUnit(); void showMenu(const QPoint &point); + void copyURI(); void copyLabel(); void copyMessage(); void copyAmount(); From 032e883b937a6b70d5c367fc2ee57d7eea8cb473 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 14 Oct 2016 12:54:15 -0400 Subject: [PATCH 1015/1802] [qa] Send segwit-encoded blocktxn messages in p2p-compactblocks --- qa/rpc-tests/p2p-compactblocks.py | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/qa/rpc-tests/p2p-compactblocks.py b/qa/rpc-tests/p2p-compactblocks.py index e7f5a1c9c6f81..1beab609b68ef 100755 --- a/qa/rpc-tests/p2p-compactblocks.py +++ b/qa/rpc-tests/p2p-compactblocks.py @@ -6,7 +6,7 @@ from test_framework.mininode import * from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * -from test_framework.blocktools import create_block, create_coinbase +from test_framework.blocktools import create_block, create_coinbase, add_witness_commitment from test_framework.siphash import siphash256 from test_framework.script import CScript, OP_TRUE @@ -123,11 +123,13 @@ def setup_network(self): ["-debug", "-logtimemicros", "-txindex"]]) connect_nodes(self.nodes[0], 1) - def build_block_on_tip(self, node): + def build_block_on_tip(self, node, segwit=False): height = node.getblockcount() tip = node.getbestblockhash() mtp = node.getblockheader(tip)['mediantime'] block = create_block(int(tip, 16), create_coinbase(height + 1), mtp + 1) + if segwit: + add_witness_commitment(block) block.solve() return block @@ -380,11 +382,11 @@ def test_compactblock_construction(self, node, test_node, version, use_witness_a # Post-segwit: upgraded nodes would only make this request of cb-version-2, # NODE_WITNESS peers. Unupgraded nodes would still make this request of # any cb-version-1-supporting peer. - def test_compactblock_requests(self, node, test_node): + def test_compactblock_requests(self, node, test_node, version, segwit): # Try announcing a block with an inv or header, expect a compactblock # request for announce in ["inv", "header"]: - block = self.build_block_on_tip(node) + block = self.build_block_on_tip(node, segwit=segwit) with mininode_lock: test_node.last_getdata = None @@ -403,8 +405,11 @@ def test_compactblock_requests(self, node, test_node): comp_block.header = CBlockHeader(block) comp_block.nonce = 0 [k0, k1] = comp_block.get_siphash_keys() + coinbase_hash = block.vtx[0].sha256 + if version == 2: + coinbase_hash = block.vtx[0].calc_sha256(True) comp_block.shortids = [ - calculate_shortid(k0, k1, block.vtx[0].sha256) ] + calculate_shortid(k0, k1, coinbase_hash) ] test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) assert_equal(int(node.getbestblockhash(), 16), block.hashPrevBlock) # Expect a getblocktxn message. @@ -414,7 +419,10 @@ def test_compactblock_requests(self, node, test_node): assert_equal(absolute_indexes, [0]) # should be a coinbase request # Send the coinbase, and verify that the tip advances. - msg = msg_blocktxn() + if version == 2: + msg = msg_witness_blocktxn() + else: + msg = msg_blocktxn() msg.block_transactions.blockhash = block.sha256 msg.block_transactions.transactions = [block.vtx[0]] test_node.send_and_ping(msg) @@ -750,9 +758,9 @@ def run_test(self): sync_blocks(self.nodes) print("\tTesting compactblock requests... ") - self.test_compactblock_requests(self.nodes[0], self.test_node) + self.test_compactblock_requests(self.nodes[0], self.test_node, 1, False) sync_blocks(self.nodes) - self.test_compactblock_requests(self.nodes[1], self.segwit_node) + self.test_compactblock_requests(self.nodes[1], self.segwit_node, 2, False) sync_blocks(self.nodes) print("\tTesting getblocktxn requests...") @@ -800,7 +808,7 @@ def run_test(self): sync_blocks(self.nodes) print("\tTesting compactblock requests (unupgraded node)... ") - self.test_compactblock_requests(self.nodes[0], self.test_node) + self.test_compactblock_requests(self.nodes[0], self.test_node, 1, True) print("\tTesting getblocktxn requests (unupgraded node)...") self.test_getblocktxn_requests(self.nodes[0], self.test_node, 1) @@ -815,7 +823,7 @@ def run_test(self): assert_equal(self.nodes[0].getbestblockhash(), self.nodes[1].getbestblockhash()) print("\tTesting compactblock requests (segwit node)... ") - self.test_compactblock_requests(self.nodes[1], self.segwit_node) + self.test_compactblock_requests(self.nodes[1], self.segwit_node, 2, True) print("\tTesting getblocktxn requests (segwit node)...") self.test_getblocktxn_requests(self.nodes[1], self.segwit_node, 2) From 1724a405c9065f2c939e936aca9b5d37fca5e954 Mon Sep 17 00:00:00 2001 From: R E Broadley Date: Fri, 14 Oct 2016 21:11:38 +0700 Subject: [PATCH 1016/1802] Display minimum ping in debug window. --- src/net.cpp | 2 +- src/net.h | 2 +- src/qt/forms/debugwindow.ui | 27 +++++++++++++++++++++++++-- src/qt/guiutil.cpp | 2 +- src/qt/peertablemodel.cpp | 6 +++--- src/qt/rpcconsole.cpp | 1 + src/rpc/net.cpp | 4 ++-- 7 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 19dd040997ad1..0f719a9c7f430 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -659,7 +659,7 @@ void CNode::copyStats(CNodeStats &stats) // Raw ping time is in microseconds, but show it to user as whole seconds (Bitcoin users should be well used to small numbers with many decimal places by now :) stats.dPingTime = (((double)nPingUsecTime) / 1e6); - stats.dPingMin = (((double)nMinPingUsecTime) / 1e6); + stats.dMinPing = (((double)nMinPingUsecTime) / 1e6); stats.dPingWait = (((double)nPingUsecWait) / 1e6); // Leave string empty if addrLocal invalid (not filled in yet) diff --git a/src/net.h b/src/net.h index 67f0abe4be820..90a4db2c63eea 100644 --- a/src/net.h +++ b/src/net.h @@ -503,7 +503,7 @@ class CNodeStats bool fWhitelisted; double dPingTime; double dPingWait; - double dPingMin; + double dMinPing; std::string addrLocal; CAddress addr; }; diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui index 9dc641979e084..8be4a955b3d34 100644 --- a/src/qt/forms/debugwindow.ui +++ b/src/qt/forms/debugwindow.ui @@ -1353,13 +1353,36 @@ + + + Min Ping + + + + + + + IBeamCursor + + + N/A + + + Qt::PlainText + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + Time Offset - + IBeamCursor @@ -1375,7 +1398,7 @@ - + Qt::Vertical diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 0beaddf997cda..42dafa1175605 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -947,7 +947,7 @@ QString formatServicesStr(quint64 mask) QString formatPingTime(double dPingTime) { - return dPingTime == 0 ? QObject::tr("N/A") : QString(QObject::tr("%1 ms")).arg(QString::number((int)(dPingTime * 1000), 10)); + return (dPingTime == std::numeric_limits::max()/1e6 || dPingTime == 0) ? QObject::tr("N/A") : QString(QObject::tr("%1 ms")).arg(QString::number((int)(dPingTime * 1000), 10)); } QString formatTimeOffset(int64_t nTimeOffset) diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp index a820bd791f70b..a2f9471fcc688 100644 --- a/src/qt/peertablemodel.cpp +++ b/src/qt/peertablemodel.cpp @@ -31,7 +31,7 @@ bool NodeLessThan::operator()(const CNodeCombinedStats &left, const CNodeCombine case PeerTableModel::Subversion: return pLeft->cleanSubVer.compare(pRight->cleanSubVer) < 0; case PeerTableModel::Ping: - return pLeft->dPingTime < pRight->dPingTime; + return pLeft->dMinPing < pRight->dMinPing; } return false; @@ -113,7 +113,7 @@ PeerTableModel::PeerTableModel(ClientModel *parent) : clientModel(parent), timer(0) { - columns << tr("NodeId") << tr("Node/Service") << tr("User Agent") << tr("Ping Time"); + columns << tr("NodeId") << tr("Node/Service") << tr("User Agent") << tr("Ping"); priv = new PeerTablePriv(); // default to unsorted priv->sortColumn = -1; @@ -166,7 +166,7 @@ QVariant PeerTableModel::data(const QModelIndex &index, int role) const case Subversion: return QString::fromStdString(rec->nodeStats.cleanSubVer); case Ping: - return GUIUtil::formatPingTime(rec->nodeStats.dPingTime); + return GUIUtil::formatPingTime(rec->nodeStats.dMinPing); } } else if (role == Qt::TextAlignmentRole) { if (index.column() == Ping) diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index b6ed75535c8d1..a1017e6c16bb8 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -895,6 +895,7 @@ void RPCConsole::updateNodeDetail(const CNodeCombinedStats *stats) ui->peerConnTime->setText(GUIUtil::formatDurationStr(GetTime() - stats->nodeStats.nTimeConnected)); ui->peerPingTime->setText(GUIUtil::formatPingTime(stats->nodeStats.dPingTime)); ui->peerPingWait->setText(GUIUtil::formatPingTime(stats->nodeStats.dPingWait)); + ui->peerMinPing->setText(GUIUtil::formatPingTime(stats->nodeStats.dMinPing)); ui->timeoffset->setText(GUIUtil::formatTimeOffset(stats->nodeStats.nTimeOffset)); ui->peerVersion->setText(QString("%1").arg(QString::number(stats->nodeStats.nVersion))); ui->peerSubversion->setText(QString::fromStdString(stats->nodeStats.cleanSubVer)); diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index b011029f51c29..a8442d86929b7 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -141,8 +141,8 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp) obj.push_back(Pair("timeoffset", stats.nTimeOffset)); if (stats.dPingTime > 0.0) obj.push_back(Pair("pingtime", stats.dPingTime)); - if (stats.dPingMin < std::numeric_limits::max()/1e6) - obj.push_back(Pair("minping", stats.dPingMin)); + if (stats.dMinPing < std::numeric_limits::max()/1e6) + obj.push_back(Pair("minping", stats.dMinPing)); if (stats.dPingWait > 0.0) obj.push_back(Pair("pingwait", stats.dPingWait)); obj.push_back(Pair("version", stats.nVersion)); From acf853df910339412bafb1743f42af1774f5b910 Mon Sep 17 00:00:00 2001 From: Johnson Lau Date: Sat, 15 Oct 2016 23:45:07 +0800 Subject: [PATCH 1017/1802] Add script tests for FindAndDelete in pre-segwit and segwit scripts --- src/script/interpreter.cpp | 4 ++-- src/test/data/tx_invalid.json | 26 ++++++++++++++++++++++++++ src/test/data/tx_valid.json | 23 +++++++++++++++++++++++ 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 41756ea71196d..e0f2f89190d93 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -874,7 +874,7 @@ bool EvalScript(vector >& stack, const CScript& script, un // Subset of script starting at the most recent codeseparator CScript scriptCode(pbegincodehash, pend); - // Drop the signature, since there's no way for a signature to sign itself + // Drop the signature in pre-segwit scripts but not segwit scripts if (sigversion == SIGVERSION_BASE) { scriptCode.FindAndDelete(CScript(vchSig)); } @@ -935,7 +935,7 @@ bool EvalScript(vector >& stack, const CScript& script, un // Subset of script starting at the most recent codeseparator CScript scriptCode(pbegincodehash, pend); - // Drop the signatures, since there's no way for a signature to sign itself + // Drop the signature in pre-segwit scripts but not segwit scripts for (int k = 0; k < nSigsCount; k++) { valtype& vchSig = stacktop(-isig-k); diff --git a/src/test/data/tx_invalid.json b/src/test/data/tx_invalid.json index f8baee05779c3..f7d9e1847ffa0 100644 --- a/src/test/data/tx_invalid.json +++ b/src/test/data/tx_invalid.json @@ -314,5 +314,31 @@ [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x21 0xff25429251b5a84f452230a3c75fd886b7fc5a7865ce4a7bb7a9d7c5be6da3dbff", 1000]], "010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH,WITNESS,DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"], +["FindAndDelete tests"], +["This is a test of FindAndDelete. The first tx is a spend of normal scriptPubKey and the second tx is a spend of bare P2WSH."], +["The redeemScript/witnessScript is CHECKSIGVERIFY <0x30450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e01>."], +["The signature is <0x30450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e01> ,"], +["where the pubkey is obtained through key recovery with sig and the wrong sighash."], +["This is to show that FindAndDelete is applied only to non-segwit scripts"], +["To show that the tests are 'correctly wrong', they should pass by modifying OP_CHECKSIG under interpreter.cpp"], +["by replacing (sigversion == SIGVERSION_BASE) with (sigversion != SIGVERSION_BASE)"], +["Non-segwit: wrong sighash (without FindAndDelete) = 1ba1fe3bc90c5d1265460e684ce6774e324f0fabdf67619eda729e64e8b6bc08"], +[[["f18783ace138abac5d3a7a5cf08e88fe6912f267ef936452e0c27d090621c169", 7000, "HASH160 0x14 0x0c746489e2d83cdbb5b90b432773342ba809c134 EQUAL", 200000]], +"010000000169c12106097dc2e0526493ef67f21269fe888ef05c7a3a5dacab38e1ac8387f1581b0000b64830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e012103b12a1ec8428fc74166926318c15e17408fea82dbb157575e16a8c365f546248f4aad4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e01ffffffff0101000000000000000000000000", "P2SH,WITNESS"], +["BIP143: wrong sighash (with FindAndDelete) = 71c9cd9b2869b9c70b01b1f0360c148f42dee72297db312638df136f43311f23"], +[[["f18783ace138abac5d3a7a5cf08e88fe6912f267ef936452e0c27d090621c169", 7500, "0x00 0x20 0x9e1be07558ea5cc8e02ed1d80c0911048afad949affa36d5c3951e3159dbea19", 200000]], +"0100000000010169c12106097dc2e0526493ef67f21269fe888ef05c7a3a5dacab38e1ac8387f14c1d000000ffffffff01010000000000000000034830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e012102a9d7ed6e161f0e255c10bbfcca0128a9e2035c2c8da58899c54d22d3a31afdef4aad4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0100000000", "P2SH,WITNESS"], +["This is multisig version of the FindAndDelete tests"], +["Script is 2 CHECKMULTISIGVERIFY DROP"], +["52af4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c0395960175"], +["Signature is 0 2 "], +["Should pass by replacing (sigversion == SIGVERSION_BASE) with (sigversion != SIGVERSION_BASE) under OP_CHECKMULTISIG"], +["Non-segwit: wrong sighash (without FindAndDelete) = 4bc6a53e8e16ef508c19e38bba08831daba85228b0211f323d4cb0999cf2a5e8"], +[[["9628667ad48219a169b41b020800162287d2c0f713c04157e95c484a8dcb7592", 7000, "HASH160 0x14 0x5748407f5ca5cdca53ba30b79040260770c9ee1b EQUAL", 200000]], +"01000000019275cb8d4a485ce95741c013f7c0d28722160008021bb469a11982d47a662896581b0000fd6f01004830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c039596015221023fd5dd42b44769c5653cbc5947ff30ab8871f240ad0c0e7432aefe84b5b4ff3421039d52178dbde360b83f19cf348deb04fa8360e1bf5634577be8e50fafc2b0e4ef4c9552af4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c0395960175ffffffff0101000000000000000000000000", "P2SH,WITNESS"], +["BIP143: wrong sighash (with FindAndDelete) = 17c50ec2181ecdfdc85ca081174b248199ba81fff730794d4f69b8ec031f2dce"], +[[["9628667ad48219a169b41b020800162287d2c0f713c04157e95c484a8dcb7592", 7500, "0x00 0x20 0x9b66c15b4e0b4eb49fa877982cafded24859fe5b0e2dbfbe4f0df1de7743fd52", 200000]], +"010000000001019275cb8d4a485ce95741c013f7c0d28722160008021bb469a11982d47a6628964c1d000000ffffffff0101000000000000000007004830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c03959601010221023cb6055f4b57a1580c5a753e19610cafaedf7e0ff377731c77837fd666eae1712102c1b1db303ac232ffa8e5e7cc2cf5f96c6e40d3e6914061204c0541cb2043a0969552af4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c039596017500000000", "P2SH,WITNESS"], + ["Make diffs cleaner by leaving a comment here without comma at the end"] ] diff --git a/src/test/data/tx_valid.json b/src/test/data/tx_valid.json index 1ea70135b437b..2f299aa5fea37 100644 --- a/src/test/data/tx_valid.json +++ b/src/test/data/tx_valid.json @@ -487,5 +487,28 @@ [[["6eb98797a21c6c10aa74edf29d618be109f48a8e94c694f3701e08ca69186436", 1, "HASH160 0x14 0x9993a429037b5d912407a71c252019287b8d27a5 EQUAL", 987654321]], "0100000000010136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000023220020a16b5755f7f6f96dbd65f5f0d6ab9418b89af4b1f14a1bb8a09062c35f0dcb54ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac080047304402206ac44d672dac41f9b00e28f4df20c52eeb087207e8d758d76d92c6fab3b73e2b0220367750dbbe19290069cba53d096f44530e4f98acaa594810388cf7409a1870ce01473044022068c7946a43232757cbdf9176f009a928e1cd9a1a8c212f15c1e11ac9f2925d9002205b75f937ff2f9f3c1246e547e54f62e027f64eefa2695578cc6432cdabce271502473044022059ebf56d98010a932cf8ecfec54c48e6139ed6adb0728c09cbe1e4fa0915302e022007cd986c8fa870ff5d2b3a89139c9fe7e499259875357e20fcbb15571c76795403483045022100fbefd94bd0a488d50b79102b5dad4ab6ced30c4069f1eaa69a4b5a763414067e02203156c6a5c9cf88f91265f5a942e96213afae16d83321c8b31bb342142a14d16381483045022100a5263ea0553ba89221984bd7f0b13613db16e7a70c549a86de0cc0444141a407022005c360ef0ae5a5d4f9f2f87a56c1546cc8268cab08c73501d6b3be2e1e1a8a08824730440220525406a1482936d5a21888260dc165497a90a15669636d8edca6b9fe490d309c022032af0c646a34a44d1f4576bf6a4a74b67940f8faa84c7df9abe12a01a11e2b4783cf56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae00000000", "P2SH,WITNESS"], +["FindAndDelete tests"], +["This is a test of FindAndDelete. The first tx is a spend of normal P2SH and the second tx is a spend of bare P2WSH."], +["The redeemScript/witnessScript is CHECKSIGVERIFY <0x30450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e01>."], +["The signature is <0x30450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e01> ,"], +["where the pubkey is obtained through key recovery with sig and correct sighash."], +["This is to show that FindAndDelete is applied only to non-segwit scripts"], +["Non-segwit: correct sighash (with FindAndDelete) = 1ba1fe3bc90c5d1265460e684ce6774e324f0fabdf67619eda729e64e8b6bc08"], +[[["f18783ace138abac5d3a7a5cf08e88fe6912f267ef936452e0c27d090621c169", 7000, "HASH160 0x14 0x0c746489e2d83cdbb5b90b432773342ba809c134 EQUAL", 200000]], +"010000000169c12106097dc2e0526493ef67f21269fe888ef05c7a3a5dacab38e1ac8387f1581b0000b64830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0121037a3fb04bcdb09eba90f69961ba1692a3528e45e67c85b200df820212d7594d334aad4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e01ffffffff0101000000000000000000000000", "P2SH,WITNESS"], +["BIP143: correct sighash (without FindAndDelete) = 71c9cd9b2869b9c70b01b1f0360c148f42dee72297db312638df136f43311f23"], +[[["f18783ace138abac5d3a7a5cf08e88fe6912f267ef936452e0c27d090621c169", 7500, "0x00 0x20 0x9e1be07558ea5cc8e02ed1d80c0911048afad949affa36d5c3951e3159dbea19", 200000]], +"0100000000010169c12106097dc2e0526493ef67f21269fe888ef05c7a3a5dacab38e1ac8387f14c1d000000ffffffff01010000000000000000034830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e012102a9781d66b61fb5a7ef00ac5ad5bc6ffc78be7b44a566e3c87870e1079368df4c4aad4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0100000000", "P2SH,WITNESS"], +["This is multisig version of the FindAndDelete tests"], +["Script is 2 CHECKMULTISIGVERIFY DROP"], +["52af4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c0395960175"], +["Signature is 0 2 "], +["Non-segwit: correct sighash (with FindAndDelete) = 1d50f00ba4db2917b903b0ec5002e017343bb38876398c9510570f5dce099295"], +[[["9628667ad48219a169b41b020800162287d2c0f713c04157e95c484a8dcb7592", 7000, "HASH160 0x14 0x5748407f5ca5cdca53ba30b79040260770c9ee1b EQUAL", 200000]], +"01000000019275cb8d4a485ce95741c013f7c0d28722160008021bb469a11982d47a662896581b0000fd6f01004830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c03959601522102cd74a2809ffeeed0092bc124fd79836706e41f048db3f6ae9df8708cefb83a1c2102e615999372426e46fd107b76eaf007156a507584aa2cc21de9eee3bdbd26d36c4c9552af4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c0395960175ffffffff0101000000000000000000000000", "P2SH,WITNESS"], +["BIP143: correct sighash (without FindAndDelete) = c1628a1e7c67f14ca0c27c06e4fdeec2e6d1a73c7a91d7c046ff83e835aebb72"], +[[["9628667ad48219a169b41b020800162287d2c0f713c04157e95c484a8dcb7592", 7500, "0x00 0x20 0x9b66c15b4e0b4eb49fa877982cafded24859fe5b0e2dbfbe4f0df1de7743fd52", 200000]], +"010000000001019275cb8d4a485ce95741c013f7c0d28722160008021bb469a11982d47a6628964c1d000000ffffffff0101000000000000000007004830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c0395960101022102966f109c54e85d3aee8321301136cedeb9fc710fdef58a9de8a73942f8e567c021034ffc99dd9a79dd3cb31e2ab3e0b09e0e67db41ac068c625cd1f491576016c84e9552af4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c039596017500000000", "P2SH,WITNESS"], + ["Make diffs cleaner by leaving a comment here without comma at the end"] ] From 37aefff5fcf7169a1b07ff8939850f630640f7e7 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sat, 15 Oct 2016 13:19:16 -0400 Subject: [PATCH 1018/1802] Fix init segfault where InitLoadWallet() calls ATMP before genesis --- src/init.cpp | 7 +++++++ src/wallet/wallet.cpp | 2 -- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index eefef7ba0b253..057d8eefeef9b 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1488,6 +1488,13 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) uiInterface.NotifyBlockTip.disconnect(BlockNotifyGenesisWait); } +#ifdef ENABLE_WALLET + // Add wallet transactions that aren't already in a block to mempool + // Do this here as mempool requires genesis block to be loaded + if (pwalletMain) + pwalletMain->ReacceptWalletTransactions(); +#endif + // ********************************************************* Step 11: start node //// debug print diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index a1f69dd94dd6c..6f86f3360db2c 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3467,8 +3467,6 @@ bool CWallet::InitLoadWallet() LogPrintf("mapWallet.size() = %u\n", walletInstance->mapWallet.size()); LogPrintf("mapAddressBook.size() = %u\n", walletInstance->mapAddressBook.size()); } - // Add wallet transactions that aren't already in a block to mapTransactions - walletInstance->ReacceptWalletTransactions(); pwalletMain = walletInstance; From aa9d3c9a503952589b359624bbb0da11dd7a5e3f Mon Sep 17 00:00:00 2001 From: Steven Date: Sat, 15 Oct 2016 13:57:19 -0400 Subject: [PATCH 1019/1802] add software-properties-common This allows using `add-apt-repository`. --- doc/build-unix.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/build-unix.md b/doc/build-unix.md index 5202072f8b8e1..a7221ddc6d160 100644 --- a/doc/build-unix.md +++ b/doc/build-unix.md @@ -82,6 +82,7 @@ install necessary parts of boost: BerkeleyDB is required for the wallet. db4.8 packages are available [here](https://launchpad.net/~bitcoin/+archive/bitcoin). You can add the repository and install using the following commands: + sudo apt-get install software-properties-common sudo add-apt-repository ppa:bitcoin/bitcoin sudo apt-get update sudo apt-get install libdb4.8-dev libdb4.8++-dev From a4ad37d4ef4bcd81bc9d867b277efdebc86bc2e8 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sat, 15 Oct 2016 17:51:05 -0400 Subject: [PATCH 1020/1802] [qa] Build v4 blocks in p2p-compactblocktests This fixes an issue in backporting to 0.13 as 0.13 enforces SF activation by block version lockin instead of through a hard-coded block height. --- qa/rpc-tests/p2p-compactblocks.py | 1 + 1 file changed, 1 insertion(+) diff --git a/qa/rpc-tests/p2p-compactblocks.py b/qa/rpc-tests/p2p-compactblocks.py index 1beab609b68ef..131654c333d4d 100755 --- a/qa/rpc-tests/p2p-compactblocks.py +++ b/qa/rpc-tests/p2p-compactblocks.py @@ -128,6 +128,7 @@ def build_block_on_tip(self, node, segwit=False): tip = node.getbestblockhash() mtp = node.getblockheader(tip)['mediantime'] block = create_block(int(tip, 16), create_coinbase(height + 1), mtp + 1) + block.nVersion = 4 if segwit: add_witness_commitment(block) block.solve() From 3ade2f64cfe43ab53e4869ffc35d5fd23201e1c1 Mon Sep 17 00:00:00 2001 From: Johnson Lau Date: Sun, 16 Oct 2016 23:53:16 +0800 Subject: [PATCH 1021/1802] Add standard limits for P2WSH with tests --- qa/rpc-tests/p2p-segwit.py | 111 +++++++++++++++++++++++++++++++++++++ src/main.cpp | 6 +- src/policy/policy.cpp | 54 +++++++++++++++++- src/policy/policy.h | 12 ++++ 4 files changed, 181 insertions(+), 2 deletions(-) diff --git a/qa/rpc-tests/p2p-segwit.py b/qa/rpc-tests/p2p-segwit.py index c2ea20bb845c8..16d1e8680273f 100755 --- a/qa/rpc-tests/p2p-segwit.py +++ b/qa/rpc-tests/p2p-segwit.py @@ -1706,6 +1706,116 @@ def test_getblocktemplate_before_lockin(self): assert(block_version & (1 << VB_WITNESS_BIT) != 0) self.nodes[0].setmocktime(0) # undo mocktime + def test_non_standard_witness(self): + print("\tTesting detection of non-standard P2WSH witness") + pad = chr(1).encode('latin-1') + + # Create scripts for tests + scripts = [] + scripts.append(CScript([OP_DROP] * 100)) + scripts.append(CScript([OP_DROP] * 99)) + scripts.append(CScript([pad * 59] * 59 + [OP_DROP] * 60)) + scripts.append(CScript([pad * 59] * 59 + [OP_DROP] * 61)) + + p2wsh_scripts = [] + + assert(len(self.utxo)) + tx = CTransaction() + tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")) + + # For each script, generate a pair of P2WSH and P2SH-P2WSH output. + outputvalue = (self.utxo[0].nValue - 1000) // (len(scripts) * 2) + for i in scripts: + p2wsh = CScript([OP_0, sha256(i)]) + p2sh = hash160(p2wsh) + p2wsh_scripts.append(p2wsh) + tx.vout.append(CTxOut(outputvalue, p2wsh)) + tx.vout.append(CTxOut(outputvalue, CScript([OP_HASH160, p2sh, OP_EQUAL]))) + tx.rehash() + txid = tx.sha256 + self.test_node.test_transaction_acceptance(tx, with_witness=False, accepted=True) + + self.nodes[0].generate(1) + sync_blocks(self.nodes) + + # Creating transactions for tests + p2wsh_txs = [] + p2sh_txs = [] + for i in range(len(scripts)): + p2wsh_tx = CTransaction() + p2wsh_tx.vin.append(CTxIn(COutPoint(txid,i*2))) + p2wsh_tx.vout.append(CTxOut(outputvalue - 5000, CScript([OP_0, hash160(hex_str_to_bytes(""))]))) + p2wsh_tx.wit.vtxinwit.append(CTxInWitness()) + p2wsh_tx.rehash() + p2wsh_txs.append(p2wsh_tx) + p2sh_tx = CTransaction() + p2sh_tx.vin.append(CTxIn(COutPoint(txid,i*2+1), CScript([p2wsh_scripts[i]]))) + p2sh_tx.vout.append(CTxOut(outputvalue - 5000, CScript([OP_0, hash160(hex_str_to_bytes(""))]))) + p2sh_tx.wit.vtxinwit.append(CTxInWitness()) + p2sh_tx.rehash() + p2sh_txs.append(p2sh_tx) + + # Testing native P2WSH + # Witness stack size, excluding witnessScript, over 100 is non-standard + p2wsh_txs[0].wit.vtxinwit[0].scriptWitness.stack = [pad] * 101 + [scripts[0]] + self.std_node.test_transaction_acceptance(p2wsh_txs[0], True, False, b'bad-witness-nonstandard') + # Non-standard nodes should accept + self.test_node.test_transaction_acceptance(p2wsh_txs[0], True, True) + + # Stack element size over 80 bytes is non-standard + p2wsh_txs[1].wit.vtxinwit[0].scriptWitness.stack = [pad * 81] * 100 + [scripts[1]] + # It can't be used to blind a node to the transaction + self.std_node.announce_tx_and_wait_for_getdata(p2wsh_txs[1]) + self.std_node.test_transaction_acceptance(p2wsh_txs[1], True, False, b'bad-witness-nonstandard') + self.std_node.announce_tx_and_wait_for_getdata(p2wsh_txs[1]) + self.std_node.test_transaction_acceptance(p2wsh_txs[1], True, False, b'bad-witness-nonstandard') + # Non-standard nodes should accept + self.test_node.test_transaction_acceptance(p2wsh_txs[1], True, True) + # Standard nodes should accept if element size is not over 80 bytes + p2wsh_txs[1].wit.vtxinwit[0].scriptWitness.stack = [pad * 80] * 100 + [scripts[1]] + self.std_node.announce_tx_and_wait_for_getdata(p2wsh_txs[1]) + self.std_node.test_transaction_acceptance(p2wsh_txs[1], True, True) + + # witnessScript size at 3600 bytes is standard + p2wsh_txs[2].wit.vtxinwit[0].scriptWitness.stack = [pad, pad, scripts[2]] + self.test_node.test_transaction_acceptance(p2wsh_txs[2], True, True) + self.std_node.test_transaction_acceptance(p2wsh_txs[2], True, True) + + # witnessScript size at 3601 bytes is non-standard + p2wsh_txs[3].wit.vtxinwit[0].scriptWitness.stack = [pad, pad, pad, scripts[3]] + self.std_node.test_transaction_acceptance(p2wsh_txs[3], True, False, b'bad-witness-nonstandard') + # Non-standard nodes should accept + self.test_node.test_transaction_acceptance(p2wsh_txs[3], True, True) + + # Repeating the same tests with P2SH-P2WSH + p2sh_txs[0].wit.vtxinwit[0].scriptWitness.stack = [pad] * 101 + [scripts[0]] + self.std_node.test_transaction_acceptance(p2sh_txs[0], True, False, b'bad-witness-nonstandard') + self.test_node.test_transaction_acceptance(p2sh_txs[0], True, True) + p2sh_txs[1].wit.vtxinwit[0].scriptWitness.stack = [pad * 81] * 100 + [scripts[1]] + self.std_node.announce_tx_and_wait_for_getdata(p2sh_txs[1]) + self.std_node.test_transaction_acceptance(p2sh_txs[1], True, False, b'bad-witness-nonstandard') + self.std_node.announce_tx_and_wait_for_getdata(p2sh_txs[1]) + self.std_node.test_transaction_acceptance(p2sh_txs[1], True, False, b'bad-witness-nonstandard') + self.test_node.test_transaction_acceptance(p2sh_txs[1], True, True) + p2sh_txs[1].wit.vtxinwit[0].scriptWitness.stack = [pad * 80] * 100 + [scripts[1]] + self.std_node.announce_tx_and_wait_for_getdata(p2sh_txs[1]) + self.std_node.test_transaction_acceptance(p2sh_txs[1], True, True) + p2sh_txs[2].wit.vtxinwit[0].scriptWitness.stack = [pad, pad, scripts[2]] + self.test_node.test_transaction_acceptance(p2sh_txs[2], True, True) + self.std_node.test_transaction_acceptance(p2sh_txs[2], True, True) + p2sh_txs[3].wit.vtxinwit[0].scriptWitness.stack = [pad, pad, pad, scripts[3]] + self.std_node.test_transaction_acceptance(p2sh_txs[3], True, False, b'bad-witness-nonstandard') + self.test_node.test_transaction_acceptance(p2sh_txs[3], True, True) + + self.nodes[0].generate(1) # Mine and clean up the mempool of non-standard node + # Valid but non-standard transactions in a block should be accepted by standard node + sync_blocks(self.nodes) + assert_equal(len(self.nodes[0].getrawmempool()), 0) + assert_equal(len(self.nodes[1].getrawmempool()), 0) + + self.utxo.pop(0) + + def run_test(self): # Setup the p2p connections and start up the network thread. self.test_node = TestNode() # sets NODE_WITNESS|NODE_NETWORK @@ -1778,6 +1888,7 @@ def run_test(self): self.test_segwit_versions() self.test_premature_coinbase_witness_spend() self.test_signature_version_1() + self.test_non_standard_witness() sync_blocks(self.nodes) if self.test_upgrade: self.test_upgrade_after_activation(self.nodes[2], 2) diff --git a/src/main.cpp b/src/main.cpp index c92a38be98f23..020378b5dc4ea 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2015 The Bitcoin Core developers +// Copyright (c) 2009-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -1273,6 +1273,10 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C if (fRequireStandard && !AreInputsStandard(tx, view)) return state.Invalid(false, REJECT_NONSTANDARD, "bad-txns-nonstandard-inputs"); + // Check for non-standard witness in P2WSH + if (!tx.wit.IsNull() && fRequireStandard && !IsWitnessStandard(tx, view)) + return state.DoS(0, false, REJECT_NONSTANDARD, "bad-witness-nonstandard", true); + int64_t nSigOpsCost = GetTransactionSigOpCost(tx, view, STANDARD_SCRIPT_VERIFY_FLAGS); CAmount nValueOut = tx.GetValueOut(); diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index 48080abc778d5..ae42b2bd74fd8 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2015 The Bitcoin developers +// Copyright (c) 2009-2016 The Bitcoin developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -154,6 +154,58 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs) return true; } +bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs) +{ + if (tx.IsCoinBase()) + return true; // Coinbases are skipped + + for (unsigned int i = 0; i < tx.vin.size(); i++) + { + // We don't care if witness for this input is empty, since it must not be bloated. + // If the script is invalid without witness, it would be caught sooner or later during validation. + if (tx.wit.vtxinwit[i].IsNull()) + continue; + + const CTxOut &prev = mapInputs.GetOutputFor(tx.vin[i]); + + // get the scriptPubKey corresponding to this input: + CScript prevScript = prev.scriptPubKey; + + if (prevScript.IsPayToScriptHash()) { + std::vector > stack; + // If the scriptPubKey is P2SH, we try to extract the redeemScript casually by converting the scriptSig + // into a stack. We do not check IsPushOnly nor compare the hash as these will be done later anyway. + // If the check fails at this stage, we know that this txid must be a bad one. + if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), SIGVERSION_BASE)) + return false; + if (stack.empty()) + return false; + prevScript = CScript(stack.back().begin(), stack.back().end()); + } + + int witnessversion = 0; + std::vector witnessprogram; + + // Non-witness program must not be associated with any witness + if (!prevScript.IsWitnessProgram(witnessversion, witnessprogram)) + return false; + + // Check P2WSH standard limits + if (witnessversion == 0 && witnessprogram.size() == 32) { + if (tx.wit.vtxinwit[i].scriptWitness.stack.back().size() > MAX_STANDARD_P2WSH_SCRIPT_SIZE) + return false; + size_t sizeWitnessStack = tx.wit.vtxinwit[i].scriptWitness.stack.size() - 1; + if (sizeWitnessStack > MAX_STANDARD_P2WSH_STACK_ITEMS) + return false; + for (unsigned int j = 0; j < sizeWitnessStack; j++) { + if (tx.wit.vtxinwit[i].scriptWitness.stack[j].size() > MAX_STANDARD_P2WSH_STACK_ITEM_SIZE) + return false; + } + } + } + return true; +} + unsigned int nBytesPerSigOp = DEFAULT_BYTES_PER_SIGOP; int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost) diff --git a/src/policy/policy.h b/src/policy/policy.h index 9d6ff1233b6aa..fb528d74868c5 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -30,6 +30,12 @@ static const unsigned int MAX_STANDARD_TX_SIGOPS_COST = MAX_BLOCK_SIGOPS_COST/5; static const unsigned int DEFAULT_MAX_MEMPOOL_SIZE = 300; /** Default for -bytespersigop */ static const unsigned int DEFAULT_BYTES_PER_SIGOP = 20; +/** The maximum number of witness stack items in a standard P2WSH script */ +static const unsigned int MAX_STANDARD_P2WSH_STACK_ITEMS = 100; +/** The maximum size of each witness stack item in a standard P2WSH script */ +static const unsigned int MAX_STANDARD_P2WSH_STACK_ITEM_SIZE = 80; +/** The maximum size of a standard witnessScript */ +static const unsigned int MAX_STANDARD_P2WSH_SCRIPT_SIZE = 3600; /** * Standard script verification flags that standard transactions will comply * with. However scripts violating these flags may still be present in valid @@ -69,6 +75,12 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason, const bool witnes * @return True if all inputs (scriptSigs) use only standard transaction forms */ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs); + /** + * Check if the transaction is over standard P2WSH resources limit: + * 3600bytes witnessScript size, 80bytes per witness stack element, 100 witness stack elements + * These limits are adequate for multi-signature up to n-of-100 using OP_CHECKSIG, OP_ADD, and OP_EQUAL, + */ +bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs); extern unsigned int nBytesPerSigOp; From 4c0c25a604cec39675187507df423cff5d707ab5 Mon Sep 17 00:00:00 2001 From: Johnson Lau Date: Sun, 2 Oct 2016 01:19:33 +0800 Subject: [PATCH 1022/1802] Require compressed keys in segwit as policy and disable signing with uncompressed keys for segwit scripts --- src/policy/policy.h | 5 +++-- src/script/interpreter.cpp | 28 ++++++++++++++++++++------ src/script/interpreter.h | 6 +++++- src/script/script_error.cpp | 2 ++ src/script/script_error.h | 1 + src/script/sign.cpp | 6 +++++- src/test/script_tests.cpp | 1 + src/test/transaction_tests.cpp | 36 ++++++++++------------------------ 8 files changed, 49 insertions(+), 36 deletions(-) diff --git a/src/policy/policy.h b/src/policy/policy.h index fb528d74868c5..814e6c0b6ff94 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2015 The Bitcoin developers +// Copyright (c) 2009-2016 The Bitcoin developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -54,7 +54,8 @@ static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY SCRIPT_VERIFY_CHECKSEQUENCEVERIFY | SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_WITNESS | - SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM; + SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM | + SCRIPT_VERIFY_WITNESS_PUBKEYTYPE; /** For convenience, standard but not mandatory verify flags. */ static const unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS; diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 41756ea71196d..836cf9ee352a0 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -79,8 +79,20 @@ bool static IsCompressedOrUncompressedPubKey(const valtype &vchPubKey) { return false; } } else { - // Non-canonical public key: neither compressed nor uncompressed - return false; + // Non-canonical public key: neither compressed nor uncompressed + return false; + } + return true; +} + +bool static IsCompressedPubKey(const valtype &vchPubKey) { + if (vchPubKey.size() != 33) { + // Non-canonical public key: invalid length for compressed key + return false; + } + if (vchPubKey[0] != 0x02 && vchPubKey[0] != 0x03) { + // Non-canonical public key: invalid prefix for compressed key + return false; } return true; } @@ -199,10 +211,14 @@ bool CheckSignatureEncoding(const vector &vchSig, unsigned int fl return true; } -bool static CheckPubKeyEncoding(const valtype &vchSig, unsigned int flags, ScriptError* serror) { - if ((flags & SCRIPT_VERIFY_STRICTENC) != 0 && !IsCompressedOrUncompressedPubKey(vchSig)) { +bool static CheckPubKeyEncoding(const valtype &vchPubKey, unsigned int flags, const SigVersion &sigversion, ScriptError* serror) { + if ((flags & SCRIPT_VERIFY_STRICTENC) != 0 && !IsCompressedOrUncompressedPubKey(vchPubKey)) { return set_error(serror, SCRIPT_ERR_PUBKEYTYPE); } + // Only compressed keys are accepted in segwit + if ((flags & SCRIPT_VERIFY_WITNESS_PUBKEYTYPE) != 0 && sigversion == SIGVERSION_WITNESS_V0 && !IsCompressedPubKey(vchPubKey)) { + return set_error(serror, SCRIPT_ERR_WITNESS_PUBKEYTYPE); + } return true; } @@ -879,7 +895,7 @@ bool EvalScript(vector >& stack, const CScript& script, un scriptCode.FindAndDelete(CScript(vchSig)); } - if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, serror)) { + if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, sigversion, serror)) { //serror is set return false; } @@ -953,7 +969,7 @@ bool EvalScript(vector >& stack, const CScript& script, un // Note how this makes the exact order of pubkey/signature evaluation // distinguishable by CHECKMULTISIG NOT if the STRICTENC flag is set. // See the script_(in)valid tests for details. - if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, serror)) { + if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, sigversion, serror)) { // serror is set return false; } diff --git a/src/script/interpreter.h b/src/script/interpreter.h index 0adc9482ffec6..79894c5300348 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2015 The Bitcoin Core developers +// Copyright (c) 2009-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -102,6 +102,10 @@ enum // Signature(s) must be empty vector if an CHECK(MULTI)SIG operation failed // SCRIPT_VERIFY_NULLFAIL = (1U << 14), + + // Public keys in segregated witness scripts must be compressed + // + SCRIPT_VERIFY_WITNESS_PUBKEYTYPE = (1U << 15), }; bool CheckSignatureEncoding(const std::vector &vchSig, unsigned int flags, ScriptError* serror); diff --git a/src/script/script_error.cpp b/src/script/script_error.cpp index e27b715c2cfea..2c5359fe8afdb 100644 --- a/src/script/script_error.cpp +++ b/src/script/script_error.cpp @@ -85,6 +85,8 @@ const char* ScriptErrorString(const ScriptError serror) return "Witness requires only-redeemscript scriptSig"; case SCRIPT_ERR_WITNESS_UNEXPECTED: return "Witness provided for non-witness script"; + case SCRIPT_ERR_WITNESS_PUBKEYTYPE: + return "Using non-compressed keys in segwit"; case SCRIPT_ERR_UNKNOWN_ERROR: case SCRIPT_ERR_ERROR_COUNT: default: break; diff --git a/src/script/script_error.h b/src/script/script_error.h index bccfdb99e23bb..430836991b2cf 100644 --- a/src/script/script_error.h +++ b/src/script/script_error.h @@ -62,6 +62,7 @@ typedef enum ScriptError_t SCRIPT_ERR_WITNESS_MALLEATED, SCRIPT_ERR_WITNESS_MALLEATED_P2SH, SCRIPT_ERR_WITNESS_UNEXPECTED, + SCRIPT_ERR_WITNESS_PUBKEYTYPE, SCRIPT_ERR_ERROR_COUNT } ScriptError; diff --git a/src/script/sign.cpp b/src/script/sign.cpp index 87f38d9c72565..f552ad5bbad25 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2015 The Bitcoin Core developers +// Copyright (c) 2009-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -26,6 +26,10 @@ bool TransactionSignatureCreator::CreateSig(std::vector& vchSig, if (!keystore->GetKey(address, key)) return false; + // Signing with uncompressed keys is disabled in witness scripts + if (sigversion == SIGVERSION_WITNESS_V0 && !key.IsCompressed()) + return false; + uint256 hash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion); if (!key.Sign(hash, vchSig)) return false; diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 7971b5122ffc9..7da95488afc43 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -99,6 +99,7 @@ static ScriptErrorDesc script_errors[]={ {SCRIPT_ERR_WITNESS_MALLEATED, "WITNESS_MALLEATED"}, {SCRIPT_ERR_WITNESS_MALLEATED_P2SH, "WITNESS_MALLEATED_P2SH"}, {SCRIPT_ERR_WITNESS_UNEXPECTED, "WITNESS_UNEXPECTED"}, + {SCRIPT_ERR_WITNESS_PUBKEYTYPE, "WITNESS_PUBKEYTYPE"}, }; const char *FormatScriptError(ScriptError_t err) diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 6163d2f630604..34d9547f3dc60 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Bitcoin Core developers +// Copyright (c) 2011-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -55,7 +55,8 @@ static std::map mapFlagNames = boost::assign::map_list_of (string("CHECKLOCKTIMEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY) (string("CHECKSEQUENCEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKSEQUENCEVERIFY) (string("WITNESS"), (unsigned int)SCRIPT_VERIFY_WITNESS) - (string("DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM); + (string("DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM) + (string("WITNESS_PUBKEYTYPE"), (unsigned int)SCRIPT_VERIFY_WITNESS_PUBKEYTYPE); unsigned int ParseScriptFlags(string strFlags) { @@ -429,7 +430,7 @@ BOOST_AUTO_TEST_CASE(test_big_witness_transaction) { mtx.nVersion = 1; CKey key; - key.MakeNewKey(false); + key.MakeNewKey(true); // Need to use compressed keys in segwit or the signing will fail CBasicKeyStore keystore; keystore.AddKeyPubKey(key, key.GetPubKey()); CKeyID hash = key.GetPubKey().GetID(); @@ -625,30 +626,13 @@ BOOST_AUTO_TEST_CASE(test_witness) CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false); CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false); - // Witness pay-to-uncompressed-pubkey (v1). - CreateCreditAndSpend(keystore, GetScriptForWitness(scriptPubkey1L), output1, input1); - CreateCreditAndSpend(keystore, GetScriptForWitness(scriptPubkey2L), output2, input2); - CheckWithFlag(output1, input1, 0, true); - CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true); - CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true); - CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true); - CheckWithFlag(output1, input2, 0, true); - CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, true); - CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false); - CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false); + // Signing disabled for witness pay-to-uncompressed-pubkey (v1). + CreateCreditAndSpend(keystore, GetScriptForWitness(scriptPubkey1L), output1, input1, false); + CreateCreditAndSpend(keystore, GetScriptForWitness(scriptPubkey2L), output2, input2, false); - // P2SH witness pay-to-uncompressed-pubkey (v1). - CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey1L))), output1, input1); - CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey2L))), output2, input2); - ReplaceRedeemScript(input2.vin[0].scriptSig, GetScriptForWitness(scriptPubkey1L)); - CheckWithFlag(output1, input1, 0, true); - CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true); - CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true); - CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true); - CheckWithFlag(output1, input2, 0, true); - CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, true); - CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false); - CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false); + // Signing disabled for P2SH witness pay-to-uncompressed-pubkey (v1). + CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey1L))), output1, input1, false); + CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey2L))), output2, input2, false); // Normal 2-of-2 multisig CreateCreditAndSpend(keystore, scriptMulti, output1, input1, false); From 9f0397aff7afa2afa9328daea0a2053122e79d44 Mon Sep 17 00:00:00 2001 From: Johnson Lau Date: Wed, 24 Aug 2016 14:44:17 +0800 Subject: [PATCH 1023/1802] Make test framework produce lowS signatures --- qa/rpc-tests/test_framework/key.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/qa/rpc-tests/test_framework/key.py b/qa/rpc-tests/test_framework/key.py index ba3038fe044f4..c63a15c1e0c92 100644 --- a/qa/rpc-tests/test_framework/key.py +++ b/qa/rpc-tests/test_framework/key.py @@ -75,6 +75,9 @@ # this specifies the curve used with ECDSA. NID_secp256k1 = 714 # from openssl/obj_mac.h +SECP256K1_ORDER = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 +SECP256K1_ORDER_HALF = SECP256K1_ORDER // 2 + # Thx to Sam Devlin for the ctypes magic 64-bit fix. def _check_result(val, func, args): if val == 0: @@ -147,7 +150,7 @@ def get_ecdh_key(self, other_pubkey, kdf=lambda k: hashlib.sha256(k).digest()): r = self.get_raw_ecdh_key(other_pubkey) return kdf(r) - def sign(self, hash): + def sign(self, hash, low_s = True): # FIXME: need unit tests for below cases if not isinstance(hash, bytes): raise TypeError('Hash must be bytes instance; got %r' % hash.__class__) @@ -159,7 +162,25 @@ def sign(self, hash): mb_sig = ctypes.create_string_buffer(sig_size0.value) result = ssl.ECDSA_sign(0, hash, len(hash), mb_sig, ctypes.byref(sig_size0), self.k) assert 1 == result - return mb_sig.raw[:sig_size0.value] + assert mb_sig.raw[0] == 0x30 + assert mb_sig.raw[1] == sig_size0.value - 2 + total_size = mb_sig.raw[1] + assert mb_sig.raw[2] == 2 + r_size = mb_sig.raw[3] + assert mb_sig.raw[4 + r_size] == 2 + s_size = mb_sig.raw[5 + r_size] + s_value = int.from_bytes(mb_sig.raw[6+r_size:6+r_size+s_size], byteorder='big') + if (not low_s) or s_value <= SECP256K1_ORDER_HALF: + return mb_sig.raw[:sig_size0.value] + else: + low_s_value = SECP256K1_ORDER - s_value + low_s_bytes = (low_s_value).to_bytes(33, byteorder='big') + while len(low_s_bytes) > 1 and low_s_bytes[0] == 0 and low_s_bytes[1] < 0x80: + low_s_bytes = low_s_bytes[1:] + new_s_size = len(low_s_bytes) + new_total_size_byte = (total_size + new_s_size - s_size).to_bytes(1,byteorder='big') + new_s_size_byte = (new_s_size).to_bytes(1,byteorder='big') + return b'\x30' + new_total_size_byte + mb_sig.raw[2:5+r_size] + new_s_size_byte + low_s_bytes def verify(self, hash, sig): """Verify a DER signature""" From b811124202152424109b8e95ebe7ac25ff2e83c0 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Thu, 6 Oct 2016 13:15:33 -0400 Subject: [PATCH 1024/1802] [qa] Add tests for uncompressed pubkeys in segwit --- qa/rpc-tests/p2p-segwit.py | 125 ++++++++++++++++++++++++++++++++++--- 1 file changed, 117 insertions(+), 8 deletions(-) diff --git a/qa/rpc-tests/p2p-segwit.py b/qa/rpc-tests/p2p-segwit.py index 16d1e8680273f..fa505d60c9b66 100755 --- a/qa/rpc-tests/p2p-segwit.py +++ b/qa/rpc-tests/p2p-segwit.py @@ -166,6 +166,17 @@ def __init__(self, sha256, n, nValue): self.n = n self.nValue = nValue +# Helper for getting the script associated with a P2PKH +def GetP2PKHScript(pubkeyhash): + return CScript([CScriptOp(OP_DUP), CScriptOp(OP_HASH160), pubkeyhash, CScriptOp(OP_EQUALVERIFY), CScriptOp(OP_CHECKSIG)]) + +# Add signature for a P2PK witness program. +def sign_P2PK_witness_input(script, txTo, inIdx, hashtype, value, key): + tx_hash = SegwitVersion1SignatureHash(script, txTo, inIdx, hashtype, value) + signature = key.sign(tx_hash) + chr(hashtype).encode('latin-1') + txTo.wit.vtxinwit[inIdx].scriptWitness.stack = [signature, script] + txTo.rehash() + class SegWitTest(BitcoinTestFramework): @@ -1323,13 +1334,6 @@ def test_signature_version_1(self): sync_blocks(self.nodes) self.utxo.pop(0) - # Add signature for a P2PK witness program. - def sign_P2PK_witness_input(script, txTo, inIdx, hashtype, value, key): - tx_hash = SegwitVersion1SignatureHash(script, txTo, inIdx, hashtype, value) - signature = key.sign(tx_hash) + chr(hashtype).encode('latin-1') - txTo.wit.vtxinwit[inIdx].scriptWitness.stack = [signature, script] - txTo.rehash() - # Test each hashtype prev_utxo = UTXO(tx.sha256, 0, tx.vout[0].nValue) for sigflag in [ 0, SIGHASH_ANYONECANPAY ]: @@ -1443,7 +1447,7 @@ def sign_P2PK_witness_input(script, txTo, inIdx, hashtype, value, key): tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b"")) tx2.vout.append(CTxOut(tx.vout[0].nValue, CScript([OP_TRUE]))) - script = CScript([CScriptOp(OP_DUP), CScriptOp(OP_HASH160), pubkeyhash, CScriptOp(OP_EQUALVERIFY), CScriptOp(OP_CHECKSIG)]) + script = GetP2PKHScript(pubkeyhash) sig_hash = SegwitVersion1SignatureHash(script, tx2, 0, SIGHASH_ALL, tx.vout[0].nValue) signature = key.sign(sig_hash) + b'\x01' # 0x1 is SIGHASH_ALL @@ -1706,6 +1710,110 @@ def test_getblocktemplate_before_lockin(self): assert(block_version & (1 << VB_WITNESS_BIT) != 0) self.nodes[0].setmocktime(0) # undo mocktime + # Uncompressed pubkeys are no longer supported in default relay policy, + # but (for now) are still valid in blocks. + def test_uncompressed_pubkey(self): + print("\tTesting uncompressed pubkeys") + # Segwit transactions using uncompressed pubkeys are not accepted + # under default policy, but should still pass consensus. + key = CECKey() + key.set_secretbytes(b"9") + key.set_compressed(False) + pubkey = CPubKey(key.get_pubkey()) + assert_equal(len(pubkey), 65) # This should be an uncompressed pubkey + + assert(len(self.utxo) > 0) + utxo = self.utxo.pop(0) + + # Test 1: P2WPKH + # First create a P2WPKH output that uses an uncompressed pubkey + pubkeyhash = hash160(pubkey) + scriptPKH = CScript([OP_0, pubkeyhash]) + tx = CTransaction() + tx.vin.append(CTxIn(COutPoint(utxo.sha256, utxo.n), b"")) + tx.vout.append(CTxOut(utxo.nValue-1000, scriptPKH)) + tx.rehash() + + # Confirm it in a block. + block = self.build_next_block() + self.update_witness_block_with_transactions(block, [tx]) + self.test_node.test_witness_block(block, accepted=True) + + # Now try to spend it. Send it to a P2WSH output, which we'll + # use in the next test. + witness_program = CScript([pubkey, CScriptOp(OP_CHECKSIG)]) + witness_hash = sha256(witness_program) + scriptWSH = CScript([OP_0, witness_hash]) + + tx2 = CTransaction() + tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b"")) + tx2.vout.append(CTxOut(tx.vout[0].nValue-1000, scriptWSH)) + script = GetP2PKHScript(pubkeyhash) + sig_hash = SegwitVersion1SignatureHash(script, tx2, 0, SIGHASH_ALL, tx.vout[0].nValue) + signature = key.sign(sig_hash) + b'\x01' # 0x1 is SIGHASH_ALL + tx2.wit.vtxinwit.append(CTxInWitness()) + tx2.wit.vtxinwit[0].scriptWitness.stack = [ signature, pubkey ] + tx2.rehash() + + # Should fail policy test. + self.test_node.test_transaction_acceptance(tx2, True, False, b'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)') + # But passes consensus. + block = self.build_next_block() + self.update_witness_block_with_transactions(block, [tx2]) + self.test_node.test_witness_block(block, accepted=True) + + # Test 2: P2WSH + # Try to spend the P2WSH output created in last test. + # Send it to a P2SH(P2WSH) output, which we'll use in the next test. + p2sh_witness_hash = hash160(scriptWSH) + scriptP2SH = CScript([OP_HASH160, p2sh_witness_hash, OP_EQUAL]) + scriptSig = CScript([scriptWSH]) + + tx3 = CTransaction() + tx3.vin.append(CTxIn(COutPoint(tx2.sha256, 0), b"")) + tx3.vout.append(CTxOut(tx2.vout[0].nValue-1000, scriptP2SH)) + tx3.wit.vtxinwit.append(CTxInWitness()) + sign_P2PK_witness_input(witness_program, tx3, 0, SIGHASH_ALL, tx2.vout[0].nValue, key) + + # Should fail policy test. + self.test_node.test_transaction_acceptance(tx3, True, False, b'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)') + # But passes consensus. + block = self.build_next_block() + self.update_witness_block_with_transactions(block, [tx3]) + self.test_node.test_witness_block(block, accepted=True) + + # Test 3: P2SH(P2WSH) + # Try to spend the P2SH output created in the last test. + # Send it to a P2PKH output, which we'll use in the next test. + scriptPubKey = GetP2PKHScript(pubkeyhash) + tx4 = CTransaction() + tx4.vin.append(CTxIn(COutPoint(tx3.sha256, 0), scriptSig)) + tx4.vout.append(CTxOut(tx3.vout[0].nValue-1000, scriptPubKey)) + tx4.wit.vtxinwit.append(CTxInWitness()) + sign_P2PK_witness_input(witness_program, tx4, 0, SIGHASH_ALL, tx3.vout[0].nValue, key) + + # Should fail policy test. + self.test_node.test_transaction_acceptance(tx4, True, False, b'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)') + block = self.build_next_block() + self.update_witness_block_with_transactions(block, [tx4]) + self.test_node.test_witness_block(block, accepted=True) + + # Test 4: Uncompressed pubkeys should still be valid in non-segwit + # transactions. + tx5 = CTransaction() + tx5.vin.append(CTxIn(COutPoint(tx4.sha256, 0), b"")) + tx5.vout.append(CTxOut(tx4.vout[0].nValue-1000, CScript([OP_TRUE]))) + (sig_hash, err) = SignatureHash(scriptPubKey, tx5, 0, SIGHASH_ALL) + signature = key.sign(sig_hash) + b'\x01' # 0x1 is SIGHASH_ALL + tx5.vin[0].scriptSig = CScript([signature, pubkey]) + tx5.rehash() + # Should pass policy and consensus. + self.test_node.test_transaction_acceptance(tx5, True, True) + block = self.build_next_block() + self.update_witness_block_with_transactions(block, [tx5]) + self.test_node.test_witness_block(block, accepted=True) + self.utxo.append(UTXO(tx5.sha256, 0, tx5.vout[0].nValue)) + def test_non_standard_witness(self): print("\tTesting detection of non-standard P2WSH witness") pad = chr(1).encode('latin-1') @@ -1887,6 +1995,7 @@ def run_test(self): self.test_standardness_v0(segwit_activated=True) self.test_segwit_versions() self.test_premature_coinbase_witness_spend() + self.test_uncompressed_pubkey() self.test_signature_version_1() self.test_non_standard_witness() sync_blocks(self.nodes) From 248f3a76a825a332e5495c5947ad283a9e5e938f Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 17 Oct 2016 00:32:36 +0800 Subject: [PATCH 1025/1802] Fix ismine and addwitnessaddress: no uncompressed keys in segwit --- src/script/ismine.cpp | 62 ++++++++++++++++++++++++++++++++++------ src/script/ismine.h | 11 +++++-- src/wallet/rpcwallet.cpp | 17 +++++++---- 3 files changed, 75 insertions(+), 15 deletions(-) diff --git a/src/script/ismine.cpp b/src/script/ismine.cpp index 0bf180341e4cc..7467d23b2d3a2 100644 --- a/src/script/ismine.cpp +++ b/src/script/ismine.cpp @@ -29,13 +29,25 @@ unsigned int HaveKeys(const vector& pubkeys, const CKeyStore& keystore) return nResult; } -isminetype IsMine(const CKeyStore &keystore, const CTxDestination& dest) +isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey, SigVersion sigversion) +{ + bool isInvalid = false; + return IsMine(keystore, scriptPubKey, isInvalid, sigversion); +} + +isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest, SigVersion sigversion) +{ + bool isInvalid = false; + return IsMine(keystore, dest, isInvalid, sigversion); +} + +isminetype IsMine(const CKeyStore &keystore, const CTxDestination& dest, bool& isInvalid, SigVersion sigversion) { CScript script = GetScriptForDestination(dest); - return IsMine(keystore, script); + return IsMine(keystore, script, isInvalid, sigversion); } -isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) +isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey, bool& isInvalid, SigVersion sigversion) { vector vSolutions; txnouttype whichType; @@ -53,12 +65,35 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) break; case TX_PUBKEY: keyID = CPubKey(vSolutions[0]).GetID(); + if (sigversion != SIGVERSION_BASE && vSolutions[0].size() != 33) { + isInvalid = true; + return ISMINE_NO; + } if (keystore.HaveKey(keyID)) return ISMINE_SPENDABLE; break; - case TX_PUBKEYHASH: case TX_WITNESS_V0_KEYHASH: + { + if (!keystore.HaveCScript(CScriptID(CScript() << OP_0 << vSolutions[0]))) { + // We do not support bare witness outputs unless the P2SH version of it would be + // acceptable as well. This protects against matching before segwit activates. + // This also applies to the P2WSH case. + break; + } + isminetype ret = ::IsMine(keystore, GetScriptForDestination(CKeyID(uint160(vSolutions[0]))), isInvalid, SIGVERSION_WITNESS_V0); + if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid)) + return ret; + break; + } + case TX_PUBKEYHASH: keyID = CKeyID(uint160(vSolutions[0])); + if (sigversion != SIGVERSION_BASE) { + CPubKey pubkey; + if (keystore.GetPubKey(keyID, pubkey) && !pubkey.IsCompressed()) { + isInvalid = true; + return ISMINE_NO; + } + } if (keystore.HaveKey(keyID)) return ISMINE_SPENDABLE; break; @@ -67,21 +102,24 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) CScriptID scriptID = CScriptID(uint160(vSolutions[0])); CScript subscript; if (keystore.GetCScript(scriptID, subscript)) { - isminetype ret = IsMine(keystore, subscript); - if (ret == ISMINE_SPENDABLE) + isminetype ret = IsMine(keystore, subscript, isInvalid); + if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid)) return ret; } break; } case TX_WITNESS_V0_SCRIPTHASH: { + if (!keystore.HaveCScript(CScriptID(CScript() << OP_0 << vSolutions[0]))) { + break; + } uint160 hash; CRIPEMD160().Write(&vSolutions[0][0], vSolutions[0].size()).Finalize(hash.begin()); CScriptID scriptID = CScriptID(hash); CScript subscript; if (keystore.GetCScript(scriptID, subscript)) { - isminetype ret = IsMine(keystore, subscript); - if (ret == ISMINE_SPENDABLE) + isminetype ret = IsMine(keystore, subscript, isInvalid, SIGVERSION_WITNESS_V0); + if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid)) return ret; } break; @@ -95,6 +133,14 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) // them) enable spend-out-from-under-you attacks, especially // in shared-wallet situations. vector keys(vSolutions.begin()+1, vSolutions.begin()+vSolutions.size()-1); + if (sigversion != SIGVERSION_BASE) { + for (size_t i = 0; i < keys.size(); i++) { + if (keys[i].size() != 33) { + isInvalid = true; + return ISMINE_NO; + } + } + } if (HaveKeys(keys, keystore) == keys.size()) return ISMINE_SPENDABLE; break; diff --git a/src/script/ismine.h b/src/script/ismine.h index 4b7db8802ba54..ec7a620e330cb 100644 --- a/src/script/ismine.h +++ b/src/script/ismine.h @@ -28,7 +28,14 @@ enum isminetype /** used for bitflags of isminetype */ typedef uint8_t isminefilter; -isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey); -isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest); +/* isInvalid becomes true when the script is found invalid by consensus or policy. This will terminate the recursion + * and return a ISMINE_NO immediately, as an invalid script should never be considered as "mine". This is needed as + * different SIGVERSION may have different network rules. Currently the only use of isInvalid is indicate uncompressed + * keys in SIGVERSION_WITNESS_V0 script, but could also be used in similar cases in the future + */ +isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey, bool& isInvalid, SigVersion = SIGVERSION_BASE); +isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey, SigVersion = SIGVERSION_BASE); +isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest, bool& isInvalid, SigVersion = SIGVERSION_BASE); +isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest, SigVersion = SIGVERSION_BASE); #endif // BITCOIN_SCRIPT_ISMINE_H diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 3eb7e5d9ba885..8e95426d11bdf 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2015 The Bitcoin Core developers +// Copyright (c) 2009-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -1025,9 +1025,12 @@ class Witnessifier : public boost::static_visitor bool operator()(const CKeyID &keyID) { CPubKey pubkey; - if (pwalletMain && pwalletMain->GetPubKey(keyID, pubkey)) { - CScript basescript; - basescript << ToByteVector(pubkey) << OP_CHECKSIG; + if (pwalletMain) { + CScript basescript = GetScriptForDestination(keyID); + isminetype typ; + typ = IsMine(*pwalletMain, basescript, SIGVERSION_WITNESS_V0); + if (typ != ISMINE_SPENDABLE && typ != ISMINE_WATCH_SOLVABLE) + return false; CScript witscript = GetScriptForWitness(basescript); pwalletMain->AddCScript(witscript); result = CScriptID(witscript); @@ -1045,6 +1048,10 @@ class Witnessifier : public boost::static_visitor result = scriptID; return true; } + isminetype typ; + typ = IsMine(*pwalletMain, subscript, SIGVERSION_WITNESS_V0); + if (typ != ISMINE_SPENDABLE && typ != ISMINE_WATCH_SOLVABLE) + return false; CScript witscript = GetScriptForWitness(subscript); pwalletMain->AddCScript(witscript); result = CScriptID(witscript); @@ -1090,7 +1097,7 @@ UniValue addwitnessaddress(const UniValue& params, bool fHelp) CTxDestination dest = address.Get(); bool ret = boost::apply_visitor(w, dest); if (!ret) { - throw JSONRPCError(RPC_WALLET_ERROR, "Public key or redeemscript not known to wallet"); + throw JSONRPCError(RPC_WALLET_ERROR, "Public key or redeemscript not known to wallet, or the key is uncompressed"); } pwalletMain->SetAddressBook(w.result, "", "receive"); From 9260085377e89e666d0cb95b462261d7e3a9c82f Mon Sep 17 00:00:00 2001 From: Johnson Lau Date: Sat, 15 Oct 2016 02:29:39 +0800 Subject: [PATCH 1026/1802] test segwit uncompressed key fixes --- qa/rpc-tests/segwit.py | 360 +++++++++++++++++++++++- qa/rpc-tests/test_framework/address.py | 74 +++++ src/test/data/script_tests.json | 368 ++++++++++++++++++++++++- src/test/script_tests.cpp | 93 +++++++ 4 files changed, 893 insertions(+), 2 deletions(-) create mode 100644 qa/rpc-tests/test_framework/address.py diff --git a/qa/rpc-tests/segwit.py b/qa/rpc-tests/segwit.py index 745a1d47508cb..41a1b3b20fd00 100755 --- a/qa/rpc-tests/segwit.py +++ b/qa/rpc-tests/segwit.py @@ -9,7 +9,10 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * -from test_framework.mininode import sha256, ripemd160 +from test_framework.mininode import sha256, ripemd160, CTransaction, CTxIn, COutPoint, CTxOut +from test_framework.address import script_to_p2sh, key_to_p2pkh +from test_framework.script import CScript, OP_HASH160, OP_CHECKSIG, OP_0, hash160, OP_EQUAL, OP_DUP, OP_EQUALVERIFY, OP_1, OP_2, OP_CHECKMULTISIG +from io import BytesIO NODE_0 = 0 NODE_1 = 1 @@ -242,5 +245,360 @@ def run_test(self): # This is an acceptable outcome pass + print("Verify behaviour of importaddress, addwitnessaddress and listunspent") + + # Some public keys to be used later + pubkeys = [ + "0363D44AABD0F1699138239DF2F042C3282C0671CC7A76826A55C8203D90E39242", # cPiM8Ub4heR9NBYmgVzJQiUH1if44GSBGiqaeJySuL2BKxubvgwb + "02D3E626B3E616FC8662B489C123349FECBFC611E778E5BE739B257EAE4721E5BF", # cPpAdHaD6VoYbW78kveN2bsvb45Q7G5PhaPApVUGwvF8VQ9brD97 + "04A47F2CBCEFFA7B9BCDA184E7D5668D3DA6F9079AD41E422FA5FD7B2D458F2538A62F5BD8EC85C2477F39650BD391EA6250207065B2A81DA8B009FC891E898F0E", # 91zqCU5B9sdWxzMt1ca3VzbtVm2YM6Hi5Rxn4UDtxEaN9C9nzXV + "02A47F2CBCEFFA7B9BCDA184E7D5668D3DA6F9079AD41E422FA5FD7B2D458F2538", # cPQFjcVRpAUBG8BA9hzr2yEzHwKoMgLkJZBBtK9vJnvGJgMjzTbd + "036722F784214129FEB9E8129D626324F3F6716555B603FFE8300BBCB882151228", # cQGtcm34xiLjB1v7bkRa4V3aAc9tS2UTuBZ1UnZGeSeNy627fN66 + "0266A8396EE936BF6D99D17920DB21C6C7B1AB14C639D5CD72B300297E416FD2EC", # cTW5mR5M45vHxXkeChZdtSPozrFwFgmEvTNnanCW6wrqwaCZ1X7K + "0450A38BD7F0AC212FEBA77354A9B036A32E0F7C81FC4E0C5ADCA7C549C4505D2522458C2D9AE3CEFD684E039194B72C8A10F9CB9D4764AB26FCC2718D421D3B84", # 92h2XPssjBpsJN5CqSP7v9a7cf2kgDunBC6PDFwJHMACM1rrVBJ + ] + + # Import a compressed key and an uncompressed key, generate some multisig addresses + self.nodes[0].importprivkey("92e6XLo5jVAVwrQKPNTs93oQco8f8sDNBcpv73Dsrs397fQtFQn") + uncompressed_spendable_address = ["mvozP4UwyGD2mGZU4D2eMvMLPB9WkMmMQu"] + self.nodes[0].importprivkey("cNC8eQ5dg3mFAVePDX4ddmPYpPbw41r9bm2jd1nLJT77e6RrzTRR") + compressed_spendable_address = ["mmWQubrDomqpgSYekvsU7HWEVjLFHAakLe"] + assert ((self.nodes[0].validateaddress(uncompressed_spendable_address[0])['iscompressed'] == False)) + assert ((self.nodes[0].validateaddress(compressed_spendable_address[0])['iscompressed'] == True)) + + self.nodes[0].importpubkey(pubkeys[0]) + compressed_solvable_address = [key_to_p2pkh(pubkeys[0])] + self.nodes[0].importpubkey(pubkeys[1]) + compressed_solvable_address.append(key_to_p2pkh(pubkeys[1])) + self.nodes[0].importpubkey(pubkeys[2]) + uncompressed_solvable_address = [key_to_p2pkh(pubkeys[2])] + + spendable_anytime = [] # These outputs should be seen anytime after importprivkey and addmultisigaddress + spendable_after_importaddress = [] # These outputs should be seen after importaddress + solvable_after_importaddress = [] # These outputs should be seen after importaddress but not spendable + unsolvable_after_importaddress = [] # These outputs should be unsolvable after importaddress + solvable_anytime = [] # These outputs should be solvable after importpubkey + unseen_anytime = [] # These outputs should never be seen + + uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], compressed_spendable_address[0]])) + uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], uncompressed_spendable_address[0]])) + compressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_spendable_address[0]])) + uncompressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], uncompressed_solvable_address[0]])) + compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_solvable_address[0]])) + compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_solvable_address[0], compressed_solvable_address[1]])) + unknown_address = ["mtKKyoHabkk6e4ppT7NaM7THqPUt7AzPrT", "2NDP3jLWAFT8NDAiUa9qiE6oBt2awmMq7Dx"] + + # Test multisig_without_privkey + # We have 2 public keys without private keys, use addmultisigaddress to add to wallet. + # Money sent to P2SH of multisig of this should only be seen after importaddress with the BASE58 P2SH address. + + multisig_without_privkey_address = self.nodes[0].addmultisigaddress(2, [pubkeys[3], pubkeys[4]]) + script = CScript([OP_2, hex_str_to_bytes(pubkeys[3]), hex_str_to_bytes(pubkeys[4]), OP_2, OP_CHECKMULTISIG]) + solvable_after_importaddress.append(CScript([OP_HASH160, hash160(script), OP_EQUAL])) + + for i in compressed_spendable_address: + v = self.nodes[0].validateaddress(i) + if (v['isscript']): + [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) + # bare and p2sh multisig with compressed keys should always be spendable + spendable_anytime.extend([bare, p2sh]) + # P2WSH and P2SH(P2WSH) multisig with compressed keys are spendable after direct importaddress + spendable_after_importaddress.extend([p2wsh, p2sh_p2wsh]) + else: + [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) + # normal P2PKH and P2PK with compressed keys should always be spendable + spendable_anytime.extend([p2pkh, p2pk]) + # P2SH_P2PK, P2SH_P2PKH, and witness with compressed keys are spendable after direct importaddress + spendable_after_importaddress.extend([p2wpkh, p2sh_p2wpkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh]) + + for i in uncompressed_spendable_address: + v = self.nodes[0].validateaddress(i) + if (v['isscript']): + [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) + # bare and p2sh multisig with uncompressed keys should always be spendable + spendable_anytime.extend([bare, p2sh]) + # P2WSH and P2SH(P2WSH) multisig with uncompressed keys are never seen + unseen_anytime.extend([p2wsh, p2sh_p2wsh]) + else: + [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) + # normal P2PKH and P2PK with uncompressed keys should always be spendable + spendable_anytime.extend([p2pkh, p2pk]) + # P2SH_P2PK and P2SH_P2PKH are spendable after direct importaddress + spendable_after_importaddress.extend([p2sh_p2pk, p2sh_p2pkh]) + # witness with uncompressed keys are never seen + unseen_anytime.extend([p2wpkh, p2sh_p2wpkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh]) + + for i in compressed_solvable_address: + v = self.nodes[0].validateaddress(i) + if (v['isscript']): + # Multisig without private is not seen after addmultisigaddress, but seen after importaddress + [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) + solvable_after_importaddress.extend([bare, p2sh, p2wsh, p2sh_p2wsh]) + else: + [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) + # normal P2PKH and P2PK with compressed keys should always be seen + solvable_anytime.extend([p2pkh, p2pk]) + # P2SH_P2PK, P2SH_P2PKH, and witness with compressed keys are seen after direct importaddress + solvable_after_importaddress.extend([p2wpkh, p2sh_p2wpkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh]) + + for i in uncompressed_solvable_address: + v = self.nodes[0].validateaddress(i) + if (v['isscript']): + [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) + # Base uncompressed multisig without private is not seen after addmultisigaddress, but seen after importaddress + solvable_after_importaddress.extend([bare, p2sh]) + # P2WSH and P2SH(P2WSH) multisig with uncompressed keys are never seen + unseen_anytime.extend([p2wsh, p2sh_p2wsh]) + else: + [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) + # normal P2PKH and P2PK with uncompressed keys should always be seen + solvable_anytime.extend([p2pkh, p2pk]) + # P2SH_P2PK, P2SH_P2PKH with uncompressed keys are seen after direct importaddress + solvable_after_importaddress.extend([p2sh_p2pk, p2sh_p2pkh]) + # witness with uncompressed keys are never seen + unseen_anytime.extend([p2wpkh, p2sh_p2wpkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh]) + + op1 = CScript([OP_1]) + op0 = CScript([OP_0]) + # 2N7MGY19ti4KDMSzRfPAssP6Pxyuxoi6jLe is the P2SH(P2PKH) version of mjoE3sSrb8ByYEvgnC3Aox86u1CHnfJA4V + unsolvable_address = ["mjoE3sSrb8ByYEvgnC3Aox86u1CHnfJA4V", "2N7MGY19ti4KDMSzRfPAssP6Pxyuxoi6jLe", script_to_p2sh(op1), script_to_p2sh(op0)] + unsolvable_address_key = hex_str_to_bytes("02341AEC7587A51CDE5279E0630A531AEA2615A9F80B17E8D9376327BAEAA59E3D") + unsolvablep2pkh = CScript([OP_DUP, OP_HASH160, hash160(unsolvable_address_key), OP_EQUALVERIFY, OP_CHECKSIG]) + unsolvablep2wshp2pkh = CScript([OP_0, sha256(unsolvablep2pkh)]) + p2shop0 = CScript([OP_HASH160, hash160(op0), OP_EQUAL]) + p2wshop1 = CScript([OP_0, sha256(op1)]) + unsolvable_after_importaddress.append(unsolvablep2pkh) + unsolvable_after_importaddress.append(unsolvablep2wshp2pkh) + unsolvable_after_importaddress.append(op1) # OP_1 will be imported as script + unsolvable_after_importaddress.append(p2wshop1) + unseen_anytime.append(op0) # OP_0 will be imported as P2SH address with no script provided + unsolvable_after_importaddress.append(p2shop0) + + spendable_txid = [] + solvable_txid = [] + spendable_txid.append(self.mine_and_test_listunspent(spendable_anytime, 2)) + solvable_txid.append(self.mine_and_test_listunspent(solvable_anytime, 1)) + self.mine_and_test_listunspent(spendable_after_importaddress + solvable_after_importaddress + unseen_anytime + unsolvable_after_importaddress, 0) + + importlist = [] + for i in compressed_spendable_address + uncompressed_spendable_address + compressed_solvable_address + uncompressed_solvable_address: + v = self.nodes[0].validateaddress(i) + if (v['isscript']): + bare = hex_str_to_bytes(v['hex']) + importlist.append(bytes_to_hex_str(bare)) + importlist.append(bytes_to_hex_str(CScript([OP_0, sha256(bare)]))) + else: + pubkey = hex_str_to_bytes(v['pubkey']) + p2pk = CScript([pubkey, OP_CHECKSIG]) + p2pkh = CScript([OP_DUP, OP_HASH160, hash160(pubkey), OP_EQUALVERIFY, OP_CHECKSIG]) + importlist.append(bytes_to_hex_str(p2pk)) + importlist.append(bytes_to_hex_str(p2pkh)) + importlist.append(bytes_to_hex_str(CScript([OP_0, hash160(pubkey)]))) + importlist.append(bytes_to_hex_str(CScript([OP_0, sha256(p2pk)]))) + importlist.append(bytes_to_hex_str(CScript([OP_0, sha256(p2pkh)]))) + + importlist.append(bytes_to_hex_str(unsolvablep2pkh)) + importlist.append(bytes_to_hex_str(unsolvablep2wshp2pkh)) + importlist.append(bytes_to_hex_str(op1)) + importlist.append(bytes_to_hex_str(p2wshop1)) + + for i in importlist: + try: + self.nodes[0].importaddress(i,"",False,True) + except JSONRPCException as exp: + assert_equal(exp.error["message"], "The wallet already contains the private key for this address or script") + + self.nodes[0].importaddress(script_to_p2sh(op0)) # import OP_0 as address only + self.nodes[0].importaddress(multisig_without_privkey_address) # Test multisig_without_privkey + + spendable_txid.append(self.mine_and_test_listunspent(spendable_anytime + spendable_after_importaddress, 2)) + solvable_txid.append(self.mine_and_test_listunspent(solvable_anytime + solvable_after_importaddress, 1)) + self.mine_and_test_listunspent(unsolvable_after_importaddress, 1) + self.mine_and_test_listunspent(unseen_anytime, 0) + + # addwitnessaddress should refuse to return a witness address if an uncompressed key is used or the address is + # not in the wallet + # note that no witness address should be returned by unsolvable addresses + # the multisig_without_privkey_address will fail because its keys were not added with importpubkey + for i in uncompressed_spendable_address + uncompressed_solvable_address + unknown_address + unsolvable_address + [multisig_without_privkey_address]: + try: + self.nodes[0].addwitnessaddress(i) + except JSONRPCException as exp: + assert_equal(exp.error["message"], "Public key or redeemscript not known to wallet, or the key is uncompressed") + else: + assert(False) + + for i in compressed_spendable_address + compressed_solvable_address: + witaddress = self.nodes[0].addwitnessaddress(i) + # addwitnessaddress should return the same address if it is a known P2SH-witness address + assert_equal(witaddress, self.nodes[0].addwitnessaddress(witaddress)) + + spendable_txid.append(self.mine_and_test_listunspent(spendable_anytime + spendable_after_importaddress, 2)) + solvable_txid.append(self.mine_and_test_listunspent(solvable_anytime + solvable_after_importaddress, 1)) + self.mine_and_test_listunspent(unsolvable_after_importaddress, 1) + self.mine_and_test_listunspent(unseen_anytime, 0) + + # Repeat some tests. This time we don't add witness scripts with importaddress + # Import a compressed key and an uncompressed key, generate some multisig addresses + self.nodes[0].importprivkey("927pw6RW8ZekycnXqBQ2JS5nPyo1yRfGNN8oq74HeddWSpafDJH") + uncompressed_spendable_address = ["mguN2vNSCEUh6rJaXoAVwY3YZwZvEmf5xi"] + self.nodes[0].importprivkey("cMcrXaaUC48ZKpcyydfFo8PxHAjpsYLhdsp6nmtB3E2ER9UUHWnw") + compressed_spendable_address = ["n1UNmpmbVUJ9ytXYXiurmGPQ3TRrXqPWKL"] + + self.nodes[0].importpubkey(pubkeys[5]) + compressed_solvable_address = [key_to_p2pkh(pubkeys[5])] + self.nodes[0].importpubkey(pubkeys[6]) + uncompressed_solvable_address = [key_to_p2pkh(pubkeys[6])] + + spendable_after_addwitnessaddress = [] # These outputs should be seen after importaddress + solvable_after_addwitnessaddress=[] # These outputs should be seen after importaddress but not spendable + unseen_anytime = [] # These outputs should never be seen + + uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], compressed_spendable_address[0]])) + uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], uncompressed_spendable_address[0]])) + compressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_spendable_address[0]])) + uncompressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_solvable_address[0], uncompressed_solvable_address[0]])) + compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_solvable_address[0]])) + + premature_witaddress = [] + + for i in compressed_spendable_address: + v = self.nodes[0].validateaddress(i) + if (v['isscript']): + [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) + # P2WSH and P2SH(P2WSH) multisig with compressed keys are spendable after addwitnessaddress + spendable_after_addwitnessaddress.extend([p2wsh, p2sh_p2wsh]) + premature_witaddress.append(script_to_p2sh(p2wsh)) + else: + [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) + # P2WPKH, P2SH_P2WPKH are spendable after addwitnessaddress + spendable_after_addwitnessaddress.extend([p2wpkh, p2sh_p2wpkh]) + premature_witaddress.append(script_to_p2sh(p2wpkh)) + + for i in uncompressed_spendable_address + uncompressed_solvable_address: + v = self.nodes[0].validateaddress(i) + if (v['isscript']): + [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) + # P2WSH and P2SH(P2WSH) multisig with uncompressed keys are never seen + unseen_anytime.extend([p2wsh, p2sh_p2wsh]) + else: + [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) + # P2WPKH, P2SH_P2WPKH with uncompressed keys are never seen + unseen_anytime.extend([p2wpkh, p2sh_p2wpkh]) + + for i in compressed_solvable_address: + v = self.nodes[0].validateaddress(i) + if (v['isscript']): + # P2WSH multisig without private key are seen after addwitnessaddress + [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) + solvable_after_addwitnessaddress.extend([p2wsh, p2sh_p2wsh]) + premature_witaddress.append(script_to_p2sh(p2wsh)) + else: + [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) + # P2SH_P2PK, P2SH_P2PKH with compressed keys are seen after addwitnessaddress + solvable_after_addwitnessaddress.extend([p2wpkh, p2sh_p2wpkh]) + premature_witaddress.append(script_to_p2sh(p2wpkh)) + + self.mine_and_test_listunspent(spendable_after_addwitnessaddress + solvable_after_addwitnessaddress + unseen_anytime, 0) + + # addwitnessaddress should refuse to return a witness address if an uncompressed key is used + # note that a multisig address returned by addmultisigaddress is not solvable until it is added with importaddress + # premature_witaddress are not accepted until the script is added with addwitnessaddress first + for i in uncompressed_spendable_address + uncompressed_solvable_address + premature_witaddress + [compressed_solvable_address[1]]: + try: + self.nodes[0].addwitnessaddress(i) + except JSONRPCException as exp: + assert_equal(exp.error["message"], "Public key or redeemscript not known to wallet, or the key is uncompressed") + else: + assert(False) + + # after importaddress it should pass addwitnessaddress + v = self.nodes[0].validateaddress(compressed_solvable_address[1]) + self.nodes[0].importaddress(v['hex'],"",False,True) + for i in compressed_spendable_address + compressed_solvable_address + premature_witaddress: + witaddress = self.nodes[0].addwitnessaddress(i) + assert_equal(witaddress, self.nodes[0].addwitnessaddress(witaddress)) + + spendable_txid.append(self.mine_and_test_listunspent(spendable_after_addwitnessaddress, 2)) + solvable_txid.append(self.mine_and_test_listunspent(solvable_after_addwitnessaddress, 1)) + self.mine_and_test_listunspent(unseen_anytime, 0) + + # Check that spendable outputs are really spendable + self.create_and_mine_tx_from_txids(spendable_txid) + + # import all the private keys so solvable addresses become spendable + self.nodes[0].importprivkey("cPiM8Ub4heR9NBYmgVzJQiUH1if44GSBGiqaeJySuL2BKxubvgwb") + self.nodes[0].importprivkey("cPpAdHaD6VoYbW78kveN2bsvb45Q7G5PhaPApVUGwvF8VQ9brD97") + self.nodes[0].importprivkey("91zqCU5B9sdWxzMt1ca3VzbtVm2YM6Hi5Rxn4UDtxEaN9C9nzXV") + self.nodes[0].importprivkey("cPQFjcVRpAUBG8BA9hzr2yEzHwKoMgLkJZBBtK9vJnvGJgMjzTbd") + self.nodes[0].importprivkey("cQGtcm34xiLjB1v7bkRa4V3aAc9tS2UTuBZ1UnZGeSeNy627fN66") + self.nodes[0].importprivkey("cTW5mR5M45vHxXkeChZdtSPozrFwFgmEvTNnanCW6wrqwaCZ1X7K") + self.create_and_mine_tx_from_txids(solvable_txid) + + def mine_and_test_listunspent(self, script_list, ismine): + utxo = find_unspent(self.nodes[0], 50) + tx = CTransaction() + tx.vin.append(CTxIn(COutPoint(int('0x'+utxo['txid'],0), utxo['vout']))) + for i in script_list: + tx.vout.append(CTxOut(10000000, i)) + tx.rehash() + signresults = self.nodes[0].signrawtransaction(bytes_to_hex_str(tx.serialize_without_witness()))['hex'] + txid = self.nodes[0].sendrawtransaction(signresults, True) + self.nodes[0].generate(1) + sync_blocks(self.nodes) + watchcount = 0 + spendcount = 0 + for i in self.nodes[0].listunspent(): + if (i['txid'] == txid): + watchcount += 1 + if (i['spendable'] == True): + spendcount += 1 + if (ismine == 2): + assert_equal(spendcount, len(script_list)) + elif (ismine == 1): + assert_equal(watchcount, len(script_list)) + assert_equal(spendcount, 0) + else: + assert_equal(watchcount, 0) + return txid + + def p2sh_address_to_script(self,v): + bare = CScript(hex_str_to_bytes(v['hex'])) + p2sh = CScript(hex_str_to_bytes(v['scriptPubKey'])) + p2wsh = CScript([OP_0, sha256(bare)]) + p2sh_p2wsh = CScript([OP_HASH160, hash160(p2wsh), OP_EQUAL]) + return([bare, p2sh, p2wsh, p2sh_p2wsh]) + + def p2pkh_address_to_script(self,v): + pubkey = hex_str_to_bytes(v['pubkey']) + p2wpkh = CScript([OP_0, hash160(pubkey)]) + p2sh_p2wpkh = CScript([OP_HASH160, hash160(p2wpkh), OP_EQUAL]) + p2pk = CScript([pubkey, OP_CHECKSIG]) + p2pkh = CScript(hex_str_to_bytes(v['scriptPubKey'])) + p2sh_p2pk = CScript([OP_HASH160, hash160(p2pk), OP_EQUAL]) + p2sh_p2pkh = CScript([OP_HASH160, hash160(p2pkh), OP_EQUAL]) + p2wsh_p2pk = CScript([OP_0, sha256(p2pk)]) + p2wsh_p2pkh = CScript([OP_0, sha256(p2pkh)]) + p2sh_p2wsh_p2pk = CScript([OP_HASH160, hash160(p2wsh_p2pk), OP_EQUAL]) + p2sh_p2wsh_p2pkh = CScript([OP_HASH160, hash160(p2wsh_p2pkh), OP_EQUAL]) + return [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] + + def create_and_mine_tx_from_txids(self, txids, success = True): + tx = CTransaction() + for i in txids: + txtmp = CTransaction() + txraw = self.nodes[0].getrawtransaction(i) + f = BytesIO(hex_str_to_bytes(txraw)) + txtmp.deserialize(f) + for j in range(len(txtmp.vout)): + tx.vin.append(CTxIn(COutPoint(int('0x'+i,0), j))) + tx.vout.append(CTxOut(0, CScript())) + tx.rehash() + signresults = self.nodes[0].signrawtransaction(bytes_to_hex_str(tx.serialize_without_witness()))['hex'] + self.nodes[0].sendrawtransaction(signresults, True) + self.nodes[0].generate(1) + sync_blocks(self.nodes) + + if __name__ == '__main__': SegWitTest().main() diff --git a/qa/rpc-tests/test_framework/address.py b/qa/rpc-tests/test_framework/address.py new file mode 100644 index 0000000000000..50b999be6110d --- /dev/null +++ b/qa/rpc-tests/test_framework/address.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python3 +# Copyright (c) 2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# +# address.py +# +# This file encodes and decodes BASE58 P2PKH and P2SH addresses +# + +from .script import hash256, hash160, sha256, CScript, OP_0 +from .util import bytes_to_hex_str, hex_str_to_bytes + +chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' + +def byte_to_base58(b, version): + result = '' + str = bytes_to_hex_str(b) + str = bytes_to_hex_str(chr(version).encode('latin-1')) + str + checksum = bytes_to_hex_str(hash256(hex_str_to_bytes(str))) + str += checksum[:8] + value = int('0x'+str,0) + while value > 0: + result = chars[value % 58] + result + value //= 58 + while (str[:2] == '00'): + result = chars[0] + result + str = str[2:] + return result + +# TODO: def base58_decode + +def keyhash_to_p2pkh(hash, main = False): + assert (len(hash) == 20) + version = 0 if main else 111 + return byte_to_base58(hash, version) + +def scripthash_to_p2sh(hash, main = False): + assert (len(hash) == 20) + version = 5 if main else 196 + return byte_to_base58(hash, version) + +def key_to_p2pkh(key, main = False): + key = check_key(key) + return keyhash_to_p2pkh(hash160(key), main) + +def script_to_p2sh(script, main = False): + script = check_script(script) + return scripthash_to_p2sh(hash160(script), main) + +def key_to_p2sh_p2wpkh(key, main = False): + key = check_key(key) + p2shscript = CScript([OP_0, hash160(key)]) + return script_to_p2sh(p2shscript, main) + +def script_to_p2sh_p2wsh(script, main = False): + script = check_script(script) + p2shscript = CScript([OP_0, sha256(script)]) + return script_to_p2sh(p2shscript, main) + +def check_key(key): + if (type(key) is str): + key = hex_str_to_bytes(key) # Assuming this is hex string + if (type(key) is bytes and (len(key) == 33 or len(key) == 65)): + return key + assert(False) + +def check_script(script): + if (type(script) is str): + script = hex_str_to_bytes(script) # Assuming this is hex string + if (type(script) is bytes or type(script) is CScript): + return script + assert(False) diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json index 06103ea5bdd66..5c054ed3e8fb0 100644 --- a/src/test/data/script_tests.json +++ b/src/test/data/script_tests.json @@ -1855,6 +1855,8 @@ "OK", "P2SH with CLEANSTACK" ], + +["Testing with uncompressed keys in witness v0 without WITNESS_PUBKEYTYPE"], [ [ "304402200d461c140cfdfcf36b94961db57ae8c18d1cb80e9d95a9e47ac22470c1bf125502201c8dc1cbfef6a3ef90acbbb992ca22fe9466ee6f9d4898eda277a7ac3ab4b25101", @@ -2139,7 +2141,371 @@ "P2PK with witness" ], -["CHECKSEQUENCEVERIFY tests"], +["Testing with compressed keys in witness v0 with WITNESS_PUBKEYTYPE"], +[ + [ + "304402204256146fcf8e73b0fd817ffa2a4e408ff0418ff987dd08a4f485b62546f6c43c02203f3c8c3e2febc051e1222867f5f9d0eaf039d6792911c10940aa3cc74123378e01", + "210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac", + 0.00000001 + ], + "", + "0 0x20 0x1863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262", + "P2SH,WITNESS,WITNESS_PUBKEYTYPE", + "OK", + "Basic P2WSH with compressed key" +], +[ + [ + "304402204edf27486f11432466b744df533e1acac727e0c83e5f912eb289a3df5bf8035f022075809fdd876ede40ad21667eba8b7e96394938f9c9c50f11b6a1280cce2cea8601", + "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + 0.00000001 + ], + "", + "0 0x14 0x751e76e8199196d454941c45d1b3a323f1433bd6", + "P2SH,WITNESS,WITNESS_PUBKEYTYPE", + "OK", + "Basic P2WPKH with compressed key" +], +[ + [ + "304402203a549090cc46bce1e5e95c4922ea2c12747988e0207b04c42f81cdbe87bb1539022050f57a245b875fd5119c419aaf050bcdf41384f0765f04b809e5bced1fe7093d01", + "210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac", + 0.00000001 + ], + "0x22 0x00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262", + "HASH160 0x14 0xe4300531190587e3880d4c3004f5355d88ff928d EQUAL", + "P2SH,WITNESS,WITNESS_PUBKEYTYPE", + "OK", + "Basic P2SH(P2WSH) with compressed key" +], +[ + [ + "304402201bc0d53046827f4a35a3166e33e3b3366c4085540dc383b95d21ed2ab11e368a0220333e78c6231214f5f8e59621e15d7eeab0d4e4d0796437e00bfbd2680c5f9c1701", + "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + 0.00000001 + ], + "0x16 0x0014751e76e8199196d454941c45d1b3a323f1433bd6", + "HASH160 0x14 0xbcfeb728b584253d5f3f70bcb780e9ef218a68f4 EQUAL", + "P2SH,WITNESS,WITNESS_PUBKEYTYPE", + "OK", + "Basic P2SH(P2WPKH) with compressed key" +], + +["Testing with uncompressed keys in witness v0 with WITNESS_PUBKEYTYPE"], +[ + [ + "304402200d461c140cfdfcf36b94961db57ae8c18d1cb80e9d95a9e47ac22470c1bf125502201c8dc1cbfef6a3ef90acbbb992ca22fe9466ee6f9d4898eda277a7ac3ab4b25101", + "410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac", + 0.00000001 + ], + "", + "0 0x20 0xb95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64", + "P2SH,WITNESS,WITNESS_PUBKEYTYPE", + "WITNESS_PUBKEYTYPE", + "Basic P2WSH" +], +[ + [ + "304402201e7216e5ccb3b61d46946ec6cc7e8c4e0117d13ac2fd4b152197e4805191c74202203e9903e33e84d9ee1dd13fb057afb7ccfb47006c23f6a067185efbc9dd780fc501", + "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", + 0.00000001 + ], + "", + "0 0x14 0x91b24bf9f5288532960ac687abb035127b1d28a5", + "P2SH,WITNESS,WITNESS_PUBKEYTYPE", + "WITNESS_PUBKEYTYPE", + "Basic P2WPKH" +], +[ + [ + "3044022066e02c19a513049d49349cf5311a1b012b7c4fae023795a18ab1d91c23496c22022025e216342c8e07ce8ef51e8daee88f84306a9de66236cab230bb63067ded1ad301", + "410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac", + 0.00000001 + ], + "0x22 0x0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64", + "HASH160 0x14 0xf386c2ba255cc56d20cfa6ea8b062f8b59945518 EQUAL", + "P2SH,WITNESS,WITNESS_PUBKEYTYPE", + "WITNESS_PUBKEYTYPE", + "Basic P2SH(P2WSH)" +], +[ + [ + "304402200929d11561cd958460371200f82e9cae64c727a495715a31828e27a7ad57b36d0220361732ced04a6f97351ecca21a56d0b8cd4932c1da1f8f569a2b68e5e48aed7801", + "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", + 0.00000001 + ], + "0x16 0x001491b24bf9f5288532960ac687abb035127b1d28a5", + "HASH160 0x14 0x17743beb429c55c942d2ec703b98c4d57c2df5c6 EQUAL", + "P2SH,WITNESS,WITNESS_PUBKEYTYPE", + "WITNESS_PUBKEYTYPE", + "Basic P2SH(P2WPKH)" +], + +["Testing P2WSH multisig with compressed keys"], +[ + [ + "", + "304402207eb8a59b5c65fc3f6aeef77066556ed5c541948a53a3ba7f7c375b8eed76ee7502201e036a7a9a98ff919ff94dc905d67a1ec006f79ef7cff0708485c8bb79dce38e01", + "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae", + 0.00000001 + ], + "", + "0 0x20 0x06c24420938f0fa3c1cb2707d867154220dca365cdbfa0dd2a83854730221460", + "P2SH,WITNESS,WITNESS_PUBKEYTYPE", + "OK", + "P2WSH CHECKMULTISIG with compressed keys" +], +[ + [ + "", + "3044022033706aed33b8155d5486df3b9bca8cdd3bd4bdb5436dce46d72cdaba51d22b4002203626e94fe53a178af46624f17315c6931f20a30b103f5e044e1eda0c3fe185c601", + "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae", + 0.00000001 + ], + "0x22 0x002006c24420938f0fa3c1cb2707d867154220dca365cdbfa0dd2a83854730221460", + "HASH160 0x14 0x26282aad7c29369d15fed062a778b6100d31a340 EQUAL", + "P2SH,WITNESS,WITNESS_PUBKEYTYPE", + "OK", + "P2SH(P2WSH) CHECKMULTISIG with compressed keys" +], +[ + [ + "", + "304402204048b7371ab1c544362efb89af0c80154747d665aa4fcfb2edfd2d161e57b42e02207e043748e96637080ffc3acbd4dcc6fee1e58d30f6d1269535f32188e5ddae7301", + "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae", + 0.00000001 + ], + "", + "0 0x20 0x06c24420938f0fa3c1cb2707d867154220dca365cdbfa0dd2a83854730221460", + "P2SH,WITNESS,WITNESS_PUBKEYTYPE", + "OK", + "P2WSH CHECKMULTISIG with compressed keys" +], +[ + [ + "", + "3044022073902ef0b8a554c36c44cc03c1b64df96ce2914ebcf946f5bb36078fd5245cdf02205b148f1ba127065fb8c83a5a9576f2dcd111739788ed4bb3ee08b2bd3860c91c01", + "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae", + 0.00000001 + ], + "0x22 0x002006c24420938f0fa3c1cb2707d867154220dca365cdbfa0dd2a83854730221460", + "HASH160 0x14 0x26282aad7c29369d15fed062a778b6100d31a340 EQUAL", + "P2SH,WITNESS,WITNESS_PUBKEYTYPE", + "OK", + "P2SH(P2WSH) CHECKMULTISIG with compressed keys" +], + +["Testing P2WSH multisig with compressed and uncompressed keys (first key being the key closer to the top of stack)"], +[ + [ + "", + "304402202d092ededd1f060609dbf8cb76950634ff42b3e62cf4adb69ab92397b07d742302204ff886f8d0817491a96d1daccdcc820f6feb122ee6230143303100db37dfa79f01", + "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae", + 0.00000001 + ], + "", + "0 0x20 0x08a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa", + "P2SH,WITNESS", + "OK", + "P2WSH CHECKMULTISIG with first key uncompressed and signing with the first key" +], +[ + [ + "", + "304402202dd7e91243f2235481ffb626c3b7baf2c859ae3a5a77fb750ef97b99a8125dc002204960de3d3c3ab9496e218ec57e5240e0e10a6f9546316fe240c216d45116d29301", + "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae", + 0.00000001 + ], + "0x22 0x002008a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa", + "HASH160 0x14 0x6f5ecd4b83b77f3c438f5214eff96454934fc5d1 EQUAL", + "P2SH,WITNESS", + "OK", + "P2SH(P2WSH) CHECKMULTISIG first key uncompressed and signing with the first key" +], +[ + [ + "", + "304402202d092ededd1f060609dbf8cb76950634ff42b3e62cf4adb69ab92397b07d742302204ff886f8d0817491a96d1daccdcc820f6feb122ee6230143303100db37dfa79f01", + "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae", + 0.00000001 + ], + "", + "0 0x20 0x08a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa", + "P2SH,WITNESS,WITNESS_PUBKEYTYPE", + "WITNESS_PUBKEYTYPE", + "P2WSH CHECKMULTISIG with first key uncompressed and signing with the first key" +], +[ + [ + "", + "304402202dd7e91243f2235481ffb626c3b7baf2c859ae3a5a77fb750ef97b99a8125dc002204960de3d3c3ab9496e218ec57e5240e0e10a6f9546316fe240c216d45116d29301", + "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae", + 0.00000001 + ], + "0x22 0x002008a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa", + "HASH160 0x14 0x6f5ecd4b83b77f3c438f5214eff96454934fc5d1 EQUAL", + "P2SH,WITNESS,WITNESS_PUBKEYTYPE", + "WITNESS_PUBKEYTYPE", + "P2SH(P2WSH) CHECKMULTISIG with first key uncompressed and signing with the first key" +], +[ + [ + "", + "304402201e9e6f7deef5b2f21d8223c5189b7d5e82d237c10e97165dd08f547c4e5ce6ed02206796372eb1cc6acb52e13ee2d7f45807780bf96b132cb6697f69434be74b1af901", + "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae", + 0.00000001 + ], + "", + "0 0x20 0x08a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa", + "P2SH,WITNESS", + "OK", + "P2WSH CHECKMULTISIG with first key uncompressed and signing with the second key" +], +[ + [ + "", + "3044022045e667f3f0f3147b95597a24babe9afecea1f649fd23637dfa7ed7e9f3ac18440220295748e81005231135289fe3a88338dabba55afa1bdb4478691337009d82b68d01", + "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae", + 0.00000001 + ], + "0x22 0x002008a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa", + "HASH160 0x14 0x6f5ecd4b83b77f3c438f5214eff96454934fc5d1 EQUAL", + "P2SH,WITNESS", + "OK", + "P2SH(P2WSH) CHECKMULTISIG with first key uncompressed and signing with the second key" +], +[ + [ + "", + "304402201e9e6f7deef5b2f21d8223c5189b7d5e82d237c10e97165dd08f547c4e5ce6ed02206796372eb1cc6acb52e13ee2d7f45807780bf96b132cb6697f69434be74b1af901", + "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae", + 0.00000001 + ], + "", + "0 0x20 0x08a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa", + "P2SH,WITNESS,WITNESS_PUBKEYTYPE", + "WITNESS_PUBKEYTYPE", + "P2WSH CHECKMULTISIG with first key uncompressed and signing with the second key" +], +[ + [ + "", + "3044022045e667f3f0f3147b95597a24babe9afecea1f649fd23637dfa7ed7e9f3ac18440220295748e81005231135289fe3a88338dabba55afa1bdb4478691337009d82b68d01", + "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae", + 0.00000001 + ], + "0x22 0x002008a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa", + "HASH160 0x14 0x6f5ecd4b83b77f3c438f5214eff96454934fc5d1 EQUAL", + "P2SH,WITNESS,WITNESS_PUBKEYTYPE", + "WITNESS_PUBKEYTYPE", + "P2SH(P2WSH) CHECKMULTISIG with first key uncompressed and signing with the second key" +], +[ + [ + "", + "3044022046f5367a261fd8f8d7de6eb390491344f8ec2501638fb9a1095a0599a21d3f4c02205c1b3b51d20091c5f1020841bbca87b44ebe25405c64e4acf758f2eae8665f8401", + "5141048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae", + 0.00000001 + ], + "", + "0 0x20 0x230828ed48871f0f362ce9432aa52f620f442cc8d9ce7a8b5e798365595a38bb", + "P2SH,WITNESS", + "OK", + "P2WSH CHECKMULTISIG with second key uncompressed and signing with the first key" +], +[ + [ + "", + "3044022053e210e4fb1881e6092fd75c3efc5163105599e246ded661c0ee2b5682cc2d6c02203a26b7ada8682a095b84c6d1b881637000b47d761fc837c4cee33555296d63f101", + "5141048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae", + 0.00000001 + ], + "0x22 0x0020230828ed48871f0f362ce9432aa52f620f442cc8d9ce7a8b5e798365595a38bb", + "HASH160 0x14 0x3478e7019ce61a68148f87549579b704cbe4c393 EQUAL", + "P2SH,WITNESS", + "OK", + "P2SH(P2WSH) CHECKMULTISIG second key uncompressed and signing with the first key" +], +[ + [ + "", + "3044022046f5367a261fd8f8d7de6eb390491344f8ec2501638fb9a1095a0599a21d3f4c02205c1b3b51d20091c5f1020841bbca87b44ebe25405c64e4acf758f2eae8665f8401", + "5141048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae", + 0.00000001 + ], + "", + "0 0x20 0x230828ed48871f0f362ce9432aa52f620f442cc8d9ce7a8b5e798365595a38bb", + "P2SH,WITNESS,WITNESS_PUBKEYTYPE", + "OK", + "P2WSH CHECKMULTISIG with second key uncompressed and signing with the first key should pass as the uncompressed key is not used" +], +[ + [ + "", + "3044022053e210e4fb1881e6092fd75c3efc5163105599e246ded661c0ee2b5682cc2d6c02203a26b7ada8682a095b84c6d1b881637000b47d761fc837c4cee33555296d63f101", + "5141048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae", + 0.00000001 + ], + "0x22 0x0020230828ed48871f0f362ce9432aa52f620f442cc8d9ce7a8b5e798365595a38bb", + "HASH160 0x14 0x3478e7019ce61a68148f87549579b704cbe4c393 EQUAL", + "P2SH,WITNESS,WITNESS_PUBKEYTYPE", + "OK", + "P2SH(P2WSH) CHECKMULTISIG with second key uncompressed and signing with the first key should pass as the uncompressed key is not used" +], +[ + [ + "", + "304402206c6d9f5daf85b54af2a93ec38b15ab27f205dbf5c735365ff12451e43613d1f40220736a44be63423ed5ebf53491618b7cc3d8a5093861908da853739c73717938b701", + "5141048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae", + 0.00000001 + ], + "", + "0 0x20 0x230828ed48871f0f362ce9432aa52f620f442cc8d9ce7a8b5e798365595a38bb", + "P2SH,WITNESS", + "OK", + "P2WSH CHECKMULTISIG with second key uncompressed and signing with the second key" +], +[ + [ + "", + "30440220687871bc6144012d75baf585bb26ce13997f7d8c626f4d8825b069c3b2d064470220108936fe1c57327764782253e99090b09c203ec400ed35ce9e026ce2ecf842a001", + "5141048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae", + 0.00000001 + ], + "0x22 0x0020230828ed48871f0f362ce9432aa52f620f442cc8d9ce7a8b5e798365595a38bb", + "HASH160 0x14 0x3478e7019ce61a68148f87549579b704cbe4c393 EQUAL", + "P2SH,WITNESS", + "OK", + "P2SH(P2WSH) CHECKMULTISIG with second key uncompressed and signing with the second key" +], +[ + [ + "", + "304402206c6d9f5daf85b54af2a93ec38b15ab27f205dbf5c735365ff12451e43613d1f40220736a44be63423ed5ebf53491618b7cc3d8a5093861908da853739c73717938b701", + "5141048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae", + 0.00000001 + ], + "", + "0 0x20 0x230828ed48871f0f362ce9432aa52f620f442cc8d9ce7a8b5e798365595a38bb", + "P2SH,WITNESS,WITNESS_PUBKEYTYPE", + "WITNESS_PUBKEYTYPE", + "P2WSH CHECKMULTISIG with second key uncompressed and signing with the second key" +], +[ + [ + "", + "30440220687871bc6144012d75baf585bb26ce13997f7d8c626f4d8825b069c3b2d064470220108936fe1c57327764782253e99090b09c203ec400ed35ce9e026ce2ecf842a001", + "5141048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae", + 0.00000001 + ], + "0x22 0x0020230828ed48871f0f362ce9432aa52f620f442cc8d9ce7a8b5e798365595a38bb", + "HASH160 0x14 0x3478e7019ce61a68148f87549579b704cbe4c393 EQUAL", + "P2SH,WITNESS,WITNESS_PUBKEYTYPE", + "WITNESS_PUBKEYTYPE", + "P2SH(P2WSH) CHECKMULTISIG with second key uncompressed and signing with the second key" +], + +["CHECKSEQUENCEVERIFY tests"], ["", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "INVALID_STACK_OPERATION", "CSV automatically fails on a empty stack"], ["-1", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "NEGATIVE_LOCKTIME", "CSV automatically fails if stack top is negative"], ["0x0100", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY,MINIMALDATA", "UNKNOWN_ERROR", "CSV fails if stack top is not minimally encoded"], diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 7da95488afc43..561adb8ea2252 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -826,6 +826,99 @@ BOOST_AUTO_TEST_CASE(script_build) "P2PK with witness", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH ).PushSig(keys.key0).Push("0").AsWit().ScriptError(SCRIPT_ERR_WITNESS_UNEXPECTED)); + // Compressed keys should pass SCRIPT_VERIFY_WITNESS_PUBKEYTYPE + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG, + "Basic P2WSH with compressed key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WITNESS_SH, + 0, 1).PushWitSig(keys.key0C).PushWitRedeem()); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C), + "Basic P2WPKH with compressed key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WITNESS_PKH, + 0, 1).PushWitSig(keys.key0C).Push(keys.pubkey0C).AsWit()); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG, + "Basic P2SH(P2WSH) with compressed key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WITNESS_SH, + 0, 1).PushWitSig(keys.key0C).PushWitRedeem().PushRedeem()); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C), + "Basic P2SH(P2WPKH) with compressed key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WITNESS_PKH, + 0, 1).PushWitSig(keys.key0C).Push(keys.pubkey0C).AsWit().PushRedeem()); + + // Testing uncompressed key in witness with SCRIPT_VERIFY_WITNESS_PUBKEYTYPE + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, + "Basic P2WSH", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WITNESS_SH, + 0, 1).PushWitSig(keys.key0).PushWitRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0), + "Basic P2WPKH", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WITNESS_PKH, + 0, 1).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, + "Basic P2SH(P2WSH)", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WITNESS_SH, + 0, 1).PushWitSig(keys.key0).PushWitRedeem().PushRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0), + "Basic P2SH(P2WPKH)", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WITNESS_PKH, + 0, 1).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().PushRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE)); + + // P2WSH 1-of-2 multisig with compressed keys + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG, + "P2WSH CHECKMULTISIG with compressed keys", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WITNESS_SH, + 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0C).PushWitRedeem()); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG, + "P2SH(P2WSH) CHECKMULTISIG with compressed keys", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WITNESS_SH, + 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0C).PushWitRedeem().PushRedeem()); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG, + "P2WSH CHECKMULTISIG with compressed keys", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WITNESS_SH, + 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1C).PushWitRedeem()); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG, + "P2SH(P2WSH) CHECKMULTISIG with compressed keys", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WITNESS_SH, + 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1C).PushWitRedeem().PushRedeem()); + + // P2WSH 1-of-2 multisig with first key uncompressed + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG, + "P2WSH CHECKMULTISIG with first key uncompressed and signing with the first key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH, + 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0).PushWitRedeem()); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG, + "P2SH(P2WSH) CHECKMULTISIG first key uncompressed and signing with the first key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_SH, + 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0).PushWitRedeem().PushRedeem()); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG, + "P2WSH CHECKMULTISIG with first key uncompressed and signing with the first key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WITNESS_SH, + 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0).PushWitRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE)); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG, + "P2SH(P2WSH) CHECKMULTISIG with first key uncompressed and signing with the first key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WITNESS_SH, + 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0).PushWitRedeem().PushRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE)); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG, + "P2WSH CHECKMULTISIG with first key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH, + 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1C).PushWitRedeem()); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG, + "P2SH(P2WSH) CHECKMULTISIG with first key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_SH, + 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1C).PushWitRedeem().PushRedeem()); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG, + "P2WSH CHECKMULTISIG with first key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WITNESS_SH, + 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1C).PushWitRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE)); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG, + "P2SH(P2WSH) CHECKMULTISIG with first key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WITNESS_SH, + 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1C).PushWitRedeem().PushRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE)); + // P2WSH 1-of-2 multisig with second key uncompressed + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG, + "P2WSH CHECKMULTISIG with second key uncompressed and signing with the first key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH, + 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0C).PushWitRedeem()); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG, + "P2SH(P2WSH) CHECKMULTISIG second key uncompressed and signing with the first key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_SH, + 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0C).PushWitRedeem().PushRedeem()); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG, + "P2WSH CHECKMULTISIG with second key uncompressed and signing with the first key should pass as the uncompressed key is not used", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WITNESS_SH, + 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0C).PushWitRedeem()); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG, + "P2SH(P2WSH) CHECKMULTISIG with second key uncompressed and signing with the first key should pass as the uncompressed key is not used", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WITNESS_SH, + 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0C).PushWitRedeem().PushRedeem()); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG, + "P2WSH CHECKMULTISIG with second key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH, + 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1).PushWitRedeem()); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG, + "P2SH(P2WSH) CHECKMULTISIG with second key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_SH, + 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1).PushWitRedeem().PushRedeem()); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG, + "P2WSH CHECKMULTISIG with second key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WITNESS_SH, + 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1).PushWitRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE)); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG, + "P2SH(P2WSH) CHECKMULTISIG with second key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WITNESS_SH, + 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1).PushWitRedeem().PushRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE)); + std::set tests_set; { From 67d6ee1e3679504f46473fe0818970565ff3b137 Mon Sep 17 00:00:00 2001 From: Johnson Lau Date: Mon, 17 Oct 2016 03:18:36 +0800 Subject: [PATCH 1027/1802] remove redundant tests in p2p-segwit.py --- qa/rpc-tests/p2p-segwit.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/qa/rpc-tests/p2p-segwit.py b/qa/rpc-tests/p2p-segwit.py index fa505d60c9b66..09ab1b80fcbb2 100755 --- a/qa/rpc-tests/p2p-segwit.py +++ b/qa/rpc-tests/p2p-segwit.py @@ -1872,16 +1872,11 @@ def test_non_standard_witness(self): # Stack element size over 80 bytes is non-standard p2wsh_txs[1].wit.vtxinwit[0].scriptWitness.stack = [pad * 81] * 100 + [scripts[1]] - # It can't be used to blind a node to the transaction - self.std_node.announce_tx_and_wait_for_getdata(p2wsh_txs[1]) - self.std_node.test_transaction_acceptance(p2wsh_txs[1], True, False, b'bad-witness-nonstandard') - self.std_node.announce_tx_and_wait_for_getdata(p2wsh_txs[1]) self.std_node.test_transaction_acceptance(p2wsh_txs[1], True, False, b'bad-witness-nonstandard') # Non-standard nodes should accept self.test_node.test_transaction_acceptance(p2wsh_txs[1], True, True) # Standard nodes should accept if element size is not over 80 bytes p2wsh_txs[1].wit.vtxinwit[0].scriptWitness.stack = [pad * 80] * 100 + [scripts[1]] - self.std_node.announce_tx_and_wait_for_getdata(p2wsh_txs[1]) self.std_node.test_transaction_acceptance(p2wsh_txs[1], True, True) # witnessScript size at 3600 bytes is standard @@ -1900,13 +1895,9 @@ def test_non_standard_witness(self): self.std_node.test_transaction_acceptance(p2sh_txs[0], True, False, b'bad-witness-nonstandard') self.test_node.test_transaction_acceptance(p2sh_txs[0], True, True) p2sh_txs[1].wit.vtxinwit[0].scriptWitness.stack = [pad * 81] * 100 + [scripts[1]] - self.std_node.announce_tx_and_wait_for_getdata(p2sh_txs[1]) - self.std_node.test_transaction_acceptance(p2sh_txs[1], True, False, b'bad-witness-nonstandard') - self.std_node.announce_tx_and_wait_for_getdata(p2sh_txs[1]) self.std_node.test_transaction_acceptance(p2sh_txs[1], True, False, b'bad-witness-nonstandard') self.test_node.test_transaction_acceptance(p2sh_txs[1], True, True) p2sh_txs[1].wit.vtxinwit[0].scriptWitness.stack = [pad * 80] * 100 + [scripts[1]] - self.std_node.announce_tx_and_wait_for_getdata(p2sh_txs[1]) self.std_node.test_transaction_acceptance(p2sh_txs[1], True, True) p2sh_txs[2].wit.vtxinwit[0].scriptWitness.stack = [pad, pad, scripts[2]] self.test_node.test_transaction_acceptance(p2sh_txs[2], True, True) From b0aea8057921f0ed2288cf07048f652c7d6d9cf3 Mon Sep 17 00:00:00 2001 From: BtcDrak Date: Fri, 26 Aug 2016 22:35:46 +0100 Subject: [PATCH 1028/1802] Sync bitcoin-tx with tx version policy --- src/bitcoin-tx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index cb863bda191f8..e09afd632e3ff 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -164,7 +164,7 @@ static void RegisterLoad(const string& strInput) static void MutateTxVersion(CMutableTransaction& tx, const string& cmdVal) { int64_t newVersion = atoi64(cmdVal); - if (newVersion < 1 || newVersion > CTransaction::CURRENT_VERSION) + if (newVersion < 1 || newVersion > CTransaction::MAX_STANDARD_VERSION) throw runtime_error("Invalid TX version requested"); tx.nVersion = (int) newVersion; From 282abd8358e254d976cad05d0eb48586db276bcd Mon Sep 17 00:00:00 2001 From: fanquake Date: Mon, 17 Oct 2016 11:43:24 +0800 Subject: [PATCH 1029/1802] [build-aux] Boost_Base serial 27 --- build-aux/m4/ax_boost_base.m4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build-aux/m4/ax_boost_base.m4 b/build-aux/m4/ax_boost_base.m4 index 45d948933d18f..650c94fa64752 100644 --- a/build-aux/m4/ax_boost_base.m4 +++ b/build-aux/m4/ax_boost_base.m4 @@ -33,7 +33,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 26 +#serial 27 AC_DEFUN([AX_BOOST_BASE], [ @@ -96,7 +96,7 @@ if test "x$want_boost" = "xyes"; then libsubdirs="lib64 libx32 lib lib64" ;; ppc64|s390x|sparc64|aarch64|ppc64le) - libsubdirs="lib64 lib lib64 ppc64le" + libsubdirs="lib64 lib lib64" ;; esac From 6dd37237222f7102e223ece948150cb5c5087e3c Mon Sep 17 00:00:00 2001 From: fanquake Date: Mon, 17 Oct 2016 11:43:59 +0800 Subject: [PATCH 1030/1802] Set minimum required Boost to 1.47.0 --- configure.ac | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 9ce10b745497c..705327e816d94 100644 --- a/configure.ac +++ b/configure.ac @@ -589,8 +589,11 @@ fi if test x$use_boost = xyes; then +dnl Minimum required Boost version +define(MINIMUM_REQUIRED_BOOST, 1.47.0) + dnl Check for boost libs -AX_BOOST_BASE +AX_BOOST_BASE([MINIMUM_REQUIRED_BOOST]) AX_BOOST_SYSTEM AX_BOOST_FILESYSTEM AX_BOOST_PROGRAM_OPTIONS From 7c1716f65d1bfe5e98eec487d3484010305ab334 Mon Sep 17 00:00:00 2001 From: poole_party Date: Mon, 17 Oct 2016 00:08:33 -0400 Subject: [PATCH 1031/1802] Documentation for Building on Windows with WSL The new Windows Subsystem for Linux (WSL) allows a user to run a bash shell directly on Windows in an Ubuntu based environment. This can be used to cross-compile Bitcoin directly on Windows without the need for a separate Linux VM or Server. The instructions included in this commit explain how to configure the environment and build Bitcoin Core using this new feature. --- doc/build-windows.md | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/doc/build-windows.md b/doc/build-windows.md index ec5f26c88b0df..044356830a6ba 100644 --- a/doc/build-windows.md +++ b/doc/build-windows.md @@ -1,13 +1,45 @@ WINDOWS BUILD NOTES ==================== -Some notes on how to build Bitcoin Core for Windows. +Below are some notes on how to build Bitcoin Core for Windows. Most developers use cross-compilation from Ubuntu to build executables for Windows. This is also used to build the release binaries. -Building on Windows itself is possible (for example using msys / mingw-w64), -but no one documented the steps to do this. If you are doing this, please contribute them. +While there are potentially a number of ways to build on Windows (for example using msys / mingw-w64), +using the Windows Subsystem For Linux is the most straight forward. If you are building with +an alternative method, please contribute the instructions here for others who are running versions +of Windows that are not compatible with the Windows Subsystem for Linux. + +Compiling with the Windows Subsystem For Linux +------------------- + +With Windows 10, Microsoft has released a new feature named the +[Windows Subsystem for Linux](https://msdn.microsoft.com/commandline/wsl/about). This feature allows you to run a bash shell directly on Windows in an Ubuntu based +environment. Within this environment you can cross compile for Windows without the need for a separate Linux VM or Server. + +This feature is not supported in versions of Windows prior to Windows 10 or on Windows Server SKUs. + +To get the bash shell, you must first activate the feature in Windows. + +1. Turn on Developer Mode + * Open Settings -> Update and Security -> For developers + * Select the Developer Mode radio button + * Restart if necessary +2. Enable the Windows Subsystem for Linux feature + * From Start, search for "Turn Windows features on or off" (type 'turn') + * Select Windows Subsystem for Linux (beta) + * Click OK + * Restart if necessary +3. Complete Installation + * Open a cmd prompt and type "bash" + * Accept the license + * Create a new UNIX user account (this is a separate account from your Windows account) + +After the bash shell is active, you can follow the instructions below for Windows 64-bit Cross-compilation. +When building dependencies within the 'depends' folder, you may encounter an error building +the protobuf dependency. If this occurs, re-run the command with sudo. This is likely +a bug with the Windows Subsystem for Linux feature and may be fixed with a future update. Cross-compilation ------------------- @@ -41,4 +73,3 @@ To build executables for Windows 64-bit: make For further documentation on the depends system see [README.md](../depends/README.md) in the depends directory. - From 5eaaa83ac1f5eb525f93e2808fafd73f5ed97013 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 13 Oct 2016 16:19:20 +0200 Subject: [PATCH 1032/1802] Kill insecure_random and associated global state There are only a few uses of `insecure_random` outside the tests. This PR replaces uses of insecure_random (and its accompanying global state) in the core code with an FastRandomContext that is automatically seeded on creation. This is meant to be used for inner loops. The FastRandomContext can be in the outer scope, or the class itself, then rand32() is used inside the loop. Useful e.g. for pushing addresses in CNode or the fee rounding, or randomization for coin selection. As a context is created per purpose, thus it gets rid of cross-thread unprotected shared usage of a single set of globals, this should also get rid of the potential race conditions. - I'd say TxMempool::check is not called enough to warrant using a special fast random context, this is switched to GetRand() (open for discussion...) - The use of `insecure_rand` in ConnectThroughProxy has been replaced by an atomic integer counter. The only goal here is to have a different credentials pair for each connection to go on a different Tor circuit, it does not need to be random nor unpredictable. - To avoid having a FastRandomContext on every CNode, the context is passed into PushAddress as appropriate. There remains an insecure_random for test usage in `test_random.h`. --- src/addrman.cpp | 8 ++++---- src/addrman.h | 3 +++ src/main.cpp | 15 ++++++++------ src/net.cpp | 3 ++- src/net.h | 4 ++-- src/netbase.cpp | 4 ++-- src/policy/fees.cpp | 2 +- src/policy/fees.h | 2 ++ src/random.cpp | 11 +++++----- src/random.h | 35 +++++++++++++++----------------- src/test/addrman_tests.cpp | 2 +- src/test/coins_tests.cpp | 2 +- src/test/crypto_tests.cpp | 2 +- src/test/merkle_tests.cpp | 2 +- src/test/net_tests.cpp | 2 +- src/test/pmt_tests.cpp | 2 +- src/test/prevector_tests.cpp | 14 ++++++------- src/test/scheduler_tests.cpp | 4 +--- src/test/sighash_tests.cpp | 2 +- src/test/skiplist_tests.cpp | 2 +- src/test/test_bitcoin.cpp | 1 + src/test/test_random.h | 23 +++++++++++++++++++++ src/test/util_tests.cpp | 2 +- src/test/versionbits_tests.cpp | 2 +- src/txmempool.cpp | 2 +- src/txmempool.h | 1 + src/wallet/test/crypto_tests.cpp | 2 +- src/wallet/wallet.cpp | 4 ++-- 28 files changed, 92 insertions(+), 66 deletions(-) create mode 100644 src/test/test_random.h diff --git a/src/addrman.cpp b/src/addrman.cpp index bfb8e94575de2..20165232122be 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -358,8 +358,8 @@ CAddrInfo CAddrMan::Select_(bool newOnly) int nKBucket = RandomInt(ADDRMAN_TRIED_BUCKET_COUNT); int nKBucketPos = RandomInt(ADDRMAN_BUCKET_SIZE); while (vvTried[nKBucket][nKBucketPos] == -1) { - nKBucket = (nKBucket + insecure_rand()) % ADDRMAN_TRIED_BUCKET_COUNT; - nKBucketPos = (nKBucketPos + insecure_rand()) % ADDRMAN_BUCKET_SIZE; + nKBucket = (nKBucket + insecure_rand.rand32()) % ADDRMAN_TRIED_BUCKET_COUNT; + nKBucketPos = (nKBucketPos + insecure_rand.rand32()) % ADDRMAN_BUCKET_SIZE; } int nId = vvTried[nKBucket][nKBucketPos]; assert(mapInfo.count(nId) == 1); @@ -375,8 +375,8 @@ CAddrInfo CAddrMan::Select_(bool newOnly) int nUBucket = RandomInt(ADDRMAN_NEW_BUCKET_COUNT); int nUBucketPos = RandomInt(ADDRMAN_BUCKET_SIZE); while (vvNew[nUBucket][nUBucketPos] == -1) { - nUBucket = (nUBucket + insecure_rand()) % ADDRMAN_NEW_BUCKET_COUNT; - nUBucketPos = (nUBucketPos + insecure_rand()) % ADDRMAN_BUCKET_SIZE; + nUBucket = (nUBucket + insecure_rand.rand32()) % ADDRMAN_NEW_BUCKET_COUNT; + nUBucketPos = (nUBucketPos + insecure_rand.rand32()) % ADDRMAN_BUCKET_SIZE; } int nId = vvNew[nUBucket][nUBucketPos]; assert(mapInfo.count(nId) == 1); diff --git a/src/addrman.h b/src/addrman.h index 9bab39049d7ab..e9e137c978a7e 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -211,6 +211,9 @@ class CAddrMan //! secret key to randomize bucket select with uint256 nKey; + //! Source of random numbers for randomization in inner loops + FastRandomContext insecure_rand; + //! Find an entry. CAddrInfo* Find(const CNetAddr& addr, int *pnId = NULL); diff --git a/src/main.cpp b/src/main.cpp index c92a38be98f23..ab0dc07529c47 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4758,6 +4758,7 @@ static void RelayAddress(const CAddress& addr, bool fReachable, CConnman& connma uint64_t hashAddr = addr.GetHash(); std::multimap mapMix; const CSipHasher hasher = connman.GetDeterministicRandomizer(RANDOMIZER_ID_ADDRESS_RELAY).Write(hashAddr << 32).Write((GetTime() + hashAddr) / (24*60*60)); + FastRandomContext insecure_rand; auto sortfunc = [&mapMix, &hasher](CNode* pnode) { if (pnode->nVersion >= CADDR_TIME_VERSION) { @@ -4766,9 +4767,9 @@ static void RelayAddress(const CAddress& addr, bool fReachable, CConnman& connma } }; - auto pushfunc = [&addr, &mapMix, &nRelayNodes] { + auto pushfunc = [&addr, &mapMix, &nRelayNodes, &insecure_rand] { for (auto mi = mapMix.begin(); mi != mapMix.end() && nRelayNodes-- > 0; ++mi) - mi->second->PushAddress(addr); + mi->second->PushAddress(addr, insecure_rand); }; connman.ForEachNodeThen(std::move(sortfunc), std::move(pushfunc)); @@ -5078,14 +5079,15 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, if (fListen && !IsInitialBlockDownload()) { CAddress addr = GetLocalAddress(&pfrom->addr, pfrom->GetLocalServices()); + FastRandomContext insecure_rand; if (addr.IsRoutable()) { LogPrint("net", "ProcessMessages: advertising address %s\n", addr.ToString()); - pfrom->PushAddress(addr); + pfrom->PushAddress(addr, insecure_rand); } else if (IsPeerAddrLocalGood(pfrom)) { addr.SetIP(pfrom->addrLocal); LogPrint("net", "ProcessMessages: advertising address %s\n", addr.ToString()); - pfrom->PushAddress(addr); + pfrom->PushAddress(addr, insecure_rand); } } @@ -6008,8 +6010,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, pfrom->vAddrToSend.clear(); vector vAddr = connman.GetAddresses(); + FastRandomContext insecure_rand; BOOST_FOREACH(const CAddress &addr, vAddr) - pfrom->PushAddress(addr); + pfrom->PushAddress(addr, insecure_rand); } @@ -6842,7 +6845,7 @@ bool SendMessages(CNode* pto, CConnman& connman) // until scheduled broadcast, then move the broadcast to within MAX_FEEFILTER_CHANGE_DELAY. else if (timeNow + MAX_FEEFILTER_CHANGE_DELAY * 1000000 < pto->nextSendTimeFeeFilter && (currentFilter < 3 * pto->lastSentFeeFilter / 4 || currentFilter > 4 * pto->lastSentFeeFilter / 3)) { - pto->nextSendTimeFeeFilter = timeNow + (insecure_rand() % MAX_FEEFILTER_CHANGE_DELAY) * 1000000; + pto->nextSendTimeFeeFilter = timeNow + GetRandInt(MAX_FEEFILTER_CHANGE_DELAY) * 1000000; } } } diff --git a/src/net.cpp b/src/net.cpp index 19dd040997ad1..643dd806dfb5c 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -187,7 +187,8 @@ void AdvertiseLocal(CNode *pnode) if (addrLocal.IsRoutable()) { LogPrint("net", "AdvertiseLocal: advertising address %s\n", addrLocal.ToString()); - pnode->PushAddress(addrLocal); + FastRandomContext insecure_rand; + pnode->PushAddress(addrLocal, insecure_rand); } } } diff --git a/src/net.h b/src/net.h index 67f0abe4be820..3417cb2abafb1 100644 --- a/src/net.h +++ b/src/net.h @@ -735,14 +735,14 @@ class CNode addrKnown.insert(_addr.GetKey()); } - void PushAddress(const CAddress& _addr) + void PushAddress(const CAddress& _addr, FastRandomContext &insecure_rand) { // Known checking here is only to save space from duplicates. // SendMessages will filter it again for knowns that were added // after addresses were pushed. if (_addr.IsValid() && !addrKnown.contains(_addr.GetKey())) { if (vAddrToSend.size() >= MAX_ADDR_TO_SEND) { - vAddrToSend[insecure_rand() % vAddrToSend.size()] = _addr; + vAddrToSend[insecure_rand.rand32() % vAddrToSend.size()] = _addr; } else { vAddrToSend.push_back(_addr); } diff --git a/src/netbase.cpp b/src/netbase.cpp index 7d7f1b6788984..9fe34108f57d1 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -596,8 +596,8 @@ static bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDe // do socks negotiation if (proxy.randomize_credentials) { ProxyCredentials random_auth; - random_auth.username = strprintf("%i", insecure_rand()); - random_auth.password = strprintf("%i", insecure_rand()); + static std::atomic_int counter; + random_auth.username = random_auth.password = strprintf("%i", counter++); if (!Socks5(strDest, (unsigned short)port, &random_auth, hSocket)) return false; } else { diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index 7b0e8b7d08cf7..c07cd2eff8be0 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -594,7 +594,7 @@ FeeFilterRounder::FeeFilterRounder(const CFeeRate& minIncrementalFee) CAmount FeeFilterRounder::round(CAmount currentMinFee) { std::set::iterator it = feeset.lower_bound(currentMinFee); - if ((it != feeset.begin() && insecure_rand() % 3 != 0) || it == feeset.end()) { + if ((it != feeset.begin() && insecure_rand.rand32() % 3 != 0) || it == feeset.end()) { it--; } return *it; diff --git a/src/policy/fees.h b/src/policy/fees.h index 463f62f710603..2c1ac3b934a12 100644 --- a/src/policy/fees.h +++ b/src/policy/fees.h @@ -7,6 +7,7 @@ #include "amount.h" #include "uint256.h" +#include "random.h" #include #include @@ -298,5 +299,6 @@ class FeeFilterRounder private: std::set feeset; + FastRandomContext insecure_rand; }; #endif /*BITCOIN_POLICYESTIMATOR_H */ diff --git a/src/random.cpp b/src/random.cpp index d9a8cc145ea91..aa027e49c437f 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -178,22 +178,21 @@ uint256 GetRandHash() return hash; } -uint32_t insecure_rand_Rz = 11; -uint32_t insecure_rand_Rw = 11; -void seed_insecure_rand(bool fDeterministic) +FastRandomContext::FastRandomContext(bool fDeterministic) { // The seed values have some unlikely fixed points which we avoid. if (fDeterministic) { - insecure_rand_Rz = insecure_rand_Rw = 11; + Rz = Rw = 11; } else { uint32_t tmp; do { GetRandBytes((unsigned char*)&tmp, 4); } while (tmp == 0 || tmp == 0x9068ffffU); - insecure_rand_Rz = tmp; + Rz = tmp; do { GetRandBytes((unsigned char*)&tmp, 4); } while (tmp == 0 || tmp == 0x464fffffU); - insecure_rand_Rw = tmp; + Rw = tmp; } } + diff --git a/src/random.h b/src/random.h index 31b80bd565bdc..e97d2d1fb0b54 100644 --- a/src/random.h +++ b/src/random.h @@ -28,25 +28,22 @@ uint256 GetRandHash(); void GetStrongRandBytes(unsigned char* buf, int num); /** - * Seed insecure_rand using the random pool. - * @param Deterministic Use a deterministic seed + * Fast randomness source. This is seeded once with secure random data, but + * is completely deterministic and insecure after that. + * This class is not thread-safe. */ -void seed_insecure_rand(bool fDeterministic = false); - -/** - * MWC RNG of George Marsaglia - * This is intended to be fast. It has a period of 2^59.3, though the - * least significant 16 bits only have a period of about 2^30.1. - * - * @return random value - */ -extern uint32_t insecure_rand_Rz; -extern uint32_t insecure_rand_Rw; -static inline uint32_t insecure_rand(void) -{ - insecure_rand_Rz = 36969 * (insecure_rand_Rz & 65535) + (insecure_rand_Rz >> 16); - insecure_rand_Rw = 18000 * (insecure_rand_Rw & 65535) + (insecure_rand_Rw >> 16); - return (insecure_rand_Rw << 16) + insecure_rand_Rz; -} +class FastRandomContext { +public: + explicit FastRandomContext(bool fDeterministic=false); + + uint32_t rand32() { + Rz = 36969 * (Rz & 65535) + (Rz >> 16); + Rw = 18000 * (Rw & 65535) + (Rw >> 16); + return (Rw << 16) + Rz; + } + + uint32_t Rz; + uint32_t Rw; +}; #endif // BITCOIN_RANDOM_H diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp index 5ccaeb57bbe2f..adff09f754880 100644 --- a/src/test/addrman_tests.cpp +++ b/src/test/addrman_tests.cpp @@ -26,7 +26,7 @@ class CAddrManTest : public CAddrMan void MakeDeterministic() { nKey.SetNull(); - seed_insecure_rand(true); + insecure_rand = FastRandomContext(true); } int RandomInt(int nMax) diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index e6923265592d7..b487686136aaf 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "coins.h" -#include "random.h" +#include "test_random.h" #include "script/standard.h" #include "uint256.h" #include "utilstrencodings.h" diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index ff0adae1d22b7..c7b4fb240c20e 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -9,7 +9,7 @@ #include "crypto/sha512.h" #include "crypto/hmac_sha256.h" #include "crypto/hmac_sha512.h" -#include "random.h" +#include "test_random.h" #include "utilstrencodings.h" #include "test/test_bitcoin.h" diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp index b40ab848dcdb4..66ca381ea7023 100644 --- a/src/test/merkle_tests.cpp +++ b/src/test/merkle_tests.cpp @@ -4,7 +4,7 @@ #include "consensus/merkle.h" #include "test/test_bitcoin.h" -#include "random.h" +#include "test_random.h" #include diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index 4a7d6e778f5dc..f4b5768693bde 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -23,7 +23,7 @@ class CAddrManSerializationMock : public CAddrMan void MakeDeterministic() { nKey.SetNull(); - seed_insecure_rand(true); + insecure_rand = FastRandomContext(true); } }; diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index e9c8691745cc5..b7f83d38f0b84 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -9,7 +9,7 @@ #include "uint256.h" #include "arith_uint256.h" #include "version.h" -#include "random.h" +#include "test_random.h" #include "test/test_bitcoin.h" #include diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp index b8c45ca564dc9..6cad02e738627 100644 --- a/src/test/prevector_tests.cpp +++ b/src/test/prevector_tests.cpp @@ -4,7 +4,7 @@ #include #include "prevector.h" -#include "random.h" +#include "test_random.h" #include "serialize.h" #include "streams.h" @@ -27,8 +27,7 @@ class prevector_tester { typedef typename pretype::size_type Size; bool passed = true; - uint32_t insecure_rand_Rz_cache; - uint32_t insecure_rand_Rw_cache; + FastRandomContext rand_cache; template @@ -171,15 +170,14 @@ class prevector_tester { test(); } ~prevector_tester() { - BOOST_CHECK_MESSAGE(passed, "insecure_rand_Rz: " - << insecure_rand_Rz_cache + BOOST_CHECK_MESSAGE(passed, "insecure_rand_Rz: " + << rand_cache.Rz << ", insecure_rand_Rw: " - << insecure_rand_Rw_cache); + << rand_cache.Rw); } prevector_tester() { seed_insecure_rand(); - insecure_rand_Rz_cache = insecure_rand_Rz; - insecure_rand_Rw_cache = insecure_rand_Rw; + rand_cache = insecure_rand_ctx; } }; diff --git a/src/test/scheduler_tests.cpp b/src/test/scheduler_tests.cpp index aa12dfbd54f8f..891ecf501567f 100644 --- a/src/test/scheduler_tests.cpp +++ b/src/test/scheduler_tests.cpp @@ -42,8 +42,6 @@ static void MicroSleep(uint64_t n) BOOST_AUTO_TEST_CASE(manythreads) { - seed_insecure_rand(false); - // Stress test: hundreds of microsecond-scheduled tasks, // serviced by 10 threads. // @@ -58,7 +56,7 @@ BOOST_AUTO_TEST_CASE(manythreads) boost::mutex counterMutex[10]; int counter[10] = { 0 }; - boost::random::mt19937 rng(insecure_rand()); + boost::random::mt19937 rng(42); boost::random::uniform_int_distribution<> zeroToNine(0, 9); boost::random::uniform_int_distribution<> randomMsec(-11, 1000); boost::random::uniform_int_distribution<> randomDelta(-1000, 1000); diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index 4a48347b702dd..0b1050d020cc5 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -6,7 +6,7 @@ #include "data/sighash.json.h" #include "hash.h" #include "main.h" // For CheckTransaction -#include "random.h" +#include "test_random.h" #include "script/interpreter.h" #include "script/script.h" #include "serialize.h" diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp index f14b902fe19a8..b19f8fbffb33b 100644 --- a/src/test/skiplist_tests.cpp +++ b/src/test/skiplist_tests.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "chain.h" -#include "random.h" +#include "test_random.h" #include "util.h" #include "test/test_bitcoin.h" diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index 02843d8525ea0..27ea837fbffe1 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -27,6 +27,7 @@ #include std::unique_ptr g_connman; +FastRandomContext insecure_rand_ctx(true); extern bool fPrintToConsole; extern void noui_connect(); diff --git a/src/test/test_random.h b/src/test/test_random.h new file mode 100644 index 0000000000000..e61b92b7bce94 --- /dev/null +++ b/src/test/test_random.h @@ -0,0 +1,23 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_TEST_RANDOM_H +#define BITCOIN_TEST_RANDOM_H + +#include "random.h" + +extern FastRandomContext insecure_rand_ctx; + +static inline void seed_insecure_rand(bool fDeterministic = false) +{ + insecure_rand_ctx = FastRandomContext(fDeterministic); +} + +static inline uint32_t insecure_rand(void) +{ + return insecure_rand_ctx.rand32(); +} + +#endif diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index efd44987473c2..0f1c7ab2224b2 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -6,7 +6,7 @@ #include "clientversion.h" #include "primitives/transaction.h" -#include "random.h" +#include "test_random.h" #include "sync.h" #include "utilstrencodings.h" #include "utilmoneystr.h" diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp index 1f86a06a3f7f7..ffc0ff6f8ead3 100644 --- a/src/test/versionbits_tests.cpp +++ b/src/test/versionbits_tests.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "chain.h" -#include "random.h" +#include "test_random.h" #include "versionbits.h" #include "test/test_bitcoin.h" #include "chainparams.h" diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 15fa6fbca3b09..0f1c166abc416 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -647,7 +647,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const if (nCheckFrequency == 0) return; - if (insecure_rand() >= nCheckFrequency) + if (GetRand(std::numeric_limits::max()) >= nCheckFrequency) return; LogPrint("mempool", "Checking mempool with %u transactions and %u inputs\n", (unsigned int)mapTx.size(), (unsigned int)mapNextTx.size()); diff --git a/src/txmempool.h b/src/txmempool.h index 941644b2b21c1..1763930ba05b1 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -15,6 +15,7 @@ #include "indirectmap.h" #include "primitives/transaction.h" #include "sync.h" +#include "random.h" #undef foreach #include "boost/multi_index_container.hpp" diff --git a/src/wallet/test/crypto_tests.cpp b/src/wallet/test/crypto_tests.cpp index 05387f5f2b5e6..c5f55ef5f0dac 100644 --- a/src/wallet/test/crypto_tests.cpp +++ b/src/wallet/test/crypto_tests.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "random.h" +#include "test/test_random.h" #include "utilstrencodings.h" #include "test/test_bitcoin.h" #include "wallet/crypter.h" diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index a1f69dd94dd6c..687d84e77a46f 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1907,7 +1907,7 @@ static void ApproximateBestSubset(vector Date: Mon, 17 Oct 2016 13:24:37 +0200 Subject: [PATCH 1033/1802] Define start and end time for segwit deployment --- src/chainparams.cpp | 8 ++++---- src/consensus/params.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index e6be1b5d5b716..25ec94b75710a 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -91,10 +91,10 @@ class CMainParams : public CChainParams { consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 1462060800; // May 1st, 2016 consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 1493596800; // May 1st, 2017 - // Deployment of SegWit (BIP141 and BIP143) + // Deployment of SegWit (BIP141, BIP143, and BIP147) consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].bit = 1; - consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 0; - consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 0; // Never / undefined + consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 1479168000; // November 15th, 2016. + consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1510704000; // November 15th, 2017. /** * The message start string is designed to be unlikely to occur in normal data. @@ -186,7 +186,7 @@ class CTestNetParams : public CChainParams { consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 1456790400; // March 1st, 2016 consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 1493596800; // May 1st, 2017 - // Deployment of SegWit (BIP141 and BIP143) + // Deployment of SegWit (BIP141, BIP143, and BIP147) consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].bit = 1; consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 1462060800; // May 1st 2016 consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1493596800; // May 1st 2017 diff --git a/src/consensus/params.h b/src/consensus/params.h index 5b2f49184fc3f..0e73cace83171 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -16,7 +16,7 @@ enum DeploymentPos { DEPLOYMENT_TESTDUMMY, DEPLOYMENT_CSV, // Deployment of BIP68, BIP112, and BIP113. - DEPLOYMENT_SEGWIT, // Deployment of BIP141 and BIP143 + DEPLOYMENT_SEGWIT, // Deployment of BIP141, BIP143, and BIP147. // NOTE: Also add new deployments to VersionBitsDeploymentInfo in versionbits.cpp MAX_VERSION_BITS_DEPLOYMENTS }; From 02a337defdd854efc78ecba6d1fb19cb1c075f16 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 21 Jun 2016 13:08:29 -0700 Subject: [PATCH 1034/1802] Dont remove a "preferred" cmpctblock peer if they provide a block --- src/main.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index ad4c3fce6866c..e27fb1fae6a50 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -485,9 +485,13 @@ void MaybeSetPeerAsAnnouncingHeaderAndIDs(const CNodeState* nodestate, CNode* pf return; } if (nodestate->fProvidesHeaderAndIDs) { - BOOST_FOREACH(const NodeId nodeid, lNodesAnnouncingHeaderAndIDs) - if (nodeid == pfrom->GetId()) + for (std::list::iterator it = lNodesAnnouncingHeaderAndIDs.begin(); it != lNodesAnnouncingHeaderAndIDs.end(); it++) { + if (*it == pfrom->GetId()) { + lNodesAnnouncingHeaderAndIDs.erase(it); + lNodesAnnouncingHeaderAndIDs.push_back(pfrom->GetId()); return; + } + } bool fAnnounceUsingCMPCTBLOCK = false; uint64_t nCMPCTBLOCKVersion = (pfrom->GetLocalServices() & NODE_WITNESS) ? 2 : 1; if (lNodesAnnouncingHeaderAndIDs.size() >= 3) { @@ -5731,6 +5735,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, return true; } + if (!fAlreadyInFlight && mapBlocksInFlight.size() == 1 && pindex->pprev->IsValid(BLOCK_VALID_CHAIN)) { + // We seem to be rather well-synced, so it appears pfrom was the first to provide us + // with this block! Let's get them to announce using compact blocks in the future. + MaybeSetPeerAsAnnouncingHeaderAndIDs(nodestate, pfrom, connman); + } + BlockTransactionsRequest req; for (size_t i = 0; i < cmpctblock.BlockTxCount(); i++) { if (!partialBlock.IsTxAvailable(i)) From fe998e962dc015978f104b782afb7daec3c4d4df Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 21 Jun 2016 16:28:38 -0700 Subject: [PATCH 1035/1802] More agressively filter compact block requests Unit test adaptations by Pieter Wuille. --- qa/rpc-tests/p2p-compactblocks.py | 4 ++-- src/main.cpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/qa/rpc-tests/p2p-compactblocks.py b/qa/rpc-tests/p2p-compactblocks.py index 131654c333d4d..a24066b0773f2 100755 --- a/qa/rpc-tests/p2p-compactblocks.py +++ b/qa/rpc-tests/p2p-compactblocks.py @@ -591,7 +591,7 @@ def test_incorrect_blocktxn_response(self, node, test_node, version): def test_getblocktxn_handler(self, node, test_node, version): # bitcoind won't respond for blocks whose height is more than 15 blocks # deep. - MAX_GETBLOCKTXN_DEPTH = 15 + MAX_GETBLOCKTXN_DEPTH = 10 chain_height = node.getblockcount() current_height = chain_height while (current_height >= chain_height - MAX_GETBLOCKTXN_DEPTH): @@ -632,7 +632,7 @@ def test_getblocktxn_handler(self, node, test_node, version): def test_compactblocks_not_at_tip(self, node, test_node): # Test that requesting old compactblocks doesn't work. - MAX_CMPCTBLOCK_DEPTH = 11 + MAX_CMPCTBLOCK_DEPTH = 6 new_blocks = [] for i in range(MAX_CMPCTBLOCK_DEPTH): test_node.clear_block_announcement() diff --git a/src/main.cpp b/src/main.cpp index e27fb1fae6a50..0002a1c08ff3d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4878,7 +4878,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam // and we don't feel like constructing the object for them, so // instead we respond with the full, non-compact block. bool fPeerWantsWitness = State(pfrom->GetId())->fWantsCmpctWitness; - if (mi->second->nHeight >= chainActive.Height() - 10) { + if (CanDirectFetch(Params().GetConsensus()) && mi->second->nHeight >= chainActive.Height() - 5) { CBlockHeaderAndShortTxIDs cmpctblock(block, fPeerWantsWitness); pfrom->PushMessageWithFlag(fPeerWantsWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::CMPCTBLOCK, cmpctblock); } else @@ -5405,8 +5405,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, return true; } - if (it->second->nHeight < chainActive.Height() - 15) { - LogPrint("net", "Peer %d sent us a getblocktxn for a block > 15 deep", pfrom->id); + if (it->second->nHeight < chainActive.Height() - 10) { + LogPrint("net", "Peer %d sent us a getblocktxn for a block > 10 deep", pfrom->id); return true; } From b2e93a343ec2dc7d255b970e6ee45e9c390f7ed0 Mon Sep 17 00:00:00 2001 From: instagibbs Date: Wed, 22 Jun 2016 08:18:22 -0400 Subject: [PATCH 1036/1802] Add cmpctblock to debug help list --- src/init.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/init.cpp b/src/init.cpp index eefef7ba0b253..685188c458462 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -423,7 +423,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-limitdescendantsize=", strprintf("Do not accept transactions if any ancestor would have more than kilobytes of in-mempool descendants (default: %u).", DEFAULT_DESCENDANT_SIZE_LIMIT)); strUsage += HelpMessageOpt("-bip9params=deployment:start:end", "Use given start/end times for specified BIP9 deployment (regtest-only)"); } - string debugCategories = "addrman, alert, bench, coindb, db, http, libevent, lock, mempool, mempoolrej, net, proxy, prune, rand, reindex, rpc, selectcoins, tor, zmq"; // Don't translate these and qt below + string debugCategories = "addrman, alert, bench, cmpctblock, coindb, db, http, libevent, lock, mempool, mempoolrej, net, proxy, prune, rand, reindex, rpc, selectcoins, tor, zmq"; // Don't translate these and qt below if (mode == HMM_BITCOIN_QT) debugCategories += ", qt"; strUsage += HelpMessageOpt("-debug=", strprintf(_("Output debugging information (default: %u, supplying is optional)"), 0) + ". " + From 3ac6de0a045cc9b2047ceb19af970e7ffbf905fa Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 31 Aug 2016 17:35:59 +0200 Subject: [PATCH 1037/1802] Align constant names for maximum compact block / blocktxn depth --- qa/rpc-tests/p2p-compactblocks.py | 4 ++-- src/main.cpp | 6 +++--- src/main.h | 5 +++++ 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/qa/rpc-tests/p2p-compactblocks.py b/qa/rpc-tests/p2p-compactblocks.py index a24066b0773f2..6b5d477131077 100755 --- a/qa/rpc-tests/p2p-compactblocks.py +++ b/qa/rpc-tests/p2p-compactblocks.py @@ -632,9 +632,9 @@ def test_getblocktxn_handler(self, node, test_node, version): def test_compactblocks_not_at_tip(self, node, test_node): # Test that requesting old compactblocks doesn't work. - MAX_CMPCTBLOCK_DEPTH = 6 + MAX_CMPCTBLOCK_DEPTH = 5 new_blocks = [] - for i in range(MAX_CMPCTBLOCK_DEPTH): + for i in range(MAX_CMPCTBLOCK_DEPTH + 1): test_node.clear_block_announcement() new_blocks.append(node.generate(1)[0]) wait_until(test_node.received_block_announcement, timeout=30) diff --git a/src/main.cpp b/src/main.cpp index 0002a1c08ff3d..7e27428513830 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4878,7 +4878,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam // and we don't feel like constructing the object for them, so // instead we respond with the full, non-compact block. bool fPeerWantsWitness = State(pfrom->GetId())->fWantsCmpctWitness; - if (CanDirectFetch(Params().GetConsensus()) && mi->second->nHeight >= chainActive.Height() - 5) { + if (CanDirectFetch(consensusParams) && mi->second->nHeight >= chainActive.Height() - MAX_CMPCTBLOCK_DEPTH) { CBlockHeaderAndShortTxIDs cmpctblock(block, fPeerWantsWitness); pfrom->PushMessageWithFlag(fPeerWantsWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::CMPCTBLOCK, cmpctblock); } else @@ -5405,8 +5405,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, return true; } - if (it->second->nHeight < chainActive.Height() - 10) { - LogPrint("net", "Peer %d sent us a getblocktxn for a block > 10 deep", pfrom->id); + if (it->second->nHeight < chainActive.Height() - MAX_BLOCKTXN_DEPTH) { + LogPrint("net", "Peer %d sent us a getblocktxn for a block > %i deep", pfrom->id, MAX_BLOCKTXN_DEPTH); return true; } diff --git a/src/main.h b/src/main.h index 2646d8f86b0a3..db58b274872b1 100644 --- a/src/main.h +++ b/src/main.h @@ -90,6 +90,11 @@ static const unsigned int BLOCK_STALLING_TIMEOUT = 2; /** Number of headers sent in one getheaders result. We rely on the assumption that if a peer sends * less than this number, we reached its tip. Changing this value is a protocol upgrade. */ static const unsigned int MAX_HEADERS_RESULTS = 2000; +/** Maximum depth of blocks we're willing to serve as compact blocks to peers + * when requested. For older blocks, a regular BLOCK response will be sent. */ +static const int MAX_CMPCTBLOCK_DEPTH = 5; +/** Maximum depth of blocks we're willing to respond to GETBLOCKTXN requests for. */ +static const int MAX_BLOCKTXN_DEPTH = 10; /** Size of the "block download window": how far ahead of our current height do we fetch? * Larger windows tolerate larger download speed differences between peer, but increase the potential * degree of disordering of blocks on disk (which make reindexing and in the future perhaps pruning From 0941f556b7f228517fcb35f8b19926dfd62f481c Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 17 Oct 2016 17:09:38 +0200 Subject: [PATCH 1038/1802] Update implemented bips for 0.13.1 --- doc/bips.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/bips.md b/doc/bips.md index 040439fbcb195..4f4161008916e 100644 --- a/doc/bips.md +++ b/doc/bips.md @@ -26,9 +26,9 @@ BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.13.0**): * [`BIP 125`](https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki): Opt-in full replace-by-fee signaling honoured in mempool and mining as of **v0.12.0** ([PR 6871](https://github.com/bitcoin/bitcoin/pull/6871)). * [`BIP 130`](https://github.com/bitcoin/bips/blob/master/bip-0130.mediawiki): direct headers announcement is negotiated with peer versions `>=70012` as of **v0.12.0** ([PR 6494](https://github.com/bitcoin/bitcoin/pull/6494)). * [`BIP 133`](https://github.com/bitcoin/bips/blob/master/bip-0133.mediawiki): feefilter messages are respected and sent for peer versions `>=70013` as of **v0.13.0** ([PR 7542](https://github.com/bitcoin/bitcoin/pull/7542)). -* [`BIP 141`](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki): Segregated Witness (Consensus Layer) as of **v0.13.0** ([PR 8149](https://github.com/bitcoin/bitcoin/pull/8149)). -* [`BIP 143`](https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki): Transaction Signature Verification for Version 0 Witness Program as of **v0.13.0** ([PR 8149](https://github.com/bitcoin/bitcoin/pull/8149)). +* [`BIP 141`](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki): Segregated Witness (Consensus Layer) as of **v0.13.0** ([PR 8149](https://github.com/bitcoin/bitcoin/pull/8149)), and defined for mainnet as of **v0.13.1** ([PR 8937](https://github.com/bitcoin/bitcoin/pull/8937)). +* [`BIP 143`](https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki): Transaction Signature Verification for Version 0 Witness Program as of **v0.13.0** ([PR 8149](https://github.com/bitcoin/bitcoin/pull/8149)) and defined for mainnet as of **v0.13.1** ([PR 8937](https://github.com/bitcoin/bitcoin/pull/8937)). * [`BIP 144`](https://github.com/bitcoin/bips/blob/master/bip-0144.mediawiki): Segregated Witness as of **0.13.0** ([PR 8149](https://github.com/bitcoin/bitcoin/pull/8149)). * [`BIP 145`](https://github.com/bitcoin/bips/blob/master/bip-0145.mediawiki): getblocktemplate updates for Segregated Witness as of **v0.13.0** ([PR 8149](https://github.com/bitcoin/bitcoin/pull/8149)). -* [`BIP 147`](https://github.com/bitcoin/bips/blob/master/bip-0147.mediawiki): NULLDUMMY softfork as of **v0.13.1** ([PR 8636](https://github.com/bitcoin/bitcoin/pull/8636)). +* [`BIP 147`](https://github.com/bitcoin/bips/blob/master/bip-0147.mediawiki): NULLDUMMY softfork as of **v0.13.1** ([PR 8636](https://github.com/bitcoin/bitcoin/pull/8636) and [PR 8937](https://github.com/bitcoin/bitcoin/pull/8937)). * [`BIP 152`](https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki): Compact block transfer and related optimizations are used as of **v0.13.0** ([PR 8068](https://github.com/bitcoin/bitcoin/pull/8068)). From 164196b7c8aecb72dd20c8681bb24b81b18aecaa Mon Sep 17 00:00:00 2001 From: matthias Date: Mon, 17 Oct 2016 17:45:36 +0200 Subject: [PATCH 1039/1802] Simple Update to File 'bitcoin-qt.desktop' --- contrib/debian/bitcoin-qt.desktop | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/contrib/debian/bitcoin-qt.desktop b/contrib/debian/bitcoin-qt.desktop index 61e1aca6ad0ce..593d7584ab06d 100644 --- a/contrib/debian/bitcoin-qt.desktop +++ b/contrib/debian/bitcoin-qt.desktop @@ -1,7 +1,8 @@ [Desktop Entry] Encoding=UTF-8 -Name=Bitcoin -Comment=Bitcoin P2P Cryptocurrency +Name=Bitcoin Core +Comment=Connect to the Bitcoin P2P Network +Comment[de]=Verbinde mit dem Bitcoin peer-to-peer Netzwerk Comment[fr]=Bitcoin, monnaie virtuelle cryptographique pair à pair Comment[tr]=Bitcoin, eşten eşe kriptografik sanal para birimi Exec=bitcoin-qt %u From 504c72ad346a1b619f1fc58d0edce91ec955a67d Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 17 Oct 2016 11:25:25 -0400 Subject: [PATCH 1040/1802] Comment that most dnsseeds only support some service bits combos --- src/chainparams.cpp | 5 +++-- src/net.cpp | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 25ec94b75710a..8670110b9a114 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -113,12 +113,13 @@ class CMainParams : public CChainParams { assert(consensus.hashGenesisBlock == uint256S("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f")); assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); - vSeeds.push_back(CDNSSeedData("bitcoin.sipa.be", "seed.bitcoin.sipa.be", true)); // Pieter Wuille + // Note that of those with the service bits flag, most only support a subset of possible options + vSeeds.push_back(CDNSSeedData("bitcoin.sipa.be", "seed.bitcoin.sipa.be", true)); // Pieter Wuille, only supports x1, x5, x9, and xd vSeeds.push_back(CDNSSeedData("bluematt.me", "dnsseed.bluematt.me")); // Matt Corallo vSeeds.push_back(CDNSSeedData("dashjr.org", "dnsseed.bitcoin.dashjr.org")); // Luke Dashjr vSeeds.push_back(CDNSSeedData("bitcoinstats.com", "seed.bitcoinstats.com")); // Christian Decker vSeeds.push_back(CDNSSeedData("xf2.org", "bitseed.xf2.org")); // Jeff Garzik - vSeeds.push_back(CDNSSeedData("bitcoin.jonasschnelli.ch", "seed.bitcoin.jonasschnelli.ch", true)); // Jonas Schnelli + vSeeds.push_back(CDNSSeedData("bitcoin.jonasschnelli.ch", "seed.bitcoin.jonasschnelli.ch", true)); // Jonas Schnelli, only supports x1, x5, x9, and xd base58Prefixes[PUBKEY_ADDRESS] = std::vector(1,0); base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,5); diff --git a/src/net.cpp b/src/net.cpp index 19dd040997ad1..5f9942c9dc0ef 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1454,6 +1454,7 @@ static std::string GetDNSHost(const CDNSSeedData& data, ServiceFlags* requiredSe return data.host; } + // See chainparams.cpp, most dnsseeds only support one or two possible servicebits hostnames return strprintf("x%x.%s", *requiredServiceBits, data.host); } From ffb4713920205db39bfd219b6162986a52ddf32b Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 17 Oct 2016 11:25:52 -0400 Subject: [PATCH 1041/1802] Add x9 service bit support to dnsseed.bluematt.me --- src/chainparams.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 8670110b9a114..fb7097cd4d59a 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -115,7 +115,7 @@ class CMainParams : public CChainParams { // Note that of those with the service bits flag, most only support a subset of possible options vSeeds.push_back(CDNSSeedData("bitcoin.sipa.be", "seed.bitcoin.sipa.be", true)); // Pieter Wuille, only supports x1, x5, x9, and xd - vSeeds.push_back(CDNSSeedData("bluematt.me", "dnsseed.bluematt.me")); // Matt Corallo + vSeeds.push_back(CDNSSeedData("bluematt.me", "dnsseed.bluematt.me", true)); // Matt Corallo, only supports x9 vSeeds.push_back(CDNSSeedData("dashjr.org", "dnsseed.bitcoin.dashjr.org")); // Luke Dashjr vSeeds.push_back(CDNSSeedData("bitcoinstats.com", "seed.bitcoinstats.com")); // Christian Decker vSeeds.push_back(CDNSSeedData("xf2.org", "bitseed.xf2.org")); // Jeff Garzik From 2449e12681ab549695f143d9b3ad2c24be03a78d Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Mon, 17 Oct 2016 13:27:23 -0400 Subject: [PATCH 1042/1802] My DNS seed supports filtering Currently supports filtering by any combination of the 4 least significant bits. --- src/chainparams.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index fb7097cd4d59a..7279570855e44 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -117,7 +117,7 @@ class CMainParams : public CChainParams { vSeeds.push_back(CDNSSeedData("bitcoin.sipa.be", "seed.bitcoin.sipa.be", true)); // Pieter Wuille, only supports x1, x5, x9, and xd vSeeds.push_back(CDNSSeedData("bluematt.me", "dnsseed.bluematt.me", true)); // Matt Corallo, only supports x9 vSeeds.push_back(CDNSSeedData("dashjr.org", "dnsseed.bitcoin.dashjr.org")); // Luke Dashjr - vSeeds.push_back(CDNSSeedData("bitcoinstats.com", "seed.bitcoinstats.com")); // Christian Decker + vSeeds.push_back(CDNSSeedData("bitcoinstats.com", "seed.bitcoinstats.com", true)); // Christian Decker, supports x1 - xf vSeeds.push_back(CDNSSeedData("xf2.org", "bitseed.xf2.org")); // Jeff Garzik vSeeds.push_back(CDNSSeedData("bitcoin.jonasschnelli.ch", "seed.bitcoin.jonasschnelli.ch", true)); // Jonas Schnelli, only supports x1, x5, x9, and xd From 1ab21cf344ed0547de5ae679b7e479cb4b1a923b Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 17 Oct 2016 16:29:03 -0400 Subject: [PATCH 1043/1802] Remove bogus assert on number of oubound connections. This value can be significantly higher if the users uses addnode --- src/net.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/net.cpp b/src/net.cpp index 5f9942c9dc0ef..cdd3076a2fc79 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1622,7 +1622,6 @@ void CConnman::ThreadOpenConnections() } } } - assert(nOutbound <= (nMaxOutbound + nMaxFeeler)); // Feeler Connections // From 3f7581d9a4f9cb7dc5499fc85528e959da6b0efc Mon Sep 17 00:00:00 2001 From: Micha Date: Tue, 18 Oct 2016 01:07:53 +0300 Subject: [PATCH 1044/1802] [TRIVIAL] reorder Windows gitian build order to match Linux The consistency is helpful for gauging Gitian build progress. Right now it's necessary to remember which platform builds in which order, which can be confusing if you're attempting to get a quick idea of how far along your builds are. --- contrib/gitian-descriptors/gitian-win.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml index 32b57b3160bd3..fe01b5b95726a 100644 --- a/contrib/gitian-descriptors/gitian-win.yml +++ b/contrib/gitian-descriptors/gitian-win.yml @@ -27,7 +27,7 @@ remotes: files: [] script: | WRAP_DIR=$HOME/wrapped - HOSTS="x86_64-w64-mingw32 i686-w64-mingw32" + HOSTS="i686-w64-mingw32 x86_64-w64-mingw32" CONFIGFLAGS="--enable-reduce-exports --disable-bench --disable-gui-tests" FAKETIME_HOST_PROGS="g++ ar ranlib nm windres strip objcopy" FAKETIME_PROGS="date makensis zip" From 9583477288072e203541b747fcffe8d50cfefb8d Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Mon, 17 Oct 2016 23:08:52 +0000 Subject: [PATCH 1045/1802] Be more aggressive in connecting to peers with relevant services. Only allow skipping relevant services until there are four outbound connections up. This avoids quickly filling up with peers lacking the relevant services when addrman has few or none of them. --- src/net.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 5f9942c9dc0ef..de8f8184a28c9 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1675,8 +1675,8 @@ void CConnman::ThreadOpenConnections() if (nANow - addr.nLastTry < 600 && nTries < 30) continue; - // only consider nodes missing relevant services after 40 failed attempts - if ((addr.nServices & nRelevantServices) != nRelevantServices && nTries < 40) + // only consider nodes missing relevant services after 40 failed attempts and only if less than half the outbound are up. + if ((addr.nServices & nRelevantServices) != nRelevantServices && (nTries < 40 || nOutbound >= (nMaxOutbound >> 1))) continue; // do not allow non-default ports, unless after 50 invalid addresses selected already From a1919adab0e72e8b465f723099788d9cc00363da Mon Sep 17 00:00:00 2001 From: R E Broadley Date: Mon, 12 Sep 2016 15:54:05 +0700 Subject: [PATCH 1046/1802] Report NodeId in misbehaving debug --- src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index f3b0e3c22eb55..1e59f80e13f59 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1846,10 +1846,10 @@ void Misbehaving(NodeId pnode, int howmuch) int banscore = GetArg("-banscore", DEFAULT_BANSCORE_THRESHOLD); if (state->nMisbehavior >= banscore && state->nMisbehavior - howmuch < banscore) { - LogPrintf("%s: %s (%d -> %d) BAN THRESHOLD EXCEEDED\n", __func__, state->name, state->nMisbehavior-howmuch, state->nMisbehavior); + LogPrintf("%s: %s peer=%d (%d -> %d) BAN THRESHOLD EXCEEDED\n", __func__, state->name, pnode, state->nMisbehavior-howmuch, state->nMisbehavior); state->fShouldBan = true; } else - LogPrintf("%s: %s (%d -> %d)\n", __func__, state->name, state->nMisbehavior-howmuch, state->nMisbehavior); + LogPrintf("%s: %s peer=%d (%d -> %d)\n", __func__, state->name, pnode, state->nMisbehavior-howmuch, state->nMisbehavior); } void static InvalidChainFound(CBlockIndex* pindexNew) From b26a7b5377f400760f49ba3aed468469ef27786e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Tim=C3=B3n?= Date: Fri, 14 Oct 2016 00:57:18 +0200 Subject: [PATCH 1047/1802] RPC: Chainparams: Remove Chainparams::fTestnetToBeDeprecatedFieldRPC --- doc/release-notes.md | 2 ++ src/chainparams.cpp | 3 --- src/chainparams.h | 3 --- src/rpc/mining.cpp | 2 -- src/rpc/misc.cpp | 2 +- 5 files changed, 3 insertions(+), 9 deletions(-) diff --git a/doc/release-notes.md b/doc/release-notes.md index 58994a6839415..0463cb8a613e2 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -65,6 +65,8 @@ contain invalid parameters. The first boolean argument to `getaddednodeinfo` has been removed. This is an incompatible change. +Call "getmininginfo" loses the "testnet" field in favor of the more generic "chain" (which has been present for years). + ### Configuration and command-line options ### Block and transaction handling diff --git a/src/chainparams.cpp b/src/chainparams.cpp index e6be1b5d5b716..5509f11b67e14 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -132,7 +132,6 @@ class CMainParams : public CChainParams { fDefaultConsistencyChecks = false; fRequireStandard = true; fMineBlocksOnDemand = false; - fTestnetToBeDeprecatedFieldRPC = false; checkpointData = (CCheckpointData) { boost::assign::map_list_of @@ -223,7 +222,6 @@ class CTestNetParams : public CChainParams { fDefaultConsistencyChecks = false; fRequireStandard = false; fMineBlocksOnDemand = false; - fTestnetToBeDeprecatedFieldRPC = true; checkpointData = (CCheckpointData) { boost::assign::map_list_of @@ -285,7 +283,6 @@ class CRegTestParams : public CChainParams { fDefaultConsistencyChecks = true; fRequireStandard = false; fMineBlocksOnDemand = true; - fTestnetToBeDeprecatedFieldRPC = false; checkpointData = (CCheckpointData){ boost::assign::map_list_of diff --git a/src/chainparams.h b/src/chainparams.h index 0c3820b7c6e72..633fbd51203f1 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -67,8 +67,6 @@ class CChainParams uint64_t PruneAfterHeight() const { return nPruneAfterHeight; } /** Make miner stop after a block is found. In RPC, don't return until nGenProcLimit blocks are generated */ bool MineBlocksOnDemand() const { return fMineBlocksOnDemand; } - /** In the future use NetworkIDString() for RPC fields */ - bool TestnetToBeDeprecatedFieldRPC() const { return fTestnetToBeDeprecatedFieldRPC; } /** Return the BIP70 network string (main, test or regtest) */ std::string NetworkIDString() const { return strNetworkID; } const std::vector& DNSSeeds() const { return vSeeds; } @@ -91,7 +89,6 @@ class CChainParams bool fDefaultConsistencyChecks; bool fRequireStandard; bool fMineBlocksOnDemand; - bool fTestnetToBeDeprecatedFieldRPC; CCheckpointData checkpointData; }; diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 6b13aa5bab02a..fa64ce8fad4b2 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -230,7 +230,6 @@ UniValue getmininginfo(const UniValue& params, bool fHelp) " \"errors\": \"...\" (string) Current errors\n" " \"networkhashps\": nnn, (numeric) The network hashes per second\n" " \"pooledtx\": n (numeric) The size of the mem pool\n" - " \"testnet\": true|false (boolean) If using testnet or not\n" " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n" "}\n" "\nExamples:\n" @@ -250,7 +249,6 @@ UniValue getmininginfo(const UniValue& params, bool fHelp) obj.push_back(Pair("errors", GetWarnings("statusbar"))); obj.push_back(Pair("networkhashps", getnetworkhashps(params, false))); obj.push_back(Pair("pooledtx", (uint64_t)mempool.size())); - obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC())); obj.push_back(Pair("chain", Params().NetworkIDString())); return obj; } diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index f0b7e0a07cffa..6bbb3925ddece 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -93,7 +93,7 @@ UniValue getinfo(const UniValue& params, bool fHelp) obj.push_back(Pair("connections", (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL))); obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string()))); obj.push_back(Pair("difficulty", (double)GetDifficulty())); - obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC())); + obj.push_back(Pair("testnet", Params().NetworkIDString() == CBaseChainParams::TESTNET)); #ifdef ENABLE_WALLET if (pwalletMain) { obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime())); From fab5ca8fee25839b76084cabf70f3f92395112c2 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Tue, 18 Oct 2016 15:09:32 +0200 Subject: [PATCH 1048/1802] contrib: Add README for pgp keys --- contrib/gitian-keys/README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 contrib/gitian-keys/README.md diff --git a/contrib/gitian-keys/README.md b/contrib/gitian-keys/README.md new file mode 100644 index 0000000000000..439910330d14a --- /dev/null +++ b/contrib/gitian-keys/README.md @@ -0,0 +1,16 @@ +PGP keys +======== + +This folder contains the public keys of developers and active contributors. + +The keys are mainly used to sign git commits or the build results of gitian +builds. + +You can import the keys into gpg as follows. Also, make sure to fetch the +latest version from the key server to see if any key was revoked in the +meantime. + +```sh +gpg --import ./*.pgp +gpg --refresh-keys +``` From 83c0f7fea8f40292700742f958d0bcab81560b85 Mon Sep 17 00:00:00 2001 From: mruddy Date: Tue, 18 Oct 2016 09:58:20 -0400 Subject: [PATCH 1049/1802] trivial: update 0.13.0 release note info on linux arm builds --- doc/release-notes/release-notes-0.13.0.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/doc/release-notes/release-notes-0.13.0.md b/doc/release-notes/release-notes-0.13.0.md index f9bf3d75de09d..4c3cb97df34cf 100644 --- a/doc/release-notes/release-notes-0.13.0.md +++ b/doc/release-notes/release-notes-0.13.0.md @@ -95,14 +95,19 @@ executables. The following extra files can be found in the download directory or torrent: -- `bitcoin-${VERSION}-arm-linux-gnueabihf.tar.gz`: Linux binaries for the most - common 32-bit ARM architecture. -- `bitcoin-${VERSION}-aarch64-linux-gnu.tar.gz`: Linux binaries for the most - common 64-bit ARM architecture. +- `bitcoin-${VERSION}-arm-linux-gnueabihf.tar.gz`: Linux binaries targeting + the 32-bit ARMv7-A architecture. +- `bitcoin-${VERSION}-aarch64-linux-gnu.tar.gz`: Linux binaries targeting + the 64-bit ARMv8-A architecture. ARM builds are still experimental. If you have problems on a certain device or Linux distribution combination please report them on the bug tracker, it may be -possible to resolve them. +possible to resolve them. Note that the device you use must be (backward) +compatible with the architecture targeted by the binary that you use. +For example, a Raspberry Pi 2 Model B or Raspberry Pi 3 Model B (in its 32-bit +execution state) device, can run the 32-bit ARMv7-A targeted binary. However, +no model of Raspberry Pi 1 device can run either binary because they are all +ARMv6 architecture devices that are not compatible with ARMv7-A or ARMv8-A. Note that Android is not considered ARM Linux in this context. The executables are not expected to work out of the box on Android. From 72ca7d924e3896838d2709d95f4c8cca670af8cf Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 30 Sep 2016 17:12:00 -0400 Subject: [PATCH 1050/1802] Don't hold cs_main when calling ProcessNewBlock from a cmpctblock --- src/main.cpp | 47 ++++++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 9f3116e358c24..4199cb30e8397 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5787,29 +5787,34 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, BlockTransactions resp; vRecv >> resp; - LOCK(cs_main); + CBlock block; + bool fBlockRead = false; + { + LOCK(cs_main); - map::iterator> >::iterator it = mapBlocksInFlight.find(resp.blockhash); - if (it == mapBlocksInFlight.end() || !it->second.second->partialBlock || - it->second.first != pfrom->GetId()) { - LogPrint("net", "Peer %d sent us block transactions for block we weren't expecting\n", pfrom->id); - return true; - } + map::iterator> >::iterator it = mapBlocksInFlight.find(resp.blockhash); + if (it == mapBlocksInFlight.end() || !it->second.second->partialBlock || + it->second.first != pfrom->GetId()) { + LogPrint("net", "Peer %d sent us block transactions for block we weren't expecting\n", pfrom->id); + return true; + } - PartiallyDownloadedBlock& partialBlock = *it->second.second->partialBlock; - CBlock block; - ReadStatus status = partialBlock.FillBlock(block, resp.txn); - if (status == READ_STATUS_INVALID) { - MarkBlockAsReceived(resp.blockhash); // Reset in-flight state in case of whitelist - Misbehaving(pfrom->GetId(), 100); - LogPrintf("Peer %d sent us invalid compact block/non-matching block transactions\n", pfrom->id); - return true; - } else if (status == READ_STATUS_FAILED) { - // Might have collided, fall back to getdata now :( - std::vector invs; - invs.push_back(CInv(MSG_BLOCK | GetFetchFlags(pfrom, chainActive.Tip(), chainparams.GetConsensus()), resp.blockhash)); - pfrom->PushMessage(NetMsgType::GETDATA, invs); - } else { + PartiallyDownloadedBlock& partialBlock = *it->second.second->partialBlock; + ReadStatus status = partialBlock.FillBlock(block, resp.txn); + if (status == READ_STATUS_INVALID) { + MarkBlockAsReceived(resp.blockhash); // Reset in-flight state in case of whitelist + Misbehaving(pfrom->GetId(), 100); + LogPrintf("Peer %d sent us invalid compact block/non-matching block transactions\n", pfrom->id); + return true; + } else if (status == READ_STATUS_FAILED) { + // Might have collided, fall back to getdata now :( + std::vector invs; + invs.push_back(CInv(MSG_BLOCK | GetFetchFlags(pfrom, chainActive.Tip(), chainparams.GetConsensus()), resp.blockhash)); + pfrom->PushMessage(NetMsgType::GETDATA, invs); + } else + fBlockRead = true; + } // Don't hold cs_main when we call into ProcessNewBlock + if (fBlockRead) { CValidationState state; ProcessNewBlock(state, chainparams, pfrom, &block, false, NULL, &connman); int nDoS; From b55d823369b163edfe23f92983b2287441b98fa2 Mon Sep 17 00:00:00 2001 From: anduck Date: Tue, 18 Oct 2016 22:43:03 +0300 Subject: [PATCH 1051/1802] Explicitly state that PPA is for Ubuntu only --- doc/build-unix.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/build-unix.md b/doc/build-unix.md index 5202072f8b8e1..d2fe2f9985b4d 100644 --- a/doc/build-unix.md +++ b/doc/build-unix.md @@ -79,7 +79,9 @@ install necessary parts of boost: sudo apt-get install libboost-all-dev -BerkeleyDB is required for the wallet. db4.8 packages are available [here](https://launchpad.net/~bitcoin/+archive/bitcoin). +BerkeleyDB is required for the wallet. + +**For Ubuntu only:** db4.8 packages are available [here](https://launchpad.net/~bitcoin/+archive/bitcoin). You can add the repository and install using the following commands: sudo add-apt-repository ppa:bitcoin/bitcoin From 18dacf9bd25154e184b097ee4e8f786d9be25637 Mon Sep 17 00:00:00 2001 From: Russell Yanofsky Date: Sun, 2 Oct 2016 17:38:48 -0400 Subject: [PATCH 1052/1802] Add microbenchmarks to profile more code paths. The new benchmarks exercise script validation, CCoinsDBView caching, mempool eviction, and wallet coin selection code. All of the benchmarks added here are extremely simple and don't necessarily mirror common real world conditions or interesting performance edge cases. Details about how specific benchmarks can be improved are noted in comments. Github-Issue: #7883 --- src/Makefile.bench.include | 6 +- src/bench/ccoins_caching.cpp | 87 +++++++++++++++++++++++++ src/bench/coin_selection.cpp | 62 ++++++++++++++++++ src/bench/mempool_eviction.cpp | 115 +++++++++++++++++++++++++++++++++ src/bench/verify_script.cpp | 103 +++++++++++++++++++++++++++++ 5 files changed, 372 insertions(+), 1 deletion(-) create mode 100644 src/bench/ccoins_caching.cpp create mode 100644 src/bench/coin_selection.cpp create mode 100644 src/bench/mempool_eviction.cpp create mode 100644 src/bench/verify_script.cpp diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include index 8c024a8c4ad81..c83432e91a600 100644 --- a/src/Makefile.bench.include +++ b/src/Makefile.bench.include @@ -14,6 +14,9 @@ bench_bench_bitcoin_SOURCES = \ bench/Examples.cpp \ bench/rollingbloom.cpp \ bench/crypto_hash.cpp \ + bench/ccoins_caching.cpp \ + bench/mempool_eviction.cpp \ + bench/verify_script.cpp \ bench/base58.cpp bench_bench_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CLFAGS) $(EVENT_PTHREADS_CFLAGS) -I$(builddir)/bench/ @@ -34,7 +37,8 @@ bench_bench_bitcoin_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS) endif if ENABLE_WALLET -bench_bench_bitcoin_LDADD += $(LIBBITCOIN_WALLET) +bench_bench_bitcoin_SOURCES += bench/coin_selection.cpp +bench_bench_bitcoin_LDADD += $(LIBBITCOIN_WALLET) $(LIBBITCOIN_CRYPTO) endif bench_bench_bitcoin_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) diff --git a/src/bench/ccoins_caching.cpp b/src/bench/ccoins_caching.cpp new file mode 100644 index 0000000000000..1e8e3d462fc15 --- /dev/null +++ b/src/bench/ccoins_caching.cpp @@ -0,0 +1,87 @@ +// Copyright (c) 2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "bench.h" +#include "coins.h" +#include "policy/policy.h" +#include "wallet/crypter.h" + +#include + +// FIXME: Dedup with SetupDummyInputs in test/transaction_tests.cpp. +// +// Helper: create two dummy transactions, each with +// two outputs. The first has 11 and 50 CENT outputs +// paid to a TX_PUBKEY, the second 21 and 22 CENT outputs +// paid to a TX_PUBKEYHASH. +// +static std::vector +SetupDummyInputs(CBasicKeyStore& keystoreRet, CCoinsViewCache& coinsRet) +{ + std::vector dummyTransactions; + dummyTransactions.resize(2); + + // Add some keys to the keystore: + CKey key[4]; + for (int i = 0; i < 4; i++) { + key[i].MakeNewKey(i % 2); + keystoreRet.AddKey(key[i]); + } + + // Create some dummy input transactions + dummyTransactions[0].vout.resize(2); + dummyTransactions[0].vout[0].nValue = 11 * CENT; + dummyTransactions[0].vout[0].scriptPubKey << ToByteVector(key[0].GetPubKey()) << OP_CHECKSIG; + dummyTransactions[0].vout[1].nValue = 50 * CENT; + dummyTransactions[0].vout[1].scriptPubKey << ToByteVector(key[1].GetPubKey()) << OP_CHECKSIG; + coinsRet.ModifyCoins(dummyTransactions[0].GetHash())->FromTx(dummyTransactions[0], 0); + + dummyTransactions[1].vout.resize(2); + dummyTransactions[1].vout[0].nValue = 21 * CENT; + dummyTransactions[1].vout[0].scriptPubKey = GetScriptForDestination(key[2].GetPubKey().GetID()); + dummyTransactions[1].vout[1].nValue = 22 * CENT; + dummyTransactions[1].vout[1].scriptPubKey = GetScriptForDestination(key[3].GetPubKey().GetID()); + coinsRet.ModifyCoins(dummyTransactions[1].GetHash())->FromTx(dummyTransactions[1], 0); + + return dummyTransactions; +} + +// Microbenchmark for simple accesses to a CCoinsViewCache database. Note from +// laanwj, "replicating the actual usage patterns of the client is hard though, +// many times micro-benchmarks of the database showed completely different +// characteristics than e.g. reindex timings. But that's not a requirement of +// every benchmark." +// (https://github.com/bitcoin/bitcoin/issues/7883#issuecomment-224807484) +static void CCoinsCaching(benchmark::State& state) +{ + CBasicKeyStore keystore; + CCoinsView coinsDummy; + CCoinsViewCache coins(&coinsDummy); + std::vector dummyTransactions = SetupDummyInputs(keystore, coins); + + CMutableTransaction t1; + t1.vin.resize(3); + t1.vin[0].prevout.hash = dummyTransactions[0].GetHash(); + t1.vin[0].prevout.n = 1; + t1.vin[0].scriptSig << std::vector(65, 0); + t1.vin[1].prevout.hash = dummyTransactions[1].GetHash(); + t1.vin[1].prevout.n = 0; + t1.vin[1].scriptSig << std::vector(65, 0) << std::vector(33, 4); + t1.vin[2].prevout.hash = dummyTransactions[1].GetHash(); + t1.vin[2].prevout.n = 1; + t1.vin[2].scriptSig << std::vector(65, 0) << std::vector(33, 4); + t1.vout.resize(2); + t1.vout[0].nValue = 90 * CENT; + t1.vout[0].scriptPubKey << OP_1; + + // Benchmark. + while (state.KeepRunning()) { + bool success = AreInputsStandard(t1, coins); + assert(success); + CAmount value = coins.GetValueIn(t1); + assert(value == (50 + 21 + 22) * CENT); + } +} + +BENCHMARK(CCoinsCaching); diff --git a/src/bench/coin_selection.cpp b/src/bench/coin_selection.cpp new file mode 100644 index 0000000000000..7091ee3e11435 --- /dev/null +++ b/src/bench/coin_selection.cpp @@ -0,0 +1,62 @@ +// Copyright (c) 2012-2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "bench.h" +#include "wallet/wallet.h" + +#include +#include + +using namespace std; + +static void addCoin(const CAmount& nValue, const CWallet& wallet, vector& vCoins) +{ + int nInput = 0; + + static int nextLockTime = 0; + CMutableTransaction tx; + tx.nLockTime = nextLockTime++; // so all transactions get different hashes + tx.vout.resize(nInput + 1); + tx.vout[nInput].nValue = nValue; + CWalletTx* wtx = new CWalletTx(&wallet, tx); + + int nAge = 6 * 24; + COutput output(wtx, nInput, nAge, true, true); + vCoins.push_back(output); +} + +// Simple benchmark for wallet coin selection. Note that it maybe be necessary +// to build up more complicated scenarios in order to get meaningful +// measurements of performance. From laanwj, "Wallet coin selection is probably +// the hardest, as you need a wider selection of scenarios, just testing the +// same one over and over isn't too useful. Generating random isn't useful +// either for measurements." +// (https://github.com/bitcoin/bitcoin/issues/7883#issuecomment-224807484) +static void CoinSelection(benchmark::State& state) +{ + const CWallet wallet; + vector vCoins; + LOCK(wallet.cs_wallet); + + while (state.KeepRunning()) { + // Empty wallet. + BOOST_FOREACH (COutput output, vCoins) + delete output.tx; + vCoins.clear(); + + // Add coins. + for (int i = 0; i < 1000; i++) + addCoin(1000 * COIN, wallet, vCoins); + addCoin(3 * COIN, wallet, vCoins); + + set > setCoinsRet; + CAmount nValueRet; + bool success = wallet.SelectCoinsMinConf(1003 * COIN, 1, 6, vCoins, setCoinsRet, nValueRet); + assert(success); + assert(nValueRet == 1003 * COIN); + assert(setCoinsRet.size() == 2); + } +} + +BENCHMARK(CoinSelection); diff --git a/src/bench/mempool_eviction.cpp b/src/bench/mempool_eviction.cpp new file mode 100644 index 0000000000000..0ae69c75fcaeb --- /dev/null +++ b/src/bench/mempool_eviction.cpp @@ -0,0 +1,115 @@ +// Copyright (c) 2011-2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "bench.h" +#include "policy/policy.h" +#include "txmempool.h" + +#include +#include + +static void AddTx(const CTransaction& tx, const CAmount& nFee, CTxMemPool& pool) +{ + int64_t nTime = 0; + double dPriority = 10.0; + unsigned int nHeight = 1; + bool spendsCoinbase = false; + unsigned int sigOpCost = 4; + LockPoints lp; + pool.addUnchecked(tx.GetHash(), CTxMemPoolEntry( + tx, nFee, nTime, dPriority, nHeight, pool.HasNoInputsOf(tx), + tx.GetValueOut(), spendsCoinbase, sigOpCost, lp)); +} + +// Right now this is only testing eviction performance in an extremely small +// mempool. Code needs to be written to generate a much wider variety of +// unique transactions for a more meaningful performance measurement. +static void MempoolEviction(benchmark::State& state) +{ + CMutableTransaction tx1 = CMutableTransaction(); + tx1.vin.resize(1); + tx1.vin[0].scriptSig = CScript() << OP_1; + tx1.vout.resize(1); + tx1.vout[0].scriptPubKey = CScript() << OP_1 << OP_EQUAL; + tx1.vout[0].nValue = 10 * COIN; + + CMutableTransaction tx2 = CMutableTransaction(); + tx2.vin.resize(1); + tx2.vin[0].scriptSig = CScript() << OP_2; + tx2.vout.resize(1); + tx2.vout[0].scriptPubKey = CScript() << OP_2 << OP_EQUAL; + tx2.vout[0].nValue = 10 * COIN; + + CMutableTransaction tx3 = CMutableTransaction(); + tx3.vin.resize(1); + tx3.vin[0].prevout = COutPoint(tx2.GetHash(), 0); + tx3.vin[0].scriptSig = CScript() << OP_2; + tx3.vout.resize(1); + tx3.vout[0].scriptPubKey = CScript() << OP_3 << OP_EQUAL; + tx3.vout[0].nValue = 10 * COIN; + + CMutableTransaction tx4 = CMutableTransaction(); + tx4.vin.resize(2); + tx4.vin[0].prevout.SetNull(); + tx4.vin[0].scriptSig = CScript() << OP_4; + tx4.vin[1].prevout.SetNull(); + tx4.vin[1].scriptSig = CScript() << OP_4; + tx4.vout.resize(2); + tx4.vout[0].scriptPubKey = CScript() << OP_4 << OP_EQUAL; + tx4.vout[0].nValue = 10 * COIN; + tx4.vout[1].scriptPubKey = CScript() << OP_4 << OP_EQUAL; + tx4.vout[1].nValue = 10 * COIN; + + CMutableTransaction tx5 = CMutableTransaction(); + tx5.vin.resize(2); + tx5.vin[0].prevout = COutPoint(tx4.GetHash(), 0); + tx5.vin[0].scriptSig = CScript() << OP_4; + tx5.vin[1].prevout.SetNull(); + tx5.vin[1].scriptSig = CScript() << OP_5; + tx5.vout.resize(2); + tx5.vout[0].scriptPubKey = CScript() << OP_5 << OP_EQUAL; + tx5.vout[0].nValue = 10 * COIN; + tx5.vout[1].scriptPubKey = CScript() << OP_5 << OP_EQUAL; + tx5.vout[1].nValue = 10 * COIN; + + CMutableTransaction tx6 = CMutableTransaction(); + tx6.vin.resize(2); + tx6.vin[0].prevout = COutPoint(tx4.GetHash(), 1); + tx6.vin[0].scriptSig = CScript() << OP_4; + tx6.vin[1].prevout.SetNull(); + tx6.vin[1].scriptSig = CScript() << OP_6; + tx6.vout.resize(2); + tx6.vout[0].scriptPubKey = CScript() << OP_6 << OP_EQUAL; + tx6.vout[0].nValue = 10 * COIN; + tx6.vout[1].scriptPubKey = CScript() << OP_6 << OP_EQUAL; + tx6.vout[1].nValue = 10 * COIN; + + CMutableTransaction tx7 = CMutableTransaction(); + tx7.vin.resize(2); + tx7.vin[0].prevout = COutPoint(tx5.GetHash(), 0); + tx7.vin[0].scriptSig = CScript() << OP_5; + tx7.vin[1].prevout = COutPoint(tx6.GetHash(), 0); + tx7.vin[1].scriptSig = CScript() << OP_6; + tx7.vout.resize(2); + tx7.vout[0].scriptPubKey = CScript() << OP_7 << OP_EQUAL; + tx7.vout[0].nValue = 10 * COIN; + tx7.vout[1].scriptPubKey = CScript() << OP_7 << OP_EQUAL; + tx7.vout[1].nValue = 10 * COIN; + + CTxMemPool pool(CFeeRate(1000)); + + while (state.KeepRunning()) { + AddTx(tx1, 10000LL, pool); + AddTx(tx2, 5000LL, pool); + AddTx(tx3, 20000LL, pool); + AddTx(tx4, 7000LL, pool); + AddTx(tx5, 1000LL, pool); + AddTx(tx6, 1100LL, pool); + AddTx(tx7, 9000LL, pool); + pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4); + pool.TrimToSize(GetVirtualTransactionSize(tx1)); + } +} + +BENCHMARK(MempoolEviction); diff --git a/src/bench/verify_script.cpp b/src/bench/verify_script.cpp new file mode 100644 index 0000000000000..dc3940cdbdd99 --- /dev/null +++ b/src/bench/verify_script.cpp @@ -0,0 +1,103 @@ +// Copyright (c) 2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "bench.h" +#include "key.h" +#if defined(HAVE_CONSENSUS_LIB) +#include "script/bitcoinconsensus.h" +#endif +#include "script/script.h" +#include "script/sign.h" +#include "streams.h" + +// FIXME: Dedup with BuildCreditingTransaction in test/script_tests.cpp. +static CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey) +{ + CMutableTransaction txCredit; + txCredit.nVersion = 1; + txCredit.nLockTime = 0; + txCredit.vin.resize(1); + txCredit.vout.resize(1); + txCredit.vin[0].prevout.SetNull(); + txCredit.vin[0].scriptSig = CScript() << CScriptNum(0) << CScriptNum(0); + txCredit.vin[0].nSequence = CTxIn::SEQUENCE_FINAL; + txCredit.vout[0].scriptPubKey = scriptPubKey; + txCredit.vout[0].nValue = 1; + + return txCredit; +} + +// FIXME: Dedup with BuildSpendingTransaction in test/script_tests.cpp. +static CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CMutableTransaction& txCredit) +{ + CMutableTransaction txSpend; + txSpend.nVersion = 1; + txSpend.nLockTime = 0; + txSpend.vin.resize(1); + txSpend.vout.resize(1); + txSpend.wit.vtxinwit.resize(1); + txSpend.vin[0].prevout.hash = txCredit.GetHash(); + txSpend.vin[0].prevout.n = 0; + txSpend.vin[0].scriptSig = scriptSig; + txSpend.vin[0].nSequence = CTxIn::SEQUENCE_FINAL; + txSpend.vout[0].scriptPubKey = CScript(); + txSpend.vout[0].nValue = txCredit.vout[0].nValue; + + return txSpend; +} + +// Microbenchmark for verification of a basic P2WPKH script. Can be easily +// modified to measure performance of other types of scripts. +static void VerifyScriptBench(benchmark::State& state) +{ + const int flags = SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH; + const int witnessversion = 0; + + // Keypair. + CKey key; + const unsigned char vchKey[32] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; + key.Set(vchKey, vchKey + 32, false); + CPubKey pubkey = key.GetPubKey(); + uint160 pubkeyHash; + CHash160().Write(pubkey.begin(), pubkey.size()).Finalize(pubkeyHash.begin()); + + // Script. + CScript scriptPubKey = CScript() << witnessversion << ToByteVector(pubkeyHash); + CScript scriptSig; + CScript witScriptPubkey = CScript() << OP_DUP << OP_HASH160 << ToByteVector(pubkeyHash) << OP_EQUALVERIFY << OP_CHECKSIG; + CTransaction txCredit = BuildCreditingTransaction(scriptPubKey); + CMutableTransaction txSpend = BuildSpendingTransaction(scriptSig, txCredit); + CScriptWitness& witness = txSpend.wit.vtxinwit[0].scriptWitness; + witness.stack.emplace_back(); + key.Sign(SignatureHash(witScriptPubkey, txSpend, 0, SIGHASH_ALL, txCredit.vout[0].nValue, SIGVERSION_WITNESS_V0), witness.stack.back(), 0); + witness.stack.back().push_back(static_cast(SIGHASH_ALL)); + witness.stack.push_back(ToByteVector(pubkey)); + + // Benchmark. + while (state.KeepRunning()) { + ScriptError err; + bool success = VerifyScript( + txSpend.vin[0].scriptSig, + txCredit.vout[0].scriptPubKey, + &txSpend.wit.vtxinwit[0].scriptWitness, + flags, + MutableTransactionSignatureChecker(&txSpend, 0, txCredit.vout[0].nValue), + &err); + assert(err == SCRIPT_ERR_OK); + assert(success); + +#if defined(HAVE_CONSENSUS_LIB) + CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); + stream << txSpend; + int csuccess = bitcoinconsensus_verify_script_with_amount( + begin_ptr(txCredit.vout[0].scriptPubKey), + txCredit.vout[0].scriptPubKey.size(), + txCredit.vout[0].nValue, + (const unsigned char*)&stream[0], stream.size(), 0, flags, nullptr); + assert(csuccess == 1); +#endif + } +} + +BENCHMARK(VerifyScriptBench); From 46304791353d2bb61004a035869612620c30b4eb Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Mon, 17 Oct 2016 23:11:35 +0000 Subject: [PATCH 1053/1802] Make dnsseed's definition of acute need include relevant services. We normally prefer to connect to peers offering the relevant services. If we're not connected to enough peers with relevant services, we probably don't know about them and could use dnsseed's help. --- src/net.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/net.cpp b/src/net.cpp index de8f8184a28c9..99f5604ff220e 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1462,12 +1462,19 @@ static std::string GetDNSHost(const CDNSSeedData& data, ServiceFlags* requiredSe void CConnman::ThreadDNSAddressSeed() { // goal: only query DNS seeds if address need is acute + // Avoiding DNS seeds when we don't need them improves user privacy by + // creating fewer identifying DNS requests, reduces trust by giving seeds + // less influence on the network topology, and reduces traffic to the seeds. if ((addrman.size() > 0) && (!GetBoolArg("-forcednsseed", DEFAULT_FORCEDNSSEED))) { MilliSleep(11 * 1000); LOCK(cs_vNodes); - if (vNodes.size() >= 2) { + int nRelevant = 0; + for (auto pnode : vNodes) { + nRelevant += pnode->fSuccessfullyConnected && ((pnode->nServices & nRelevantServices) == nRelevantServices); + } + if (nRelevant >= 2) { LogPrintf("P2P peers available. Skipped DNS seeding.\n"); return; } From 59daa58d6a17bb1170c724f2d01d43c2ec21a9b4 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Tue, 18 Oct 2016 07:17:19 +0000 Subject: [PATCH 1054/1802] RPC/Mining: getblocktemplate: Update and fix formatting of help --- src/rpc/mining.cpp | 66 +++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 92ca4bab6bc1e..33c1893ff6944 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -319,67 +319,73 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) { if (fHelp || params.size() > 1) throw runtime_error( - "getblocktemplate ( \"jsonrequestobject\" )\n" + "getblocktemplate ( TemplateRequest )\n" "\nIf the request parameters include a 'mode' key, that is used to explicitly select between the default 'template' request or a 'proposal'.\n" "It returns data needed to construct a block to work on.\n" - "For full specification, see BIPs 22 and 9:\n" + "For full specification, see BIPs 22, 23, 9, and 145:\n" " https://github.com/bitcoin/bips/blob/master/bip-0022.mediawiki\n" + " https://github.com/bitcoin/bips/blob/master/bip-0023.mediawiki\n" " https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki#getblocktemplate_changes\n" + " https://github.com/bitcoin/bips/blob/master/bip-0145.mediawiki\n" "\nArguments:\n" - "1. \"jsonrequestobject\" (string, optional) A json object in the following spec\n" + "1. TemplateRequest (json object, optional) A json object in the following spec\n" " {\n" - " \"mode\":\"template\" (string, optional) This must be set to \"template\" or omitted\n" - " \"capabilities\":[ (array, optional) A list of strings\n" - " \"support\" (string) client side supported feature, 'longpoll', 'coinbasetxn', 'coinbasevalue', 'proposal', 'serverlist', 'workid'\n" + " \"mode\":\"template\" (string, optional) This must be set to \"template\", \"proposal\" (see BIP 23), or omitted\n" + " \"capabilities\":[ (array, optional) A list of strings\n" + " \"support\" (string) client side supported feature, 'longpoll', 'coinbasetxn', 'coinbasevalue', 'proposal', 'serverlist', 'workid'\n" " ,...\n" - " ]\n" + " ],\n" + " \"rules\":[ (array, optional) A list of strings\n" + " \"support\" (string) client side supported softfork deployment\n" + " ,...\n" + " ]\n" " }\n" "\n" "\nResult:\n" "{\n" - " \"version\" : n, (numeric) The block version\n" + " \"version\" : n, (numeric) The preferred block version\n" " \"rules\" : [ \"rulename\", ... ], (array of strings) specific block rules that are to be enforced\n" " \"vbavailable\" : { (json object) set of pending, supported versionbit (BIP 9) softfork deployments\n" - " \"rulename\" : bitnumber (numeric) identifies the bit number as indicating acceptance and readiness for the named softfork rule\n" + " \"rulename\" : bitnumber (numeric) identifies the bit number as indicating acceptance and readiness for the named softfork rule\n" " ,...\n" " },\n" " \"vbrequired\" : n, (numeric) bit mask of versionbits the server requires set in submissions\n" - " \"previousblockhash\" : \"xxxx\", (string) The hash of current highest block\n" + " \"previousblockhash\" : \"xxxx\", (string) The hash of current highest block\n" " \"transactions\" : [ (array) contents of non-coinbase transactions that should be included in the next block\n" " {\n" - " \"data\" : \"xxxx\", (string) transaction data encoded in hexadecimal (byte-for-byte)\n" - " \"txid\" : \"xxxx\", (string) transaction id encoded in little-endian hexadecimal\n" - " \"hash\" : \"xxxx\", (string) hash encoded in little-endian hexadecimal (including witness data)\n" - " \"depends\" : [ (array) array of numbers \n" - " n (numeric) transactions before this one (by 1-based index in 'transactions' list) that must be present in the final block if this one is\n" + " \"data\" : \"xxxx\", (string) transaction data encoded in hexadecimal (byte-for-byte)\n" + " \"txid\" : \"xxxx\", (string) transaction id encoded in little-endian hexadecimal\n" + " \"hash\" : \"xxxx\", (string) hash encoded in little-endian hexadecimal (including witness data)\n" + " \"depends\" : [ (array) array of numbers \n" + " n (numeric) transactions before this one (by 1-based index in 'transactions' list) that must be present in the final block if this one is\n" " ,...\n" " ],\n" - " \"fee\": n, (numeric) difference in value between transaction inputs and outputs (in Satoshis); for coinbase transactions, this is a negative Number of the total collected block fees (ie, not including the block subsidy); if key is not present, fee is unknown and clients MUST NOT assume there isn't one\n" - " \"sigops\" : n, (numeric) total SigOps cost, as counted for purposes of block limits; if key is not present, sigop cost is unknown and clients MUST NOT assume it is zero\n" - " \"weight\" : n, (numeric) total transaction weight, as counted for purposes of block limits\n" - " \"required\" : true|false (boolean) if provided and true, this transaction must be in the final block\n" + " \"fee\": n, (numeric) difference in value between transaction inputs and outputs (in Satoshis); for coinbase transactions, this is a negative Number of the total collected block fees (ie, not including the block subsidy); if key is not present, fee is unknown and clients MUST NOT assume there isn't one\n" + " \"sigops\" : n, (numeric) total SigOps cost, as counted for purposes of block limits; if key is not present, sigop cost is unknown and clients MUST NOT assume it is zero\n" + " \"weight\" : n, (numeric) total transaction weight, as counted for purposes of block limits\n" + " \"required\" : true|false (boolean) if provided and true, this transaction must be in the final block\n" " }\n" " ,...\n" " ],\n" - " \"coinbaseaux\" : { (json object) data that should be included in the coinbase's scriptSig content\n" - " \"flags\" : \"flags\" (string) \n" + " \"coinbaseaux\" : { (json object) data that should be included in the coinbase's scriptSig content\n" + " \"flags\" : \"xx\" (string) key name is to be ignored, and value included in scriptSig\n" " },\n" - " \"coinbasevalue\" : n, (numeric) maximum allowable input to coinbase transaction, including the generation award and transaction fees (in Satoshis)\n" - " \"coinbasetxn\" : { ... }, (json object) information for coinbase transaction\n" - " \"target\" : \"xxxx\", (string) The hash target\n" - " \"mintime\" : xxx, (numeric) The minimum timestamp appropriate for next block time in seconds since epoch (Jan 1 1970 GMT)\n" - " \"mutable\" : [ (array of string) list of ways the block template may be changed \n" - " \"value\" (string) A way the block template may be changed, e.g. 'time', 'transactions', 'prevblock'\n" + " \"coinbasevalue\" : n, (numeric) maximum allowable input to coinbase transaction, including the generation award and transaction fees (in Satoshis)\n" + " \"coinbasetxn\" : { ... }, (json object) information for coinbase transaction\n" + " \"target\" : \"xxxx\", (string) The hash target\n" + " \"mintime\" : xxx, (numeric) The minimum timestamp appropriate for next block time in seconds since epoch (Jan 1 1970 GMT)\n" + " \"mutable\" : [ (array of string) list of ways the block template may be changed \n" + " \"value\" (string) A way the block template may be changed, e.g. 'time', 'transactions', 'prevblock'\n" " ,...\n" " ],\n" - " \"noncerange\" : \"00000000ffffffff\", (string) A range of valid nonces\n" - " \"sigoplimit\" : n, (numeric) cost limit of sigops in blocks\n" + " \"noncerange\" : \"00000000ffffffff\",(string) A range of valid nonces\n" + " \"sigoplimit\" : n, (numeric) limit of sigops in blocks\n" " \"sizelimit\" : n, (numeric) limit of block size\n" " \"weightlimit\" : n, (numeric) limit of block weight\n" " \"curtime\" : ttt, (numeric) current timestamp in seconds since epoch (Jan 1 1970 GMT)\n" - " \"bits\" : \"xxx\", (string) compressed target of next block\n" + " \"bits\" : \"xxxxxxxx\", (string) compressed target of next block\n" " \"height\" : n (numeric) The height of the next block\n" "}\n" From ef0c9ee2960fda58b2fe5b0c3b4c672231b30322 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Mon, 30 Nov 2015 20:57:20 +0100 Subject: [PATCH 1055/1802] [Qt] make warnings label selectable --- src/qt/forms/overviewpage.ui | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/qt/forms/overviewpage.ui b/src/qt/forms/overviewpage.ui index 6d792d1475fed..4a6ee92508d5e 100644 --- a/src/qt/forms/overviewpage.ui +++ b/src/qt/forms/overviewpage.ui @@ -20,7 +20,7 @@ false - background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop:0 #F0D0A0, stop:1 #F8D488); color:#000000; + QLabel { background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop:0 #F0D0A0, stop:1 #F8D488); color:#000000; } true @@ -28,6 +28,9 @@ 3 + + Qt::TextSelectableByMouse + From 23c32a9694e119f957c124f4501294ae7a5fd99a Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 29 Sep 2016 18:48:27 +0200 Subject: [PATCH 1056/1802] rpc: Change JSONRPCRequest to JSONRPCRequestObj This is more consistent with `JSONRPCReplyObj`. --- src/bitcoin-cli.cpp | 2 +- src/rpc/protocol.cpp | 4 ++-- src/rpc/protocol.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 9d4c4e53bd26b..2d66448d80ac3 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -223,7 +223,7 @@ UniValue CallRPC(const string& strMethod, const UniValue& params) evhttp_add_header(output_headers, "Authorization", (std::string("Basic ") + EncodeBase64(strRPCUserColonPass)).c_str()); // Attach request data - std::string strRequest = JSONRPCRequest(strMethod, params, 1); + std::string strRequest = JSONRPCRequestObj(strMethod, params, 1).write() + "\n"; struct evbuffer * output_buffer = evhttp_request_get_output_buffer(req); assert(output_buffer); evbuffer_add(output_buffer, strRequest.data(), strRequest.size()); diff --git a/src/rpc/protocol.cpp b/src/rpc/protocol.cpp index bb885bb5a655d..ec186f4fc5888 100644 --- a/src/rpc/protocol.cpp +++ b/src/rpc/protocol.cpp @@ -26,13 +26,13 @@ using namespace std; * 1.2 spec: http://jsonrpc.org/historical/json-rpc-over-http.html */ -string JSONRPCRequest(const string& strMethod, const UniValue& params, const UniValue& id) +UniValue JSONRPCRequestObj(const string& strMethod, const UniValue& params, const UniValue& id) { UniValue request(UniValue::VOBJ); request.push_back(Pair("method", strMethod)); request.push_back(Pair("params", params)); request.push_back(Pair("id", id)); - return request.write() + "\n"; + return request; } UniValue JSONRPCReplyObj(const UniValue& result, const UniValue& error, const UniValue& id) diff --git a/src/rpc/protocol.h b/src/rpc/protocol.h index 1d2ef0e41e67e..c74fa0070fc6d 100644 --- a/src/rpc/protocol.h +++ b/src/rpc/protocol.h @@ -77,7 +77,7 @@ enum RPCErrorCode RPC_WALLET_ALREADY_UNLOCKED = -17, //!< Wallet is already unlocked }; -std::string JSONRPCRequest(const std::string& strMethod, const UniValue& params, const UniValue& id); +UniValue JSONRPCRequestObj(const std::string& strMethod, const UniValue& params, const UniValue& id); UniValue JSONRPCReplyObj(const UniValue& result, const UniValue& error, const UniValue& id); std::string JSONRPCReply(const UniValue& result, const UniValue& error, const UniValue& id); UniValue JSONRPCError(int code, const std::string& message); From 69d1c25768a8649bfc7eb8e9c35b8fe9874ac9fc Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 22 Sep 2016 09:46:41 +0200 Subject: [PATCH 1057/1802] [RPC] Give RPC commands more information about the RPC request --- src/httprpc.cpp | 7 +- src/qt/rpcconsole.cpp | 5 +- src/rest.cpp | 6 +- src/rpc/blockchain.cpp | 158 ++++++------ src/rpc/mining.cpp | 90 +++---- src/rpc/misc.cpp | 42 ++-- src/rpc/net.cpp | 72 +++--- src/rpc/rawtransaction.cpp | 90 +++---- src/rpc/server.cpp | 29 +-- src/rpc/server.h | 13 +- src/test/rpc_tests.cpp | 7 +- src/wallet/rpcdump.cpp | 100 ++++---- src/wallet/rpcwallet.cpp | 486 ++++++++++++++++++------------------- 13 files changed, 558 insertions(+), 547 deletions(-) diff --git a/src/httprpc.cpp b/src/httprpc.cpp index 6a6c5276cc1e5..54651911aa38d 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -172,19 +172,22 @@ static bool HTTPReq_JSONRPC(HTTPRequest* req, const std::string &) return false; } - JSONRequest jreq; + JSONRPCRequest jreq; try { // Parse request UniValue valRequest; if (!valRequest.read(req->ReadBody())) throw JSONRPCError(RPC_PARSE_ERROR, "Parse error"); + // Set the URI + jreq.URI = req->GetURI(); + std::string strReply; // singleton request if (valRequest.isObject()) { jreq.parse(valRequest); - UniValue result = tableRPC.execute(jreq.strMethod, jreq.params); + UniValue result = tableRPC.execute(jreq); // Send reply strReply = JSONRPCReply(result, NullUniValue, jreq.id); diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index a1017e6c16bb8..f10dddf589e28 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -246,7 +246,10 @@ bool RPCConsole::RPCExecuteCommandLine(std::string &strResult, const std::string std::string strPrint; // Convert argument list to JSON objects in method-dependent way, // and pass it along with the method name to the dispatcher. - lastResult = tableRPC.execute(stack.back()[0], RPCConvertValues(stack.back()[0], std::vector(stack.back().begin() + 1, stack.back().end()))); + JSONRPCRequest req; + req.params = RPCConvertValues(stack.back()[0], std::vector(stack.back().begin() + 1, stack.back().end())); + req.strMethod = stack.back()[0]; + lastResult = tableRPC.execute(req); state = STATE_COMMAND_EXECUTED; curarg.clear(); diff --git a/src/rest.cpp b/src/rest.cpp index c81559212419f..707dfe69871f7 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -274,7 +274,7 @@ static bool rest_block_notxdetails(HTTPRequest* req, const std::string& strURIPa } // A bit of a hack - dependency on a function defined in rpc/blockchain.cpp -UniValue getblockchaininfo(const UniValue& params, bool fHelp); +UniValue getblockchaininfo(const JSONRPCRequest& request); static bool rest_chaininfo(HTTPRequest* req, const std::string& strURIPart) { @@ -285,8 +285,8 @@ static bool rest_chaininfo(HTTPRequest* req, const std::string& strURIPart) switch (rf) { case RF_JSON: { - UniValue rpcParams(UniValue::VARR); - UniValue chainInfoObject = getblockchaininfo(rpcParams, false); + JSONRPCRequest jsonRequest; + UniValue chainInfoObject = getblockchaininfo(jsonRequest); string strJSON = chainInfoObject.write() + "\n"; req->WriteHeader("Content-Type", "application/json"); req->WriteReply(HTTP_OK, strJSON); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 5414ac9ffd449..0c827a1e3881d 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -146,9 +146,9 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx return result; } -UniValue getblockcount(const UniValue& params, bool fHelp) +UniValue getblockcount(const JSONRPCRequest& request) { - if (fHelp || params.size() != 0) + if (request.fHelp || request.params.size() != 0) throw runtime_error( "getblockcount\n" "\nReturns the number of blocks in the longest block chain.\n" @@ -163,9 +163,9 @@ UniValue getblockcount(const UniValue& params, bool fHelp) return chainActive.Height(); } -UniValue getbestblockhash(const UniValue& params, bool fHelp) +UniValue getbestblockhash(const JSONRPCRequest& request) { - if (fHelp || params.size() != 0) + if (request.fHelp || request.params.size() != 0) throw runtime_error( "getbestblockhash\n" "\nReturns the hash of the best (tip) block in the longest block chain.\n" @@ -190,9 +190,9 @@ void RPCNotifyBlockChange(bool ibd, const CBlockIndex * pindex) cond_blockchange.notify_all(); } -UniValue waitfornewblock(const UniValue& params, bool fHelp) +UniValue waitfornewblock(const JSONRPCRequest& request) { - if (fHelp || params.size() > 1) + if (request.fHelp || request.params.size() > 1) throw runtime_error( "waitfornewblock\n" "\nWaits for a specific new block and returns useful info about it.\n" @@ -209,8 +209,8 @@ UniValue waitfornewblock(const UniValue& params, bool fHelp) + HelpExampleRpc("waitfornewblock", "1000") ); int timeout = 0; - if (params.size() > 0) - timeout = params[0].get_int(); + if (request.params.size() > 0) + timeout = request.params[0].get_int(); CUpdatedBlock block; { @@ -228,9 +228,9 @@ UniValue waitfornewblock(const UniValue& params, bool fHelp) return ret; } -UniValue waitforblock(const UniValue& params, bool fHelp) +UniValue waitforblock(const JSONRPCRequest& request) { - if (fHelp || params.size() < 1 || params.size() > 2) + if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw runtime_error( "waitforblock\n" "\nWaits for a specific new block and returns useful info about it.\n" @@ -249,10 +249,10 @@ UniValue waitforblock(const UniValue& params, bool fHelp) ); int timeout = 0; - uint256 hash = uint256S(params[0].get_str()); + uint256 hash = uint256S(request.params[0].get_str()); - if (params.size() > 1) - timeout = params[1].get_int(); + if (request.params.size() > 1) + timeout = request.params[1].get_int(); CUpdatedBlock block; { @@ -270,9 +270,9 @@ UniValue waitforblock(const UniValue& params, bool fHelp) return ret; } -UniValue waitforblockheight(const UniValue& params, bool fHelp) +UniValue waitforblockheight(const JSONRPCRequest& request) { - if (fHelp || params.size() < 1 || params.size() > 2) + if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw runtime_error( "waitforblock\n" "\nWaits for (at least) block height and returns the height and hash\n" @@ -292,10 +292,10 @@ UniValue waitforblockheight(const UniValue& params, bool fHelp) ); int timeout = 0; - int height = params[0].get_int(); + int height = request.params[0].get_int(); - if (params.size() > 1) - timeout = params[1].get_int(); + if (request.params.size() > 1) + timeout = request.params[1].get_int(); CUpdatedBlock block; { @@ -312,9 +312,9 @@ UniValue waitforblockheight(const UniValue& params, bool fHelp) return ret; } -UniValue getdifficulty(const UniValue& params, bool fHelp) +UniValue getdifficulty(const JSONRPCRequest& request) { - if (fHelp || params.size() != 0) + if (request.fHelp || request.params.size() != 0) throw runtime_error( "getdifficulty\n" "\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n" @@ -411,9 +411,9 @@ UniValue mempoolToJSON(bool fVerbose = false) } } -UniValue getrawmempool(const UniValue& params, bool fHelp) +UniValue getrawmempool(const JSONRPCRequest& request) { - if (fHelp || params.size() > 1) + if (request.fHelp || request.params.size() > 1) throw runtime_error( "getrawmempool ( verbose )\n" "\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n" @@ -436,15 +436,15 @@ UniValue getrawmempool(const UniValue& params, bool fHelp) ); bool fVerbose = false; - if (params.size() > 0) - fVerbose = params[0].get_bool(); + if (request.params.size() > 0) + fVerbose = request.params[0].get_bool(); return mempoolToJSON(fVerbose); } -UniValue getmempoolancestors(const UniValue& params, bool fHelp) +UniValue getmempoolancestors(const JSONRPCRequest& request) { - if (fHelp || params.size() < 1 || params.size() > 2) { + if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) { throw runtime_error( "getmempoolancestors txid (verbose)\n" "\nIf txid is in the mempool, returns all in-mempool ancestors.\n" @@ -469,10 +469,10 @@ UniValue getmempoolancestors(const UniValue& params, bool fHelp) } bool fVerbose = false; - if (params.size() > 1) - fVerbose = params[1].get_bool(); + if (request.params.size() > 1) + fVerbose = request.params[1].get_bool(); - uint256 hash = ParseHashV(params[0], "parameter 1"); + uint256 hash = ParseHashV(request.params[0], "parameter 1"); LOCK(mempool.cs); @@ -506,9 +506,9 @@ UniValue getmempoolancestors(const UniValue& params, bool fHelp) } } -UniValue getmempooldescendants(const UniValue& params, bool fHelp) +UniValue getmempooldescendants(const JSONRPCRequest& request) { - if (fHelp || params.size() < 1 || params.size() > 2) { + if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) { throw runtime_error( "getmempooldescendants txid (verbose)\n" "\nIf txid is in the mempool, returns all in-mempool descendants.\n" @@ -533,10 +533,10 @@ UniValue getmempooldescendants(const UniValue& params, bool fHelp) } bool fVerbose = false; - if (params.size() > 1) - fVerbose = params[1].get_bool(); + if (request.params.size() > 1) + fVerbose = request.params[1].get_bool(); - uint256 hash = ParseHashV(params[0], "parameter 1"); + uint256 hash = ParseHashV(request.params[0], "parameter 1"); LOCK(mempool.cs); @@ -570,9 +570,9 @@ UniValue getmempooldescendants(const UniValue& params, bool fHelp) } } -UniValue getmempoolentry(const UniValue& params, bool fHelp) +UniValue getmempoolentry(const JSONRPCRequest& request) { - if (fHelp || params.size() != 1) { + if (request.fHelp || request.params.size() != 1) { throw runtime_error( "getmempoolentry txid\n" "\nReturns mempool data for given transaction\n" @@ -588,7 +588,7 @@ UniValue getmempoolentry(const UniValue& params, bool fHelp) ); } - uint256 hash = ParseHashV(params[0], "parameter 1"); + uint256 hash = ParseHashV(request.params[0], "parameter 1"); LOCK(mempool.cs); @@ -603,9 +603,9 @@ UniValue getmempoolentry(const UniValue& params, bool fHelp) return info; } -UniValue getblockhash(const UniValue& params, bool fHelp) +UniValue getblockhash(const JSONRPCRequest& request) { - if (fHelp || params.size() != 1) + if (request.fHelp || request.params.size() != 1) throw runtime_error( "getblockhash index\n" "\nReturns hash of block in best-block-chain at index provided.\n" @@ -620,7 +620,7 @@ UniValue getblockhash(const UniValue& params, bool fHelp) LOCK(cs_main); - int nHeight = params[0].get_int(); + int nHeight = request.params[0].get_int(); if (nHeight < 0 || nHeight > chainActive.Height()) throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); @@ -628,9 +628,9 @@ UniValue getblockhash(const UniValue& params, bool fHelp) return pblockindex->GetBlockHash().GetHex(); } -UniValue getblockheader(const UniValue& params, bool fHelp) +UniValue getblockheader(const JSONRPCRequest& request) { - if (fHelp || params.size() < 1 || params.size() > 2) + if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw runtime_error( "getblockheader \"hash\" ( verbose )\n" "\nIf verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'.\n" @@ -664,12 +664,12 @@ UniValue getblockheader(const UniValue& params, bool fHelp) LOCK(cs_main); - std::string strHash = params[0].get_str(); + std::string strHash = request.params[0].get_str(); uint256 hash(uint256S(strHash)); bool fVerbose = true; - if (params.size() > 1) - fVerbose = params[1].get_bool(); + if (request.params.size() > 1) + fVerbose = request.params[1].get_bool(); if (mapBlockIndex.count(hash) == 0) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); @@ -687,9 +687,9 @@ UniValue getblockheader(const UniValue& params, bool fHelp) return blockheaderToJSON(pblockindex); } -UniValue getblock(const UniValue& params, bool fHelp) +UniValue getblock(const JSONRPCRequest& request) { - if (fHelp || params.size() < 1 || params.size() > 2) + if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw runtime_error( "getblock \"hash\" ( verbose )\n" "\nIf verbose is false, returns a string that is serialized, hex-encoded data for block 'hash'.\n" @@ -730,12 +730,12 @@ UniValue getblock(const UniValue& params, bool fHelp) LOCK(cs_main); - std::string strHash = params[0].get_str(); + std::string strHash = request.params[0].get_str(); uint256 hash(uint256S(strHash)); bool fVerbose = true; - if (params.size() > 1) - fVerbose = params[1].get_bool(); + if (request.params.size() > 1) + fVerbose = request.params[1].get_bool(); if (mapBlockIndex.count(hash) == 0) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); @@ -814,9 +814,9 @@ static bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats) return true; } -UniValue gettxoutsetinfo(const UniValue& params, bool fHelp) +UniValue gettxoutsetinfo(const JSONRPCRequest& request) { - if (fHelp || params.size() != 0) + if (request.fHelp || request.params.size() != 0) throw runtime_error( "gettxoutsetinfo\n" "\nReturns statistics about the unspent transaction output set.\n" @@ -854,9 +854,9 @@ UniValue gettxoutsetinfo(const UniValue& params, bool fHelp) return ret; } -UniValue gettxout(const UniValue& params, bool fHelp) +UniValue gettxout(const JSONRPCRequest& request) { - if (fHelp || params.size() < 2 || params.size() > 3) + if (request.fHelp || request.params.size() < 2 || request.params.size() > 3) throw runtime_error( "gettxout \"txid\" n ( includemempool )\n" "\nReturns details about an unspent transaction output.\n" @@ -896,12 +896,12 @@ UniValue gettxout(const UniValue& params, bool fHelp) UniValue ret(UniValue::VOBJ); - std::string strHash = params[0].get_str(); + std::string strHash = request.params[0].get_str(); uint256 hash(uint256S(strHash)); - int n = params[1].get_int(); + int n = request.params[1].get_int(); bool fMempool = true; - if (params.size() > 2) - fMempool = params[2].get_bool(); + if (request.params.size() > 2) + fMempool = request.params[2].get_bool(); CCoins coins; if (fMempool) { @@ -934,11 +934,11 @@ UniValue gettxout(const UniValue& params, bool fHelp) return ret; } -UniValue verifychain(const UniValue& params, bool fHelp) +UniValue verifychain(const JSONRPCRequest& request) { int nCheckLevel = GetArg("-checklevel", DEFAULT_CHECKLEVEL); int nCheckDepth = GetArg("-checkblocks", DEFAULT_CHECKBLOCKS); - if (fHelp || params.size() > 2) + if (request.fHelp || request.params.size() > 2) throw runtime_error( "verifychain ( checklevel numblocks )\n" "\nVerifies blockchain database.\n" @@ -954,10 +954,10 @@ UniValue verifychain(const UniValue& params, bool fHelp) LOCK(cs_main); - if (params.size() > 0) - nCheckLevel = params[0].get_int(); - if (params.size() > 1) - nCheckDepth = params[1].get_int(); + if (request.params.size() > 0) + nCheckLevel = request.params[0].get_int(); + if (request.params.size() > 1) + nCheckDepth = request.params[1].get_int(); return CVerifyDB().VerifyDB(Params(), pcoinsTip, nCheckLevel, nCheckDepth); } @@ -1021,9 +1021,9 @@ void BIP9SoftForkDescPushBack(UniValue& bip9_softforks, const std::string &name, bip9_softforks.push_back(Pair(name, BIP9SoftForkDesc(consensusParams, id))); } -UniValue getblockchaininfo(const UniValue& params, bool fHelp) +UniValue getblockchaininfo(const JSONRPCRequest& request) { - if (fHelp || params.size() != 0) + if (request.fHelp || request.params.size() != 0) throw runtime_error( "getblockchaininfo\n" "Returns an object containing various state info regarding block chain processing.\n" @@ -1113,9 +1113,9 @@ struct CompareBlocksByHeight } }; -UniValue getchaintips(const UniValue& params, bool fHelp) +UniValue getchaintips(const JSONRPCRequest& request) { - if (fHelp || params.size() != 0) + if (request.fHelp || request.params.size() != 0) throw runtime_error( "getchaintips\n" "Return information about all known tips in the block tree," @@ -1229,9 +1229,9 @@ UniValue mempoolInfoToJSON() return ret; } -UniValue getmempoolinfo(const UniValue& params, bool fHelp) +UniValue getmempoolinfo(const JSONRPCRequest& request) { - if (fHelp || params.size() != 0) + if (request.fHelp || request.params.size() != 0) throw runtime_error( "getmempoolinfo\n" "\nReturns details on the active state of the TX memory pool.\n" @@ -1251,9 +1251,9 @@ UniValue getmempoolinfo(const UniValue& params, bool fHelp) return mempoolInfoToJSON(); } -UniValue preciousblock(const UniValue& params, bool fHelp) +UniValue preciousblock(const JSONRPCRequest& request) { - if (fHelp || params.size() != 1) + if (request.fHelp || request.params.size() != 1) throw runtime_error( "preciousblock \"hash\"\n" "\nTreats a block as if it were received before others with the same work.\n" @@ -1267,7 +1267,7 @@ UniValue preciousblock(const UniValue& params, bool fHelp) + HelpExampleRpc("preciousblock", "\"blockhash\"") ); - std::string strHash = params[0].get_str(); + std::string strHash = request.params[0].get_str(); uint256 hash(uint256S(strHash)); CBlockIndex* pblockindex; @@ -1289,9 +1289,9 @@ UniValue preciousblock(const UniValue& params, bool fHelp) return NullUniValue; } -UniValue invalidateblock(const UniValue& params, bool fHelp) +UniValue invalidateblock(const JSONRPCRequest& request) { - if (fHelp || params.size() != 1) + if (request.fHelp || request.params.size() != 1) throw runtime_error( "invalidateblock \"hash\"\n" "\nPermanently marks a block as invalid, as if it violated a consensus rule.\n" @@ -1303,7 +1303,7 @@ UniValue invalidateblock(const UniValue& params, bool fHelp) + HelpExampleRpc("invalidateblock", "\"blockhash\"") ); - std::string strHash = params[0].get_str(); + std::string strHash = request.params[0].get_str(); uint256 hash(uint256S(strHash)); CValidationState state; @@ -1327,9 +1327,9 @@ UniValue invalidateblock(const UniValue& params, bool fHelp) return NullUniValue; } -UniValue reconsiderblock(const UniValue& params, bool fHelp) +UniValue reconsiderblock(const JSONRPCRequest& request) { - if (fHelp || params.size() != 1) + if (request.fHelp || request.params.size() != 1) throw runtime_error( "reconsiderblock \"hash\"\n" "\nRemoves invalidity status of a block and its descendants, reconsider them for activation.\n" @@ -1342,7 +1342,7 @@ UniValue reconsiderblock(const UniValue& params, bool fHelp) + HelpExampleRpc("reconsiderblock", "\"blockhash\"") ); - std::string strHash = params[0].get_str(); + std::string strHash = request.params[0].get_str(); uint256 hash(uint256S(strHash)); { diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 891b04482c963..d509dd691f55d 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -74,9 +74,9 @@ UniValue GetNetworkHashPS(int lookup, int height) { return workDiff.getdouble() / timeDiff; } -UniValue getnetworkhashps(const UniValue& params, bool fHelp) +UniValue getnetworkhashps(const JSONRPCRequest& request) { - if (fHelp || params.size() > 2) + if (request.fHelp || request.params.size() > 2) throw runtime_error( "getnetworkhashps ( blocks height )\n" "\nReturns the estimated network hashes per second based on the last n blocks.\n" @@ -93,7 +93,7 @@ UniValue getnetworkhashps(const UniValue& params, bool fHelp) ); LOCK(cs_main); - return GetNetworkHashPS(params.size() > 0 ? params[0].get_int() : 120, params.size() > 1 ? params[1].get_int() : -1); + return GetNetworkHashPS(request.params.size() > 0 ? request.params[0].get_int() : 120, request.params.size() > 1 ? request.params[1].get_int() : -1); } UniValue generateBlocks(boost::shared_ptr coinbaseScript, int nGenerate, uint64_t nMaxTries, bool keepScript) @@ -146,9 +146,9 @@ UniValue generateBlocks(boost::shared_ptr coinbaseScript, int nG return blockHashes; } -UniValue generate(const UniValue& params, bool fHelp) +UniValue generate(const JSONRPCRequest& request) { - if (fHelp || params.size() < 1 || params.size() > 2) + if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw runtime_error( "generate numblocks ( maxtries )\n" "\nMine up to numblocks blocks immediately (before the RPC call returns)\n" @@ -162,10 +162,10 @@ UniValue generate(const UniValue& params, bool fHelp) + HelpExampleCli("generate", "11") ); - int nGenerate = params[0].get_int(); + int nGenerate = request.params[0].get_int(); uint64_t nMaxTries = 1000000; - if (params.size() > 1) { - nMaxTries = params[1].get_int(); + if (request.params.size() > 1) { + nMaxTries = request.params[1].get_int(); } boost::shared_ptr coinbaseScript; @@ -182,9 +182,9 @@ UniValue generate(const UniValue& params, bool fHelp) return generateBlocks(coinbaseScript, nGenerate, nMaxTries, true); } -UniValue generatetoaddress(const UniValue& params, bool fHelp) +UniValue generatetoaddress(const JSONRPCRequest& request) { - if (fHelp || params.size() < 2 || params.size() > 3) + if (request.fHelp || request.params.size() < 2 || request.params.size() > 3) throw runtime_error( "generatetoaddress numblocks address (maxtries)\n" "\nMine blocks immediately to a specified address (before the RPC call returns)\n" @@ -199,13 +199,13 @@ UniValue generatetoaddress(const UniValue& params, bool fHelp) + HelpExampleCli("generatetoaddress", "11 \"myaddress\"") ); - int nGenerate = params[0].get_int(); + int nGenerate = request.params[0].get_int(); uint64_t nMaxTries = 1000000; - if (params.size() > 2) { - nMaxTries = params[2].get_int(); + if (request.params.size() > 2) { + nMaxTries = request.params[2].get_int(); } - CBitcoinAddress address(params[1].get_str()); + CBitcoinAddress address(request.params[1].get_str()); if (!address.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Error: Invalid address"); @@ -215,9 +215,9 @@ UniValue generatetoaddress(const UniValue& params, bool fHelp) return generateBlocks(coinbaseScript, nGenerate, nMaxTries, false); } -UniValue getmininginfo(const UniValue& params, bool fHelp) +UniValue getmininginfo(const JSONRPCRequest& request) { - if (fHelp || params.size() != 0) + if (request.fHelp || request.params.size() != 0) throw runtime_error( "getmininginfo\n" "\nReturns a json object containing mining-related information." @@ -248,7 +248,7 @@ UniValue getmininginfo(const UniValue& params, bool fHelp) obj.push_back(Pair("currentblocktx", (uint64_t)nLastBlockTx)); obj.push_back(Pair("difficulty", (double)GetDifficulty())); obj.push_back(Pair("errors", GetWarnings("statusbar"))); - obj.push_back(Pair("networkhashps", getnetworkhashps(params, false))); + obj.push_back(Pair("networkhashps", getnetworkhashps(request))); obj.push_back(Pair("pooledtx", (uint64_t)mempool.size())); obj.push_back(Pair("chain", Params().NetworkIDString())); return obj; @@ -256,9 +256,9 @@ UniValue getmininginfo(const UniValue& params, bool fHelp) // NOTE: Unlike wallet RPC (which use BTC values), mining RPCs follow GBT (BIP 22) in using satoshi amounts -UniValue prioritisetransaction(const UniValue& params, bool fHelp) +UniValue prioritisetransaction(const JSONRPCRequest& request) { - if (fHelp || params.size() != 3) + if (request.fHelp || request.params.size() != 3) throw runtime_error( "prioritisetransaction \n" "Accepts the transaction into mined blocks at a higher (or lower) priority\n" @@ -279,10 +279,10 @@ UniValue prioritisetransaction(const UniValue& params, bool fHelp) LOCK(cs_main); - uint256 hash = ParseHashStr(params[0].get_str(), "txid"); - CAmount nAmount = params[2].get_int64(); + uint256 hash = ParseHashStr(request.params[0].get_str(), "txid"); + CAmount nAmount = request.params[2].get_int64(); - mempool.PrioritiseTransaction(hash, params[0].get_str(), params[1].get_real(), nAmount); + mempool.PrioritiseTransaction(hash, request.params[0].get_str(), request.params[1].get_real(), nAmount); return true; } @@ -315,9 +315,9 @@ std::string gbt_vb_name(const Consensus::DeploymentPos pos) { return s; } -UniValue getblocktemplate(const UniValue& params, bool fHelp) +UniValue getblocktemplate(const JSONRPCRequest& request) { - if (fHelp || params.size() > 1) + if (request.fHelp || request.params.size() > 1) throw runtime_error( "getblocktemplate ( TemplateRequest )\n" "\nIf the request parameters include a 'mode' key, that is used to explicitly select between the default 'template' request or a 'proposal'.\n" @@ -400,9 +400,9 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) UniValue lpval = NullUniValue; std::set setClientRules; int64_t nMaxVersionPreVB = -1; - if (params.size() > 0) + if (request.params.size() > 0) { - const UniValue& oparam = params[0].get_obj(); + const UniValue& oparam = request.params[0].get_obj(); const UniValue& modeval = find_value(oparam, "mode"); if (modeval.isStr()) strMode = modeval.get_str(); @@ -705,9 +705,9 @@ class submitblock_StateCatcher : public CValidationInterface }; }; -UniValue submitblock(const UniValue& params, bool fHelp) +UniValue submitblock(const JSONRPCRequest& request) { - if (fHelp || params.size() < 1 || params.size() > 2) + if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw runtime_error( "submitblock \"hexdata\" ( \"jsonparametersobject\" )\n" "\nAttempts to submit new block to network.\n" @@ -727,7 +727,7 @@ UniValue submitblock(const UniValue& params, bool fHelp) ); CBlock block; - if (!DecodeHexBlk(block, params[0].get_str())) + if (!DecodeHexBlk(block, request.params[0].get_str())) throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed"); uint256 hash = block.GetHash(); @@ -774,9 +774,9 @@ UniValue submitblock(const UniValue& params, bool fHelp) return BIP22ValidationResult(state); } -UniValue estimatefee(const UniValue& params, bool fHelp) +UniValue estimatefee(const JSONRPCRequest& request) { - if (fHelp || params.size() != 1) + if (request.fHelp || request.params.size() != 1) throw runtime_error( "estimatefee nblocks\n" "\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n" @@ -792,9 +792,9 @@ UniValue estimatefee(const UniValue& params, bool fHelp) + HelpExampleCli("estimatefee", "6") ); - RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM)); + RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VNUM)); - int nBlocks = params[0].get_int(); + int nBlocks = request.params[0].get_int(); if (nBlocks < 1) nBlocks = 1; @@ -805,9 +805,9 @@ UniValue estimatefee(const UniValue& params, bool fHelp) return ValueFromAmount(feeRate.GetFeePerK()); } -UniValue estimatepriority(const UniValue& params, bool fHelp) +UniValue estimatepriority(const JSONRPCRequest& request) { - if (fHelp || params.size() != 1) + if (request.fHelp || request.params.size() != 1) throw runtime_error( "estimatepriority nblocks\n" "\nEstimates the approximate priority a zero-fee transaction needs to begin\n" @@ -823,18 +823,18 @@ UniValue estimatepriority(const UniValue& params, bool fHelp) + HelpExampleCli("estimatepriority", "6") ); - RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM)); + RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VNUM)); - int nBlocks = params[0].get_int(); + int nBlocks = request.params[0].get_int(); if (nBlocks < 1) nBlocks = 1; return mempool.estimatePriority(nBlocks); } -UniValue estimatesmartfee(const UniValue& params, bool fHelp) +UniValue estimatesmartfee(const JSONRPCRequest& request) { - if (fHelp || params.size() != 1) + if (request.fHelp || request.params.size() != 1) throw runtime_error( "estimatesmartfee nblocks\n" "\nWARNING: This interface is unstable and may disappear or change!\n" @@ -856,9 +856,9 @@ UniValue estimatesmartfee(const UniValue& params, bool fHelp) + HelpExampleCli("estimatesmartfee", "6") ); - RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM)); + RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VNUM)); - int nBlocks = params[0].get_int(); + int nBlocks = request.params[0].get_int(); UniValue result(UniValue::VOBJ); int answerFound; @@ -868,9 +868,9 @@ UniValue estimatesmartfee(const UniValue& params, bool fHelp) return result; } -UniValue estimatesmartpriority(const UniValue& params, bool fHelp) +UniValue estimatesmartpriority(const JSONRPCRequest& request) { - if (fHelp || params.size() != 1) + if (request.fHelp || request.params.size() != 1) throw runtime_error( "estimatesmartpriority nblocks\n" "\nWARNING: This interface is unstable and may disappear or change!\n" @@ -892,9 +892,9 @@ UniValue estimatesmartpriority(const UniValue& params, bool fHelp) + HelpExampleCli("estimatesmartpriority", "6") ); - RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM)); + RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VNUM)); - int nBlocks = params[0].get_int(); + int nBlocks = request.params[0].get_int(); UniValue result(UniValue::VOBJ); int answerFound; diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 6bbb3925ddece..eaef4856b3c5e 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -39,9 +39,9 @@ using namespace std; * * Or alternatively, create a specific query method for the information. **/ -UniValue getinfo(const UniValue& params, bool fHelp) +UniValue getinfo(const JSONRPCRequest& request) { - if (fHelp || params.size() != 0) + if (request.fHelp || request.params.size() != 0) throw runtime_error( "getinfo\n" "\nDEPRECATED. Returns an object containing various state info.\n" @@ -148,9 +148,9 @@ class DescribeAddressVisitor : public boost::static_visitor }; #endif -UniValue validateaddress(const UniValue& params, bool fHelp) +UniValue validateaddress(const JSONRPCRequest& request) { - if (fHelp || params.size() != 1) + if (request.fHelp || request.params.size() != 1) throw runtime_error( "validateaddress \"bitcoinaddress\"\n" "\nReturn information about the given bitcoin address.\n" @@ -181,7 +181,7 @@ UniValue validateaddress(const UniValue& params, bool fHelp) LOCK(cs_main); #endif - CBitcoinAddress address(params[0].get_str()); + CBitcoinAddress address(request.params[0].get_str()); bool isValid = address.IsValid(); UniValue ret(UniValue::VOBJ); @@ -278,9 +278,9 @@ CScript _createmultisig_redeemScript(const UniValue& params) return result; } -UniValue createmultisig(const UniValue& params, bool fHelp) +UniValue createmultisig(const JSONRPCRequest& request) { - if (fHelp || params.size() < 2 || params.size() > 2) + if (request.fHelp || request.params.size() < 2 || request.params.size() > 2) { string msg = "createmultisig nrequired [\"key\",...]\n" "\nCreates a multi-signature address with n signature of m keys required.\n" @@ -310,7 +310,7 @@ UniValue createmultisig(const UniValue& params, bool fHelp) } // Construct using pay-to-script-hash: - CScript inner = _createmultisig_redeemScript(params); + CScript inner = _createmultisig_redeemScript(request.params); CScriptID innerID(inner); CBitcoinAddress address(innerID); @@ -321,9 +321,9 @@ UniValue createmultisig(const UniValue& params, bool fHelp) return result; } -UniValue verifymessage(const UniValue& params, bool fHelp) +UniValue verifymessage(const JSONRPCRequest& request) { - if (fHelp || params.size() != 3) + if (request.fHelp || request.params.size() != 3) throw runtime_error( "verifymessage \"bitcoinaddress\" \"signature\" \"message\"\n" "\nVerify a signed message\n" @@ -346,9 +346,9 @@ UniValue verifymessage(const UniValue& params, bool fHelp) LOCK(cs_main); - string strAddress = params[0].get_str(); - string strSign = params[1].get_str(); - string strMessage = params[2].get_str(); + string strAddress = request.params[0].get_str(); + string strSign = request.params[1].get_str(); + string strMessage = request.params[2].get_str(); CBitcoinAddress addr(strAddress); if (!addr.IsValid()) @@ -375,9 +375,9 @@ UniValue verifymessage(const UniValue& params, bool fHelp) return (pubkey.GetID() == keyID); } -UniValue signmessagewithprivkey(const UniValue& params, bool fHelp) +UniValue signmessagewithprivkey(const JSONRPCRequest& request) { - if (fHelp || params.size() != 2) + if (request.fHelp || request.params.size() != 2) throw runtime_error( "signmessagewithprivkey \"privkey\" \"message\"\n" "\nSign a message with the private key of an address\n" @@ -395,8 +395,8 @@ UniValue signmessagewithprivkey(const UniValue& params, bool fHelp) + HelpExampleRpc("signmessagewithprivkey", "\"privkey\", \"my message\"") ); - string strPrivkey = params[0].get_str(); - string strMessage = params[1].get_str(); + string strPrivkey = request.params[0].get_str(); + string strMessage = request.params[1].get_str(); CBitcoinSecret vchSecret; bool fGood = vchSecret.SetString(strPrivkey); @@ -417,9 +417,9 @@ UniValue signmessagewithprivkey(const UniValue& params, bool fHelp) return EncodeBase64(&vchSig[0], vchSig.size()); } -UniValue setmocktime(const UniValue& params, bool fHelp) +UniValue setmocktime(const JSONRPCRequest& request) { - if (fHelp || params.size() != 1) + if (request.fHelp || request.params.size() != 1) throw runtime_error( "setmocktime timestamp\n" "\nSet the local time to given timestamp (-regtest only)\n" @@ -437,8 +437,8 @@ UniValue setmocktime(const UniValue& params, bool fHelp) // in a long time. LOCK(cs_main); - RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM)); - SetMockTime(params[0].get_int64()); + RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VNUM)); + SetMockTime(request.params[0].get_int64()); uint64_t t = GetTime(); if(g_connman) { diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index a8442d86929b7..2b43f08f0be0a 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -23,9 +23,9 @@ using namespace std; -UniValue getconnectioncount(const UniValue& params, bool fHelp) +UniValue getconnectioncount(const JSONRPCRequest& request) { - if (fHelp || params.size() != 0) + if (request.fHelp || request.params.size() != 0) throw runtime_error( "getconnectioncount\n" "\nReturns the number of connections to other nodes.\n" @@ -42,9 +42,9 @@ UniValue getconnectioncount(const UniValue& params, bool fHelp) return (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL); } -UniValue ping(const UniValue& params, bool fHelp) +UniValue ping(const JSONRPCRequest& request) { - if (fHelp || params.size() != 0) + if (request.fHelp || request.params.size() != 0) throw runtime_error( "ping\n" "\nRequests that a ping be sent to all other nodes, to measure ping time.\n" @@ -65,9 +65,9 @@ UniValue ping(const UniValue& params, bool fHelp) return NullUniValue; } -UniValue getpeerinfo(const UniValue& params, bool fHelp) +UniValue getpeerinfo(const JSONRPCRequest& request) { - if (fHelp || params.size() != 0) + if (request.fHelp || request.params.size() != 0) throw runtime_error( "getpeerinfo\n" "\nReturns data about each connected network node as a json array of objects.\n" @@ -184,12 +184,12 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp) return ret; } -UniValue addnode(const UniValue& params, bool fHelp) +UniValue addnode(const JSONRPCRequest& request) { string strCommand; - if (params.size() == 2) - strCommand = params[1].get_str(); - if (fHelp || params.size() != 2 || + if (request.params.size() == 2) + strCommand = request.params[1].get_str(); + if (request.fHelp || request.params.size() != 2 || (strCommand != "onetry" && strCommand != "add" && strCommand != "remove")) throw runtime_error( "addnode \"node\" \"add|remove|onetry\"\n" @@ -206,7 +206,7 @@ UniValue addnode(const UniValue& params, bool fHelp) if(!g_connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); - string strNode = params[0].get_str(); + string strNode = request.params[0].get_str(); if (strCommand == "onetry") { @@ -229,9 +229,9 @@ UniValue addnode(const UniValue& params, bool fHelp) return NullUniValue; } -UniValue disconnectnode(const UniValue& params, bool fHelp) +UniValue disconnectnode(const JSONRPCRequest& request) { - if (fHelp || params.size() != 1) + if (request.fHelp || request.params.size() != 1) throw runtime_error( "disconnectnode \"node\" \n" "\nImmediately disconnects from the specified node.\n" @@ -245,16 +245,16 @@ UniValue disconnectnode(const UniValue& params, bool fHelp) if(!g_connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); - bool ret = g_connman->DisconnectNode(params[0].get_str()); + bool ret = g_connman->DisconnectNode(request.params[0].get_str()); if (!ret) throw JSONRPCError(RPC_CLIENT_NODE_NOT_CONNECTED, "Node not found in connected nodes"); return NullUniValue; } -UniValue getaddednodeinfo(const UniValue& params, bool fHelp) +UniValue getaddednodeinfo(const JSONRPCRequest& request) { - if (fHelp || params.size() > 1) + if (request.fHelp || request.params.size() > 1) throw runtime_error( "getaddednodeinfo ( \"node\" )\n" "\nReturns information about the given added node, or all added nodes\n" @@ -286,10 +286,10 @@ UniValue getaddednodeinfo(const UniValue& params, bool fHelp) std::vector vInfo = g_connman->GetAddedNodeInfo(); - if (params.size() == 1) { + if (request.params.size() == 1) { bool found = false; for (const AddedNodeInfo& info : vInfo) { - if (info.strAddedNode == params[0].get_str()) { + if (info.strAddedNode == request.params[0].get_str()) { vInfo.assign(1, info); found = true; break; @@ -320,9 +320,9 @@ UniValue getaddednodeinfo(const UniValue& params, bool fHelp) return ret; } -UniValue getnettotals(const UniValue& params, bool fHelp) +UniValue getnettotals(const JSONRPCRequest& request) { - if (fHelp || params.size() > 0) + if (request.fHelp || request.params.size() > 0) throw runtime_error( "getnettotals\n" "\nReturns information about network traffic, including bytes in, bytes out,\n" @@ -386,9 +386,9 @@ static UniValue GetNetworksInfo() return networks; } -UniValue getnetworkinfo(const UniValue& params, bool fHelp) +UniValue getnetworkinfo(const JSONRPCRequest& request) { - if (fHelp || params.size() != 0) + if (request.fHelp || request.params.size() != 0) throw runtime_error( "getnetworkinfo\n" "Returns an object containing various state info regarding P2P networking.\n" @@ -456,12 +456,12 @@ UniValue getnetworkinfo(const UniValue& params, bool fHelp) return obj; } -UniValue setban(const UniValue& params, bool fHelp) +UniValue setban(const JSONRPCRequest& request) { string strCommand; - if (params.size() >= 2) - strCommand = params[1].get_str(); - if (fHelp || params.size() < 2 || + if (request.params.size() >= 2) + strCommand = request.params[1].get_str(); + if (request.fHelp || request.params.size() < 2 || (strCommand != "add" && strCommand != "remove")) throw runtime_error( "setban \"ip(/netmask)\" \"add|remove\" (bantime) (absolute)\n" @@ -483,16 +483,16 @@ UniValue setban(const UniValue& params, bool fHelp) CNetAddr netAddr; bool isSubnet = false; - if (params[0].get_str().find("/") != string::npos) + if (request.params[0].get_str().find("/") != string::npos) isSubnet = true; if (!isSubnet) { CNetAddr resolved; - LookupHost(params[0].get_str().c_str(), resolved, false); + LookupHost(request.params[0].get_str().c_str(), resolved, false); netAddr = resolved; } else - LookupSubNet(params[0].get_str().c_str(), subNet); + LookupSubNet(request.params[0].get_str().c_str(), subNet); if (! (isSubnet ? subNet.IsValid() : netAddr.IsValid()) ) throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Invalid IP/Subnet"); @@ -503,11 +503,11 @@ UniValue setban(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned"); int64_t banTime = 0; //use standard bantime if not specified - if (params.size() >= 3 && !params[2].isNull()) - banTime = params[2].get_int64(); + if (request.params.size() >= 3 && !request.params[2].isNull()) + banTime = request.params[2].get_int64(); bool absolute = false; - if (params.size() == 4 && params[3].isTrue()) + if (request.params.size() == 4 && request.params[3].isTrue()) absolute = true; isSubnet ? g_connman->Ban(subNet, BanReasonManuallyAdded, banTime, absolute) : g_connman->Ban(netAddr, BanReasonManuallyAdded, banTime, absolute); @@ -520,9 +520,9 @@ UniValue setban(const UniValue& params, bool fHelp) return NullUniValue; } -UniValue listbanned(const UniValue& params, bool fHelp) +UniValue listbanned(const JSONRPCRequest& request) { - if (fHelp || params.size() != 0) + if (request.fHelp || request.params.size() != 0) throw runtime_error( "listbanned\n" "\nList all banned IPs/Subnets.\n" @@ -553,9 +553,9 @@ UniValue listbanned(const UniValue& params, bool fHelp) return bannedAddresses; } -UniValue clearbanned(const UniValue& params, bool fHelp) +UniValue clearbanned(const JSONRPCRequest& request) { - if (fHelp || params.size() != 0) + if (request.fHelp || request.params.size() != 0) throw runtime_error( "clearbanned\n" "\nClear all banned IPs.\n" diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 2ea65b8e99ac4..0656a61755382 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -126,9 +126,9 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) } } -UniValue getrawtransaction(const UniValue& params, bool fHelp) +UniValue getrawtransaction(const JSONRPCRequest& request) { - if (fHelp || params.size() < 1 || params.size() > 2) + if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw runtime_error( "getrawtransaction \"txid\" ( verbose )\n" "\nNOTE: By default this function only works sometimes. This is when the tx is in the mempool\n" @@ -198,11 +198,11 @@ UniValue getrawtransaction(const UniValue& params, bool fHelp) LOCK(cs_main); - uint256 hash = ParseHashV(params[0], "parameter 1"); + uint256 hash = ParseHashV(request.params[0], "parameter 1"); bool fVerbose = false; - if (params.size() > 1) - fVerbose = (params[1].get_int() != 0); + if (request.params.size() > 1) + fVerbose = (request.params[1].get_int() != 0); CTransaction tx; uint256 hashBlock; @@ -220,9 +220,9 @@ UniValue getrawtransaction(const UniValue& params, bool fHelp) return result; } -UniValue gettxoutproof(const UniValue& params, bool fHelp) +UniValue gettxoutproof(const JSONRPCRequest& request) { - if (fHelp || (params.size() != 1 && params.size() != 2)) + if (request.fHelp || (request.params.size() != 1 && request.params.size() != 2)) throw runtime_error( "gettxoutproof [\"txid\",...] ( blockhash )\n" "\nReturns a hex-encoded proof that \"txid\" was included in a block.\n" @@ -244,7 +244,7 @@ UniValue gettxoutproof(const UniValue& params, bool fHelp) set setTxids; uint256 oneTxid; - UniValue txids = params[0].get_array(); + UniValue txids = request.params[0].get_array(); for (unsigned int idx = 0; idx < txids.size(); idx++) { const UniValue& txid = txids[idx]; if (txid.get_str().length() != 64 || !IsHex(txid.get_str())) @@ -261,9 +261,9 @@ UniValue gettxoutproof(const UniValue& params, bool fHelp) CBlockIndex* pblockindex = NULL; uint256 hashBlock; - if (params.size() > 1) + if (request.params.size() > 1) { - hashBlock = uint256S(params[1].get_str()); + hashBlock = uint256S(request.params[1].get_str()); if (!mapBlockIndex.count(hashBlock)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); pblockindex = mapBlockIndex[hashBlock]; @@ -301,9 +301,9 @@ UniValue gettxoutproof(const UniValue& params, bool fHelp) return strHex; } -UniValue verifytxoutproof(const UniValue& params, bool fHelp) +UniValue verifytxoutproof(const JSONRPCRequest& request) { - if (fHelp || params.size() != 1) + if (request.fHelp || request.params.size() != 1) throw runtime_error( "verifytxoutproof \"proof\"\n" "\nVerifies that a proof points to a transaction in a block, returning the transaction it commits to\n" @@ -314,7 +314,7 @@ UniValue verifytxoutproof(const UniValue& params, bool fHelp) "[\"txid\"] (array, strings) The txid(s) which the proof commits to, or empty array if the proof is invalid\n" ); - CDataStream ssMB(ParseHexV(params[0], "proof"), SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS); + CDataStream ssMB(ParseHexV(request.params[0], "proof"), SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS); CMerkleBlock merkleBlock; ssMB >> merkleBlock; @@ -335,9 +335,9 @@ UniValue verifytxoutproof(const UniValue& params, bool fHelp) return res; } -UniValue createrawtransaction(const UniValue& params, bool fHelp) +UniValue createrawtransaction(const JSONRPCRequest& request) { - if (fHelp || params.size() < 2 || params.size() > 3) + if (request.fHelp || request.params.size() < 2 || request.params.size() > 3) throw runtime_error( "createrawtransaction [{\"txid\":\"id\",\"vout\":n},...] {\"address\":amount,\"data\":\"hex\",...} ( locktime )\n" "\nCreate a transaction spending the given inputs and creating new outputs.\n" @@ -373,17 +373,17 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp) + HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"{\\\"data\\\":\\\"00010203\\\"}\"") ); - RPCTypeCheck(params, boost::assign::list_of(UniValue::VARR)(UniValue::VOBJ)(UniValue::VNUM), true); - if (params[0].isNull() || params[1].isNull()) + RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VARR)(UniValue::VOBJ)(UniValue::VNUM), true); + if (request.params[0].isNull() || request.params[1].isNull()) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, arguments 1 and 2 must be non-null"); - UniValue inputs = params[0].get_array(); - UniValue sendTo = params[1].get_obj(); + UniValue inputs = request.params[0].get_array(); + UniValue sendTo = request.params[1].get_obj(); CMutableTransaction rawTx; - if (params.size() > 2 && !params[2].isNull()) { - int64_t nLockTime = params[2].get_int64(); + if (request.params.size() > 2 && !request.params[2].isNull()) { + int64_t nLockTime = request.params[2].get_int64(); if (nLockTime < 0 || nLockTime > std::numeric_limits::max()) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, locktime out of range"); rawTx.nLockTime = nLockTime; @@ -448,9 +448,9 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp) return EncodeHexTx(rawTx); } -UniValue decoderawtransaction(const UniValue& params, bool fHelp) +UniValue decoderawtransaction(const JSONRPCRequest& request) { - if (fHelp || params.size() != 1) + if (request.fHelp || request.params.size() != 1) throw runtime_error( "decoderawtransaction \"hexstring\"\n" "\nReturn a JSON object representing the serialized, hex-encoded transaction.\n" @@ -504,11 +504,11 @@ UniValue decoderawtransaction(const UniValue& params, bool fHelp) ); LOCK(cs_main); - RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)); + RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)); CTransaction tx; - if (!DecodeHexTx(tx, params[0].get_str(), true)) + if (!DecodeHexTx(tx, request.params[0].get_str(), true)) throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); UniValue result(UniValue::VOBJ); @@ -517,9 +517,9 @@ UniValue decoderawtransaction(const UniValue& params, bool fHelp) return result; } -UniValue decodescript(const UniValue& params, bool fHelp) +UniValue decodescript(const JSONRPCRequest& request) { - if (fHelp || params.size() != 1) + if (request.fHelp || request.params.size() != 1) throw runtime_error( "decodescript \"hex\"\n" "\nDecode a hex-encoded script.\n" @@ -542,12 +542,12 @@ UniValue decodescript(const UniValue& params, bool fHelp) + HelpExampleRpc("decodescript", "\"hexstring\"") ); - RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)); + RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)); UniValue r(UniValue::VOBJ); CScript script; - if (params[0].get_str().size() > 0){ - vector scriptData(ParseHexV(params[0], "argument")); + if (request.params[0].get_str().size() > 0){ + vector scriptData(ParseHexV(request.params[0], "argument")); script = CScript(scriptData.begin(), scriptData.end()); } else { // Empty scripts are valid @@ -578,9 +578,9 @@ static void TxInErrorToJSON(const CTxIn& txin, UniValue& vErrorsRet, const std:: vErrorsRet.push_back(entry); } -UniValue signrawtransaction(const UniValue& params, bool fHelp) +UniValue signrawtransaction(const JSONRPCRequest& request) { - if (fHelp || params.size() < 1 || params.size() > 4) + if (request.fHelp || request.params.size() < 1 || request.params.size() > 4) throw runtime_error( "signrawtransaction \"hexstring\" ( [{\"txid\":\"id\",\"vout\":n,\"scriptPubKey\":\"hex\",\"redeemScript\":\"hex\"},...] [\"privatekey1\",...] sighashtype )\n" "\nSign inputs for raw transaction (serialized, hex-encoded).\n" @@ -644,9 +644,9 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp) #else LOCK(cs_main); #endif - RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VARR)(UniValue::VARR)(UniValue::VSTR), true); + RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)(UniValue::VARR)(UniValue::VARR)(UniValue::VSTR), true); - vector txData(ParseHexV(params[0], "argument 1")); + vector txData(ParseHexV(request.params[0], "argument 1")); CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION); vector txVariants; while (!ssData.empty()) { @@ -687,9 +687,9 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp) bool fGivenKeys = false; CBasicKeyStore tempKeystore; - if (params.size() > 2 && !params[2].isNull()) { + if (request.params.size() > 2 && !request.params[2].isNull()) { fGivenKeys = true; - UniValue keys = params[2].get_array(); + UniValue keys = request.params[2].get_array(); for (unsigned int idx = 0; idx < keys.size(); idx++) { UniValue k = keys[idx]; CBitcoinSecret vchSecret; @@ -708,8 +708,8 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp) #endif // Add previous txouts given in the RPC call: - if (params.size() > 1 && !params[1].isNull()) { - UniValue prevTxs = params[1].get_array(); + if (request.params.size() > 1 && !request.params[1].isNull()) { + UniValue prevTxs = request.params[1].get_array(); for (unsigned int idx = 0; idx < prevTxs.size(); idx++) { const UniValue& p = prevTxs[idx]; if (!p.isObject()) @@ -777,7 +777,7 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp) #endif int nHashType = SIGHASH_ALL; - if (params.size() > 3 && !params[3].isNull()) { + if (request.params.size() > 3 && !request.params[3].isNull()) { static map mapSigHashValues = boost::assign::map_list_of (string("ALL"), int(SIGHASH_ALL)) @@ -787,7 +787,7 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp) (string("SINGLE"), int(SIGHASH_SINGLE)) (string("SINGLE|ANYONECANPAY"), int(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY)) ; - string strHashType = params[3].get_str(); + string strHashType = request.params[3].get_str(); if (mapSigHashValues.count(strHashType)) nHashType = mapSigHashValues[strHashType]; else @@ -842,9 +842,9 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp) return result; } -UniValue sendrawtransaction(const UniValue& params, bool fHelp) +UniValue sendrawtransaction(const JSONRPCRequest& request) { - if (fHelp || params.size() < 1 || params.size() > 2) + if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw runtime_error( "sendrawtransaction \"hexstring\" ( allowhighfees )\n" "\nSubmits raw transaction (serialized, hex-encoded) to local node and network.\n" @@ -866,17 +866,17 @@ UniValue sendrawtransaction(const UniValue& params, bool fHelp) ); LOCK(cs_main); - RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VBOOL)); + RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)(UniValue::VBOOL)); // parse hex string from parameter CTransaction tx; - if (!DecodeHexTx(tx, params[0].get_str())) + if (!DecodeHexTx(tx, request.params[0].get_str())) throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); uint256 hashTx = tx.GetHash(); bool fLimitFree = false; CAmount nMaxRawTxFee = maxTxFee; - if (params.size() > 1 && params[1].get_bool()) + if (request.params.size() > 1 && request.params[1].get_bool()) nMaxRawTxFee = 0; CCoinsViewCache &view = *pcoinsTip; diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 5fb97f7496217..29d0bee1b2789 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -195,10 +195,11 @@ std::string CRPCTable::help(const std::string& strCommand) const continue; try { - UniValue params; + JSONRPCRequest jreq; + jreq.fHelp = true; rpcfn_type pfn = pcmd->actor; if (setDone.insert(pfn).second) - (*pfn)(params, true); + (*pfn)(jreq); } catch (const std::exception& e) { @@ -228,9 +229,9 @@ std::string CRPCTable::help(const std::string& strCommand) const return strRet; } -UniValue help(const UniValue& params, bool fHelp) +UniValue help(const JSONRPCRequest& jsonRequest) { - if (fHelp || params.size() > 1) + if (jsonRequest.fHelp || jsonRequest.params.size() > 1) throw runtime_error( "help ( \"command\" )\n" "\nList all commands, or get help for a specified command.\n" @@ -241,17 +242,17 @@ UniValue help(const UniValue& params, bool fHelp) ); string strCommand; - if (params.size() > 0) - strCommand = params[0].get_str(); + if (jsonRequest.params.size() > 0) + strCommand = jsonRequest.params[0].get_str(); return tableRPC.help(strCommand); } -UniValue stop(const UniValue& params, bool fHelp) +UniValue stop(const JSONRPCRequest& jsonRequest) { // Accept the deprecated and ignored 'detach' boolean argument - if (fHelp || params.size() > 1) + if (jsonRequest.fHelp || jsonRequest.params.size() > 1) throw runtime_error( "stop\n" "\nStop Bitcoin server."); @@ -354,7 +355,7 @@ bool RPCIsInWarmup(std::string *outStatus) return fRPCInWarmup; } -void JSONRequest::parse(const UniValue& valRequest) +void JSONRPCRequest::parse(const UniValue& valRequest) { // Parse request if (!valRequest.isObject()) @@ -388,11 +389,11 @@ static UniValue JSONRPCExecOne(const UniValue& req) { UniValue rpc_result(UniValue::VOBJ); - JSONRequest jreq; + JSONRPCRequest jreq; try { jreq.parse(req); - UniValue result = tableRPC.execute(jreq.strMethod, jreq.params); + UniValue result = tableRPC.execute(jreq); rpc_result = JSONRPCReplyObj(result, NullUniValue, jreq.id); } catch (const UniValue& objError) @@ -417,7 +418,7 @@ std::string JSONRPCExecBatch(const UniValue& vReq) return ret.write() + "\n"; } -UniValue CRPCTable::execute(const std::string &strMethod, const UniValue ¶ms) const +UniValue CRPCTable::execute(const JSONRPCRequest &request) const { // Return immediately if in warmup { @@ -427,7 +428,7 @@ UniValue CRPCTable::execute(const std::string &strMethod, const UniValue ¶ms } // Find method - const CRPCCommand *pcmd = tableRPC[strMethod]; + const CRPCCommand *pcmd = tableRPC[request.strMethod]; if (!pcmd) throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found"); @@ -436,7 +437,7 @@ UniValue CRPCTable::execute(const std::string &strMethod, const UniValue ¶ms try { // Execute - return pcmd->actor(params, false); + return pcmd->actor(request); } catch (const std::exception& e) { diff --git a/src/rpc/server.h b/src/rpc/server.h index 4e0aa2c6d6f6f..d8b5097035c91 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -41,14 +41,16 @@ struct UniValueType { UniValue::VType type; }; -class JSONRequest +class JSONRPCRequest { public: UniValue id; std::string strMethod; UniValue params; + bool fHelp; + std::string URI; - JSONRequest() { id = NullUniValue; } + JSONRPCRequest() { id = NullUniValue; } void parse(const UniValue& valRequest); }; @@ -122,7 +124,7 @@ void RPCUnsetTimerInterface(RPCTimerInterface *iface); */ void RPCRunLater(const std::string& name, boost::function func, int64_t nSeconds); -typedef UniValue(*rpcfn_type)(const UniValue& params, bool fHelp); +typedef UniValue(*rpcfn_type)(const JSONRPCRequest& jsonRequest); class CRPCCommand { @@ -147,12 +149,11 @@ class CRPCTable /** * Execute a method. - * @param method Method to execute - * @param params UniValue Array of arguments (JSON objects) + * @param request The JSONRPCRequest to execute * @returns Result of the call. * @throws an exception (UniValue) when an error happens. */ - UniValue execute(const std::string &method, const UniValue ¶ms) const; + UniValue execute(const JSONRPCRequest &request) const; /** * Returns a list of registered commands diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index a15915aad2f10..a3d1a2558904d 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -24,11 +24,14 @@ UniValue CallRPC(string args) boost::split(vArgs, args, boost::is_any_of(" \t")); string strMethod = vArgs[0]; vArgs.erase(vArgs.begin()); - UniValue params = RPCConvertValues(strMethod, vArgs); + JSONRPCRequest request; + request.strMethod = strMethod; + request.params = RPCConvertValues(strMethod, vArgs); + request.fHelp = false; BOOST_CHECK(tableRPC[strMethod]); rpcfn_type method = tableRPC[strMethod]->actor; try { - UniValue result = (*method)(params, false); + UniValue result = (*method)(request); return result; } catch (const UniValue& objError) { diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index e80fa7dff81d8..8a1bbd5684526 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -74,12 +74,12 @@ std::string DecodeDumpString(const std::string &str) { return ret.str(); } -UniValue importprivkey(const UniValue& params, bool fHelp) +UniValue importprivkey(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() < 1 || params.size() > 3) + if (request.fHelp || request.params.size() < 1 || request.params.size() > 3) throw runtime_error( "importprivkey \"bitcoinprivkey\" ( \"label\" rescan )\n" "\nAdds a private key (as returned by dumpprivkey) to your wallet.\n" @@ -104,15 +104,15 @@ UniValue importprivkey(const UniValue& params, bool fHelp) EnsureWalletIsUnlocked(); - string strSecret = params[0].get_str(); + string strSecret = request.params[0].get_str(); string strLabel = ""; - if (params.size() > 1) - strLabel = params[1].get_str(); + if (request.params.size() > 1) + strLabel = request.params[1].get_str(); // Whether to perform rescan after import bool fRescan = true; - if (params.size() > 2) - fRescan = params[2].get_bool(); + if (request.params.size() > 2) + fRescan = request.params[2].get_bool(); if (fRescan && fPruneMode) throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode"); @@ -184,12 +184,12 @@ void ImportAddress(const CBitcoinAddress& address, const string& strLabel) pwalletMain->SetAddressBook(address.Get(), strLabel, "receive"); } -UniValue importaddress(const UniValue& params, bool fHelp) +UniValue importaddress(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() < 1 || params.size() > 4) + if (request.fHelp || request.params.size() < 1 || request.params.size() > 4) throw runtime_error( "importaddress \"address\" ( \"label\" rescan p2sh )\n" "\nAdds a script (in hex) or address that can be watched as if it were in your wallet but cannot be used to spend.\n" @@ -213,31 +213,31 @@ UniValue importaddress(const UniValue& params, bool fHelp) string strLabel = ""; - if (params.size() > 1) - strLabel = params[1].get_str(); + if (request.params.size() > 1) + strLabel = request.params[1].get_str(); // Whether to perform rescan after import bool fRescan = true; - if (params.size() > 2) - fRescan = params[2].get_bool(); + if (request.params.size() > 2) + fRescan = request.params[2].get_bool(); if (fRescan && fPruneMode) throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode"); // Whether to import a p2sh version, too bool fP2SH = false; - if (params.size() > 3) - fP2SH = params[3].get_bool(); + if (request.params.size() > 3) + fP2SH = request.params[3].get_bool(); LOCK2(cs_main, pwalletMain->cs_wallet); - CBitcoinAddress address(params[0].get_str()); + CBitcoinAddress address(request.params[0].get_str()); if (address.IsValid()) { if (fP2SH) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Cannot use the p2sh flag with an address - use a script instead"); ImportAddress(address, strLabel); - } else if (IsHex(params[0].get_str())) { - std::vector data(ParseHex(params[0].get_str())); + } else if (IsHex(request.params[0].get_str())) { + std::vector data(ParseHex(request.params[0].get_str())); ImportScript(CScript(data.begin(), data.end()), strLabel, fP2SH); } else { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address or script"); @@ -252,12 +252,12 @@ UniValue importaddress(const UniValue& params, bool fHelp) return NullUniValue; } -UniValue importprunedfunds(const UniValue& params, bool fHelp) +UniValue importprunedfunds(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() != 2) + if (request.fHelp || request.params.size() != 2) throw runtime_error( "importprunedfunds\n" "\nImports funds without rescan. Corresponding address or script must previously be included in wallet. Aimed towards pruned wallets. The end-user is responsible to import additional transactions that subsequently spend the imported outputs or rescan after the point in the blockchain the transaction is included.\n" @@ -267,12 +267,12 @@ UniValue importprunedfunds(const UniValue& params, bool fHelp) ); CTransaction tx; - if (!DecodeHexTx(tx, params[0].get_str())) + if (!DecodeHexTx(tx, request.params[0].get_str())) throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); uint256 hashTx = tx.GetHash(); CWalletTx wtx(pwalletMain,tx); - CDataStream ssMB(ParseHexV(params[1], "proof"), SER_NETWORK, PROTOCOL_VERSION); + CDataStream ssMB(ParseHexV(request.params[1], "proof"), SER_NETWORK, PROTOCOL_VERSION); CMerkleBlock merkleBlock; ssMB >> merkleBlock; @@ -311,12 +311,12 @@ UniValue importprunedfunds(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No addresses in wallet correspond to included transaction"); } -UniValue removeprunedfunds(const UniValue& params, bool fHelp) +UniValue removeprunedfunds(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() != 1) + if (request.fHelp || request.params.size() != 1) throw runtime_error( "removeprunedfunds \"txid\"\n" "\nDeletes the specified transaction from the wallet. Meant for use with pruned wallets and as a companion to importprunedfunds. This will effect wallet balances.\n" @@ -331,7 +331,7 @@ UniValue removeprunedfunds(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); uint256 hash; - hash.SetHex(params[0].get_str()); + hash.SetHex(request.params[0].get_str()); vector vHash; vHash.push_back(hash); vector vHashOut; @@ -347,12 +347,12 @@ UniValue removeprunedfunds(const UniValue& params, bool fHelp) return NullUniValue; } -UniValue importpubkey(const UniValue& params, bool fHelp) +UniValue importpubkey(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() < 1 || params.size() > 4) + if (request.fHelp || request.params.size() < 1 || request.params.size() > 4) throw runtime_error( "importpubkey \"pubkey\" ( \"label\" rescan )\n" "\nAdds a public key (in hex) that can be watched as if it were in your wallet but cannot be used to spend.\n" @@ -372,20 +372,20 @@ UniValue importpubkey(const UniValue& params, bool fHelp) string strLabel = ""; - if (params.size() > 1) - strLabel = params[1].get_str(); + if (request.params.size() > 1) + strLabel = request.params[1].get_str(); // Whether to perform rescan after import bool fRescan = true; - if (params.size() > 2) - fRescan = params[2].get_bool(); + if (request.params.size() > 2) + fRescan = request.params[2].get_bool(); if (fRescan && fPruneMode) throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode"); - if (!IsHex(params[0].get_str())) + if (!IsHex(request.params[0].get_str())) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey must be a hex string"); - std::vector data(ParseHex(params[0].get_str())); + std::vector data(ParseHex(request.params[0].get_str())); CPubKey pubKey(data.begin(), data.end()); if (!pubKey.IsFullyValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey is not a valid public key"); @@ -405,12 +405,12 @@ UniValue importpubkey(const UniValue& params, bool fHelp) } -UniValue importwallet(const UniValue& params, bool fHelp) +UniValue importwallet(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() != 1) + if (request.fHelp || request.params.size() != 1) throw runtime_error( "importwallet \"filename\"\n" "\nImports keys from a wallet dump file (see dumpwallet).\n" @@ -433,7 +433,7 @@ UniValue importwallet(const UniValue& params, bool fHelp) EnsureWalletIsUnlocked(); ifstream file; - file.open(params[0].get_str().c_str(), std::ios::in | std::ios::ate); + file.open(request.params[0].get_str().c_str(), std::ios::in | std::ios::ate); if (!file.is_open()) throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file"); @@ -512,12 +512,12 @@ UniValue importwallet(const UniValue& params, bool fHelp) return NullUniValue; } -UniValue dumpprivkey(const UniValue& params, bool fHelp) +UniValue dumpprivkey(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() != 1) + if (request.fHelp || request.params.size() != 1) throw runtime_error( "dumpprivkey \"bitcoinaddress\"\n" "\nReveals the private key corresponding to 'bitcoinaddress'.\n" @@ -536,7 +536,7 @@ UniValue dumpprivkey(const UniValue& params, bool fHelp) EnsureWalletIsUnlocked(); - string strAddress = params[0].get_str(); + string strAddress = request.params[0].get_str(); CBitcoinAddress address; if (!address.SetString(strAddress)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); @@ -550,12 +550,12 @@ UniValue dumpprivkey(const UniValue& params, bool fHelp) } -UniValue dumpwallet(const UniValue& params, bool fHelp) +UniValue dumpwallet(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() != 1) + if (request.fHelp || request.params.size() != 1) throw runtime_error( "dumpwallet \"filename\"\n" "\nDumps all wallet keys in a human-readable format.\n" @@ -571,7 +571,7 @@ UniValue dumpwallet(const UniValue& params, bool fHelp) EnsureWalletIsUnlocked(); ofstream file; - file.open(params[0].get_str().c_str()); + file.open(request.params[0].get_str().c_str()); if (!file.is_open()) throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file"); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 8e95426d11bdf..33620aa6ff59e 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -101,12 +101,12 @@ string AccountFromValue(const UniValue& value) return strAccount; } -UniValue getnewaddress(const UniValue& params, bool fHelp) +UniValue getnewaddress(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() > 1) + if (request.fHelp || request.params.size() > 1) throw runtime_error( "getnewaddress ( \"account\" )\n" "\nReturns a new Bitcoin address for receiving payments.\n" @@ -125,8 +125,8 @@ UniValue getnewaddress(const UniValue& params, bool fHelp) // Parse the account first so we don't generate a key if there's an error string strAccount; - if (params.size() > 0) - strAccount = AccountFromValue(params[0]); + if (request.params.size() > 0) + strAccount = AccountFromValue(request.params[0]); if (!pwalletMain->IsLocked()) pwalletMain->TopUpKeyPool(); @@ -153,12 +153,12 @@ CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false) return CBitcoinAddress(pubKey.GetID()); } -UniValue getaccountaddress(const UniValue& params, bool fHelp) +UniValue getaccountaddress(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() != 1) + if (request.fHelp || request.params.size() != 1) throw runtime_error( "getaccountaddress \"account\"\n" "\nDEPRECATED. Returns the current Bitcoin address for receiving payments to this account.\n" @@ -176,7 +176,7 @@ UniValue getaccountaddress(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); // Parse the account first so we don't generate a key if there's an error - string strAccount = AccountFromValue(params[0]); + string strAccount = AccountFromValue(request.params[0]); UniValue ret(UniValue::VSTR); @@ -185,12 +185,12 @@ UniValue getaccountaddress(const UniValue& params, bool fHelp) } -UniValue getrawchangeaddress(const UniValue& params, bool fHelp) +UniValue getrawchangeaddress(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() > 1) + if (request.fHelp || request.params.size() > 1) throw runtime_error( "getrawchangeaddress\n" "\nReturns a new Bitcoin address, for receiving change.\n" @@ -220,12 +220,12 @@ UniValue getrawchangeaddress(const UniValue& params, bool fHelp) } -UniValue setaccount(const UniValue& params, bool fHelp) +UniValue setaccount(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() < 1 || params.size() > 2) + if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw runtime_error( "setaccount \"bitcoinaddress\" \"account\"\n" "\nDEPRECATED. Sets the account associated with the given address.\n" @@ -239,13 +239,13 @@ UniValue setaccount(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); - CBitcoinAddress address(params[0].get_str()); + CBitcoinAddress address(request.params[0].get_str()); if (!address.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); string strAccount; - if (params.size() > 1) - strAccount = AccountFromValue(params[1]); + if (request.params.size() > 1) + strAccount = AccountFromValue(request.params[1]); // Only add the account if the address is yours. if (IsMine(*pwalletMain, address.Get())) @@ -266,12 +266,12 @@ UniValue setaccount(const UniValue& params, bool fHelp) } -UniValue getaccount(const UniValue& params, bool fHelp) +UniValue getaccount(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() != 1) + if (request.fHelp || request.params.size() != 1) throw runtime_error( "getaccount \"bitcoinaddress\"\n" "\nDEPRECATED. Returns the account associated with the given address.\n" @@ -286,7 +286,7 @@ UniValue getaccount(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); - CBitcoinAddress address(params[0].get_str()); + CBitcoinAddress address(request.params[0].get_str()); if (!address.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); @@ -298,12 +298,12 @@ UniValue getaccount(const UniValue& params, bool fHelp) } -UniValue getaddressesbyaccount(const UniValue& params, bool fHelp) +UniValue getaddressesbyaccount(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() != 1) + if (request.fHelp || request.params.size() != 1) throw runtime_error( "getaddressesbyaccount \"account\"\n" "\nDEPRECATED. Returns the list of addresses for the given account.\n" @@ -321,7 +321,7 @@ UniValue getaddressesbyaccount(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); - string strAccount = AccountFromValue(params[0]); + string strAccount = AccountFromValue(request.params[0]); // Find all addresses that have the given account UniValue ret(UniValue::VARR); @@ -369,12 +369,12 @@ static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtr throw JSONRPCError(RPC_WALLET_ERROR, "Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of the wallet and coins were spent in the copy but not marked as spent here."); } -UniValue sendtoaddress(const UniValue& params, bool fHelp) +UniValue sendtoaddress(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() < 2 || params.size() > 5) + if (request.fHelp || request.params.size() < 2 || request.params.size() > 5) throw runtime_error( "sendtoaddress \"bitcoinaddress\" amount ( \"comment\" \"comment-to\" subtractfeefromamount )\n" "\nSend an amount to a given address.\n" @@ -400,25 +400,25 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); - CBitcoinAddress address(params[0].get_str()); + CBitcoinAddress address(request.params[0].get_str()); if (!address.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); // Amount - CAmount nAmount = AmountFromValue(params[1]); + CAmount nAmount = AmountFromValue(request.params[1]); if (nAmount <= 0) throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send"); // Wallet comments CWalletTx wtx; - if (params.size() > 2 && !params[2].isNull() && !params[2].get_str().empty()) - wtx.mapValue["comment"] = params[2].get_str(); - if (params.size() > 3 && !params[3].isNull() && !params[3].get_str().empty()) - wtx.mapValue["to"] = params[3].get_str(); + if (request.params.size() > 2 && !request.params[2].isNull() && !request.params[2].get_str().empty()) + wtx.mapValue["comment"] = request.params[2].get_str(); + if (request.params.size() > 3 && !request.params[3].isNull() && !request.params[3].get_str().empty()) + wtx.mapValue["to"] = request.params[3].get_str(); bool fSubtractFeeFromAmount = false; - if (params.size() > 4) - fSubtractFeeFromAmount = params[4].get_bool(); + if (request.params.size() > 4) + fSubtractFeeFromAmount = request.params[4].get_bool(); EnsureWalletIsUnlocked(); @@ -427,12 +427,12 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp) return wtx.GetHash().GetHex(); } -UniValue listaddressgroupings(const UniValue& params, bool fHelp) +UniValue listaddressgroupings(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp) + if (request.fHelp) throw runtime_error( "listaddressgroupings\n" "\nLists groups of addresses which have had their common ownership\n" @@ -478,12 +478,12 @@ UniValue listaddressgroupings(const UniValue& params, bool fHelp) return jsonGroupings; } -UniValue signmessage(const UniValue& params, bool fHelp) +UniValue signmessage(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() != 2) + if (request.fHelp || request.params.size() != 2) throw runtime_error( "signmessage \"bitcoinaddress\" \"message\"\n" "\nSign a message with the private key of an address" @@ -508,8 +508,8 @@ UniValue signmessage(const UniValue& params, bool fHelp) EnsureWalletIsUnlocked(); - string strAddress = params[0].get_str(); - string strMessage = params[1].get_str(); + string strAddress = request.params[0].get_str(); + string strMessage = request.params[1].get_str(); CBitcoinAddress addr(strAddress); if (!addr.IsValid()) @@ -534,12 +534,12 @@ UniValue signmessage(const UniValue& params, bool fHelp) return EncodeBase64(&vchSig[0], vchSig.size()); } -UniValue getreceivedbyaddress(const UniValue& params, bool fHelp) +UniValue getreceivedbyaddress(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() < 1 || params.size() > 2) + if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw runtime_error( "getreceivedbyaddress \"bitcoinaddress\" ( minconf )\n" "\nReturns the total amount received by the given bitcoinaddress in transactions with at least minconf confirmations.\n" @@ -562,7 +562,7 @@ UniValue getreceivedbyaddress(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); // Bitcoin address - CBitcoinAddress address = CBitcoinAddress(params[0].get_str()); + CBitcoinAddress address = CBitcoinAddress(request.params[0].get_str()); if (!address.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); CScript scriptPubKey = GetScriptForDestination(address.Get()); @@ -571,8 +571,8 @@ UniValue getreceivedbyaddress(const UniValue& params, bool fHelp) // Minimum confirmations int nMinDepth = 1; - if (params.size() > 1) - nMinDepth = params[1].get_int(); + if (request.params.size() > 1) + nMinDepth = request.params[1].get_int(); // Tally CAmount nAmount = 0; @@ -592,12 +592,12 @@ UniValue getreceivedbyaddress(const UniValue& params, bool fHelp) } -UniValue getreceivedbyaccount(const UniValue& params, bool fHelp) +UniValue getreceivedbyaccount(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() < 1 || params.size() > 2) + if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw runtime_error( "getreceivedbyaccount \"account\" ( minconf )\n" "\nDEPRECATED. Returns the total amount received by addresses with in transactions with at least [minconf] confirmations.\n" @@ -621,11 +621,11 @@ UniValue getreceivedbyaccount(const UniValue& params, bool fHelp) // Minimum confirmations int nMinDepth = 1; - if (params.size() > 1) - nMinDepth = params[1].get_int(); + if (request.params.size() > 1) + nMinDepth = request.params[1].get_int(); // Get the set of pub keys assigned to account - string strAccount = AccountFromValue(params[0]); + string strAccount = AccountFromValue(request.params[0]); set setAddress = pwalletMain->GetAccountAddresses(strAccount); // Tally @@ -649,12 +649,12 @@ UniValue getreceivedbyaccount(const UniValue& params, bool fHelp) } -UniValue getbalance(const UniValue& params, bool fHelp) +UniValue getbalance(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() > 3) + if (request.fHelp || request.params.size() > 3) throw runtime_error( "getbalance ( \"account\" minconf includeWatchonly )\n" "\nIf account is not specified, returns the server's total available balance.\n" @@ -678,18 +678,18 @@ UniValue getbalance(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); - if (params.size() == 0) + if (request.params.size() == 0) return ValueFromAmount(pwalletMain->GetBalance()); int nMinDepth = 1; - if (params.size() > 1) - nMinDepth = params[1].get_int(); + if (request.params.size() > 1) + nMinDepth = request.params[1].get_int(); isminefilter filter = ISMINE_SPENDABLE; - if(params.size() > 2) - if(params[2].get_bool()) + if(request.params.size() > 2) + if(request.params[2].get_bool()) filter = filter | ISMINE_WATCH_ONLY; - if (params[0].get_str() == "*") { + if (request.params[0].get_str() == "*") { // Calculate total balance a different way from GetBalance() // (GetBalance() sums up all unspent TxOuts) // getbalance and "getbalance * 1 true" should return the same number @@ -717,19 +717,19 @@ UniValue getbalance(const UniValue& params, bool fHelp) return ValueFromAmount(nBalance); } - string strAccount = AccountFromValue(params[0]); + string strAccount = AccountFromValue(request.params[0]); CAmount nBalance = pwalletMain->GetAccountBalance(strAccount, nMinDepth, filter); return ValueFromAmount(nBalance); } -UniValue getunconfirmedbalance(const UniValue ¶ms, bool fHelp) +UniValue getunconfirmedbalance(const JSONRPCRequest &request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() > 0) + if (request.fHelp || request.params.size() > 0) throw runtime_error( "getunconfirmedbalance\n" "Returns the server's total unconfirmed balance\n"); @@ -740,12 +740,12 @@ UniValue getunconfirmedbalance(const UniValue ¶ms, bool fHelp) } -UniValue movecmd(const UniValue& params, bool fHelp) +UniValue movecmd(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() < 3 || params.size() > 5) + if (request.fHelp || request.params.size() < 3 || request.params.size() > 5) throw runtime_error( "move \"fromaccount\" \"toaccount\" amount ( minconf \"comment\" )\n" "\nDEPRECATED. Move a specified amount from one account in your wallet to another.\n" @@ -768,17 +768,17 @@ UniValue movecmd(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); - string strFrom = AccountFromValue(params[0]); - string strTo = AccountFromValue(params[1]); - CAmount nAmount = AmountFromValue(params[2]); + string strFrom = AccountFromValue(request.params[0]); + string strTo = AccountFromValue(request.params[1]); + CAmount nAmount = AmountFromValue(request.params[2]); if (nAmount <= 0) throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send"); - if (params.size() > 3) + if (request.params.size() > 3) // unused parameter, used to be nMinDepth, keep type-checking it though - (void)params[3].get_int(); + (void)request.params[3].get_int(); string strComment; - if (params.size() > 4) - strComment = params[4].get_str(); + if (request.params.size() > 4) + strComment = request.params[4].get_str(); if (!pwalletMain->AccountMove(strFrom, strTo, nAmount, strComment)) throw JSONRPCError(RPC_DATABASE_ERROR, "database error"); @@ -787,12 +787,12 @@ UniValue movecmd(const UniValue& params, bool fHelp) } -UniValue sendfrom(const UniValue& params, bool fHelp) +UniValue sendfrom(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() < 3 || params.size() > 6) + if (request.fHelp || request.params.size() < 3 || request.params.size() > 6) throw runtime_error( "sendfrom \"fromaccount\" \"tobitcoinaddress\" amount ( minconf \"comment\" \"comment-to\" )\n" "\nDEPRECATED (use sendtoaddress). Sent an amount from an account to a bitcoin address." @@ -820,23 +820,23 @@ UniValue sendfrom(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); - string strAccount = AccountFromValue(params[0]); - CBitcoinAddress address(params[1].get_str()); + string strAccount = AccountFromValue(request.params[0]); + CBitcoinAddress address(request.params[1].get_str()); if (!address.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); - CAmount nAmount = AmountFromValue(params[2]); + CAmount nAmount = AmountFromValue(request.params[2]); if (nAmount <= 0) throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send"); int nMinDepth = 1; - if (params.size() > 3) - nMinDepth = params[3].get_int(); + if (request.params.size() > 3) + nMinDepth = request.params[3].get_int(); CWalletTx wtx; wtx.strFromAccount = strAccount; - if (params.size() > 4 && !params[4].isNull() && !params[4].get_str().empty()) - wtx.mapValue["comment"] = params[4].get_str(); - if (params.size() > 5 && !params[5].isNull() && !params[5].get_str().empty()) - wtx.mapValue["to"] = params[5].get_str(); + if (request.params.size() > 4 && !request.params[4].isNull() && !request.params[4].get_str().empty()) + wtx.mapValue["comment"] = request.params[4].get_str(); + if (request.params.size() > 5 && !request.params[5].isNull() && !request.params[5].get_str().empty()) + wtx.mapValue["to"] = request.params[5].get_str(); EnsureWalletIsUnlocked(); @@ -851,12 +851,12 @@ UniValue sendfrom(const UniValue& params, bool fHelp) } -UniValue sendmany(const UniValue& params, bool fHelp) +UniValue sendmany(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() < 2 || params.size() > 5) + if (request.fHelp || request.params.size() < 2 || request.params.size() > 5) throw runtime_error( "sendmany \"fromaccount\" {\"address\":amount,...} ( minconf \"comment\" [\"address\",...] )\n" "\nSend multiple times. Amounts are double-precision floating point numbers." @@ -897,20 +897,20 @@ UniValue sendmany(const UniValue& params, bool fHelp) if (pwalletMain->GetBroadcastTransactions() && !g_connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); - string strAccount = AccountFromValue(params[0]); - UniValue sendTo = params[1].get_obj(); + string strAccount = AccountFromValue(request.params[0]); + UniValue sendTo = request.params[1].get_obj(); int nMinDepth = 1; - if (params.size() > 2) - nMinDepth = params[2].get_int(); + if (request.params.size() > 2) + nMinDepth = request.params[2].get_int(); CWalletTx wtx; wtx.strFromAccount = strAccount; - if (params.size() > 3 && !params[3].isNull() && !params[3].get_str().empty()) - wtx.mapValue["comment"] = params[3].get_str(); + if (request.params.size() > 3 && !request.params[3].isNull() && !request.params[3].get_str().empty()) + wtx.mapValue["comment"] = request.params[3].get_str(); UniValue subtractFeeFromAmount(UniValue::VARR); - if (params.size() > 4) - subtractFeeFromAmount = params[4].get_array(); + if (request.params.size() > 4) + subtractFeeFromAmount = request.params[4].get_array(); set setAddress; vector vecSend; @@ -968,12 +968,12 @@ UniValue sendmany(const UniValue& params, bool fHelp) // Defined in rpc/misc.cpp extern CScript _createmultisig_redeemScript(const UniValue& params); -UniValue addmultisigaddress(const UniValue& params, bool fHelp) +UniValue addmultisigaddress(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() < 2 || params.size() > 3) + if (request.fHelp || request.params.size() < 2 || request.params.size() > 3) { string msg = "addmultisigaddress nrequired [\"key\",...] ( \"account\" )\n" "\nAdd a nrequired-to-sign multisignature address to the wallet.\n" @@ -1004,11 +1004,11 @@ UniValue addmultisigaddress(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); string strAccount; - if (params.size() > 2) - strAccount = AccountFromValue(params[2]); + if (request.params.size() > 2) + strAccount = AccountFromValue(request.params[2]); // Construct using pay-to-script-hash: - CScript inner = _createmultisig_redeemScript(params); + CScript inner = _createmultisig_redeemScript(request.params); CScriptID innerID(inner); pwalletMain->AddCScript(inner); @@ -1061,12 +1061,12 @@ class Witnessifier : public boost::static_visitor } }; -UniValue addwitnessaddress(const UniValue& params, bool fHelp) +UniValue addwitnessaddress(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() < 1 || params.size() > 1) + if (request.fHelp || request.params.size() < 1 || request.params.size() > 1) { string msg = "addwitnessaddress \"address\"\n" "\nAdd a witness address for a script (with pubkey or redeemscript known).\n" @@ -1089,7 +1089,7 @@ UniValue addwitnessaddress(const UniValue& params, bool fHelp) } } - CBitcoinAddress address(params[0].get_str()); + CBitcoinAddress address(request.params[0].get_str()); if (!address.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); @@ -1239,12 +1239,12 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts) return ret; } -UniValue listreceivedbyaddress(const UniValue& params, bool fHelp) +UniValue listreceivedbyaddress(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() > 3) + if (request.fHelp || request.params.size() > 3) throw runtime_error( "listreceivedbyaddress ( minconf includeempty includeWatchonly)\n" "\nList balances by receiving address.\n" @@ -1274,15 +1274,15 @@ UniValue listreceivedbyaddress(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); - return ListReceived(params, false); + return ListReceived(request.params, false); } -UniValue listreceivedbyaccount(const UniValue& params, bool fHelp) +UniValue listreceivedbyaccount(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() > 3) + if (request.fHelp || request.params.size() > 3) throw runtime_error( "listreceivedbyaccount ( minconf includeempty includeWatchonly)\n" "\nDEPRECATED. List balances by account.\n" @@ -1311,7 +1311,7 @@ UniValue listreceivedbyaccount(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); - return ListReceived(params, true); + return ListReceived(request.params, true); } static void MaybePushAddress(UniValue & entry, const CTxDestination &dest) @@ -1413,12 +1413,12 @@ void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Un } } -UniValue listtransactions(const UniValue& params, bool fHelp) +UniValue listtransactions(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() > 4) + if (request.fHelp || request.params.size() > 4) throw runtime_error( "listtransactions ( \"account\" count from includeWatchonly)\n" "\nReturns up to 'count' most recent transactions skipping the first 'from' transactions for account 'account'.\n" @@ -1480,17 +1480,17 @@ UniValue listtransactions(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); string strAccount = "*"; - if (params.size() > 0) - strAccount = params[0].get_str(); + if (request.params.size() > 0) + strAccount = request.params[0].get_str(); int nCount = 10; - if (params.size() > 1) - nCount = params[1].get_int(); + if (request.params.size() > 1) + nCount = request.params[1].get_int(); int nFrom = 0; - if (params.size() > 2) - nFrom = params[2].get_int(); + if (request.params.size() > 2) + nFrom = request.params[2].get_int(); isminefilter filter = ISMINE_SPENDABLE; - if(params.size() > 3) - if(params[3].get_bool()) + if(request.params.size() > 3) + if(request.params[3].get_bool()) filter = filter | ISMINE_WATCH_ONLY; if (nCount < 0) @@ -1540,12 +1540,12 @@ UniValue listtransactions(const UniValue& params, bool fHelp) return ret; } -UniValue listaccounts(const UniValue& params, bool fHelp) +UniValue listaccounts(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() > 2) + if (request.fHelp || request.params.size() > 2) throw runtime_error( "listaccounts ( minconf includeWatchonly)\n" "\nDEPRECATED. Returns Object that has account names as keys, account balances as values.\n" @@ -1571,11 +1571,11 @@ UniValue listaccounts(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); int nMinDepth = 1; - if (params.size() > 0) - nMinDepth = params[0].get_int(); + if (request.params.size() > 0) + nMinDepth = request.params[0].get_int(); isminefilter includeWatchonly = ISMINE_SPENDABLE; - if(params.size() > 1) - if(params[1].get_bool()) + if(request.params.size() > 1) + if(request.params[1].get_bool()) includeWatchonly = includeWatchonly | ISMINE_WATCH_ONLY; map mapAccountBalances; @@ -1619,12 +1619,12 @@ UniValue listaccounts(const UniValue& params, bool fHelp) return ret; } -UniValue listsinceblock(const UniValue& params, bool fHelp) +UniValue listsinceblock(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp) + if (request.fHelp) throw runtime_error( "listsinceblock ( \"blockhash\" target-confirmations includeWatchonly)\n" "\nGet all transactions in blocks since block [blockhash], or all transactions if omitted\n" @@ -1667,26 +1667,26 @@ UniValue listsinceblock(const UniValue& params, bool fHelp) int target_confirms = 1; isminefilter filter = ISMINE_SPENDABLE; - if (params.size() > 0) + if (request.params.size() > 0) { uint256 blockId; - blockId.SetHex(params[0].get_str()); + blockId.SetHex(request.params[0].get_str()); BlockMap::iterator it = mapBlockIndex.find(blockId); if (it != mapBlockIndex.end()) pindex = it->second; } - if (params.size() > 1) + if (request.params.size() > 1) { - target_confirms = params[1].get_int(); + target_confirms = request.params[1].get_int(); if (target_confirms < 1) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter"); } - if(params.size() > 2) - if(params[2].get_bool()) + if(request.params.size() > 2) + if(request.params[2].get_bool()) filter = filter | ISMINE_WATCH_ONLY; int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1; @@ -1711,12 +1711,12 @@ UniValue listsinceblock(const UniValue& params, bool fHelp) return ret; } -UniValue gettransaction(const UniValue& params, bool fHelp) +UniValue gettransaction(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() < 1 || params.size() > 2) + if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw runtime_error( "gettransaction \"txid\" ( includeWatchonly )\n" "\nGet detailed information about in-wallet transaction \n" @@ -1758,11 +1758,11 @@ UniValue gettransaction(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); uint256 hash; - hash.SetHex(params[0].get_str()); + hash.SetHex(request.params[0].get_str()); isminefilter filter = ISMINE_SPENDABLE; - if(params.size() > 1) - if(params[1].get_bool()) + if(request.params.size() > 1) + if(request.params[1].get_bool()) filter = filter | ISMINE_WATCH_ONLY; UniValue entry(UniValue::VOBJ); @@ -1791,12 +1791,12 @@ UniValue gettransaction(const UniValue& params, bool fHelp) return entry; } -UniValue abandontransaction(const UniValue& params, bool fHelp) +UniValue abandontransaction(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() != 1) + if (request.fHelp || request.params.size() != 1) throw runtime_error( "abandontransaction \"txid\"\n" "\nMark in-wallet transaction as abandoned\n" @@ -1815,7 +1815,7 @@ UniValue abandontransaction(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); uint256 hash; - hash.SetHex(params[0].get_str()); + hash.SetHex(request.params[0].get_str()); if (!pwalletMain->mapWallet.count(hash)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id"); @@ -1826,12 +1826,12 @@ UniValue abandontransaction(const UniValue& params, bool fHelp) } -UniValue backupwallet(const UniValue& params, bool fHelp) +UniValue backupwallet(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() != 1) + if (request.fHelp || request.params.size() != 1) throw runtime_error( "backupwallet \"destination\"\n" "\nSafely copies current wallet file to destination, which can be a directory or a path with filename.\n" @@ -1844,7 +1844,7 @@ UniValue backupwallet(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); - string strDest = params[0].get_str(); + string strDest = request.params[0].get_str(); if (!pwalletMain->BackupWallet(strDest)) throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!"); @@ -1852,12 +1852,12 @@ UniValue backupwallet(const UniValue& params, bool fHelp) } -UniValue keypoolrefill(const UniValue& params, bool fHelp) +UniValue keypoolrefill(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() > 1) + if (request.fHelp || request.params.size() > 1) throw runtime_error( "keypoolrefill ( newsize )\n" "\nFills the keypool." @@ -1873,10 +1873,10 @@ UniValue keypoolrefill(const UniValue& params, bool fHelp) // 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool unsigned int kpSize = 0; - if (params.size() > 0) { - if (params[0].get_int() < 0) + if (request.params.size() > 0) { + if (request.params[0].get_int() < 0) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size."); - kpSize = (unsigned int)params[0].get_int(); + kpSize = (unsigned int)request.params[0].get_int(); } EnsureWalletIsUnlocked(); @@ -1896,12 +1896,12 @@ static void LockWallet(CWallet* pWallet) pWallet->Lock(); } -UniValue walletpassphrase(const UniValue& params, bool fHelp) +UniValue walletpassphrase(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2)) + if (pwalletMain->IsCrypted() && (request.fHelp || request.params.size() != 2)) throw runtime_error( "walletpassphrase \"passphrase\" timeout\n" "\nStores the wallet decryption key in memory for 'timeout' seconds.\n" @@ -1923,17 +1923,17 @@ UniValue walletpassphrase(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); - if (fHelp) + if (request.fHelp) return true; if (!pwalletMain->IsCrypted()) throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called."); - // Note that the walletpassphrase is stored in params[0] which is not mlock()ed + // Note that the walletpassphrase is stored in request.params[0] which is not mlock()ed SecureString strWalletPass; strWalletPass.reserve(100); // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string) - // Alternately, find a way to make params[0] mlock()'d to begin with. - strWalletPass = params[0].get_str().c_str(); + // Alternately, find a way to make request.params[0] mlock()'d to begin with. + strWalletPass = request.params[0].get_str().c_str(); if (strWalletPass.length() > 0) { @@ -1947,7 +1947,7 @@ UniValue walletpassphrase(const UniValue& params, bool fHelp) pwalletMain->TopUpKeyPool(); - int64_t nSleepTime = params[1].get_int64(); + int64_t nSleepTime = request.params[1].get_int64(); LOCK(cs_nWalletUnlockTime); nWalletUnlockTime = GetTime() + nSleepTime; RPCRunLater("lockwallet", boost::bind(LockWallet, pwalletMain), nSleepTime); @@ -1956,12 +1956,12 @@ UniValue walletpassphrase(const UniValue& params, bool fHelp) } -UniValue walletpassphrasechange(const UniValue& params, bool fHelp) +UniValue walletpassphrasechange(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2)) + if (pwalletMain->IsCrypted() && (request.fHelp || request.params.size() != 2)) throw runtime_error( "walletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\n" "\nChanges the wallet passphrase from 'oldpassphrase' to 'newpassphrase'.\n" @@ -1975,20 +1975,20 @@ UniValue walletpassphrasechange(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); - if (fHelp) + if (request.fHelp) return true; if (!pwalletMain->IsCrypted()) throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrasechange was called."); // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string) - // Alternately, find a way to make params[0] mlock()'d to begin with. + // Alternately, find a way to make request.params[0] mlock()'d to begin with. SecureString strOldWalletPass; strOldWalletPass.reserve(100); - strOldWalletPass = params[0].get_str().c_str(); + strOldWalletPass = request.params[0].get_str().c_str(); SecureString strNewWalletPass; strNewWalletPass.reserve(100); - strNewWalletPass = params[1].get_str().c_str(); + strNewWalletPass = request.params[1].get_str().c_str(); if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1) throw runtime_error( @@ -2002,12 +2002,12 @@ UniValue walletpassphrasechange(const UniValue& params, bool fHelp) } -UniValue walletlock(const UniValue& params, bool fHelp) +UniValue walletlock(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0)) + if (pwalletMain->IsCrypted() && (request.fHelp || request.params.size() != 0)) throw runtime_error( "walletlock\n" "\nRemoves the wallet encryption key from memory, locking the wallet.\n" @@ -2026,7 +2026,7 @@ UniValue walletlock(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); - if (fHelp) + if (request.fHelp) return true; if (!pwalletMain->IsCrypted()) throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletlock was called."); @@ -2041,12 +2041,12 @@ UniValue walletlock(const UniValue& params, bool fHelp) } -UniValue encryptwallet(const UniValue& params, bool fHelp) +UniValue encryptwallet(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1)) + if (!pwalletMain->IsCrypted() && (request.fHelp || request.params.size() != 1)) throw runtime_error( "encryptwallet \"passphrase\"\n" "\nEncrypts the wallet with 'passphrase'. This is for first time encryption.\n" @@ -2072,16 +2072,16 @@ UniValue encryptwallet(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); - if (fHelp) + if (request.fHelp) return true; if (pwalletMain->IsCrypted()) throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an encrypted wallet, but encryptwallet was called."); // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string) - // Alternately, find a way to make params[0] mlock()'d to begin with. + // Alternately, find a way to make request.params[0] mlock()'d to begin with. SecureString strWalletPass; strWalletPass.reserve(100); - strWalletPass = params[0].get_str().c_str(); + strWalletPass = request.params[0].get_str().c_str(); if (strWalletPass.length() < 1) throw runtime_error( @@ -2098,12 +2098,12 @@ UniValue encryptwallet(const UniValue& params, bool fHelp) return "wallet encrypted; Bitcoin server stopping, restart to run with encrypted wallet. The keypool has been flushed and a new HD seed was generated (if you are using HD). You need to make a new backup."; } -UniValue lockunspent(const UniValue& params, bool fHelp) +UniValue lockunspent(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() < 1 || params.size() > 2) + if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw runtime_error( "lockunspent unlock ([{\"txid\":\"txid\",\"vout\":n},...])\n" "\nUpdates list of temporarily unspendable outputs.\n" @@ -2142,20 +2142,20 @@ UniValue lockunspent(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); - if (params.size() == 1) - RPCTypeCheck(params, boost::assign::list_of(UniValue::VBOOL)); + if (request.params.size() == 1) + RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VBOOL)); else - RPCTypeCheck(params, boost::assign::list_of(UniValue::VBOOL)(UniValue::VARR)); + RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VBOOL)(UniValue::VARR)); - bool fUnlock = params[0].get_bool(); + bool fUnlock = request.params[0].get_bool(); - if (params.size() == 1) { + if (request.params.size() == 1) { if (fUnlock) pwalletMain->UnlockAllCoins(); return true; } - UniValue outputs = params[1].get_array(); + UniValue outputs = request.params[1].get_array(); for (unsigned int idx = 0; idx < outputs.size(); idx++) { const UniValue& output = outputs[idx]; if (!output.isObject()) @@ -2187,12 +2187,12 @@ UniValue lockunspent(const UniValue& params, bool fHelp) return true; } -UniValue listlockunspent(const UniValue& params, bool fHelp) +UniValue listlockunspent(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() > 0) + if (request.fHelp || request.params.size() > 0) throw runtime_error( "listlockunspent\n" "\nReturns list of temporarily unspendable outputs.\n" @@ -2236,12 +2236,12 @@ UniValue listlockunspent(const UniValue& params, bool fHelp) return ret; } -UniValue settxfee(const UniValue& params, bool fHelp) +UniValue settxfee(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() < 1 || params.size() > 1) + if (request.fHelp || request.params.size() < 1 || request.params.size() > 1) throw runtime_error( "settxfee amount\n" "\nSet the transaction fee per kB. Overwrites the paytxfee parameter.\n" @@ -2257,18 +2257,18 @@ UniValue settxfee(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); // Amount - CAmount nAmount = AmountFromValue(params[0]); + CAmount nAmount = AmountFromValue(request.params[0]); payTxFee = CFeeRate(nAmount, 1000); return true; } -UniValue getwalletinfo(const UniValue& params, bool fHelp) +UniValue getwalletinfo(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() != 0) + if (request.fHelp || request.params.size() != 0) throw runtime_error( "getwalletinfo\n" "Returns an object containing various wallet state info.\n" @@ -2309,12 +2309,12 @@ UniValue getwalletinfo(const UniValue& params, bool fHelp) return obj; } -UniValue resendwallettransactions(const UniValue& params, bool fHelp) +UniValue resendwallettransactions(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() != 0) + if (request.fHelp || request.params.size() != 0) throw runtime_error( "resendwallettransactions\n" "Immediately re-broadcast unconfirmed wallet transactions to all peers.\n" @@ -2337,12 +2337,12 @@ UniValue resendwallettransactions(const UniValue& params, bool fHelp) return result; } -UniValue listunspent(const UniValue& params, bool fHelp) +UniValue listunspent(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() > 3) + if (request.fHelp || request.params.size() > 3) throw runtime_error( "listunspent ( minconf maxconf [\"address\",...] )\n" "\nReturns array of unspent transaction outputs\n" @@ -2379,19 +2379,19 @@ UniValue listunspent(const UniValue& params, bool fHelp) + HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"") ); - RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM)(UniValue::VNUM)(UniValue::VARR)); + RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VNUM)(UniValue::VNUM)(UniValue::VARR)); int nMinDepth = 1; - if (params.size() > 0) - nMinDepth = params[0].get_int(); + if (request.params.size() > 0) + nMinDepth = request.params[0].get_int(); int nMaxDepth = 9999999; - if (params.size() > 1) - nMaxDepth = params[1].get_int(); + if (request.params.size() > 1) + nMaxDepth = request.params[1].get_int(); set setAddress; - if (params.size() > 2) { - UniValue inputs = params[2].get_array(); + if (request.params.size() > 2) { + UniValue inputs = request.params[2].get_array(); for (unsigned int idx = 0; idx < inputs.size(); idx++) { const UniValue& input = inputs[idx]; CBitcoinAddress address(input.get_str()); @@ -2448,12 +2448,12 @@ UniValue listunspent(const UniValue& params, bool fHelp) return results; } -UniValue fundrawtransaction(const UniValue& params, bool fHelp) +UniValue fundrawtransaction(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(fHelp)) + if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; - if (fHelp || params.size() < 1 || params.size() > 2) + if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw runtime_error( "fundrawtransaction \"hexstring\" ( options )\n" "\nAdd inputs to a transaction until it has enough in value to meet its out value.\n" @@ -2494,7 +2494,7 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) + HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"") ); - RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)); + RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)); CTxDestination changeAddress = CNoDestination(); int changePosition = -1; @@ -2503,15 +2503,15 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) CFeeRate feeRate = CFeeRate(0); bool overrideEstimatedFeerate = false; - if (params.size() > 1) { - if (params[1].type() == UniValue::VBOOL) { + if (request.params.size() > 1) { + if (request.params[1].type() == UniValue::VBOOL) { // backward compatibility bool only fallback - includeWatching = params[1].get_bool(); + includeWatching = request.params[1].get_bool(); } else { - RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VOBJ)); + RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)(UniValue::VOBJ)); - UniValue options = params[1]; + UniValue options = request.params[1]; RPCTypeCheckObj(options, { @@ -2551,7 +2551,7 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) // parse hex string from parameter CTransaction origTx; - if (!DecodeHexTx(origTx, params[0].get_str(), true)) + if (!DecodeHexTx(origTx, request.params[0].get_str(), true)) throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); if (origTx.vout.size() == 0) @@ -2575,14 +2575,14 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) return result; } -extern UniValue dumpprivkey(const UniValue& params, bool fHelp); // in rpcdump.cpp -extern UniValue importprivkey(const UniValue& params, bool fHelp); -extern UniValue importaddress(const UniValue& params, bool fHelp); -extern UniValue importpubkey(const UniValue& params, bool fHelp); -extern UniValue dumpwallet(const UniValue& params, bool fHelp); -extern UniValue importwallet(const UniValue& params, bool fHelp); -extern UniValue importprunedfunds(const UniValue& params, bool fHelp); -extern UniValue removeprunedfunds(const UniValue& params, bool fHelp); +extern UniValue dumpprivkey(const JSONRPCRequest& request); // in rpcdump.cpp +extern UniValue importprivkey(const JSONRPCRequest& request); +extern UniValue importaddress(const JSONRPCRequest& request); +extern UniValue importpubkey(const JSONRPCRequest& request); +extern UniValue dumpwallet(const JSONRPCRequest& request); +extern UniValue importwallet(const JSONRPCRequest& request); +extern UniValue importprunedfunds(const JSONRPCRequest& request); +extern UniValue removeprunedfunds(const JSONRPCRequest& request); static const CRPCCommand commands[] = { // category name actor (function) okSafeMode From e7156ad61be2fe935fdb64e9d0e877fa0e9f7f9e Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 22 Sep 2016 09:58:13 +0200 Subject: [PATCH 1058/1802] [RPC] pass HTTP basic authentication username to the JSONRequest object --- src/httprpc.cpp | 11 +++++++---- src/rest.cpp | 1 + src/rpc/server.h | 3 ++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/httprpc.cpp b/src/httprpc.cpp index 54651911aa38d..e35acb6cd99ce 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -127,7 +127,7 @@ static bool multiUserAuthorized(std::string strUserPass) return false; } -static bool RPCAuthorized(const std::string& strAuth) +static bool RPCAuthorized(const std::string& strAuth, std::string& strAuthUsernameOut) { if (strRPCUserColonPass.empty()) // Belt-and-suspenders measure if InitRPCAuthentication was not called return false; @@ -136,7 +136,10 @@ static bool RPCAuthorized(const std::string& strAuth) std::string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64); std::string strUserPass = DecodeBase64(strUserPass64); - + + if (strUserPass.find(":") != std::string::npos) + strAuthUsernameOut = strUserPass.substr(0, strUserPass.find(":")); + //Check if authorized under single-user field if (TimingResistantEqual(strUserPass, strRPCUserColonPass)) { return true; @@ -159,7 +162,8 @@ static bool HTTPReq_JSONRPC(HTTPRequest* req, const std::string &) return false; } - if (!RPCAuthorized(authHeader.second)) { + JSONRPCRequest jreq; + if (!RPCAuthorized(authHeader.second, jreq.authUser)) { LogPrintf("ThreadRPCServer incorrect password attempt from %s\n", req->GetPeer().ToString()); /* Deter brute-forcing @@ -172,7 +176,6 @@ static bool HTTPReq_JSONRPC(HTTPRequest* req, const std::string &) return false; } - JSONRPCRequest jreq; try { // Parse request UniValue valRequest; diff --git a/src/rest.cpp b/src/rest.cpp index 707dfe69871f7..b8b5420626d3b 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -286,6 +286,7 @@ static bool rest_chaininfo(HTTPRequest* req, const std::string& strURIPart) switch (rf) { case RF_JSON: { JSONRPCRequest jsonRequest; + jsonRequest.params = UniValue(UniValue::VARR); UniValue chainInfoObject = getblockchaininfo(jsonRequest); string strJSON = chainInfoObject.write() + "\n"; req->WriteHeader("Content-Type", "application/json"); diff --git a/src/rpc/server.h b/src/rpc/server.h index d8b5097035c91..c59886222c276 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -49,8 +49,9 @@ class JSONRPCRequest UniValue params; bool fHelp; std::string URI; + std::string authUser; - JSONRPCRequest() { id = NullUniValue; } + JSONRPCRequest() { id = NullUniValue; params = NullUniValue; fHelp = false; } void parse(const UniValue& valRequest); }; From fc146095d20452686efe1944b143452bec394343 Mon Sep 17 00:00:00 2001 From: mruddy Date: Fri, 6 May 2016 22:08:39 +0000 Subject: [PATCH 1059/1802] RPC: augment getblockchaininfo bip9_softforks data --- qa/rpc-tests/bip9-softforks.py | 9 +++ src/main.cpp | 6 ++ src/main.h | 3 +- src/rpc/blockchain.cpp | 4 +- src/test/versionbits_tests.cpp | 104 ++++++++++++++++++++------------- src/versionbits.cpp | 35 +++++++++++ src/versionbits.h | 4 +- 7 files changed, 121 insertions(+), 44 deletions(-) diff --git a/qa/rpc-tests/bip9-softforks.py b/qa/rpc-tests/bip9-softforks.py index be6ddde112ea2..c42ed44c259a3 100755 --- a/qa/rpc-tests/bip9-softforks.py +++ b/qa/rpc-tests/bip9-softforks.py @@ -81,6 +81,9 @@ def get_bip9_status(self, key): return info['bip9_softforks'][key] def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignature, bitno): + assert_equal(self.get_bip9_status(bipName)['status'], 'defined') + assert_equal(self.get_bip9_status(bipName)['since'], 0) + # generate some coins for later self.coinbase_blocks = self.nodes[0].generate(2) self.height = 3 # height of the next block to build @@ -89,6 +92,7 @@ def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignatu self.last_block_time = int(time.time()) assert_equal(self.get_bip9_status(bipName)['status'], 'defined') + assert_equal(self.get_bip9_status(bipName)['since'], 0) tmpl = self.nodes[0].getblocktemplate({}) assert(bipName not in tmpl['rules']) assert(bipName not in tmpl['vbavailable']) @@ -101,6 +105,7 @@ def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignatu yield TestInstance(test_blocks, sync_every_block=False) assert_equal(self.get_bip9_status(bipName)['status'], 'started') + assert_equal(self.get_bip9_status(bipName)['since'], 144) tmpl = self.nodes[0].getblocktemplate({}) assert(bipName not in tmpl['rules']) assert_equal(tmpl['vbavailable'][bipName], bitno) @@ -117,6 +122,7 @@ def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignatu yield TestInstance(test_blocks, sync_every_block=False) assert_equal(self.get_bip9_status(bipName)['status'], 'started') + assert_equal(self.get_bip9_status(bipName)['since'], 144) tmpl = self.nodes[0].getblocktemplate({}) assert(bipName not in tmpl['rules']) assert_equal(tmpl['vbavailable'][bipName], bitno) @@ -133,6 +139,7 @@ def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignatu yield TestInstance(test_blocks, sync_every_block=False) assert_equal(self.get_bip9_status(bipName)['status'], 'locked_in') + assert_equal(self.get_bip9_status(bipName)['since'], 432) tmpl = self.nodes[0].getblocktemplate({}) assert(bipName not in tmpl['rules']) @@ -142,6 +149,7 @@ def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignatu yield TestInstance(test_blocks, sync_every_block=False) assert_equal(self.get_bip9_status(bipName)['status'], 'locked_in') + assert_equal(self.get_bip9_status(bipName)['since'], 432) tmpl = self.nodes[0].getblocktemplate({}) assert(bipName not in tmpl['rules']) @@ -167,6 +175,7 @@ def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignatu yield TestInstance([[block, True]]) assert_equal(self.get_bip9_status(bipName)['status'], 'active') + assert_equal(self.get_bip9_status(bipName)['since'], 576) tmpl = self.nodes[0].getblocktemplate({}) assert(bipName in tmpl['rules']) assert(bipName not in tmpl['vbavailable']) diff --git a/src/main.cpp b/src/main.cpp index 1777717cd9db2..50158b468780a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6918,6 +6918,12 @@ ThresholdState VersionBitsTipState(const Consensus::Params& params, Consensus::D return VersionBitsState(chainActive.Tip(), params, pos, versionbitscache); } +int VersionBitsTipStateSinceHeight(const Consensus::Params& params, Consensus::DeploymentPos pos) +{ + LOCK(cs_main); + return VersionBitsStateSinceHeight(chainActive.Tip(), params, pos, versionbitscache); +} + class CMainCleanup { public: diff --git a/src/main.h b/src/main.h index e91f6e46fed5c..3eab9b89daa66 100644 --- a/src/main.h +++ b/src/main.h @@ -297,7 +297,8 @@ std::string FormatStateMessage(const CValidationState &state); /** Get the BIP9 state for a given deployment at the current tip. */ ThresholdState VersionBitsTipState(const Consensus::Params& params, Consensus::DeploymentPos pos); - +/** Get the block height at which the BIP9 deployment switched into the state for the block building on the current tip. */ +int VersionBitsTipStateSinceHeight(const Consensus::Params& params, Consensus::DeploymentPos pos); /** * Count ECDSA signature operations the old-fashioned (pre-0.6) way diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 5414ac9ffd449..141ca87b69bdc 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1009,6 +1009,7 @@ static UniValue BIP9SoftForkDesc(const Consensus::Params& consensusParams, Conse } rv.push_back(Pair("startTime", consensusParams.vDeployments[id].nStartTime)); rv.push_back(Pair("timeout", consensusParams.vDeployments[id].nTimeout)); + rv.push_back(Pair("since", VersionBitsTipStateSinceHeight(consensusParams, id))); return rv; } @@ -1053,7 +1054,8 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) " \"status\": \"xxxx\", (string) one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\"\n" " \"bit\": xx, (numeric) the bit (0-28) in the block version field used to signal this softfork (only for \"started\" status)\n" " \"startTime\": xx, (numeric) the minimum median time past of a block at which the bit gains its meaning\n" - " \"timeout\": xx (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in\n" + " \"timeout\": xx, (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in\n" + " \"since\": xx (numeric) height of the first block to which the status applies\n" " }\n" " }\n" "}\n" diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp index ffc0ff6f8ead3..784e796998524 100644 --- a/src/test/versionbits_tests.cpp +++ b/src/test/versionbits_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2015 The Bitcoin Core developers +// Copyright (c) 2014-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -30,6 +30,7 @@ class TestConditionChecker : public AbstractThresholdConditionChecker bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const { return (pindex->nVersion & 0x100); } ThresholdState GetStateFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateFor(pindexPrev, paramsDummy, cache); } + int GetStateSinceHeightFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateSinceHeightFor(pindexPrev, paramsDummy, cache); } }; #define CHECKERS 6 @@ -78,6 +79,16 @@ class VersionBitsTester return *this; } + VersionBitsTester& TestStateSinceHeight(int height) { + for (int i = 0; i < CHECKERS; i++) { + if ((insecure_rand() & ((1 << i) - 1)) == 0) { + BOOST_CHECK_MESSAGE(checker[i].GetStateSinceHeightFor(vpblock.empty() ? NULL : vpblock.back()) == height, strprintf("Test %i for StateSinceHeight", num)); + } + } + num++; + return *this; + } + VersionBitsTester& TestDefined() { for (int i = 0; i < CHECKERS; i++) { if ((insecure_rand() & ((1 << i) - 1)) == 0) { @@ -137,53 +148,64 @@ BOOST_AUTO_TEST_CASE(versionbits_test) { for (int i = 0; i < 64; i++) { // DEFINED -> FAILED - VersionBitsTester().TestDefined() - .Mine(1, TestTime(1), 0x100).TestDefined() - .Mine(11, TestTime(11), 0x100).TestDefined() - .Mine(989, TestTime(989), 0x100).TestDefined() - .Mine(999, TestTime(20000), 0x100).TestDefined() - .Mine(1000, TestTime(20000), 0x100).TestFailed() - .Mine(1999, TestTime(30001), 0x100).TestFailed() - .Mine(2000, TestTime(30002), 0x100).TestFailed() - .Mine(2001, TestTime(30003), 0x100).TestFailed() - .Mine(2999, TestTime(30004), 0x100).TestFailed() - .Mine(3000, TestTime(30005), 0x100).TestFailed() + VersionBitsTester().TestDefined().TestStateSinceHeight(0) + .Mine(1, TestTime(1), 0x100).TestDefined().TestStateSinceHeight(0) + .Mine(11, TestTime(11), 0x100).TestDefined().TestStateSinceHeight(0) + .Mine(989, TestTime(989), 0x100).TestDefined().TestStateSinceHeight(0) + .Mine(999, TestTime(20000), 0x100).TestDefined().TestStateSinceHeight(0) + .Mine(1000, TestTime(20000), 0x100).TestFailed().TestStateSinceHeight(1000) + .Mine(1999, TestTime(30001), 0x100).TestFailed().TestStateSinceHeight(1000) + .Mine(2000, TestTime(30002), 0x100).TestFailed().TestStateSinceHeight(1000) + .Mine(2001, TestTime(30003), 0x100).TestFailed().TestStateSinceHeight(1000) + .Mine(2999, TestTime(30004), 0x100).TestFailed().TestStateSinceHeight(1000) + .Mine(3000, TestTime(30005), 0x100).TestFailed().TestStateSinceHeight(1000) // DEFINED -> STARTED -> FAILED - .Reset().TestDefined() - .Mine(1, TestTime(1), 0).TestDefined() - .Mine(1000, TestTime(10000) - 1, 0x100).TestDefined() // One second more and it would be defined - .Mine(2000, TestTime(10000), 0x100).TestStarted() // So that's what happens the next period - .Mine(2051, TestTime(10010), 0).TestStarted() // 51 old blocks - .Mine(2950, TestTime(10020), 0x100).TestStarted() // 899 new blocks - .Mine(3000, TestTime(20000), 0).TestFailed() // 50 old blocks (so 899 out of the past 1000) - .Mine(4000, TestTime(20010), 0x100).TestFailed() + .Reset().TestDefined().TestStateSinceHeight(0) + .Mine(1, TestTime(1), 0).TestDefined().TestStateSinceHeight(0) + .Mine(1000, TestTime(10000) - 1, 0x100).TestDefined().TestStateSinceHeight(0) // One second more and it would be defined + .Mine(2000, TestTime(10000), 0x100).TestStarted().TestStateSinceHeight(2000) // So that's what happens the next period + .Mine(2051, TestTime(10010), 0).TestStarted().TestStateSinceHeight(2000) // 51 old blocks + .Mine(2950, TestTime(10020), 0x100).TestStarted().TestStateSinceHeight(2000) // 899 new blocks + .Mine(3000, TestTime(20000), 0).TestFailed().TestStateSinceHeight(3000) // 50 old blocks (so 899 out of the past 1000) + .Mine(4000, TestTime(20010), 0x100).TestFailed().TestStateSinceHeight(3000) // DEFINED -> STARTED -> FAILED while threshold reached - .Reset().TestDefined() - .Mine(1, TestTime(1), 0).TestDefined() - .Mine(1000, TestTime(10000) - 1, 0x101).TestDefined() // One second more and it would be defined - .Mine(2000, TestTime(10000), 0x101).TestStarted() // So that's what happens the next period - .Mine(2999, TestTime(30000), 0x100).TestStarted() // 999 new blocks - .Mine(3000, TestTime(30000), 0x100).TestFailed() // 1 new block (so 1000 out of the past 1000 are new) - .Mine(3999, TestTime(30001), 0).TestFailed() - .Mine(4000, TestTime(30002), 0).TestFailed() - .Mine(14333, TestTime(30003), 0).TestFailed() - .Mine(24000, TestTime(40000), 0).TestFailed() + .Reset().TestDefined().TestStateSinceHeight(0) + .Mine(1, TestTime(1), 0).TestDefined().TestStateSinceHeight(0) + .Mine(1000, TestTime(10000) - 1, 0x101).TestDefined().TestStateSinceHeight(0) // One second more and it would be defined + .Mine(2000, TestTime(10000), 0x101).TestStarted().TestStateSinceHeight(2000) // So that's what happens the next period + .Mine(2999, TestTime(30000), 0x100).TestStarted().TestStateSinceHeight(2000) // 999 new blocks + .Mine(3000, TestTime(30000), 0x100).TestFailed().TestStateSinceHeight(3000) // 1 new block (so 1000 out of the past 1000 are new) + .Mine(3999, TestTime(30001), 0).TestFailed().TestStateSinceHeight(3000) + .Mine(4000, TestTime(30002), 0).TestFailed().TestStateSinceHeight(3000) + .Mine(14333, TestTime(30003), 0).TestFailed().TestStateSinceHeight(3000) + .Mine(24000, TestTime(40000), 0).TestFailed().TestStateSinceHeight(3000) // DEFINED -> STARTED -> LOCKEDIN at the last minute -> ACTIVE .Reset().TestDefined() - .Mine(1, TestTime(1), 0).TestDefined() - .Mine(1000, TestTime(10000) - 1, 0x101).TestDefined() // One second more and it would be defined - .Mine(2000, TestTime(10000), 0x101).TestStarted() // So that's what happens the next period - .Mine(2050, TestTime(10010), 0x200).TestStarted() // 50 old blocks - .Mine(2950, TestTime(10020), 0x100).TestStarted() // 900 new blocks - .Mine(2999, TestTime(19999), 0x200).TestStarted() // 49 old blocks - .Mine(3000, TestTime(29999), 0x200).TestLockedIn() // 1 old block (so 900 out of the past 1000) - .Mine(3999, TestTime(30001), 0).TestLockedIn() - .Mine(4000, TestTime(30002), 0).TestActive() - .Mine(14333, TestTime(30003), 0).TestActive() - .Mine(24000, TestTime(40000), 0).TestActive(); + .Mine(1, TestTime(1), 0).TestDefined().TestStateSinceHeight(0) + .Mine(1000, TestTime(10000) - 1, 0x101).TestDefined().TestStateSinceHeight(0) // One second more and it would be defined + .Mine(2000, TestTime(10000), 0x101).TestStarted().TestStateSinceHeight(2000) // So that's what happens the next period + .Mine(2050, TestTime(10010), 0x200).TestStarted().TestStateSinceHeight(2000) // 50 old blocks + .Mine(2950, TestTime(10020), 0x100).TestStarted().TestStateSinceHeight(2000) // 900 new blocks + .Mine(2999, TestTime(19999), 0x200).TestStarted().TestStateSinceHeight(2000) // 49 old blocks + .Mine(3000, TestTime(29999), 0x200).TestLockedIn().TestStateSinceHeight(3000) // 1 old block (so 900 out of the past 1000) + .Mine(3999, TestTime(30001), 0).TestLockedIn().TestStateSinceHeight(3000) + .Mine(4000, TestTime(30002), 0).TestActive().TestStateSinceHeight(4000) + .Mine(14333, TestTime(30003), 0).TestActive().TestStateSinceHeight(4000) + .Mine(24000, TestTime(40000), 0).TestActive().TestStateSinceHeight(4000) + + // DEFINED multiple periods -> STARTED multiple periods -> FAILED + .Reset().TestDefined().TestStateSinceHeight(0) + .Mine(999, TestTime(999), 0).TestDefined().TestStateSinceHeight(0) + .Mine(1000, TestTime(1000), 0).TestDefined().TestStateSinceHeight(0) + .Mine(2000, TestTime(2000), 0).TestDefined().TestStateSinceHeight(0) + .Mine(3000, TestTime(10000), 0).TestStarted().TestStateSinceHeight(3000) + .Mine(4000, TestTime(10000), 0).TestStarted().TestStateSinceHeight(3000) + .Mine(5000, TestTime(10000), 0).TestStarted().TestStateSinceHeight(3000) + .Mine(6000, TestTime(20000), 0).TestFailed().TestStateSinceHeight(6000) + .Mine(7000, TestTime(20000), 0x100).TestFailed().TestStateSinceHeight(6000); } // Sanity checks of version bit deployments diff --git a/src/versionbits.cpp b/src/versionbits.cpp index bf32ae6627945..d73f3405109d0 100644 --- a/src/versionbits.cpp +++ b/src/versionbits.cpp @@ -105,6 +105,36 @@ ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* return state; } +int AbstractThresholdConditionChecker::GetStateSinceHeightFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const +{ + const ThresholdState initialState = GetStateFor(pindexPrev, params, cache); + + // BIP 9 about state DEFINED: "The genesis block is by definition in this state for each deployment." + if (initialState == THRESHOLD_DEFINED) { + return 0; + } + + const int nPeriod = Period(params); + + // A block's state is always the same as that of the first of its period, so it is computed based on a pindexPrev whose height equals a multiple of nPeriod - 1. + // To ease understanding of the following height calculation, it helps to remember that + // right now pindexPrev points to the block prior to the block that we are computing for, thus: + // if we are computing for the last block of a period, then pindexPrev points to the second to last block of the period, and + // if we are computing for the first block of a period, then pindexPrev points to the last block of the previous period. + // The parent of the genesis block is represented by NULL. + pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod)); + + const CBlockIndex* previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod); + + while (previousPeriodParent != NULL && GetStateFor(previousPeriodParent, params, cache) == initialState) { + pindexPrev = previousPeriodParent; + previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod); + } + + // Adjust the result because right now we point to the parent block. + return pindexPrev->nHeight + 1; +} + namespace { /** @@ -137,6 +167,11 @@ ThresholdState VersionBitsState(const CBlockIndex* pindexPrev, const Consensus:: return VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, cache.caches[pos]); } +int VersionBitsStateSinceHeight(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache) +{ + return VersionBitsConditionChecker(pos).GetStateSinceHeightFor(pindexPrev, params, cache.caches[pos]); +} + uint32_t VersionBitsMask(const Consensus::Params& params, Consensus::DeploymentPos pos) { return VersionBitsConditionChecker(pos).Mask(params); diff --git a/src/versionbits.h b/src/versionbits.h index ede2dcdda8a7a..7a929266aa24c 100644 --- a/src/versionbits.h +++ b/src/versionbits.h @@ -51,8 +51,9 @@ class AbstractThresholdConditionChecker { virtual int Threshold(const Consensus::Params& params) const =0; public: - // Note that the function below takes a pindexPrev as input: they compute information for block B based on its parent. + // Note that the functions below take a pindexPrev as input: they compute information for block B based on its parent. ThresholdState GetStateFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const; + int GetStateSinceHeightFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const; }; struct VersionBitsCache @@ -63,6 +64,7 @@ struct VersionBitsCache }; ThresholdState VersionBitsState(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache); +int VersionBitsStateSinceHeight(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache); uint32_t VersionBitsMask(const Consensus::Params& params, Consensus::DeploymentPos pos); #endif From cb08fdbf78685b55029768524ca867772711c32b Mon Sep 17 00:00:00 2001 From: Pedro Branco Date: Thu, 16 Jun 2016 15:57:48 +0100 Subject: [PATCH 1060/1802] Add importmulti rpc call --- qa/pull-tester/rpc-tests.py | 1 + qa/rpc-tests/importmulti.py | 293 +++++++++++++++++++++++++++ src/chain.cpp | 7 + src/chain.h | 3 + src/rpc/client.cpp | 2 + src/wallet/rpcdump.cpp | 390 ++++++++++++++++++++++++++++++++++++ src/wallet/rpcwallet.cpp | 2 + 7 files changed, 698 insertions(+) create mode 100755 qa/rpc-tests/importmulti.py diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index 7430bb22565e4..778f8d8a77818 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -145,6 +145,7 @@ 'signmessages.py', 'p2p-compactblocks.py', 'nulldummy.py', + 'importmulti.py', ] if ENABLE_ZMQ: testScripts.append('zmq_test.py') diff --git a/qa/rpc-tests/importmulti.py b/qa/rpc-tests/importmulti.py new file mode 100755 index 0000000000000..960cb63d768c5 --- /dev/null +++ b/qa/rpc-tests/importmulti.py @@ -0,0 +1,293 @@ +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * + +class ImportMultiTest (BitcoinTestFramework): + def __init__(self): + super().__init__() + self.num_nodes = 2 + self.setup_clean_chain = True + + def setup_network(self, split=False): + self.nodes = start_nodes(2, self.options.tmpdir) + self.is_network_split=False + + def run_test (self): + print ("Mining blocks...") + self.nodes[0].generate(1) + self.nodes[1].generate(1) + + # keyword definition + PRIV_KEY = 'privkey' + PUB_KEY = 'pubkey' + ADDRESS_KEY = 'address' + SCRIPT_KEY = 'script' + + + node0_address1 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) + node0_address2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) + node0_address3 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) + + #Check only one address + assert_equal(node0_address1['ismine'], True) + + #Node 1 sync test + assert_equal(self.nodes[1].getblockcount(),1) + + #Address Test - before import + address_info = self.nodes[1].validateaddress(node0_address1['address']) + assert_equal(address_info['iswatchonly'], False) + assert_equal(address_info['ismine'], False) + + + # RPC importmulti ----------------------------------------------- + + # Bitcoin Address + print("Should import an address") + address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) + result = self.nodes[1].importmulti([{ + "scriptPubKey": { + "address": address['address'] + } + }]) + assert_equal(result[0]['success'], True) + address_assert = self.nodes[1].validateaddress(address['address']) + assert_equal(address_assert['iswatchonly'], True) + assert_equal(address_assert['ismine'], False) + + + # ScriptPubKey + internal + print("Should import a scriptPubKey with internal flag") + address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) + result = self.nodes[1].importmulti([{ + "scriptPubKey": address['scriptPubKey'], + "internal": True + }]) + assert_equal(result[0]['success'], True) + address_assert = self.nodes[1].validateaddress(address['address']) + assert_equal(address_assert['iswatchonly'], True) + assert_equal(address_assert['ismine'], False) + + # ScriptPubKey + !internal + print("Should not import a scriptPubKey without internal flag") + address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) + result = self.nodes[1].importmulti([{ + "scriptPubKey": address['scriptPubKey'] + }]) + assert_equal(result[0]['success'], False) + assert_equal(result[0]['error']['code'], -8) + assert_equal(result[0]['error']['message'], 'Internal must be set for hex scriptPubKey') + address_assert = self.nodes[1].validateaddress(address['address']) + assert_equal(address_assert['iswatchonly'], False) + assert_equal(address_assert['ismine'], False) + + + # Address + Public key + !Internal + print("Should import an address with public key") + address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) + result = self.nodes[1].importmulti([{ + "scriptPubKey": { + "address": address['address'] + }, + "pubkeys": [ address['pubkey'] ] + }]) + assert_equal(result[0]['success'], True) + address_assert = self.nodes[1].validateaddress(address['address']) + assert_equal(address_assert['iswatchonly'], True) + assert_equal(address_assert['ismine'], False) + + + # ScriptPubKey + Public key + internal + print("Should import a scriptPubKey with internal and with public key") + address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) + request = [{ + "scriptPubKey": address['scriptPubKey'], + "pubkeys": [ address['pubkey'] ], + "internal": True + }]; + result = self.nodes[1].importmulti(request) + assert_equal(result[0]['success'], True) + address_assert = self.nodes[1].validateaddress(address['address']) + assert_equal(address_assert['iswatchonly'], True) + assert_equal(address_assert['ismine'], False) + + # ScriptPubKey + Public key + !internal + print("Should not import a scriptPubKey without internal and with public key") + address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) + request = [{ + "scriptPubKey": address['scriptPubKey'], + "pubkeys": [ address['pubkey'] ] + }]; + result = self.nodes[1].importmulti(request) + assert_equal(result[0]['success'], False) + assert_equal(result[0]['error']['code'], -8) + assert_equal(result[0]['error']['message'], 'Internal must be set for hex scriptPubKey') + address_assert = self.nodes[1].validateaddress(address['address']) + assert_equal(address_assert['iswatchonly'], False) + assert_equal(address_assert['ismine'], False) + + # Address + Private key + !watchonly + print("Should import an address with private key") + address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) + result = self.nodes[1].importmulti([{ + "scriptPubKey": { + "address": address['address'] + }, + "keys": [ self.nodes[0].dumpprivkey(address['address']) ] + }]) + assert_equal(result[0]['success'], True) + address_assert = self.nodes[1].validateaddress(address['address']) + assert_equal(address_assert['iswatchonly'], False) + assert_equal(address_assert['ismine'], True) + + # Address + Private key + watchonly + print("Should not import an address with private key and with watchonly") + address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) + result = self.nodes[1].importmulti([{ + "scriptPubKey": { + "address": address['address'] + }, + "keys": [ self.nodes[0].dumpprivkey(address['address']) ], + "watchonly": True + }]) + assert_equal(result[0]['success'], False) + assert_equal(result[0]['error']['code'], -8) + assert_equal(result[0]['error']['message'], 'Incompatibility found between watchonly and keys') + address_assert = self.nodes[1].validateaddress(address['address']) + assert_equal(address_assert['iswatchonly'], False) + assert_equal(address_assert['ismine'], False) + + # ScriptPubKey + Private key + internal + print("Should import a scriptPubKey with internal and with private key") + address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) + result = self.nodes[1].importmulti([{ + "scriptPubKey": address['scriptPubKey'], + "keys": [ self.nodes[0].dumpprivkey(address['address']) ], + "internal": True + }]) + assert_equal(result[0]['success'], True) + address_assert = self.nodes[1].validateaddress(address['address']) + assert_equal(address_assert['iswatchonly'], False) + assert_equal(address_assert['ismine'], True) + + # ScriptPubKey + Private key + !internal + print("Should not import a scriptPubKey without internal and with private key") + address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) + result = self.nodes[1].importmulti([{ + "scriptPubKey": address['scriptPubKey'], + "keys": [ self.nodes[0].dumpprivkey(address['address']) ] + }]) + assert_equal(result[0]['success'], False) + assert_equal(result[0]['error']['code'], -8) + assert_equal(result[0]['error']['message'], 'Internal must be set for hex scriptPubKey') + address_assert = self.nodes[1].validateaddress(address['address']) + assert_equal(address_assert['iswatchonly'], False) + assert_equal(address_assert['ismine'], False) + + + # P2SH address + sig_address_1 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) + sig_address_2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) + sig_address_3 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) + multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['address'], sig_address_2['address'], sig_address_3['pubkey']]) + self.nodes[1].generate(100) + transactionid = self.nodes[1].sendtoaddress(multi_sig_script['address'], 10.00) + self.nodes[1].generate(1) + transaction = self.nodes[1].gettransaction(transactionid); + + print("Should import a p2sh") + result = self.nodes[1].importmulti([{ + "scriptPubKey": { + "address": multi_sig_script['address'] + } + }]) + assert_equal(result[0]['success'], True) + address_assert = self.nodes[1].validateaddress(multi_sig_script['address']) + assert_equal(address_assert['isscript'], True) + assert_equal(address_assert['iswatchonly'], True) + p2shunspent = self.nodes[1].listunspent(0,999999, [multi_sig_script['address']])[0] + assert_equal(p2shunspent['spendable'], False) + assert_equal(p2shunspent['solvable'], False) + + + # P2SH + Redeem script + sig_address_1 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) + sig_address_2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) + sig_address_3 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) + multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['address'], sig_address_2['address'], sig_address_3['pubkey']]) + self.nodes[1].generate(100) + transactionid = self.nodes[1].sendtoaddress(multi_sig_script['address'], 10.00) + self.nodes[1].generate(1) + transaction = self.nodes[1].gettransaction(transactionid); + + print("Should import a p2sh with respective redeem script") + result = self.nodes[1].importmulti([{ + "scriptPubKey": { + "address": multi_sig_script['address'] + }, + "redeemscript": multi_sig_script['redeemScript'] + }]) + assert_equal(result[0]['success'], True) + + p2shunspent = self.nodes[1].listunspent(0,999999, [multi_sig_script['address']])[0] + assert_equal(p2shunspent['spendable'], False) + assert_equal(p2shunspent['solvable'], True) + + + # P2SH + Redeem script + Private Keys + !Watchonly + sig_address_1 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) + sig_address_2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) + sig_address_3 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) + multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['address'], sig_address_2['address'], sig_address_3['pubkey']]) + self.nodes[1].generate(100) + transactionid = self.nodes[1].sendtoaddress(multi_sig_script['address'], 10.00) + self.nodes[1].generate(1) + transaction = self.nodes[1].gettransaction(transactionid); + + print("Should import a p2sh with respective redeem script and private keys") + result = self.nodes[1].importmulti([{ + "scriptPubKey": { + "address": multi_sig_script['address'] + }, + "redeemscript": multi_sig_script['redeemScript'], + "keys": [ self.nodes[0].dumpprivkey(sig_address_1['address']), self.nodes[0].dumpprivkey(sig_address_2['address'])] + }]) + assert_equal(result[0]['success'], True) + + p2shunspent = self.nodes[1].listunspent(0,999999, [multi_sig_script['address']])[0] + assert_equal(p2shunspent['spendable'], False) + assert_equal(p2shunspent['solvable'], True) + + # P2SH + Redeem script + Private Keys + Watchonly + sig_address_1 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) + sig_address_2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) + sig_address_3 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) + multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['address'], sig_address_2['address'], sig_address_3['pubkey']]) + self.nodes[1].generate(100) + transactionid = self.nodes[1].sendtoaddress(multi_sig_script['address'], 10.00) + self.nodes[1].generate(1) + transaction = self.nodes[1].gettransaction(transactionid); + + print("Should import a p2sh with respective redeem script and private keys") + result = self.nodes[1].importmulti([{ + "scriptPubKey": { + "address": multi_sig_script['address'] + }, + "redeemscript": multi_sig_script['redeemScript'], + "keys": [ self.nodes[0].dumpprivkey(sig_address_1['address']), self.nodes[0].dumpprivkey(sig_address_2['address'])], + "watchonly": True + }]) + assert_equal(result[0]['success'], False) + assert_equal(result[0]['error']['code'], -8) + assert_equal(result[0]['error']['message'], 'Incompatibility found between watchonly and keys') + + # TODO Consistency tests? + + + +if __name__ == '__main__': + ImportMultiTest ().main () diff --git a/src/chain.cpp b/src/chain.cpp index 77e924e703043..1e611906d146f 100644 --- a/src/chain.cpp +++ b/src/chain.cpp @@ -61,6 +61,13 @@ const CBlockIndex *CChain::FindFork(const CBlockIndex *pindex) const { return pindex; } +CBlockIndex* CChain::FindLatestBefore(int64_t nTime) const +{ + std::vector::const_iterator lower = std::lower_bound(vChain.begin(), vChain.end(), nTime, + [](CBlockIndex* pBlock, const int64_t& time) -> bool { return pBlock->GetBlockTime() < time; }); + return (lower == vChain.end() ? NULL : *lower); +} + /** Turn the lowest '1' bit in the binary representation of a number into a '0'. */ int static inline InvertLowestOne(int n) { return n & (n - 1); } diff --git a/src/chain.h b/src/chain.h index e2f8c565224c2..46a16a30617f4 100644 --- a/src/chain.h +++ b/src/chain.h @@ -459,6 +459,9 @@ class CChain { /** Find the last common block between this chain and a block index entry. */ const CBlockIndex *FindFork(const CBlockIndex *pindex) const; + + /** Find the most recent block with timestamp lower than the given. */ + CBlockIndex* FindLatestBefore(int64_t nTime) const; }; #endif // BITCOIN_CHAIN_H diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index c14d9d67474fe..8370a0f43effb 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -95,6 +95,8 @@ static const CRPCConvertParam vRPCConvertParams[] = { "importaddress", 2 }, { "importaddress", 3 }, { "importpubkey", 2 }, + { "importmulti", 0 }, + { "importmulti", 1 }, { "verifychain", 0 }, { "verifychain", 1 }, { "keypoolrefill", 0 }, diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 8a1bbd5684526..0297337c2a399 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -24,6 +24,7 @@ #include +#include #include using namespace std; @@ -637,3 +638,392 @@ UniValue dumpwallet(const JSONRPCRequest& request) file.close(); return NullUniValue; } + + +UniValue processImport(const UniValue& data) { + // TODO List: + // - Check consistency between pubkeys/privkeys and scriptPubKey/redeemScript. + + try { + bool success = false; + + // Required fields. + const UniValue& scriptPubKey = data["scriptPubKey"]; + + // Should have script or JSON with "address". + if (!(scriptPubKey.getType() == UniValue::VOBJ && scriptPubKey.exists("address")) && !(scriptPubKey.getType() == UniValue::VSTR)) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid scriptPubKey"); + } + + // Optional fields. + const string& strRedeemScript = data.exists("redeemscript") ? data["redeemscript"].get_str() : ""; + const UniValue& pubKeys = data.exists("pubkeys") ? data["pubkeys"].get_array() : UniValue(); + const UniValue& keys = data.exists("keys") ? data["keys"].get_array() : UniValue(); + const bool& internal = data.exists("internal") ? data["internal"].get_bool() : false; + const bool& watchOnly = data.exists("watchonly") ? data["watchonly"].get_bool() : false; + const string& label = data.exists("label") && !internal ? data["label"].get_str() : ""; + const int64_t& timestamp = data.exists("timestamp") && data["timestamp"].get_int64() > 1 ? data["timestamp"].get_int64() : 1; + + bool isScript = scriptPubKey.getType() == UniValue::VSTR; + bool isP2SH = strRedeemScript.length() > 0; + const string& output = isScript ? scriptPubKey.get_str() : scriptPubKey["address"].get_str(); + + // Parse the output. + CScript script; + CBitcoinAddress address; + + if (!isScript) { + address = CBitcoinAddress(output); + script = GetScriptForDestination(address.Get()); + } else { + if (!IsHex(output)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid scriptPubKey"); + } + + std::vector vData(ParseHex(output)); + script = CScript(vData.begin(), vData.end()); + } + + // Watchonly and private keys + if (watchOnly && keys.size()) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Incompatibility found between watchonly and keys"); + } + + // Internal + Label + if (internal && data.exists("label")) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Incompatibility found between internal and label"); + } + + // Not having Internal + Script + if (!internal && isScript) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Internal must be set for hex scriptPubKey"); + } + + // Keys / PubKeys size check. + if (!isP2SH && (keys.size() > 1 || pubKeys.size() > 1)) { // Address / scriptPubKey + throw JSONRPCError(RPC_INVALID_PARAMETER, "More than private key given for one address"); + } + + // Invalid P2SH redeemScript + if (isP2SH && !IsHex(strRedeemScript)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid redeem script"); + } + + // Process. // + + // P2SH + if (isP2SH) { + // TODO: check consistency between private keys and p2sh redeemscript + p2sh address + + // Import redeem script. + std::vector vData(ParseHex(strRedeemScript)); + CScript redeemScript = CScript(vData.begin(), vData.end()); + + // Invalid P2SH address + if (!script.IsPayToScriptHash()) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid P2SH address / script"); + } + + pwalletMain->MarkDirty(); + + if (!pwalletMain->HaveWatchOnly(redeemScript) && !pwalletMain->AddWatchOnly(redeemScript)) { + throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet"); + } + + if (!pwalletMain->HaveCScript(redeemScript) && !pwalletMain->AddCScript(redeemScript)) { + throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2sh redeemScript to wallet"); + } + + CBitcoinAddress redeemAddress = CBitcoinAddress(CScriptID(redeemScript)); + CScript redeemDestination = GetScriptForDestination(redeemAddress.Get()); + + if (::IsMine(*pwalletMain, redeemDestination) == ISMINE_SPENDABLE) { + throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script"); + } + + pwalletMain->MarkDirty(); + + if (!pwalletMain->HaveWatchOnly(redeemDestination) && !pwalletMain->AddWatchOnly(redeemDestination)) { + throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet"); + } + + // add to address book or update label + if (address.IsValid()) { + pwalletMain->SetAddressBook(address.Get(), label, "receive"); + } + + // Import private keys. + if (keys.size()) { + for (size_t i = 0; i < keys.size(); i++) { + const string& privkey = keys[i].get_str(); + + CBitcoinSecret vchSecret; + bool fGood = vchSecret.SetString(privkey); + + if (!fGood) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding"); + } + + CKey key = vchSecret.GetKey(); + + if (!key.IsValid()) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range"); + } + + CPubKey pubkey = key.GetPubKey(); + assert(key.VerifyPubKey(pubkey)); + + CKeyID vchAddress = pubkey.GetID(); + pwalletMain->MarkDirty(); + pwalletMain->SetAddressBook(vchAddress, label, "receive"); + + if (pwalletMain->HaveKey(vchAddress)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Already have this key"); + } + + pwalletMain->mapKeyMetadata[vchAddress].nCreateTime = timestamp; + + if (!pwalletMain->AddKeyPubKey(key, pubkey)) { + throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet"); + } + + if (timestamp < pwalletMain->nTimeFirstKey) { + pwalletMain->nTimeFirstKey = timestamp; + } + } + } + + success = true; + } else { + // TODO: check consistency between private/public keys and scriptPubKey / address + + // Import public keys. + if (pubKeys.size() && keys.size() == 0) { + const string& strPubKey = pubKeys[0].get_str(); + + if (!IsHex(strPubKey)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey must be a hex string"); + } + + std::vector data(ParseHex(strPubKey)); + CPubKey pubKey(data.begin(), data.end()); + + if (!pubKey.IsFullyValid()) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey is not a valid public key"); + } + + CBitcoinAddress pubKeyAddress = CBitcoinAddress(pubKey.GetID()); + CScript pubKeyScript = GetScriptForDestination(pubKeyAddress.Get()); + + if (::IsMine(*pwalletMain, pubKeyScript) == ISMINE_SPENDABLE) { + throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script"); + } + + pwalletMain->MarkDirty(); + + if (!pwalletMain->HaveWatchOnly(pubKeyScript) && !pwalletMain->AddWatchOnly(pubKeyScript)) { + throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet"); + } + + // add to address book or update label + if (pubKeyAddress.IsValid()) { + pwalletMain->SetAddressBook(pubKeyAddress.Get(), label, "receive"); + } + + // TODO Is this necessary? + CScript scriptRawPubKey = GetScriptForRawPubKey(pubKey); + + if (::IsMine(*pwalletMain, scriptRawPubKey) == ISMINE_SPENDABLE) { + throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script"); + } + + pwalletMain->MarkDirty(); + + if (!pwalletMain->HaveWatchOnly(scriptRawPubKey) && !pwalletMain->AddWatchOnly(scriptRawPubKey)) { + throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet"); + } + + success = true; + } + + // Import private keys. + if (keys.size()) { + const string& strPrivkey = keys[0].get_str(); + + // Checks. + CBitcoinSecret vchSecret; + bool fGood = vchSecret.SetString(strPrivkey); + + if (!fGood) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding"); + } + + CKey key = vchSecret.GetKey(); + if (!key.IsValid()) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range"); + } + + CPubKey pubKey = key.GetPubKey(); + assert(key.VerifyPubKey(pubKey)); + + CKeyID vchAddress = pubkey.GetID(); + pwalletMain->MarkDirty(); + pwalletMain->SetAddressBook(vchAddress, label, "receive"); + + if (pwalletMain->HaveKey(vchAddress)) { + return false; + } + + pwalletMain->mapKeyMetadata[vchAddress].nCreateTime = timestamp; + + if (!pwalletMain->AddKeyPubKey(key, pubKey)) { + throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet"); + } + + if (timestamp < pwalletMain->nTimeFirstKey) { + pwalletMain->nTimeFirstKey = timestamp; + } + + success = true; + } + + // Import scriptPubKey only. + if (pubKeys.size() == 0 && keys.size() == 0) { + if (::IsMine(*pwalletMain, script) == ISMINE_SPENDABLE) { + throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script"); + } + + pwalletMain->MarkDirty(); + + if (!pwalletMain->HaveWatchOnly(script) && !pwalletMain->AddWatchOnly(script)) { + throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet"); + } + + if (scriptPubKey.getType() == UniValue::VOBJ) { + // add to address book or update label + if (address.IsValid()) { + pwalletMain->SetAddressBook(address.Get(), label, "receive"); + } + } + + success = true; + } + } + + UniValue result = UniValue(UniValue::VOBJ); + result.pushKV("success", UniValue(success)); + return result; + } catch (const UniValue& e) { + UniValue result = UniValue(UniValue::VOBJ); + result.pushKV("success", UniValue(false)); + result.pushKV("error", e); + return result; + } catch (...) { + UniValue result = UniValue(UniValue::VOBJ); + result.pushKV("success", UniValue(false)); + result.pushKV("error", JSONRPCError(RPC_MISC_ERROR, "Missing required fields")); + return result; + } +} + +UniValue importmulti(const JSONRPCRequest& mainRequest) +{ + // clang-format off + if (mainRequest.fHelp || mainRequest.params.size() < 1 || mainRequest.params.size() > 2) + throw runtime_error( + "importmulti '[]' '' \n\n" + "Import addresses/scripts (with private or public keys, redeem script (P2SH)), rescanning all addresses in one-shot-only (rescan can be disabled via options).\n\n" + "Arguments:\n" + "1. request array (array, required) Data to be imported\n" + " [ (array of json objects)\n" + " {\n" + " \"scriptPubKey\": \"